stitchkit 0.85.0 → 0.85.2
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 +33 -0
- 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 +8 -1
- package/dist/agent-runtime/run-operation-lifecycle.d.ts.map +1 -1
- package/dist/agent-runtime-harness.js +1 -1
- package/dist/agent-runtime.js +1 -1
- package/dist/{index-9merfjxf.js → index-2jg7b11j.js} +103 -34
- package/llms-full.txt +9 -4
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,39 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
|
|
|
15
15
|
|
|
16
16
|
## [Unreleased]
|
|
17
17
|
|
|
18
|
+
## [0.85.2] — 2026-09-08
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **An asynchronous store no longer fails a run before the provider is
|
|
23
|
+
called.** The assistant checkpoint and the model-request admission are two
|
|
24
|
+
owned mutations of one run, written by two independent schedules — the stream
|
|
25
|
+
consumer and the SDK's model middleware — and each named the revision it read
|
|
26
|
+
before its own `await`. Where the store answered on a later tick (a worker, a
|
|
27
|
+
socket, a real database) the second write named a spent revision, the losing
|
|
28
|
+
compare-and-set threw out of `wrapStream`, and the run ended
|
|
29
|
+
`provider_failure` with zero provider calls; frequent checkpoints
|
|
30
|
+
(`checkpointEveryEvents: 1`) made it reliable. Owned mutations of a run now
|
|
31
|
+
take their turn in one per-run queue and read the revision inside that turn.
|
|
32
|
+
Independent runs are unaffected — the queue is per run — and fencing,
|
|
33
|
+
cancellation and checkpoint durability are unchanged. Proven on the packed
|
|
34
|
+
tarball by a consumer-lane fixture, not only in-repo. → ADR 0174 (amended).
|
|
35
|
+
|
|
36
|
+
## [0.85.1] — 2026-09-07
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- **A later model step cannot outrun its durable lifecycle or the previous
|
|
41
|
+
structural checkpoint.** AI SDK lifecycle callbacks deliberately suppress
|
|
42
|
+
callback failures, so the 0.85.0 request-start write could lose a revision
|
|
43
|
+
race with stream persistence while the provider request still executed. The
|
|
44
|
+
runtime now uses the callback only for concrete-model call identity; awaited
|
|
45
|
+
step preparation and model middleware record request admission before `doStream`, and every step
|
|
46
|
+
after the first waits for the prior step's structural checkpoint. A rejected
|
|
47
|
+
lifecycle write therefore prevents the provider call instead of producing an
|
|
48
|
+
unrecorded inference. Deferred-store and failed-admission tests cover both
|
|
49
|
+
sides of the guarantee. → ADR 0174 (amended).
|
|
50
|
+
|
|
18
51
|
## [0.85.0] — 2026-09-07
|
|
19
52
|
|
|
20
53
|
### ⚠️ Breaking changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-execution.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/run-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,OAAO,EACb,MAAM,IAAI,CAAC;AAMZ,OAAO,EAAE,KAAK,iBAAiB,EAAuB,MAAM,UAAU,CAAC;AAEvE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"run-execution.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/run-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,OAAO,EACb,MAAM,IAAI,CAAC;AAMZ,OAAO,EAAE,KAAK,iBAAiB,EAAuB,MAAM,UAAU,CAAC;AAEvE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAK1D,OAAO,KAAK,EAAqB,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAavE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAKL,KAAK,QAAQ,EAOd,MAAM,WAAW,CAAC;AAuCnB,8DAA8D;AAC9D,MAAM,WAAW,uBAAuB,CAAC,OAAO,EAAE,KAAK,SAAS,OAAO;IACrE,MAAM,EAAE,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC3C,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,IAAI,MAAM,CAAC;IACrB,GAAG,IAAI,IAAI,CAAC;IACZ,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,sBAAsB,CAAC;CACpC;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,KAAK,SAAS,OAAO,EAC9D,YAAY,EAAE,uBAAuB,CAAC,OAAO,EAAE,KAAK,CAAC,WAcb;IACtC,WAAW,EAAE,QAAQ,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,UAAU,CAAC,IAAI,IAAI,CAAC;CACrB,KAAG,OAAO,CAAC,kBAAkB,CAAC,CA8iChC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owned mutations of one run, applied one at a time.
|
|
3
|
+
*
|
|
4
|
+
* Every owned mutation is a compare-and-set against the run's current revision,
|
|
5
|
+
* and the revision it must name is the one the previous mutation produced.
|
|
6
|
+
* Reading that revision and writing it back are therefore safe apart only while
|
|
7
|
+
* nothing else can write in between — which stops being true the moment a store
|
|
8
|
+
* returns a promise that yields. With an asynchronous store the assistant
|
|
9
|
+
* checkpoint and the model-request admission both name the revision they read
|
|
10
|
+
* before their own `await`, the later write is rejected as a conflict, and the
|
|
11
|
+
* run fails without the provider ever having been called.
|
|
12
|
+
*
|
|
13
|
+
* The terminal commit answers the same hazard with a bounded retry, which suits
|
|
14
|
+
* it: committing a terminal twice is a duplicate the store recognises. It does
|
|
15
|
+
* not suit these two — a retried operation write would publish a second
|
|
16
|
+
* lifecycle event for one provider call — so they take their turn instead.
|
|
17
|
+
*/
|
|
18
|
+
export type RunMutationQueue = <T>(mutation: () => Promise<T>) => Promise<T>;
|
|
19
|
+
/** A queue of owned mutations for one run. */
|
|
20
|
+
export declare function createRunMutationQueue(): RunMutationQueue;
|
|
21
|
+
//# sourceMappingURL=run-mutation-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-mutation-queue.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/run-mutation-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAE7E,8CAA8C;AAC9C,wBAAgB,sBAAsB,IAAI,gBAAgB,CAgBzD"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { type LanguageModel } from 'ai';
|
|
1
2
|
import type { AgentRuntimeEvent } from './event-schema.js';
|
|
3
|
+
import type { RunMutationQueue } from './run-mutation-queue.js';
|
|
2
4
|
import { type AgentRun, type AgentSnapshot } from './schemas.js';
|
|
3
5
|
import type { AgentRuntimeStore } from './store.js';
|
|
4
6
|
type TerminalOperationPhase = 'completed' | 'failed' | 'cancelled';
|
|
@@ -9,11 +11,16 @@ export interface AgentRunOperationLifecycleConfig {
|
|
|
9
11
|
acceptSnapshot(snapshot: AgentSnapshot): void;
|
|
10
12
|
publish(event: AgentRuntimeEvent): Promise<void>;
|
|
11
13
|
now(): Date;
|
|
14
|
+
/** The order every owned mutation of this run takes its turn in. */
|
|
15
|
+
serialize: RunMutationQueue;
|
|
12
16
|
}
|
|
13
17
|
/** One durable latest-operation state machine for an executing run. */
|
|
14
18
|
export declare function createAgentRunOperationLifecycle(config: AgentRunOperationLifecycleConfig): {
|
|
19
|
+
noteProviderCall(callId: string): void;
|
|
20
|
+
prepareModel(model: LanguageModel, step: number, fallbackCallId: string): Promise<LanguageModel>;
|
|
21
|
+
checkpointStep(step: number): void;
|
|
22
|
+
failStepCheckpoints(error: unknown): void;
|
|
15
23
|
startCompaction(operationId: string): Promise<void>;
|
|
16
|
-
startModelRequest(providerCallId: string, step: number): Promise<void>;
|
|
17
24
|
firstOutput(): Promise<void>;
|
|
18
25
|
finish(phase: TerminalOperationPhase): Promise<void>;
|
|
19
26
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-operation-lifecycle.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/run-operation-lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"run-operation-lifecycle.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/run-operation-lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAqB,MAAM,IAAI,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EACL,KAAK,QAAQ,EAGb,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAGjD,KAAK,sBAAsB,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEnE,MAAM,WAAW,gCAAgC;IAC/C,KAAK,EAAE,iBAAiB,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,IAAI,QAAQ,CAAC;IACvB,cAAc,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAC9C,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,GAAG,IAAI,IAAI,CAAC;IACZ,oEAAoE;IACpE,SAAS,EAAE,gBAAgB,CAAC;CAC7B;AAED,uEAAuE;AACvE,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,gCAAgC;IA+CrF,gBAAgB,SAAS,MAAM,GAAG,IAAI;IAGhC,YAAY,QACT,aAAa,QACd,MAAM,kBACI,MAAM,GACrB,OAAO,CAAC,aAAa,CAAC;IAgCzB,cAAc,OAAO,MAAM,GAAG,IAAI;IAQlC,mBAAmB,QAAQ,OAAO,GAAG,IAAI;IAIzC,eAAe,cAAc,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnD,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B,MAAM,QAAQ,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;EAavD"}
|
package/dist/agent-runtime.js
CHANGED
|
@@ -934,6 +934,23 @@ function repairedSearchCall(toolCall, searchName) {
|
|
|
934
934
|
};
|
|
935
935
|
}
|
|
936
936
|
|
|
937
|
+
// src/agent-runtime/run-mutation-queue.ts
|
|
938
|
+
function createRunMutationQueue() {
|
|
939
|
+
let tail = Promise.resolve();
|
|
940
|
+
return (mutation) => {
|
|
941
|
+
const result = tail.then(mutation, mutation);
|
|
942
|
+
tail = result.then(() => {
|
|
943
|
+
return;
|
|
944
|
+
}, () => {
|
|
945
|
+
return;
|
|
946
|
+
});
|
|
947
|
+
return result;
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
// src/agent-runtime/run-operation-lifecycle.ts
|
|
952
|
+
import { wrapLanguageModel } from "ai";
|
|
953
|
+
|
|
937
954
|
// src/agent-runtime/runtime-internals.ts
|
|
938
955
|
import { z as z2 } from "zod";
|
|
939
956
|
function findRun(runs, runId) {
|
|
@@ -1078,7 +1095,10 @@ function createIdleDeadline(parent, timeoutMs) {
|
|
|
1078
1095
|
// src/agent-runtime/run-operation-lifecycle.ts
|
|
1079
1096
|
function createAgentRunOperationLifecycle(config) {
|
|
1080
1097
|
let active;
|
|
1081
|
-
|
|
1098
|
+
let providerCallId;
|
|
1099
|
+
let checkpointedStep = -1;
|
|
1100
|
+
const checkpointWaiters = new Map;
|
|
1101
|
+
const record = (operation) => config.serialize(async () => {
|
|
1082
1102
|
const current = config.currentRun();
|
|
1083
1103
|
const snapshot = appliedSnapshot(await config.store.recordRunOperation({
|
|
1084
1104
|
conversationId: current.conversationId,
|
|
@@ -1100,8 +1120,58 @@ function createAgentRunOperationLifecycle(config) {
|
|
|
1100
1120
|
operation,
|
|
1101
1121
|
emittedAt: config.now().toISOString()
|
|
1102
1122
|
});
|
|
1103
|
-
};
|
|
1123
|
+
});
|
|
1124
|
+
const startModelRequest = (callId, step) => record(AgentRunOperationSchema.parse({
|
|
1125
|
+
operationId: `${callId}:${step}`,
|
|
1126
|
+
kind: "model-request",
|
|
1127
|
+
phase: "started",
|
|
1128
|
+
step,
|
|
1129
|
+
startedAt: config.now().toISOString()
|
|
1130
|
+
}));
|
|
1104
1131
|
return {
|
|
1132
|
+
noteProviderCall(callId) {
|
|
1133
|
+
providerCallId = callId;
|
|
1134
|
+
},
|
|
1135
|
+
async prepareModel(model, step, fallbackCallId) {
|
|
1136
|
+
if (step > checkpointedStep + 1) {
|
|
1137
|
+
const waiter = checkpointWaiters.get(step - 1) ?? Promise.withResolvers();
|
|
1138
|
+
checkpointWaiters.set(step - 1, waiter);
|
|
1139
|
+
await waiter.promise;
|
|
1140
|
+
}
|
|
1141
|
+
if (typeof model === "string") {
|
|
1142
|
+
await startModelRequest(fallbackCallId, step);
|
|
1143
|
+
return model;
|
|
1144
|
+
}
|
|
1145
|
+
return wrapLanguageModel({
|
|
1146
|
+
model,
|
|
1147
|
+
middleware: {
|
|
1148
|
+
specificationVersion: "v4",
|
|
1149
|
+
wrapStream: async ({ doStream }) => {
|
|
1150
|
+
const callId = providerCallId;
|
|
1151
|
+
providerCallId = undefined;
|
|
1152
|
+
if (!callId) {
|
|
1153
|
+
throw new Error("AgentRuntime model call reached the provider without lifecycle identity");
|
|
1154
|
+
}
|
|
1155
|
+
await startModelRequest(callId, step);
|
|
1156
|
+
return doStream();
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
});
|
|
1160
|
+
},
|
|
1161
|
+
checkpointStep(step) {
|
|
1162
|
+
checkpointedStep = Math.max(checkpointedStep, step);
|
|
1163
|
+
for (const [waitingFor, waiter] of checkpointWaiters) {
|
|
1164
|
+
if (waitingFor > checkpointedStep)
|
|
1165
|
+
continue;
|
|
1166
|
+
checkpointWaiters.delete(waitingFor);
|
|
1167
|
+
waiter.resolve();
|
|
1168
|
+
}
|
|
1169
|
+
},
|
|
1170
|
+
failStepCheckpoints(error) {
|
|
1171
|
+
for (const waiter of checkpointWaiters.values())
|
|
1172
|
+
waiter.reject(error);
|
|
1173
|
+
checkpointWaiters.clear();
|
|
1174
|
+
},
|
|
1105
1175
|
startCompaction(operationId) {
|
|
1106
1176
|
return record(AgentRunOperationSchema.parse({
|
|
1107
1177
|
operationId,
|
|
@@ -1110,15 +1180,6 @@ function createAgentRunOperationLifecycle(config) {
|
|
|
1110
1180
|
startedAt: config.now().toISOString()
|
|
1111
1181
|
}));
|
|
1112
1182
|
},
|
|
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
1183
|
firstOutput() {
|
|
1123
1184
|
if (active?.kind !== "model-request" || active.phase !== "started") {
|
|
1124
1185
|
return Promise.resolve();
|
|
@@ -1267,9 +1328,11 @@ function createRunExecutor(dependencies) {
|
|
|
1267
1328
|
let terminalPolicyName;
|
|
1268
1329
|
const idleDeadline = createIdleDeadline(input.signal, idleTimeoutMs);
|
|
1269
1330
|
const executionSignal = idleDeadline.signal;
|
|
1331
|
+
const serialize = createRunMutationQueue();
|
|
1270
1332
|
const operationLifecycle = createAgentRunOperationLifecycle({
|
|
1271
1333
|
store: config.store,
|
|
1272
1334
|
runtimeEpoch,
|
|
1335
|
+
serialize,
|
|
1273
1336
|
currentRun: () => run,
|
|
1274
1337
|
acceptSnapshot: (next) => {
|
|
1275
1338
|
snapshot = next;
|
|
@@ -1300,7 +1363,7 @@ function createRunExecutor(dependencies) {
|
|
|
1300
1363
|
...provider && { provider }
|
|
1301
1364
|
}));
|
|
1302
1365
|
};
|
|
1303
|
-
const checkpoint = async () => {
|
|
1366
|
+
const checkpoint = () => serialize(async () => {
|
|
1304
1367
|
assistant = AgentMessageSchema.parse({
|
|
1305
1368
|
...assistant,
|
|
1306
1369
|
parts,
|
|
@@ -1333,7 +1396,7 @@ function createRunExecutor(dependencies) {
|
|
|
1333
1396
|
metrics: checkpointMetrics,
|
|
1334
1397
|
emittedAt: now().toISOString()
|
|
1335
1398
|
});
|
|
1336
|
-
};
|
|
1399
|
+
});
|
|
1337
1400
|
try {
|
|
1338
1401
|
if (config.history?.compact) {
|
|
1339
1402
|
await operationLifecycle.startCompaction(generateId());
|
|
@@ -1506,16 +1569,17 @@ function createRunExecutor(dependencies) {
|
|
|
1506
1569
|
}
|
|
1507
1570
|
return messages;
|
|
1508
1571
|
};
|
|
1572
|
+
const fallbackModel = selectedModel.model;
|
|
1509
1573
|
const result = streamAgentTextBoundary({
|
|
1510
|
-
model:
|
|
1574
|
+
model: fallbackModel,
|
|
1511
1575
|
tools,
|
|
1512
1576
|
instructions: withCarriedSystem(prompt.instructions),
|
|
1513
1577
|
messages: history,
|
|
1514
1578
|
abortSignal: executionSignal,
|
|
1515
1579
|
maxRetries: 0,
|
|
1516
1580
|
stopWhen: stopConditions,
|
|
1517
|
-
onLanguageModelCallStart:
|
|
1518
|
-
|
|
1581
|
+
onLanguageModelCallStart: (event) => {
|
|
1582
|
+
operationLifecycle.noteProviderCall(event.callId);
|
|
1519
1583
|
},
|
|
1520
1584
|
repairToolCall: deferredToolRepair(config.loop?.prepareStep),
|
|
1521
1585
|
...config.loop?.toolApproval && {
|
|
@@ -1525,25 +1589,27 @@ function createRunExecutor(dependencies) {
|
|
|
1525
1589
|
...config.loop?.toolApprovalSecret && {
|
|
1526
1590
|
experimental_toolApprovalSecret: config.loop.toolApprovalSecret
|
|
1527
1591
|
},
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
})?.inputTokens ?? normalizeSdkUsage(previousStep.usage).inputTokens;
|
|
1536
|
-
}
|
|
1537
|
-
const prepared = await config.loop?.prepareStep?.({
|
|
1538
|
-
...options,
|
|
1539
|
-
...runtimeContext
|
|
1540
|
-
});
|
|
1541
|
-
const injected = await takeInjectedMessages();
|
|
1542
|
-
if (injected.length === 0)
|
|
1543
|
-
return prepared;
|
|
1544
|
-
const base = prepared?.messages ?? options.messages;
|
|
1545
|
-
return { ...prepared, messages: [...base, ...injected] };
|
|
1592
|
+
prepareStep: async (options) => {
|
|
1593
|
+
const previousStep = options.steps.at(-1);
|
|
1594
|
+
if (previousStep) {
|
|
1595
|
+
lastPromptTokens = selectedModel?.normalizeUsage?.({
|
|
1596
|
+
usage: previousStep.usage,
|
|
1597
|
+
providerMetadata: previousStep.providerMetadata
|
|
1598
|
+
})?.inputTokens ?? normalizeSdkUsage(previousStep.usage).inputTokens;
|
|
1546
1599
|
}
|
|
1600
|
+
const prepared = await config.loop?.prepareStep?.({
|
|
1601
|
+
...options,
|
|
1602
|
+
...runtimeContext
|
|
1603
|
+
});
|
|
1604
|
+
const injected = await takeInjectedMessages();
|
|
1605
|
+
const preparedStep = injected.length === 0 ? prepared : {
|
|
1606
|
+
...prepared,
|
|
1607
|
+
messages: [...prepared?.messages ?? options.messages, ...injected]
|
|
1608
|
+
};
|
|
1609
|
+
return {
|
|
1610
|
+
...preparedStep,
|
|
1611
|
+
model: await operationLifecycle.prepareModel(preparedStep?.model ?? fallbackModel, options.stepNumber, generateId())
|
|
1612
|
+
};
|
|
1547
1613
|
}
|
|
1548
1614
|
});
|
|
1549
1615
|
for await (const part of result.stream) {
|
|
@@ -1819,6 +1885,8 @@ function createRunExecutor(dependencies) {
|
|
|
1819
1885
|
if (structuralBoundary || eventsSinceCheckpoint >= checkpointEveryEvents) {
|
|
1820
1886
|
await checkpoint();
|
|
1821
1887
|
eventsSinceCheckpoint = 0;
|
|
1888
|
+
if (part.type === "finish-step")
|
|
1889
|
+
operationLifecycle.checkpointStep(step - 1);
|
|
1822
1890
|
}
|
|
1823
1891
|
}
|
|
1824
1892
|
await operationLifecycle.finish(executionSignal.aborted ? "cancelled" : terminalReason === "provider_failure" ? "failed" : "completed");
|
|
@@ -1844,6 +1912,7 @@ function createRunExecutor(dependencies) {
|
|
|
1844
1912
|
}
|
|
1845
1913
|
}
|
|
1846
1914
|
} catch (error) {
|
|
1915
|
+
operationLifecycle.failStepCheckpoints(error);
|
|
1847
1916
|
internalCause = error;
|
|
1848
1917
|
const latest = await config.store.loadRun({
|
|
1849
1918
|
conversationId: run.conversationId,
|
package/llms-full.txt
CHANGED
|
@@ -5276,8 +5276,11 @@ transaction. Drivers without this guarantee must leave the capability absent. Se
|
|
|
5276
5276
|
- `run-operation` follows a successful operation CAS. Its `operation` is the
|
|
5277
5277
|
durable `AgentRun.lastOperation`: `model-request` or `compaction`, with
|
|
5278
5278
|
`started`, `first-output`, `completed`, `failed` or `cancelled` phase and the
|
|
5279
|
-
original timestamps.
|
|
5280
|
-
|
|
5279
|
+
original timestamps. Concrete models use SDK call identity in an awaited model
|
|
5280
|
+
middleware; global provider IDs use a runtime-generated identity during awaited
|
|
5281
|
+
step preparation. Both durably admit the request before entering `doStream`, so a failed
|
|
5282
|
+
write prevents the provider call. This does not claim HTTP transmission is
|
|
5283
|
+
measured. First output is a
|
|
5281
5284
|
non-empty text/reasoning/tool-argument delta or complete tool call; metadata,
|
|
5282
5285
|
usage, files and sources do not count;
|
|
5283
5286
|
- `tool-status` is transient lifecycle presentation with JSON-safe input on
|
|
@@ -5292,7 +5295,9 @@ request/response and step-finish boundaries force an assistant checkpoint and
|
|
|
5292
5295
|
reset that batch. The checkpoint is awaited after the managed loop observes the
|
|
5293
5296
|
normalized boundary. It does **not** promise persistence before a tool side
|
|
5294
5297
|
effect: tool fencing supplies the real ownership checks around execution, while
|
|
5295
|
-
cross-crash effect idempotency stays application-owned.
|
|
5298
|
+
cross-crash effect idempotency stays application-owned. The following model
|
|
5299
|
+
step waits for the previous step-finish checkpoint before its own durable
|
|
5300
|
+
request admission and provider invocation. → ADR 0174.
|
|
5296
5301
|
|
|
5297
5302
|
`compaction` names invocation of the configured callback, including a
|
|
5298
5303
|
`not_needed` context-budget check; it does not by itself say that history was
|
|
@@ -15187,7 +15192,7 @@ Server-only optional application runtime. See the
|
|
|
15187
15192
|
| `AgentHistoryProjectionOptions` | _type_ | storage-neutral file resolver, explicit unresolved-file behavior, and how an interrupted turn reaches the model (`interruptedAssistant`) |
|
|
15188
15193
|
| `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) |
|
|
15189
15194
|
| `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 |
|
|
15195
|
+
| `AgentRunOperationKindSchema` / `AgentRunOperationPhaseSchema` / `AgentRunOperationSchema` / `AgentRunOperation` | schemas / _type_ | latest durable model-request or compaction phase with operation/step identity and original timestamps; request admission is awaited before provider invocation |
|
|
15191
15196
|
| `RecordRunOperationSchema` / `RecordRunOperation` | schema / _type_ | owner/fencing/revision-checked mutation of `AgentRun.lastOperation` |
|
|
15192
15197
|
| `createAgentObservability` | function | separate agent-run sink over the shared bounded observability lifecycle |
|
|
15193
15198
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stitchkit",
|
|
3
|
-
"version": "0.85.
|
|
3
|
+
"version": "0.85.2",
|
|
4
4
|
"description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -285,7 +285,7 @@
|
|
|
285
285
|
"@types/json-schema": "^7.0.15",
|
|
286
286
|
"@types/react": "^19.2.18",
|
|
287
287
|
"@typescript/typescript6": "^6.0.2",
|
|
288
|
-
"ai": "^7.0.
|
|
288
|
+
"ai": "^7.0.93",
|
|
289
289
|
"fake-indexeddb": "^6.2.5",
|
|
290
290
|
"grammy": "^1.45.1",
|
|
291
291
|
"react": "^19.2.8",
|