@coreplane/switchboard 1.227.0 → 1.228.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 (35) hide show
  1. package/dist/assets/deploy/cloudflare-memory/worker.ts +157 -3
  2. package/dist/assets/deploy/cloudflare-resident/worker.ts +129 -14
  3. package/dist/assets/deploy/cloudflare-sandbox/Dockerfile +22 -18
  4. package/dist/assets/deploy/cloudflare-sandbox/package.json +1 -1
  5. package/dist/assets/deploy/cloudflare-sandbox/runtime-supervisor.sh +11 -10
  6. package/dist/assets/deploy/cloudflare-sandbox/worker.ts +332 -299
  7. package/dist/assets/deploy/cloudflare-sandbox/wrangler.template.jsonc +2 -2
  8. package/dist/assets/package-lock.json +7 -48
  9. package/dist/assets/package.json +1 -1
  10. package/dist/assets/project.json +2 -2
  11. package/dist/assets/source.json +3 -3
  12. package/dist/assets/src/agents/registry.ts +15 -0
  13. package/dist/assets/src/core/coordinator/contract.ts +6 -0
  14. package/dist/assets/src/core/coordinator/driver.ts +8 -6
  15. package/dist/assets/src/core/runEvents.ts +34 -1
  16. package/dist/assets/src/core/runFriction.ts +2 -1
  17. package/dist/assets/src/core/runRecord.ts +46 -3
  18. package/dist/assets/src/core/runUsage.ts +199 -0
  19. package/dist/assets/src/core/ship/coordinator.ts +4 -2
  20. package/dist/assets/src/execution/residentRebind.ts +84 -7
  21. package/dist/assets/src/execution/sandboxErrors.ts +14 -38
  22. package/dist/assets/src/execution/sandboxLifecycle.ts +78 -0
  23. package/dist/assets/web/dist/.vite/manifest.json +18 -18
  24. package/dist/assets/web/dist/assets/{ResidentDetailPage-Chvll3wy.js → ResidentDetailPage-B1Q9pabX.js} +1 -1
  25. package/dist/assets/web/dist/assets/{ResidentsIndexPage-B5f8IwGF.js → ResidentsIndexPage-CP7U_4aK.js} +1 -1
  26. package/dist/assets/web/dist/assets/{RunRoutePage-CRvmCuXh.js → RunRoutePage-dCC25f_b.js} +4 -4
  27. package/dist/assets/web/dist/assets/{RunsIndexPage-BTJuKFTv.js → RunsIndexPage-Cgp4t4C8.js} +1 -1
  28. package/dist/assets/web/dist/assets/{ScheduledPage-BVfgUBvP.js → ScheduledPage-DthDA2xG.js} +1 -1
  29. package/dist/assets/web/dist/assets/{StatusDot-CFXbAw7S.js → StatusDot-DDc88Kbs.js} +1 -1
  30. package/dist/assets/web/dist/assets/{Tooltip-DcHMtbHJ.js → Tooltip-CBapNhsh.js} +1 -1
  31. package/dist/assets/web/dist/assets/{dist-DKhqHu0V.js → dist-BnwSD1cL.js} +1 -1
  32. package/dist/assets/web/dist/assets/{main-CveRd2yk.js → main-ZhQGbZ2E.js} +2 -2
  33. package/dist/cli.js +808 -155
  34. package/package.json +1 -1
  35. package/dist/assets/src/execution/sandboxKeepalive.ts +0 -118
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coreplane/switchboard",
3
- "version": "1.227.0",
3
+ "version": "1.228.0",
4
4
  "description": "Mention it in Slack and an agent reviews the PR, ships the fix, or answers the question — on the model you choose, with its tools running where you decide.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://openswitchboard.dev",
@@ -1,118 +0,0 @@
1
- // Sandbox activity keepalive (docs/reference/specs/execution.md item 2): one in-flight
2
- // exec never outlives the container's activity timeout.
3
- //
4
- // On @cloudflare/containers 0.0.28 the base class kept an activity clock that
5
- // every proxied fetch renewed ONCE, before the fetch, and an alarm loop
6
- // stopped the container (SIGTERM) the moment the clock read expired — with no
7
- // notion of a request still in flight. So a single command running longer
8
- // than `sleepAfter` had its container killed under it, deterministically, at
9
- // exactly `sleepAfter`: the command ends in `Command execution failed` and
10
- // the next one lands in a fresh container with an empty /workspace. Renewing
11
- // the clock on a timer WHILE a command runs turns `sleepAfter` into what its
12
- // name says: idle time. The 0.3.x containers class that ships with sandbox
13
- // 0.12.x counts in-flight requests itself and refuses to expire while one is
14
- // open, so the keepalive is now belt-and-braces; it stays until a live
15
- // long-command run proves the SDK's own tracking on our path.
16
- //
17
- // Deliberately free of node: imports so wrangler can bundle it into the
18
- // sandbox Worker.
19
-
20
- /** How long an IDLE container stays warm before the Durable Object stops it,
21
- * in the Container class's own `<n>[smh]` grammar. With the keepalive below
22
- * (and the SDK's own in-flight tracking) this is pure idle time — a running
23
- * command can never reach it. 5 minutes frees a finished thread's slot
24
- * (`max_instances`) sooner than the SDK default (20 min on 0.3.x, 10 min on
25
- * 0.12.x), while a follow-up inside 5 minutes still lands on the same warm
26
- * workspace; a later one re-clones, which is the documented per-thread
27
- * degradation (item 1). */
28
- export const SANDBOX_SLEEP_AFTER = "5m";
29
-
30
- /** How often a running command renews the activity clock. Well inside
31
- * SANDBOX_SLEEP_AFTER (the unit tests hold the ordering), so between two
32
- * renewals the clock always has minutes to spare. */
33
- export const EXEC_KEEPALIVE_INTERVAL_MS = 60_000;
34
-
35
- /** The Container class's `sleepAfter` grammar (`"5m"`, `"90s"`, `"1h"`), in
36
- * milliseconds — so a test can compare the interval against it. */
37
- export function parseSleepAfterMs(expr: string): number {
38
- const m = /^(\d+)([smh])$/.exec(expr);
39
- if (!m) throw new Error(`invalid sleepAfter expression: "${expr}" (expected <n>s, <n>m or <n>h)`);
40
- const n = Number(m[1]);
41
- return n * (m[2] === "s" ? 1_000 : m[2] === "m" ? 60_000 : 3_600_000);
42
- }
43
-
44
- /** Run `run()` while calling `renew()` every `intervalMs` until it settles —
45
- * resolve or reject alike. A renew that throws or rejects is swallowed: the
46
- * keepalive exists to protect the command's result, never to replace it. A
47
- * command that finishes inside one interval never triggers a renew. */
48
- export async function withActivityKeepalive<T>(
49
- renew: () => void | Promise<void>,
50
- run: () => Promise<T>,
51
- intervalMs: number,
52
- ): Promise<T> {
53
- const timer = setInterval(() => {
54
- try {
55
- void Promise.resolve(renew()).catch(() => {});
56
- } catch {
57
- // a synchronous throw from renew — same policy as an async rejection
58
- }
59
- }, intervalMs);
60
- try {
61
- return await run();
62
- } finally {
63
- clearInterval(timer);
64
- }
65
- }
66
-
67
- /** The texts the SDK produces when the container is torn down under a
68
- * command, across generations. 0.3.x: the exec handler's generic wrapper (its
69
- * real cause, "Session terminated", sat in a field the client discarded), the
70
- * cause itself, and the stale-session answer the same attempt got once the
71
- * sessions were cleared. 0.12.x: the typed `SessionTerminatedError` text
72
- * (`Session '<id>' shell exited (exit code: <n>)`) and the
73
- * `OperationInterruptedError` text for a container that stopped under a
74
- * pending call, and the disconnect text for a sandbox `destroy()`ed under a
75
- * pending call. Anything else — a transport error, a file-op failure — is
76
- * never recycle-shaped, whenever it arrives. */
77
- const RECYCLE_SHAPED: readonly RegExp[] = [
78
- /^Command execution failed$/,
79
- /^Session terminated$/i,
80
- /^Session '[^']*' not found$/i,
81
- /^Session '[^']*' shell exited \(exit code: /i,
82
- /^The sandbox container stopped while the operation was pending\.?$/i,
83
- /^The sandbox was destroyed while the operation was pending\.?$/i,
84
- ];
85
-
86
- /** The 0.12.x typed errors that MEAN the container went away under the call.
87
- * Matched by name, not `instanceof`: the Worker sees them after the Durable
88
- * Object RPC boundary, which keeps `name`/`message` and drops the prototype. */
89
- export const RECYCLE_ERROR_NAMES: readonly string[] = ["SessionTerminatedError", "OperationInterruptedError"];
90
-
91
- /** Type first, text second: a typed recycle error, or a recycle-shaped text. */
92
- export function isRecycleError(err: { name?: string; message?: string }): boolean {
93
- if (err.name && RECYCLE_ERROR_NAMES.includes(err.name)) return true;
94
- return !!err.message && RECYCLE_SHAPED.some((re) => re.test(err.message!.trim()));
95
- }
96
-
97
- /** Grace inside which a recycle-shaped TEXT is taken at face value: a session
98
- * that fails to start does so in seconds, not minutes. A typed recycle error
99
- * needs no grace — the SDK is stating the container stopped. */
100
- const RECYCLE_SUSPECT_AFTER_MS = 60_000;
101
-
102
- /** The message `/exec` puts in-body when a command's failure looks like the
103
- * container was recycled under it: a typed recycle error (`certain`), or a
104
- * recycle-shaped text that arrived more than a minute into THIS attempt (a
105
- * startup failure shows in seconds). Any other text, however late, is
106
- * returned unchanged — timing alone never rewords an unrelated error. The exit
107
- * code stays 127: it IS an infra failure — the workspace really is gone — and
108
- * a faked exit 124 would tell the model to shorten a command that was never
109
- * the problem. */
110
- export function recycledMidCommandMessage(elapsedMs: number, msg: string, certain = false): string {
111
- const shaped = RECYCLE_SHAPED.some((re) => re.test(msg.trim()));
112
- if (!certain && (!shaped || elapsedMs <= RECYCLE_SUSPECT_AFTER_MS)) return msg;
113
- const secs = Math.round(elapsedMs / 1_000);
114
- return (
115
- `sandbox recycled mid-command after ${secs}s — the container was replaced and /workspace is empty; ` +
116
- `re-clone before continuing (${msg})`
117
- );
118
- }