@agentskit/chat-devtools 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AgentsKit
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # @agentskit/chat-devtools
2
+
3
+ Application trace capture, upstream replay-fixture composition, and semantic renderer parity diagnostics for AgentsKit Chat.
4
+
5
+ This package does not record or replay model calls. Use `createRecordingAdapter` and `createReplayAdapter` from `@agentskit/eval/replay`; store the resulting cassette beside application traces with `createReplayFixture`.
package/dist/index.cjs ADDED
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ApplicationTraceRecordSchema: () => ApplicationTraceRecordSchema,
24
+ RendererOutcomeSchema: () => RendererOutcomeSchema,
25
+ ReplayFixtureSchema: () => ReplayFixtureSchema,
26
+ SemanticOutcomeSchema: () => SemanticOutcomeSchema,
27
+ TraceCategorySchema: () => TraceCategorySchema,
28
+ captureActionPolicyTrace: () => captureActionPolicyTrace,
29
+ captureActionTrace: () => captureActionTrace,
30
+ captureTurnTrace: () => captureTurnTrace,
31
+ compareRendererOutcomes: () => compareRendererOutcomes,
32
+ createReplayFixture: () => createReplayFixture,
33
+ createTraceCapture: () => createTraceCapture,
34
+ parseReplayFixture: () => parseReplayFixture,
35
+ serializeReplayFixture: () => serializeReplayFixture
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+ var import_replay = require("@agentskit/eval/replay");
39
+ var import_zod = require("zod");
40
+ var IdSchema = import_zod.z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/);
41
+ var DetailSchema = import_zod.z.record(import_zod.z.string().min(1).max(128), import_zod.z.json()).refine((value) => new TextEncoder().encode(JSON.stringify(value)).byteLength <= 65536, "Trace detail exceeds 64 KiB.");
42
+ var TraceCategorySchema = import_zod.z.enum(["route", "agent", "repair", "fallback", "policy", "action", "lifecycle"]);
43
+ var ApplicationTraceRecordSchema = import_zod.z.object({
44
+ id: IdSchema,
45
+ sequence: import_zod.z.number().int().nonnegative(),
46
+ at: import_zod.z.iso.datetime(),
47
+ category: TraceCategorySchema,
48
+ parentId: IdSchema.optional(),
49
+ detail: DetailSchema
50
+ }).strict().readonly();
51
+ var redact = (value, fields) => {
52
+ if (Array.isArray(value)) return value.map((item) => redact(item, fields));
53
+ if (value !== null && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, fields.has(key.toLowerCase()) ? "[REDACTED]" : redact(item, fields)]));
54
+ return value;
55
+ };
56
+ var deepFreeze = (value) => {
57
+ if (Array.isArray(value)) {
58
+ value.forEach(deepFreeze);
59
+ return Object.freeze(value);
60
+ }
61
+ if (value !== null && typeof value === "object") {
62
+ Object.values(value).forEach(deepFreeze);
63
+ return Object.freeze(value);
64
+ }
65
+ return value;
66
+ };
67
+ var createTraceCapture = (options = {}) => {
68
+ const fields = new Set((options.redactFields ?? []).map((field) => field.toLowerCase()));
69
+ const records = [];
70
+ return {
71
+ append: (input) => {
72
+ if (input.parentId !== void 0 && !records.some((record2) => record2.id === input.parentId)) throw new Error("Trace parent must refer to an earlier record.");
73
+ const sequence = records.length;
74
+ const detail = DetailSchema.parse(redact(DetailSchema.parse(input.detail), fields));
75
+ const record = deepFreeze(ApplicationTraceRecordSchema.parse({ id: `trace-${sequence}`, sequence, at: input.at ?? (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString(), category: input.category, ...input.parentId === void 0 ? {} : { parentId: input.parentId }, detail }));
76
+ records.push(record);
77
+ return record;
78
+ },
79
+ snapshot: () => Object.freeze(records.map((record) => deepFreeze({ ...record, detail: structuredClone(record.detail) })))
80
+ };
81
+ };
82
+ var captureTurnTrace = (capture, trace, parentId) => capture.append({
83
+ category: trace.kind === "deterministic" ? "route" : trace.kind === "agentic" ? "agent" : trace.kind === "repaired" ? "repair" : "fallback",
84
+ detail: { kind: trace.kind, ...trace.routeId === void 0 ? {} : { routeId: trace.routeId }, fromState: trace.fromState, toState: trace.toState },
85
+ ...parentId === void 0 ? {} : { parentId }
86
+ });
87
+ var captureActionPolicyTrace = (capture, trace, parentId) => capture.append({
88
+ category: "policy",
89
+ at: new Date(trace.timestamp).toISOString(),
90
+ detail: { policyTraceId: trace.id, toolCallId: trace.toolCallId, action: trace.action, phase: trace.phase, decision: trace.decision, reason: trace.reason, requiredCapabilities: [...trace.requiredCapabilities] },
91
+ ...parentId === void 0 ? {} : { parentId }
92
+ });
93
+ var captureActionTrace = (capture, action, parentId) => capture.append({
94
+ category: "action",
95
+ detail: { action: action.action, toolCallId: action.toolCallId, status: action.status, expiresAt: action.expiresAt },
96
+ ...parentId === void 0 ? {} : { parentId }
97
+ });
98
+ var ReplayFixtureSchema = import_zod.z.object({
99
+ protocol: import_zod.z.literal("agentskit.chat.replay"),
100
+ version: import_zod.z.literal(1),
101
+ cassette: import_zod.z.unknown(),
102
+ traces: import_zod.z.array(ApplicationTraceRecordSchema).max(1e4)
103
+ }).strict().readonly().superRefine((fixture, context) => {
104
+ const prior = /* @__PURE__ */ new Set();
105
+ fixture.traces.forEach((trace, index) => {
106
+ if (trace.sequence !== index) context.addIssue({ code: "custom", path: ["traces", index, "sequence"], message: "Trace sequence must be contiguous." });
107
+ if (prior.has(trace.id)) context.addIssue({ code: "custom", path: ["traces", index, "id"], message: "Trace ids must be unique." });
108
+ if (trace.parentId !== void 0 && !prior.has(trace.parentId)) context.addIssue({ code: "custom", path: ["traces", index, "parentId"], message: "Trace parent must precede its child." });
109
+ prior.add(trace.id);
110
+ });
111
+ });
112
+ var createReplayFixture = (cassette, traces) => {
113
+ const upstream = (0, import_replay.parseCassette)((0, import_replay.serializeCassette)(cassette));
114
+ const envelope = ReplayFixtureSchema.parse({ protocol: "agentskit.chat.replay", version: 1, cassette: upstream, traces });
115
+ return { ...envelope, cassette: upstream };
116
+ };
117
+ var serializeReplayFixture = (fixture) => JSON.stringify(createReplayFixture(fixture.cassette, fixture.traces), null, 2);
118
+ var parseReplayFixture = (input) => {
119
+ if (new TextEncoder().encode(input).byteLength > 16777216) throw new Error("Replay fixture exceeds 16 MiB.");
120
+ const envelope = ReplayFixtureSchema.parse(JSON.parse(input));
121
+ const cassette = (0, import_replay.parseCassette)(JSON.stringify(envelope.cassette));
122
+ return { ...envelope, cassette };
123
+ };
124
+ var SemanticOutcomeSchema = import_zod.z.object({ turnId: IdSchema, kind: IdSchema, value: import_zod.z.json().optional() }).strict().readonly();
125
+ var RendererOutcomeSchema = import_zod.z.object({ renderer: IdSchema, outcomes: import_zod.z.array(SemanticOutcomeSchema).max(1e4) }).strict().readonly();
126
+ var canonical = (value) => JSON.stringify(value, (_key, item) => item !== null && typeof item === "object" && !Array.isArray(item) ? Object.fromEntries(Object.entries(item).sort(([left], [right]) => left.localeCompare(right))) : item);
127
+ var compareRendererOutcomes = (input) => {
128
+ const renderers = import_zod.z.array(RendererOutcomeSchema).min(2).parse(input);
129
+ if (new Set(renderers.map((item) => item.renderer)).size !== renderers.length) throw new Error("Renderer ids must be unique.");
130
+ const key = (outcome) => `${outcome.turnId}\0${outcome.kind}`;
131
+ for (const item of renderers) if (new Set(item.outcomes.map(key)).size !== item.outcomes.length) throw new Error("Turn and kind pairs must be unique per renderer.");
132
+ const baseline = renderers[0];
133
+ const expected = new Map(baseline.outcomes.map((outcome) => [key(outcome), outcome]));
134
+ const outcomeKeys = new Set(renderers.flatMap((renderer) => renderer.outcomes.map(key)));
135
+ const mismatches = [];
136
+ for (const renderer of renderers.slice(1)) {
137
+ const actual = new Map(renderer.outcomes.map((outcome) => [key(outcome), outcome]));
138
+ for (const outcomeKey of outcomeKeys) {
139
+ const left = expected.get(outcomeKey);
140
+ const right = actual.get(outcomeKey);
141
+ if (canonical(left) !== canonical(right)) {
142
+ const [turnId, kind] = outcomeKey.split("\0");
143
+ mismatches.push({ renderer: renderer.renderer, turnId, kind, ...left === void 0 ? {} : { expected: left }, ...right === void 0 ? {} : { actual: right } });
144
+ }
145
+ }
146
+ }
147
+ return deepFreeze(structuredClone({ ok: mismatches.length === 0, baseline: baseline.renderer, renderers: renderers.map((item) => item.renderer), mismatches }));
148
+ };
149
+ // Annotate the CommonJS export names for ESM import in node:
150
+ 0 && (module.exports = {
151
+ ApplicationTraceRecordSchema,
152
+ RendererOutcomeSchema,
153
+ ReplayFixtureSchema,
154
+ SemanticOutcomeSchema,
155
+ TraceCategorySchema,
156
+ captureActionPolicyTrace,
157
+ captureActionTrace,
158
+ captureTurnTrace,
159
+ compareRendererOutcomes,
160
+ createReplayFixture,
161
+ createTraceCapture,
162
+ parseReplayFixture,
163
+ serializeReplayFixture
164
+ });
@@ -0,0 +1,107 @@
1
+ import { Cassette } from '@agentskit/eval/replay';
2
+ import { ActionPolicyTrace, ActionConfirmation, TurnTrace } from '@agentskit/chat';
3
+ import { z } from 'zod';
4
+
5
+ declare const TraceCategorySchema: z.ZodEnum<{
6
+ route: "route";
7
+ agent: "agent";
8
+ repair: "repair";
9
+ fallback: "fallback";
10
+ policy: "policy";
11
+ action: "action";
12
+ lifecycle: "lifecycle";
13
+ }>;
14
+ declare const ApplicationTraceRecordSchema: z.ZodReadonly<z.ZodObject<{
15
+ id: z.ZodString;
16
+ sequence: z.ZodNumber;
17
+ at: z.ZodISODateTime;
18
+ category: z.ZodEnum<{
19
+ route: "route";
20
+ agent: "agent";
21
+ repair: "repair";
22
+ fallback: "fallback";
23
+ policy: "policy";
24
+ action: "action";
25
+ lifecycle: "lifecycle";
26
+ }>;
27
+ parentId: z.ZodOptional<z.ZodString>;
28
+ detail: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
29
+ }, z.core.$strict>>;
30
+ type TraceCategory = z.infer<typeof TraceCategorySchema>;
31
+ type ApplicationTraceRecord = z.infer<typeof ApplicationTraceRecordSchema>;
32
+ interface TraceCaptureOptions {
33
+ readonly redactFields?: readonly string[];
34
+ readonly now?: () => Date;
35
+ }
36
+ interface AppendTraceInput {
37
+ readonly category: TraceCategory;
38
+ readonly detail: Readonly<Record<string, unknown>>;
39
+ readonly parentId?: string;
40
+ readonly at?: string;
41
+ }
42
+ interface TraceCapture {
43
+ append(input: AppendTraceInput): ApplicationTraceRecord;
44
+ snapshot(): readonly ApplicationTraceRecord[];
45
+ }
46
+ declare const createTraceCapture: (options?: TraceCaptureOptions) => TraceCapture;
47
+ declare const captureTurnTrace: (capture: TraceCapture, trace: TurnTrace, parentId?: string) => ApplicationTraceRecord;
48
+ declare const captureActionPolicyTrace: (capture: TraceCapture, trace: ActionPolicyTrace, parentId?: string) => ApplicationTraceRecord;
49
+ declare const captureActionTrace: (capture: TraceCapture, action: ActionConfirmation, parentId?: string) => ApplicationTraceRecord;
50
+ declare const ReplayFixtureSchema: z.ZodReadonly<z.ZodObject<{
51
+ protocol: z.ZodLiteral<"agentskit.chat.replay">;
52
+ version: z.ZodLiteral<1>;
53
+ cassette: z.ZodUnknown;
54
+ traces: z.ZodArray<z.ZodReadonly<z.ZodObject<{
55
+ id: z.ZodString;
56
+ sequence: z.ZodNumber;
57
+ at: z.ZodISODateTime;
58
+ category: z.ZodEnum<{
59
+ route: "route";
60
+ agent: "agent";
61
+ repair: "repair";
62
+ fallback: "fallback";
63
+ policy: "policy";
64
+ action: "action";
65
+ lifecycle: "lifecycle";
66
+ }>;
67
+ parentId: z.ZodOptional<z.ZodString>;
68
+ detail: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
69
+ }, z.core.$strict>>>;
70
+ }, z.core.$strict>>;
71
+ type ReplayFixture = Omit<z.infer<typeof ReplayFixtureSchema>, 'cassette'> & {
72
+ readonly cassette: Cassette;
73
+ };
74
+ declare const createReplayFixture: (cassette: Cassette, traces: readonly ApplicationTraceRecord[]) => ReplayFixture;
75
+ declare const serializeReplayFixture: (fixture: ReplayFixture) => string;
76
+ declare const parseReplayFixture: (input: string) => ReplayFixture;
77
+ declare const SemanticOutcomeSchema: z.ZodReadonly<z.ZodObject<{
78
+ turnId: z.ZodString;
79
+ kind: z.ZodString;
80
+ value: z.ZodOptional<z.ZodJSONSchema>;
81
+ }, z.core.$strict>>;
82
+ declare const RendererOutcomeSchema: z.ZodReadonly<z.ZodObject<{
83
+ renderer: z.ZodString;
84
+ outcomes: z.ZodArray<z.ZodReadonly<z.ZodObject<{
85
+ turnId: z.ZodString;
86
+ kind: z.ZodString;
87
+ value: z.ZodOptional<z.ZodJSONSchema>;
88
+ }, z.core.$strict>>>;
89
+ }, z.core.$strict>>;
90
+ type SemanticOutcome = z.infer<typeof SemanticOutcomeSchema>;
91
+ type RendererOutcome = z.infer<typeof RendererOutcomeSchema>;
92
+ interface ParityMismatch {
93
+ readonly renderer: string;
94
+ readonly turnId: string;
95
+ readonly kind: string;
96
+ readonly expected?: SemanticOutcome;
97
+ readonly actual?: SemanticOutcome;
98
+ }
99
+ interface RendererParityReport {
100
+ readonly ok: boolean;
101
+ readonly baseline: string;
102
+ readonly renderers: readonly string[];
103
+ readonly mismatches: readonly ParityMismatch[];
104
+ }
105
+ declare const compareRendererOutcomes: (input: readonly RendererOutcome[]) => RendererParityReport;
106
+
107
+ export { type AppendTraceInput, type ApplicationTraceRecord, ApplicationTraceRecordSchema, type ParityMismatch, type RendererOutcome, RendererOutcomeSchema, type RendererParityReport, type ReplayFixture, ReplayFixtureSchema, type SemanticOutcome, SemanticOutcomeSchema, type TraceCapture, type TraceCaptureOptions, type TraceCategory, TraceCategorySchema, captureActionPolicyTrace, captureActionTrace, captureTurnTrace, compareRendererOutcomes, createReplayFixture, createTraceCapture, parseReplayFixture, serializeReplayFixture };
@@ -0,0 +1,107 @@
1
+ import { Cassette } from '@agentskit/eval/replay';
2
+ import { ActionPolicyTrace, ActionConfirmation, TurnTrace } from '@agentskit/chat';
3
+ import { z } from 'zod';
4
+
5
+ declare const TraceCategorySchema: z.ZodEnum<{
6
+ route: "route";
7
+ agent: "agent";
8
+ repair: "repair";
9
+ fallback: "fallback";
10
+ policy: "policy";
11
+ action: "action";
12
+ lifecycle: "lifecycle";
13
+ }>;
14
+ declare const ApplicationTraceRecordSchema: z.ZodReadonly<z.ZodObject<{
15
+ id: z.ZodString;
16
+ sequence: z.ZodNumber;
17
+ at: z.ZodISODateTime;
18
+ category: z.ZodEnum<{
19
+ route: "route";
20
+ agent: "agent";
21
+ repair: "repair";
22
+ fallback: "fallback";
23
+ policy: "policy";
24
+ action: "action";
25
+ lifecycle: "lifecycle";
26
+ }>;
27
+ parentId: z.ZodOptional<z.ZodString>;
28
+ detail: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
29
+ }, z.core.$strict>>;
30
+ type TraceCategory = z.infer<typeof TraceCategorySchema>;
31
+ type ApplicationTraceRecord = z.infer<typeof ApplicationTraceRecordSchema>;
32
+ interface TraceCaptureOptions {
33
+ readonly redactFields?: readonly string[];
34
+ readonly now?: () => Date;
35
+ }
36
+ interface AppendTraceInput {
37
+ readonly category: TraceCategory;
38
+ readonly detail: Readonly<Record<string, unknown>>;
39
+ readonly parentId?: string;
40
+ readonly at?: string;
41
+ }
42
+ interface TraceCapture {
43
+ append(input: AppendTraceInput): ApplicationTraceRecord;
44
+ snapshot(): readonly ApplicationTraceRecord[];
45
+ }
46
+ declare const createTraceCapture: (options?: TraceCaptureOptions) => TraceCapture;
47
+ declare const captureTurnTrace: (capture: TraceCapture, trace: TurnTrace, parentId?: string) => ApplicationTraceRecord;
48
+ declare const captureActionPolicyTrace: (capture: TraceCapture, trace: ActionPolicyTrace, parentId?: string) => ApplicationTraceRecord;
49
+ declare const captureActionTrace: (capture: TraceCapture, action: ActionConfirmation, parentId?: string) => ApplicationTraceRecord;
50
+ declare const ReplayFixtureSchema: z.ZodReadonly<z.ZodObject<{
51
+ protocol: z.ZodLiteral<"agentskit.chat.replay">;
52
+ version: z.ZodLiteral<1>;
53
+ cassette: z.ZodUnknown;
54
+ traces: z.ZodArray<z.ZodReadonly<z.ZodObject<{
55
+ id: z.ZodString;
56
+ sequence: z.ZodNumber;
57
+ at: z.ZodISODateTime;
58
+ category: z.ZodEnum<{
59
+ route: "route";
60
+ agent: "agent";
61
+ repair: "repair";
62
+ fallback: "fallback";
63
+ policy: "policy";
64
+ action: "action";
65
+ lifecycle: "lifecycle";
66
+ }>;
67
+ parentId: z.ZodOptional<z.ZodString>;
68
+ detail: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
69
+ }, z.core.$strict>>>;
70
+ }, z.core.$strict>>;
71
+ type ReplayFixture = Omit<z.infer<typeof ReplayFixtureSchema>, 'cassette'> & {
72
+ readonly cassette: Cassette;
73
+ };
74
+ declare const createReplayFixture: (cassette: Cassette, traces: readonly ApplicationTraceRecord[]) => ReplayFixture;
75
+ declare const serializeReplayFixture: (fixture: ReplayFixture) => string;
76
+ declare const parseReplayFixture: (input: string) => ReplayFixture;
77
+ declare const SemanticOutcomeSchema: z.ZodReadonly<z.ZodObject<{
78
+ turnId: z.ZodString;
79
+ kind: z.ZodString;
80
+ value: z.ZodOptional<z.ZodJSONSchema>;
81
+ }, z.core.$strict>>;
82
+ declare const RendererOutcomeSchema: z.ZodReadonly<z.ZodObject<{
83
+ renderer: z.ZodString;
84
+ outcomes: z.ZodArray<z.ZodReadonly<z.ZodObject<{
85
+ turnId: z.ZodString;
86
+ kind: z.ZodString;
87
+ value: z.ZodOptional<z.ZodJSONSchema>;
88
+ }, z.core.$strict>>>;
89
+ }, z.core.$strict>>;
90
+ type SemanticOutcome = z.infer<typeof SemanticOutcomeSchema>;
91
+ type RendererOutcome = z.infer<typeof RendererOutcomeSchema>;
92
+ interface ParityMismatch {
93
+ readonly renderer: string;
94
+ readonly turnId: string;
95
+ readonly kind: string;
96
+ readonly expected?: SemanticOutcome;
97
+ readonly actual?: SemanticOutcome;
98
+ }
99
+ interface RendererParityReport {
100
+ readonly ok: boolean;
101
+ readonly baseline: string;
102
+ readonly renderers: readonly string[];
103
+ readonly mismatches: readonly ParityMismatch[];
104
+ }
105
+ declare const compareRendererOutcomes: (input: readonly RendererOutcome[]) => RendererParityReport;
106
+
107
+ export { type AppendTraceInput, type ApplicationTraceRecord, ApplicationTraceRecordSchema, type ParityMismatch, type RendererOutcome, RendererOutcomeSchema, type RendererParityReport, type ReplayFixture, ReplayFixtureSchema, type SemanticOutcome, SemanticOutcomeSchema, type TraceCapture, type TraceCaptureOptions, type TraceCategory, TraceCategorySchema, captureActionPolicyTrace, captureActionTrace, captureTurnTrace, compareRendererOutcomes, createReplayFixture, createTraceCapture, parseReplayFixture, serializeReplayFixture };
package/dist/index.js ADDED
@@ -0,0 +1,127 @@
1
+ // src/index.ts
2
+ import { parseCassette, serializeCassette } from "@agentskit/eval/replay";
3
+ import { z } from "zod";
4
+ var IdSchema = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/);
5
+ var DetailSchema = z.record(z.string().min(1).max(128), z.json()).refine((value) => new TextEncoder().encode(JSON.stringify(value)).byteLength <= 65536, "Trace detail exceeds 64 KiB.");
6
+ var TraceCategorySchema = z.enum(["route", "agent", "repair", "fallback", "policy", "action", "lifecycle"]);
7
+ var ApplicationTraceRecordSchema = z.object({
8
+ id: IdSchema,
9
+ sequence: z.number().int().nonnegative(),
10
+ at: z.iso.datetime(),
11
+ category: TraceCategorySchema,
12
+ parentId: IdSchema.optional(),
13
+ detail: DetailSchema
14
+ }).strict().readonly();
15
+ var redact = (value, fields) => {
16
+ if (Array.isArray(value)) return value.map((item) => redact(item, fields));
17
+ if (value !== null && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, fields.has(key.toLowerCase()) ? "[REDACTED]" : redact(item, fields)]));
18
+ return value;
19
+ };
20
+ var deepFreeze = (value) => {
21
+ if (Array.isArray(value)) {
22
+ value.forEach(deepFreeze);
23
+ return Object.freeze(value);
24
+ }
25
+ if (value !== null && typeof value === "object") {
26
+ Object.values(value).forEach(deepFreeze);
27
+ return Object.freeze(value);
28
+ }
29
+ return value;
30
+ };
31
+ var createTraceCapture = (options = {}) => {
32
+ const fields = new Set((options.redactFields ?? []).map((field) => field.toLowerCase()));
33
+ const records = [];
34
+ return {
35
+ append: (input) => {
36
+ if (input.parentId !== void 0 && !records.some((record2) => record2.id === input.parentId)) throw new Error("Trace parent must refer to an earlier record.");
37
+ const sequence = records.length;
38
+ const detail = DetailSchema.parse(redact(DetailSchema.parse(input.detail), fields));
39
+ const record = deepFreeze(ApplicationTraceRecordSchema.parse({ id: `trace-${sequence}`, sequence, at: input.at ?? (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString(), category: input.category, ...input.parentId === void 0 ? {} : { parentId: input.parentId }, detail }));
40
+ records.push(record);
41
+ return record;
42
+ },
43
+ snapshot: () => Object.freeze(records.map((record) => deepFreeze({ ...record, detail: structuredClone(record.detail) })))
44
+ };
45
+ };
46
+ var captureTurnTrace = (capture, trace, parentId) => capture.append({
47
+ category: trace.kind === "deterministic" ? "route" : trace.kind === "agentic" ? "agent" : trace.kind === "repaired" ? "repair" : "fallback",
48
+ detail: { kind: trace.kind, ...trace.routeId === void 0 ? {} : { routeId: trace.routeId }, fromState: trace.fromState, toState: trace.toState },
49
+ ...parentId === void 0 ? {} : { parentId }
50
+ });
51
+ var captureActionPolicyTrace = (capture, trace, parentId) => capture.append({
52
+ category: "policy",
53
+ at: new Date(trace.timestamp).toISOString(),
54
+ detail: { policyTraceId: trace.id, toolCallId: trace.toolCallId, action: trace.action, phase: trace.phase, decision: trace.decision, reason: trace.reason, requiredCapabilities: [...trace.requiredCapabilities] },
55
+ ...parentId === void 0 ? {} : { parentId }
56
+ });
57
+ var captureActionTrace = (capture, action, parentId) => capture.append({
58
+ category: "action",
59
+ detail: { action: action.action, toolCallId: action.toolCallId, status: action.status, expiresAt: action.expiresAt },
60
+ ...parentId === void 0 ? {} : { parentId }
61
+ });
62
+ var ReplayFixtureSchema = z.object({
63
+ protocol: z.literal("agentskit.chat.replay"),
64
+ version: z.literal(1),
65
+ cassette: z.unknown(),
66
+ traces: z.array(ApplicationTraceRecordSchema).max(1e4)
67
+ }).strict().readonly().superRefine((fixture, context) => {
68
+ const prior = /* @__PURE__ */ new Set();
69
+ fixture.traces.forEach((trace, index) => {
70
+ if (trace.sequence !== index) context.addIssue({ code: "custom", path: ["traces", index, "sequence"], message: "Trace sequence must be contiguous." });
71
+ if (prior.has(trace.id)) context.addIssue({ code: "custom", path: ["traces", index, "id"], message: "Trace ids must be unique." });
72
+ if (trace.parentId !== void 0 && !prior.has(trace.parentId)) context.addIssue({ code: "custom", path: ["traces", index, "parentId"], message: "Trace parent must precede its child." });
73
+ prior.add(trace.id);
74
+ });
75
+ });
76
+ var createReplayFixture = (cassette, traces) => {
77
+ const upstream = parseCassette(serializeCassette(cassette));
78
+ const envelope = ReplayFixtureSchema.parse({ protocol: "agentskit.chat.replay", version: 1, cassette: upstream, traces });
79
+ return { ...envelope, cassette: upstream };
80
+ };
81
+ var serializeReplayFixture = (fixture) => JSON.stringify(createReplayFixture(fixture.cassette, fixture.traces), null, 2);
82
+ var parseReplayFixture = (input) => {
83
+ if (new TextEncoder().encode(input).byteLength > 16777216) throw new Error("Replay fixture exceeds 16 MiB.");
84
+ const envelope = ReplayFixtureSchema.parse(JSON.parse(input));
85
+ const cassette = parseCassette(JSON.stringify(envelope.cassette));
86
+ return { ...envelope, cassette };
87
+ };
88
+ var SemanticOutcomeSchema = z.object({ turnId: IdSchema, kind: IdSchema, value: z.json().optional() }).strict().readonly();
89
+ var RendererOutcomeSchema = z.object({ renderer: IdSchema, outcomes: z.array(SemanticOutcomeSchema).max(1e4) }).strict().readonly();
90
+ var canonical = (value) => JSON.stringify(value, (_key, item) => item !== null && typeof item === "object" && !Array.isArray(item) ? Object.fromEntries(Object.entries(item).sort(([left], [right]) => left.localeCompare(right))) : item);
91
+ var compareRendererOutcomes = (input) => {
92
+ const renderers = z.array(RendererOutcomeSchema).min(2).parse(input);
93
+ if (new Set(renderers.map((item) => item.renderer)).size !== renderers.length) throw new Error("Renderer ids must be unique.");
94
+ const key = (outcome) => `${outcome.turnId}\0${outcome.kind}`;
95
+ for (const item of renderers) if (new Set(item.outcomes.map(key)).size !== item.outcomes.length) throw new Error("Turn and kind pairs must be unique per renderer.");
96
+ const baseline = renderers[0];
97
+ const expected = new Map(baseline.outcomes.map((outcome) => [key(outcome), outcome]));
98
+ const outcomeKeys = new Set(renderers.flatMap((renderer) => renderer.outcomes.map(key)));
99
+ const mismatches = [];
100
+ for (const renderer of renderers.slice(1)) {
101
+ const actual = new Map(renderer.outcomes.map((outcome) => [key(outcome), outcome]));
102
+ for (const outcomeKey of outcomeKeys) {
103
+ const left = expected.get(outcomeKey);
104
+ const right = actual.get(outcomeKey);
105
+ if (canonical(left) !== canonical(right)) {
106
+ const [turnId, kind] = outcomeKey.split("\0");
107
+ mismatches.push({ renderer: renderer.renderer, turnId, kind, ...left === void 0 ? {} : { expected: left }, ...right === void 0 ? {} : { actual: right } });
108
+ }
109
+ }
110
+ }
111
+ return deepFreeze(structuredClone({ ok: mismatches.length === 0, baseline: baseline.renderer, renderers: renderers.map((item) => item.renderer), mismatches }));
112
+ };
113
+ export {
114
+ ApplicationTraceRecordSchema,
115
+ RendererOutcomeSchema,
116
+ ReplayFixtureSchema,
117
+ SemanticOutcomeSchema,
118
+ TraceCategorySchema,
119
+ captureActionPolicyTrace,
120
+ captureActionTrace,
121
+ captureTurnTrace,
122
+ compareRendererOutcomes,
123
+ createReplayFixture,
124
+ createTraceCapture,
125
+ parseReplayFixture,
126
+ serializeReplayFixture
127
+ };
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@agentskit/chat-devtools",
3
+ "version": "0.1.0",
4
+ "description": "Replayable application traces and semantic renderer parity for AgentsKit Chat.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/AgentsKit-io/agentskit-chat.git",
9
+ "directory": "packages/devtools"
10
+ },
11
+ "homepage": "https://github.com/AgentsKit-io/agentskit-chat#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/AgentsKit-io/agentskit-chat/issues"
14
+ },
15
+ "type": "module",
16
+ "main": "./dist/index.cjs",
17
+ "module": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js",
23
+ "require": "./dist/index.cjs"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "dependencies": {
30
+ "@agentskit/eval": "^0.4.19",
31
+ "zod": "^4.3.6",
32
+ "@agentskit/chat": "0.1.0"
33
+ },
34
+ "devDependencies": {
35
+ "@agentskit/core": "^1.12.2",
36
+ "@types/node": "^25.0.0",
37
+ "tsup": "^8.5.1"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public",
41
+ "provenance": true
42
+ },
43
+ "scripts": {
44
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean",
45
+ "lint": "tsc --noEmit",
46
+ "test": "vitest run --coverage"
47
+ }
48
+ }