mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-04 18:47:21 +00:00
Generated the JSON contracts of the Visual Briefing assistant at compile time
This commit is contained in:
7 files changed
+118
-13
No files matched your search
+1
-1
@@ -204,7 +204,7 @@ public sealed partial class VisualBriefingArtifactService
|
||||
return context;
|
||||
|
||||
if (path is "$index")
|
||||
return JsonSerializer.SerializeToElement(0);
|
||||
return JsonSerializer.SerializeToElement(0, JSON_OPTIONS);
|
||||
|
||||
if (path.StartsWith(".", StringComparison.Ordinal))
|
||||
return GetDataAtPath(context, path[1..]);
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Assistants.VisualBriefing;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json writes and reads the canonical JSON of visual briefings, built at
|
||||
/// compile time.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Much of what these contracts write goes into the hashes of stored briefings, see VisualBriefingJson.Canonical.
|
||||
/// The hashes of the artifacts are generic: every list they hash needs a contract of its own. A test fails for a type
|
||||
/// which is missing here.
|
||||
/// </remarks>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
|
||||
// The header and the data of an exported briefing, and the build which the progress view shows:
|
||||
[JsonSerializable(typeof(VisualBriefingExportManifest))]
|
||||
[JsonSerializable(typeof(VisualBriefingBuildRecord))]
|
||||
[JsonSerializable(typeof(VisualBriefingCompiledData))]
|
||||
[JsonSerializable(typeof(VisualBriefingContentData))]
|
||||
[JsonSerializable(typeof(VisualBriefingInteractionData))]
|
||||
[JsonSerializable(typeof(VisualBriefingProtectedData))]
|
||||
[JsonSerializable(typeof(Dictionary<string, JsonElement>))]
|
||||
[JsonSerializable(typeof(JsonElement))]
|
||||
[JsonSerializable(typeof(JsonObject))]
|
||||
[JsonSerializable(typeof(string))]
|
||||
[JsonSerializable(typeof(int))]
|
||||
|
||||
// The payload hashes of the artifacts:
|
||||
[JsonSerializable(typeof(List<VisualBriefingEvidenceFact>))]
|
||||
[JsonSerializable(typeof(List<VisualBriefingEvidenceMetric>))]
|
||||
[JsonSerializable(typeof(List<VisualBriefingEvidenceTable>))]
|
||||
[JsonSerializable(typeof(List<VisualBriefingSourceCoverage>))]
|
||||
[JsonSerializable(typeof(List<VisualBriefingAssetPlanItem>))]
|
||||
[JsonSerializable(typeof(List<VisualBriefingPlanSection>))]
|
||||
[JsonSerializable(typeof(List<VisualBriefingSlotValue>))]
|
||||
[JsonSerializable(typeof(List<VisualBriefingChartSpec>))]
|
||||
[JsonSerializable(typeof(List<VisualBriefingControlSpec>))]
|
||||
[JsonSerializable(typeof(List<VisualBriefingFormulaSpec>))]
|
||||
[JsonSerializable(typeof(Dictionary<string, string>))]
|
||||
[JsonSerializable(typeof(Dictionary<string, List<string>>))]
|
||||
[JsonSerializable(typeof(VisualBriefingLayoutNode))]
|
||||
|
||||
// The prompts of the stages:
|
||||
[JsonSerializable(typeof(IEnumerable<VisualBriefingSourcePrompt>))]
|
||||
[JsonSerializable(typeof(string[]))]
|
||||
[JsonSerializable(typeof(VisualBriefingRequiredSlot[]))]
|
||||
[JsonSerializable(typeof(VisualBriefingControlRequirement[]))]
|
||||
[JsonSerializable(typeof(VisualBriefingEvidencePrompt))]
|
||||
[JsonSerializable(typeof(VisualBriefingParentDesign))]
|
||||
|
||||
// The answers of the models:
|
||||
[JsonSerializable(typeof(VisualBriefingEvidenceResponse))]
|
||||
[JsonSerializable(typeof(VisualBriefingPlanResponse))]
|
||||
[JsonSerializable(typeof(VisualBriefingContentResponse))]
|
||||
[JsonSerializable(typeof(VisualBriefingDesignResponse))]
|
||||
|
||||
// The fingerprint which decides whether the editor holds unsaved changes:
|
||||
[JsonSerializable(typeof(VisualBriefingPersistenceFingerprint))]
|
||||
internal sealed partial class VisualBriefingCanonicalJsonContext : JsonSerializerContext;
|
||||
@@ -28,7 +28,9 @@ internal static class VisualBriefingJson
|
||||
/// and a mismatch makes the store discard the stored artifact. Any change here — a converter, a
|
||||
/// naming policy, an encoder — therefore invalidates every briefing that was ever written, which
|
||||
/// surfaces as a failed integrity check rather than as a build error. This is why enums stay numeric
|
||||
/// here even though the persisted manifest writes their member names.
|
||||
/// here even though the persisted manifest writes their member names. Unlike other options of the app,
|
||||
/// these are not made read-only right here, because MWAIS0010 wants nothing but the object creation;
|
||||
/// System.Text.Json locks them with their first use anyway.
|
||||
/// </remarks>
|
||||
[CanonicalJsonConfiguration]
|
||||
internal static JsonSerializerOptions Canonical { get; } = new()
|
||||
@@ -38,6 +40,7 @@ internal static class VisualBriefingJson
|
||||
WriteIndented = false,
|
||||
Encoder = JavaScriptEncoder.Default,
|
||||
UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow,
|
||||
TypeInfoResolver = VisualBriefingCanonicalJsonContext.Default,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -52,7 +55,7 @@ internal static class VisualBriefingJson
|
||||
/// defined outside the feature, such as the target language and the audience enums. Reading accepts
|
||||
/// numbers as well, so manifests written before this distinction existed keep loading.
|
||||
/// </remarks>
|
||||
internal static JsonSerializerOptions Persistence { get; } = new()
|
||||
internal static JsonSerializerOptions Persistence { get; } = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNameCaseInsensitive = false,
|
||||
@@ -60,5 +63,6 @@ internal static class VisualBriefingJson
|
||||
Encoder = JavaScriptEncoder.Default,
|
||||
UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow,
|
||||
Converters = { new JsonStringEnumConverter() },
|
||||
};
|
||||
TypeInfoResolver = VisualBriefingPersistenceJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Assistants.VisualBriefing;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json reads and writes the files of visual briefings, built at compile time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(VisualBriefingManifest))]
|
||||
[JsonSerializable(typeof(VisualBriefingEvidenceArtifact))]
|
||||
[JsonSerializable(typeof(VisualBriefingPlanArtifact))]
|
||||
[JsonSerializable(typeof(VisualBriefingContentArtifact))]
|
||||
[JsonSerializable(typeof(VisualBriefingPresentationArtifact))]
|
||||
[JsonSerializable(typeof(VisualBriefingBuildRecord))]
|
||||
[JsonSerializable(typeof(VisualBriefingOperationDiagnostics))]
|
||||
|
||||
// The briefing selected last:
|
||||
[JsonSerializable(typeof(Guid?))]
|
||||
internal sealed partial class VisualBriefingPersistenceJsonContext : JsonSerializerContext;
|
||||
@@ -24,7 +24,7 @@ public sealed partial class VisualBriefingStore
|
||||
try
|
||||
{
|
||||
this.LastSelectedBriefingId = briefingId;
|
||||
await WriteTextAtomicAsync(this.SelectionPath(), JsonSerializer.Serialize<Guid?>(briefingId), overwrite: true, token);
|
||||
await WriteTextAtomicAsync(this.SelectionPath(), JsonSerializer.Serialize<Guid?>(briefingId, JSON_OPTIONS), overwrite: true, token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -47,7 +47,7 @@ public sealed partial class VisualBriefingStore
|
||||
return;
|
||||
|
||||
this.LastSelectedBriefingId = null;
|
||||
await WriteTextAtomicAsync(this.SelectionPath(), JsonSerializer.Serialize<Guid?>(null), overwrite: true, token);
|
||||
await WriteTextAtomicAsync(this.SelectionPath(), JsonSerializer.Serialize<Guid?>(null, JSON_OPTIONS), overwrite: true, token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -67,7 +67,7 @@ public sealed partial class VisualBriefingStore
|
||||
try
|
||||
{
|
||||
var serialized = await File.ReadAllTextAsync(path, token);
|
||||
var selected = JsonSerializer.Deserialize<Guid?>(serialized);
|
||||
var selected = JsonSerializer.Deserialize<Guid?>(serialized, JSON_OPTIONS);
|
||||
this.LastSelectedBriefingId = selected is not null &&
|
||||
Directory.Exists(this.BriefingDirectory(selected.Value))
|
||||
? selected
|
||||
|
||||
Reference in new issue
Block a user