@coreplane/switchboard 1.254.0 → 1.254.1
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.
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchboard",
|
|
3
|
-
"version": "1.254.
|
|
3
|
+
"version": "1.254.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "switchboard",
|
|
9
|
-
"version": "1.254.
|
|
9
|
+
"version": "1.254.1",
|
|
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.254.
|
|
20448
|
+
"version": "1.254.1",
|
|
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.254.
|
|
3
|
+
"version": "1.254.1",
|
|
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
|
@@ -362,7 +362,7 @@ void _everyKindListed;
|
|
|
362
362
|
* the message, the thread's sticky preset, the user or the channel scope's
|
|
363
363
|
* `agent`, `defaults.agent`, or the request router. The replay harness
|
|
364
364
|
* (`load route`) reads it to tell a requester's own choice from a fallback. */
|
|
365
|
-
export type AgentSource = "directive" | "sticky" | "user" | "channel" | "default" | "route";
|
|
365
|
+
export type AgentSource = "directive" | "sticky" | "user" | "channel" | "default" | "route" | "operator";
|
|
366
366
|
|
|
367
367
|
/** How an operator asked a run to stop: `soft` — take no new steps and
|
|
368
368
|
* wrap up through the normal finale; `hard` — abort the in-flight call now, no
|
package/dist/cli.js
CHANGED
|
@@ -41402,11 +41402,17 @@ async function operatorStage(deps, ctx) {
|
|
|
41402
41402
|
function operatorAuthorTurns(tail, author, requestText) {
|
|
41403
41403
|
return [...tail.filter((t) => t.actor === author).map((t) => t.text), requestText];
|
|
41404
41404
|
}
|
|
41405
|
-
function verifierHolds(line3, bound) {
|
|
41406
|
-
if (/^agent:\S/.test(line3.trim())) return true;
|
|
41405
|
+
function verifierHolds(line3, bound, startsRun = false) {
|
|
41406
|
+
if (startsRun || /^agent:\S/.test(line3.trim())) return true;
|
|
41407
41407
|
if (!bound) return false;
|
|
41408
41408
|
return bound.def.id === "steer.run" || bound.radius === "write" || bound.radius === "destructive";
|
|
41409
41409
|
}
|
|
41410
|
+
function presetBindOf(line3, presets) {
|
|
41411
|
+
const trimmed = line3.trim();
|
|
41412
|
+
const head = /^agent:(\S+)/.exec(trimmed);
|
|
41413
|
+
const name = head ? head[1] : /^(\S+)/.exec(trimmed)?.[1];
|
|
41414
|
+
return name !== void 0 && presets.includes(name) ? name : void 0;
|
|
41415
|
+
}
|
|
41410
41416
|
async function verifyOperatorBind(turns, line3, model, opts = {}) {
|
|
41411
41417
|
try {
|
|
41412
41418
|
const answer = await model(verifierPrompt({ turns, line: line3 }), {
|
|
@@ -41433,37 +41439,52 @@ function verifierModelOf(deps) {
|
|
|
41433
41439
|
}
|
|
41434
41440
|
async function executeOperatorDecision(deps, ctx) {
|
|
41435
41441
|
const { event, io, msg } = ctx;
|
|
41442
|
+
const answered = { kind: "answered" };
|
|
41436
41443
|
if (event.outcome === "question") {
|
|
41437
41444
|
await io.reply(event.question ?? "");
|
|
41438
41445
|
await recordOperatorDecision(deps, msg, event, ctx.ending, ctx.trace);
|
|
41439
|
-
return
|
|
41446
|
+
return answered;
|
|
41440
41447
|
}
|
|
41441
41448
|
if (event.outcome === "refusal") {
|
|
41442
41449
|
await io.reply(event.refusalText ?? "");
|
|
41443
41450
|
await recordOperatorDecision(deps, msg, event, ctx.ending, ctx.trace);
|
|
41444
|
-
return
|
|
41451
|
+
return answered;
|
|
41445
41452
|
}
|
|
41446
41453
|
const commands = deps.commands;
|
|
41454
|
+
const presets = routablePresets();
|
|
41455
|
+
const presetNames = presets.map((p) => p.name);
|
|
41447
41456
|
const confirm = effectiveConfirm(deps.config.boundaryLayers(msg.channelId, msg.userId));
|
|
41448
41457
|
let authorTurns;
|
|
41449
41458
|
const authorTurnsOnce = () => authorTurns ??= operatorThreadTail(deps.runLedger, ctx.thread, msg.threadKey).then(
|
|
41450
41459
|
(tail) => operatorAuthorTurns(tail, msg.userId, msg.text)
|
|
41451
41460
|
);
|
|
41452
41461
|
let carried = false;
|
|
41453
|
-
|
|
41454
|
-
|
|
41462
|
+
const binds = event.binds ?? [];
|
|
41463
|
+
for (const [i, bind] of binds.entries()) {
|
|
41464
|
+
const preset = presetBindOf(bind.line, presetNames);
|
|
41465
|
+
const parsed = commands && preset === void 0 ? parseChatCommand(bind.line, commands) : null;
|
|
41455
41466
|
const def = parsed?.kind === "invoke" ? commands?.list().find((c) => c.id === parsed.id) : void 0;
|
|
41456
41467
|
const bound = parsed?.kind === "invoke" && def ? { def, radius: boundBlastRadius(def, parsed.input) } : void 0;
|
|
41457
41468
|
let verified;
|
|
41458
|
-
if (verifierHolds(bind.line, bound)) {
|
|
41469
|
+
if (verifierHolds(bind.line, bound, preset !== void 0)) {
|
|
41459
41470
|
const model = verifierModelOf(deps);
|
|
41460
|
-
const
|
|
41471
|
+
const held2 = preset !== void 0 ? `agent:${preset} ${msg.text}` : bind.line;
|
|
41472
|
+
const verdict = model ? await verifyOperatorBind(await authorTurnsOnce(), held2, model) : { agrees: false, reason: "no model to verify on" };
|
|
41461
41473
|
if (!verdict.agrees) {
|
|
41462
41474
|
await io.reply(renderVerifierHandBack(bind.line, verdict.reason));
|
|
41463
41475
|
continue;
|
|
41464
41476
|
}
|
|
41465
41477
|
verified = renderVerifierLine(verdict.reason);
|
|
41466
41478
|
}
|
|
41479
|
+
if (preset !== void 0) {
|
|
41480
|
+
const identity2 = presets.find((p) => p.name === preset)?.identity;
|
|
41481
|
+
const radius2 = identity2 === "write" ? "write" : "read";
|
|
41482
|
+
await io.reply(`${renderOperatorReceipt(bind.line, radius2, bind.reason)}${verified ? `
|
|
41483
|
+
${verified}` : ""}`);
|
|
41484
|
+
for (const rest of binds.slice(i + 1)) await io.reply(`${HAND_BACK_PREFIX}
|
|
41485
|
+
\`${rest.line}\``);
|
|
41486
|
+
return { kind: "route", preset, line: bind.line, reason: bind.reason };
|
|
41487
|
+
}
|
|
41467
41488
|
if (!parsed || parsed.kind !== "invoke" || !def || !bound) {
|
|
41468
41489
|
await io.reply(`${verified ? `${verified}
|
|
41469
41490
|
` : ""}${HAND_BACK_PREFIX}
|
|
@@ -41486,7 +41507,7 @@ ${HAND_BACK_PREFIX}
|
|
|
41486
41507
|
if (res.text.length > 0) await io.reply(res.text);
|
|
41487
41508
|
}
|
|
41488
41509
|
if (!carried) await recordOperatorDecision(deps, msg, event, ctx.ending, ctx.trace);
|
|
41489
|
-
return
|
|
41510
|
+
return answered;
|
|
41490
41511
|
}
|
|
41491
41512
|
var OPERATOR_TOOL_NAME, OPERATOR_TIMEOUT_MS, OPERATOR_MAX_BINDS, OPERATOR_QUESTION_MARKER;
|
|
41492
41513
|
var init_operator = __esm({
|
|
@@ -51506,8 +51527,10 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
51506
51527
|
}
|
|
51507
51528
|
};
|
|
51508
51529
|
try {
|
|
51509
|
-
const
|
|
51530
|
+
const configuredOperator = !resume && !restart && !opts.parent && !opts.coordinator ? operatorModeOf(deps.config.config) : "off";
|
|
51531
|
+
const operatorMode = configuredOperator === "on" && parseDirectives(msg.text).agent !== void 0 ? "off" : configuredOperator;
|
|
51510
51532
|
let operatorEvent;
|
|
51533
|
+
let operatorPreset;
|
|
51511
51534
|
let operatorThread;
|
|
51512
51535
|
if (operatorMode !== "off") {
|
|
51513
51536
|
const runsService2 = deps.runs ?? createRunsService({ registry, store: deps.runStore });
|
|
@@ -51527,7 +51550,7 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
51527
51550
|
registry.publish(live.runId, { type: "operator", ...operatorEvent, at: clock4() });
|
|
51528
51551
|
operatorEvent = void 0;
|
|
51529
51552
|
} else if (operatorMode === "on" && operatorEvent && !operatorFellBack) {
|
|
51530
|
-
await root.span(
|
|
51553
|
+
const execution = await root.span(
|
|
51531
51554
|
"dispatch.operator_decision",
|
|
51532
51555
|
() => executeOperatorDecision(deps, {
|
|
51533
51556
|
msg,
|
|
@@ -51538,12 +51561,14 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
51538
51561
|
...operatorThread ? { thread: operatorThread } : {}
|
|
51539
51562
|
})
|
|
51540
51563
|
);
|
|
51541
|
-
return ended;
|
|
51564
|
+
if (execution.kind === "answered") return ended;
|
|
51565
|
+
operatorPreset = execution.preset;
|
|
51542
51566
|
}
|
|
51543
51567
|
}
|
|
51544
|
-
if (await answerChatCommand(deps, { msg, io, ending, trace, ...operatorEvent ? { operator: operatorEvent } : {} }))
|
|
51568
|
+
if (operatorPreset === void 0 && await answerChatCommand(deps, { msg, io, ending, trace, ...operatorEvent ? { operator: operatorEvent } : {} }))
|
|
51545
51569
|
return ended;
|
|
51546
51570
|
const { directives, history } = await readRequest({ msg, io, root });
|
|
51571
|
+
if (operatorPreset !== void 0) directives.agent = operatorPreset;
|
|
51547
51572
|
const runsService = deps.runs ?? createRunsService({ registry, store: deps.runStore });
|
|
51548
51573
|
const thread = opts.thread ?? (opts.parent || opts.coordinator || resume || restart || history.length === 0 ? void 0 : operatorThread ?? await readThread(runsService, msg.threadKey));
|
|
51549
51574
|
const lineage = lineageOf(thread?.[0]);
|
|
@@ -51567,6 +51592,7 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
51567
51592
|
});
|
|
51568
51593
|
const { sticky } = settled;
|
|
51569
51594
|
let { resolved, agentSource } = settled;
|
|
51595
|
+
if (operatorPreset !== void 0) agentSource = "operator";
|
|
51570
51596
|
let route3;
|
|
51571
51597
|
const threadLive = admission.get(msg.threadKey) !== void 0 || !resume && !restart && deps.threadsElsewhere.get(msg.threadKey) !== void 0;
|
|
51572
51598
|
if (thread && !threadLive && directives.agent === void 0 && deps.coordinatorInstances !== void 0) {
|
|
@@ -52504,6 +52530,7 @@ var init_dispatcher = __esm({
|
|
|
52504
52530
|
init_references();
|
|
52505
52531
|
init_actor();
|
|
52506
52532
|
init_config2();
|
|
52533
|
+
init_directives();
|
|
52507
52534
|
init_resolve();
|
|
52508
52535
|
init_route();
|
|
52509
52536
|
init_operator();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coreplane/switchboard",
|
|
3
|
-
"version": "1.254.
|
|
3
|
+
"version": "1.254.1",
|
|
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",
|