@vendoai/apps 0.4.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 (203) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +8 -0
  3. package/dist/adapter-conformance.d.ts +48 -0
  4. package/dist/adapter-conformance.d.ts.map +1 -0
  5. package/dist/adapter-conformance.js +196 -0
  6. package/dist/adapter-conformance.js.map +1 -0
  7. package/dist/agent-tools.d.ts +10 -0
  8. package/dist/agent-tools.d.ts.map +1 -0
  9. package/dist/agent-tools.js +252 -0
  10. package/dist/agent-tools.js.map +1 -0
  11. package/dist/app-data.d.ts +23 -0
  12. package/dist/app-data.d.ts.map +1 -0
  13. package/dist/app-data.js +129 -0
  14. package/dist/app-data.js.map +1 -0
  15. package/dist/app-token.d.ts +24 -0
  16. package/dist/app-token.d.ts.map +1 -0
  17. package/dist/app-token.js +61 -0
  18. package/dist/app-token.js.map +1 -0
  19. package/dist/audit.d.ts +11 -0
  20. package/dist/audit.d.ts.map +1 -0
  21. package/dist/audit.js +19 -0
  22. package/dist/audit.js.map +1 -0
  23. package/dist/automation-plan.d.ts +43 -0
  24. package/dist/automation-plan.d.ts.map +1 -0
  25. package/dist/automation-plan.js +212 -0
  26. package/dist/automation-plan.js.map +1 -0
  27. package/dist/bench/client.d.ts +43 -0
  28. package/dist/bench/client.d.ts.map +1 -0
  29. package/dist/bench/client.js +129 -0
  30. package/dist/bench/client.js.map +1 -0
  31. package/dist/bench/fixtures.d.ts +42 -0
  32. package/dist/bench/fixtures.d.ts.map +1 -0
  33. package/dist/bench/fixtures.js +146 -0
  34. package/dist/bench/fixtures.js.map +1 -0
  35. package/dist/bench/judge.d.ts +9 -0
  36. package/dist/bench/judge.d.ts.map +1 -0
  37. package/dist/bench/judge.js +71 -0
  38. package/dist/bench/judge.js.map +1 -0
  39. package/dist/bench/metrics.d.ts +32 -0
  40. package/dist/bench/metrics.d.ts.map +1 -0
  41. package/dist/bench/metrics.js +172 -0
  42. package/dist/bench/metrics.js.map +1 -0
  43. package/dist/bench/prompts.d.ts +17 -0
  44. package/dist/bench/prompts.d.ts.map +1 -0
  45. package/dist/bench/prompts.js +100 -0
  46. package/dist/bench/prompts.js.map +1 -0
  47. package/dist/bench/report.d.ts +43 -0
  48. package/dist/bench/report.d.ts.map +1 -0
  49. package/dist/bench/report.js +74 -0
  50. package/dist/bench/report.js.map +1 -0
  51. package/dist/bench/runner.d.ts +15 -0
  52. package/dist/bench/runner.d.ts.map +1 -0
  53. package/dist/bench/runner.js +26 -0
  54. package/dist/bench/runner.js.map +1 -0
  55. package/dist/bench/toolfork.d.ts +18 -0
  56. package/dist/bench/toolfork.d.ts.map +1 -0
  57. package/dist/bench/toolfork.js +125 -0
  58. package/dist/bench/toolfork.js.map +1 -0
  59. package/dist/box-agent.d.ts +78 -0
  60. package/dist/box-agent.d.ts.map +1 -0
  61. package/dist/box-agent.js +137 -0
  62. package/dist/box-agent.js.map +1 -0
  63. package/dist/box-env.d.ts +26 -0
  64. package/dist/box-env.d.ts.map +1 -0
  65. package/dist/box-env.js +52 -0
  66. package/dist/box-env.js.map +1 -0
  67. package/dist/call.d.ts +23 -0
  68. package/dist/call.d.ts.map +1 -0
  69. package/dist/call.js +45 -0
  70. package/dist/call.js.map +1 -0
  71. package/dist/cloud.d.ts +4917 -0
  72. package/dist/cloud.d.ts.map +1 -0
  73. package/dist/cloud.js +16 -0
  74. package/dist/cloud.js.map +1 -0
  75. package/dist/e2b/index.d.ts +30 -0
  76. package/dist/e2b/index.d.ts.map +1 -0
  77. package/dist/e2b/index.js +273 -0
  78. package/dist/e2b/index.js.map +1 -0
  79. package/dist/egress-approval.d.ts +73 -0
  80. package/dist/egress-approval.d.ts.map +1 -0
  81. package/dist/egress-approval.js +74 -0
  82. package/dist/egress-approval.js.map +1 -0
  83. package/dist/engine.d.ts +188 -0
  84. package/dist/engine.d.ts.map +1 -0
  85. package/dist/engine.js +1507 -0
  86. package/dist/engine.js.map +1 -0
  87. package/dist/fn.d.ts +22 -0
  88. package/dist/fn.d.ts.map +1 -0
  89. package/dist/fn.js +108 -0
  90. package/dist/fn.js.map +1 -0
  91. package/dist/history.d.ts +21 -0
  92. package/dist/history.d.ts.map +1 -0
  93. package/dist/history.js +158 -0
  94. package/dist/history.js.map +1 -0
  95. package/dist/inclient.d.ts +48 -0
  96. package/dist/inclient.d.ts.map +1 -0
  97. package/dist/inclient.js +68 -0
  98. package/dist/inclient.js.map +1 -0
  99. package/dist/index.d.ts +24 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +25 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/interchange.d.ts +17 -0
  104. package/dist/interchange.d.ts.map +1 -0
  105. package/dist/interchange.js +133 -0
  106. package/dist/interchange.js.map +1 -0
  107. package/dist/machine-lifecycle.d.ts +102 -0
  108. package/dist/machine-lifecycle.d.ts.map +1 -0
  109. package/dist/machine-lifecycle.js +360 -0
  110. package/dist/machine-lifecycle.js.map +1 -0
  111. package/dist/manifest.d.ts +42 -0
  112. package/dist/manifest.d.ts.map +1 -0
  113. package/dist/manifest.js +53 -0
  114. package/dist/manifest.js.map +1 -0
  115. package/dist/open.d.ts +45 -0
  116. package/dist/open.d.ts.map +1 -0
  117. package/dist/open.js +245 -0
  118. package/dist/open.js.map +1 -0
  119. package/dist/parked-action.d.ts +51 -0
  120. package/dist/parked-action.d.ts.map +1 -0
  121. package/dist/parked-action.js +29 -0
  122. package/dist/parked-action.js.map +1 -0
  123. package/dist/persistence.d.ts +41 -0
  124. package/dist/persistence.d.ts.map +1 -0
  125. package/dist/persistence.js +86 -0
  126. package/dist/persistence.js.map +1 -0
  127. package/dist/pins.d.ts +231 -0
  128. package/dist/pins.d.ts.map +1 -0
  129. package/dist/pins.js +213 -0
  130. package/dist/pins.js.map +1 -0
  131. package/dist/pipeline.d.ts +142 -0
  132. package/dist/pipeline.d.ts.map +1 -0
  133. package/dist/pipeline.js +1014 -0
  134. package/dist/pipeline.js.map +1 -0
  135. package/dist/prewired-schema.d.ts +16 -0
  136. package/dist/prewired-schema.d.ts.map +1 -0
  137. package/dist/prewired-schema.js +48 -0
  138. package/dist/prewired-schema.js.map +1 -0
  139. package/dist/redaction.d.ts +13 -0
  140. package/dist/redaction.d.ts.map +1 -0
  141. package/dist/redaction.js +67 -0
  142. package/dist/redaction.js.map +1 -0
  143. package/dist/runtime.d.ts +463 -0
  144. package/dist/runtime.d.ts.map +1 -0
  145. package/dist/runtime.js +1715 -0
  146. package/dist/runtime.js.map +1 -0
  147. package/dist/sandbox.d.ts +90 -0
  148. package/dist/sandbox.d.ts.map +1 -0
  149. package/dist/sandbox.js +2 -0
  150. package/dist/sandbox.js.map +1 -0
  151. package/dist/schedules.d.ts +89 -0
  152. package/dist/schedules.d.ts.map +1 -0
  153. package/dist/schedules.js +334 -0
  154. package/dist/schedules.js.map +1 -0
  155. package/dist/secret-exposure.d.ts +55 -0
  156. package/dist/secret-exposure.d.ts.map +1 -0
  157. package/dist/secret-exposure.js +53 -0
  158. package/dist/secret-exposure.js.map +1 -0
  159. package/dist/ship-diff.d.ts +47 -0
  160. package/dist/ship-diff.d.ts.map +1 -0
  161. package/dist/ship-diff.js +39 -0
  162. package/dist/ship-diff.js.map +1 -0
  163. package/dist/testing/fake-box.d.ts +67 -0
  164. package/dist/testing/fake-box.d.ts.map +1 -0
  165. package/dist/testing/fake-box.js +166 -0
  166. package/dist/testing/fake-box.js.map +1 -0
  167. package/dist/testing/fake-sandbox-v2.d.ts +59 -0
  168. package/dist/testing/fake-sandbox-v2.d.ts.map +1 -0
  169. package/dist/testing/fake-sandbox-v2.js +121 -0
  170. package/dist/testing/fake-sandbox-v2.js.map +1 -0
  171. package/dist/testing/fake-sandbox.d.ts +94 -0
  172. package/dist/testing/fake-sandbox.d.ts.map +1 -0
  173. package/dist/testing/fake-sandbox.js +239 -0
  174. package/dist/testing/fake-sandbox.js.map +1 -0
  175. package/dist/testing/guard-fixture.d.ts +19 -0
  176. package/dist/testing/guard-fixture.d.ts.map +1 -0
  177. package/dist/testing/guard-fixture.js +134 -0
  178. package/dist/testing/guard-fixture.js.map +1 -0
  179. package/dist/testing/index.d.ts +8 -0
  180. package/dist/testing/index.d.ts.map +1 -0
  181. package/dist/testing/index.js +8 -0
  182. package/dist/testing/index.js.map +1 -0
  183. package/dist/testing/memory-store.d.ts +5 -0
  184. package/dist/testing/memory-store.d.ts.map +1 -0
  185. package/dist/testing/memory-store.js +4 -0
  186. package/dist/testing/memory-store.js.map +1 -0
  187. package/dist/testing/scripted-model.d.ts +32 -0
  188. package/dist/testing/scripted-model.d.ts.map +1 -0
  189. package/dist/testing/scripted-model.js +112 -0
  190. package/dist/testing/scripted-model.js.map +1 -0
  191. package/dist/testing/seed-app-row.d.ts +4 -0
  192. package/dist/testing/seed-app-row.d.ts.map +1 -0
  193. package/dist/testing/seed-app-row.js +7 -0
  194. package/dist/testing/seed-app-row.js.map +1 -0
  195. package/dist/unified-diff.d.ts +13 -0
  196. package/dist/unified-diff.d.ts.map +1 -0
  197. package/dist/unified-diff.js +127 -0
  198. package/dist/unified-diff.js.map +1 -0
  199. package/dist/version-hash.d.ts +9 -0
  200. package/dist/version-hash.d.ts.map +1 -0
  201. package/dist/version-hash.js +12 -0
  202. package/dist/version-hash.js.map +1 -0
  203. package/package.json +84 -0
package/dist/open.js ADDED
@@ -0,0 +1,245 @@
1
+ import { VENDO_TREE_FORMAT_V2, VendoError, validateTreeV2, } from "@vendoai/core";
2
+ import { detectPinDrift, pinComponentName } from "./pins.js";
3
+ const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
4
+ // Query paths come from the app document — model-written or imported from an untrusted
5
+ // .vendoapp artifact — so a pointer segment that names a prototype key must never resolve.
6
+ const UNSAFE_KEYS = new Set(["__proto__", "constructor", "prototype"]);
7
+ const decodePointer = (pointer) => {
8
+ if (pointer === "")
9
+ return [];
10
+ if (!pointer.startsWith("/"))
11
+ return null;
12
+ const encoded = pointer.slice(1).split("/");
13
+ if (encoded.some((part) => /~(?![01])/u.test(part)))
14
+ return null;
15
+ const parts = encoded.map((part) => part.replaceAll("~1", "/").replaceAll("~0", "~"));
16
+ if (parts.some((part) => UNSAFE_KEYS.has(part)))
17
+ return null;
18
+ return parts;
19
+ };
20
+ const arrayIndex = (part) => /^(0|[1-9][0-9]*)$/.test(part) ? Number(part) : null;
21
+ const child = (target, part) => {
22
+ if (Array.isArray(target)) {
23
+ const index = arrayIndex(part);
24
+ return index === null ? undefined : target[index];
25
+ }
26
+ return target[part];
27
+ };
28
+ const assignChild = (target, part, value) => {
29
+ if (Array.isArray(target)) {
30
+ const index = arrayIndex(part);
31
+ if (index === null || !Number.isSafeInteger(index) || index > target.length)
32
+ return false;
33
+ target[index] = value;
34
+ return true;
35
+ }
36
+ target[part] = value;
37
+ return true;
38
+ };
39
+ const setQueryData = (data, pointer, value) => {
40
+ const parts = decodePointer(pointer);
41
+ if (parts === null)
42
+ return false;
43
+ if (parts.length === 0) {
44
+ if (!isObject(value))
45
+ return false;
46
+ const replacement = structuredClone(value);
47
+ for (const key of Object.keys(data))
48
+ delete data[key];
49
+ for (const [key, item] of Object.entries(replacement)) {
50
+ if (!UNSAFE_KEYS.has(key))
51
+ data[key] = item;
52
+ }
53
+ return true;
54
+ }
55
+ let target = data;
56
+ for (let index = 0; index < parts.length - 1; index += 1) {
57
+ const part = parts[index];
58
+ const next = parts[index + 1];
59
+ if (part === undefined || next === undefined)
60
+ return false;
61
+ let current = child(target, part);
62
+ if (!isObject(current) && !Array.isArray(current)) {
63
+ current = arrayIndex(next) === null ? {} : [];
64
+ if (!assignChild(target, part, current))
65
+ return false;
66
+ }
67
+ target = current;
68
+ }
69
+ const final = parts.at(-1);
70
+ if (final === undefined)
71
+ return false;
72
+ return assignChild(target, final, structuredClone(value));
73
+ };
74
+ /** A v2 query's result lives at `"/" + name` by definition (v2 spec §2). */
75
+ const queryPointer = (query) => `/${query.name}`;
76
+ /**
77
+ * Start queries as soon as they appear. Results may arrive in any order, but
78
+ * every emitted/final data model is rebuilt in source order so later queries
79
+ * retain the same deterministic last-write behavior as the old serial loop.
80
+ */
81
+ export const createProgressiveQueryResolver = (caller, app, ctx, onData) => {
82
+ const states = [];
83
+ const pending = new Set();
84
+ let baseData = {};
85
+ let resolvedData = {};
86
+ const recompute = (notify = true) => {
87
+ const data = structuredClone(baseData);
88
+ for (const state of states) {
89
+ if (!state.settled || state.result === undefined)
90
+ continue;
91
+ if (state.result.status !== "ok")
92
+ continue;
93
+ setQueryData(data, queryPointer(state.query), state.result.output);
94
+ }
95
+ resolvedData = data;
96
+ if (notify)
97
+ onData?.(structuredClone(data));
98
+ };
99
+ const start = (query, index) => {
100
+ const key = JSON.stringify(query);
101
+ const state = { key, query: structuredClone(query), settled: false };
102
+ states[index] = state;
103
+ const task = caller
104
+ .callQuery(app, query.tool, query.input ?? {}, ctx)
105
+ .then((result) => {
106
+ if (states[index] !== state)
107
+ return;
108
+ state.result = result;
109
+ state.settled = true;
110
+ recompute();
111
+ })
112
+ .catch((error) => {
113
+ if (states[index] !== state)
114
+ return;
115
+ state.settled = true;
116
+ state.error = error;
117
+ recompute();
118
+ });
119
+ pending.add(task);
120
+ void task.finally(() => pending.delete(task));
121
+ };
122
+ return {
123
+ update(tree) {
124
+ baseData = structuredClone(tree.data ?? {});
125
+ const queries = tree.queries ?? [];
126
+ if (states.length > queries.length)
127
+ states.length = queries.length;
128
+ queries.forEach((query, index) => {
129
+ const key = JSON.stringify(query);
130
+ if (states[index]?.key !== key)
131
+ start(query, index);
132
+ });
133
+ recompute(false);
134
+ },
135
+ async complete() {
136
+ while (pending.size > 0)
137
+ await Promise.all([...pending]);
138
+ recompute(false);
139
+ return structuredClone(resolvedData);
140
+ },
141
+ };
142
+ };
143
+ /**
144
+ * 06-apps §§8–9 — the in-client venue field and the pin-drift report are
145
+ * SERVER-AUTHORITATIVE. The stored tree is model-written or imported from an
146
+ * untrusted `.vendoapp`, so a forged `inClient` or `pinDrift` riding the
147
+ * document must never reach the client: strip both before the verified
148
+ * verdict and the computed drift (when any) are attached — and strip at
149
+ * persist time too (the runtime shares this helper), streamed or at rest.
150
+ */
151
+ export const stripServerAuthoritativeFields = (payload) => {
152
+ delete payload.inClient;
153
+ delete payload.pinDrift;
154
+ return payload;
155
+ };
156
+ /** 06-apps §8 — jail furnishing for forked pins rides inside the tagged tree
157
+ * payload (UIPayload is forward-compatible). */
158
+ const attachPinFurnishings = (tree, app, pinBaselines) => {
159
+ const furnishings = Object.fromEntries((app.pins ?? []).flatMap((pin) => {
160
+ const baseline = pinBaselines.find((candidate) => candidate.slot === pin.slot && candidate.hash === pin.base);
161
+ if (baseline === undefined)
162
+ return [];
163
+ return [[pinComponentName(pin.slot), {
164
+ ...(baseline.sourceImports === undefined ? {} : { sourceImports: structuredClone(baseline.sourceImports) }),
165
+ ...(baseline.subSources === undefined ? {} : { subSources: structuredClone(baseline.subSources) }),
166
+ ...(baseline.sampleProps === undefined ? {} : { sampleProps: structuredClone(baseline.sampleProps) }),
167
+ ...(baseline.styles === undefined ? {} : { styles: structuredClone(baseline.styles) }),
168
+ }]];
169
+ }));
170
+ if (Object.keys(furnishings).length > 0) {
171
+ tree.furnishings = furnishings;
172
+ }
173
+ };
174
+ /** Wave 4 — the one refusal for every layer-3 path while the flag is off. */
175
+ export const servedAppsDisabledError = () => new VendoError("not-implemented", "served (layer-3) app surfaces are experimental and disabled for this project — enable them with createVendo({ apps: { experimentalServedApps: true } }) (AppsConfig.experimentalServedApps) to let a machine serve the app surface", { experiment: "servedApps", flag: "experimentalServedApps" });
176
+ /** Wave 9 — the one refusal for NEW layer-2 box work while machines are off
177
+ * (same house pattern as {@link servedAppsDisabledError}). The escalation
178
+ * ladder only lands here when no automation can express the request, so the
179
+ * message says exactly that instead of silently degrading to a broken
180
+ * automation. Already-provisioned machines are never gated by this — only
181
+ * new graduation/provisioning is. */
182
+ export const machinesDisabledError = () => new VendoError("not-implemented", "this request needs custom server code (a box machine), and machine-backed (layer-2) execution is experimental and disabled for this project — enable it with createVendo({ apps: { experimentalMachines: true } }) (AppsConfig.experimentalMachines); scheduled/triggered work that tools can express rides the automations engine without it", { experiment: "machines", flag: "experimentalMachines" });
183
+ /** 06-apps §§1–2 — construct the open surface. */
184
+ export const createAppOpener = (caller, pinBaselines = [], inClientVenue, served) => async (app, ctx) => {
185
+ if (app.ui === "http") {
186
+ // execution-v2 Wave 4 — the layer-3 served surface, host-gated behind the
187
+ // experimental flag: opening a served app while the flag is off refuses
188
+ // with the SAME typed error as generation (a served app that exists from
189
+ // elsewhere is refused too, not just new builds).
190
+ if (served === undefined || !served.enabled) {
191
+ throw servedAppsDisabledError();
192
+ }
193
+ // A served document without a machine has NO surface anywhere (a v1-era
194
+ // import or a de-graduated doc): say so instead of a confusing wake error.
195
+ if (app.machine === undefined) {
196
+ throw new VendoError("validation", "this served app has no machine — its surface is gone; re-graduate it with an edit or re-create the app");
197
+ }
198
+ // Wake-on-open: a sleeping machine resumes here (the accepted wake
199
+ // latency; the host shows its ordinary loading state — no v1 cover or
200
+ // screenshot machinery).
201
+ return { kind: "http", url: await served.urlFor(app) };
202
+ }
203
+ if (app.tree === undefined) {
204
+ throw new VendoError("validation", "tree app has no ui payload");
205
+ }
206
+ // v2 spec §§1–2 — the canonical vendo-genui/v2 tree: validate, resolve
207
+ // queries (results at "/" + name), and serve with document components at
208
+ // payload level (the v2 renderer lifts them into the shared walk).
209
+ if (app.tree.formatVersion === VENDO_TREE_FORMAT_V2) {
210
+ const validation = validateTreeV2(app.tree);
211
+ if (!validation.ok)
212
+ throw new VendoError("validation", validation.error.message);
213
+ const tree = stripServerAuthoritativeFields(structuredClone(validation.tree));
214
+ const inClient = await inClientVenue?.(app);
215
+ if (inClient !== undefined) {
216
+ tree.inClient = inClient;
217
+ }
218
+ const pinDrift = detectPinDrift(app, pinBaselines);
219
+ if (pinDrift.length > 0) {
220
+ tree.pinDrift = pinDrift;
221
+ }
222
+ attachPinFurnishings(tree, app, pinBaselines);
223
+ const queries = createProgressiveQueryResolver(caller, app, ctx);
224
+ queries.update(tree);
225
+ tree.data = await queries.complete();
226
+ const payload = {
227
+ ...tree,
228
+ ...(app.components === undefined ? {} : { components: structuredClone(app.components) }),
229
+ // W4b — the stamped per-island tool manifests ride the payload beside
230
+ // the sources; the renderer exposes ONLY these tools to each island.
231
+ ...(app.componentTools === undefined ? {} : { componentTools: structuredClone(app.componentTools) }),
232
+ };
233
+ return app.components === undefined
234
+ ? { kind: "tree", payload }
235
+ : { kind: "tree", payload, components: structuredClone(app.components) };
236
+ }
237
+ // 01-core §8 — an unregistered format tag is a contained failure: the payload
238
+ // passes through untouched (no query resolution) and the renderer shows the
239
+ // notice. v2 is the only registered tree format (v1 is discarded).
240
+ const payload = stripServerAuthoritativeFields(structuredClone(app.tree));
241
+ return app.components === undefined
242
+ ? { kind: "tree", payload }
243
+ : { kind: "tree", payload, components: structuredClone(app.components) };
244
+ };
245
+ //# sourceMappingURL=open.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.js","sourceRoot":"","sources":["../src/open.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { type AppId, type ApprovalId, type RunContext, type StoreAdapter, type ToolCall } from "@vendoai/core";
2
+ /**
3
+ * W0 — parked in-app actions (the approve→resume engine seam).
4
+ *
5
+ * A mutating in-app action (`runtime.call`) that the guard sends to approval
6
+ * returns `pending-approval` to the surface — the action shows "Running". The
7
+ * guard parks the approval; deciding it approved makes the EXACT same call
8
+ * eligible for a one-shot approved replay (guard `#consumeApprovedCall`), but
9
+ * only if someone re-dispatches it. Nobody did — so every gated mutation
10
+ * stalled at "Running" forever (held-out gate C4/C11).
11
+ *
12
+ * This collection records the exact parked call (its guard-minted id, args, and
13
+ * the app-venue context it ran in) keyed by the approval that gates it, so the
14
+ * runtime's `onApprovalDecision` subscriber can re-dispatch it the instant the
15
+ * owner approves — the SAME onApprovalDecision seam exposure/egress already
16
+ * ride. A parked record exists exactly while its approval is undecided; both
17
+ * decisions clear it (approve re-dispatches then clears; deny just clears —
18
+ * fail closed, the effect never lands).
19
+ *
20
+ * Hygiene mirrors the egress/exposure stores: records live in their own
21
+ * collection keyed by app id (a copy's fresh id has none) and are cleared with
22
+ * the app on delete.
23
+ */
24
+ export interface ParkedAction {
25
+ /** The guard approval that gates this call. */
26
+ approvalId: ApprovalId;
27
+ appId: AppId;
28
+ /** The app owner's principal subject — the only principal who may approve. */
29
+ owner: string;
30
+ /**
31
+ * The EXACT call the guard parked: its guard-minted id, tool, and args. The
32
+ * approved replay matches on call id + args + descriptor, so this must be
33
+ * re-dispatched byte-for-byte — a fresh call id would re-park, not run.
34
+ */
35
+ call: ToolCall;
36
+ /** The app-venue context the call ran in (venue/presence/appId/subject) — the
37
+ * approved replay also pins these, so re-dispatch reuses them verbatim. */
38
+ ctx: RunContext;
39
+ }
40
+ export interface ParkedActions {
41
+ /** Park one in-app action on its guard approval (re-parking overwrites). */
42
+ put(action: ParkedAction): Promise<void>;
43
+ /** The action riding a specific guard approval id, or null if none. */
44
+ byApproval(approvalId: ApprovalId): Promise<ParkedAction | null>;
45
+ /** Clear the parked action for one approval (its approval was decided, either way). */
46
+ remove(approvalId: ApprovalId): Promise<void>;
47
+ /** Delete every parked action for one app (app deletion cleanup). */
48
+ clearForApp(appId: AppId): Promise<void>;
49
+ }
50
+ export declare const createParkedActions: (store: StoreAdapter) => ParkedActions;
51
+ //# sourceMappingURL=parked-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parked-action.d.ts","sourceRoot":"","sources":["../src/parked-action.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,KAAK,EACV,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,QAAQ,EAEd,MAAM,eAAe,CAAC;AAGvB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC;IACb,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,EAAE,QAAQ,CAAC;IACf;gFAC4E;IAC5E,GAAG,EAAE,UAAU,CAAC;CACjB;AASD,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,GAAG,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,uEAAuE;IACvE,UAAU,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IACjE,uFAAuF;IACvF,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,qEAAqE;IACrE,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,mBAAmB,GAAI,OAAO,YAAY,KAAG,aAuBzD,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { listAllRecords } from "./persistence.js";
2
+ const COLLECTION = "vendo_parked_action";
3
+ const parkedData = (record) => record.data;
4
+ const listAll = (store, refs) => listAllRecords(store.records(COLLECTION), { refs });
5
+ export const createParkedActions = (store) => {
6
+ const collection = store.records(COLLECTION);
7
+ return {
8
+ async put(action) {
9
+ await collection.put({
10
+ id: action.approvalId,
11
+ data: action,
12
+ refs: { subject: action.owner, app_id: action.appId, approval: action.approvalId },
13
+ });
14
+ },
15
+ async byApproval(approvalId) {
16
+ const record = await collection.get(approvalId);
17
+ return record === null ? null : parkedData(record);
18
+ },
19
+ async remove(approvalId) {
20
+ await collection.delete(approvalId);
21
+ },
22
+ async clearForApp(appId) {
23
+ for (const record of await listAll(store, { app_id: appId })) {
24
+ await collection.delete(record.id);
25
+ }
26
+ },
27
+ };
28
+ };
29
+ //# sourceMappingURL=parked-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parked-action.js","sourceRoot":"","sources":["../src/parked-action.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAyClD,MAAM,UAAU,GAAG,qBAAqB,CAAC;AAEzC,MAAM,UAAU,GAAG,CAAC,MAAmB,EAAgB,EAAE,CAAC,MAAM,CAAC,IAAoB,CAAC;AAEtF,MAAM,OAAO,GAAG,CAAC,KAAmB,EAAE,IAA4B,EAA0B,EAAE,CAC5F,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AAatD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAmB,EAAiB,EAAE;IACxE,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7C,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,MAAM;YACd,MAAM,UAAU,CAAC,GAAG,CAAC;gBACnB,EAAE,EAAE,MAAM,CAAC,UAAU;gBACrB,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE;aACnF,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,UAAU;YACzB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAChD,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACrD,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,UAAU;YACrB,MAAM,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACtC,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,KAAK;YACrB,KAAK,MAAM,MAAM,IAAI,MAAM,OAAO,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;gBAC7D,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { type AppDocument, type AppId, type RecordQuery, type RecordStore, type VendoRecord } from "@vendoai/core";
2
+ /** Drain a cursor-paginated listing. A page that repeats its cursor (or drops
3
+ * it) terminates the loop, so a misbehaving adapter cannot spin forever. */
4
+ export declare const listAllRecords: (records: RecordStore, query?: Omit<RecordQuery, "cursor">) => Promise<VendoRecord[]>;
5
+ export declare const validateDocument: (input: unknown, appId: AppId) => AppDocument;
6
+ /** The vendo_apps row shape (02-store §2: id, subject, enabled, doc). The
7
+ * store's reserved records("vendo_apps") routing speaks exactly this — the
8
+ * document alone is NOT the row; ownership and the automations arm/disarm
9
+ * bit ride beside it. */
10
+ export interface AppRowData {
11
+ subject: string;
12
+ enabled: boolean;
13
+ doc: AppDocument;
14
+ }
15
+ /** Trigger edits invalidate enable-time capture, cursor, and webhook state.
16
+ * Canonical comparison — key order must not cause a spurious disarm. */
17
+ export declare const enabledAfterDocumentEdit: (previous: AppDocument, next: AppDocument, enabled: boolean) => boolean;
18
+ export declare const rowFromRecord: (record: VendoRecord) => AppRowData;
19
+ export declare const documentFromRecord: (record: VendoRecord) => AppDocument;
20
+ export interface AppRecordWrite {
21
+ id: AppId;
22
+ data: AppRowData;
23
+ refs: {
24
+ subject: string;
25
+ trigger_kind?: string;
26
+ };
27
+ }
28
+ export declare const appRecordInput: (app: AppDocument, subject: string, enabled?: boolean) => AppRecordWrite;
29
+ /**
30
+ * Wave 7 — mint the next `machine.envStaleAt` marker, strictly greater than
31
+ * the previous one. Two grant flips in the same millisecond must never mint
32
+ * EQUAL markers: a wake that read the first would clear the second's marker
33
+ * after injecting the older env, losing the newer flip (e.g. a revocation).
34
+ * Marks serialize through the app row's CAS, so bumping past the previous
35
+ * marker is enough.
36
+ */
37
+ export declare const nextEnvStaleAt: (previous?: string) => string;
38
+ /** Bounded read-mutate-CAS on the app row; the store's revision receipt
39
+ * arbitrates racers (adapters without atomic/revision fall back to put). */
40
+ export declare const updateAppRow: (records: RecordStore, appId: AppId, mutate: (doc: AppDocument) => AppDocument) => Promise<AppDocument>;
41
+ //# sourceMappingURL=persistence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAEvB;6EAC6E;AAC7E,eAAO,MAAM,cAAc,GACzB,SAAS,WAAW,EACpB,QAAO,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAM,KACtC,OAAO,CAAC,WAAW,EAAE,CAUvB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,EAAE,OAAO,KAAK,KAAG,WAS/D,CAAC;AAEF;;;0BAG0B;AAC1B,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,WAAW,CAAC;CAClB;AAED;yEACyE;AACzE,eAAO,MAAM,wBAAwB,GACnC,UAAU,WAAW,EACrB,MAAM,WAAW,EACjB,SAAS,OAAO,KACf,OAIF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,WAAW,KAAG,UAenD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,QAAQ,WAAW,KAAG,WAC9B,CAAC;AAE5B,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,KAAK,CAAC;IACV,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAClD;AAED,eAAO,MAAM,cAAc,GACzB,KAAK,WAAW,EAChB,SAAS,MAAM,EACf,iBAAe,KACd,cAMD,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GAAI,WAAW,MAAM,KAAG,MAIlD,CAAC;AAEF;6EAC6E;AAC7E,eAAO,MAAM,YAAY,GACvB,SAAS,WAAW,EACpB,OAAO,KAAK,EACZ,QAAQ,CAAC,GAAG,EAAE,WAAW,KAAK,WAAW,KACxC,OAAO,CAAC,WAAW,CAcrB,CAAC"}
@@ -0,0 +1,86 @@
1
+ import { VendoError, canonicalJson, validateAppDocument, } from "@vendoai/core";
2
+ /** Drain a cursor-paginated listing. A page that repeats its cursor (or drops
3
+ * it) terminates the loop, so a misbehaving adapter cannot spin forever. */
4
+ export const listAllRecords = async (records, query = {}) => {
5
+ const found = [];
6
+ let cursor;
7
+ do {
8
+ const page = await records.list(cursor === undefined ? query : { ...query, cursor });
9
+ found.push(...page.records);
10
+ if (page.cursor === undefined || page.cursor === cursor)
11
+ break;
12
+ cursor = page.cursor;
13
+ } while (cursor !== undefined);
14
+ return found;
15
+ };
16
+ export const validateDocument = (input, appId) => {
17
+ const result = validateAppDocument(input);
18
+ if (!result.ok || result.app.id !== appId) {
19
+ const reason = result.ok
20
+ ? `document id ${result.app.id} does not match its app row`
21
+ : result.error.message;
22
+ throw new VendoError("validation", `invalid app document for ${appId}`, { appId, reason });
23
+ }
24
+ return structuredClone(result.app);
25
+ };
26
+ /** Trigger edits invalidate enable-time capture, cursor, and webhook state.
27
+ * Canonical comparison — key order must not cause a spurious disarm. */
28
+ export const enabledAfterDocumentEdit = (previous, next, enabled) => {
29
+ const canon = (trigger) => trigger === undefined ? "" : canonicalJson(trigger);
30
+ return canon(previous.trigger) === canon(next.trigger) && enabled;
31
+ };
32
+ export const rowFromRecord = (record) => {
33
+ const data = record.data;
34
+ if (data === null || typeof data !== "object"
35
+ || typeof data.subject !== "string"
36
+ || typeof data.enabled !== "boolean"
37
+ || data.doc === undefined) {
38
+ throw new VendoError("validation", `invalid app row for ${record.id}`, { appId: record.id });
39
+ }
40
+ return {
41
+ subject: data.subject,
42
+ enabled: data.enabled,
43
+ doc: validateDocument(data.doc, record.id),
44
+ };
45
+ };
46
+ export const documentFromRecord = (record) => rowFromRecord(record).doc;
47
+ export const appRecordInput = (app, subject, enabled = false) => ({
48
+ id: app.id,
49
+ data: { subject, enabled, doc: validateDocument(app, app.id) },
50
+ // trigger_kind indexes apps by trigger kind for the automations tick/emit. The reserved
51
+ // vendo_apps store derives the same value from a column; a generic StoreAdapter keeps this.
52
+ refs: { subject, ...(app.trigger === undefined ? {} : { trigger_kind: app.trigger.on.kind }) },
53
+ });
54
+ /**
55
+ * Wave 7 — mint the next `machine.envStaleAt` marker, strictly greater than
56
+ * the previous one. Two grant flips in the same millisecond must never mint
57
+ * EQUAL markers: a wake that read the first would clear the second's marker
58
+ * after injecting the older env, losing the newer flip (e.g. a revocation).
59
+ * Marks serialize through the app row's CAS, so bumping past the previous
60
+ * marker is enough.
61
+ */
62
+ export const nextEnvStaleAt = (previous) => {
63
+ const now = Date.now();
64
+ const floor = previous === undefined ? Number.NaN : Date.parse(previous);
65
+ return new Date(Number.isFinite(floor) && floor >= now ? floor + 1 : now).toISOString();
66
+ };
67
+ /** Bounded read-mutate-CAS on the app row; the store's revision receipt
68
+ * arbitrates racers (adapters without atomic/revision fall back to put). */
69
+ export const updateAppRow = async (records, appId, mutate) => {
70
+ for (let attempt = 0; attempt < 3; attempt += 1) {
71
+ const record = await records.get(appId);
72
+ if (record === null)
73
+ throw new VendoError("not-found", `app not found: ${appId}`, { appId });
74
+ const row = rowFromRecord(record);
75
+ const next = mutate(structuredClone(row.doc));
76
+ const input = appRecordInput(next, row.subject, row.enabled);
77
+ if (records.atomic === undefined || record.revision === undefined) {
78
+ await records.put(input);
79
+ return next;
80
+ }
81
+ if (await records.atomic.compareAndSwap(input, record.revision) !== null)
82
+ return next;
83
+ }
84
+ throw new VendoError("conflict", `app ${appId} was concurrently modified`, { appId });
85
+ };
86
+ //# sourceMappingURL=persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"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"}