stitchkit 0.85.1 → 0.86.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/CHANGELOG.md +178 -0
- package/README.md +3 -0
- package/dist/agent-runtime/agent-tool.d.ts +25 -0
- package/dist/agent-runtime/agent-tool.d.ts.map +1 -0
- package/dist/agent-runtime/child-tools.d.ts +69 -0
- package/dist/agent-runtime/child-tools.d.ts.map +1 -0
- package/dist/agent-runtime/children.d.ts +113 -0
- package/dist/agent-runtime/children.d.ts.map +1 -0
- package/dist/agent-runtime/coding-tool-contract.d.ts +29 -0
- package/dist/agent-runtime/coding-tool-contract.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-refusals.d.ts +2 -0
- package/dist/agent-runtime/coding-tool-refusals.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-shell.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tools.d.ts +1 -0
- package/dist/agent-runtime/coding-tools.d.ts.map +1 -1
- package/dist/agent-runtime/control-schema.d.ts +17 -0
- package/dist/agent-runtime/control-schema.d.ts.map +1 -1
- package/dist/agent-runtime/event-schema.d.ts +34 -0
- package/dist/agent-runtime/event-schema.d.ts.map +1 -1
- package/dist/agent-runtime/event-search-tools.d.ts +53 -0
- package/dist/agent-runtime/event-search-tools.d.ts.map +1 -0
- package/dist/agent-runtime/event-search.d.ts +23 -0
- package/dist/agent-runtime/event-search.d.ts.map +1 -0
- package/dist/agent-runtime/fault-bench.d.ts +45 -0
- package/dist/agent-runtime/fault-bench.d.ts.map +1 -0
- package/dist/agent-runtime/observability.d.ts +6 -0
- package/dist/agent-runtime/observability.d.ts.map +1 -1
- package/dist/agent-runtime/projections.d.ts +69 -0
- package/dist/agent-runtime/projections.d.ts.map +1 -0
- package/dist/agent-runtime/provider-failure.d.ts +5 -1
- package/dist/agent-runtime/provider-failure.d.ts.map +1 -1
- package/dist/agent-runtime/provider-origin.d.ts +12 -0
- package/dist/agent-runtime/provider-origin.d.ts.map +1 -0
- package/dist/agent-runtime/retry-policy.d.ts +27 -0
- package/dist/agent-runtime/retry-policy.d.ts.map +1 -0
- package/dist/agent-runtime/run-execution.d.ts +0 -9
- package/dist/agent-runtime/run-execution.d.ts.map +1 -1
- package/dist/agent-runtime/run-mutation-queue.d.ts +21 -0
- package/dist/agent-runtime/run-mutation-queue.d.ts.map +1 -0
- package/dist/agent-runtime/run-operation-lifecycle.d.ts +3 -0
- package/dist/agent-runtime/run-operation-lifecycle.d.ts.map +1 -1
- package/dist/agent-runtime/runtime.d.ts +15 -0
- package/dist/agent-runtime/runtime.d.ts.map +1 -1
- package/dist/agent-runtime/sandbox.d.ts +66 -0
- package/dist/agent-runtime/sandbox.d.ts.map +1 -0
- package/dist/agent-runtime/schedule-tools.d.ts +35 -0
- package/dist/agent-runtime/schedule-tools.d.ts.map +1 -0
- package/dist/agent-runtime/schedules.d.ts +63 -0
- package/dist/agent-runtime/schedules.d.ts.map +1 -0
- package/dist/agent-runtime/schemas.d.ts +9 -0
- package/dist/agent-runtime/schemas.d.ts.map +1 -1
- package/dist/agent-runtime/spill.d.ts +24 -0
- package/dist/agent-runtime/spill.d.ts.map +1 -0
- package/dist/agent-runtime/sqlite-purge.d.ts.map +1 -1
- package/dist/agent-runtime/sqlite.d.ts +26 -0
- package/dist/agent-runtime/sqlite.d.ts.map +1 -1
- package/dist/agent-runtime/state-slots.d.ts +48 -0
- package/dist/agent-runtime/state-slots.d.ts.map +1 -0
- package/dist/agent-runtime/state-tools.d.ts +58 -0
- package/dist/agent-runtime/state-tools.d.ts.map +1 -0
- package/dist/agent-runtime/store-driver.d.ts +13 -0
- package/dist/agent-runtime/store-driver.d.ts.map +1 -1
- package/dist/agent-runtime/store-events.d.ts +829 -0
- package/dist/agent-runtime/store-events.d.ts.map +1 -0
- package/dist/agent-runtime/store-migrations/v1-to-v2.d.ts +6 -0
- package/dist/agent-runtime/store-migrations/v1-to-v2.d.ts.map +1 -0
- package/dist/agent-runtime/store.d.ts +45 -0
- package/dist/agent-runtime/store.d.ts.map +1 -1
- package/dist/agent-runtime/terminal-commit.d.ts +1 -1
- package/dist/agent-runtime-browser.js +5 -3
- package/dist/agent-runtime-coding-tools.js +144 -15
- package/dist/agent-runtime-harness.js +12 -10
- package/dist/agent-runtime-sqlite-bun.d.ts +1 -1
- package/dist/agent-runtime-sqlite-bun.d.ts.map +1 -1
- package/dist/agent-runtime-sqlite-bun.js +4 -3
- package/dist/agent-runtime-sqlite-node.d.ts +1 -1
- package/dist/agent-runtime-sqlite-node.d.ts.map +1 -1
- package/dist/agent-runtime-sqlite-node.js +4 -3
- package/dist/agent-runtime-testing.d.ts +3 -0
- package/dist/agent-runtime-testing.d.ts.map +1 -0
- package/dist/agent-runtime-testing.js +156 -0
- package/dist/agent-runtime.d.ts +16 -2
- package/dist/agent-runtime.d.ts.map +1 -1
- package/dist/agent-runtime.js +1591 -154
- package/dist/application.js +14 -14
- package/dist/cli.js +6 -6
- package/dist/{index-fwbkp2jn.js → index-0vfdh685.js} +2 -2
- package/dist/{index-5z8tezpx.js → index-0ydchz76.js} +3 -3
- package/dist/{index-3ds42w1w.js → index-1szetq6f.js} +33 -4
- package/dist/{index-jpp7jd1p.js → index-33xckd7h.js} +898 -425
- package/dist/{index-27487ay5.js → index-9hw9eq48.js} +4 -4
- package/dist/{index-66nxrgy0.js → index-b7qwhbzq.js} +428 -46
- package/dist/index-cnyk6te3.js +77 -0
- package/dist/index-gskm1k5a.js +50 -0
- package/dist/{index-fq492hg0.js → index-hber83mk.js} +254 -157
- package/dist/{index-4hk633vz.js → index-hkm6wysp.js} +9 -2
- package/dist/{index-dx9xehwt.js → index-kc6h6hg0.js} +1 -1
- package/dist/{index-x15ss2dx.js → index-p1b1y93x.js} +3 -0
- package/dist/{index-mgtxfe6b.js → index-r159gjwy.js} +8 -1
- package/dist/{index-s4ckmrac.js → index-rcgsnrr6.js} +3 -3
- package/dist/index-vfgb58nf.js +252 -0
- package/dist/{index-dggwnnjv.js → index-wn9cb82y.js} +1 -1
- package/dist/{index-ff0kcqvp.js → index-z2452tsw.js} +3 -3
- package/dist/testing/agent-store-conformance.d.ts.map +1 -1
- package/dist/testing.js +54 -80
- package/dist/tool-invoker.js +4 -4
- package/dist/tools/internal/surface-projector.d.ts.map +1 -1
- package/dist/tools/manifest.d.ts +16 -0
- package/dist/tools/manifest.d.ts.map +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +10 -8
- package/llms-full.txt +321 -13
- package/package.json +6 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// src/agent-runtime/testing.ts
|
|
2
|
+
function createAgentRaceBarrier(timeoutMs = 5000) {
|
|
3
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1) {
|
|
4
|
+
throw new TypeError("Agent race barrier timeoutMs must be a positive safe integer");
|
|
5
|
+
}
|
|
6
|
+
const reached = Promise.withResolvers();
|
|
7
|
+
const released = Promise.withResolvers();
|
|
8
|
+
let announced = false;
|
|
9
|
+
return {
|
|
10
|
+
reached: reached.promise,
|
|
11
|
+
async wait() {
|
|
12
|
+
if (!announced) {
|
|
13
|
+
announced = true;
|
|
14
|
+
reached.resolve();
|
|
15
|
+
}
|
|
16
|
+
let timer;
|
|
17
|
+
try {
|
|
18
|
+
await Promise.race([
|
|
19
|
+
released.promise,
|
|
20
|
+
new Promise((_resolve, reject) => {
|
|
21
|
+
timer = setTimeout(() => reject(new Error(`Agent race barrier exceeded ${timeoutMs}ms teardown bound`)), timeoutMs);
|
|
22
|
+
})
|
|
23
|
+
]);
|
|
24
|
+
} finally {
|
|
25
|
+
if (timer !== undefined)
|
|
26
|
+
clearTimeout(timer);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
release: released.resolve
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function createAgentRaceTrace() {
|
|
33
|
+
const recorded = [];
|
|
34
|
+
return {
|
|
35
|
+
record(name) {
|
|
36
|
+
const entry = { name, sequence: recorded.length };
|
|
37
|
+
recorded.push(entry);
|
|
38
|
+
return entry;
|
|
39
|
+
},
|
|
40
|
+
entries: () => recorded.map((entry) => ({ ...entry })),
|
|
41
|
+
assertBefore(first, second) {
|
|
42
|
+
const firstEntry = recorded.find((entry) => entry.name === first);
|
|
43
|
+
const secondEntry = recorded.find((entry) => entry.name === second);
|
|
44
|
+
if (!firstEntry || !secondEntry || firstEntry.sequence >= secondEntry.sequence) {
|
|
45
|
+
throw new Error(`Expected ${first} before ${second}`);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
assertSequence(names) {
|
|
49
|
+
const actual = recorded.map((entry) => entry.name);
|
|
50
|
+
if (actual.length !== names.length || actual.some((name, index) => name !== names[index])) {
|
|
51
|
+
throw new Error(`Expected trace ${names.join(" -> ")}, received ${actual.join(" -> ")}`);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
count: (name) => recorded.filter((entry) => entry.name === name).length
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function createAgentRaceDriver(timeoutMs = 5000) {
|
|
58
|
+
const trace = createAgentRaceTrace();
|
|
59
|
+
const barriers = new Map;
|
|
60
|
+
return {
|
|
61
|
+
trace,
|
|
62
|
+
barrier(name) {
|
|
63
|
+
const existing = barriers.get(name);
|
|
64
|
+
if (existing)
|
|
65
|
+
return existing;
|
|
66
|
+
const created = createAgentRaceBarrier(timeoutMs);
|
|
67
|
+
barriers.set(name, created);
|
|
68
|
+
return created;
|
|
69
|
+
},
|
|
70
|
+
releaseAll() {
|
|
71
|
+
for (const barrier of barriers.values())
|
|
72
|
+
barrier.release();
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { createAgentRaceBarrier, createAgentRaceTrace, createAgentRaceDriver };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// src/agent-runtime/sandbox.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var AgentSandboxRestrictionSchema = z.enum([
|
|
4
|
+
"network-denied",
|
|
5
|
+
"write-contained",
|
|
6
|
+
"secrets-hidden",
|
|
7
|
+
"process-contained"
|
|
8
|
+
]);
|
|
9
|
+
var AgentSandboxGradeSchema = z.discriminatedUnion("grade", [
|
|
10
|
+
z.object({ grade: z.literal("full"), restrictions: z.array(AgentSandboxRestrictionSchema) }).strict(),
|
|
11
|
+
z.object({
|
|
12
|
+
grade: z.literal("partial"),
|
|
13
|
+
restrictions: z.array(AgentSandboxRestrictionSchema),
|
|
14
|
+
gaps: z.array(AgentSandboxRestrictionSchema)
|
|
15
|
+
}).strict(),
|
|
16
|
+
z.object({ grade: z.literal("unavailable"), reason: z.string().min(1) }).strict()
|
|
17
|
+
]);
|
|
18
|
+
var probes = new WeakMap;
|
|
19
|
+
function probeAgentProcessSandbox(sandbox, options = {}) {
|
|
20
|
+
if (options.refresh)
|
|
21
|
+
probes.delete(sandbox);
|
|
22
|
+
const present = probes.get(sandbox);
|
|
23
|
+
if (present)
|
|
24
|
+
return present;
|
|
25
|
+
const pending = Promise.resolve(sandbox.probe()).then((grade) => AgentSandboxGradeSchema.parse(grade));
|
|
26
|
+
probes.set(sandbox, pending);
|
|
27
|
+
return pending;
|
|
28
|
+
}
|
|
29
|
+
function missingSandboxRestrictions(grade, required) {
|
|
30
|
+
if (grade.grade === "unavailable")
|
|
31
|
+
return required;
|
|
32
|
+
const present = new Set(grade.restrictions);
|
|
33
|
+
return required.filter((restriction) => !present.has(restriction));
|
|
34
|
+
}
|
|
35
|
+
async function recordAgentSandboxProbe(input) {
|
|
36
|
+
const grade = await probeAgentProcessSandbox(input.sandbox);
|
|
37
|
+
const missing = missingSandboxRestrictions(grade, input.required);
|
|
38
|
+
await input.store.appendEvent({
|
|
39
|
+
conversationId: input.conversationId,
|
|
40
|
+
kind: "sandbox/probed",
|
|
41
|
+
payload: {
|
|
42
|
+
result: grade,
|
|
43
|
+
required: [...input.required],
|
|
44
|
+
missing: [...missing]
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return grade;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { AgentSandboxRestrictionSchema, AgentSandboxGradeSchema, probeAgentProcessSandbox, missingSandboxRestrictions, recordAgentSandboxProbe };
|
|
@@ -1,51 +1,51 @@
|
|
|
1
1
|
import {
|
|
2
2
|
assistantStatus
|
|
3
3
|
} from "./index-y2s6h5bf.js";
|
|
4
|
+
import {
|
|
5
|
+
AcceptInputAndAssignRunSchema,
|
|
6
|
+
AcquireAgentRunSchema,
|
|
7
|
+
AgentRecoverablePageSchema,
|
|
8
|
+
AgentRunViewSchema,
|
|
9
|
+
AgentStoreEventEnvelopeSchema,
|
|
10
|
+
AgentStoreEventPageSchema,
|
|
11
|
+
AgentStoreTransitionSchema,
|
|
12
|
+
AppendAgentStoreEventSchema,
|
|
13
|
+
CheckpointRunAssistantSchema,
|
|
14
|
+
CommitRunTerminalSchema,
|
|
15
|
+
ReadAgentStoreEventsSchema,
|
|
16
|
+
RecordRunOperationSchema,
|
|
17
|
+
RecoverAgentRunSchema,
|
|
18
|
+
ReplaceCompactedRangeSchema,
|
|
19
|
+
RequestRunInterruptSchema,
|
|
20
|
+
agentStoreEventDraft,
|
|
21
|
+
canonicalAgentJson,
|
|
22
|
+
decodeAgentConversationArchive,
|
|
23
|
+
encodeAgentConversationArchive
|
|
24
|
+
} from "./index-vfgb58nf.js";
|
|
4
25
|
import {
|
|
5
26
|
AgentMessageSchema,
|
|
6
27
|
AgentRecordIdSchema,
|
|
7
28
|
AgentRecordVersionSchema,
|
|
8
|
-
AgentRunOperationSchema,
|
|
9
29
|
AgentRunSchema,
|
|
10
30
|
AgentSnapshotSchema,
|
|
11
|
-
AgentTerminalReasonSchema,
|
|
12
|
-
AgentUsageSchema,
|
|
13
31
|
runStateForTerminalReason
|
|
14
|
-
} from "./index-
|
|
15
|
-
|
|
16
|
-
// src/agent-runtime/conversations.ts
|
|
17
|
-
import { z } from "zod";
|
|
18
|
-
var AgentConversationSummarySchema = z.object({
|
|
19
|
-
conversationId: AgentRecordIdSchema,
|
|
20
|
-
version: AgentRecordVersionSchema,
|
|
21
|
-
updatedAt: z.iso.datetime({ offset: true }),
|
|
22
|
-
preview: z.string(),
|
|
23
|
-
activeRuns: z.int().nonnegative()
|
|
24
|
-
}).strict();
|
|
25
|
-
var AgentConversationPageSchema = z.object({
|
|
26
|
-
items: z.array(AgentConversationSummarySchema),
|
|
27
|
-
nextCursor: z.string().min(1).optional()
|
|
28
|
-
}).strict();
|
|
29
|
-
var AgentConversationMessagePageSchema = z.object({
|
|
30
|
-
items: z.array(AgentMessageSchema),
|
|
31
|
-
nextCursor: z.string().min(1).optional()
|
|
32
|
-
}).strict();
|
|
32
|
+
} from "./index-p1b1y93x.js";
|
|
33
33
|
|
|
34
34
|
// src/agent-runtime/purge.ts
|
|
35
|
-
import { z
|
|
36
|
-
var AgentConversationPurgeInputSchema =
|
|
35
|
+
import { z } from "zod";
|
|
36
|
+
var AgentConversationPurgeInputSchema = z.strictObject({
|
|
37
37
|
conversationId: AgentRecordIdSchema,
|
|
38
38
|
expectedVersion: AgentRecordVersionSchema.optional()
|
|
39
39
|
});
|
|
40
|
-
var AgentConversationPurgeResultSchema =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
outcome:
|
|
46
|
-
runIds:
|
|
40
|
+
var AgentConversationPurgeResultSchema = z.discriminatedUnion("outcome", [
|
|
41
|
+
z.strictObject({ outcome: z.literal("purged") }),
|
|
42
|
+
z.strictObject({ outcome: z.literal("already_purged") }),
|
|
43
|
+
z.strictObject({ outcome: z.literal("unsupported") }),
|
|
44
|
+
z.strictObject({
|
|
45
|
+
outcome: z.literal("active"),
|
|
46
|
+
runIds: z.array(AgentRecordIdSchema).min(1)
|
|
47
47
|
}),
|
|
48
|
-
|
|
48
|
+
z.strictObject({ outcome: z.literal("conflict"), actualVersion: AgentRecordVersionSchema })
|
|
49
49
|
]);
|
|
50
50
|
|
|
51
51
|
class AgentConversationPurgedError extends Error {
|
|
@@ -61,112 +61,27 @@ async function purgeAgentConversation(store, input) {
|
|
|
61
61
|
return AgentConversationPurgeResultSchema.parse(await store.purgeConversation(parsed));
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
// src/agent-runtime/
|
|
65
|
-
import { z as
|
|
66
|
-
var
|
|
67
|
-
outcome: z3.literal("conflict"),
|
|
68
|
-
actualVersion: AgentRecordVersionSchema
|
|
69
|
-
});
|
|
70
|
-
var AgentStoreNotFoundSchema = z3.object({ outcome: z3.literal("not_found") });
|
|
71
|
-
var AgentStoreAppliedSchema = z3.object({
|
|
72
|
-
outcome: z3.literal("applied"),
|
|
73
|
-
snapshot: AgentSnapshotSchema
|
|
74
|
-
});
|
|
75
|
-
var AgentStoreDuplicateSchema = z3.object({
|
|
76
|
-
outcome: z3.literal("duplicate"),
|
|
77
|
-
input: AgentMessageSchema,
|
|
78
|
-
inputMessageId: AgentRecordIdSchema,
|
|
79
|
-
runId: AgentRecordIdSchema,
|
|
80
|
-
assistantMessageId: AgentRecordIdSchema,
|
|
81
|
-
run: AgentRunSchema,
|
|
82
|
-
assistant: AgentMessageSchema.optional(),
|
|
83
|
-
snapshot: AgentSnapshotSchema
|
|
84
|
-
});
|
|
85
|
-
var AgentStoreMutationResultSchema = z3.discriminatedUnion("outcome", [
|
|
86
|
-
AgentStoreAppliedSchema,
|
|
87
|
-
AgentStoreDuplicateSchema,
|
|
88
|
-
AgentStoreConflictSchema,
|
|
89
|
-
AgentStoreNotFoundSchema
|
|
90
|
-
]);
|
|
91
|
-
var AgentRunViewSchema = z3.object({
|
|
92
|
-
snapshotVersion: AgentRecordVersionSchema,
|
|
93
|
-
run: AgentRunSchema,
|
|
94
|
-
assistant: AgentMessageSchema.optional()
|
|
95
|
-
});
|
|
96
|
-
var AcceptInputAndAssignRunSchema = z3.object({
|
|
97
|
-
idempotencyKey: z3.string().min(1),
|
|
98
|
-
expectedVersion: AgentRecordVersionSchema.optional(),
|
|
99
|
-
input: AgentMessageSchema,
|
|
100
|
-
run: AgentRunSchema,
|
|
101
|
-
coalesceIntoRunId: AgentRecordIdSchema.optional()
|
|
102
|
-
});
|
|
103
|
-
var AcquireAgentRunSchema = z3.object({
|
|
104
|
-
conversationId: AgentRecordIdSchema,
|
|
105
|
-
runId: AgentRecordIdSchema,
|
|
106
|
-
expectedRevision: AgentRecordVersionSchema,
|
|
107
|
-
ownerId: z3.string().min(1)
|
|
108
|
-
});
|
|
109
|
-
var CheckpointRunAssistantSchema = z3.object({
|
|
110
|
-
conversationId: AgentRecordIdSchema,
|
|
111
|
-
runId: AgentRecordIdSchema,
|
|
112
|
-
expectedRevision: AgentRecordVersionSchema,
|
|
113
|
-
ownerId: z3.string().min(1),
|
|
114
|
-
fencingToken: AgentRecordVersionSchema.optional(),
|
|
115
|
-
assistant: AgentMessageSchema,
|
|
116
|
-
usage: AgentUsageSchema.optional()
|
|
117
|
-
});
|
|
118
|
-
var RecordRunOperationSchema = z3.object({
|
|
119
|
-
conversationId: AgentRecordIdSchema,
|
|
120
|
-
runId: AgentRecordIdSchema,
|
|
121
|
-
expectedRevision: AgentRecordVersionSchema,
|
|
122
|
-
ownerId: z3.string().min(1),
|
|
123
|
-
fencingToken: AgentRecordVersionSchema.optional(),
|
|
124
|
-
operation: AgentRunOperationSchema
|
|
125
|
-
});
|
|
126
|
-
var CommitRunTerminalSchema = z3.object({
|
|
127
|
-
conversationId: AgentRecordIdSchema,
|
|
128
|
-
runId: AgentRecordIdSchema,
|
|
129
|
-
expectedRevision: AgentRecordVersionSchema,
|
|
130
|
-
ownerId: z3.string().min(1),
|
|
131
|
-
fencingToken: AgentRecordVersionSchema.optional(),
|
|
132
|
-
assistant: AgentMessageSchema,
|
|
133
|
-
reason: AgentTerminalReasonSchema,
|
|
134
|
-
policyName: z3.string().min(1).optional(),
|
|
135
|
-
usage: AgentUsageSchema.optional(),
|
|
136
|
-
absorb: z3.array(z3.object({
|
|
137
|
-
runId: AgentRecordIdSchema,
|
|
138
|
-
inputMessageIds: z3.array(AgentRecordIdSchema).min(1)
|
|
139
|
-
})).min(1).optional()
|
|
140
|
-
});
|
|
141
|
-
var RequestRunInterruptSchema = z3.object({
|
|
142
|
-
conversationId: AgentRecordIdSchema,
|
|
143
|
-
runId: AgentRecordIdSchema,
|
|
144
|
-
expectedRevision: AgentRecordVersionSchema
|
|
145
|
-
});
|
|
146
|
-
var RecoverAgentRunSchema = z3.object({
|
|
147
|
-
conversationId: AgentRecordIdSchema,
|
|
148
|
-
runId: AgentRecordIdSchema,
|
|
149
|
-
expectedRevision: AgentRecordVersionSchema,
|
|
150
|
-
action: z3.enum(["requeue", "abandon"]),
|
|
151
|
-
replaySafe: z3.boolean().optional()
|
|
152
|
-
});
|
|
153
|
-
var ReplaceCompactedRangeSchema = z3.object({
|
|
154
|
-
conversationId: AgentRecordIdSchema,
|
|
155
|
-
expectedVersion: AgentRecordVersionSchema,
|
|
156
|
-
replacedMessageIds: z3.array(AgentRecordIdSchema).min(1),
|
|
157
|
-
summary: AgentMessageSchema
|
|
158
|
-
});
|
|
159
|
-
var AgentRecoverableDescriptorSchema = z3.object({
|
|
64
|
+
// src/agent-runtime/conversations.ts
|
|
65
|
+
import { z as z2 } from "zod";
|
|
66
|
+
var AgentConversationSummarySchema = z2.object({
|
|
160
67
|
conversationId: AgentRecordIdSchema,
|
|
161
|
-
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
68
|
+
version: AgentRecordVersionSchema,
|
|
69
|
+
updatedAt: z2.iso.datetime({ offset: true }),
|
|
70
|
+
preview: z2.string(),
|
|
71
|
+
activeRuns: z2.int().nonnegative()
|
|
72
|
+
}).strict();
|
|
73
|
+
var AgentConversationPageSchema = z2.object({
|
|
74
|
+
items: z2.array(AgentConversationSummarySchema),
|
|
75
|
+
nextCursor: z2.string().min(1).optional()
|
|
76
|
+
}).strict();
|
|
77
|
+
var AgentConversationMessagePageSchema = z2.object({
|
|
78
|
+
items: z2.array(AgentMessageSchema),
|
|
79
|
+
nextCursor: z2.string().min(1).optional()
|
|
80
|
+
}).strict();
|
|
167
81
|
|
|
168
82
|
// src/agent-runtime/store-driver.ts
|
|
169
|
-
import {
|
|
83
|
+
import { createHash } from "node:crypto";
|
|
84
|
+
import { z as z3 } from "zod";
|
|
170
85
|
|
|
171
86
|
// src/agent-runtime/store-purge.ts
|
|
172
87
|
function createStoreConversationPurge(driver, conversations) {
|
|
@@ -192,40 +107,59 @@ function createStoreConversationPurge(driver, conversations) {
|
|
|
192
107
|
}
|
|
193
108
|
|
|
194
109
|
// src/agent-runtime/store-driver.ts
|
|
195
|
-
var AgentRuntimeHeadSchema =
|
|
196
|
-
schemaVersion:
|
|
110
|
+
var AgentRuntimeHeadSchema = z3.object({
|
|
111
|
+
schemaVersion: z3.literal(1),
|
|
197
112
|
conversationId: AgentRecordIdSchema,
|
|
198
113
|
version: AgentRecordVersionSchema
|
|
199
114
|
});
|
|
200
|
-
var AgentStoredRunSchema =
|
|
201
|
-
schemaVersion:
|
|
115
|
+
var AgentStoredRunSchema = z3.object({
|
|
116
|
+
schemaVersion: z3.literal(1),
|
|
202
117
|
run: AgentRunSchema,
|
|
203
118
|
terminalAssistant: AgentMessageSchema.optional()
|
|
204
119
|
});
|
|
205
|
-
var AgentAdmissionReceiptSchema =
|
|
206
|
-
schemaVersion:
|
|
120
|
+
var AgentAdmissionReceiptSchema = z3.object({
|
|
121
|
+
schemaVersion: z3.literal(1),
|
|
207
122
|
conversationId: AgentRecordIdSchema,
|
|
208
|
-
idempotencyKey:
|
|
123
|
+
idempotencyKey: z3.string().min(1),
|
|
209
124
|
input: AgentMessageSchema,
|
|
210
125
|
runId: AgentRecordIdSchema,
|
|
211
126
|
assistantMessageId: AgentRecordIdSchema
|
|
212
127
|
});
|
|
213
|
-
var AgentHistoryMutationSchema =
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
type:
|
|
128
|
+
var AgentHistoryMutationSchema = z3.discriminatedUnion("type", [
|
|
129
|
+
z3.object({ type: z3.literal("admit"), input: AgentMessageSchema }),
|
|
130
|
+
z3.object({
|
|
131
|
+
type: z3.literal("upsert-assistant"),
|
|
217
132
|
message: AgentMessageSchema
|
|
218
133
|
}),
|
|
219
|
-
|
|
220
|
-
type:
|
|
221
|
-
replacedMessageIds:
|
|
134
|
+
z3.object({
|
|
135
|
+
type: z3.literal("replace-compacted-range"),
|
|
136
|
+
replacedMessageIds: z3.array(AgentRecordIdSchema).min(1),
|
|
222
137
|
summary: AgentMessageSchema
|
|
223
138
|
})
|
|
224
139
|
]);
|
|
225
|
-
var AgentRecoverableScanInputSchema =
|
|
226
|
-
cursor:
|
|
227
|
-
limit:
|
|
140
|
+
var AgentRecoverableScanInputSchema = z3.object({
|
|
141
|
+
cursor: z3.string().min(1).optional(),
|
|
142
|
+
limit: z3.number().int().min(1).max(1000)
|
|
228
143
|
});
|
|
144
|
+
function transitionRecord(operation) {
|
|
145
|
+
if (operation.type !== "checkpoint")
|
|
146
|
+
return operation;
|
|
147
|
+
const { assistant, ...rest } = operation.input;
|
|
148
|
+
const body = canonicalAgentJson(assistant);
|
|
149
|
+
return {
|
|
150
|
+
type: operation.type,
|
|
151
|
+
input: {
|
|
152
|
+
...rest,
|
|
153
|
+
assistant: {
|
|
154
|
+
id: assistant.id,
|
|
155
|
+
status: assistant.status,
|
|
156
|
+
sha256: createHash("sha256").update(body).digest("hex"),
|
|
157
|
+
parts: assistant.parts.length,
|
|
158
|
+
bytes: Buffer.byteLength(body)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
229
163
|
function emptyHead(conversationId) {
|
|
230
164
|
return AgentRuntimeHeadSchema.parse({
|
|
231
165
|
schemaVersion: 1,
|
|
@@ -328,7 +262,7 @@ function validateSnapshot(head, messages, records) {
|
|
|
328
262
|
}
|
|
329
263
|
}
|
|
330
264
|
}
|
|
331
|
-
var RecoverableCursorSchema =
|
|
265
|
+
var RecoverableCursorSchema = z3.tuple([AgentRecordIdSchema, AgentRecordIdSchema]);
|
|
332
266
|
function recoverableCursor(input) {
|
|
333
267
|
return JSON.stringify([input.conversationId, input.run.id]);
|
|
334
268
|
}
|
|
@@ -650,7 +584,7 @@ function validateAdmissionReceipt(receipt, record, conversationId) {
|
|
|
650
584
|
}
|
|
651
585
|
}
|
|
652
586
|
function createAgentRuntimeStore(driver) {
|
|
653
|
-
const
|
|
587
|
+
const snapshotIn = async (transaction, conversationId) => {
|
|
654
588
|
const [stored, messages, activeRecords] = await Promise.all([
|
|
655
589
|
driver.head.load(transaction, conversationId),
|
|
656
590
|
driver.history.load(transaction, conversationId),
|
|
@@ -662,7 +596,10 @@ function createAgentRuntimeStore(driver) {
|
|
|
662
596
|
runIds: referencedRunIds(messages)
|
|
663
597
|
});
|
|
664
598
|
return snapshotOf(head, messages, mergeRunRecords(activeRecords, referencedRecords));
|
|
665
|
-
}
|
|
599
|
+
};
|
|
600
|
+
const loadSnapshot = (conversationId) => driver.transaction((transaction) => snapshotIn(transaction, conversationId), {
|
|
601
|
+
access: "read"
|
|
602
|
+
});
|
|
666
603
|
const loadRun = (input) => driver.transaction(async (transaction) => {
|
|
667
604
|
const [stored, record] = await Promise.all([
|
|
668
605
|
driver.head.load(transaction, input.conversationId),
|
|
@@ -798,12 +735,142 @@ function createAgentRuntimeStore(driver) {
|
|
|
798
735
|
for (const mutation of reduced.historyMutations ?? []) {
|
|
799
736
|
await driver.history.apply(transaction, mutation);
|
|
800
737
|
}
|
|
738
|
+
await driver.events.append(transaction, agentStoreEventDraft({
|
|
739
|
+
conversationId,
|
|
740
|
+
kind: "runtime/transition",
|
|
741
|
+
payload: z3.json().parse(transitionRecord(operation))
|
|
742
|
+
}));
|
|
801
743
|
return { outcome: "applied", snapshot: reduced.snapshot };
|
|
802
744
|
});
|
|
745
|
+
const appendEvent = (input) => {
|
|
746
|
+
const parsed = AppendAgentStoreEventSchema.parse(input);
|
|
747
|
+
return driver.transaction(async (transaction) => {
|
|
748
|
+
if (await driver.conversations?.isPurged(transaction, parsed.conversationId)) {
|
|
749
|
+
throw new AgentConversationPurgedError;
|
|
750
|
+
}
|
|
751
|
+
return driver.events.append(transaction, agentStoreEventDraft(parsed));
|
|
752
|
+
});
|
|
753
|
+
};
|
|
754
|
+
const readEvents = (input) => {
|
|
755
|
+
const parsed = ReadAgentStoreEventsSchema.parse(input);
|
|
756
|
+
return driver.transaction(async (transaction) => AgentStoreEventPageSchema.parse(await driver.events.list(transaction, parsed)), { access: "read" });
|
|
757
|
+
};
|
|
758
|
+
const exportConversation = (conversationId) => driver.transaction(async (transaction) => {
|
|
759
|
+
const events = [];
|
|
760
|
+
let fromSeq;
|
|
761
|
+
do {
|
|
762
|
+
const page = AgentStoreEventPageSchema.parse(await driver.events.list(transaction, ReadAgentStoreEventsSchema.parse({
|
|
763
|
+
conversationId,
|
|
764
|
+
...fromSeq && { fromSeq },
|
|
765
|
+
limit: 1e4
|
|
766
|
+
})));
|
|
767
|
+
events.push(...page.items);
|
|
768
|
+
fromSeq = page.nextSeq;
|
|
769
|
+
} while (fromSeq !== undefined);
|
|
770
|
+
const durable = await driver.archive?.export(transaction, conversationId) ?? {
|
|
771
|
+
projections: [],
|
|
772
|
+
spills: []
|
|
773
|
+
};
|
|
774
|
+
const snapshot = await snapshotIn(transaction, conversationId);
|
|
775
|
+
return encodeAgentConversationArchive({
|
|
776
|
+
format: "stitchkit.agent-conversation",
|
|
777
|
+
formatVersion: 1,
|
|
778
|
+
conversationId,
|
|
779
|
+
events,
|
|
780
|
+
projections: [
|
|
781
|
+
{ archiveType: "runtime-snapshot", snapshot: z3.json().parse(snapshot) },
|
|
782
|
+
...durable.projections
|
|
783
|
+
],
|
|
784
|
+
spills: durable.spills
|
|
785
|
+
});
|
|
786
|
+
}, { access: "read" });
|
|
787
|
+
const importConversation = async (bytes) => {
|
|
788
|
+
const archive = decodeAgentConversationArchive(bytes);
|
|
789
|
+
return driver.transaction(async (transaction) => {
|
|
790
|
+
const existing = await driver.events.list(transaction, {
|
|
791
|
+
conversationId: archive.conversationId,
|
|
792
|
+
limit: 1
|
|
793
|
+
});
|
|
794
|
+
if (existing.items.length > 0) {
|
|
795
|
+
throw new TypeError("Conversation event log must be empty before import");
|
|
796
|
+
}
|
|
797
|
+
for (const event of archive.events) {
|
|
798
|
+
const appended = await driver.events.append(transaction, {
|
|
799
|
+
schemaVersion: event.schemaVersion,
|
|
800
|
+
eventId: event.eventId,
|
|
801
|
+
conversationId: event.conversationId,
|
|
802
|
+
kind: event.kind,
|
|
803
|
+
occurredAt: event.occurredAt,
|
|
804
|
+
payload: event.payload,
|
|
805
|
+
...event.ignorable && { ignorable: true }
|
|
806
|
+
});
|
|
807
|
+
if (appended.seq !== event.seq) {
|
|
808
|
+
throw new TypeError("Conversation archive event sequence is not contiguous");
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
const snapshotEntry = archive.projections.find((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) && entry.archiveType === "runtime-snapshot");
|
|
812
|
+
if (snapshotEntry && typeof snapshotEntry === "object" && !Array.isArray(snapshotEntry)) {
|
|
813
|
+
const snapshot = AgentSnapshotSchema.parse(snapshotEntry.snapshot);
|
|
814
|
+
if (snapshot.conversationId !== archive.conversationId) {
|
|
815
|
+
throw new TypeError("Conversation archive snapshot belongs to another conversation");
|
|
816
|
+
}
|
|
817
|
+
if (snapshot.version > 0 || snapshot.messages.length > 0 || snapshot.runs.length > 0) {
|
|
818
|
+
const outcome = await driver.head.compareAndSwap(transaction, {
|
|
819
|
+
conversationId: snapshot.conversationId,
|
|
820
|
+
expectedVersion: 0,
|
|
821
|
+
next: AgentRuntimeHeadSchema.parse({
|
|
822
|
+
schemaVersion: 1,
|
|
823
|
+
conversationId: snapshot.conversationId,
|
|
824
|
+
version: snapshot.version
|
|
825
|
+
})
|
|
826
|
+
});
|
|
827
|
+
if (outcome.outcome !== "applied") {
|
|
828
|
+
throw new TypeError("Conversation archive snapshot target is not empty");
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
for (const run of snapshot.runs) {
|
|
832
|
+
const terminalAssistant = snapshot.messages.find((message) => message.id === run.assistantMessageId);
|
|
833
|
+
await driver.runs.save(transaction, AgentStoredRunSchema.parse({
|
|
834
|
+
schemaVersion: 1,
|
|
835
|
+
run,
|
|
836
|
+
...terminalAssistant && { terminalAssistant }
|
|
837
|
+
}));
|
|
838
|
+
}
|
|
839
|
+
for (const message of snapshot.messages) {
|
|
840
|
+
await driver.history.apply(transaction, { type: "admit", input: message });
|
|
841
|
+
}
|
|
842
|
+
for (const event of archive.events) {
|
|
843
|
+
if (event.kind !== "runtime/transition")
|
|
844
|
+
continue;
|
|
845
|
+
const transition = AgentStoreTransitionSchema.parse(event.payload);
|
|
846
|
+
if (transition.type !== "accept")
|
|
847
|
+
continue;
|
|
848
|
+
const assigned = snapshot.runs.find((run) => run.inputMessageIds.includes(transition.input.input.id));
|
|
849
|
+
if (!assigned) {
|
|
850
|
+
throw new TypeError("Conversation archive admission has no assigned run");
|
|
851
|
+
}
|
|
852
|
+
await driver.admissions.create(transaction, AgentAdmissionReceiptSchema.parse({
|
|
853
|
+
schemaVersion: 1,
|
|
854
|
+
conversationId: archive.conversationId,
|
|
855
|
+
idempotencyKey: transition.input.idempotencyKey,
|
|
856
|
+
input: transition.input.input,
|
|
857
|
+
runId: assigned.id,
|
|
858
|
+
assistantMessageId: assigned.assistantMessageId
|
|
859
|
+
}));
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
await driver.archive?.import(transaction, archive);
|
|
863
|
+
return { conversationId: archive.conversationId, events: archive.events.length };
|
|
864
|
+
});
|
|
865
|
+
};
|
|
803
866
|
return {
|
|
804
867
|
loadSnapshot,
|
|
805
868
|
loadRun,
|
|
806
869
|
listActiveRuns,
|
|
870
|
+
appendEvent,
|
|
871
|
+
readEvents,
|
|
872
|
+
exportConversation,
|
|
873
|
+
importConversation,
|
|
807
874
|
...driver.conversations && {
|
|
808
875
|
purgeConversation: createStoreConversationPurge(driver, driver.conversations)
|
|
809
876
|
},
|
|
@@ -860,6 +927,7 @@ function createMemoryAgentRuntimeStore() {
|
|
|
860
927
|
let runs = new Map;
|
|
861
928
|
let admissions = new Map;
|
|
862
929
|
let histories = new Map;
|
|
930
|
+
let events = new Map;
|
|
863
931
|
let transactionTail = Promise.resolve();
|
|
864
932
|
const driver = {
|
|
865
933
|
async transaction(work) {
|
|
@@ -876,7 +944,11 @@ function createMemoryAgentRuntimeStore() {
|
|
|
876
944
|
heads: cloneHeadMap(heads),
|
|
877
945
|
runs: cloneNestedMap(runs, (record) => AgentStoredRunSchema.parse(structuredClone(record))),
|
|
878
946
|
admissions: cloneNestedMap(admissions, (receipt) => AgentAdmissionReceiptSchema.parse(structuredClone(receipt))),
|
|
879
|
-
histories: cloneHistoryMap(histories)
|
|
947
|
+
histories: cloneHistoryMap(histories),
|
|
948
|
+
events: new Map([...events].map(([conversationId, stored]) => [
|
|
949
|
+
conversationId,
|
|
950
|
+
stored.map((event) => AgentStoreEventEnvelopeSchema.parse(structuredClone(event)))
|
|
951
|
+
]))
|
|
880
952
|
};
|
|
881
953
|
try {
|
|
882
954
|
const result = await work(transaction);
|
|
@@ -885,6 +957,7 @@ function createMemoryAgentRuntimeStore() {
|
|
|
885
957
|
runs = transaction.runs;
|
|
886
958
|
admissions = transaction.admissions;
|
|
887
959
|
histories = transaction.histories;
|
|
960
|
+
events = transaction.events;
|
|
888
961
|
return result;
|
|
889
962
|
} finally {
|
|
890
963
|
release.resolve();
|
|
@@ -900,6 +973,7 @@ function createMemoryAgentRuntimeStore() {
|
|
|
900
973
|
transaction.runs.delete(conversationId);
|
|
901
974
|
transaction.admissions.delete(conversationId);
|
|
902
975
|
transaction.histories.delete(conversationId);
|
|
976
|
+
transaction.events.delete(conversationId);
|
|
903
977
|
}
|
|
904
978
|
},
|
|
905
979
|
head: {
|
|
@@ -995,6 +1069,29 @@ function createMemoryAgentRuntimeStore() {
|
|
|
995
1069
|
]);
|
|
996
1070
|
}
|
|
997
1071
|
},
|
|
1072
|
+
events: {
|
|
1073
|
+
async append(transaction, draft) {
|
|
1074
|
+
const current = transaction.events.get(draft.conversationId) ?? [];
|
|
1075
|
+
const event = AgentStoreEventEnvelopeSchema.parse({
|
|
1076
|
+
...draft,
|
|
1077
|
+
seq: (current.at(-1)?.seq ?? 0) + 1
|
|
1078
|
+
});
|
|
1079
|
+
if (current.some((candidate) => candidate.eventId === event.eventId)) {
|
|
1080
|
+
throw new TypeError("Agent store event identity is already present");
|
|
1081
|
+
}
|
|
1082
|
+
transaction.events.set(draft.conversationId, [...current, event]);
|
|
1083
|
+
return event;
|
|
1084
|
+
},
|
|
1085
|
+
async list(transaction, input) {
|
|
1086
|
+
const selected = (transaction.events.get(input.conversationId) ?? []).filter((event) => (input.fromSeq === undefined || event.seq >= input.fromSeq) && (input.toSeq === undefined || event.seq <= input.toSeq));
|
|
1087
|
+
const items = selected.slice(0, input.limit);
|
|
1088
|
+
const last = items.at(-1);
|
|
1089
|
+
return AgentStoreEventPageSchema.parse({
|
|
1090
|
+
items,
|
|
1091
|
+
...selected.length > items.length && last ? { nextSeq: last.seq + 1 } : {}
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
998
1095
|
async scanRecoverable(input) {
|
|
999
1096
|
const descriptors = [...runs].flatMap(([conversationId, conversationRuns]) => [...conversationRuns.values()].filter((record) => isActiveRunState(record.run.state)).map((record) => ({ conversationId, run: record.run }))).sort((left, right) => left.conversationId.localeCompare(right.conversationId) || left.run.id.localeCompare(right.run.id));
|
|
1000
1097
|
const cursorTuple = input.cursor ? parseRecoverableCursor(input.cursor) : undefined;
|
|
@@ -1014,4 +1111,4 @@ function createMemoryAgentRuntimeStore() {
|
|
|
1014
1111
|
return createAgentRuntimeStore(driver);
|
|
1015
1112
|
}
|
|
1016
1113
|
|
|
1017
|
-
export {
|
|
1114
|
+
export { AgentConversationPurgeInputSchema, AgentConversationPurgeResultSchema, AgentConversationPurgedError, purgeAgentConversation, AgentConversationSummarySchema, AgentConversationPageSchema, AgentConversationMessagePageSchema, AgentRuntimeHeadSchema, AgentStoredRunSchema, AgentAdmissionReceiptSchema, AgentHistoryMutationSchema, ACTIVE_AGENT_RUN_STATES, createAgentRuntimeStore, createMemoryAgentRuntimeStore };
|