stitchkit 0.99.0 → 0.100.1

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.
Files changed (147) hide show
  1. package/CHANGELOG.md +124 -1
  2. package/dist/agent-runtime/contained-darwin.d.ts +0 -17
  3. package/dist/agent-runtime/contained-darwin.d.ts.map +1 -1
  4. package/dist/agent-runtime/contained-write.d.ts.map +1 -1
  5. package/dist/agent-runtime/invocation-attempt.d.ts +28 -0
  6. package/dist/agent-runtime/invocation-attempt.d.ts.map +1 -0
  7. package/dist/agent-runtime/invocation-failure.d.ts +6 -0
  8. package/dist/agent-runtime/invocation-failure.d.ts.map +1 -0
  9. package/dist/agent-runtime/invocation-payload.d.ts +20 -0
  10. package/dist/agent-runtime/invocation-payload.d.ts.map +1 -0
  11. package/dist/agent-runtime/invocation-read.d.ts +131 -0
  12. package/dist/agent-runtime/invocation-read.d.ts.map +1 -0
  13. package/dist/agent-runtime/invocation-schema.d.ts +378 -0
  14. package/dist/agent-runtime/invocation-schema.d.ts.map +1 -0
  15. package/dist/agent-runtime/invocations.d.ts +52 -0
  16. package/dist/agent-runtime/invocations.d.ts.map +1 -0
  17. package/dist/agent-runtime/projections.d.ts.map +1 -1
  18. package/dist/agent-runtime/run-acquisition.d.ts.map +1 -1
  19. package/dist/agent-runtime/run-execution-state.d.ts +4 -2
  20. package/dist/agent-runtime/run-execution-state.d.ts.map +1 -1
  21. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  22. package/dist/agent-runtime/run-failure.d.ts.map +1 -1
  23. package/dist/agent-runtime/run-model-attempts.d.ts.map +1 -1
  24. package/dist/agent-runtime/run-operation-lifecycle.d.ts +2 -2
  25. package/dist/agent-runtime/run-operation-lifecycle.d.ts.map +1 -1
  26. package/dist/agent-runtime/run-provider-ledger.d.ts +1 -0
  27. package/dist/agent-runtime/run-provider-ledger.d.ts.map +1 -1
  28. package/dist/agent-runtime/runtime.d.ts +11 -0
  29. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  30. package/dist/agent-runtime/schedule-dispatch.d.ts +9 -2
  31. package/dist/agent-runtime/schedule-dispatch.d.ts.map +1 -1
  32. package/dist/agent-runtime/schedule-records.d.ts +8 -2
  33. package/dist/agent-runtime/schedule-records.d.ts.map +1 -1
  34. package/dist/agent-runtime/schedules.d.ts +5 -0
  35. package/dist/agent-runtime/schedules.d.ts.map +1 -1
  36. package/dist/agent-runtime/sqlite-events.d.ts.map +1 -1
  37. package/dist/agent-runtime/store-create.d.ts.map +1 -1
  38. package/dist/agent-runtime/store-driver-contract.d.ts +9 -0
  39. package/dist/agent-runtime/store-driver-contract.d.ts.map +1 -1
  40. package/dist/agent-runtime/store-event-once.d.ts +37 -0
  41. package/dist/agent-runtime/store-event-once.d.ts.map +1 -0
  42. package/dist/agent-runtime/store-memory.d.ts.map +1 -1
  43. package/dist/agent-runtime/store.d.ts +11 -0
  44. package/dist/agent-runtime/store.d.ts.map +1 -1
  45. package/dist/application/change-subscription.d.ts +36 -0
  46. package/dist/application/change-subscription.d.ts.map +1 -0
  47. package/dist/application/diagnostic-journal-contract.d.ts +3 -6
  48. package/dist/application/diagnostic-journal-contract.d.ts.map +1 -1
  49. package/dist/application/notification-delivery.d.ts +55 -0
  50. package/dist/application/notification-delivery.d.ts.map +1 -0
  51. package/dist/application/notification-outbox-state.d.ts +41 -0
  52. package/dist/application/notification-outbox-state.d.ts.map +1 -0
  53. package/dist/application/notification-outbox.d.ts +7 -1
  54. package/dist/application/notification-outbox.d.ts.map +1 -1
  55. package/dist/application/watch-hub-core.d.ts +14 -84
  56. package/dist/application/watch-hub-core.d.ts.map +1 -1
  57. package/dist/application/watch-hub-source.d.ts +98 -0
  58. package/dist/application/watch-hub-source.d.ts.map +1 -0
  59. package/dist/application/watch-hub.d.ts +10 -2
  60. package/dist/application/watch-hub.d.ts.map +1 -1
  61. package/dist/browser/session-credentials.d.ts +26 -0
  62. package/dist/browser/session-credentials.d.ts.map +1 -0
  63. package/dist/browser/session.d.ts +33 -0
  64. package/dist/browser/session.d.ts.map +1 -0
  65. package/dist/durability/events.d.ts +6 -0
  66. package/dist/durability/events.d.ts.map +1 -1
  67. package/dist/entrypoints/agent-runtime/coding-tools.js +3 -2
  68. package/dist/entrypoints/agent-runtime/harness.js +5 -3
  69. package/dist/entrypoints/agent-runtime/sandbox.js +3 -2
  70. package/dist/entrypoints/agent-runtime/sqlite/bun.js +3 -3
  71. package/dist/entrypoints/agent-runtime/sqlite/node.js +3 -3
  72. package/dist/entrypoints/agent-runtime/testing.js +3 -3
  73. package/dist/entrypoints/agent-runtime.d.ts +3 -0
  74. package/dist/entrypoints/agent-runtime.d.ts.map +1 -1
  75. package/dist/entrypoints/agent-runtime.js +65 -20
  76. package/dist/entrypoints/application/diagnostic-journal.js +2 -1
  77. package/dist/entrypoints/application.d.ts +3 -1
  78. package/dist/entrypoints/application.d.ts.map +1 -1
  79. package/dist/entrypoints/application.js +820 -294
  80. package/dist/entrypoints/files.js +9 -2
  81. package/dist/entrypoints/index.d.ts +2 -0
  82. package/dist/entrypoints/index.d.ts.map +1 -1
  83. package/dist/entrypoints/index.js +199 -0
  84. package/dist/entrypoints/live.js +78 -19
  85. package/dist/entrypoints/node.js +1 -1
  86. package/dist/entrypoints/react.d.ts +1 -1
  87. package/dist/entrypoints/react.d.ts.map +1 -1
  88. package/dist/entrypoints/react.js +59 -16
  89. package/dist/entrypoints/server.js +4 -4
  90. package/dist/{index-sp1tzwnb.js → index-10x2hbx0.js} +5 -2
  91. package/dist/{index-8p52kd5p.js → index-c6bxbsnc.js} +100 -14
  92. package/dist/{index-gxrt5h6v.js → index-cyktc4bp.js} +3 -0
  93. package/dist/{index-1m2thnq0.js → index-eaysmdtq.js} +11 -2
  94. package/dist/{index-jhx828hc.js → index-f4fx2tza.js} +948 -279
  95. package/dist/{index-px2gm2jp.js → index-fhwqwxe0.js} +17 -55
  96. package/dist/{index-e4hkgm5t.js → index-gw8bmyaj.js} +4 -2
  97. package/dist/{index-p3vsv1fb.js → index-hadmp193.js} +14 -5
  98. package/dist/{index-wt743f7f.js → index-k6gpggb9.js} +2 -1
  99. package/dist/index-q3pyb9n0.js +22 -0
  100. package/dist/{index-wsm5w4ee.js → index-vqr7f7v8.js} +51 -3
  101. package/dist/index-zjjyynm3.js +42 -0
  102. package/dist/internal/coalesced-task.d.ts +17 -0
  103. package/dist/internal/coalesced-task.d.ts.map +1 -0
  104. package/dist/internal/darwin-binding.d.ts +19 -0
  105. package/dist/internal/darwin-binding.d.ts.map +1 -0
  106. package/dist/internal/exclusive-lock.d.ts +20 -7
  107. package/dist/internal/exclusive-lock.d.ts.map +1 -1
  108. package/dist/internal/mutation-queue.d.ts +4 -0
  109. package/dist/internal/mutation-queue.d.ts.map +1 -0
  110. package/dist/internal/process-identity.d.ts +1 -1
  111. package/dist/internal/process-identity.d.ts.map +1 -1
  112. package/dist/internal/process-instance.d.ts +26 -0
  113. package/dist/internal/process-instance.d.ts.map +1 -0
  114. package/dist/internal/with-exclusive-lock.d.ts.map +1 -1
  115. package/dist/live/watch-client-state.d.ts +71 -0
  116. package/dist/live/watch-client-state.d.ts.map +1 -0
  117. package/dist/live/watch-client.d.ts +5 -1
  118. package/dist/live/watch-client.d.ts.map +1 -1
  119. package/dist/live/watch-contract.d.ts +12 -0
  120. package/dist/live/watch-contract.d.ts.map +1 -1
  121. package/dist/react/cache-bridge.d.ts +10 -0
  122. package/dist/react/cache-bridge.d.ts.map +1 -1
  123. package/dist/server/realtime.d.ts.map +1 -1
  124. package/llms/agent-runtime.2.txt +102 -0
  125. package/llms/agent-runtime.3.txt +30 -1
  126. package/llms/agent-runtime.txt +8 -3
  127. package/llms/application.2.txt +84 -2
  128. package/llms/application.txt +32 -2
  129. package/llms/files.txt +1 -1
  130. package/llms/live.txt +8 -0
  131. package/llms/react.txt +8 -0
  132. package/llms/server.3.txt +57 -0
  133. package/llms/stitchkit.2.txt +41 -0
  134. package/llms/stitchkit.3.txt +26 -0
  135. package/llms/stitchkit.txt +3 -3
  136. package/llms/upgrading-0.37.0.txt +176 -0
  137. package/llms/{upgrading-0.37.0-0.58.0.txt → upgrading-0.44.0-0.60.0.txt} +229 -169
  138. package/llms/{upgrading-0.59.0-0.71.0.txt → upgrading-0.61.0-0.73.0.txt} +122 -229
  139. package/llms/{upgrading-0.72.0-0.99.0.txt → upgrading-0.74.0-0.100.0.txt} +80 -123
  140. package/llms/upgrading.txt +4 -3
  141. package/llms-full.txt +471 -11
  142. package/llms.txt +10 -9
  143. package/native/darwin-arm64.node +0 -0
  144. package/native/darwin-x64.node +0 -0
  145. package/package.json +1 -1
  146. package/dist/agent-runtime/run-mutation-queue.d.ts +0 -21
  147. package/dist/agent-runtime/run-mutation-queue.d.ts.map +0 -1
@@ -1,21 +1,17 @@
1
+ import {
2
+ loadDarwinBinding
3
+ } from "./index-zjjyynm3.js";
4
+
1
5
  // src/agent-runtime/contained-scan.ts
2
- import path3 from "node:path";
6
+ import path2 from "node:path";
3
7
 
4
8
  // src/agent-runtime/contained-files.ts
5
9
  import { constants } from "node:fs";
6
10
  import { lstat, mkdir, open, readdir, realpath } from "node:fs/promises";
7
- import path2 from "node:path";
11
+ import path from "node:path";
8
12
 
9
13
  // src/agent-runtime/contained-darwin.ts
10
- import {
11
- close as closeDescriptor,
12
- existsSync,
13
- fstat,
14
- read as readDescriptor
15
- } from "node:fs";
16
- import { createRequire } from "node:module";
17
- import path from "node:path";
18
- import { fileURLToPath } from "node:url";
14
+ import { close as closeDescriptor, fstat, read as readDescriptor } from "node:fs";
19
15
  var FILE_TYPE_MASK = 61440;
20
16
  var FILE_TYPE_DIRECTORY = 16384;
21
17
  var FILE_TYPE_REGULAR = 32768;
@@ -23,40 +19,6 @@ var FILE_TYPE_SYMLINK = 40960;
23
19
  function modeIs(mode, type) {
24
20
  return (mode & FILE_TYPE_MASK) === type;
25
21
  }
26
- function hasFunctions(value, names) {
27
- return typeof value === "object" && value !== null && names.every((name) => typeof Reflect.get(value, name) === "function");
28
- }
29
- var darwinBinding;
30
- function loadDarwinBinding() {
31
- if (darwinBinding)
32
- return darwinBinding;
33
- const directory = path.dirname(fileURLToPath(import.meta.url));
34
- const binary = `darwin-${process.arch}.node`;
35
- const candidates = [
36
- path.resolve(directory, "../native", binary),
37
- path.resolve(directory, "../../native", binary)
38
- ];
39
- const selected = candidates.find((candidate) => existsSync(candidate));
40
- if (!selected) {
41
- throw new Error(`Contained filesystem operations need the packaged Darwin ${process.arch} backend`);
42
- }
43
- const loaded = createRequire(import.meta.url)(selected);
44
- const methods = [
45
- "openDirectoryAt",
46
- "openFileAt",
47
- "createFileAt",
48
- "createDirectoryAt",
49
- "statAt",
50
- "listAt",
51
- "renameAt",
52
- "unlinkAt"
53
- ];
54
- if (!hasFunctions(loaded, methods)) {
55
- throw new Error("The packaged Darwin contained-files backend has an invalid surface");
56
- }
57
- darwinBinding = loaded;
58
- return darwinBinding;
59
- }
60
22
 
61
23
  class NumericFileHandle {
62
24
  fd;
@@ -110,7 +72,7 @@ async function openPinnedDirectory(absolute) {
110
72
  }
111
73
  }
112
74
  function safeSegments(relative) {
113
- if (path2.isAbsolute(relative))
75
+ if (path.isAbsolute(relative))
114
76
  throw new Error("Contained paths must be relative");
115
77
  const segments = relative.split(/[\\/]/u);
116
78
  if (segments.length === 0 || segments.some((segment) => segment === "" || segment === "." || segment === "..")) {
@@ -122,13 +84,13 @@ async function openDirectoryAt(directory, name) {
122
84
  if (process.platform === "darwin") {
123
85
  return new NumericFileHandle(loadDarwinBinding().openDirectoryAt(directory.fd, name));
124
86
  }
125
- return open(path2.join(descriptorPath(directory), name), constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
87
+ return open(path.join(descriptorPath(directory), name), constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
126
88
  }
127
89
  async function openFileAt(directory, name) {
128
90
  if (process.platform === "darwin") {
129
91
  return new NumericFileHandle(loadDarwinBinding().openFileAt(directory.fd, name));
130
92
  }
131
- return open(path2.join(descriptorPath(directory), name), constants.O_RDONLY | constants.O_NOFOLLOW);
93
+ return open(path.join(descriptorPath(directory), name), constants.O_RDONLY | constants.O_NOFOLLOW);
132
94
  }
133
95
  function entryMetadata(mode, size) {
134
96
  return {
@@ -144,7 +106,7 @@ async function statAt(directory, name) {
144
106
  const metadata = loadDarwinBinding().statAt(directory.fd, name);
145
107
  return metadata ? entryMetadata(metadata.mode, metadata.size) : null;
146
108
  }
147
- return lstat(path2.join(descriptorPath(directory), name)).catch((error) => {
109
+ return lstat(path.join(descriptorPath(directory), name)).catch((error) => {
148
110
  if (error.code === "ENOENT")
149
111
  return null;
150
112
  throw error;
@@ -176,7 +138,7 @@ async function listContainedDirectory(root, relative, maxEntries, authorizePath)
176
138
  const admitted = [];
177
139
  const denied = [];
178
140
  for (const entry of raw) {
179
- const entryPath = relative === "." ? entry.name : path2.join(relative, entry.name);
141
+ const entryPath = relative === "." ? entry.name : path.join(relative, entry.name);
180
142
  if (authorizePath && !await authorizePath(entryPath)) {
181
143
  denied.push({ name: entry.name, kind: containedEntryKind(entry) });
182
144
  continue;
@@ -217,7 +179,7 @@ async function createDirectoryAt(directory, name) {
217
179
  return loadDarwinBinding().createDirectoryAt(directory.fd, name, 511);
218
180
  }
219
181
  try {
220
- await mkdir(path2.join(descriptorPath(directory), name));
182
+ await mkdir(path.join(descriptorPath(directory), name));
221
183
  return true;
222
184
  } catch (error) {
223
185
  if (error.code === "EEXIST")
@@ -235,7 +197,7 @@ async function missingContainedDirectories(root, relative) {
235
197
  for (const segment of segments) {
236
198
  walked = [...walked, segment];
237
199
  if (missing.length > 0) {
238
- missing.push(walked.join(path2.sep));
200
+ missing.push(walked.join(path.sep));
239
201
  continue;
240
202
  }
241
203
  const next = await openDirectoryAt(current, segment).catch((error) => {
@@ -244,7 +206,7 @@ async function missingContainedDirectories(root, relative) {
244
206
  throw error;
245
207
  });
246
208
  if (!next) {
247
- missing.push(walked.join(path2.sep));
209
+ missing.push(walked.join(path.sep));
248
210
  continue;
249
211
  }
250
212
  await current.close();
@@ -373,7 +335,7 @@ async function scanContainedFiles(input) {
373
335
  const entries = [...await listAt(directory)];
374
336
  entries.sort((left, right) => left.name.localeCompare(right.name));
375
337
  for (const entry of entries) {
376
- const relative = relativeDirectory ? path3.join(relativeDirectory, entry.name) : entry.name;
338
+ const relative = relativeDirectory ? path2.join(relativeDirectory, entry.name) : entry.name;
377
339
  const kind = entry.isDirectory() ? "directory" : entry.isSymbolicLink() ? "symlink" : entry.isFile() ? "file" : "other";
378
340
  if (kind === "file" && input.includeFile && !input.includeFile(relative))
379
341
  continue;
@@ -445,4 +407,4 @@ async function scanContainedFiles(input) {
445
407
  return { files, truncated, skippedDirectories, skippedSymlinks, denied, deniedTruncated };
446
408
  }
447
409
 
448
- export { loadDarwinBinding, NumericFileHandle, descriptorPath, listContainedDirectory, missingContainedDirectories, openContainedParent, openContainedFile, assertContainedFileCurrent, assertContainedParentCurrent, containedEntryMetadata, openContainedParentFile, readContainedUtf8Handle, walkContainedFiles, scanContainedFiles };
410
+ export { NumericFileHandle, descriptorPath, listContainedDirectory, missingContainedDirectories, openContainedParent, openContainedFile, assertContainedFileCurrent, assertContainedParentCurrent, containedEntryMetadata, openContainedParentFile, readContainedUtf8Handle, walkContainedFiles, scanContainedFiles };
@@ -5,14 +5,16 @@ import {
5
5
  containedEntryMetadata,
6
6
  descriptorPath,
7
7
  listContainedDirectory,
8
- loadDarwinBinding,
9
8
  missingContainedDirectories,
10
9
  openContainedFile,
11
10
  openContainedParent,
12
11
  openContainedParentFile,
13
12
  readContainedUtf8Handle,
14
13
  scanContainedFiles
15
- } from "./index-px2gm2jp.js";
14
+ } from "./index-fhwqwxe0.js";
15
+ import {
16
+ loadDarwinBinding
17
+ } from "./index-zjjyynm3.js";
16
18
  import {
17
19
  codingPathRefusal,
18
20
  codingRefusal,
@@ -2365,11 +2365,20 @@ function bindRealtimeServer(contract, handle, options = {}) {
2365
2365
  onRejected: options.onRejected,
2366
2366
  logger: options.logger
2367
2367
  });
2368
- handler({
2369
- raw,
2370
- events,
2371
- to: (room) => outbound(raw.to(room))
2372
- });
2368
+ const failed = (error) => {
2369
+ try {
2370
+ raw.disconnect(true);
2371
+ } catch {}
2372
+ if (options.logger)
2373
+ options.logger.error("Realtime connection handler failed", { error });
2374
+ else
2375
+ console.error("[stitchkit] realtime connection handler failed", error);
2376
+ };
2377
+ try {
2378
+ Promise.resolve(handler({ raw, events, to: (room) => outbound(raw.to(room)) })).catch(failed);
2379
+ } catch (error) {
2380
+ failed(error);
2381
+ }
2373
2382
  };
2374
2383
  handle.io.on("connection", listener);
2375
2384
  return () => {
@@ -175,6 +175,7 @@ function deltaWins(delta, value) {
175
175
  import { z as z2 } from "zod";
176
176
  var WatchKeySchema = z2.object({
177
177
  service: z2.string().min(1),
178
+ instance: z2.string().min(1).max(128).optional(),
178
179
  action: z2.string().min(1),
179
180
  digest: z2.string().min(1)
180
181
  }).strict().readonly();
@@ -221,7 +222,7 @@ var watchContract = {
221
222
  }
222
223
  };
223
224
  function watchKeyString(key) {
224
- return `${key.service}/${key.action}/${key.digest}`;
225
+ return `${key.service}/${key.action}/${key.digest}${key.instance === undefined ? "" : `/${encodeURIComponent(key.instance)}`}`;
225
226
  }
226
227
 
227
228
  export { WatchDeltaSchema, WatchArrayOpSchema, diff, apply, deltaWins, WatchKeySchema, WatchHaveSchema, WatchValueSchema, WatchStateSchema, WATCH_OPEN, WATCH_CLOSE, WATCH_VALUE, WATCH_STATE, watchContract, watchKeyString };
@@ -0,0 +1,22 @@
1
+ // src/internal/mutation-queue.ts
2
+ function createMutationQueue(maxPending = Number.POSITIVE_INFINITY) {
3
+ if (maxPending !== Number.POSITIVE_INFINITY && (!Number.isInteger(maxPending) || maxPending < 1)) {
4
+ throw new RangeError("maxPending must be a positive integer");
5
+ }
6
+ let tail = Promise.resolve();
7
+ let pending = 0;
8
+ return (mutation) => {
9
+ if (pending >= maxPending)
10
+ return Promise.reject(new Error("Mutation queue capacity exceeded"));
11
+ pending += 1;
12
+ const result = tail.then(mutation, mutation);
13
+ tail = result.then(() => {
14
+ pending -= 1;
15
+ }, () => {
16
+ pending -= 1;
17
+ });
18
+ return result;
19
+ };
20
+ }
21
+
22
+ export { createMutationQueue };
@@ -19,7 +19,7 @@ import {
19
19
  canonicalAgentJson,
20
20
  decodeAgentConversationArchive,
21
21
  encodeAgentConversationArchive
22
- } from "./index-gxrt5h6v.js";
22
+ } from "./index-cyktc4bp.js";
23
23
  import {
24
24
  AgentMessageSchema,
25
25
  AgentRecordIdSchema,
@@ -427,6 +427,52 @@ async function importConversation(driver, bytes) {
427
427
  });
428
428
  }
429
429
 
430
+ // src/agent-runtime/store-event-once.ts
431
+ import { createHash } from "node:crypto";
432
+ function eventOnceId(conversationId, kind, key) {
433
+ if (!key)
434
+ throw new TypeError("Event admission key must not be empty");
435
+ return createHash("sha256").update(JSON.stringify([conversationId, kind, key])).digest("hex");
436
+ }
437
+ async function findEvent(driver, transaction, conversationId, eventId) {
438
+ if (driver.events.find)
439
+ return driver.events.find(transaction, { conversationId, eventId });
440
+ let fromSeq;
441
+ do {
442
+ const page = await driver.events.list(transaction, {
443
+ conversationId,
444
+ fromSeq,
445
+ limit: 1e4
446
+ });
447
+ const found = page.items.find((event) => event.eventId === eventId);
448
+ if (found)
449
+ return found;
450
+ fromSeq = page.nextSeq;
451
+ } while (fromSeq !== undefined);
452
+ return;
453
+ }
454
+ function appendEventOnce(driver, input, key) {
455
+ const parsed = AppendAgentStoreEventSchema.parse(input);
456
+ const eventId = eventOnceId(parsed.conversationId, parsed.kind, key);
457
+ return driver.transaction(async (transaction) => {
458
+ if (await driver.conversations?.isPurged(transaction, parsed.conversationId)) {
459
+ throw new AgentConversationPurgedError;
460
+ }
461
+ const previous = await findEvent(driver, transaction, parsed.conversationId, eventId);
462
+ if (previous)
463
+ return { outcome: "duplicate", event: previous };
464
+ const event = await driver.events.append(transaction, {
465
+ ...agentStoreEventDraft(parsed),
466
+ eventId
467
+ });
468
+ return { outcome: "applied", event };
469
+ });
470
+ }
471
+ function findEventOnce(driver, input) {
472
+ const eventId = eventOnceId(input.conversationId, input.kind, input.key);
473
+ return driver.transaction((transaction) => findEvent(driver, transaction, input.conversationId, eventId), { access: "read" });
474
+ }
475
+
430
476
  // src/agent-runtime/store-mutate.ts
431
477
  import { z as z4 } from "zod";
432
478
 
@@ -453,7 +499,7 @@ function applied(current, input, effects) {
453
499
  }
454
500
 
455
501
  // src/agent-runtime/store-reducer.ts
456
- import { createHash } from "node:crypto";
502
+ import { createHash as createHash2 } from "node:crypto";
457
503
 
458
504
  // src/agent-runtime/store-reduce-history.ts
459
505
  function reduceAccept(current, input) {
@@ -737,7 +783,7 @@ function transitionRecord(operation) {
737
783
  assistant: {
738
784
  id: assistant.id,
739
785
  status: assistant.status,
740
- sha256: createHash("sha256").update(body).digest("hex"),
786
+ sha256: createHash2("sha256").update(body).digest("hex"),
741
787
  parts: assistant.parts.length,
742
788
  bytes: Buffer.byteLength(body)
743
789
  }
@@ -979,6 +1025,8 @@ function createAgentRuntimeStore(driver) {
979
1025
  loadSnapshot: (conversationId) => loadSnapshot(driver, conversationId),
980
1026
  loadRun: (input) => loadRun(driver, input),
981
1027
  listActiveRuns: (conversationId) => listActiveRuns(driver, conversationId),
1028
+ appendEventOnce: (input, key) => appendEventOnce(driver, input, key),
1029
+ findEventOnce: (input) => findEventOnce(driver, input),
982
1030
  appendEvent: (input) => appendEvent(driver, input),
983
1031
  readEvents: (input) => readEvents(driver, input),
984
1032
  exportConversation: (conversationId) => exportConversation(driver, conversationId),
@@ -0,0 +1,42 @@
1
+ // src/internal/darwin-binding.ts
2
+ import { existsSync } from "node:fs";
3
+ import { createRequire } from "node:module";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ function hasFunctions(value, names) {
7
+ return typeof value === "object" && value !== null && names.every((name) => typeof Reflect.get(value, name) === "function");
8
+ }
9
+ var darwinBinding;
10
+ function loadDarwinBinding() {
11
+ if (darwinBinding)
12
+ return darwinBinding;
13
+ const directory = path.dirname(fileURLToPath(import.meta.url));
14
+ const binary = `darwin-${process.arch}.node`;
15
+ const candidates = [
16
+ path.resolve(directory, "../native", binary),
17
+ path.resolve(directory, "../../native", binary)
18
+ ];
19
+ const selected = candidates.find((candidate) => existsSync(candidate));
20
+ if (!selected) {
21
+ throw new Error(`Contained filesystem operations need the packaged Darwin ${process.arch} backend`);
22
+ }
23
+ const loaded = createRequire(import.meta.url)(selected);
24
+ const methods = [
25
+ "openDirectoryAt",
26
+ "openFileAt",
27
+ "createFileAt",
28
+ "createDirectoryAt",
29
+ "statAt",
30
+ "listAt",
31
+ "renameAt",
32
+ "unlinkAt",
33
+ "processIdentity"
34
+ ];
35
+ if (!hasFunctions(loaded, methods)) {
36
+ throw new Error("The packaged Darwin contained-files backend has an invalid surface");
37
+ }
38
+ darwinBinding = loaded;
39
+ return darwinBinding;
40
+ }
41
+
42
+ export { loadDarwinBinding };
@@ -0,0 +1,17 @@
1
+ import { type BackoffPolicy } from './backoff.js';
2
+ export interface CoalescedTask {
3
+ readonly running: boolean;
4
+ /** A trigger arrived that no pass has served yet. */
5
+ readonly pending: boolean;
6
+ trigger(): void;
7
+ pauseRetry(): void;
8
+ close(): void;
9
+ }
10
+ /** One job per key; hints during work become one trailing pass, failures retain retry. */
11
+ export declare function createCoalescedTask(config: {
12
+ run(): Promise<void>;
13
+ active(): boolean;
14
+ onError(error: unknown): void;
15
+ backoff: BackoffPolicy;
16
+ }): CoalescedTask;
17
+ //# sourceMappingURL=coalesced-task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coalesced-task.d.ts","sourceRoot":"","sources":["../../src/internal/coalesced-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAiB,MAAM,WAAW,CAAC;AAE9D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,OAAO,IAAI,IAAI,CAAC;IAChB,UAAU,IAAI,IAAI,CAAC;IACnB,KAAK,IAAI,IAAI,CAAC;CACf;AAED,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrB,MAAM,IAAI,OAAO,CAAC;IAClB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,aAAa,CAAC;CACxB,GAAG,aAAa,CAuDhB"}
@@ -0,0 +1,19 @@
1
+ export interface DarwinEntry {
2
+ name: string;
3
+ mode: number;
4
+ size: number;
5
+ }
6
+ export interface DarwinBinding {
7
+ processIdentity(pid: number): unknown;
8
+ openDirectoryAt(directory: number, name: string): number;
9
+ openFileAt(directory: number, name: string): number;
10
+ createFileAt(directory: number, name: string, mode: number): number;
11
+ createDirectoryAt(directory: number, name: string, mode: number): boolean;
12
+ statAt(directory: number, name: string): Omit<DarwinEntry, 'name'> | null;
13
+ listAt(directory: number): readonly DarwinEntry[];
14
+ renameAt(directory: number, source: string, target: string): void;
15
+ unlinkAt(directory: number, name: string): void;
16
+ }
17
+ export declare function hasFunctions(value: unknown, names: readonly string[]): boolean;
18
+ export declare function loadDarwinBinding(): DarwinBinding;
19
+ //# sourceMappingURL=darwin-binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"darwin-binding.d.ts","sourceRoot":"","sources":["../../src/internal/darwin-binding.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACtC,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACzD,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACpD,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACpE,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1E,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAC1E,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,WAAW,EAAE,CAAC;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAClE,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACjD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAM9E;AAID,wBAAgB,iBAAiB,IAAI,aAAa,CAgCjD"}
@@ -1,15 +1,27 @@
1
+ import { z } from 'zod';
2
+ import { type ProcessOwnerEvidence } from './process-instance.js';
1
3
  /** Who holds a lock, as its file records it. */
2
- export interface ExclusiveLockOwner {
3
- readonly pid: number;
4
- readonly host: string;
5
- readonly acquiredAt: string;
6
- /** Stable machine identity; absent where the platform offers none, and in older locks. */
7
- readonly machine?: string;
8
- }
4
+ declare const ExclusiveLockOwnerSchema: z.ZodObject<{
5
+ pid: z.ZodNumber;
6
+ host: z.ZodString;
7
+ acquiredAt: z.ZodString;
8
+ machine: z.ZodCatch<z.ZodOptional<z.ZodString>>;
9
+ process: z.ZodCatch<z.ZodOptional<z.ZodNullable<z.ZodObject<{
10
+ platform: z.ZodEnum<{
11
+ darwin: "darwin";
12
+ linux: "linux";
13
+ }>;
14
+ bootId: z.ZodString;
15
+ namespace: z.ZodString;
16
+ startId: z.ZodString;
17
+ }, z.core.$strict>>>>;
18
+ }, z.core.$strip>;
19
+ export type ExclusiveLockOwner = z.infer<typeof ExclusiveLockOwnerSchema>;
9
20
  /** Why a present lock was not taken. */
10
21
  export interface ExclusiveLockDiagnosis {
11
22
  readonly attribution: 'this-machine' | 'another-machine' | 'unattributable';
12
23
  readonly liveness: 'alive' | 'gone' | 'not-probed';
24
+ readonly identity?: ProcessOwnerEvidence['identity'];
13
25
  readonly owner: ExclusiveLockOwner | null;
14
26
  }
15
27
  /** A lock this process holds. */
@@ -48,4 +60,5 @@ export type ExclusiveLockAttempt = {
48
60
  export declare function attemptExclusiveLock(path: string, options: ExclusiveLockAttemptOptions): Promise<ExclusiveLockAttempt>;
49
61
  /** Read the owner a present lock records, for a refusal that has to name it. */
50
62
  export declare function readExclusiveLockOwner(path: string): Promise<ExclusiveLockOwner | null>;
63
+ export {};
51
64
  //# sourceMappingURL=exclusive-lock.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"exclusive-lock.d.ts","sourceRoot":"","sources":["../../src/internal/exclusive-lock.ts"],"names":[],"mappings":"AA8BA,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,0FAA0F;IAC1F,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wCAAwC;AACxC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,WAAW,EAAE,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;IAC5E,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC;IACnD,QAAQ,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;CAC3C;AAED,iCAAiC;AACjC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,uFAAuF;IACvF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,GACpC;IACE,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,sBAAsB,CAAC;CAC7C,CAAC;AAsLN;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,oBAAoB,CAAC,CAe/B;AAED,gFAAgF;AAChF,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAEpC"}
1
+ {"version":3,"file":"exclusive-lock.d.ts","sourceRoot":"","sources":["../../src/internal/exclusive-lock.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAEL,KAAK,oBAAoB,EAG1B,MAAM,oBAAoB,CAAC;AAK5B,gDAAgD;AAChD,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;iBAO5B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,wCAAwC;AACxC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,WAAW,EAAE,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;IAC5E,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;CAC3C;AAED,iCAAiC;AACjC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,uFAAuF;IACvF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,GACpC;IACE,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,sBAAsB,CAAC;CAC7C,CAAC;AAmLN;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,oBAAoB,CAAC,CAe/B;AAED,gFAAgF;AAChF,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAEpC"}
@@ -0,0 +1,4 @@
1
+ /** FIFO mutations with caller-visible failures and an optional finite admission bound. */
2
+ export type MutationQueue = <T>(mutation: () => Promise<T>) => Promise<T>;
3
+ export declare function createMutationQueue(maxPending?: number): MutationQueue;
4
+ //# sourceMappingURL=mutation-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutation-queue.d.ts","sourceRoot":"","sources":["../../src/internal/mutation-queue.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAE1E,wBAAgB,mBAAmB,CAAC,UAAU,SAA2B,GAAG,aAAa,CAwBxF"}
@@ -29,7 +29,7 @@ export declare function machineIdentity(declared: string | undefined): Promise<s
29
29
  * carries the ordinary doubt about reuse. Found by a consuming application, which measured `Z` and a
30
30
  * successful signal on both platforms of its fleet. → ADR 0147.
31
31
  */
32
- export declare function probeLiveness(pid: number): Promise<'alive' | 'gone'>;
32
+ export declare function probeLiveness(pid: number, reach?: (target: number) => true): Promise<'alive' | 'gone'>;
33
33
  /**
34
34
  * The state letter of a pid, or `null` where this platform will not say.
35
35
  *
@@ -1 +1 @@
1
- {"version":3,"file":"process-identity.d.ts","sourceRoot":"","sources":["../../src/internal/process-identity.ts"],"names":[],"mappings":"AA8CA;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE7D;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,SAAU,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiBtF;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAW1F;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAY1E;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnD,OAAO,CAAC,OAAO,CAAC,CAuBlB"}
1
+ {"version":3,"file":"process-identity.d.ts","sourceRoot":"","sources":["../../src/internal/process-identity.ts"],"names":[],"mappings":"AA8CA;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE7D;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,SAAU,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiBtF;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAW1F;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,KAAK,YAAY,MAAM,SAA4B,GAClD,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAY3B;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnD,OAAO,CAAC,OAAO,CAAC,CAuBlB"}
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod';
2
+ import { probeLiveness } from './process-identity.js';
3
+ export declare const ProcessInstanceSchema: z.ZodObject<{
4
+ platform: z.ZodEnum<{
5
+ darwin: "darwin";
6
+ linux: "linux";
7
+ }>;
8
+ bootId: z.ZodString;
9
+ namespace: z.ZodString;
10
+ startId: z.ZodString;
11
+ }, z.core.$strict>;
12
+ export type ProcessInstance = z.infer<typeof ProcessInstanceSchema>;
13
+ /** /proc stat field 22 follows a command name that may itself contain spaces and parentheses. */
14
+ export declare function linuxProcessStart(stat: string, pid: number): string | null;
15
+ /** @internal procRoot permits kernel-format fixtures without changing a real process or boot. */
16
+ export declare function readProcessInstance(pid: number, procRoot?: string): Promise<ProcessInstance | null>;
17
+ export interface ProcessOwnerEvidence {
18
+ readonly liveness: 'alive' | 'gone' | 'not-probed';
19
+ readonly identity: 'matched' | 'different-boot' | 'reused-pid' | 'pid-gone' | 'legacy' | 'unavailable';
20
+ }
21
+ /** Compare identities only inside one machine (the caller establishes that boundary). */
22
+ export declare function probeProcessOwner(pid: number, recorded: ProcessInstance | null | undefined, probes?: {
23
+ read: typeof readProcessInstance;
24
+ liveness: typeof probeLiveness;
25
+ }): Promise<ProcessOwnerEvidence>;
26
+ //# sourceMappingURL=process-instance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-instance.d.ts","sourceRoot":"","sources":["../../src/internal/process-instance.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,eAAO,MAAM,qBAAqB;;;;;;;;kBAOvB,CAAC;AACZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS1E;AAED,iGAAiG;AACjG,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,QAAQ,SAAU,GACjB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CA6CjC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC;IACnD,QAAQ,CAAC,QAAQ,EACb,SAAS,GACT,gBAAgB,GAChB,YAAY,GACZ,UAAU,GACV,QAAQ,GACR,aAAa,CAAC;CACnB;AAED,yFAAyF;AACzF,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,EAC5C,MAAM;IAAK,IAAI;IAAuB,QAAQ;CAAiB,GAC9D,OAAO,CAAC,oBAAoB,CAAC,CAyB/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"with-exclusive-lock.d.ts","sourceRoot":"","sources":["../../src/internal/with-exclusive-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAwB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEjF,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,iFAAiF;IACjF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,qEAAqE;AACrE,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,wFAAwF;IACxF,QAAQ,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IALnC,IAAI,SAAwB;IACrC,YACW,IAAI,EAAE,cAAc,GAAG,cAAc,EACrC,KAAK,EAAE,MAAM;IACtB,wFAAwF;IAC/E,MAAM,EAAE,kBAAkB,GAAG,IAAI,EAC1C,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAG9B;CACF;AAkCD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC5C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,CAAC,CAAC,CAwDZ"}
1
+ {"version":3,"file":"with-exclusive-lock.d.ts","sourceRoot":"","sources":["../../src/internal/with-exclusive-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,iFAAiF;IACjF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,qEAAqE;AACrE,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,wFAAwF;IACxF,QAAQ,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IALnC,IAAI,SAAwB;IACrC,YACW,IAAI,EAAE,cAAc,GAAG,cAAc,EACrC,KAAK,EAAE,MAAM;IACtB,wFAAwF;IAC/E,MAAM,EAAE,kBAAkB,GAAG,IAAI,EAC1C,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAG9B;CACF;AAyCD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC5C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,CAAC,CAAC,CAwDZ"}
@@ -0,0 +1,71 @@
1
+ import type { WatchClientConfig, WatchListeners } from './watch-client.js';
2
+ import { type WatchKey, type WatchStateFrame, type WatchValueFrame } from './watch-contract.js';
3
+ type Listeners<T> = WatchListeners<T>;
4
+ export interface WatchClientEntry {
5
+ epoch: number;
6
+ released: boolean;
7
+ readonly key: WatchKey;
8
+ readonly args: Record<string, unknown>;
9
+ readonly listeners: Set<Listeners<unknown>>;
10
+ revision: number;
11
+ value?: unknown;
12
+ hasValue: boolean;
13
+ /**
14
+ * The server's identity for the value held, carried back on the next `open`.
15
+ *
16
+ * Kept rather than recomputed so that what is offered is what the server
17
+ * actually said, not this client's opinion of the value it built — if those
18
+ * two ever disagree, offering the recomputed one would hide the disagreement
19
+ * and offering the server's one surfaces it as a difference that will not
20
+ * apply.
21
+ */
22
+ fingerprint?: string;
23
+ /**
24
+ * Whether the **current** connection has been told about this key.
25
+ *
26
+ * On the entry rather than on a handle: two handles asking one question share
27
+ * a subscription, so the second must not send a second `open` — and a
28
+ * reconnect has to clear it for both.
29
+ */
30
+ opened: boolean;
31
+ /**
32
+ * Whether a value frame has answered the latest `open`.
33
+ *
34
+ * A revision is a counter of one hub's life of the key, so it orders frames
35
+ * within one open and says nothing across two: a restarted API starts at 1
36
+ * again. Until the first answer to an open arrives, the held revision is not
37
+ * a floor — without this, a client that held revision 40 from the previous
38
+ * process dropped every full value of the new one as "no newer" until its
39
+ * counter passed 40, while showing itself live.
40
+ */
41
+ answered: boolean;
42
+ state: WatchStateFrame;
43
+ release?: ReturnType<typeof setTimeout>;
44
+ }
45
+ export declare function publishState(entry: WatchClientEntry, state: WatchStateFrame): void;
46
+ /**
47
+ * Tell the server about a key, and turn every way that can fail into a state.
48
+ *
49
+ * Nothing here rejects. It runs from a subscribe and from a reconnect, neither
50
+ * of which has anywhere to put a rejected promise — and a disconnected socket
51
+ * rejects the request, which is exactly the moment this runs. An unhandled
52
+ * rejection in a console is also the one outcome that tells the subscriber
53
+ * nothing at all.
54
+ */
55
+ export declare function openWatch(config: WatchClientConfig, openTimeoutMs: number, entry: WatchClientEntry): Promise<void>;
56
+ /**
57
+ * What one value frame does to an entry: a new value, a confirmation of the
58
+ * held one, a late answer to drop, or a reason the key has to start over.
59
+ * The entry's revision, value and fingerprint move here and nowhere else.
60
+ */
61
+ export declare function applyWatchFrame(entry: WatchClientEntry, frame: WatchValueFrame): {
62
+ kind: 'value';
63
+ value: unknown;
64
+ } | {
65
+ kind: 'confirmed' | 'stale';
66
+ } | {
67
+ kind: 'resync';
68
+ message: string;
69
+ };
70
+ export {};
71
+ //# sourceMappingURL=watch-client-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-client-state.d.ts","sourceRoot":"","sources":["../../src/live/watch-client-state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,eAAe,EACrB,MAAM,kBAAkB,CAAC;AAG1B,KAAK,SAAS,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC;AACtC,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;;;;;;;;OASG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;CACzC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAGlF;AAED;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,IAAI,CAAC,CAsDf;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,gBAAgB,EACvB,KAAK,EAAE,eAAe,GAEpB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA2DtC"}
@@ -1,3 +1,4 @@
1
+ import type { SessionOperation } from '../browser/session.js';
1
2
  /**
2
3
  * The client half of a watched read.
3
4
  *
@@ -44,7 +45,7 @@
44
45
  * sense a rendering component can use.
45
46
  */
46
47
  import type { ContractDef, EndpointDef } from '../contract/define.js';
47
- import { WATCH_CLOSE, WATCH_OPEN, WATCH_STATE, WATCH_VALUE, type WatchHave, type WatchKey, type WatchStateFrame, type WatchValueFrame } from './watch-contract.js';
48
+ import { WATCH_CLOSE, type WATCH_OPEN, WATCH_STATE, WATCH_VALUE, type WatchHave, type WatchKey, type WatchStateFrame, type WatchValueFrame } from './watch-contract.js';
48
49
  export interface WatchListeners<TValue> {
49
50
  value(value: TValue): void;
50
51
  /** Phase and, when unhealthy, the read's own code and message. */
@@ -125,6 +126,9 @@ export interface WatchTransport {
125
126
  onConnectionChange(listener: (connected: boolean, reason?: string) => void): () => void;
126
127
  }
127
128
  export interface WatchClientConfig {
129
+ readonly session?: SessionOperation<unknown>;
130
+ readonly maxKeys?: number;
131
+ readonly maxListenersPerKey?: number;
128
132
  readonly transport: WatchTransport;
129
133
  /** How long a key's value is retained after its last subscriber. Default 0. */
130
134
  readonly holdMs?: number;