mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-18 02:18:00 +00:00
Added the visual briefing assistant (#893)
Build and Release / Determine run mode (push) Has been cancelled
Build and Release / Read metadata (push) Has been cancelled
Build and Release / Sync Flatpak repo (push) Has been cancelled
Build and Release / Collect Flatpak artifacts (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
Build and Release / Determine run mode (push) Has been cancelled
Build and Release / Read metadata (push) Has been cancelled
Build and Release / Sync Flatpak repo (push) Has been cancelled
Build and Release / Collect Flatpak artifacts (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
This commit is contained in:
1 parent
df4663fff4
commit
58cc811a58
214 files changed
+18943
-353
No files matched your search
@@ -0,0 +1,146 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace AIStudio.Assistants.VisualBriefing;
|
||||
|
||||
/// <summary>
|
||||
/// Centralizes canonical JSON, structural signatures, and SHA-256 hashes for visual briefings.
|
||||
/// </summary>
|
||||
internal static class VisualBriefingHashing
|
||||
{
|
||||
/// <summary>
|
||||
/// Computes a lowercase SHA-256 hash for UTF-8 text.
|
||||
/// </summary>
|
||||
/// <param name="value">The text to hash.</param>
|
||||
/// <returns>The lowercase hexadecimal hash.</returns>
|
||||
internal static string Compute(string value) => Convert.ToHexStringLower(SHA256.HashData(Encoding.UTF8.GetBytes(value)));
|
||||
|
||||
/// <summary>
|
||||
/// Computes a hash over unambiguously separated text sections.
|
||||
/// </summary>
|
||||
/// <param name="values">The ordered text sections.</param>
|
||||
/// <returns>The lowercase hexadecimal hash.</returns>
|
||||
internal static string ComputeSections(params string?[] values) => Compute(string.Join('\u001e', values.Select(value => value ?? string.Empty)));
|
||||
|
||||
/// <summary>
|
||||
/// Computes a lowercase SHA-256 hash for a file without loading it fully into memory.
|
||||
/// </summary>
|
||||
/// <param name="path">The file path.</param>
|
||||
/// <param name="token">The cancellation token.</param>
|
||||
/// <returns>The lowercase hexadecimal hash.</returns>
|
||||
internal static async Task<string> ComputeFileAsync(string path, CancellationToken token)
|
||||
{
|
||||
await using var stream = new FileStream(
|
||||
path,
|
||||
FileMode.Open,
|
||||
FileAccess.Read,
|
||||
FileShare.Read,
|
||||
65_536,
|
||||
FileOptions.Asynchronous | FileOptions.SequentialScan);
|
||||
|
||||
return Convert.ToHexStringLower(await SHA256.HashDataAsync(stream, token));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns canonical JSON for one value, with ordinally sorted object properties.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Hashed values go through here instead of being serialized directly. Plain serialization writes
|
||||
/// properties in declaration order, which would tie every stored hash to the order in which the
|
||||
/// members happen to appear in the C# file: reordering two properties would invalidate every
|
||||
/// briefing already on disk, without any visible change to the data.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the value to canonicalize.</typeparam>
|
||||
/// <param name="value">The value to canonicalize.</param>
|
||||
/// <returns>Compact canonical JSON.</returns>
|
||||
internal static string CanonicalJson<T>(T value) => CanonicalJson(JsonSerializer.SerializeToElement(value, VisualBriefingJson.Canonical));
|
||||
|
||||
/// <summary>
|
||||
/// Returns canonical JSON with ordinally sorted object properties.
|
||||
/// </summary>
|
||||
/// <param name="value">The JSON value to canonicalize.</param>
|
||||
/// <returns>Compact canonical JSON.</returns>
|
||||
internal static string CanonicalJson(JsonElement value)
|
||||
{
|
||||
using var stream = new MemoryStream();
|
||||
using (var writer = new Utf8JsonWriter(stream))
|
||||
WriteCanonical(writer, value);
|
||||
|
||||
return Encoding.UTF8.GetString(stream.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the structural signature of canonical business data.
|
||||
/// </summary>
|
||||
/// <param name="value">The JSON value to inspect.</param>
|
||||
/// <returns>A stable hash of its property and collection shape.</returns>
|
||||
internal static string StructuralSignature(JsonElement value)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
AppendStructuralSignature(builder, value);
|
||||
return Compute(builder.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes one JSON value in canonical order.
|
||||
/// </summary>
|
||||
/// <param name="writer">The JSON writer.</param>
|
||||
/// <param name="value">The value to write.</param>
|
||||
private static void WriteCanonical(Utf8JsonWriter writer, JsonElement value)
|
||||
{
|
||||
switch (value.ValueKind)
|
||||
{
|
||||
case JsonValueKind.Object:
|
||||
writer.WriteStartObject();
|
||||
foreach (var property in value.EnumerateObject().OrderBy(property => property.Name, StringComparer.Ordinal))
|
||||
{
|
||||
writer.WritePropertyName(property.Name);
|
||||
WriteCanonical(writer, property.Value);
|
||||
}
|
||||
writer.WriteEndObject();
|
||||
break;
|
||||
|
||||
case JsonValueKind.Array:
|
||||
writer.WriteStartArray();
|
||||
foreach (var item in value.EnumerateArray())
|
||||
WriteCanonical(writer, item);
|
||||
writer.WriteEndArray();
|
||||
break;
|
||||
|
||||
default:
|
||||
value.WriteTo(writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends type and property shape without business values.
|
||||
/// </summary>
|
||||
/// <param name="builder">The signature builder.</param>
|
||||
/// <param name="value">The value to inspect.</param>
|
||||
private static void AppendStructuralSignature(StringBuilder builder, JsonElement value)
|
||||
{
|
||||
builder.Append(value.ValueKind);
|
||||
switch (value.ValueKind)
|
||||
{
|
||||
case JsonValueKind.Object:
|
||||
builder.Append('{');
|
||||
foreach (var property in value.EnumerateObject().OrderBy(property => property.Name, StringComparer.Ordinal))
|
||||
{
|
||||
builder.Append(property.Name).Append(':');
|
||||
AppendStructuralSignature(builder, property.Value);
|
||||
}
|
||||
builder.Append('}');
|
||||
break;
|
||||
|
||||
case JsonValueKind.Array:
|
||||
builder.Append('[');
|
||||
var first = value.EnumerateArray().FirstOrDefault();
|
||||
if (first.ValueKind is not JsonValueKind.Undefined)
|
||||
AppendStructuralSignature(builder, first);
|
||||
builder.Append(']');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user