@coreplane/switchboard 1.222.0 → 1.223.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.
|
@@ -328,6 +328,20 @@ workspaceDir: ./workspaces
|
|
|
328
328
|
# harness:
|
|
329
329
|
# coding: pi
|
|
330
330
|
|
|
331
|
+
# What the harness writes into pi's per-run settings for every run on pi
|
|
332
|
+
# (docs/reference/specs/harness-pi.md item 4): pi's compaction thresholds, in
|
|
333
|
+
# tokens, under pi's own names. pi compacts when the context passes the model's
|
|
334
|
+
# window less `reserveTokens` and keeps about `keepRecentTokens` of the newest
|
|
335
|
+
# turns; unset, pi's defaults stand (16384 reserved, 20000 kept) and the file
|
|
336
|
+
# is exactly what it was before this block existed. A reserve near the window
|
|
337
|
+
# makes a short run compact — what a receipt or a test of the compaction path
|
|
338
|
+
# wants; production leaves it unset. Positive integers only; any other shape
|
|
339
|
+
# or key fails the load by name.
|
|
340
|
+
# pi:
|
|
341
|
+
# compaction:
|
|
342
|
+
# reserveTokens: 150000
|
|
343
|
+
# keepRecentTokens: 8000
|
|
344
|
+
|
|
331
345
|
# The fan-out cap a spawning run meets (docs/reference/specs/agent-conductor.md).
|
|
332
346
|
# `agent:conductor` starts child runs as the person who asked — each an
|
|
333
347
|
# ordinary run in a thread of its own, under that person's permissions — and
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.223.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "switchboard",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.223.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.223.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.223.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
package/dist/cli.js
CHANGED
|
@@ -2858,8 +2858,24 @@ function validateConfig(cfg) {
|
|
|
2858
2858
|
if (cfg.routing !== void 0) validateRouting(cfg.routing, cfg.providers);
|
|
2859
2859
|
if (cfg.artifacts !== void 0) validateArtifacts(cfg.artifacts);
|
|
2860
2860
|
if (cfg.harness !== void 0) validateHarness(cfg.harness);
|
|
2861
|
+
if (cfg.pi !== void 0) validatePi(cfg.pi);
|
|
2861
2862
|
validateDashboardConfig(cfg.dashboard);
|
|
2862
2863
|
}
|
|
2864
|
+
function validatePi(pi) {
|
|
2865
|
+
if (typeof pi !== "object" || pi === null || Array.isArray(pi)) throw new Error("config.yaml: pi must be a mapping");
|
|
2866
|
+
for (const key of unknownKeys2(pi, PI_KEYS)) throw new Error(`config.yaml: pi.${key} is not a known key`);
|
|
2867
|
+
const { compaction } = pi;
|
|
2868
|
+
if (compaction === void 0) return;
|
|
2869
|
+
if (typeof compaction !== "object" || compaction === null || Array.isArray(compaction))
|
|
2870
|
+
throw new Error("config.yaml: pi.compaction must be a mapping");
|
|
2871
|
+
for (const key of unknownKeys2(compaction, PI_COMPACTION_KEYS))
|
|
2872
|
+
throw new Error(`config.yaml: pi.compaction.${key} is not a known key`);
|
|
2873
|
+
for (const key of Object.keys(PI_COMPACTION_KEYS)) {
|
|
2874
|
+
const value = compaction[key];
|
|
2875
|
+
if (value !== void 0 && (typeof value !== "number" || !Number.isInteger(value) || value <= 0))
|
|
2876
|
+
throw new Error(`config.yaml: pi.compaction.${key} must be a positive integer (tokens)`);
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2863
2879
|
function validateHarness(harness) {
|
|
2864
2880
|
if (typeof harness !== "object" || harness === null || Array.isArray(harness))
|
|
2865
2881
|
throw new Error("config.yaml: harness must be a mapping of preset to harness (native | pi)");
|
|
@@ -2977,7 +2993,7 @@ function validateRuntimeOverrides(ro) {
|
|
|
2977
2993
|
}
|
|
2978
2994
|
}
|
|
2979
2995
|
}
|
|
2980
|
-
var MAX_INSTRUCTIONS_LENGTH, CONFIG_KEYS, SELF_IMPROVEMENT_KEYS, BOUNDARY_KEYS, MIN_BOUNDARY_MINUTES, ROUTE_ANSWER_MODES, ROUTING_KEYS, SHIP_KEYS, SPAWN_KEYS;
|
|
2996
|
+
var MAX_INSTRUCTIONS_LENGTH, CONFIG_KEYS, SELF_IMPROVEMENT_KEYS, BOUNDARY_KEYS, MIN_BOUNDARY_MINUTES, PI_KEYS, PI_COMPACTION_KEYS, ROUTE_ANSWER_MODES, ROUTING_KEYS, SHIP_KEYS, SPAWN_KEYS;
|
|
2981
2997
|
var init_validate = __esm({
|
|
2982
2998
|
"../../src/config/validate.ts"() {
|
|
2983
2999
|
"use strict";
|
|
@@ -3012,6 +3028,7 @@ var init_validate = __esm({
|
|
|
3012
3028
|
spawn: true,
|
|
3013
3029
|
routing: true,
|
|
3014
3030
|
harness: true,
|
|
3031
|
+
pi: true,
|
|
3015
3032
|
slack: true,
|
|
3016
3033
|
runHistory: true,
|
|
3017
3034
|
runtimeOverrides: true,
|
|
@@ -3026,6 +3043,8 @@ var init_validate = __esm({
|
|
|
3026
3043
|
};
|
|
3027
3044
|
BOUNDARY_KEYS = { maxMinutes: true, maxIdentity: true, machines: true };
|
|
3028
3045
|
MIN_BOUNDARY_MINUTES = 2;
|
|
3046
|
+
PI_KEYS = { compaction: true };
|
|
3047
|
+
PI_COMPACTION_KEYS = { reserveTokens: true, keepRecentTokens: true };
|
|
3029
3048
|
ROUTE_ANSWER_MODES = ["tool", "text"];
|
|
3030
3049
|
ROUTING_KEYS = { auto: true, model: true, answer: true };
|
|
3031
3050
|
SHIP_KEYS = { maxRounds: true, maxMinutes: true };
|
|
@@ -12186,6 +12205,8 @@ var init_costs = __esm({
|
|
|
12186
12205
|
async fetchCostReport(range) {
|
|
12187
12206
|
const rows = [];
|
|
12188
12207
|
let closedThrough = null;
|
|
12208
|
+
const endExclusive = range.partialLastDay ? range.to : addDays2(range.to, 1);
|
|
12209
|
+
if (range.from >= endExclusive) return { rows, closedThrough };
|
|
12189
12210
|
let page2 = null;
|
|
12190
12211
|
for (let i = 0; ; i++) {
|
|
12191
12212
|
if (i >= MAX_COST_PAGES)
|
|
@@ -12194,7 +12215,7 @@ var init_costs = __esm({
|
|
|
12194
12215
|
);
|
|
12195
12216
|
const url = new URL(ANTHROPIC_COST_REPORT);
|
|
12196
12217
|
url.searchParams.set("starting_at", `${range.from}T00:00:00Z`);
|
|
12197
|
-
url.searchParams.set("ending_at", `${
|
|
12218
|
+
url.searchParams.set("ending_at", `${endExclusive}T00:00:00Z`);
|
|
12198
12219
|
url.searchParams.set("bucket_width", "1d");
|
|
12199
12220
|
url.searchParams.append("group_by[]", "workspace_id");
|
|
12200
12221
|
url.searchParams.set("limit", "31");
|
|
@@ -31092,12 +31113,18 @@ function piSystemPrompt(spec) {
|
|
|
31092
31113
|
${harnessPromptNote(spec.relayTools, spec.identity)}
|
|
31093
31114
|
`;
|
|
31094
31115
|
}
|
|
31095
|
-
function piSettingsJson() {
|
|
31096
|
-
|
|
31116
|
+
function piSettingsJson(compaction) {
|
|
31117
|
+
const settings = { defaultProjectTrust: "never", checkForUpdates: false };
|
|
31118
|
+
const thresholds = {
|
|
31119
|
+
...compaction?.reserveTokens !== void 0 ? { reserveTokens: compaction.reserveTokens } : {},
|
|
31120
|
+
...compaction?.keepRecentTokens !== void 0 ? { keepRecentTokens: compaction.keepRecentTokens } : {}
|
|
31121
|
+
};
|
|
31122
|
+
if (Object.keys(thresholds).length > 0) settings.compaction = thresholds;
|
|
31123
|
+
return JSON.stringify(settings, null, 2) + "\n";
|
|
31097
31124
|
}
|
|
31098
31125
|
function piLaunchFiles(spec) {
|
|
31099
31126
|
return [
|
|
31100
|
-
{ path: `${spec.paths.agentDir}/settings.json`, content: piSettingsJson() },
|
|
31127
|
+
{ path: `${spec.paths.agentDir}/settings.json`, content: piSettingsJson(spec.compaction) },
|
|
31101
31128
|
{ path: `${spec.paths.agentDir}/models.json`, content: piModelsJson(spec) },
|
|
31102
31129
|
{ path: `${spec.paths.agentDir}/SYSTEM.md`, content: piSystemPrompt(spec) },
|
|
31103
31130
|
{ path: spec.paths.extension, content: PI_EXTENSION_SOURCE }
|
|
@@ -32210,6 +32237,9 @@ function promptOf(seed) {
|
|
|
32210
32237
|
}
|
|
32211
32238
|
return { message: texts.join("\n\n"), ...images.length > 0 ? { images } : {} };
|
|
32212
32239
|
}
|
|
32240
|
+
function settlementText(s) {
|
|
32241
|
+
return s.action === "synthetic" ? s.text : `The bot restarted while this ${s.toolUse.name} call was in flight; its result was lost \u2014 re-check its effects before re-running it.`;
|
|
32242
|
+
}
|
|
32213
32243
|
function settlementResults(settlements) {
|
|
32214
32244
|
if (settlements.length === 0) return void 0;
|
|
32215
32245
|
return {
|
|
@@ -32217,11 +32247,14 @@ function settlementResults(settlements) {
|
|
|
32217
32247
|
content: settlements.map((s) => ({
|
|
32218
32248
|
type: "tool_result",
|
|
32219
32249
|
toolUseId: s.toolUse.id,
|
|
32220
|
-
content: s
|
|
32250
|
+
content: settlementText(s),
|
|
32221
32251
|
isError: true
|
|
32222
32252
|
}))
|
|
32223
32253
|
};
|
|
32224
32254
|
}
|
|
32255
|
+
function settlementAnswer(s) {
|
|
32256
|
+
return { content: [{ type: "text", text: settlementText(s) }], isError: true };
|
|
32257
|
+
}
|
|
32225
32258
|
async function runPiHarness(deps, run2) {
|
|
32226
32259
|
const { container, clock: clock3 } = deps;
|
|
32227
32260
|
const now = () => clock3();
|
|
@@ -32298,6 +32331,8 @@ async function runPiHarness(deps, run2) {
|
|
|
32298
32331
|
}
|
|
32299
32332
|
};
|
|
32300
32333
|
const forget = deps.registry.register(live);
|
|
32334
|
+
const calls = deps.registry.calls(run2.runId);
|
|
32335
|
+
for (const s of run2.resume?.settlements ?? []) calls?.settle(s.toolUse.id, settlementAnswer(s));
|
|
32301
32336
|
let pid;
|
|
32302
32337
|
let transport;
|
|
32303
32338
|
let facts2;
|
|
@@ -32342,9 +32377,10 @@ async function runPiHarness(deps, run2) {
|
|
|
32342
32377
|
offset: recorded.logOffset
|
|
32343
32378
|
});
|
|
32344
32379
|
catchingUp = true;
|
|
32380
|
+
const inFlight = run2.resume?.settlements.length ?? 0;
|
|
32345
32381
|
note(
|
|
32346
32382
|
"resumed",
|
|
32347
|
-
`resumed after a restart: pi still runs in the container (pid ${pid}); continuing its session with ${Math.round(remainingMs / 6e4)} min of budget left`
|
|
32383
|
+
`resumed after a restart: pi still runs in the container (pid ${pid}); continuing its session with ${Math.round(remainingMs / 6e4)} min of budget left` + (inFlight > 0 ? ` \u2014 ${inFlight} call(s) were in flight, each answered with a restart note if pi asks for it again` : "")
|
|
32348
32384
|
);
|
|
32349
32385
|
} else {
|
|
32350
32386
|
paths = await container.makeRoot(run2.runId);
|
|
@@ -32359,7 +32395,8 @@ async function runPiHarness(deps, run2) {
|
|
|
32359
32395
|
...run2.effort ? { effort: run2.effort } : {},
|
|
32360
32396
|
identity: run2.agent.identity,
|
|
32361
32397
|
system: run2.system,
|
|
32362
|
-
relayTools: run2.tools.map((t) => t.name)
|
|
32398
|
+
relayTools: run2.tools.map((t) => t.name),
|
|
32399
|
+
...deps.compaction ? { compaction: deps.compaction } : {}
|
|
32363
32400
|
};
|
|
32364
32401
|
let session;
|
|
32365
32402
|
if (run2.resume) {
|
|
@@ -32417,7 +32454,9 @@ async function runPiHarness(deps, run2) {
|
|
|
32417
32454
|
}
|
|
32418
32455
|
transport.send({ id: "retry", type: "set_auto_retry", enabled: false });
|
|
32419
32456
|
transport.send({ id: "state", type: "get_state" });
|
|
32420
|
-
if (reattached
|
|
32457
|
+
if (reattached)
|
|
32458
|
+
transport.send({ id: "prompt", type: "prompt", message: CONTINUE_PROMPT, streamingBehavior: "steer" });
|
|
32459
|
+
else if (run2.resume) transport.send({ id: "prompt", type: "prompt", message: CONTINUE_PROMPT });
|
|
32421
32460
|
else transport.send({ id: "prompt", type: "prompt", ...promptOf(run2.messages) });
|
|
32422
32461
|
let warned = false;
|
|
32423
32462
|
let settled = false;
|
|
@@ -33571,6 +33610,9 @@ async function runLoop2(deps, ctx) {
|
|
|
33571
33610
|
harnessUrl,
|
|
33572
33611
|
registry: deps.harness.registry,
|
|
33573
33612
|
...deps.runBearers ? { bearers: deps.runBearers } : {},
|
|
33613
|
+
// The deployment's compaction thresholds ride into pi's settings for
|
|
33614
|
+
// every run on pi (harness-pi item 4); absent, pi's defaults stand.
|
|
33615
|
+
...deps.config.config.pi?.compaction ? { compaction: deps.config.config.pi.compaction } : {},
|
|
33574
33616
|
clock: clock3,
|
|
33575
33617
|
sleep: (ms) => new Promise((r) => setTimeout(r, ms))
|
|
33576
33618
|
},
|
|
@@ -43082,6 +43124,13 @@ var init_relay = __esm({
|
|
|
43082
43124
|
}
|
|
43083
43125
|
return answer;
|
|
43084
43126
|
}
|
|
43127
|
+
/** The call's answer is known before it is asked (harness-pi item 8): the
|
|
43128
|
+
* record's settlement for a call in flight when the previous generation
|
|
43129
|
+
* died, whose extension asks again with the same id. Every ask reads it and
|
|
43130
|
+
* the tool never runs; a call already joined keeps the answer it has. */
|
|
43131
|
+
settle(callId, answer) {
|
|
43132
|
+
if (!this.calls.has(callId)) this.calls.set(callId, Promise.resolve(answer));
|
|
43133
|
+
}
|
|
43085
43134
|
end() {
|
|
43086
43135
|
this.ending.abort();
|
|
43087
43136
|
this.calls.clear();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coreplane/switchboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.223.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",
|