stitchkit 0.110.3 → 0.110.4

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.
@@ -35,8 +35,11 @@ import {
35
35
  canonicalAgentJson2,
36
36
  encodeAgentConversationArchive2,
37
37
  decodeAgentConversationArchive2,
38
- assistantStatus
39
- } from "./index-4fgg1507.js";
38
+ assistantStatus,
39
+ ProviderJournalMessageSchema,
40
+ ProviderJournalRequestSchema,
41
+ ProviderJournalResponseSchema
42
+ } from "./index-jna0ejsa.js";
40
43
  import {
41
44
  StepEventPayloadSchema,
42
45
  ParkEventPayloadSchema,
@@ -170,7 +173,7 @@ function emptyHead(conversationId) {
170
173
  }
171
174
 
172
175
  // src/agent-runtime/store-create.ts
173
- import { z as z16 } from "zod";
176
+ import { z as z15 } from "zod";
174
177
 
175
178
  // src/agent-runtime/store-archive.ts
176
179
  import { z as z5 } from "zod";
@@ -992,10 +995,10 @@ async function exportConversationIn(driver, transaction, conversationId) {
992
995
 
993
996
  // src/agent-runtime/store-branch.ts
994
997
  import { createHash as createHash7 } from "node:crypto";
995
- import { z as z14 } from "zod";
998
+ import { z as z13 } from "zod";
996
999
 
997
1000
  // src/agent-runtime/branch-events.ts
998
- import { z as z10 } from "zod";
1001
+ import { z as z9 } from "zod";
999
1002
 
1000
1003
  // src/agent-runtime/branch-messages.ts
1001
1004
  import { z as z6 } from "zod";
@@ -1068,7 +1071,7 @@ function branchPart(ids, part) {
1068
1071
  return { ...part, reference: ids.reference("spill", part.reference) };
1069
1072
  case "tool-call": {
1070
1073
  if (part.provider)
1071
- throw new TypeError("Branch cannot rekey opaque tool provider metadata");
1074
+ branchOpaqueJson(part.provider.data);
1072
1075
  return {
1073
1076
  ...part,
1074
1077
  callId: ids.reference("call", part.callId),
@@ -1095,7 +1098,7 @@ function branchPart(ids, part) {
1095
1098
  throw new TypeError("Branch cannot rekey an opaque provider part");
1096
1099
  case "reasoning":
1097
1100
  if (part.provider)
1098
- throw new TypeError("Branch cannot rekey opaque reasoning provider metadata");
1101
+ branchOpaqueJson(part.provider.data);
1099
1102
  return part;
1100
1103
  default:
1101
1104
  return part;
@@ -1261,92 +1264,17 @@ var BranchObservationSchema = z7.object({ sourceKind: Id, payload: z7.json() }).
1261
1264
 
1262
1265
  // src/agent-runtime/branch-provider.ts
1263
1266
  import { createHash as createHash3 } from "node:crypto";
1264
- import { z as z8 } from "zod";
1265
- var Hash3 = z8.string().regex(/^[a-f0-9]{64}$/);
1266
- var Text = z8.object({ type: z8.enum(["text", "reasoning"]), text: z8.string() }).strict();
1267
- var Call = z8.object({
1268
- type: z8.literal("tool-call"),
1269
- toolCallId: z8.string(),
1270
- toolName: z8.string(),
1271
- input: z8.json()
1272
- }).strict();
1273
- var Result = z8.object({
1274
- type: z8.literal("tool-result"),
1275
- toolCallId: z8.string(),
1276
- toolName: z8.string(),
1277
- output: z8.discriminatedUnion("type", [
1278
- z8.object({ type: z8.enum(["text", "error-text"]), value: z8.string() }).strict(),
1279
- z8.object({ type: z8.enum(["json", "error-json"]), value: z8.json() }).strict()
1280
- ])
1281
- }).strict();
1282
- var Message = z8.object({
1283
- role: z8.enum(["user", "assistant", "tool"]),
1284
- content: z8.union([
1285
- z8.string(),
1286
- z8.array(z8.union([
1287
- Text,
1288
- Call,
1289
- Result,
1290
- z8.object({
1291
- type: z8.literal("tool-approval-request"),
1292
- approvalId: z8.string(),
1293
- toolCallId: z8.string(),
1294
- signature: z8.string().optional(),
1295
- isAutomatic: z8.boolean().optional()
1296
- }).strict(),
1297
- z8.object({
1298
- type: z8.literal("tool-approval-response"),
1299
- approvalId: z8.string(),
1300
- approved: z8.boolean(),
1301
- reason: z8.string().optional()
1302
- }).strict(),
1303
- z8.object({
1304
- type: z8.literal("file"),
1305
- data: z8.union([
1306
- z8.string(),
1307
- z8.object({
1308
- binary: z8.literal(true),
1309
- sha256: Hash3,
1310
- bytes: z8.int().nonnegative()
1311
- }).strict()
1312
- ]),
1313
- mediaType: z8.string(),
1314
- filename: z8.string().optional()
1315
- }).strict(),
1316
- z8.object({
1317
- type: z8.literal("image"),
1318
- image: z8.union([
1319
- z8.string(),
1320
- z8.object({
1321
- binary: z8.literal(true),
1322
- sha256: Hash3,
1323
- bytes: z8.int().nonnegative()
1324
- }).strict()
1325
- ]),
1326
- mediaType: z8.string().optional()
1327
- }).strict()
1328
- ]))
1329
- ])
1330
- }).strict();
1331
- var ProviderMessage = z8.object({ sha256: Hash3, message: Message }).strict();
1332
- var ProviderRequest = z8.object({
1333
- runId: z8.string(),
1334
- attempt: z8.int().nonnegative(),
1335
- stepNumber: z8.int().nonnegative(),
1336
- modelId: z8.string(),
1337
- instructionsSha256: Hash3,
1338
- messageShas: z8.array(Hash3),
1339
- bodySha256: Hash3
1340
- }).strict();
1341
- var ProviderResponse = z8.object({
1342
- runId: z8.string(),
1343
- attempt: z8.int().nonnegative(),
1344
- stepNumber: z8.int().nonnegative(),
1345
- response: z8.object({ id: z8.string(), provider: z8.string().optional() }).strict()
1346
- }).strict();
1347
1267
  function hash(value) {
1348
1268
  return createHash3("sha256").update(canonicalAgentJson2(value)).digest("hex");
1349
1269
  }
1270
+ function checkFileData(value) {
1271
+ if (value === null || typeof value !== "object" || Array.isArray(value))
1272
+ return;
1273
+ if (value.type === "reference" && "reference" in value)
1274
+ branchOpaqueJson(value.reference);
1275
+ else if (!("type" in value) && value.binary !== true)
1276
+ branchOpaqueJson(value);
1277
+ }
1350
1278
 
1351
1279
  class BranchProvider {
1352
1280
  ids;
@@ -1356,12 +1284,20 @@ class BranchProvider {
1356
1284
  }
1357
1285
  rekey(kind, raw) {
1358
1286
  if (kind === "provider/message") {
1359
- const value = ProviderMessage.parse(raw);
1287
+ const value = ProviderJournalMessageSchema.parse(raw);
1360
1288
  if (hash(value.message) !== value.sha256)
1361
1289
  throw new TypeError("Branch provider message digest is inconsistent");
1290
+ if (value.message.providerOptions)
1291
+ branchOpaqueJson(value.message.providerOptions);
1362
1292
  const message = {
1363
1293
  ...value.message,
1364
1294
  content: typeof value.message.content === "string" ? value.message.content : value.message.content.map((part) => {
1295
+ if ("providerOptions" in part && part.providerOptions)
1296
+ branchOpaqueJson(part.providerOptions);
1297
+ if (part.type === "file" || part.type === "reasoning-file")
1298
+ checkFileData(part.data);
1299
+ if (part.type === "image")
1300
+ checkFileData(part.image);
1365
1301
  if (part.type === "tool-call")
1366
1302
  return {
1367
1303
  ...part,
@@ -1369,8 +1305,21 @@ class BranchProvider {
1369
1305
  input: branchToolJson(this.ids, part.toolName, part.input, false)
1370
1306
  };
1371
1307
  if (part.type === "tool-result") {
1308
+ if ("providerOptions" in part.output && part.output.providerOptions)
1309
+ branchOpaqueJson(part.output.providerOptions);
1372
1310
  if (part.output.type === "error-json")
1373
1311
  branchOpaqueJson(part.output.value);
1312
+ if (part.output.type === "content")
1313
+ for (const item of part.output.value) {
1314
+ if (item.providerOptions)
1315
+ branchOpaqueJson(item.providerOptions);
1316
+ if (item.type === "file")
1317
+ checkFileData(item.data);
1318
+ if ("providerReference" in item)
1319
+ branchOpaqueJson(item.providerReference);
1320
+ if ("fileId" in item && typeof item.fileId !== "string")
1321
+ branchOpaqueJson(item.fileId);
1322
+ }
1374
1323
  return {
1375
1324
  ...part,
1376
1325
  toolCallId: this.ids.reference("call", part.toolCallId),
@@ -1384,7 +1333,8 @@ class BranchProvider {
1384
1333
  return {
1385
1334
  type: part.type,
1386
1335
  approvalId: this.ids.reference("approval", part.approvalId),
1387
- toolCallId: this.ids.reference("call", part.toolCallId)
1336
+ toolCallId: this.ids.reference("call", part.toolCallId),
1337
+ ...part.reason !== undefined && { reason: part.reason }
1388
1338
  };
1389
1339
  if (part.type === "tool-approval-response")
1390
1340
  return {
@@ -1399,7 +1349,7 @@ class BranchProvider {
1399
1349
  return { sha256, message };
1400
1350
  }
1401
1351
  if (kind === "provider/request") {
1402
- const value = ProviderRequest.parse(raw);
1352
+ const value = ProviderJournalRequestSchema.parse(raw);
1403
1353
  const sourceHash = createHash3("sha256").update(value.instructionsSha256).update(value.messageShas.join(",")).digest("hex");
1404
1354
  if (sourceHash !== value.bodySha256)
1405
1355
  throw new TypeError("Branch provider request digest is inconsistent");
@@ -1416,13 +1366,13 @@ class BranchProvider {
1416
1366
  bodySha256: createHash3("sha256").update(value.instructionsSha256).update(messageShas.join(",")).digest("hex")
1417
1367
  };
1418
1368
  }
1419
- const value = ProviderResponse.parse(raw);
1369
+ const value = ProviderJournalResponseSchema.parse(raw);
1420
1370
  return { ...value, runId: this.ids.reference("run", value.runId) };
1421
1371
  }
1422
1372
  }
1423
1373
 
1424
1374
  // src/agent-runtime/branch-transitions.ts
1425
- import { z as z9 } from "zod";
1375
+ import { z as z8 } from "zod";
1426
1376
  function rekeyBranchTransition(ids, source, operation) {
1427
1377
  const message = (value) => branchMessage(ids, source, value);
1428
1378
  const input = operation.input;
@@ -1493,11 +1443,11 @@ function rekeyBranchTransition(ids, source, operation) {
1493
1443
  }
1494
1444
  }
1495
1445
  function branchJson(value) {
1496
- return z9.json().parse(value);
1446
+ return z8.json().parse(value);
1497
1447
  }
1498
1448
 
1499
1449
  // src/agent-runtime/branch-events.ts
1500
- var Hash4 = z10.string().regex(/^[a-f0-9]{64}$/);
1450
+ var Hash3 = z9.string().regex(/^[a-f0-9]{64}$/);
1501
1451
  function rekeyBranchEvents(ids, source, events, retainedMessages = new Map) {
1502
1452
  const hydrated = events.map((event) => {
1503
1453
  const assistant = retainedMessages.get(event.eventId);
@@ -1544,14 +1494,14 @@ function rekeyBranchEvent(ids, source, event, provider) {
1544
1494
  if (event.kind === "runtime/transition") {
1545
1495
  const operation = branchTransition(event);
1546
1496
  const rekeyed = rekeyBranchTransition(ids, source, operation);
1547
- const raw = z10.object({
1548
- type: z10.string(),
1549
- input: z10.object({
1550
- assistant: z10.object({
1551
- sha256: Hash4.optional(),
1552
- sourceSha256: Hash4.optional(),
1553
- bytes: z10.int(),
1554
- parts: z10.int()
1497
+ const raw = z9.object({
1498
+ type: z9.string(),
1499
+ input: z9.object({
1500
+ assistant: z9.object({
1501
+ sha256: Hash3.optional(),
1502
+ sourceSha256: Hash3.optional(),
1503
+ bytes: z9.int(),
1504
+ parts: z9.int()
1555
1505
  }).passthrough()
1556
1506
  }).passthrough()
1557
1507
  }).passthrough().safeParse(event.payload);
@@ -1709,32 +1659,32 @@ class BranchIdentities {
1709
1659
 
1710
1660
  // src/agent-runtime/branch-source.ts
1711
1661
  import { createHash as createHash6 } from "node:crypto";
1712
- import { z as z13 } from "zod";
1662
+ import { z as z12 } from "zod";
1713
1663
 
1714
1664
  // src/agent-runtime/archive-projection.ts
1715
- import { z as z11 } from "zod";
1716
- var ArchiveProjectionSchema = z11.object({
1717
- name: z11.string(),
1718
- version: z11.int().positive(),
1719
- uptoSeq: z11.int().nonnegative(),
1720
- value: z11.json(),
1721
- updatedAt: z11.string()
1665
+ import { z as z10 } from "zod";
1666
+ var ArchiveProjectionSchema = z10.object({
1667
+ name: z10.string(),
1668
+ version: z10.int().positive(),
1669
+ uptoSeq: z10.int().nonnegative(),
1670
+ value: z10.json(),
1671
+ updatedAt: z10.string()
1722
1672
  }).strict();
1723
1673
 
1724
1674
  // src/agent-runtime/archive-spill.ts
1725
1675
  import { createHash as createHash5 } from "node:crypto";
1726
- import { z as z12 } from "zod";
1727
- var ArchiveSpillSchema = z12.object({
1728
- reference: z12.string().min(1),
1729
- runId: z12.string().min(1).optional(),
1730
- toolCallId: z12.string().min(1).optional(),
1731
- mediaType: z12.string().min(1),
1732
- bytes: z12.int().nonnegative(),
1733
- sha256: z12.string().regex(/^[a-f0-9]{64}$/),
1734
- createdAt: z12.iso.datetime({ offset: true }),
1735
- expiresAt: z12.iso.datetime({ offset: true }).optional(),
1676
+ import { z as z11 } from "zod";
1677
+ var ArchiveSpillSchema = z11.object({
1678
+ reference: z11.string().min(1),
1679
+ runId: z11.string().min(1).optional(),
1680
+ toolCallId: z11.string().min(1).optional(),
1681
+ mediaType: z11.string().min(1),
1682
+ bytes: z11.int().nonnegative(),
1683
+ sha256: z11.string().regex(/^[a-f0-9]{64}$/),
1684
+ createdAt: z11.iso.datetime({ offset: true }),
1685
+ expiresAt: z11.iso.datetime({ offset: true }).optional(),
1736
1686
  authorization: AgentCodingToolAuthorizationSchema2.optional(),
1737
- base64: z12.string()
1687
+ base64: z11.string()
1738
1688
  }).strict().superRefine((spill, ctx) => {
1739
1689
  const bytes = Buffer.from(spill.base64, "base64");
1740
1690
  if (bytes.toString("base64") !== spill.base64 || bytes.byteLength !== spill.bytes || createHash5("sha256").update(bytes).digest("hex") !== spill.sha256) {
@@ -1746,7 +1696,7 @@ var ArchiveSpillSchema = z12.object({
1746
1696
  });
1747
1697
 
1748
1698
  // src/agent-runtime/branch-source.ts
1749
- var SnapshotProjection = z13.object({ archiveType: z13.literal("runtime-snapshot"), snapshot: AgentSnapshotSchema2 }).strict();
1699
+ var SnapshotProjection = z12.object({ archiveType: z12.literal("runtime-snapshot"), snapshot: AgentSnapshotSchema2 }).strict();
1750
1700
  function branchHash(value) {
1751
1701
  return createHash6("sha256").update(canonicalAgentJson2(value)).digest("hex");
1752
1702
  }
@@ -1763,13 +1713,13 @@ function boundary(events, throughRunId) {
1763
1713
  for (const event of events) {
1764
1714
  if (event.kind !== "runtime/transition")
1765
1715
  continue;
1766
- const candidate = z13.object({
1767
- type: z13.string(),
1768
- input: z13.object({
1769
- runId: z13.string().optional(),
1770
- reason: z13.string().optional(),
1771
- action: z13.string().optional(),
1772
- absorb: z13.array(z13.object({ runId: z13.string() })).optional()
1716
+ const candidate = z12.object({
1717
+ type: z12.string(),
1718
+ input: z12.object({
1719
+ runId: z12.string().optional(),
1720
+ reason: z12.string().optional(),
1721
+ action: z12.string().optional(),
1722
+ absorb: z12.array(z12.object({ runId: z12.string() })).optional()
1773
1723
  })
1774
1724
  }).safeParse(event.payload);
1775
1725
  if (!candidate.success)
@@ -1788,7 +1738,7 @@ function prepareBranchSource(bytes, source) {
1788
1738
  if (event.seq !== index + 1)
1789
1739
  throw new TypeError("Branch source event sequence is incomplete");
1790
1740
  }
1791
- const projections = archive.projections.map((value) => z13.union([SnapshotProjection, ArchiveProjectionSchema]).parse(value));
1741
+ const projections = archive.projections.map((value) => z12.union([SnapshotProjection, ArchiveProjectionSchema]).parse(value));
1792
1742
  if (projections.some((value, index) => canonicalAgentJson2(value) !== canonicalAgentJson2(archive.projections[index])))
1793
1743
  throw new TypeError("Branch archive snapshot contains an unknown opaque field");
1794
1744
  const snapshots = projections.filter((value) => ("archiveType" in value));
@@ -1958,12 +1908,12 @@ async function branchConversation(driver, raw) {
1958
1908
  conversationId: input.destinationConversationId,
1959
1909
  events: [],
1960
1910
  projections: [],
1961
- spills: z14.array(z14.json()).parse(spills)
1911
+ spills: z13.array(z13.json()).parse(spills)
1962
1912
  });
1963
1913
  await driver.events.append(tx, agentStoreEventDraft({
1964
1914
  conversationId: input.destinationConversationId,
1965
1915
  kind: "runtime/branched",
1966
- payload: z14.json().parse(receipt)
1916
+ payload: z13.json().parse(receipt)
1967
1917
  }));
1968
1918
  return { outcome: "created", receipt };
1969
1919
  });
@@ -2016,7 +1966,7 @@ function findEventOnce(driver, input) {
2016
1966
  }
2017
1967
 
2018
1968
  // src/agent-runtime/store-mutate.ts
2019
- import { z as z15 } from "zod";
1969
+ import { z as z14 } from "zod";
2020
1970
  function validateAdmissionReceipt(receipt, record, conversationId) {
2021
1971
  const input = receipt.input;
2022
1972
  const run = record.run;
@@ -2163,7 +2113,7 @@ async function persistApplied(driver, transaction, read, operation, reduced) {
2163
2113
  await driver.events.append(transaction, agentStoreEventDraft({
2164
2114
  conversationId,
2165
2115
  kind: "runtime/transition",
2166
- payload: z15.json().parse(transitionRecord(operation, reduced))
2116
+ payload: z14.json().parse(transitionRecord(operation, reduced))
2167
2117
  }));
2168
2118
  return { outcome: "applied", snapshot: reduced.snapshot };
2169
2119
  }
@@ -2212,9 +2162,9 @@ function createStoreConversationPurge(driver, conversations) {
2212
2162
  }
2213
2163
 
2214
2164
  // src/agent-runtime/store-create.ts
2215
- var AgentRecoverableScanInputSchema = z16.object({
2216
- cursor: z16.string().min(1).optional(),
2217
- limit: z16.number().int().min(1).max(1000)
2165
+ var AgentRecoverableScanInputSchema = z15.object({
2166
+ cursor: z15.string().min(1).optional(),
2167
+ limit: z15.number().int().min(1).max(1000)
2218
2168
  });
2219
2169
  function createAgentRuntimeStore2(driver) {
2220
2170
  const mutate = (operation) => mutateStore(driver, operation);
@@ -612,6 +612,12 @@ spill. Compacted content stays in the event history and SQLite inactive rows; th
612
612
  same active summaries. A hash-only checkpoint is historical digest evidence, marked
613
613
  `sourceSha256`; a later full terminal record must settle its content.
614
614
 
615
+ Recorded provider options and canonical reasoning/tool-call provider metadata are retained.
616
+ Provider message hashes and request references remain consistent after rekey. Metadata is
617
+ data, subject to the opaque JSON reference guard: an undocumented runtime reference key
618
+ refuses instead of carrying a source identity into the destination. Unknown message fields
619
+ and malformed request/message digests also refuse before any destination writes.
620
+
615
621
  A branch grants no source authority. Terminal run owners/fences and approval signatures are
616
622
  removed. State, schedules, children, retries, sandbox, approval rejection and durability facts are
617
623
  retained as inert `runtime/branch-observation` records; they cannot repopulate operational state
package/llms-full.txt CHANGED
@@ -5810,6 +5810,12 @@ spill. Compacted content stays in the event history and SQLite inactive rows; th
5810
5810
  same active summaries. A hash-only checkpoint is historical digest evidence, marked
5811
5811
  `sourceSha256`; a later full terminal record must settle its content.
5812
5812
 
5813
+ Recorded provider options and canonical reasoning/tool-call provider metadata are retained.
5814
+ Provider message hashes and request references remain consistent after rekey. Metadata is
5815
+ data, subject to the opaque JSON reference guard: an undocumented runtime reference key
5816
+ refuses instead of carrying a source identity into the destination. Unknown message fields
5817
+ and malformed request/message digests also refuse before any destination writes.
5818
+
5813
5819
  A branch grants no source authority. Terminal run owners/fences and approval signatures are
5814
5820
  removed. State, schedules, children, retries, sandbox, approval rejection and durability facts are
5815
5821
  retained as inert `runtime/branch-observation` records; they cannot repopulate operational state
package/llms.txt CHANGED
@@ -25,7 +25,7 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
25
25
  - **stitchkit/primitives**: [llms/primitives.txt](llms/primitives.txt) 11.7 KB
26
26
  - **stitchkit/server**: [llms/server.txt](llms/server.txt) 45.3 KB → [llms/server.2.txt](llms/server.2.txt) 14.6 KB → [llms/server.3.txt](llms/server.3.txt) 45.6 KB → [llms/server.4.txt](llms/server.4.txt) 38.3 KB → [llms/server.5.txt](llms/server.5.txt) 22.1 KB
27
27
  - **stitchkit/observability**: [llms/observability.txt](llms/observability.txt) 45.9 KB
28
- - **stitchkit/agent-runtime**: [llms/agent-runtime.txt](llms/agent-runtime.txt) 42.2 KB → [llms/agent-runtime.2.txt](llms/agent-runtime.2.txt) 46.7 KB → [llms/agent-runtime.3.txt](llms/agent-runtime.3.txt) 35.6 KB
28
+ - **stitchkit/agent-runtime**: [llms/agent-runtime.txt](llms/agent-runtime.txt) 42.7 KB → [llms/agent-runtime.2.txt](llms/agent-runtime.2.txt) 46.7 KB → [llms/agent-runtime.3.txt](llms/agent-runtime.3.txt) 35.6 KB
29
29
  - **stitchkit/agent-runtime/testing**: [llms/agent-runtime-testing.txt](llms/agent-runtime-testing.txt) 2.6 KB
30
30
  - **stitchkit/agent-runtime/harness**: [llms/agent-runtime-harness.txt](llms/agent-runtime-harness.txt) 11.0 KB
31
31
  - **stitchkit/agent-runtime/coding-tools**: [llms/agent-runtime-coding-tools.txt](llms/agent-runtime-coding-tools.txt) 5.0 KB
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.110.3",
3
+ "version": "0.110.4",
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",