@coreplane/switchboard 1.219.0 → 1.220.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/Dockerfile +16 -0
- package/dist/assets/config/config.example.yaml +4 -2
- 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 +4 -3
- package/dist/assets/src/core/runEvents.ts +6 -0
- package/dist/assets/src/core/runFriction.ts +11 -0
- package/dist/assets/src/core/runRecord.ts +35 -0
- package/dist/cli.js +3017 -2353
- package/package.json +1 -1
package/dist/assets/Dockerfile
CHANGED
|
@@ -71,6 +71,22 @@ RUN apt-get update \
|
|
|
71
71
|
COPY --from=meat /go/bin/meat /usr/local/bin/meat
|
|
72
72
|
RUN command -v meat >/dev/null && meat -h >/dev/null 2>&1
|
|
73
73
|
|
|
74
|
+
# pi (docs/reference/specs/harness-pi.md item 12): the harness for a preset
|
|
75
|
+
# without a workspace (general, research, conductor) runs pi as a child of
|
|
76
|
+
# the bot itself, since such a run has no execution container. The same layer
|
|
77
|
+
# as the execution images', on this image's Node (the same 24 tag), installed
|
|
78
|
+
# globally as root before the switch to the bot's user, so `switchboard` finds
|
|
79
|
+
# it on PATH and cannot alter it; at an EXACT pin held equal across the three
|
|
80
|
+
# images by src/deploy/imagePiHarness.test.ts (the pnpm lesson: a floating tag
|
|
81
|
+
# would move the harness's protocol with the build date). Proven by the layer,
|
|
82
|
+
# so the BUILD fails, not a run. Dark until a deployment sets
|
|
83
|
+
# `harness: { general: pi }`: nothing here starts pi on its own, and a run's
|
|
84
|
+
# pi on this host holds none of pi's own shell or file tools.
|
|
85
|
+
RUN npm install -g @earendil-works/pi-coding-agent@0.85.1 \
|
|
86
|
+
&& npm cache clean --force \
|
|
87
|
+
&& pi --version | grep -qx '0.85.1' \
|
|
88
|
+
&& pi --help | grep -q -- '--mode <mode>'
|
|
89
|
+
|
|
74
90
|
# Non-root user; agents run bash with this user's (container-scoped) permissions.
|
|
75
91
|
RUN useradd -m -u 1001 switchboard
|
|
76
92
|
WORKDIR /app
|
|
@@ -320,8 +320,10 @@ workspaceDir: ./workspaces
|
|
|
320
320
|
# with the run's model-proxy bearer as its only key, every event bridged onto
|
|
321
321
|
# the run's own record, our tools and tool rules as its extension. Every
|
|
322
322
|
# preset declares `native` until the pi series moves it; a deployment moves a
|
|
323
|
-
# preset early here.
|
|
324
|
-
#
|
|
323
|
+
# preset early here. A preset with a workspace (coding, review, explore) runs
|
|
324
|
+
# pi in the run's container; a preset without one (general, research,
|
|
325
|
+
# conductor) runs it as a child of the bot, with none of pi's own shell or
|
|
326
|
+
# file tools. A preset the registry does not know, or a value that is
|
|
325
327
|
# neither harness, fails the load by name.
|
|
326
328
|
# harness:
|
|
327
329
|
# coding: pi
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.220.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "switchboard",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.220.0",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"workspaces": [
|
|
12
12
|
"web",
|
|
@@ -16710,7 +16710,7 @@
|
|
|
16710
16710
|
},
|
|
16711
16711
|
"packages/switchboard": {
|
|
16712
16712
|
"name": "@coreplane/switchboard",
|
|
16713
|
-
"version": "1.
|
|
16713
|
+
"version": "1.220.0",
|
|
16714
16714
|
"license": "Apache-2.0",
|
|
16715
16715
|
"dependencies": {
|
|
16716
16716
|
"@anthropic-ai/sdk": "^0.124.0",
|
package/dist/assets/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.220.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
|
@@ -121,8 +121,9 @@ export interface AgentDef {
|
|
|
121
121
|
residentSystem?: string;
|
|
122
122
|
/** Which loop drives the preset's runs (`HARNESSES`): the native loop
|
|
123
123
|
* unless declared, and whatever a deployment's `harness.<preset>` says
|
|
124
|
-
* over that.
|
|
125
|
-
*
|
|
124
|
+
* over that. A preset with a workspace runs pi in the run's execution
|
|
125
|
+
* container; a preset without one (machine class `none`) runs it as a
|
|
126
|
+
* child of the bot, with none of pi's own tools. */
|
|
126
127
|
harness?: Harness;
|
|
127
128
|
}
|
|
128
129
|
|
|
@@ -602,7 +603,7 @@ const WORK_PRESETS = {
|
|
|
602
603
|
explore: {
|
|
603
604
|
name: "explore",
|
|
604
605
|
description:
|
|
605
|
-
"
|
|
606
|
+
"Read-only investigation of a repository in a cold sandbox: runs builds, suites and pipelines, searches the web, and reports a claim table with commands and numbers. Never opens a PR; cannot attach or post files.",
|
|
606
607
|
system: EXPLORE_SYSTEM,
|
|
607
608
|
toolset: "explore",
|
|
608
609
|
// Always a cold per-thread sandbox with the checkout, never the resident a
|
|
@@ -71,6 +71,11 @@ export type RunNoteKind =
|
|
|
71
71
|
* executor's bounded wait (docs/reference/specs/execution.md item 14). Capacity, not a
|
|
72
72
|
* dead sandbox: the run goes on and the model is told to retry or finish. */
|
|
73
73
|
| "fleet_busy"
|
|
74
|
+
/** The sandbox restarted under the run and came back (docs/reference/specs/
|
|
75
|
+
* resident-repos.md item 65): the executor waited for the resident's wake
|
|
76
|
+
* and re-attached; the interrupted call was settled with a synthetic
|
|
77
|
+
* result (run-loop.md item 19) and the run goes on. */
|
|
78
|
+
| "sandbox_restarted"
|
|
74
79
|
| "stop_requested"
|
|
75
80
|
| "stopped"
|
|
76
81
|
/** Setup spans the request's stream sink had to drop before this run was
|
|
@@ -154,6 +159,7 @@ export const RUN_NOTE_KINDS = [
|
|
|
154
159
|
"turn_budget_exhausted",
|
|
155
160
|
"sandbox_dead",
|
|
156
161
|
"fleet_busy",
|
|
162
|
+
"sandbox_restarted",
|
|
157
163
|
"stop_requested",
|
|
158
164
|
"stopped",
|
|
159
165
|
"spans_dropped",
|
|
@@ -562,6 +562,17 @@ export function analyzeRunFriction(events: readonly RunEvent[], opts: FrictionOp
|
|
|
562
562
|
eventIndex: index,
|
|
563
563
|
});
|
|
564
564
|
return;
|
|
565
|
+
case "sandbox_restarted":
|
|
566
|
+
// The container rolled under the run and came back: the run went on,
|
|
567
|
+
// but the minutes spent waiting for the wake are friction the deploy
|
|
568
|
+
// window owns.
|
|
569
|
+
findings.push({
|
|
570
|
+
category: "infra_failure",
|
|
571
|
+
severity: "medium",
|
|
572
|
+
summary: `sandbox restarted: ${ev.summary}`,
|
|
573
|
+
eventIndex: index,
|
|
574
|
+
});
|
|
575
|
+
return;
|
|
565
576
|
}
|
|
566
577
|
});
|
|
567
578
|
// A slow turn whose produced event is past the stream (a turn that ended the run).
|
|
@@ -158,6 +158,39 @@ export interface RunRecord {
|
|
|
158
158
|
* on records written before the session log existed and on runs without
|
|
159
159
|
* a conversation of their own. */
|
|
160
160
|
session?: RunSession;
|
|
161
|
+
/** The pull request the run's post-step opened or edited (item 2): the last
|
|
162
|
+
* `pr_opened` event, folded at the assembly. Present only on a run that
|
|
163
|
+
* reached one. A follow-up in the thread continues on its head branch
|
|
164
|
+
* (docs/reference/specs/resident-repos.md item 29) — read off the record,
|
|
165
|
+
* never off the reply's text. */
|
|
166
|
+
pr?: RunPullRequest;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** A pull request as the record names it (item 2): its number and its GitHub
|
|
170
|
+
* URL, both from the `pr_opened` event the coding post-step published. */
|
|
171
|
+
export interface RunPullRequest {
|
|
172
|
+
number: number;
|
|
173
|
+
url: string;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** The pull request a run's events say it opened or edited — the last
|
|
177
|
+
* `pr_opened` wins, as an edit after an open names the same PR — or nothing. */
|
|
178
|
+
export function prOfEvents(events: readonly RunEvent[]): RunPullRequest | undefined {
|
|
179
|
+
let pr: RunPullRequest | undefined;
|
|
180
|
+
for (const e of events) if (e.type === "pr_opened") pr = { number: e.number, url: e.url };
|
|
181
|
+
return pr;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function isRunPullRequestShape(v: unknown): v is RunPullRequest {
|
|
185
|
+
if (typeof v !== "object" || v === null) return false;
|
|
186
|
+
const p = v as Record<string, unknown>;
|
|
187
|
+
return (
|
|
188
|
+
typeof p.number === "number" &&
|
|
189
|
+
Number.isInteger(p.number) &&
|
|
190
|
+
p.number > 0 &&
|
|
191
|
+
typeof p.url === "string" &&
|
|
192
|
+
p.url.length > 0
|
|
193
|
+
);
|
|
161
194
|
}
|
|
162
195
|
|
|
163
196
|
/** The three places a run's conversation can start (item 52): the thread's
|
|
@@ -574,6 +607,8 @@ export function isRunRecord(v: unknown): v is RunRecord {
|
|
|
574
607
|
if (r.dispositions !== undefined && !isFindingDispositionsShape(r.dispositions)) return false;
|
|
575
608
|
if (r.reviewPost !== undefined && !isReviewPostShape(r.reviewPost)) return false;
|
|
576
609
|
if (r.profile !== undefined && !isRunProfileRecord(r.profile)) return false;
|
|
610
|
+
// The pull request the run reached (item 2): a positive integer and a URL, or absent.
|
|
611
|
+
if (r.pr !== undefined && !isRunPullRequestShape(r.pr)) return false;
|
|
577
612
|
// A parent is named by a run id (item 46): the same shape as the record's own.
|
|
578
613
|
if (r.parentRunId !== undefined && (typeof r.parentRunId !== "string" || !RUN_ID_PATTERN.test(r.parentRunId)))
|
|
579
614
|
return false;
|