iterate 0.2.6 → 0.3.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.
Files changed (218) hide show
  1. package/README.md +86 -76
  2. package/THIRD_PARTY_NOTICES.md +55 -0
  3. package/bin/iterate.js +18 -3
  4. package/dist/api-url-B6404M82.mjs +17 -0
  5. package/dist/api-url-B6404M82.mjs.map +1 -0
  6. package/dist/app-ref-BipL0feU.mjs +35 -0
  7. package/dist/app-ref-BipL0feU.mjs.map +1 -0
  8. package/dist/app-ref-C1CrgXqX.mjs +7 -0
  9. package/dist/app-ref-C1CrgXqX.mjs.map +1 -0
  10. package/dist/app-ref-DYai_om1.mjs +7 -0
  11. package/dist/app-ref-DYai_om1.mjs.map +1 -0
  12. package/dist/cli-D0c-pDL_.mjs +1010 -0
  13. package/dist/cli-D0c-pDL_.mjs.map +1 -0
  14. package/dist/client.d.ts +3 -0
  15. package/dist/client.mjs +4 -0
  16. package/dist/cloudflare-BTm90gQ4.mjs +951 -0
  17. package/dist/cloudflare-BTm90gQ4.mjs.map +1 -0
  18. package/dist/contract-s4FW4eES.mjs +309 -0
  19. package/dist/contract-s4FW4eES.mjs.map +1 -0
  20. package/dist/document-review/index.d.ts +5 -0
  21. package/dist/document-review/types.d.ts +107 -0
  22. package/dist/document-review.mjs +7015 -0
  23. package/dist/document-review.mjs.map +1 -0
  24. package/dist/durable-object-processor-durability-CNsTjAJS.mjs +205 -0
  25. package/dist/durable-object-processor-durability-CNsTjAJS.mjs.map +1 -0
  26. package/dist/idempotency-DleloJNt.mjs +28 -0
  27. package/dist/idempotency-DleloJNt.mjs.map +1 -0
  28. package/dist/index.mjs +1 -1
  29. package/dist/itx/api-url.d.ts +6 -0
  30. package/dist/itx/itx-node-client.d.ts +65 -0
  31. package/dist/itx/itx-session.d.ts +215 -0
  32. package/dist/itx/owned-rpc-session.d.ts +14 -0
  33. package/dist/itx/query-client.d.ts +10 -0
  34. package/dist/itx-api.generated.d.ts +6195 -0
  35. package/dist/itx-session-sjud8GiT.mjs +534 -0
  36. package/dist/itx-session-sjud8GiT.mjs.map +1 -0
  37. package/dist/live-state-BJNqOwFw.mjs +299 -0
  38. package/dist/live-state-BJNqOwFw.mjs.map +1 -0
  39. package/dist/next/api.d.ts +479 -0
  40. package/dist/next/api.mjs +0 -0
  41. package/dist/next/app-server.d.ts +44 -0
  42. package/dist/next/app-server.mjs +479 -0
  43. package/dist/next/app-server.mjs.map +1 -0
  44. package/dist/next/app-session.d.ts +49 -0
  45. package/dist/next/app-session.mjs +238 -0
  46. package/dist/next/app-session.mjs.map +1 -0
  47. package/dist/next/app.d.ts +29 -0
  48. package/dist/next/app.mjs +141 -0
  49. package/dist/next/app.mjs.map +1 -0
  50. package/dist/next/client/live-state.d.ts +63 -0
  51. package/dist/next/client/oauth.d.ts +12 -0
  52. package/dist/next/client/react.d.ts +109 -0
  53. package/dist/next/client/socket.d.ts +6 -0
  54. package/dist/next/client.mjs +156 -0
  55. package/dist/next/client.mjs.map +1 -0
  56. package/dist/next/expression.d.ts +146 -0
  57. package/dist/next/expression.mjs +399 -0
  58. package/dist/next/expression.mjs.map +1 -0
  59. package/dist/next/lib.d.ts +56 -0
  60. package/dist/next/lib.mjs +199 -0
  61. package/dist/next/lib.mjs.map +1 -0
  62. package/dist/next/oauth-scopes.d.ts +32 -0
  63. package/dist/next/oauth-scopes.mjs +40 -0
  64. package/dist/next/oauth-scopes.mjs.map +1 -0
  65. package/dist/next/oauth.mjs +29 -0
  66. package/dist/next/oauth.mjs.map +1 -0
  67. package/dist/next/principal.d.ts +64 -0
  68. package/dist/next/principal.mjs +98 -0
  69. package/dist/next/principal.mjs.map +1 -0
  70. package/dist/next/project-ingress.d.ts +37 -0
  71. package/dist/next/project-ingress.mjs +75 -0
  72. package/dist/next/project-ingress.mjs.map +1 -0
  73. package/dist/next/react.mjs +285 -0
  74. package/dist/next/react.mjs.map +1 -0
  75. package/dist/next/sdk/auth.d.ts +5 -0
  76. package/dist/next/sdk/index.d.ts +112 -0
  77. package/dist/next/sdk.mjs +139 -0
  78. package/dist/next/sdk.mjs.map +1 -0
  79. package/dist/next/stream/processor.d.ts +378 -0
  80. package/dist/next/stream/processor.mjs +582 -0
  81. package/dist/next/stream/processor.mjs.map +1 -0
  82. package/dist/next/stream/run.d.ts +58 -0
  83. package/dist/next/stream/run.mjs +40 -0
  84. package/dist/next/stream/run.mjs.map +1 -0
  85. package/dist/next-node.d.ts +15 -0
  86. package/dist/next-node.mjs +51 -0
  87. package/dist/next-node.mjs.map +1 -0
  88. package/dist/node.d.ts +3 -0
  89. package/dist/node.mjs +185 -0
  90. package/dist/node.mjs.map +1 -0
  91. package/dist/processor-host-capabilities-BMFH3KTM.mjs +56 -0
  92. package/dist/processor-host-capabilities-BMFH3KTM.mjs.map +1 -0
  93. package/dist/processors/cloudflare.d.ts +3 -0
  94. package/dist/processors/durable-object-processor-durability.d.ts +79 -0
  95. package/dist/processors/event-consumption-metrics.d.ts +82 -0
  96. package/dist/processors/idempotency.d.ts +13 -0
  97. package/dist/processors/index.d.ts +12 -0
  98. package/dist/processors/processor-contracts.d.ts +342 -0
  99. package/dist/processors/processor-facet.d.ts +186 -0
  100. package/dist/processors/processor-host-capabilities.d.ts +60 -0
  101. package/dist/processors/prompt-sections.d.ts +17 -0
  102. package/dist/processors/rpc-types.d.ts +515 -0
  103. package/dist/processors/schemas.d.ts +102 -0
  104. package/dist/processors/stream-handle.d.ts +45 -0
  105. package/dist/processors/stream-processor-keepalive.d.ts +95 -0
  106. package/dist/processors/stream-processor-registry.d.ts +233 -0
  107. package/dist/processors/stream-processor-runner.d.ts +289 -0
  108. package/dist/processors/stream-processor.d.ts +339 -0
  109. package/dist/processors/stream-runtime-metrics.d.ts +107 -0
  110. package/dist/processors/testing.d.ts +302 -0
  111. package/dist/processors-BoNyeBfQ.mjs +10 -0
  112. package/dist/processors-BoNyeBfQ.mjs.map +1 -0
  113. package/dist/processors-cloudflare.mjs +3 -0
  114. package/dist/processors-testing.mjs +435 -0
  115. package/dist/processors-testing.mjs.map +1 -0
  116. package/dist/processors.mjs +52 -0
  117. package/dist/processors.mjs.map +1 -0
  118. package/dist/protocol-DnK_f2m6.mjs +251 -0
  119. package/dist/protocol-DnK_f2m6.mjs.map +1 -0
  120. package/dist/sdk/capnweb/index.d.ts +2 -0
  121. package/dist/sdk/capnweb/live-state/compact.d.ts +5 -0
  122. package/dist/sdk/capnweb/live-state/diff.d.ts +41 -0
  123. package/dist/sdk/capnweb/live-state/engine.d.ts +44 -0
  124. package/dist/sdk/capnweb/live-state/index.d.ts +41 -0
  125. package/dist/sdk/capnweb/live-state/protocol.d.ts +87 -0
  126. package/dist/sdk/capnweb/live-state/retain.d.ts +23 -0
  127. package/dist/sdk/capnweb/live-state/store.d.ts +20 -0
  128. package/dist/sdk/capnweb/live-state/types.d.ts +11 -0
  129. package/dist/sdk/capnweb/react.d.ts +45 -0
  130. package/dist/sdk/capnweb/react.mjs +316 -0
  131. package/dist/sdk/capnweb/react.mjs.map +1 -0
  132. package/dist/sdk/capnweb.mjs +4 -0
  133. package/dist/sdk/itx/react.d.ts +191 -0
  134. package/dist/sdk/itx/react.mjs +383 -0
  135. package/dist/sdk/itx/react.mjs.map +1 -0
  136. package/dist/sdk-DMB-IM11.mjs +933 -0
  137. package/dist/sdk-DMB-IM11.mjs.map +1 -0
  138. package/dist/sdk.d.ts +339 -0
  139. package/dist/sdk.mjs +2 -0
  140. package/dist/serve-itx.d.ts +46 -0
  141. package/dist/starter-apps/flake-dashboard/app-ref.d.ts +31 -0
  142. package/dist/starter-apps/flake-dashboard/configured-worker.mjs +1055 -0
  143. package/dist/starter-apps/flake-dashboard/configured-worker.mjs.map +1 -0
  144. package/dist/starter-apps/flake-dashboard/contract.d.ts +4839 -0
  145. package/dist/starter-apps/flake-dashboard/contract.mjs +2 -0
  146. package/dist/starter-apps/flake-dashboard/index.d.ts +17 -0
  147. package/dist/starter-apps/flake-dashboard/index.mjs +56 -0
  148. package/dist/starter-apps/flake-dashboard/index.mjs.map +1 -0
  149. package/dist/starter-apps/flake-dashboard/worker.d.ts +4607 -0
  150. package/dist/starter-apps/github-ai-linter/ai-linter.d.ts +8914 -0
  151. package/dist/starter-apps/github-ai-linter/configured-worker.mjs +17987 -0
  152. package/dist/starter-apps/github-ai-linter/configured-worker.mjs.map +1 -0
  153. package/dist/starter-apps/github-ai-linter/contract.d.ts +9193 -0
  154. package/dist/starter-apps/github-ai-linter/index.d.ts +10 -0
  155. package/dist/starter-apps/github-ai-linter/index.mjs +36 -0
  156. package/dist/starter-apps/github-ai-linter/index.mjs.map +1 -0
  157. package/dist/starter-apps/github-ai-linter/prompt.d.ts +13 -0
  158. package/dist/starter-apps/github-ai-linter/review-bot.d.ts +808 -0
  159. package/dist/starter-apps/github-ai-linter/rules.d.ts +34 -0
  160. package/dist/starter-apps/github-ai-linter/worker-ref.d.ts +19 -0
  161. package/dist/starter-apps/github-ai-linter/worker.d.ts +19 -0
  162. package/dist/starter-apps/github-ai-linter/worker.mjs +947 -0
  163. package/dist/starter-apps/github-ai-linter/worker.mjs.map +1 -0
  164. package/dist/starter-apps/guestbook/app-ref.d.ts +27 -0
  165. package/dist/starter-apps/guestbook/client.d.ts +7 -0
  166. package/dist/starter-apps/guestbook/client.mjs +59 -0
  167. package/dist/starter-apps/guestbook/configured-worker.mjs +205 -0
  168. package/dist/starter-apps/guestbook/configured-worker.mjs.map +1 -0
  169. package/dist/starter-apps/guestbook/index.d.ts +9 -0
  170. package/dist/starter-apps/guestbook/index.mjs +31 -0
  171. package/dist/starter-apps/guestbook/index.mjs.map +1 -0
  172. package/dist/starter-apps/guestbook/processor.d.ts +2267 -0
  173. package/dist/starter-apps/guestbook/worker.d.ts +26 -0
  174. package/dist/starter-apps/guestbook/worker.mjs +191 -0
  175. package/dist/starter-apps/guestbook/worker.mjs.map +1 -0
  176. package/dist/starter-apps/media/configured-worker.mjs +577 -0
  177. package/dist/starter-apps/media/configured-worker.mjs.map +1 -0
  178. package/dist/starter-apps/media/index.mjs +36 -0
  179. package/dist/starter-apps/media/index.mjs.map +1 -0
  180. package/dist/starter-apps/media/ref.mjs +20 -0
  181. package/dist/starter-apps/media/ref.mjs.map +1 -0
  182. package/dist/starter-apps/media/worker.mjs +579 -0
  183. package/dist/starter-apps/media/worker.mjs.map +1 -0
  184. package/dist/starter-apps/notes/configured-worker.mjs +6134 -0
  185. package/dist/starter-apps/notes/configured-worker.mjs.map +1 -0
  186. package/dist/starter-apps/notes/index.mjs +23 -0
  187. package/dist/starter-apps/notes/index.mjs.map +1 -0
  188. package/dist/starter-apps/notes/ref.mjs +21 -0
  189. package/dist/starter-apps/notes/ref.mjs.map +1 -0
  190. package/dist/starter-apps/notes/worker.mjs +427 -0
  191. package/dist/starter-apps/notes/worker.mjs.map +1 -0
  192. package/dist/starter-apps/todo/client.mjs +59 -0
  193. package/dist/starter-apps/todo/configured-worker.mjs +2864 -0
  194. package/dist/starter-apps/todo/configured-worker.mjs.map +1 -0
  195. package/dist/starter-apps/todo/index.d.ts +8 -0
  196. package/dist/starter-apps/todo/index.mjs +29 -0
  197. package/dist/starter-apps/todo/index.mjs.map +1 -0
  198. package/dist/stream-processor-keepalive-DAQTP6m3.mjs +2082 -0
  199. package/dist/stream-processor-keepalive-DAQTP6m3.mjs.map +1 -0
  200. package/dist/usingCtx-inzbY1Qz.mjs +57 -0
  201. package/dist/usingCtx-mZx5nsAW.mjs +11800 -0
  202. package/dist/usingCtx-mZx5nsAW.mjs.map +1 -0
  203. package/dist/worker-ref-DZxPDmb_.mjs +390 -0
  204. package/dist/worker-ref-DZxPDmb_.mjs.map +1 -0
  205. package/menubar/Iterate.entitlements +12 -0
  206. package/menubar/Iterate.swift +914 -0
  207. package/menubar/IterateIcon.swift +145 -0
  208. package/menubar/README.md +28 -0
  209. package/menubar/build-menubar-app.sh +59 -0
  210. package/package.json +235 -18
  211. package/dist/cli-DMS4kJph.mjs +0 -868
  212. package/dist/cli-DMS4kJph.mjs.map +0 -1
  213. package/dist/config-DtnR7Lv7.mjs +0 -170
  214. package/dist/config-DtnR7Lv7.mjs.map +0 -1
  215. package/dist/index.d.mts.map +0 -1
  216. package/dist/stream-tui/agent-chat-terminal.d.mts +0 -1
  217. package/dist/stream-tui/agent-chat-terminal.mjs +0 -933
  218. package/dist/stream-tui/agent-chat-terminal.mjs.map +0 -1
@@ -0,0 +1,6 @@
1
+ export declare function openSocketWithRetry(url: string | URL, options?: {
2
+ delaysMs?: readonly number[];
3
+ /** the constructor to use — a test's fake, `WebSocket` otherwise */
4
+ WebSocket?: typeof WebSocket;
5
+ sleep?: (ms: number) => Promise<void>;
6
+ }): Promise<WebSocket>;
@@ -0,0 +1,156 @@
1
+ import { applyPatch } from "./lib.mjs";
2
+ import { z } from "zod";
3
+ //#region src/next/client/live-state.ts
4
+ /** The delta as it arrives over the wire — PARSED, never cast: `from`/`to` MUST be real numbers (a
5
+ * non-numeric rev would poison the held revision and silently wedge every later frame), and each
6
+ * patch op is a known RFC-6902-subset shape. A frame that fails this heals through the seed door
7
+ * rather than being applied — the same recovery the store already runs on a revision gap. */
8
+ const LiveStateDeltaMessage = z.object({
9
+ key: z.string(),
10
+ from: z.number(),
11
+ to: z.number(),
12
+ patch: z.array(z.union([
13
+ z.object({
14
+ op: z.literal("add"),
15
+ path: z.string(),
16
+ value: z.unknown()
17
+ }),
18
+ z.object({
19
+ op: z.literal("replace"),
20
+ path: z.string(),
21
+ value: z.unknown()
22
+ }),
23
+ z.object({
24
+ op: z.literal("remove"),
25
+ path: z.string()
26
+ })
27
+ ])).nullable()
28
+ });
29
+ function createLiveStateStore() {
30
+ let held = {
31
+ rev: null,
32
+ state: void 0
33
+ };
34
+ const listeners = /* @__PURE__ */ new Set();
35
+ const notify = () => listeners.forEach((l) => l());
36
+ return {
37
+ get: () => held.state,
38
+ rev: () => held.rev,
39
+ subscribe: (listener) => {
40
+ listeners.add(listener);
41
+ return () => void listeners.delete(listener);
42
+ },
43
+ seed: (seed) => {
44
+ if (held.rev !== null && seed.rev < held.rev) return;
45
+ held = {
46
+ rev: seed.rev,
47
+ state: seed.state
48
+ };
49
+ notify();
50
+ },
51
+ apply: (delta, resync) => {
52
+ if (held.rev !== null && delta.to <= held.rev) return;
53
+ if (delta.from !== held.rev || !delta.patch) {
54
+ resync();
55
+ return;
56
+ }
57
+ held = {
58
+ rev: delta.to,
59
+ state: applyPatch(held.state, delta.patch)
60
+ };
61
+ notify();
62
+ }
63
+ };
64
+ }
65
+ /** Subscribe to a producer's live state and reduce it into a store. `door` reads the seed
66
+ * (`itx.invoke("itx.facets.get('slug').liveSnapshot()")` for a processor, or a mini-app's
67
+ * own `state()` method). Subscribe happens BEFORE the first seed, so a delta racing the seed just
68
+ * triggers one door re-read — never a lost update. Gap heals are SINGLE-FLIGHT (a burst of gapped
69
+ * frames triggers one door read, not one per frame); a failed heal is reported through `onResync`
70
+ * and retried by the next delivered delta (its `from` still mismatches, so it re-triggers). */
71
+ async function connectLiveState(itx, opts) {
72
+ const store = createLiveStateStore();
73
+ let healing = false;
74
+ let healWantedAgain = false;
75
+ let disposed = false;
76
+ const reseed = () => {
77
+ if (disposed) return;
78
+ if (healing) {
79
+ healWantedAgain = true;
80
+ return;
81
+ }
82
+ healing = true;
83
+ const settled = () => {
84
+ healing = false;
85
+ if (disposed || !healWantedAgain) return;
86
+ healWantedAgain = false;
87
+ reseed();
88
+ };
89
+ opts.door().then((s) => {
90
+ if (!disposed) {
91
+ store.seed(s);
92
+ opts.onResync?.("healed");
93
+ }
94
+ settled();
95
+ }, (e) => {
96
+ if (!disposed) opts.onResync?.(e instanceof Error ? e : new Error(String(e)));
97
+ settled();
98
+ });
99
+ };
100
+ const subscription = await itx.subscribe({
101
+ name: opts.name,
102
+ consumes: ["events.iterate.com/live-state/changed"],
103
+ target: (events) => {
104
+ if (disposed) return;
105
+ for (const e of events) {
106
+ let parsed;
107
+ try {
108
+ parsed = LiveStateDeltaMessage.safeParse(JSON.parse(JSON.stringify(e.payload)));
109
+ } catch {
110
+ parsed = void 0;
111
+ }
112
+ if (!parsed?.success) {
113
+ reseed();
114
+ continue;
115
+ }
116
+ if (parsed.data.key !== opts.key) continue;
117
+ try {
118
+ store.apply(parsed.data, reseed);
119
+ } catch {
120
+ reseed();
121
+ }
122
+ }
123
+ }
124
+ });
125
+ try {
126
+ const seed = opts.door();
127
+ const { signal } = opts;
128
+ const aborted = signal && new Promise((_, reject) => {
129
+ const abort = () => reject(signal.reason ?? /* @__PURE__ */ new Error("connectLiveState: aborted while the first seed was pending"));
130
+ if (signal.aborted) abort();
131
+ else signal.addEventListener("abort", abort, { once: true });
132
+ });
133
+ if (aborted) seed.catch(() => void 0);
134
+ store.seed(await (aborted ? Promise.race([seed, aborted]) : seed));
135
+ } catch (error) {
136
+ disposed = true;
137
+ try {
138
+ subscription[Symbol.dispose]();
139
+ } catch {}
140
+ throw error;
141
+ }
142
+ return {
143
+ store,
144
+ async dispose() {
145
+ if (disposed) return;
146
+ disposed = true;
147
+ try {
148
+ subscription[Symbol.dispose]();
149
+ } catch {}
150
+ }
151
+ };
152
+ }
153
+ //#endregion
154
+ export { connectLiveState, createLiveStateStore };
155
+
156
+ //# sourceMappingURL=client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.mjs","names":[],"sources":["../../src/next/client/live-state.ts"],"sourcesContent":["// client/live-state.ts — THE CLIENT HALF of live state (`iterate/next/client`), framework-free, for\n// browsers and node test clients. Two concepts:\n// live state store — `createLiveStateStore`: the pure reduce — seed through the door, apply each delta, heal on a gap\n// live state client — `connectLiveState`: wire an itx session's `subscribe` + a seed door to the store\n\nimport { z } from \"zod\";\nimport { applyPatch, type PatchOp } from \"../lib.ts\";\n\n// ── live state store ── THE CLIENT HALF of live state, for browsers and node test clients.\n// Adapted from apps/os's `createLiveStateStore` (packages/iterate/src/sdk/capnweb/live-state), kept\n// deliberately tiny, and pointed at the CLEAN-ROOM wire instead of apps/os's in-band snapshot:\n//\n// • SEED through the producer's door — `{rev, state}` read via an RPC method (a processor's\n// `liveSnapshot()`, a mini-app's `state()`). apps/os reduces the first snapshot in-band on the\n// subscription; here the stream keeps no per-subscriber state, so the seed is a separate read.\n// • APPLY each `{key, from, to, patch}` delta the subscription delivers: a patch lands only when\n// its `from` matches the held rev; a mismatch means a missed delta (or a reborn producer's fresh\n// epoch) — resync by re-reading the door, exactly like apps/os's revision-gap resync.\n//\n// The patch format is lib.ts (an RFC-6902 subset), so this store shares ONE applyPatch with\n// the producer — no second diff implementation. No capnweb import: a caller wires the transport and\n// hands deltas in, so the same store backs a node test client and the React hook (client/demo.tsx).\n\n/** One live-state delta off the wire — the payload of an `events.iterate.com/live-state/changed`\n * ephemeral event, delivered raw to the subscriber. */\n/** `patch: null` = the change was too large to send — the rev moved, re-seed through the door. */\nexport type LiveStateDelta = { key: string; from: number; to: number; patch: PatchOp[] | null };\n\n/** The delta as it arrives over the wire — PARSED, never cast: `from`/`to` MUST be real numbers (a\n * non-numeric rev would poison the held revision and silently wedge every later frame), and each\n * patch op is a known RFC-6902-subset shape. A frame that fails this heals through the seed door\n * rather than being applied — the same recovery the store already runs on a revision gap. */\nconst LiveStateDeltaMessage: z.ZodType<LiveStateDelta> = z.object({\n key: z.string(),\n from: z.number(),\n to: z.number(),\n patch: z\n .array(\n z.union([\n z.object({ op: z.literal(\"add\"), path: z.string(), value: z.unknown() }),\n z.object({ op: z.literal(\"replace\"), path: z.string(), value: z.unknown() }),\n z.object({ op: z.literal(\"remove\"), path: z.string() }),\n ]),\n )\n .nullable(),\n});\n\n/** What the producer's seed door returns: the current revision paired with the current value. */\nexport type LiveStateSeed<S> = { rev: number; state: S };\n\nexport type LiveStateStore<S> = {\n /** The current value, or undefined until the first seed lands. */\n get(): S | undefined;\n /** The held revision, or null before the first seed. */\n rev(): number | null;\n /** Subscribe to changes (for React's useSyncExternalStore, or a test's await-loop). */\n subscribe(listener: () => void): () => void;\n /** Seed (or re-seed) from the door — the first paint, and the heal after a gap. */\n seed(seed: LiveStateSeed<S>): void;\n /** Reduce one delta in; on a revision gap call `resync` and hold the value until a fresh seed. */\n apply(delta: LiveStateDelta, resync: () => void): void;\n};\n\nexport function createLiveStateStore<S>(): LiveStateStore<S> {\n // `rev: null` until the first seed lands.\n let held: { rev: number | null; state: S | undefined } = { rev: null, state: undefined };\n const listeners = new Set<() => void>();\n const notify = () => listeners.forEach((l) => l());\n return {\n get: () => held.state,\n rev: () => held.rev,\n subscribe: (listener) => {\n listeners.add(listener);\n return () => void listeners.delete(listener);\n },\n seed: (seed) => {\n // MONOTONIC: a late-resolving OLDER door read must never move the store backwards past state\n // deltas have already advanced (a delta-triggered resync can race the initial seed). Revisions\n // are time-seeded epochs plus increments, so \"newer\" is numeric.\n if (held.rev !== null && seed.rev < held.rev) return;\n held = { rev: seed.rev, state: seed.state };\n notify();\n },\n apply: (delta, resync) => {\n // A delta at-or-behind the held rev is a duplicate/out-of-order frame — drop it silently.\n // (Epochs are minted from the clock, so a reborn producer's fresh chain sits numerically above\n // every rev an old chain handed out; a frame wholly behind us is genuinely old. The one\n // exception is a clock that regressed across a producer rebirth — accepted: the next applied\n // or gapped frame resyncs through the door anyway.)\n if (held.rev !== null && delta.to <= held.rev) return;\n // A gap (its `from` is not the held rev — including \"no seed yet\") means a missed delta or a\n // reborn epoch, and a `null` patch means the change was too large to send — either way re-read\n // the door instead of applying onto a diverged base.\n if (delta.from !== held.rev || !delta.patch) {\n resync();\n return;\n }\n held = { rev: delta.to, state: applyPatch(held.state as S, delta.patch) };\n notify();\n },\n };\n}\n\n// ── live state client ── wire an itx session's `subscribe` + a seed door to a LiveStateStore.\n// This is the whole cleanroom client: a subscription that consumes the one live-state event type\n// (`itx.subscribe({ target, consumes: [\"events.iterate.com/live-state/changed\"] })`) delivers every\n// key's deltas in batches; this filters the watched `key` and reduces each delta into the store; a\n// `door` thunk reads `{rev, state}` for the first paint and every gap heal. Transport lives here so\n// the store (client/live-state.ts) and the React hook stay pure.\n\n/** The slice of an itx session this needs — a capnweb `IterateContextRpcTarget` proxy satisfies it structurally:\n * `subscribe` hands back a DISPOSABLE handle (disposing it removes the subscription server-side). */\nexport type LiveStateItx = {\n subscribe(input: {\n name?: string;\n consumes?: string[];\n target: (events: unknown[], range: unknown) => void;\n }): Promise<{ [Symbol.dispose](): void }>;\n};\n\n/** A connected live-state subscription: the store rendering it, and the dispose that removes the\n * server-side subscription (the handle's disposer; the session's end does the same). */\nexport type LiveStateConnection<S> = {\n store: LiveStateStore<S>;\n /** Unsubscribe on the server and stop reducing deltas. Safe to call more than once. */\n dispose(): Promise<void>;\n};\n\n/** Subscribe to a producer's live state and reduce it into a store. `door` reads the seed\n * (`itx.invoke(\"itx.facets.get('slug').liveSnapshot()\")` for a processor, or a mini-app's\n * own `state()` method). Subscribe happens BEFORE the first seed, so a delta racing the seed just\n * triggers one door re-read — never a lost update. Gap heals are SINGLE-FLIGHT (a burst of gapped\n * frames triggers one door read, not one per frame); a failed heal is reported through `onResync`\n * and retried by the next delivered delta (its `from` still mismatches, so it re-triggers). */\nexport async function connectLiveState<S>(\n itx: LiveStateItx,\n opts: {\n key: string;\n name?: string;\n door: () => Promise<LiveStateSeed<S>>;\n /** Called after each gap heal attempt: \"healed\" on a fresh seed, the error when the door read\n * failed (the store keeps its last value; the next delta retries). */\n onResync?: (result: \"healed\" | Error) => void;\n /** Abort while the FIRST seed is still pending (a component unmounting): the row just configured\n * is recalled and the connect rejects — a door that never answers leaves nothing lent. */\n signal?: AbortSignal;\n },\n): Promise<LiveStateConnection<S>> {\n const store = createLiveStateStore<S>();\n let healing = false;\n let healWantedAgain = false; // a gap seen WHILE a heal was in flight: the seed may predate it\n let disposed = false;\n const reseed = () => {\n if (disposed) return;\n if (healing) {\n healWantedAgain = true;\n return;\n }\n healing = true;\n const settled = () => {\n healing = false;\n if (disposed || !healWantedAgain) return;\n healWantedAgain = false;\n reseed();\n };\n void opts.door().then(\n (s) => {\n if (!disposed) {\n store.seed(s);\n opts.onResync?.(\"healed\");\n }\n settled();\n },\n (e: unknown) => {\n if (!disposed) opts.onResync?.(e instanceof Error ? e : new Error(String(e)));\n settled();\n },\n );\n };\n const subscription = await itx.subscribe({\n name: opts.name,\n consumes: [\"events.iterate.com/live-state/changed\"],\n // A batch of live-state deltas (every key's); keep the watched key's. capnweb hands each event\n // as a live proxy value — deep-copy to a plain object before reducing.\n target: (events: unknown[]) => {\n if (disposed) return;\n for (const e of events) {\n // capnweb hands each event as a live proxy value — deep-copy to a plain object, then PARSE\n // the frame (never cast network data). The whole decode is guarded: an ABSENT payload makes\n // `JSON.parse(JSON.stringify(undefined))` throw before validation, and any throw here would\n // skip every later delta in the batch. A malformed OR undecodable frame heals via the door\n // instead of poisoning the held rev or escaping this callback.\n let parsed: ReturnType<(typeof LiveStateDeltaMessage)[\"safeParse\"]> | undefined;\n try {\n parsed = LiveStateDeltaMessage.safeParse(\n JSON.parse(JSON.stringify((e as { payload: unknown }).payload)),\n );\n } catch {\n parsed = undefined;\n }\n if (!parsed?.success) {\n reseed();\n continue;\n }\n if (parsed.data.key !== opts.key) continue;\n // `store.apply` runs `applyPatch`, which THROWS on a patch it refuses (a `/__proto__` path a\n // legitimate state with an own `__proto__` key produces, say). Contain it per frame: heal via\n // the door — which re-seeds the state DIRECTLY, no patch to reject — instead of escaping this\n // callback and skipping every later frame.\n try {\n store.apply(parsed.data, reseed);\n } catch {\n reseed();\n }\n }\n },\n });\n try {\n const seed = opts.door();\n const { signal } = opts;\n const aborted =\n signal &&\n new Promise<never>((_, reject) => {\n const abort = () =>\n reject(\n signal.reason ??\n new Error(\"connectLiveState: aborted while the first seed was pending\"),\n );\n if (signal.aborted) abort();\n else signal.addEventListener(\"abort\", abort, { once: true });\n });\n if (aborted) seed.catch(() => undefined); // the door may still settle after the abort — quietly\n store.seed(await (aborted ? Promise.race([seed, aborted]) : seed));\n } catch (error) {\n // The seed failed after the row was configured: recall it, or the server keeps delivering to a\n // callback no one holds (and the session's other rows wait behind it).\n disposed = true;\n try {\n subscription[Symbol.dispose]();\n } catch {\n // a dead session has already removed it\n }\n throw error;\n }\n return {\n store,\n async dispose() {\n if (disposed) return;\n disposed = true;\n try {\n subscription[Symbol.dispose](); // the server removes the row and recalls the lent callback\n } catch {\n // a dead session has already removed it — the socket close disposed every handle\n }\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ import { RpcTarget } from "capnweb";
2
+ /** One step: a property read (string) or a call (`[method, ...args]`). Args are plain JSON. The
3
+ * method `""` is the ANONYMOUS call — call the value itself: `itx.builtins.rpcStubs.get('cam')(1, 2)`
4
+ * is `["itx","builtins","rpcStubs",["get","cam"],["",1,2]]` — what a `provide(stub)` rule spells when
5
+ * the lent stub is called with args. */
6
+ export type ItxExpressionStep = string | [method: string, ...args: unknown[]];
7
+ /** An itx expression as data: the scope root (`itx`) then get/call steps. THE parsed form every door
8
+ * works on. */
9
+ export type ItxExpression = ItxExpressionStep[];
10
+ /** THE dispatch target, in EITHER codec half — a dotted string that starts with the scope root
11
+ * (`"itx.facets.get('core')"`) OR the parsed structured form (`["itx","facets",["get","core"]]`).
12
+ * Both carry call args (the string via `.method(args)`), and `normalizedItxExpression` normalizes
13
+ * either to the structured form — so either works wherever one works, at every door that dispatches. */
14
+ export type ItxExpressionInput = string | ItxExpression;
15
+ /** An itx-expression PREFIX — a rewrite rule's `match`: dotted names, any of which may be a call step
16
+ * PINNING literal args — `itx.ai.run` or `itx.ai.run('gpt-5')` or `itx.repo.get('main').files`. A
17
+ * pinned arg must equal the call's arg at that position for the rule to match, and is CONSUMED by
18
+ * the match (partial application): `itx.ai.run('gpt-5') ⇒ itx.openai.chat` makes
19
+ * `itx.ai.run('gpt-5', inputs)` into `itx.openai.chat(inputs)`. */
20
+ export type ItxExpressionPrefix = ItxExpression;
21
+ /** The name a step carries: the property itself, or a call step's method. */
22
+ export declare const itxExpressionStepName: (step: ItxExpressionStep | undefined) => string | undefined;
23
+ /** The merge entry's key — `...@` — read by rule 7. */
24
+ export declare const ITX_EXPRESSION_MERGE_KEY = "...@";
25
+ /** Is `value` the marker literal `{ "@": true }`? */
26
+ export declare const isItxExpressionHole: (value: unknown) => boolean;
27
+ /** Does `value` (a step, an arg tree, a whole expression) hold the marker or a merge entry anywhere? */
28
+ export declare function containsItxExpressionHole(value: unknown): boolean;
29
+ /** Parse the STRING half: dotted names + `.method(args)` calls (args JSON5-parsed); rejects reserved
30
+ * names + bare scope calls. `holes: true` — a rewrite rule's TARGET only — lexes `@` / `...@` into
31
+ * the marker literals; anywhere else a bare `@` is refused. */
32
+ export declare function parse(source: string, options?: {
33
+ holes?: boolean;
34
+ }): ItxExpression;
35
+ /** THE ONE NORMALIZING DOOR: either half, normalized to the array half and checked — a string is
36
+ * parsed (short by rule), an array is shape-checked in place. Every door that takes an
37
+ * `ItxExpressionInput` (the edge `invoke`, the resolver, the event builders, the prefix parser
38
+ * below) enters through it. */
39
+ export declare function normalizedItxExpression(input: ItxExpressionInput, options?: {
40
+ holes?: boolean;
41
+ }): ItxExpression;
42
+ /** Object args print with their keys SORTED, so two spellings of one object are one canonical string
43
+ * — one rewrite-rule row, one facet memo, one library connection memo (library.ts) — the way
44
+ * `jsonEqual` already matches them. A `JSON.stringify` / `JSON5.stringify` replacer. */
45
+ export declare const keySortedForPrint: (_key: string, value: unknown) => unknown;
46
+ /** Canonical stored form: dotted path + `.method(args)` calls (args `JSON5.stringify`d, object keys
47
+ * sorted). `holes: true` — a rewrite rule's TARGET only — spells the marker literals back as `@` /
48
+ * `...@`, and `parse(print(e, { holes: true }), { holes: true })` round-trips; without it the
49
+ * reserved literals print as the plain JSON5 they are, so a CALL that happens to carry `{ "@": true }`
50
+ * as data round-trips through `parse` (no holes) unchanged — the resolve/invoke law holds for it. */
51
+ export declare function print(expr: ItxExpression, options?: {
52
+ holes?: boolean;
53
+ }): string;
54
+ /** Parse an itx-expression prefix (either codec half) — `normalizedItxExpression` (so every step is
55
+ * an identifier that is not reserved, in either half) plus the two refusals only a PREFIX has: the
56
+ * anonymous call step (`f(x)(y)` — a prefix cannot call a result), and a call step with NO args,
57
+ * which pins nothing and is the same prefix as the plain name: spell `itx.ai.run`. */
58
+ export declare function parseItxExpressionPrefix(source: ItxExpressionInput): ItxExpressionPrefix;
59
+ /** THE ONE canonical spelling of an itx-expression prefix — the rewrite-rule table's key, what a lent
60
+ * stub is keyed by through `provide`'s sugar: parsed, then printed (dotted names; pinned args as JSON5
61
+ * literals). */
62
+ export declare function canonicalItxExpressionPrefix(source: ItxExpressionInput): string;
63
+ /** Register a pipelinable promise brand (the workerd entrypoint's two calls at boot). */
64
+ export declare function registerPipelinedRpcBrand(brand: abstract new (...args: never[]) => unknown): void;
65
+ /**
66
+ * THE step walk: property steps `Reflect.get` with the receiver carried; call steps `Reflect.apply`
67
+ * ON that receiver (detaching a method from a Workers-RPC receiver breaks it); an ordinary promise
68
+ * is awaited between steps, a branded one (PIPELINED_RPC_BRANDS, above) is not.
69
+ *
70
+ * ⚠️ DataCloneError LEARNING:
71
+ * invoke facet/RPC-stub methods with `Reflect.apply(fn, receiver, args)`, NEVER `stub[m].apply(stub,
72
+ * args)`. Reading `.apply` off an RPC stub's method proxy is a capnweb PIPELINED REMOTE PATH;
73
+ * calling it passes the stub as an argument, so workerd serializes it — and a Worker-Loader facet
74
+ * stub may never be serialized (`requireAllowsTransfer()` throws unconditionally) → `DataCloneError:
75
+ * Durable Object Facet stubs cannot be transferred between Workers`. Do not "simplify" this away.
76
+ */
77
+ export declare function walkSteps(start: {
78
+ value: unknown;
79
+ receiver: unknown;
80
+ }, steps: ItxExpression): Promise<{
81
+ value: unknown;
82
+ receiver: unknown;
83
+ }>;
84
+ /** Apply `args` to a resolved value on its carried receiver, or a LOUD error if it is not callable
85
+ * (never the silent arg-drop apps/os shipped). An `InvokeHandle` is NOT a JS function (a real
86
+ * RpcTarget so dotted access pipelines — the invoke handle section), so ROOT-calling it dispatches
87
+ * those args at its EMPTY path: `handle(events,range)` ⇒ the bare callback the handle fronts. The one
88
+ * bridge between "callable capability" and "pipelinable RpcTarget". */
89
+ export declare function callOn(value: unknown, receiver: unknown, args: unknown[]): Promise<unknown>;
90
+ /** Install the hop drawn in the header on a class's PROTOTYPE CHAIN, with the scope `root` (`["itx"]`
91
+ * for the edge context, `[]` for a handle). Call ONCE per class. Constructor inheritance is
92
+ * untouched — only `Class.prototype`'s parent link changes, and the hop forwards everything it does
93
+ * not intercept. */
94
+ export declare function installPrototypeInvokeFallback<T extends abstract new (...args: never[]) => object>(cls: T, root: readonly string[]): void;
95
+ /** A branded, pipelinable handle for a MID-CHAIN capability (`facets.get(name)`, `cd(path)`,
96
+ * `workers.get(spec)`, a lent stub) whose unknown dotted members reduce into ONE dispatch of the
97
+ * itx-expression STEPS relative to it; the constructor's `dispatch` routes those steps into the
98
+ * underlying object. Declared members (`invoke` / `applyRoot`) win over the fallback, so a
99
+ * capability cannot be named either — the two reserved words this wrapper adds. */
100
+ export declare class InvokeHandle extends RpcTarget {
101
+ #private;
102
+ constructor(dispatchItxExpressionSteps: (itxExpressionSteps: ItxExpression) => unknown);
103
+ /** THE reduce door the prototype hop dispatches onto; the expression is RELATIVE to this handle. */
104
+ invoke(itxExpressionSteps: ItxExpression): unknown;
105
+ /** Call the bare capability this handle fronts — the ANONYMOUS call step (`callOn` in the dispatch section
106
+ * uses it when a rewritten call's target IS a handle: `handle(events, range)`). */
107
+ applyRoot(args: unknown[]): unknown;
108
+ }
109
+ /** Walk itx-expression steps off a capnweb stub; the ANONYMOUS call step (`""`) calls the value
110
+ * itself (a bare function lent as a capability). NO await inside the loop: on a capnweb stub every
111
+ * step is a PIPELINED path, so an n-step chain costs ONE round trip, flushed by the caller's single
112
+ * await. A DIRECT call on the stub, never `.apply`: reading `.apply` off a capnweb stub's method is
113
+ * itself a pipelined remote path (`walkSteps`'s DataCloneError learning). Exported for the library
114
+ * tier, which may import this module only. */
115
+ export declare function walkStepsOnRpcStub(stub: unknown, steps: ItxExpression): unknown;
116
+ /** `itx.facets.get(name)` / `itx.facets.get(name, { source, className })` — a facet of this context. */
117
+ export declare class FacetHandle extends InvokeHandle {
118
+ }
119
+ /** A HANDLE ON THE WIRE IS THE EXPRESSION THAT NAMES IT. An `InvokeHandle` a context mints (`repos.get(path)`,
120
+ * `workspaces.get(path)`, `facets.get(name)`, `cd(path)`, `workers.get(spec)`) holds no state — it is a
121
+ * dispatch closure over a path — yet as a Workers-RPC result it would cross a hop as a LIVE stub whose
122
+ * session keeps the context's actor resident for as long as the holder keeps it (prd 2026-09-22: ~125
123
+ * such sessions parked around the clock). So the context's RPC door answers with THIS instead: the
124
+ * caller's own expression, which from the caller's root denotes the same handle; the caller mints its
125
+ * own handle over it (`materializeItxHandleReference`), and every later verb is one whole call the
126
+ * context resolves from scratch. Nothing outlives a call. A lent client stub (`RpcStubHandle`) is the
127
+ * one handle that IS live and crosses as itself. */
128
+ export declare const ITX_HANDLE_REFERENCE_KEY = "$itxHandleExpression";
129
+ export type ItxHandleReference = {
130
+ [ITX_HANDLE_REFERENCE_KEY]: ItxExpression;
131
+ };
132
+ export declare const isItxHandleReference: (value: unknown) => value is ItxHandleReference;
133
+ /** What a context's RPC door hands back for `expression`'s result: a reference when the result is a
134
+ * path-shaped handle (an `InvokeHandle` that is not a lent stub) or a reference from a hop below —
135
+ * re-rooted, since `expression` is how THIS caller reached it — else nothing (the result crosses as it
136
+ * is). Runtime args that fold into a terminal NAME fold here exactly as the resolver folds them, so the
137
+ * reference is the call the resolver ran; args left over apply to the value and never name a handle. */
138
+ export declare function itxHandleReferenceOf(result: unknown, expression: ItxExpression, args?: unknown[]): ItxHandleReference | undefined;
139
+ /** The holder's side: a reference becomes a handle of the HOLDER's own whose every dotted call is one
140
+ * whole expression through `invoke` — the reference's expression plus the steps. Anything else passes
141
+ * through untouched. The proxy hands relative steps; a caller's own `.invoke("itx.whoami()")` is a
142
+ * whole call, spelled from the root. */
143
+ export declare function materializeItxHandleReference(result: unknown, invoke: (expression: ItxExpression) => unknown): unknown;
144
+ /** `itx.rpcStubs.get(key)` — a live stub lent to the registry. */
145
+ export declare class RpcStubHandle extends InvokeHandle {
146
+ }