@coreplane/switchboard 1.212.0 → 1.213.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/README.md +5 -3
- package/dist/assets/config/config.example.yaml +44 -0
- package/dist/assets/deploy/cloudflare/worker.ts +6 -0
- package/dist/assets/deploy/cloudflare-resident/Dockerfile +24 -0
- package/dist/assets/deploy/cloudflare-resident/worker.ts +353 -18
- package/dist/assets/deploy/cloudflare-resident/wrangler.template.jsonc +9 -1
- package/dist/assets/deploy/cloudflare-sandbox/Dockerfile +18 -0
- package/dist/assets/deploy/secrets.manifest.json +18 -0
- package/dist/assets/package-lock.json +5 -3
- package/dist/assets/package.json +2 -1
- package/dist/assets/source.json +3 -3
- package/dist/assets/src/agents/registry.ts +37 -0
- package/dist/assets/src/core/redact.ts +11 -1
- package/dist/assets/src/core/runEvents.ts +41 -1
- package/dist/assets/src/core/runFriction.ts +6 -4
- package/dist/assets/src/core/trace/workerTrace.ts +4 -0
- package/dist/assets/src/execution/residentRefresh.ts +151 -5
- package/dist/assets/web/dist/.vite/manifest.json +19 -19
- package/dist/assets/web/dist/assets/{ResidentDetailPage-CM5nWw-Z.js → ResidentDetailPage-CvwjhjlG.js} +1 -1
- package/dist/assets/web/dist/assets/{ResidentsIndexPage-BKBnuvp3.js → ResidentsIndexPage-DoN6XuNx.js} +1 -1
- package/dist/assets/web/dist/assets/RunRoutePage-FzLNexjF.js +12 -0
- package/dist/assets/web/dist/assets/{RunsIndexPage-w2jJP5xu.js → RunsIndexPage-DhSUbF9k.js} +1 -1
- package/dist/assets/web/dist/assets/{ScheduledPage-D3-k9DPz.js → ScheduledPage-Bq0Yg4nT.js} +1 -1
- package/dist/assets/web/dist/assets/{StatusDot-BmFHnV8m.js → StatusDot-D8Wwt1KC.js} +1 -1
- package/dist/assets/web/dist/assets/{Tooltip-DoThP2fW.js → Tooltip-DpDK7jWZ.js} +1 -1
- package/dist/assets/web/dist/assets/{dist-YrRKtxsS.js → dist-B7BVkB7x.js} +1 -1
- package/dist/assets/web/dist/assets/{main-D6nzMf0k.js → main-BFkEOy3K.js} +2 -2
- package/dist/assets/web/dist/assets/main-DCH3Mezs.css +1 -0
- package/dist/cli.js +2336 -328
- package/package.json +2 -1
- package/dist/assets/web/dist/assets/RunRoutePage-Bu4CwEzt.js +0 -12
- package/dist/assets/web/dist/assets/main-CuENKPdD.css +0 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
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.
|
|
11
11
|
|
|
12
12
|
<p align="center">
|
|
13
|
-
<img alt="A review in a Slack thread:
|
|
13
|
+
<img alt="A review in a Slack thread: a plain request to look at a pull request, the card naming the agent it picked and why, then the verdict with its findings." src="https://raw.githubusercontent.com/coreplanelabs/switchboard/HEAD/docs/public/slack/run.gif" width="395">
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
16
|
<picture>
|
|
@@ -33,7 +33,7 @@ Next: [Get started](https://github.com/coreplanelabs/switchboard/blob/HEAD/docs/
|
|
|
33
33
|
|
|
34
34
|
## How it is put together
|
|
35
35
|
|
|
36
|
-
Four seams: Channel, Provider, Executor, Agent. Each is an interface with more than one implementation. The dispatcher sits between them:
|
|
36
|
+
Four seams: Channel, Provider, Executor, Agent. Each is an interface with more than one implementation. The dispatcher sits between them: it reads what you asked for and picks the agent, resolves the model through the config layers, checks authorization and runs the agent loop ([How a request flows](https://github.com/coreplanelabs/switchboard/blob/HEAD/docs/explanation/how-a-request-flows.md)).
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
## What you need
|
|
@@ -47,8 +47,10 @@ Four seams: Channel, Provider, Executor, Agent. Each is an interface with more t
|
|
|
47
47
|
| Optional | An E2B account | Per-thread micro-VMs without Cloudflare |
|
|
48
48
|
| Optional | A Brave Search key (`BRAVE_SEARCH_API_KEY`) | Web search for the research agent |
|
|
49
49
|
|
|
50
|
-
Off means
|
|
50
|
+
Off means the bot never offers it and the dashboard and the plan never show it ([Turn features on and off](https://github.com/coreplanelabs/switchboard/blob/HEAD/docs/how-to/turn-features-on-and-off.md)). The bot is `npx @coreplane/switchboard start` on any machine with Node, or the published image `ghcr.io/coreplanelabs/switchboard`.
|
|
51
51
|
|
|
52
52
|
## Learn more
|
|
53
53
|
|
|
54
54
|
Docs: <https://openswitchboard.dev> ([`docs/`](https://github.com/coreplanelabs/switchboard/blob/HEAD/docs/README.md)) · [CONTRIBUTING.md](https://github.com/coreplanelabs/switchboard/blob/HEAD/CONTRIBUTING.md) · [AGENTS.md](https://github.com/coreplanelabs/switchboard/blob/HEAD/AGENTS.md) · [SECURITY.md](https://github.com/coreplanelabs/switchboard/blob/HEAD/SECURITY.md) · [Apache-2.0](https://github.com/coreplanelabs/switchboard/blob/HEAD/LICENSE).
|
|
55
|
+
|
|
56
|
+
Going deeper: commands and directives exist for whoever wants to type them ([Slack commands](https://github.com/coreplanelabs/switchboard/blob/HEAD/docs/reference/slack-commands.md)); a plain sentence needs none.
|
|
@@ -212,6 +212,27 @@ execution:
|
|
|
212
212
|
# Under docker compose this directory is a named volume, so checkouts survive a restart.
|
|
213
213
|
workspaceDir: ./workspaces
|
|
214
214
|
|
|
215
|
+
# The artifact store (docs/reference/specs/execution.md item 20): one private R2
|
|
216
|
+
# bucket a run's files move through by reference — a screenshot a coding run
|
|
217
|
+
# attaches, a video a person drops on a thread. DEFAULT OFF: absent means no
|
|
218
|
+
# store; attach_file keeps its inline path (10 MiB cap) and an inbound video is
|
|
219
|
+
# skipped with its name, exactly as before. Configured, the bot signs presigned
|
|
220
|
+
# URLs and the container moves the bytes; the bot never holds a file. Needs
|
|
221
|
+
# three bot secrets — ARTIFACTS_R2_ACCESS_KEY_ID and ARTIFACTS_R2_SECRET_ACCESS_KEY
|
|
222
|
+
# (an R2 API token scoped Object Read & Write to this bucket only) and
|
|
223
|
+
# ARTIFACTS_COPY_TOKEN (self-minted, shared with the bot's own Worker) — and
|
|
224
|
+
# PUBLIC_BASE_URL; a configured store with any of them unset fails startup by
|
|
225
|
+
# name. `deploy` creates the bucket; `artifacts lifecycle` applies retention;
|
|
226
|
+
# `artifacts check` reads whether the bucket is private.
|
|
227
|
+
# artifacts:
|
|
228
|
+
# r2:
|
|
229
|
+
# accountId: <your Cloudflare account id> # the S3 endpoint is <accountId>.r2.cloudflarestorage.com
|
|
230
|
+
# bucket: switchboard-artifacts # the bot's Worker binds the same name
|
|
231
|
+
# retentionDays: 30 # objects expire after this many days (default 30)
|
|
232
|
+
# inbound:
|
|
233
|
+
# maxBytesPerMessage: 2147483648 # the most staged bytes one message may carry (default 2 GiB)
|
|
234
|
+
# copyTimeoutMs: 1200000 # how long the bot waits on one inbound copy (default 20 min)
|
|
235
|
+
|
|
215
236
|
# Cross-session self-learning memory (docs/reference/specs/memory.md). DEFAULT OFF: absent, or
|
|
216
237
|
# enabled:false, means the dispatcher uses a NullMemoryStore and the model input
|
|
217
238
|
# is byte-identical to memory-off — zero behavior change. When enabled, before
|
|
@@ -293,6 +314,18 @@ workspaceDir: ./workspaces
|
|
|
293
314
|
# maxRounds: 3 # review rounds per unit
|
|
294
315
|
# maxMinutes: 120 # the ship preset's wall-clock budget in minutes (the registry's default)
|
|
295
316
|
|
|
317
|
+
# Which loop drives each preset's runs (docs/reference/specs/harness-pi.md):
|
|
318
|
+
# `native`, the in-process turn loop, or `pi`, the pi coding agent started
|
|
319
|
+
# inside the run's own execution container and driven over its RPC protocol —
|
|
320
|
+
# with the run's model-proxy bearer as its only key, every event bridged onto
|
|
321
|
+
# the run's own record, our tools and tool rules as its extension. Every
|
|
322
|
+
# preset declares `native` until the pi series moves it; a deployment moves a
|
|
323
|
+
# preset early here. Only a preset with a workspace (coding, review, explore)
|
|
324
|
+
# can run on pi. A preset the registry does not know, or a value that is
|
|
325
|
+
# neither harness, fails the load by name.
|
|
326
|
+
# harness:
|
|
327
|
+
# coding: pi
|
|
328
|
+
|
|
296
329
|
# The fan-out cap a spawning run meets (docs/reference/specs/agent-conductor.md).
|
|
297
330
|
# `agent:conductor` starts child runs as the person who asked — each an
|
|
298
331
|
# ordinary run in a thread of its own, under that person's permissions — and
|
|
@@ -302,6 +335,17 @@ workspaceDir: ./workspaces
|
|
|
302
335
|
# spawn:
|
|
303
336
|
# maxChildren: 3
|
|
304
337
|
|
|
338
|
+
# The request router (docs/reference/specs/routing-and-config.md item 21). ON BY
|
|
339
|
+
# DEFAULT: a plain message — no `agent:` directive, no sticky preset, no channel
|
|
340
|
+
# or user `agent` — asks the fast model which preset it means and runs as that
|
|
341
|
+
# preset, the card saying why (`routed: <reason>`) and how to run it another way.
|
|
342
|
+
# `ship` is never routed. The one way off, so every plain message runs
|
|
343
|
+
# `defaults.agent` as before the router: `auto: false`. `model` is the router's
|
|
344
|
+
# model; default `defaults.models.general`.
|
|
345
|
+
# routing:
|
|
346
|
+
# auto: false
|
|
347
|
+
# model: anthropic/claude-haiku-4-5
|
|
348
|
+
|
|
305
349
|
# Spend reporting: GET /costs (Access-gated). Optional. See docs/reference/specs/costs.md.
|
|
306
350
|
# costs:
|
|
307
351
|
# cloudflareAccountId: <32-hex account id>
|
|
@@ -90,6 +90,9 @@ export interface Env {
|
|
|
90
90
|
MEMORY_TOKEN?: string; // durable memory + friction ledger + schedule firings + MCP registry: bearer for the state Worker
|
|
91
91
|
MCP_CREDENTIAL_KEY?: string; // MCP registry: the bot-only key that seals server credentials before they reach the McpDO
|
|
92
92
|
STATE_WORKER_URL?: string; // var: the state Worker's base URL — where this shim records each scheduled firing
|
|
93
|
+
ARTIFACTS_R2_ACCESS_KEY_ID?: string; // artifact store: the bucket-scoped S3 token the bot signs presigned URLs with
|
|
94
|
+
ARTIFACTS_R2_SECRET_ACCESS_KEY?: string; // artifact store: the secret half of that token
|
|
95
|
+
ARTIFACTS_COPY_TOKEN?: string; // artifact store: the bearer the bot presents to this Worker's /artifacts/copy route
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
/** Every secret/var the Worker forwards into the container. Optional entries
|
|
@@ -115,6 +118,9 @@ const FORWARDED_OPTIONAL = [
|
|
|
115
118
|
"MEMORY_TOKEN",
|
|
116
119
|
"MCP_CREDENTIAL_KEY",
|
|
117
120
|
"STATE_WORKER_URL",
|
|
121
|
+
"ARTIFACTS_R2_ACCESS_KEY_ID",
|
|
122
|
+
"ARTIFACTS_R2_SECRET_ACCESS_KEY",
|
|
123
|
+
"ARTIFACTS_COPY_TOKEN",
|
|
118
124
|
] as const satisfies readonly (keyof Env)[];
|
|
119
125
|
|
|
120
126
|
/** The container's environment, computed from the Worker env AT START TIME.
|
|
@@ -153,6 +153,24 @@ RUN apt-get update \
|
|
|
153
153
|
&& playwright screenshot --viewport-size=640,480 'data:text/html,<h1>ok</h1>' /tmp/ok.png && test -s /tmp/ok.png \
|
|
154
154
|
&& rm -f /tmp/proof.mp4 /tmp/proof_*.png /tmp/ok.png
|
|
155
155
|
|
|
156
|
+
# pi — the coding harness the bot can start INSIDE this container in place of
|
|
157
|
+
# its native turn loop (docs/reference/specs/harness-pi.md): `pi --mode rpc`,
|
|
158
|
+
# one process per run in the thread's worktree, driven by the bot over its
|
|
159
|
+
# JSONL protocol, with the run's model-proxy bearer as its only key (never a
|
|
160
|
+
# model key: the bearer buys calls through the bot, docs/reference/specs/
|
|
161
|
+
# model-proxy.md). Installed globally with this image's Node — pi needs
|
|
162
|
+
# >= 22.19.0 and the image ships 24 — so every user finds it on PATH, at an
|
|
163
|
+
# EXACT pin held by src/deploy/imagePiHarness.test.ts (the pnpm lesson: a
|
|
164
|
+
# floating tag would move the harness's protocol with the build date, and a
|
|
165
|
+
# pi minor changes RPC events and extension hooks). Proven by the layer, so
|
|
166
|
+
# the BUILD fails, not a run: the pi on PATH answers the pin, and its own help
|
|
167
|
+
# names the RPC mode the harness drives. Dark until a deployment sets
|
|
168
|
+
# `harness: { coding: pi }`: nothing here starts pi on its own.
|
|
169
|
+
RUN npm install -g @earendil-works/pi-coding-agent@0.85.1 \
|
|
170
|
+
&& npm cache clean --force \
|
|
171
|
+
&& pi --version | grep -qx '0.85.1' \
|
|
172
|
+
&& pi --help | grep -q -- '--mode <mode>'
|
|
173
|
+
|
|
156
174
|
# Agent commands never run as root (repo code runs unprivileged, one user per
|
|
157
175
|
# thread — docs/reference/specs/resident-repos.md). The SDK's exec has no user/uid option
|
|
158
176
|
# (verified against 0.13.0-next.751.1), so the container server itself runs as
|
|
@@ -175,3 +193,9 @@ RUN set -eux; \
|
|
|
175
193
|
# browser tree under /opt and launch it, so the BUILD fails if a chmod or the
|
|
176
194
|
# path ever regresses, not a run.
|
|
177
195
|
RUN su -s /bin/bash worker1 -c "playwright screenshot --viewport-size=640,480 'data:text/html,<h1>ok</h1>' /tmp/ok.png && test -s /tmp/ok.png && rm -f /tmp/ok.png"
|
|
196
|
+
|
|
197
|
+
# pi once more, as worker1: a run's pi is started as the thread's user through
|
|
198
|
+
# the same `su`, so the BUILD proves an unprivileged user finds the pin on PATH
|
|
199
|
+
# and pi answers without a writable home (its config directory is the run's
|
|
200
|
+
# own, named by PI_CODING_AGENT_DIR at start).
|
|
201
|
+
RUN su -s /bin/bash worker1 -c "pi --version | grep -qx '0.85.1'"
|