@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
@@ -0,0 +1,360 @@
1
+ import { VendoError, safeErrorMessage, } from "@vendoai/core";
2
+ import { rowFromRecord, updateAppRow } from "./persistence.js";
3
+ /** Execution-v2 wake/sleep policy: auto-sleep after 5 minutes idle. */
4
+ const DEFAULT_IDLE_MS = 5 * 60_000;
5
+ export const createMachineLifecycle = (config) => {
6
+ const records = config.store.records("vendo_apps");
7
+ const buildEnv = config.buildEnv ?? (() => ({}));
8
+ const idleMs = config.idleMs ?? DEFAULT_IDLE_MS;
9
+ const clock = config.clock ?? {
10
+ setTimeout: (fn, ms) => globalThis.setTimeout(fn, ms),
11
+ clearTimeout: (handle) => globalThis.clearTimeout(handle),
12
+ };
13
+ const live = new Map();
14
+ const waking = new Map();
15
+ const provisioning = new Map();
16
+ const requireAdapter = () => {
17
+ if (config.sandbox === undefined) {
18
+ throw new VendoError("sandbox-unavailable", "sandbox execution is unavailable");
19
+ }
20
+ return config.sandbox;
21
+ };
22
+ /** Authoritative document read — the caller's copy may predate a sleep's re-snapshot. */
23
+ const currentDocument = async (appId) => {
24
+ const record = await records.get(appId);
25
+ if (record === null) {
26
+ throw new VendoError("not-found", `app ${appId} does not exist`, { appId });
27
+ }
28
+ return rowFromRecord(record).doc;
29
+ };
30
+ /** Read-mutate-CAS on the app row; the store's revision receipt arbitrates racers. */
31
+ const updateDocument = (appId, mutate) => updateAppRow(records, appId, mutate);
32
+ const armIdleTimer = (appId) => {
33
+ const entry = live.get(appId);
34
+ if (entry === undefined)
35
+ return;
36
+ if (entry.timer !== undefined)
37
+ clock.clearTimeout(entry.timer);
38
+ entry.timer = clock.setTimeout(() => {
39
+ // A request still inside the box means the machine is not idle: a request
40
+ // outliving idleMs must never be snapshotted mid-flight. Its completion
41
+ // re-arms; this re-arm only covers a request outliving several idleMs.
42
+ if ((live.get(appId)?.inflight ?? 0) > 0) {
43
+ armIdleTimer(appId);
44
+ return;
45
+ }
46
+ void sleepById(appId).catch(() => undefined);
47
+ }, idleMs);
48
+ };
49
+ /** The seam's dead-machine signal (sandbox.ts): a request() throwing
50
+ * not-found means the PROVIDER lost the machine (TTL, sweep) — an app-level
51
+ * status never throws through the seam. */
52
+ const isMachineGone = (error) => error instanceof VendoError && error.code === "not-found";
53
+ /** One tracked request against a specific live raw machine (no recovery). */
54
+ const requestOnce = async (appId, raw, req) => {
55
+ const entry = live.get(appId);
56
+ const tracked = entry !== undefined && entry.raw === raw;
57
+ if (tracked)
58
+ entry.inflight += 1;
59
+ armIdleTimer(appId);
60
+ try {
61
+ return await raw.request(req);
62
+ }
63
+ finally {
64
+ if (tracked)
65
+ entry.inflight -= 1;
66
+ armIdleTimer(appId);
67
+ }
68
+ };
69
+ /** Wave 7 — drop a live entry whose provider state died out from under us.
70
+ * Guarded on the exact raw machine so a racing recovery (or a fresh wake)
71
+ * is never evicted by a stale handle's late failure. */
72
+ const evictDead = async (appId, raw) => {
73
+ const entry = live.get(appId);
74
+ if (entry === undefined || entry.raw !== raw)
75
+ return;
76
+ live.delete(appId);
77
+ if (entry.timer !== undefined)
78
+ clock.clearTimeout(entry.timer);
79
+ // Best-effort: the provider already reaped it; never snapshot a dead box.
80
+ await entry.raw.destroy().catch(() => undefined);
81
+ };
82
+ /** Every request through the machine counts as activity and re-arms the idle
83
+ * timer. A dead-machine failure (provider TTL/sweep) evicts the live entry
84
+ * and retries ONCE from the durable snapshot ref; a second failure
85
+ * surfaces. */
86
+ const withIdleTracking = (appId, raw) => ({
87
+ id: raw.id,
88
+ request: async (req) => {
89
+ try {
90
+ return await requestOnce(appId, raw, req);
91
+ }
92
+ catch (error) {
93
+ if (!isMachineGone(error))
94
+ throw error;
95
+ await evictDead(appId, raw);
96
+ // Re-wake from the stored snapshot ref (concurrent recoveries coalesce
97
+ // on the waking single-flight); the retry targets the fresh raw
98
+ // machine directly so a second dead-machine failure surfaces instead
99
+ // of recursing into another recovery.
100
+ await wakeById(appId);
101
+ const fresh = live.get(appId);
102
+ if (fresh === undefined)
103
+ throw error;
104
+ return await requestOnce(appId, fresh.raw, req);
105
+ }
106
+ },
107
+ url: (port) => raw.url(port),
108
+ snapshot: () => raw.snapshot(),
109
+ stop: () => raw.stop(),
110
+ destroy: () => raw.destroy(),
111
+ });
112
+ /** Remove an app's live entry (if any), cancel its timer, and return it. */
113
+ const takeLive = async (appId) => {
114
+ const pending = waking.get(appId);
115
+ if (pending !== undefined)
116
+ await pending.catch(() => undefined);
117
+ const entry = live.get(appId);
118
+ if (entry === undefined)
119
+ return undefined;
120
+ live.delete(appId);
121
+ if (entry.timer !== undefined)
122
+ clock.clearTimeout(entry.timer);
123
+ return entry;
124
+ };
125
+ const sleepById = async (appId) => {
126
+ const entry = await takeLive(appId);
127
+ if (entry === undefined)
128
+ return null;
129
+ try {
130
+ const snapshotRef = await entry.raw.snapshot();
131
+ // provisionedAt keeps recording provisioning; only the ref moves forward.
132
+ // A machine field cleared by a concurrent destroy stays cleared.
133
+ let superseded;
134
+ const updated = await updateDocument(appId, (doc) => {
135
+ if (doc.machine === undefined)
136
+ return doc;
137
+ superseded = doc.machine.snapshotRef;
138
+ return { ...doc, machine: { ...doc.machine, snapshotRef } };
139
+ });
140
+ // Snapshots are independent provider resources: release whichever ref
141
+ // lost — the superseded one normally, or ours if a concurrent destroy
142
+ // cleared the field while we were snapshotting.
143
+ const orphan = updated.machine?.snapshotRef === snapshotRef ? superseded : snapshotRef;
144
+ if (orphan !== undefined && orphan !== updated.machine?.snapshotRef) {
145
+ await config.sandbox?.destroy(orphan).catch(() => undefined);
146
+ }
147
+ return updated;
148
+ }
149
+ finally {
150
+ // snapshot() leaves the source machine RUNNING (e2b semantics): the
151
+ // checkpoint is what survives, so the live source is destroyed — a mere
152
+ // stop would leave a paused provider resource lingering beside the ref.
153
+ await entry.raw.destroy().catch(() => undefined);
154
+ }
155
+ };
156
+ const provision = async (app) => {
157
+ const inflight = provisioning.get(app.id);
158
+ if (inflight !== undefined)
159
+ return inflight;
160
+ const run = (async () => {
161
+ const doc = await currentDocument(app.id);
162
+ if (doc.machine !== undefined)
163
+ return doc;
164
+ const adapter = requireAdapter();
165
+ // Lane E — the egress policy gates provisioning BEFORE any provider
166
+ // call: an unapproved declared domain throws here and no machine exists.
167
+ const allowlist = await config.allowedDomains?.(doc);
168
+ const machine = await adapter.create({
169
+ ...(config.template === undefined ? {} : { template: config.template }),
170
+ env: await buildEnv(doc),
171
+ ...(allowlist === undefined ? {} : { allowedDomains: allowlist }),
172
+ });
173
+ try {
174
+ const snapshotRef = await machine.snapshot();
175
+ const provisionedAt = new Date().toISOString();
176
+ // A CAS retry can re-read a document another app server already
177
+ // provisioned; the winner's machine stays, and our snapshot is released.
178
+ const updated = await updateDocument(app.id, (current) => current.machine === undefined
179
+ ? { ...current, machine: { snapshotRef, provisionedAt } }
180
+ : current);
181
+ if (updated.machine?.snapshotRef !== snapshotRef) {
182
+ await adapter.destroy(snapshotRef).catch(() => undefined);
183
+ }
184
+ return updated;
185
+ }
186
+ finally {
187
+ // Provision ends asleep: the snapshot IS the machine until a wake, and
188
+ // snapshot() leaves the source running — destroy it, don't just stop.
189
+ await machine.destroy().catch(() => undefined);
190
+ }
191
+ })();
192
+ provisioning.set(app.id, run);
193
+ try {
194
+ return await run;
195
+ }
196
+ finally {
197
+ provisioning.delete(app.id);
198
+ }
199
+ };
200
+ const wake = async (app) => wakeById(app.id);
201
+ /**
202
+ * Wave 7 — rebuild a machine's boundary env when its document carries the
203
+ * env-stale marker (a secret grant changed after the last injection), then
204
+ * clear the marker. Clearing is guarded on the marker VALUE seen — a grant
205
+ * committed during the rebuild keeps its own fresher marker for the next
206
+ * wake (markers are strictly increasing, so values never collide). A failed
207
+ * clear is benign: the env is fresh and the re-push is idempotent. Throws
208
+ * on injection failure; the CALLER owns tearing the machine down (fail
209
+ * closed — a box we cannot re-police must not serve).
210
+ */
211
+ const rebuildStaleEnv = async (appId, doc, machine) => {
212
+ const staleAt = doc.machine?.envStaleAt;
213
+ if (staleAt === undefined || config.injectEnv === undefined)
214
+ return;
215
+ try {
216
+ await config.injectEnv(machine, await buildEnv(doc));
217
+ }
218
+ catch (error) {
219
+ throw new VendoError("sandbox-unavailable", `machine env rebuild failed for ${appId} after a grant change`, { appId, reason: safeErrorMessage(error) });
220
+ }
221
+ await updateDocument(appId, (current) => {
222
+ if (current.machine === undefined || current.machine.envStaleAt !== staleAt)
223
+ return current;
224
+ const { envStaleAt: _stale, ...rest } = current.machine;
225
+ return { ...current, machine: rest };
226
+ }).catch(() => undefined);
227
+ };
228
+ const wakeById = async (appId) => {
229
+ const entry = live.get(appId);
230
+ if (entry !== undefined) {
231
+ // Lane E — a live machine answers to the CURRENT policy too: a
232
+ // declaration that lost (or never had) approval refuses here rather
233
+ // than riding the warm entry. (A running provider machine's network
234
+ // policy cannot be re-tightened in place — the refusal plus the idle
235
+ // sleep is the containment; the next wake re-applies the policy.)
236
+ // Evaluated over the authoritative row, not the caller's copy — a
237
+ // grant committed since the caller loaded its document must count.
238
+ if (config.allowedDomains !== undefined || config.injectEnv !== undefined) {
239
+ const doc = await currentDocument(appId);
240
+ if (config.allowedDomains !== undefined)
241
+ await config.allowedDomains(doc);
242
+ // Wave 7 — a durable env-stale marker written by ANOTHER process
243
+ // (whose grant commit cannot reach this process's live entry to
244
+ // sleep it) must not ride the warm entry until the idle sweep.
245
+ try {
246
+ await rebuildStaleEnv(appId, doc, entry.raw);
247
+ }
248
+ catch (error) {
249
+ const taken = await takeLive(appId);
250
+ await taken?.raw.destroy().catch(() => undefined);
251
+ throw error;
252
+ }
253
+ }
254
+ armIdleTimer(appId);
255
+ return entry.wrapped;
256
+ }
257
+ const pending = waking.get(appId);
258
+ if (pending !== undefined)
259
+ return pending;
260
+ const run = (async () => {
261
+ const doc = await currentDocument(appId);
262
+ if (doc.machine === undefined) {
263
+ throw new VendoError("validation", `app ${appId} has no machine to wake`, { appId });
264
+ }
265
+ const adapter = requireAdapter();
266
+ // Lane E — a wake applies the CURRENT egress policy over the snapshot's
267
+ // stored one (grants may have changed while the machine slept); it also
268
+ // refuses loudly when a declared domain lost or never had approval.
269
+ const raw = config.allowedDomains === undefined
270
+ ? await adapter.resume(doc.machine.snapshotRef)
271
+ : await adapter.resume(doc.machine.snapshotRef, {
272
+ allowedDomains: await config.allowedDomains(doc),
273
+ });
274
+ // Wave 7 — a grant changed while the machine slept: the resumed snapshot
275
+ // carries the OLD env (every provider restores snapshot env), so rebuild
276
+ // the boundary env through the control port before anything rides this
277
+ // wake. A failed rebuild fails the wake CLOSED — registering the machine
278
+ // live would let a revoked secret keep serving until the idle sweep. The
279
+ // marker and the document ref survive, so the next wake retries.
280
+ try {
281
+ await rebuildStaleEnv(appId, doc, raw);
282
+ }
283
+ catch (error) {
284
+ await raw.destroy().catch(() => undefined);
285
+ throw error;
286
+ }
287
+ const wrapped = withIdleTracking(appId, raw);
288
+ live.set(appId, { raw, wrapped, inflight: 0 });
289
+ armIdleTimer(appId);
290
+ return wrapped;
291
+ })();
292
+ waking.set(appId, run);
293
+ try {
294
+ return await run;
295
+ }
296
+ finally {
297
+ waking.delete(appId);
298
+ }
299
+ };
300
+ const sleep = async (app) => {
301
+ const slept = await sleepById(app.id);
302
+ return slept ?? await currentDocument(app.id);
303
+ };
304
+ const discard = async (app) => {
305
+ // Rollback: take the live machine off the books and destroy it WITHOUT a
306
+ // snapshot, so the document keeps pointing at its pre-edit ref. A mere
307
+ // stop would leave a paused provider resource beside the untouched ref.
308
+ const entry = await takeLive(app.id);
309
+ if (entry !== undefined)
310
+ await entry.raw.destroy().catch(() => undefined);
311
+ };
312
+ const destroyMachine = async (app) => {
313
+ const doc = await currentDocument(app.id);
314
+ if (doc.machine === undefined && !live.has(app.id) && !waking.has(app.id)) {
315
+ return doc;
316
+ }
317
+ const adapter = requireAdapter();
318
+ const entry = await takeLive(app.id);
319
+ // A live machine is its own provider resource — destroy it, not just stop.
320
+ if (entry !== undefined)
321
+ await entry.raw.destroy().catch(() => undefined);
322
+ // Clear the field FIRST, capturing the ref from the winning write: a sleep
323
+ // racing this destroy may have just stored a newer ref, and destroying a
324
+ // stale read's ref would orphan the newer snapshot.
325
+ let clearedRef;
326
+ const updated = await updateDocument(app.id, (current) => {
327
+ clearedRef = current.machine?.snapshotRef;
328
+ const { machine: _machine, ...rest } = current;
329
+ return rest;
330
+ });
331
+ if (clearedRef !== undefined)
332
+ await adapter.destroy(clearedRef);
333
+ return updated;
334
+ };
335
+ const buildAppEnv = async (app) => buildEnv(await currentDocument(app.id));
336
+ const destroyResources = async (app) => {
337
+ const entry = await takeLive(app.id);
338
+ if (entry !== undefined)
339
+ await entry.raw.destroy().catch(() => undefined);
340
+ // Read the stored ref (the caller's copy may predate a sleep's re-snapshot)
341
+ // and reap it directly — no document write, so a machine-cleared tree that
342
+ // still names fn: refs cannot fail validation and strand the snapshot.
343
+ const doc = await currentDocument(app.id).catch(() => app);
344
+ const ref = doc.machine?.snapshotRef;
345
+ if (ref !== undefined)
346
+ await config.sandbox?.destroy(ref).catch(() => undefined);
347
+ };
348
+ return {
349
+ available: () => config.sandbox !== undefined,
350
+ peek: (appId) => live.get(appId)?.wrapped,
351
+ provision,
352
+ wake,
353
+ sleep,
354
+ discard,
355
+ destroyMachine,
356
+ destroyResources,
357
+ buildAppEnv,
358
+ };
359
+ };
360
+ //# sourceMappingURL=machine-lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-lifecycle.js","sourceRoot":"","sources":["../src/machine-lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { z } from "zod";
2
+ export interface VendoManifestSchedule {
3
+ cron: string;
4
+ fn: string;
5
+ }
6
+ export interface VendoManifest {
7
+ schedules?: VendoManifestSchedule[];
8
+ egress?: string[];
9
+ }
10
+ /** Strict on every level: an unknown key is a loud validation error, so a
11
+ * manifest written against a future contract fails at the seam that reads it
12
+ * instead of being silently half-honored. */
13
+ export declare const vendoManifestSchema: z.ZodObject<{
14
+ schedules: z.ZodOptional<z.ZodArray<z.ZodObject<{
15
+ cron: z.ZodEffects<z.ZodString, string, string>;
16
+ fn: z.ZodString;
17
+ }, "strict", z.ZodTypeAny, {
18
+ cron: string;
19
+ fn: string;
20
+ }, {
21
+ cron: string;
22
+ fn: string;
23
+ }>, "many">>;
24
+ egress: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
25
+ }, "strict", z.ZodTypeAny, {
26
+ egress?: string[] | undefined;
27
+ schedules?: {
28
+ cron: string;
29
+ fn: string;
30
+ }[] | undefined;
31
+ }, {
32
+ egress?: string[] | undefined;
33
+ schedules?: {
34
+ cron: string;
35
+ fn: string;
36
+ }[] | undefined;
37
+ }>;
38
+ /** Parse + validate a `vendo.json` source. Every seam that reads the manifest
39
+ * calls this; an invalid manifest is a loud VendoError("validation"), never a
40
+ * silently-dropped declaration. */
41
+ export declare function parseVendoManifest(source: string): VendoManifest;
42
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsBxB,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;6CAE6C;AAC7C,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;EAYc,CAAC;AAE/C;;mCAEmC;AACnC,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAchE"}
@@ -0,0 +1,53 @@
1
+ import { VendoError } from "@vendoai/core";
2
+ import { z } from "zod";
3
+ /** execution-v2 spec ("The skin of the box") — `vendo.json`, the manifest an
4
+ * app ships at its box root. v2 carries exactly two declarations and nothing
5
+ * else (YAGNI): `schedules` ("at this cron, POST /fn/<name>"), read by the
6
+ * scheduler broker (Wave 2 Lane D), and `egress`, the outbound-domain
7
+ * allowlist the sandbox network layer enforces (Wave 2 Lane E). Declarative
8
+ * only — no runtime library is required inside the box. */
9
+ /** The fn-name half of core's 01 §8 `fn:<name>` grammar, bounded like tool
10
+ * route names — a schedule targets `POST /fn/<name>`, never a `fn:` ref. */
11
+ const FN_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_-]{0,63}$/;
12
+ /** Five whitespace-separated cron fields ("0 8 * * *"). Field syntax stays the
13
+ * broker's concern; the manifest gate pins the shape so a typo\'d schedule
14
+ * fails at parse time, not silently at fire time. */
15
+ const CRON_FIELD_PATTERN = /^[0-9A-Za-z*,/-]+$/;
16
+ const isCronExpression = (value) => {
17
+ const fields = value.trim().split(/\s+/);
18
+ return fields.length === 5 && fields.every((field) => CRON_FIELD_PATTERN.test(field));
19
+ };
20
+ /** Strict on every level: an unknown key is a loud validation error, so a
21
+ * manifest written against a future contract fails at the seam that reads it
22
+ * instead of being silently half-honored. */
23
+ export const vendoManifestSchema = z.object({
24
+ schedules: z.array(z.object({
25
+ cron: z.string().refine(isCronExpression, {
26
+ message: "cron must be five whitespace-separated fields (e.g. \"0 8 * * *\")",
27
+ }),
28
+ fn: z.string().regex(FN_NAME_PATTERN, {
29
+ message: "fn must be a bare fn name (POST /fn/<name> target), matching [A-Za-z_][A-Za-z0-9_-]{0,63}",
30
+ }),
31
+ }).strict()).optional(),
32
+ egress: z.array(z.string().min(1)).optional(),
33
+ }).strict();
34
+ /** Parse + validate a `vendo.json` source. Every seam that reads the manifest
35
+ * calls this; an invalid manifest is a loud VendoError("validation"), never a
36
+ * silently-dropped declaration. */
37
+ export function parseVendoManifest(source) {
38
+ let raw;
39
+ try {
40
+ raw = JSON.parse(source);
41
+ }
42
+ catch {
43
+ throw new VendoError("validation", "vendo.json is not valid JSON");
44
+ }
45
+ const parsed = vendoManifestSchema.safeParse(raw);
46
+ if (!parsed.success) {
47
+ const issue = parsed.error.issues[0];
48
+ const path = issue === undefined || issue.path.length === 0 ? "manifest" : issue.path.join(".");
49
+ throw new VendoError("validation", `invalid vendo.json: ${path}: ${issue?.message ?? "invalid"}`);
50
+ }
51
+ return parsed.data;
52
+ }
53
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;2DAK2D;AAE3D;4EAC4E;AAC5E,MAAM,eAAe,GAAG,gCAAgC,CAAC;AAEzD;;qDAEqD;AACrD,MAAM,kBAAkB,GAAG,oBAAoB,CAAC;AAChD,MAAM,gBAAgB,GAAG,CAAC,KAAa,EAAW,EAAE;IAClD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AACxF,CAAC,CAAC;AAYF;;6CAE6C;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,SAAS,EAAE,CAAC,CAAC,KAAK,CAChB,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE;YACxC,OAAO,EAAE,oEAAoE;SAC9E,CAAC;QACF,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE;YACpC,OAAO,EAAE,2FAA2F;SACrG,CAAC;KACH,CAAC,CAAC,MAAM,EAAE,CACZ,CAAC,QAAQ,EAAE;IACZ,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC9C,CAAC,CAAC,MAAM,EAAqC,CAAC;AAE/C;;mCAEmC;AACnC,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,UAAU,CAAC,YAAY,EAAE,8BAA8B,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAClD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChG,MAAM,IAAI,UAAU,CAAC,YAAY,EAAE,uBAAuB,IAAI,KAAK,KAAK,EAAE,OAAO,IAAI,SAAS,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC"}
package/dist/open.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ import { VendoError, type AppDocument, type Json, type RunContext, type TreeV2 } from "@vendoai/core";
2
+ import type { AppCaller } from "./call.js";
3
+ import type { InClientVenueState } from "./inclient.js";
4
+ import { type PinBaseline } from "./pins.js";
5
+ import type { OpenSurface } from "./runtime.js";
6
+ export interface ProgressiveQueryResolver {
7
+ update(tree: TreeV2): void;
8
+ complete(): Promise<Record<string, Json>>;
9
+ }
10
+ /**
11
+ * Start queries as soon as they appear. Results may arrive in any order, but
12
+ * every emitted/final data model is rebuilt in source order so later queries
13
+ * retain the same deterministic last-write behavior as the old serial loop.
14
+ */
15
+ export declare const createProgressiveQueryResolver: (caller: AppCaller, app: AppDocument, ctx: RunContext, onData?: (data: Record<string, Json>) => void) => ProgressiveQueryResolver;
16
+ /**
17
+ * 06-apps §§8–9 — the in-client venue field and the pin-drift report are
18
+ * SERVER-AUTHORITATIVE. The stored tree is model-written or imported from an
19
+ * untrusted `.vendoapp`, so a forged `inClient` or `pinDrift` riding the
20
+ * document must never reach the client: strip both before the verified
21
+ * verdict and the computed drift (when any) are attached — and strip at
22
+ * persist time too (the runtime shares this helper), streamed or at rest.
23
+ */
24
+ export declare const stripServerAuthoritativeFields: <T extends object>(payload: T) => T;
25
+ /**
26
+ * execution-v2 Wave 4 — the layer-3 served surface seam the runtime injects:
27
+ * `enabled` mirrors the host's experimental flag, and `urlFor` wakes the app's
28
+ * machine (wake-on-open) and resolves its public ingress URL for $PORT.
29
+ */
30
+ export interface ServedSurface {
31
+ enabled: boolean;
32
+ urlFor(app: AppDocument): Promise<string>;
33
+ }
34
+ /** Wave 4 — the one refusal for every layer-3 path while the flag is off. */
35
+ export declare const servedAppsDisabledError: () => VendoError;
36
+ /** Wave 9 — the one refusal for NEW layer-2 box work while machines are off
37
+ * (same house pattern as {@link servedAppsDisabledError}). The escalation
38
+ * ladder only lands here when no automation can express the request, so the
39
+ * message says exactly that instead of silently degrading to a broken
40
+ * automation. Already-provisioned machines are never gated by this — only
41
+ * new graduation/provisioning is. */
42
+ export declare const machinesDisabledError: () => VendoError;
43
+ /** 06-apps §§1–2 — construct the open surface. */
44
+ export declare const createAppOpener: (caller: AppCaller, pinBaselines?: readonly PinBaseline[], inClientVenue?: (app: AppDocument) => Promise<InClientVenueState | undefined>, served?: ServedSurface) => ((app: AppDocument, ctx: RunContext) => Promise<OpenSurface>);
45
+ //# sourceMappingURL=open.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../src/open.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,UAAU,EAEV,KAAK,WAAW,EAChB,KAAK,IAAI,EACT,KAAK,UAAU,EAEf,KAAK,MAAM,EAEZ,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAoC,KAAK,WAAW,EAAiB,MAAM,WAAW,CAAC;AAC9F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAiFhD,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;CAC3C;AAED;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,GACzC,QAAQ,SAAS,EACjB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,IAAI,KAC5C,wBAwDF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,8BAA8B,GAAI,CAAC,SAAS,MAAM,EAAE,SAAS,CAAC,KAAG,CAI7E,CAAC;AAwBF;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3C;AAED,6EAA6E;AAC7E,eAAO,MAAM,uBAAuB,QAAO,UAI1C,CAAC;AAEF;;;;;sCAKsC;AACtC,eAAO,MAAM,qBAAqB,QAAO,UAIxC,CAAC;AAEF,kDAAkD;AAClD,eAAO,MAAM,eAAe,GAC1B,QAAQ,SAAS,EACjB,eAAc,SAAS,WAAW,EAAO,EACzC,gBAAgB,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,EAC7E,SAAS,aAAa,KACrB,CAAC,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,WAAW,CAAC,CA+D9D,CAAC"}