@coreplane/switchboard 1.258.0 → 1.260.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.
- package/dist/assets/config/config.example.yaml +17 -25
- package/dist/assets/deploy/cloudflare-memory/worker.ts +178 -27
- package/dist/assets/deploy/cloudflare-resident/worker.ts +74 -52
- package/dist/assets/deploy/cloudflare-sandbox/Dockerfile +6 -3
- package/dist/assets/package-lock.json +3 -3
- package/dist/assets/package.json +1 -1
- package/dist/assets/source.json +3 -3
- package/dist/assets/src/agents/registry.ts +3 -5
- package/dist/assets/src/core/authz/policy.ts +5 -0
- package/dist/assets/src/core/budgets.ts +7 -0
- package/dist/assets/src/core/coordinator/contract.ts +93 -5
- package/dist/assets/src/core/coordinator/driver.ts +386 -124
- package/dist/assets/src/core/memory/types.ts +5 -0
- package/dist/assets/src/core/pipelineStanding.ts +11 -4
- package/dist/assets/src/core/plane/decide.ts +53 -12
- package/dist/assets/src/core/provider.ts +8 -3
- package/dist/assets/src/core/runEvents.ts +14 -15
- package/dist/assets/src/core/runRecord.ts +36 -3
- package/dist/assets/src/core/ship/coordinator.ts +58 -18
- package/dist/assets/src/core/ship/renewal.ts +21 -8
- package/dist/assets/src/core/types.ts +12 -1
- package/dist/assets/web/dist/.vite/manifest.json +67 -67
- package/dist/assets/web/dist/assets/{DeliveryPage-DadntjSp.js → DeliveryPage-DvMrWUg7.js} +1 -1
- package/dist/assets/web/dist/assets/HomePage-CcGEJ4w0.js +1 -0
- package/dist/assets/web/dist/assets/{PendingTurnRow-DBPMLVsm.js → PendingTurnRow-BzGVxDYs.js} +1 -1
- package/dist/assets/web/dist/assets/{PlanePage-DLusMGQ0.js → PlanePage-Arj9cyd5.js} +1 -1
- package/dist/assets/web/dist/assets/{ResidentDetailPage-CPnHnrxy.js → ResidentDetailPage-CBPPe4Sj.js} +1 -1
- package/dist/assets/web/dist/assets/{ResidentsIndexPage-C9hASwHL.js → ResidentsIndexPage-CEpXgGo7.js} +1 -1
- package/dist/assets/web/dist/assets/RunFoldRow-BJq7tnLr.js +1 -0
- package/dist/assets/web/dist/assets/{RunRoutePage-o1xzkTGZ.js → RunRoutePage-DWiny7LN.js} +4 -4
- package/dist/assets/web/dist/assets/RunsIndexPage-Cxufw5sV.js +1 -0
- package/dist/assets/web/dist/assets/{ScheduledPage-BIdfC0V3.js → ScheduledPage-SBcuDdVg.js} +1 -1
- package/dist/assets/web/dist/assets/{SettingsPage-CnqWAjl3.js → SettingsPage-DrD_vWdp.js} +1 -1
- package/dist/assets/web/dist/assets/{SilentTurn-DGNg0sIZ.js → SilentTurn-Bjl7EPEN.js} +1 -1
- package/dist/assets/web/dist/assets/{StatusDot-D_D_iJS8.js → StatusDot-BqteQTav.js} +1 -1
- package/dist/assets/web/dist/assets/{Tooltip-DVFmM7on.js → Tooltip-KRqJXEPN.js} +1 -1
- package/dist/assets/web/dist/assets/{UnitRoutePage-7fAXFoB_.js → UnitRoutePage-Cv28FV4I.js} +1 -1
- package/dist/assets/web/dist/assets/{budgets-BRLm6oID.js → budgets-DQXVllsm.js} +1 -1
- package/dist/assets/web/dist/assets/{dist-C1VX-_mm.js → dist-CTASUSno.js} +1 -1
- package/dist/assets/web/dist/assets/{indexRow-BO_GIdF6.js → indexRow-B1YBy_IL.js} +1 -1
- package/dist/assets/web/dist/assets/{main-Cl7xHG34.js → main-eTAe9-hk.js} +2 -2
- package/dist/assets/web/dist/assets/{sseReplay-BjlKmQsY.js → sseReplay-BcsNbn2j.js} +1 -1
- package/dist/cli.js +8324 -7937
- package/package.json +1 -1
- package/dist/assets/web/dist/assets/HomePage-BEEpTnVT.js +0 -1
- package/dist/assets/web/dist/assets/RunFoldRow-OPe7Z0Cz.js +0 -1
- package/dist/assets/web/dist/assets/RunsIndexPage-0YAClYQh.js +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.260.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "switchboard",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.260.0",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"workspaces": [
|
|
12
12
|
"web",
|
|
@@ -20445,7 +20445,7 @@
|
|
|
20445
20445
|
},
|
|
20446
20446
|
"packages/switchboard": {
|
|
20447
20447
|
"name": "@coreplane/switchboard",
|
|
20448
|
-
"version": "1.
|
|
20448
|
+
"version": "1.260.0",
|
|
20449
20449
|
"license": "Apache-2.0",
|
|
20450
20450
|
"dependencies": {
|
|
20451
20451
|
"@earendil-works/pi-ai": "0.85.1",
|
package/dist/assets/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.260.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"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.",
|
|
6
6
|
"license": "Apache-2.0",
|
package/dist/assets/source.json
CHANGED
|
@@ -47,11 +47,9 @@ export function machineNeedsRepo(machine: MachineClass): boolean {
|
|
|
47
47
|
export const IDENTITIES = ["none", "read", "write"] as const;
|
|
48
48
|
export type Identity = (typeof IDENTITIES)[number];
|
|
49
49
|
|
|
50
|
-
/** The model tiers a preset may run on
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* a parent choosing a child's model at spawn is held to the child preset's
|
|
54
|
-
* set, and escalation is a new run — a run's tier is fixed at dispatch. */
|
|
50
|
+
/** The model tiers a preset may run on. The retired classifier leaves no
|
|
51
|
+
* configured fast-tier ref, so current run models resolve strong; declarations
|
|
52
|
+
* remain explicit for model-card tiering and future configured catalogues. */
|
|
55
53
|
export const MODEL_TIERS = ["fast", "strong"] as const;
|
|
56
54
|
export type ModelTier = (typeof MODEL_TIERS)[number];
|
|
57
55
|
|
|
@@ -118,6 +118,11 @@ export const POLICY: readonly Rule[] = [
|
|
|
118
118
|
// `pulls rebase` force-pushes the pipeline's branches and can start a paid
|
|
119
119
|
// fix round (record 0071): a grant, never a chat baseline.
|
|
120
120
|
{ action: "pulls:write", resource: "command", when: [grant("pulls:write")] },
|
|
121
|
+
// `pulls merge|enqueue` (record 0070, criterion 4): a person's merge through
|
|
122
|
+
// the door — the grant, never a baseline, so a grant-less person has a
|
|
123
|
+
// thread that reads everything and merges nothing. The release pull
|
|
124
|
+
// request's handoff and the approval fences are the handler's own refusals.
|
|
125
|
+
{ action: "merge:write", resource: "command", when: [grant("merge:write")] },
|
|
121
126
|
|
|
122
127
|
// ── repos ────────────────────────────────────────────────────────────────
|
|
123
128
|
{ action: "repo:read", resource: "command", when: [grant("repo:read")] },
|
|
@@ -236,6 +236,13 @@ export const HOSTED_DEADLINE_MARGIN_MINUTES = 60;
|
|
|
236
236
|
* and the pause before a busy spawn is asked again. */
|
|
237
237
|
export const SHIP_WAIT = { marginMinutes: 5, chunkMinutes: 5, mergeChunkMinutes: 5, busyRetryMinutes: 2 } as const;
|
|
238
238
|
|
|
239
|
+
/** How long a restarting close gives its replacement dispatch to claim the
|
|
240
|
+
* same run before a read with no successor treats the close as final
|
|
241
|
+
* (run-history item 47a). One whole coordinator wait chunk lets an ordinary
|
|
242
|
+
* replacement claim without shortening the parent's first wait; a successor
|
|
243
|
+
* found after this deadline still wins because read-record searches first. */
|
|
244
|
+
export const RESTART_CLAIM_GRACE_MS = minutesToMs(SHIP_WAIT.chunkMinutes);
|
|
245
|
+
|
|
239
246
|
/** The plane's table (docs/decisions/0064): how long a finished run stays on
|
|
240
247
|
* it, a reservation's window, and the default re-ask cadence — how often a
|
|
241
248
|
* silent resident something waits on is probed (`plane.reaskMinutes`
|
|
@@ -111,12 +111,24 @@ export interface ThreadEventAttachment {
|
|
|
111
111
|
mediaType: string;
|
|
112
112
|
data: string;
|
|
113
113
|
name?: string;
|
|
114
|
+
/** The accepted channel file's by-reference source, when one exists, so the
|
|
115
|
+
* coding child can stage it without moving the inline bytes through a
|
|
116
|
+
* second request. */
|
|
117
|
+
staged?: {
|
|
118
|
+
name: string;
|
|
119
|
+
size: number;
|
|
120
|
+
type: string;
|
|
121
|
+
url: string;
|
|
122
|
+
messageId: string;
|
|
123
|
+
workspaceIndex?: number;
|
|
124
|
+
};
|
|
114
125
|
}
|
|
115
126
|
|
|
116
127
|
export interface ThreadEvent {
|
|
117
128
|
/** Assigned by the store's append, in arrival order, per unit. */
|
|
118
129
|
seq: number;
|
|
119
|
-
/** The channel's message id,
|
|
130
|
+
/** The channel's message id, or another producer's stable event id. An
|
|
131
|
+
* append that repeats it on one unit returns the original row. */
|
|
120
132
|
id?: string;
|
|
121
133
|
/** The sender (platform-namespaced) and the display name the channel knew. */
|
|
122
134
|
sender: string;
|
|
@@ -174,11 +186,24 @@ export function capThreadEvent<T extends Omit<ThreadEvent, "seq"> & { seq?: numb
|
|
|
174
186
|
}
|
|
175
187
|
}
|
|
176
188
|
|
|
189
|
+
const isThreadEventStagedFile = (v: unknown): v is NonNullable<ThreadEventAttachment["staged"]> =>
|
|
190
|
+
isObject(v) &&
|
|
191
|
+
typeof v.name === "string" &&
|
|
192
|
+
typeof v.size === "number" &&
|
|
193
|
+
Number.isInteger(v.size) &&
|
|
194
|
+
v.size > 0 &&
|
|
195
|
+
typeof v.type === "string" &&
|
|
196
|
+
typeof v.url === "string" &&
|
|
197
|
+
typeof v.messageId === "string" &&
|
|
198
|
+
(v.workspaceIndex === undefined ||
|
|
199
|
+
(typeof v.workspaceIndex === "number" && Number.isInteger(v.workspaceIndex) && v.workspaceIndex >= 0));
|
|
200
|
+
|
|
177
201
|
const isThreadEventAttachment = (v: unknown): v is ThreadEventAttachment =>
|
|
178
202
|
isObject(v) &&
|
|
179
203
|
typeof v.mediaType === "string" &&
|
|
180
204
|
typeof v.data === "string" &&
|
|
181
|
-
(v.name === undefined || typeof v.name === "string")
|
|
205
|
+
(v.name === undefined || typeof v.name === "string") &&
|
|
206
|
+
(v.staged === undefined || isThreadEventStagedFile(v.staged));
|
|
182
207
|
|
|
183
208
|
const isThreadEventMode = (v: unknown): v is ThreadEventMode => v === "steer" || v === "wake" || v === "interrupt";
|
|
184
209
|
|
|
@@ -399,6 +424,26 @@ export interface UnitIdle {
|
|
|
399
424
|
wakes: number;
|
|
400
425
|
}
|
|
401
426
|
|
|
427
|
+
/** The durable answer to one indexed idle wait. The wait id is the key on the
|
|
428
|
+
* unit row, so a reclaimed runner receives byte-for-byte the decision the
|
|
429
|
+
* first caller stored instead of spending a renewal or consuming an event
|
|
430
|
+
* twice. */
|
|
431
|
+
export type UnitWakeAnswer =
|
|
432
|
+
| {
|
|
433
|
+
kind: "segment";
|
|
434
|
+
index: number;
|
|
435
|
+
from?: string;
|
|
436
|
+
runId?: string;
|
|
437
|
+
spendUsd: number | null;
|
|
438
|
+
handoff?: Handoff;
|
|
439
|
+
texts: string[];
|
|
440
|
+
senders: string[];
|
|
441
|
+
leaseMs?: number;
|
|
442
|
+
}
|
|
443
|
+
| { kind: "answered"; reply: string }
|
|
444
|
+
| { kind: "stopped" }
|
|
445
|
+
| { kind: "expired" };
|
|
446
|
+
|
|
402
447
|
/** What the severity gate caught on a round: the level in force and the gated findings as `id (severity)`. */
|
|
403
448
|
export interface RoundGate {
|
|
404
449
|
level: AddressSeverity;
|
|
@@ -456,14 +501,20 @@ export interface CoordinatorUnit {
|
|
|
456
501
|
* (null once any run's cost is unknown), `handoff` that child's lists, and
|
|
457
502
|
* `wakes` how many wakes this idle has answered — zero at the write. */
|
|
458
503
|
idle?: UnitIdle;
|
|
504
|
+
/** Answers to indexed idle waits, keyed by the wait step's durable identity. */
|
|
505
|
+
wakes?: Record<string, UnitWakeAnswer>;
|
|
459
506
|
/** The round boundaries the coordinator reported, oldest first (the `ship_round`
|
|
460
507
|
* vocabulary). `gate` rides an approve the machine's severity check caught
|
|
461
508
|
* carrying a finding at or above the level in force ([agent-ship](../../../docs/reference/specs/agent-ship.md)
|
|
462
509
|
* item 9) — a mismatch to be seen, since the child's parser holds an approve
|
|
463
510
|
* to the same level. */
|
|
464
511
|
rounds: Array<{ index: number; agent: string; outcome: string; at: number; gate?: RoundGate }>;
|
|
465
|
-
/** How the unit ended: the ending's kind and the thread's report, when it
|
|
466
|
-
|
|
512
|
+
/** How the unit ended: the ending's kind and the thread's report, when it
|
|
513
|
+
* has. `cause` names the machine's reason behind a driver-posted kind;
|
|
514
|
+
* `step` and `round` locate that reason without parsing the report. For a
|
|
515
|
+
* `step_threw` failure the driver records all available fields before it
|
|
516
|
+
* rethrows (issue 2100); unit-start has no round yet. */
|
|
517
|
+
ending?: { kind: string; report: string; at: number; cause?: string; step?: string; round?: number };
|
|
467
518
|
startedAt?: number;
|
|
468
519
|
}
|
|
469
520
|
|
|
@@ -548,6 +599,27 @@ const isSegment = (v: unknown): boolean =>
|
|
|
548
599
|
(v.runId === undefined || isText(v.runId)) &&
|
|
549
600
|
typeof v.at === "number";
|
|
550
601
|
|
|
602
|
+
export const isUnitWakeAnswer = (v: unknown): v is UnitWakeAnswer => {
|
|
603
|
+
if (!isObject(v)) return false;
|
|
604
|
+
if (v.kind === "answered") return typeof v.reply === "string";
|
|
605
|
+
if (v.kind === "stopped" || v.kind === "expired") return true;
|
|
606
|
+
return (
|
|
607
|
+
v.kind === "segment" &&
|
|
608
|
+
typeof v.index === "number" &&
|
|
609
|
+
Number.isInteger(v.index) &&
|
|
610
|
+
v.index >= 1 &&
|
|
611
|
+
(v.from === undefined || isText(v.from)) &&
|
|
612
|
+
(v.runId === undefined || isText(v.runId)) &&
|
|
613
|
+
(v.spendUsd === null || isFinite(v.spendUsd)) &&
|
|
614
|
+
(v.handoff === undefined || isHandoffShape(v.handoff)) &&
|
|
615
|
+
Array.isArray(v.texts) &&
|
|
616
|
+
v.texts.every((text) => typeof text === "string") &&
|
|
617
|
+
Array.isArray(v.senders) &&
|
|
618
|
+
v.senders.every((sender) => isText(sender)) &&
|
|
619
|
+
(v.leaseMs === undefined || (isFinite(v.leaseMs) && v.leaseMs > 0))
|
|
620
|
+
);
|
|
621
|
+
};
|
|
622
|
+
|
|
551
623
|
export function isCoordinatorUnit(v: unknown): v is CoordinatorUnit {
|
|
552
624
|
if (!isObject(v)) return false;
|
|
553
625
|
const r = v;
|
|
@@ -562,6 +634,13 @@ export function isCoordinatorUnit(v: unknown): v is CoordinatorUnit {
|
|
|
562
634
|
if (r.lastPush !== undefined && !isText(r.lastPush)) return false;
|
|
563
635
|
if (r.segments !== undefined && (!Array.isArray(r.segments) || !r.segments.every(isSegment))) return false;
|
|
564
636
|
if (r.idle !== undefined && !isUnitIdle(r.idle)) return false;
|
|
637
|
+
if (
|
|
638
|
+
r.wakes !== undefined &&
|
|
639
|
+
(!isObject(r.wakes) ||
|
|
640
|
+
Array.isArray(r.wakes) ||
|
|
641
|
+
!Object.entries(r.wakes).every(([waitId, answer]) => STEP_NAME_PATTERN.test(waitId) && isUnitWakeAnswer(answer)))
|
|
642
|
+
)
|
|
643
|
+
return false;
|
|
565
644
|
if (
|
|
566
645
|
!Array.isArray(r.rounds) ||
|
|
567
646
|
r.rounds.length > MAX_ROUNDS ||
|
|
@@ -578,7 +657,16 @@ export function isCoordinatorUnit(v: unknown): v is CoordinatorUnit {
|
|
|
578
657
|
return false;
|
|
579
658
|
if (
|
|
580
659
|
r.ending !== undefined &&
|
|
581
|
-
!(
|
|
660
|
+
!(
|
|
661
|
+
isObject(r.ending) &&
|
|
662
|
+
isText(r.ending.kind) &&
|
|
663
|
+
isText(r.ending.report, MAX_REPORT) &&
|
|
664
|
+
isFinite(r.ending.at) &&
|
|
665
|
+
(r.ending.cause === undefined || isText(r.ending.cause, 64)) &&
|
|
666
|
+
(r.ending.step === undefined || (typeof r.ending.step === "string" && STEP_NAME_PATTERN.test(r.ending.step))) &&
|
|
667
|
+
(r.ending.round === undefined ||
|
|
668
|
+
(typeof r.ending.round === "number" && Number.isInteger(r.ending.round) && r.ending.round >= 0))
|
|
669
|
+
)
|
|
582
670
|
)
|
|
583
671
|
return false;
|
|
584
672
|
if (r.startedAt !== undefined && !isFinite(r.startedAt)) return false;
|