stitchkit 0.84.1 → 0.85.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 +37 -0
- package/dist/agent-runtime/control-schema.d.ts +61 -0
- package/dist/agent-runtime/control-schema.d.ts.map +1 -1
- package/dist/agent-runtime/event-schema.d.ts +88 -1
- package/dist/agent-runtime/event-schema.d.ts.map +1 -1
- package/dist/agent-runtime/run-execution.d.ts.map +1 -1
- package/dist/agent-runtime/run-operation-lifecycle.d.ts +21 -0
- package/dist/agent-runtime/run-operation-lifecycle.d.ts.map +1 -0
- package/dist/agent-runtime/schemas.d.ts +67 -0
- package/dist/agent-runtime/schemas.d.ts.map +1 -1
- package/dist/agent-runtime/store-driver.d.ts +18 -0
- package/dist/agent-runtime/store-driver.d.ts.map +1 -1
- package/dist/agent-runtime/store.d.ts +208 -0
- package/dist/agent-runtime/store.d.ts.map +1 -1
- package/dist/agent-runtime/terminal-commit.d.ts +9 -0
- package/dist/agent-runtime/terminal-commit.d.ts.map +1 -1
- package/dist/agent-runtime-browser.js +11 -3
- package/dist/agent-runtime-harness.js +4 -4
- package/dist/agent-runtime-sqlite-bun.js +3 -3
- package/dist/agent-runtime-sqlite-node.js +3 -3
- package/dist/agent-runtime.d.ts +2 -2
- package/dist/agent-runtime.d.ts.map +1 -1
- package/dist/agent-runtime.js +14 -4
- package/dist/{index-85vfqd7m.js → index-4hk633vz.js} +11 -3
- package/dist/{index-devfkwfm.js → index-66nxrgy0.js} +2 -2
- package/dist/{index-st8v8739.js → index-9merfjxf.js} +141 -14
- package/dist/{index-5s3zajp8.js → index-ff0kcqvp.js} +9 -3
- package/dist/{index-11vzj2sk.js → index-fq492hg0.js} +28 -2
- package/dist/{index-x1th9s8c.js → index-x15ss2dx.js} +50 -1
- package/dist/testing.js +26 -2
- package/llms-full.txt +56 -5
- package/package.json +1 -1
|
@@ -12,17 +12,18 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
AgentRuntimeEventSchema,
|
|
14
14
|
agentDurableEventId
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-4hk633vz.js";
|
|
16
16
|
import {
|
|
17
17
|
AgentAssistantPlaceholderSchema,
|
|
18
18
|
AgentJsonObjectSchema,
|
|
19
19
|
AgentMessagePartSchema,
|
|
20
20
|
AgentMessageSchema,
|
|
21
21
|
AgentProvenanceSchema,
|
|
22
|
+
AgentRunOperationSchema,
|
|
22
23
|
AgentRunSchema,
|
|
23
24
|
AgentSnapshotSchema,
|
|
24
25
|
runStateForTerminalReason
|
|
25
|
-
} from "./index-
|
|
26
|
+
} from "./index-x15ss2dx.js";
|
|
26
27
|
import {
|
|
27
28
|
isAgentToolError
|
|
28
29
|
} from "./index-3xnq72rz.js";
|
|
@@ -1074,6 +1075,73 @@ function createIdleDeadline(parent, timeoutMs) {
|
|
|
1074
1075
|
};
|
|
1075
1076
|
}
|
|
1076
1077
|
|
|
1078
|
+
// src/agent-runtime/run-operation-lifecycle.ts
|
|
1079
|
+
function createAgentRunOperationLifecycle(config) {
|
|
1080
|
+
let active;
|
|
1081
|
+
const record = async (operation) => {
|
|
1082
|
+
const current = config.currentRun();
|
|
1083
|
+
const snapshot = appliedSnapshot(await config.store.recordRunOperation({
|
|
1084
|
+
conversationId: current.conversationId,
|
|
1085
|
+
runId: current.id,
|
|
1086
|
+
expectedRevision: current.revision,
|
|
1087
|
+
ownerId: config.runtimeEpoch,
|
|
1088
|
+
...current.fencingToken !== undefined && { fencingToken: current.fencingToken },
|
|
1089
|
+
operation
|
|
1090
|
+
}), "run operation");
|
|
1091
|
+
config.acceptSnapshot(snapshot);
|
|
1092
|
+
const run = findRun(snapshot.runs, current.id);
|
|
1093
|
+
active = operation;
|
|
1094
|
+
await config.publish({
|
|
1095
|
+
type: "run-operation",
|
|
1096
|
+
eventId: agentDurableEventId("run-operation", run.id, snapshot.version),
|
|
1097
|
+
conversationId: run.conversationId,
|
|
1098
|
+
runId: run.id,
|
|
1099
|
+
snapshotVersion: snapshot.version,
|
|
1100
|
+
operation,
|
|
1101
|
+
emittedAt: config.now().toISOString()
|
|
1102
|
+
});
|
|
1103
|
+
};
|
|
1104
|
+
return {
|
|
1105
|
+
startCompaction(operationId) {
|
|
1106
|
+
return record(AgentRunOperationSchema.parse({
|
|
1107
|
+
operationId,
|
|
1108
|
+
kind: "compaction",
|
|
1109
|
+
phase: "started",
|
|
1110
|
+
startedAt: config.now().toISOString()
|
|
1111
|
+
}));
|
|
1112
|
+
},
|
|
1113
|
+
startModelRequest(providerCallId, step) {
|
|
1114
|
+
return record(AgentRunOperationSchema.parse({
|
|
1115
|
+
operationId: `${providerCallId}:${step}`,
|
|
1116
|
+
kind: "model-request",
|
|
1117
|
+
phase: "started",
|
|
1118
|
+
step,
|
|
1119
|
+
startedAt: config.now().toISOString()
|
|
1120
|
+
}));
|
|
1121
|
+
},
|
|
1122
|
+
firstOutput() {
|
|
1123
|
+
if (active?.kind !== "model-request" || active.phase !== "started") {
|
|
1124
|
+
return Promise.resolve();
|
|
1125
|
+
}
|
|
1126
|
+
return record(AgentRunOperationSchema.parse({
|
|
1127
|
+
...active,
|
|
1128
|
+
phase: "first-output",
|
|
1129
|
+
firstOutputAt: config.now().toISOString()
|
|
1130
|
+
}));
|
|
1131
|
+
},
|
|
1132
|
+
finish(phase) {
|
|
1133
|
+
if (!active || ["completed", "failed", "cancelled"].includes(active.phase)) {
|
|
1134
|
+
return Promise.resolve();
|
|
1135
|
+
}
|
|
1136
|
+
return record(AgentRunOperationSchema.parse({
|
|
1137
|
+
...active,
|
|
1138
|
+
phase,
|
|
1139
|
+
finishedAt: config.now().toISOString()
|
|
1140
|
+
}));
|
|
1141
|
+
}
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1077
1145
|
// src/agent-runtime/run-execution.ts
|
|
1078
1146
|
function snapshotForRunPrompt(snapshot, runId) {
|
|
1079
1147
|
const runIndex = snapshot.runs.findIndex((candidate) => candidate.id === runId);
|
|
@@ -1184,7 +1252,7 @@ function createRunExecutor(dependencies) {
|
|
|
1184
1252
|
let observedVersion = snapshot.version;
|
|
1185
1253
|
const parts = [];
|
|
1186
1254
|
const absorbed = new Map;
|
|
1187
|
-
let
|
|
1255
|
+
let eventsSinceCheckpoint = 0;
|
|
1188
1256
|
let sequence = 0;
|
|
1189
1257
|
let terminalReason = "success";
|
|
1190
1258
|
let nonModelUsage = input.acceptedRun.usage;
|
|
@@ -1199,6 +1267,18 @@ function createRunExecutor(dependencies) {
|
|
|
1199
1267
|
let terminalPolicyName;
|
|
1200
1268
|
const idleDeadline = createIdleDeadline(input.signal, idleTimeoutMs);
|
|
1201
1269
|
const executionSignal = idleDeadline.signal;
|
|
1270
|
+
const operationLifecycle = createAgentRunOperationLifecycle({
|
|
1271
|
+
store: config.store,
|
|
1272
|
+
runtimeEpoch,
|
|
1273
|
+
currentRun: () => run,
|
|
1274
|
+
acceptSnapshot: (next) => {
|
|
1275
|
+
snapshot = next;
|
|
1276
|
+
observedVersion = next.version;
|
|
1277
|
+
run = findRun(next.runs, run.id);
|
|
1278
|
+
},
|
|
1279
|
+
publish,
|
|
1280
|
+
now
|
|
1281
|
+
});
|
|
1202
1282
|
const updateReasoning = (text, metadata) => {
|
|
1203
1283
|
const provider = providerEnvelope(metadata);
|
|
1204
1284
|
if (reasoningPartIndex === undefined) {
|
|
@@ -1256,14 +1336,30 @@ function createRunExecutor(dependencies) {
|
|
|
1256
1336
|
};
|
|
1257
1337
|
try {
|
|
1258
1338
|
if (config.history?.compact) {
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1339
|
+
await operationLifecycle.startCompaction(generateId());
|
|
1340
|
+
let compacted;
|
|
1341
|
+
try {
|
|
1342
|
+
compacted = await config.history.compact({
|
|
1343
|
+
conversationId: run.conversationId,
|
|
1344
|
+
store: config.store,
|
|
1345
|
+
signal: executionSignal
|
|
1346
|
+
});
|
|
1347
|
+
snapshot = compacted.snapshot;
|
|
1348
|
+
observedVersion = snapshot.version;
|
|
1349
|
+
run = findRun(snapshot.runs, run.id);
|
|
1350
|
+
await operationLifecycle.finish("completed");
|
|
1351
|
+
} catch (error) {
|
|
1352
|
+
const latest = await config.store.loadRun({
|
|
1353
|
+
conversationId: run.conversationId,
|
|
1354
|
+
runId: run.id
|
|
1355
|
+
});
|
|
1356
|
+
if (latest?.run.ownerId === runtimeEpoch) {
|
|
1357
|
+
observedVersion = latest.snapshotVersion;
|
|
1358
|
+
run = latest.run;
|
|
1359
|
+
}
|
|
1360
|
+
await operationLifecycle.finish(executionSignal.aborted ? "cancelled" : "failed");
|
|
1361
|
+
throw error;
|
|
1362
|
+
}
|
|
1267
1363
|
if (compacted.usage) {
|
|
1268
1364
|
nonModelUsage = addUsage(nonModelUsage, compacted.usage);
|
|
1269
1365
|
usage = modelUsage ? addUsage(nonModelUsage, modelUsage) : nonModelUsage;
|
|
@@ -1418,6 +1514,9 @@ function createRunExecutor(dependencies) {
|
|
|
1418
1514
|
abortSignal: executionSignal,
|
|
1419
1515
|
maxRetries: 0,
|
|
1420
1516
|
stopWhen: stopConditions,
|
|
1517
|
+
onLanguageModelCallStart: async (event) => {
|
|
1518
|
+
await operationLifecycle.startModelRequest(event.callId, step);
|
|
1519
|
+
},
|
|
1421
1520
|
repairToolCall: deferredToolRepair(config.loop?.prepareStep),
|
|
1422
1521
|
...config.loop?.toolApproval && {
|
|
1423
1522
|
toolApproval: config.loop.toolApproval,
|
|
@@ -1428,6 +1527,13 @@ function createRunExecutor(dependencies) {
|
|
|
1428
1527
|
},
|
|
1429
1528
|
...(config.loop?.prepareStep || injection) && {
|
|
1430
1529
|
prepareStep: async (options) => {
|
|
1530
|
+
const previousStep = options.steps.at(-1);
|
|
1531
|
+
if (previousStep) {
|
|
1532
|
+
lastPromptTokens = selectedModel?.normalizeUsage?.({
|
|
1533
|
+
usage: previousStep.usage,
|
|
1534
|
+
providerMetadata: previousStep.providerMetadata
|
|
1535
|
+
})?.inputTokens ?? normalizeSdkUsage(previousStep.usage).inputTokens;
|
|
1536
|
+
}
|
|
1431
1537
|
const prepared = await config.loop?.prepareStep?.({
|
|
1432
1538
|
...options,
|
|
1433
1539
|
...runtimeContext
|
|
@@ -1442,11 +1548,14 @@ function createRunExecutor(dependencies) {
|
|
|
1442
1548
|
});
|
|
1443
1549
|
for await (const part of result.stream) {
|
|
1444
1550
|
idleDeadline.touch();
|
|
1445
|
-
|
|
1551
|
+
eventsSinceCheckpoint += 1;
|
|
1446
1552
|
sequence += 1;
|
|
1447
|
-
if (firstOutputAt === undefined &&
|
|
1553
|
+
if (firstOutputAt === undefined && (part.type === "text-delta" && part.text.length > 0 || part.type === "reasoning-delta" && part.text.length > 0 || part.type === "tool-input-delta" && part.delta.length > 0 || part.type === "tool-call")) {
|
|
1448
1554
|
firstOutputAt = performance.now();
|
|
1449
1555
|
}
|
|
1556
|
+
if (part.type === "text-delta" && part.text.length > 0 || part.type === "reasoning-delta" && part.text.length > 0 || part.type === "tool-input-delta" && part.delta.length > 0 || part.type === "tool-call") {
|
|
1557
|
+
await operationLifecycle.firstOutput();
|
|
1558
|
+
}
|
|
1450
1559
|
if (part.type === "text-delta") {
|
|
1451
1560
|
appendText(parts, part.text);
|
|
1452
1561
|
await publish({
|
|
@@ -1552,6 +1661,7 @@ function createRunExecutor(dependencies) {
|
|
|
1552
1661
|
status: "interrupted",
|
|
1553
1662
|
emittedAt: now().toISOString()
|
|
1554
1663
|
});
|
|
1664
|
+
await checkpoint();
|
|
1555
1665
|
throw part.error;
|
|
1556
1666
|
}
|
|
1557
1667
|
const output = isAgentToolError(part.error) ? jsonValue(part.error.output) : { message: "Tool execution failed" };
|
|
@@ -1661,6 +1771,7 @@ function createRunExecutor(dependencies) {
|
|
|
1661
1771
|
terminalReason = part.error instanceof AgentContextOverflowError ? "context_overflow" : "provider_failure";
|
|
1662
1772
|
internalCause = part.error;
|
|
1663
1773
|
} else if (part.type === "finish-step") {
|
|
1774
|
+
await operationLifecycle.finish(part.finishReason === "error" ? "failed" : "completed");
|
|
1664
1775
|
const stepTrace = trace ? config.observe?.rootTrace(trace) : undefined;
|
|
1665
1776
|
const stepUsage = selectedModel.normalizeUsage?.({
|
|
1666
1777
|
usage: part.usage,
|
|
@@ -1696,9 +1807,21 @@ function createRunExecutor(dependencies) {
|
|
|
1696
1807
|
modelUsage = mergeModelTotals(normalizeSdkUsage(part.totalUsage), modelUsage);
|
|
1697
1808
|
usage = nonModelUsage ? addUsage(nonModelUsage, modelUsage) : modelUsage;
|
|
1698
1809
|
}
|
|
1699
|
-
|
|
1810
|
+
const structuralBoundary = [
|
|
1811
|
+
"tool-call",
|
|
1812
|
+
"tool-result",
|
|
1813
|
+
"tool-error",
|
|
1814
|
+
"tool-output-denied",
|
|
1815
|
+
"tool-approval-request",
|
|
1816
|
+
"tool-approval-response",
|
|
1817
|
+
"finish-step"
|
|
1818
|
+
].includes(part.type);
|
|
1819
|
+
if (structuralBoundary || eventsSinceCheckpoint >= checkpointEveryEvents) {
|
|
1700
1820
|
await checkpoint();
|
|
1821
|
+
eventsSinceCheckpoint = 0;
|
|
1822
|
+
}
|
|
1701
1823
|
}
|
|
1824
|
+
await operationLifecycle.finish(executionSignal.aborted ? "cancelled" : terminalReason === "provider_failure" ? "failed" : "completed");
|
|
1702
1825
|
if (terminalPolicyName !== undefined)
|
|
1703
1826
|
terminalReason = "policy_stop";
|
|
1704
1827
|
if (executionSignal.aborted)
|
|
@@ -1732,6 +1855,10 @@ function createRunExecutor(dependencies) {
|
|
|
1732
1855
|
observedVersion = latest.snapshotVersion;
|
|
1733
1856
|
run = latestRun;
|
|
1734
1857
|
}
|
|
1858
|
+
const staleOwner = isToolExecutionControlError(error) && error.reason === "stale_run";
|
|
1859
|
+
if (!staleOwner) {
|
|
1860
|
+
await operationLifecycle.finish(executionSignal.aborted || durableInterrupt ? "cancelled" : "failed");
|
|
1861
|
+
}
|
|
1735
1862
|
if (isToolExecutionControlError(error) || executionSignal.aborted || durableInterrupt) {
|
|
1736
1863
|
terminalReason = executionSignal.aborted ? abortTerminalReason(executionSignal) : "interrupted";
|
|
1737
1864
|
parts.push(AgentMessagePartSchema.parse({
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AgentRuntimeEventSchema
|
|
3
|
-
} from "./index-
|
|
3
|
+
} from "./index-4hk633vz.js";
|
|
4
4
|
import {
|
|
5
5
|
AgentMessagePartSchema,
|
|
6
6
|
AgentSnapshotSchema
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-x15ss2dx.js";
|
|
8
8
|
|
|
9
9
|
// src/agent-runtime/control-schema.ts
|
|
10
10
|
import { z } from "zod";
|
|
@@ -82,7 +82,13 @@ var AgentMultiSessionCursorSchema = z.object({
|
|
|
82
82
|
}).strict())
|
|
83
83
|
}).strict();
|
|
84
84
|
function durable(event) {
|
|
85
|
-
return [
|
|
85
|
+
return [
|
|
86
|
+
"admission",
|
|
87
|
+
"assistant-checkpoint",
|
|
88
|
+
"run-state",
|
|
89
|
+
"run-operation",
|
|
90
|
+
"terminal"
|
|
91
|
+
].includes(event.type);
|
|
86
92
|
}
|
|
87
93
|
function advanceAgentMultiSessionCursor(raw, event) {
|
|
88
94
|
const cursor = AgentMultiSessionCursorSchema.parse(raw);
|
|
@@ -5,12 +5,13 @@ import {
|
|
|
5
5
|
AgentMessageSchema,
|
|
6
6
|
AgentRecordIdSchema,
|
|
7
7
|
AgentRecordVersionSchema,
|
|
8
|
+
AgentRunOperationSchema,
|
|
8
9
|
AgentRunSchema,
|
|
9
10
|
AgentSnapshotSchema,
|
|
10
11
|
AgentTerminalReasonSchema,
|
|
11
12
|
AgentUsageSchema,
|
|
12
13
|
runStateForTerminalReason
|
|
13
|
-
} from "./index-
|
|
14
|
+
} from "./index-x15ss2dx.js";
|
|
14
15
|
|
|
15
16
|
// src/agent-runtime/conversations.ts
|
|
16
17
|
import { z } from "zod";
|
|
@@ -114,6 +115,14 @@ var CheckpointRunAssistantSchema = z3.object({
|
|
|
114
115
|
assistant: AgentMessageSchema,
|
|
115
116
|
usage: AgentUsageSchema.optional()
|
|
116
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
|
+
});
|
|
117
126
|
var CommitRunTerminalSchema = z3.object({
|
|
118
127
|
conversationId: AgentRecordIdSchema,
|
|
119
128
|
runId: AgentRecordIdSchema,
|
|
@@ -437,6 +446,19 @@ function reduceStore(current, operation) {
|
|
|
437
446
|
historyMutations: [{ type: "upsert-assistant", message: input.assistant }]
|
|
438
447
|
});
|
|
439
448
|
}
|
|
449
|
+
if (operation.type === "operation" && run) {
|
|
450
|
+
const input = operation.input;
|
|
451
|
+
if (run.revision !== input.expectedRevision || run.state !== "running" && run.state !== "interrupt_requested" || run.ownerId !== input.ownerId || input.fencingToken !== undefined && run.fencingToken !== input.fencingToken) {
|
|
452
|
+
return conflict(run.revision);
|
|
453
|
+
}
|
|
454
|
+
const next = AgentRunSchema.parse({
|
|
455
|
+
...run,
|
|
456
|
+
lastOperation: input.operation,
|
|
457
|
+
revision: run.revision + 1,
|
|
458
|
+
updatedAt: new Date().toISOString()
|
|
459
|
+
});
|
|
460
|
+
return applied(current, { runs: replaceRun(current.runs, next) }, { runRecords: [AgentStoredRunSchema.parse({ schemaVersion: 1, run: next })] });
|
|
461
|
+
}
|
|
440
462
|
if (operation.type === "interrupt" && run) {
|
|
441
463
|
if (run.revision !== operation.input.expectedRevision || run.state !== "running") {
|
|
442
464
|
return conflict(run.revision);
|
|
@@ -794,6 +816,10 @@ function createAgentRuntimeStore(driver) {
|
|
|
794
816
|
type: "checkpoint",
|
|
795
817
|
input: CheckpointRunAssistantSchema.parse(input)
|
|
796
818
|
}),
|
|
819
|
+
recordRunOperation: (input) => mutate({
|
|
820
|
+
type: "operation",
|
|
821
|
+
input: RecordRunOperationSchema.parse(input)
|
|
822
|
+
}),
|
|
797
823
|
requestRunInterrupt: (input) => mutate({
|
|
798
824
|
type: "interrupt",
|
|
799
825
|
input: RequestRunInterruptSchema.parse(input)
|
|
@@ -988,4 +1014,4 @@ function createMemoryAgentRuntimeStore() {
|
|
|
988
1014
|
return createAgentRuntimeStore(driver);
|
|
989
1015
|
}
|
|
990
1016
|
|
|
991
|
-
export { AgentConversationSummarySchema, AgentConversationPageSchema, AgentConversationMessagePageSchema, AgentConversationPurgeInputSchema, AgentConversationPurgeResultSchema, AgentConversationPurgedError, purgeAgentConversation, AgentStoreConflictSchema, AgentStoreNotFoundSchema, AgentStoreAppliedSchema, AgentStoreDuplicateSchema, AgentStoreMutationResultSchema, AgentRunViewSchema, AcceptInputAndAssignRunSchema, AcquireAgentRunSchema, CheckpointRunAssistantSchema, CommitRunTerminalSchema, RequestRunInterruptSchema, RecoverAgentRunSchema, ReplaceCompactedRangeSchema, AgentRecoverableDescriptorSchema, AgentRecoverablePageSchema, AgentRuntimeHeadSchema, AgentStoredRunSchema, AgentAdmissionReceiptSchema, AgentHistoryMutationSchema, ACTIVE_AGENT_RUN_STATES, createAgentRuntimeStore, createMemoryAgentRuntimeStore };
|
|
1017
|
+
export { AgentConversationSummarySchema, AgentConversationPageSchema, AgentConversationMessagePageSchema, AgentConversationPurgeInputSchema, AgentConversationPurgeResultSchema, AgentConversationPurgedError, purgeAgentConversation, AgentStoreConflictSchema, AgentStoreNotFoundSchema, AgentStoreAppliedSchema, AgentStoreDuplicateSchema, AgentStoreMutationResultSchema, AgentRunViewSchema, AcceptInputAndAssignRunSchema, AcquireAgentRunSchema, CheckpointRunAssistantSchema, RecordRunOperationSchema, CommitRunTerminalSchema, RequestRunInterruptSchema, RecoverAgentRunSchema, ReplaceCompactedRangeSchema, AgentRecoverableDescriptorSchema, AgentRecoverablePageSchema, AgentRuntimeHeadSchema, AgentStoredRunSchema, AgentAdmissionReceiptSchema, AgentHistoryMutationSchema, ACTIVE_AGENT_RUN_STATES, createAgentRuntimeStore, createMemoryAgentRuntimeStore };
|
|
@@ -125,6 +125,54 @@ var AgentRunStateSchema = z.enum([
|
|
|
125
125
|
"abandoned"
|
|
126
126
|
]);
|
|
127
127
|
var AgentRunQueuePrioritySchema = z.enum(["interrupt-next"]);
|
|
128
|
+
var AgentRunOperationKindSchema = z.enum(["model-request", "compaction"]);
|
|
129
|
+
var AgentRunOperationPhaseSchema = z.enum([
|
|
130
|
+
"started",
|
|
131
|
+
"first-output",
|
|
132
|
+
"completed",
|
|
133
|
+
"failed",
|
|
134
|
+
"cancelled"
|
|
135
|
+
]);
|
|
136
|
+
var AgentRunOperationFieldsSchema = z.object({
|
|
137
|
+
operationId: AgentRecordIdSchema,
|
|
138
|
+
kind: AgentRunOperationKindSchema,
|
|
139
|
+
phase: AgentRunOperationPhaseSchema,
|
|
140
|
+
step: z.int().nonnegative().optional(),
|
|
141
|
+
startedAt: AgentTimestampSchema,
|
|
142
|
+
firstOutputAt: AgentTimestampSchema.optional(),
|
|
143
|
+
finishedAt: AgentTimestampSchema.optional()
|
|
144
|
+
});
|
|
145
|
+
var AgentRunOperationSchema = AgentRunOperationFieldsSchema.superRefine((operation, ctx) => {
|
|
146
|
+
if (operation.kind === "model-request" !== (operation.step !== undefined)) {
|
|
147
|
+
ctx.addIssue({
|
|
148
|
+
code: "custom",
|
|
149
|
+
path: ["step"],
|
|
150
|
+
message: "Only a model request has a step identity"
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (operation.kind === "compaction" && operation.phase === "first-output") {
|
|
154
|
+
ctx.addIssue({
|
|
155
|
+
code: "custom",
|
|
156
|
+
path: ["phase"],
|
|
157
|
+
message: "Compaction has no first-output phase"
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (operation.phase === "first-output" && operation.firstOutputAt === undefined || operation.phase === "started" && operation.firstOutputAt !== undefined || operation.kind === "compaction" && operation.firstOutputAt !== undefined) {
|
|
161
|
+
ctx.addIssue({
|
|
162
|
+
code: "custom",
|
|
163
|
+
path: ["firstOutputAt"],
|
|
164
|
+
message: "Only model output phases carry the observed first-output timestamp"
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
const terminal = ["completed", "failed", "cancelled"].includes(operation.phase);
|
|
168
|
+
if (terminal !== (operation.finishedAt !== undefined)) {
|
|
169
|
+
ctx.addIssue({
|
|
170
|
+
code: "custom",
|
|
171
|
+
path: ["finishedAt"],
|
|
172
|
+
message: "A terminal operation phase carries its observed finish timestamp"
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
});
|
|
128
176
|
var AgentTerminalReasonSchema = z.enum([
|
|
129
177
|
"success",
|
|
130
178
|
"policy_stop",
|
|
@@ -204,6 +252,7 @@ var AgentRunFieldsSchema = z.object({
|
|
|
204
252
|
terminalPolicyName: z.string().min(1).optional(),
|
|
205
253
|
absorbedIntoRunId: AgentRecordIdSchema.optional(),
|
|
206
254
|
usage: AgentUsageSchema.optional(),
|
|
255
|
+
lastOperation: AgentRunOperationSchema.optional(),
|
|
207
256
|
createdAt: AgentTimestampSchema,
|
|
208
257
|
updatedAt: AgentTimestampSchema
|
|
209
258
|
});
|
|
@@ -277,4 +326,4 @@ var AgentRunMetricsSchema = z.object({
|
|
|
277
326
|
ttftMs: z.number().nonnegative().optional()
|
|
278
327
|
});
|
|
279
328
|
|
|
280
|
-
export { AgentRecordIdSchema, AgentRecordVersionSchema, AgentTimestampSchema, AgentJsonObjectSchema, AgentProviderEnvelopeSchema, AgentTextPartSchema, AgentReasoningPartSchema, AgentFilePartSchema, AgentSourcePartSchema, AgentToolCallPartSchema, AgentToolResultPartSchema, AgentToolApprovalRequestPartSchema, AgentToolApprovalResponsePartSchema, AgentOpaquePartSchema, AgentControlPartSchema, AgentMessagePartSchema, AgentMessageRoleSchema, AgentMessageStatusSchema, AgentMessageSchema, AgentAssistantPlaceholderSchema, AgentRunStateSchema, AgentRunQueuePrioritySchema, AgentTerminalReasonSchema, runStateForTerminalReason, AgentProvenanceSchema, AgentUsageValueSchema, AgentCostValueSchema, AgentUsageSchema, AgentRunSchema, AgentSnapshotSchema, AgentRunMetricsSchema };
|
|
329
|
+
export { AgentRecordIdSchema, AgentRecordVersionSchema, AgentTimestampSchema, AgentJsonObjectSchema, AgentProviderEnvelopeSchema, AgentTextPartSchema, AgentReasoningPartSchema, AgentFilePartSchema, AgentSourcePartSchema, AgentToolCallPartSchema, AgentToolResultPartSchema, AgentToolApprovalRequestPartSchema, AgentToolApprovalResponsePartSchema, AgentOpaquePartSchema, AgentControlPartSchema, AgentMessagePartSchema, AgentMessageRoleSchema, AgentMessageStatusSchema, AgentMessageSchema, AgentAssistantPlaceholderSchema, AgentRunStateSchema, AgentRunQueuePrioritySchema, AgentRunOperationKindSchema, AgentRunOperationPhaseSchema, AgentRunOperationSchema, AgentTerminalReasonSchema, runStateForTerminalReason, AgentProvenanceSchema, AgentUsageValueSchema, AgentCostValueSchema, AgentUsageSchema, AgentRunSchema, AgentSnapshotSchema, AgentRunMetricsSchema };
|
package/dist/testing.js
CHANGED
|
@@ -7,7 +7,7 @@ import"./index-3z73fh2c.js";
|
|
|
7
7
|
import {
|
|
8
8
|
AgentMessageSchema,
|
|
9
9
|
AgentRunSchema
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-x15ss2dx.js";
|
|
11
11
|
import {
|
|
12
12
|
RealtimeRejectDirectionSchema,
|
|
13
13
|
RealtimeRejectFaultSchema,
|
|
@@ -450,10 +450,34 @@ async function conformanceScenario(store, conversationIds) {
|
|
|
450
450
|
if (!recoverable.items.some((item) => item.run.id === running.id)) {
|
|
451
451
|
throw new Error("A running run must appear in a recoverable scan");
|
|
452
452
|
}
|
|
453
|
+
const operation = await store.recordRunOperation({
|
|
454
|
+
conversationId,
|
|
455
|
+
runId: running.id,
|
|
456
|
+
expectedRevision: checkpointedRun.revision,
|
|
457
|
+
ownerId: "conformance-owner",
|
|
458
|
+
fencingToken: checkpointedRun.fencingToken,
|
|
459
|
+
operation: {
|
|
460
|
+
operationId: "model-call-1:0",
|
|
461
|
+
kind: "model-request",
|
|
462
|
+
phase: "first-output",
|
|
463
|
+
step: 0,
|
|
464
|
+
startedAt: "2026-08-22T00:00:01.800Z",
|
|
465
|
+
firstOutputAt: "2026-08-22T00:00:01.900Z"
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
requireOutcome(operation, "applied");
|
|
469
|
+
const operatedRun = operation.snapshot.runs.find((run) => run.id === running.id);
|
|
470
|
+
if (operatedRun?.lastOperation?.operationId !== "model-call-1:0") {
|
|
471
|
+
throw new Error("Run operation identity did not survive its durable mutation");
|
|
472
|
+
}
|
|
473
|
+
const operatedView = await store.loadRun({ conversationId, runId: running.id });
|
|
474
|
+
if (operatedView?.run.lastOperation?.startedAt !== "2026-08-22T00:00:01.800Z") {
|
|
475
|
+
throw new Error("loadRun did not retain the original operation timestamp");
|
|
476
|
+
}
|
|
453
477
|
const interrupted = await store.requestRunInterrupt({
|
|
454
478
|
conversationId,
|
|
455
479
|
runId: running.id,
|
|
456
|
-
expectedRevision:
|
|
480
|
+
expectedRevision: operatedRun.revision
|
|
457
481
|
});
|
|
458
482
|
requireOutcome(interrupted, "applied");
|
|
459
483
|
const interruptedRun = interrupted.snapshot.runs.find((run) => run.id === running.id);
|
package/llms-full.txt
CHANGED
|
@@ -63,11 +63,11 @@ own, recorded as an ADR.
|
|
|
63
63
|
| `stitchkit/tracking/server` | server (Bun or Node) | evolving | the decisions a tracking backend makes — dispositions, visit lease over an application-owned store, active intervals, presence; no database |
|
|
64
64
|
| `stitchkit/release` | browser **and** server | evolving | a page follows the release it was built for — `createReleaseMarker` on the server, `createReleaseWatcher` in the browser, the `X-Build-Id` header and a socket event between them |
|
|
65
65
|
| `stitchkit/geo` | server (Bun or Node) | evolving | managed GeoIP reader generations, last-known-good reload and the optional MaxMind adapter |
|
|
66
|
-
| `stitchkit/observability` | server | stable<br>_redefined in 1 of the
|
|
66
|
+
| `stitchkit/observability` | server | stable<br>_redefined in 1 of the 30 minors since 0.56.2, most recently 0.83.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
|
|
67
67
|
| `stitchkit/testing` | tests on Bun or Node | stable | in-process generated clients over a real Fetch handler, plus the store and managed-resource conformance kits |
|
|
68
68
|
| `stitchkit/declaration` | browser + build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
|
|
69
69
|
| `stitchkit/react` | browser + server rendering | stable | `createCursorQuery`, `createCacheBridge`, QueryClient and `ApiError` retry policy |
|
|
70
|
-
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in
|
|
70
|
+
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 16 of the 30 minors since 0.56.2, most recently 0.85.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
|
|
71
71
|
| `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
|
|
72
72
|
| `stitchkit/agent-runtime/coding-tools` | server (Bun or Node) | evolving | bounded host-authorized direct file and shell tools; a root boundary, not an OS sandbox |
|
|
73
73
|
| `stitchkit/agent-runtime/openrouter` | server | evolving | isolated OpenRouter language-model adapter |
|
|
@@ -75,7 +75,7 @@ own, recorded as an ADR.
|
|
|
75
75
|
| `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
|
|
76
76
|
| `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
|
|
77
77
|
| `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
|
|
78
|
-
| `stitchkit/application` | browser + server | evolving<br>_redefined in 7 of the
|
|
78
|
+
| `stitchkit/application` | browser + server | evolving<br>_redefined in 7 of the 30 minors since 0.56.2, most recently 0.83.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
|
|
79
79
|
| `stitchkit/application/grammy` | server | evolving | isolated grammY polling and webhook lifecycle adapters |
|
|
80
80
|
| `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
|
|
81
81
|
| `stitchkit/application/schemas` | browser + server | evolving | the application's snapshot, health and shutdown schemas alone, without the kernel |
|
|
@@ -5273,12 +5273,33 @@ transaction. Drivers without this guarantee must leave the capability absent. Se
|
|
|
5273
5273
|
while provider metadata stays inside a validated canonical envelope;
|
|
5274
5274
|
- `assistant-checkpoint` follows a successful checkpoint CAS;
|
|
5275
5275
|
- `run-state` follows durable queue/acquire/interrupt transitions;
|
|
5276
|
+
- `run-operation` follows a successful operation CAS. Its `operation` is the
|
|
5277
|
+
durable `AgentRun.lastOperation`: `model-request` or `compaction`, with
|
|
5278
|
+
`started`, `first-output`, `completed`, `failed` or `cancelled` phase and the
|
|
5279
|
+
original timestamps. Model request start means the provider call is about to
|
|
5280
|
+
enter `doStream`, not that HTTP transmission is measured. First output is a
|
|
5281
|
+
non-empty text/reasoning/tool-argument delta or complete tool call; metadata,
|
|
5282
|
+
usage, files and sources do not count;
|
|
5276
5283
|
- `tool-status` is transient lifecycle presentation with JSON-safe input on
|
|
5277
5284
|
start and output on completion. A mounted typed failure carries the same safe
|
|
5278
5285
|
`{ error, details?, _hint? }` envelope as the durable result; an unknown
|
|
5279
5286
|
internal cause remains generic and stays in local observability only;
|
|
5280
5287
|
- `terminal` follows the winning terminal CAS.
|
|
5281
5288
|
|
|
5289
|
+
`loop.checkpointEveryEvents` batches ordinary stream parts (default `20`) and
|
|
5290
|
+
does not batch live event delivery. Tool call/result/error/denial, approval
|
|
5291
|
+
request/response and step-finish boundaries force an assistant checkpoint and
|
|
5292
|
+
reset that batch. The checkpoint is awaited after the managed loop observes the
|
|
5293
|
+
normalized boundary. It does **not** promise persistence before a tool side
|
|
5294
|
+
effect: tool fencing supplies the real ownership checks around execution, while
|
|
5295
|
+
cross-crash effect idempotency stays application-owned. → ADR 0174.
|
|
5296
|
+
|
|
5297
|
+
`compaction` names invocation of the configured callback, including a
|
|
5298
|
+
`not_needed` context-budget check; it does not by itself say that history was
|
|
5299
|
+
summarized. Operation timestamps are retained wall-clock observations and may
|
|
5300
|
+
move backwards after a clock correction. Do not subtract them for duration;
|
|
5301
|
+
phase order comes from durable snapshot versions/event order.
|
|
5302
|
+
|
|
5282
5303
|
These are post-commit notifications, not a transactional outbox: a process can
|
|
5283
5304
|
crash between the database commit and `publish`. Reconnect should load canonical
|
|
5284
5305
|
state. Exactly-once external delivery remains an application-owned outbox.
|
|
@@ -11022,6 +11043,33 @@ of the range if you want a different one.
|
|
|
11022
11043
|
So upgrading is: read the `### ⚠️ Breaking changes` of every version *above* your
|
|
11023
11044
|
current one *up to* your target, and apply each snippet.
|
|
11024
11045
|
|
|
11046
|
+
## Released migration: 0.85.0
|
|
11047
|
+
|
|
11048
|
+
Only if you implement `AgentRuntimeStore` directly. Add the new durable
|
|
11049
|
+
operation mutation beside the existing run mutations:
|
|
11050
|
+
|
|
11051
|
+
```ts
|
|
11052
|
+
// before
|
|
11053
|
+
const store: AgentRuntimeStore = {
|
|
11054
|
+
checkpointRunAssistant,
|
|
11055
|
+
commitRunTerminal,
|
|
11056
|
+
// ...
|
|
11057
|
+
}
|
|
11058
|
+
|
|
11059
|
+
// after
|
|
11060
|
+
const store: AgentRuntimeStore = {
|
|
11061
|
+
checkpointRunAssistant,
|
|
11062
|
+
recordRunOperation,
|
|
11063
|
+
commitRunTerminal,
|
|
11064
|
+
// ...
|
|
11065
|
+
}
|
|
11066
|
+
```
|
|
11067
|
+
|
|
11068
|
+
It must atomically replace `AgentRun.lastOperation`, increment the run revision
|
|
11069
|
+
and conversation snapshot version, and enforce the supplied owner, fencing
|
|
11070
|
+
token and expected revision. Adapters built with `createAgentRuntimeStore`
|
|
11071
|
+
already receive the reference implementation; no driver method is added.
|
|
11072
|
+
|
|
11025
11073
|
## What your range does, and does not, do for you
|
|
11026
11074
|
|
|
11027
11075
|
A caret range (`"stitchkit": "^0.71.0"`) is a real gate: it resolves `< 0.72.0`,
|
|
@@ -15138,7 +15186,9 @@ Server-only optional application runtime. See the
|
|
|
15138
15186
|
| `AgentSessionCloseResult` | _type_ | what `close()` achieved: `settled`, or `timedOut` with `remaining` runs still in flight. Only omitting `forceTimeoutMs` guarantees nothing is in flight on return |
|
|
15139
15187
|
| `AgentHistoryProjectionOptions` | _type_ | storage-neutral file resolver, explicit unresolved-file behavior, and how an interrupted turn reaches the model (`interruptedAssistant`) |
|
|
15140
15188
|
| `createAgentToolFenceLifecycle` | function | pre-effect and post-effect run ownership fence for `mountAgent`; compose beside application idempotency for [durable operations](../guide/mcp-and-agents.md#durable-application-owned-execution) |
|
|
15141
|
-
| `AgentRuntimeEventSchema` | schema | transient stream lifecycle plus post-commit admission/checkpoint/run-state/terminal projections |
|
|
15189
|
+
| `AgentRuntimeEventSchema` | schema | transient stream lifecycle plus post-commit admission/checkpoint/run-state/run-operation/terminal projections |
|
|
15190
|
+
| `AgentRunOperationKindSchema` / `AgentRunOperationPhaseSchema` / `AgentRunOperationSchema` / `AgentRunOperation` | schemas / _type_ | latest durable model-request or compaction phase with operation/step identity and original timestamps |
|
|
15191
|
+
| `RecordRunOperationSchema` / `RecordRunOperation` | schema / _type_ | owner/fencing/revision-checked mutation of `AgentRun.lastOperation` |
|
|
15142
15192
|
| `createAgentObservability` | function | separate agent-run sink over the shared bounded observability lifecycle |
|
|
15143
15193
|
|
|
15144
15194
|
### Complete runtime inventory
|
|
@@ -15268,7 +15318,8 @@ provider and required capabilities without constructing the model; runtime `mode
|
|
|
15268
15318
|
runs before durable admission.
|
|
15269
15319
|
|
|
15270
15320
|
Delivery exports are `AgentAdmissionEventSchema`, `AgentCheckpointEventSchema`,
|
|
15271
|
-
`AgentRunStateEventSchema`, `
|
|
15321
|
+
`AgentRunStateEventSchema`, `AgentRunOperationEventSchema`, `AgentTerminalEventSchema`,
|
|
15322
|
+
`AgentTransientDeltaEventSchema`,
|
|
15272
15323
|
`AgentReasoningStartEventSchema`, `AgentReasoningDeltaEventSchema`,
|
|
15273
15324
|
`AgentReasoningEndEventSchema`, `AgentToolStatusEventSchema`, `AgentRuntimeEvent`,
|
|
15274
15325
|
`AgentRuntimeEventCursor`, `AgentRuntimeEventCursorSchema`, `AgentRuntimeCursorAdvance`,
|
package/package.json
CHANGED