@koda-sl/baker-bridge 0.168.0-dev.d78500250 → 0.169.0-dev.e03ffd565
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 +47 -50
- package/dist/hono/agent.d.ts.map +1 -1
- package/dist/hono/agent.js +3 -3
- package/dist/hono/agent.js.map +1 -1
- package/dist/hono/agent.test.js +91 -175
- package/dist/hono/agent.test.js.map +1 -1
- package/dist/hono/attachments.d.ts.map +1 -1
- package/dist/hono/attachments.js +9 -1
- package/dist/hono/attachments.js.map +1 -1
- package/dist/hono/attachments.test.js +22 -1
- package/dist/hono/attachments.test.js.map +1 -1
- package/dist/hono/bridge-job.d.ts +7 -19
- package/dist/hono/bridge-job.d.ts.map +1 -1
- package/dist/hono/bridge-job.js +31 -110
- package/dist/hono/bridge-job.js.map +1 -1
- package/dist/hono/bridge-job.test.js +44 -184
- package/dist/hono/bridge-job.test.js.map +1 -1
- package/dist/hono/flow-input-card-fields.test.js +1 -1
- package/dist/hono/flow-input.d.ts +1 -1
- package/dist/hono/flow-input.js +1 -1
- package/dist/hono/main-sync.d.ts +22 -0
- package/dist/hono/main-sync.d.ts.map +1 -1
- package/dist/hono/main-sync.js +110 -2
- package/dist/hono/main-sync.js.map +1 -1
- package/dist/hono/main-sync.test.js +127 -1
- package/dist/hono/main-sync.test.js.map +1 -1
- package/dist/hono/openrouter-session.d.ts +13 -16
- package/dist/hono/openrouter-session.d.ts.map +1 -1
- package/dist/hono/openrouter-session.js +13 -16
- package/dist/hono/openrouter-session.js.map +1 -1
- package/dist/hono/publish-handoff.d.ts +0 -1
- package/dist/hono/publish-handoff.d.ts.map +1 -1
- package/dist/hono/publish-handoff.js +0 -53
- package/dist/hono/publish-handoff.js.map +1 -1
- package/dist/hono/publish-handoff.test.js +0 -48
- package/dist/hono/publish-handoff.test.js.map +1 -1
- package/dist/hono/relay.d.ts +0 -8
- package/dist/hono/relay.d.ts.map +1 -1
- package/dist/hono/relay.js +0 -2
- package/dist/hono/relay.js.map +1 -1
- package/dist/hono/relay.test.js +0 -24
- package/dist/hono/relay.test.js.map +1 -1
- package/dist/hono/runtime-files.d.ts +0 -1
- package/dist/hono/runtime-files.d.ts.map +1 -1
- package/dist/hono/runtime-files.js +0 -3
- package/dist/hono/runtime-files.js.map +1 -1
- package/dist/hono/types.d.ts +0 -12
- package/dist/hono/types.d.ts.map +1 -1
- package/dist/review/digest.d.ts +0 -13
- package/dist/review/digest.d.ts.map +1 -1
- package/dist/review/digest.js +1 -1
- package/dist/review/digest.js.map +1 -1
- package/package.json +1 -1
- package/dist/hono/effort-route.d.ts +0 -43
- package/dist/hono/effort-route.d.ts.map +0 -1
- package/dist/hono/effort-route.js +0 -36
- package/dist/hono/effort-route.js.map +0 -1
- package/dist/hono/effort-route.test.d.ts +0 -2
- package/dist/hono/effort-route.test.d.ts.map +0 -1
- package/dist/hono/effort-route.test.js +0 -54
- package/dist/hono/effort-route.test.js.map +0 -1
- package/dist/hono/tool-result-ledger.d.ts +0 -30
- package/dist/hono/tool-result-ledger.d.ts.map +0 -1
- package/dist/hono/tool-result-ledger.js +0 -63
- package/dist/hono/tool-result-ledger.js.map +0 -1
- package/dist/hono/tool-result-ledger.test.d.ts +0 -2
- package/dist/hono/tool-result-ledger.test.d.ts.map +0 -1
- package/dist/hono/tool-result-ledger.test.js +0 -61
- package/dist/hono/tool-result-ledger.test.js.map +0 -1
- package/dist/hono/workspace-instructions.d.ts +0 -43
- package/dist/hono/workspace-instructions.d.ts.map +0 -1
- package/dist/hono/workspace-instructions.js +0 -68
- package/dist/hono/workspace-instructions.js.map +0 -1
- package/dist/hono/workspace-instructions.test.d.ts +0 -2
- package/dist/hono/workspace-instructions.test.d.ts.map +0 -1
- package/dist/hono/workspace-instructions.test.js +0 -68
- package/dist/hono/workspace-instructions.test.js.map +0 -1
package/dist/hono/bridge-job.js
CHANGED
|
@@ -15,7 +15,6 @@ import { CONNECTION_INPUT_TOOL_NAME, CONNECTION_PLATFORMS, connectedButNotLoaded
|
|
|
15
15
|
import { messageContextTokens, pickContextWindow, streamEventContextUsage, turnContextUsage, } from "./context-usage.js";
|
|
16
16
|
import { CREDENTIAL_INPUT_TOOL_NAME, normalizeCredentialInputToolInput, } from "./credential-input.js";
|
|
17
17
|
import { credentialScrubHooks } from "./credential-scrub.js";
|
|
18
|
-
import { DEFAULT_TURN_EFFORT, decideTurnEffort } from "./effort-route.js";
|
|
19
18
|
import { agentStatedFlowMessage, FLOW_INPUT_TOOL_NAME, nodeTargetRefusals, normalizeFlowInputToolInput, readRawFlowTree, sanitizeFlowRequests, unknownFlowPrefillMessage, } from "./flow-input.js";
|
|
20
19
|
import { writesInventedLogo } from "./invented-logo.js";
|
|
21
20
|
import { jevJudge } from "./jev.js";
|
|
@@ -24,7 +23,7 @@ import { composioScopesToInvalidate, failedCustomServers, reportMcpInvalid, serv
|
|
|
24
23
|
import { agentModelOverride, autoCompactWindowForModel, betasForModel, contextWindowForModel, } from "./model-capabilities.js";
|
|
25
24
|
import { agentShellPrefixEnv, killFirstWrapper } from "./oom-priority.js";
|
|
26
25
|
import { anthropicCustomHeaders, runtimeOpenRouterTags } from "./openrouter-attribution.js";
|
|
27
|
-
import { buildAgentExtraBody, EXTRA_BODY_ENV, MODEL_CAPABILITIES_ENV,
|
|
26
|
+
import { BEDROCK_SERVABLE_CAPABILITIES, buildAgentExtraBody, EXTRA_BODY_ENV, MODEL_CAPABILITIES_ENV, } from "./openrouter-session.js";
|
|
28
27
|
import { credentialReminder, currentReferenceReminder, kickoffBriefReminder } from "./prompt-context.js";
|
|
29
28
|
import { publishLanguageReminder, publishRunReminder, publishStandingReminder } from "./publish-handoff.js";
|
|
30
29
|
import { bridgeRuntimeFiles } from "./runtime-files.js";
|
|
@@ -36,10 +35,8 @@ import { skillLanguageHooks } from "./skill-language.js";
|
|
|
36
35
|
import { BridgeSlashCommands, leadingSkillCommand, verbatimSlashCommand } from "./slash-commands.js";
|
|
37
36
|
import { createBakerUiServer, normalizeTagInputToolInput, sanitizeTagChanges, TAG_INPUT_TOOL_NAME, unknownPrefillMessage, } from "./tag-input.js";
|
|
38
37
|
import { blockingToolDelegated, toolRunAsCommand } from "./tool-in-shell.js";
|
|
39
|
-
import { ToolResultLedger } from "./tool-result-ledger.js";
|
|
40
38
|
import { recordTurnEvent } from "./turn-events.js";
|
|
41
39
|
import { addQueryModelUsage, queryModelUsage, turnModelUsageList } from "./turn-model-usage.js";
|
|
42
|
-
import { prepareSharedInstructions } from "./workspace-instructions.js";
|
|
43
40
|
import { settleWorkspaceAfterTasks } from "./workspace-settle.js";
|
|
44
41
|
export function parsePlanDecision(value) {
|
|
45
42
|
if (!value || typeof value !== "object") {
|
|
@@ -220,13 +217,6 @@ const BASE_DISALLOWED_TOOLS = [
|
|
|
220
217
|
// not asked to fund a research fleet. Ordinary fan-out is unaffected:
|
|
221
218
|
// `Task` stays, so the scaffold's subagents still run.
|
|
222
219
|
"Workflow",
|
|
223
|
-
// Developer tools: design-system sync, code-review findings, Jupyter edits.
|
|
224
|
-
// None was called once in 358 production chats (Oct 2026), and each
|
|
225
|
-
// definition rides every request whenever the CLI does not defer it —
|
|
226
|
-
// DesignSync's alone is ~9k characters.
|
|
227
|
-
"DesignSync",
|
|
228
|
-
"ReportFindings",
|
|
229
|
-
"NotebookEdit",
|
|
230
220
|
// NOT listed: `SendMessage`. It is how the model follows up with a
|
|
231
221
|
// subagent it already ran, and the CLI tells it to on every Agent result.
|
|
232
222
|
// The continued subagent runs in the background, but it announces itself
|
|
@@ -255,7 +245,7 @@ function disallowedToolsFor(job) {
|
|
|
255
245
|
function modelForJob(job, sessionModel) {
|
|
256
246
|
return job.review?.model ?? sessionModel;
|
|
257
247
|
}
|
|
258
|
-
export const REVIEW_DISALLOWED_TOOLS = ["Edit", "Write", "MultiEdit", "ExitPlanMode", "Skill"];
|
|
248
|
+
export const REVIEW_DISALLOWED_TOOLS = ["Edit", "Write", "MultiEdit", "NotebookEdit", "ExitPlanMode", "Skill"];
|
|
259
249
|
/**
|
|
260
250
|
* The findings contract, enforced by the SDK rather than parsed back out of
|
|
261
251
|
* prose. `structured_output` on the result message is what reaches Convex, and
|
|
@@ -442,19 +432,6 @@ function createBridgeJobState() {
|
|
|
442
432
|
detachedSession: false,
|
|
443
433
|
modelUsageTotals: new Map(),
|
|
444
434
|
queryModelUsage: new Map(),
|
|
445
|
-
toolResults: new ToolResultLedger(),
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
/** What a finished turn reports about its spend: per-model usage and per-tool result sizes. */
|
|
449
|
-
function turnUsage(state) {
|
|
450
|
-
const toolResults = state.toolResults.summary();
|
|
451
|
-
return {
|
|
452
|
-
modelUsage: turnModelUsageList(state.modelUsageTotals),
|
|
453
|
-
...(toolResults.length > 0 ? { toolResults } : {}),
|
|
454
|
-
// An unjudged turn is left off: no decision on the record means Jev never answered.
|
|
455
|
-
...(state.effortDecision && state.effortDecision.reason !== "unjudged"
|
|
456
|
-
? { effortDecision: state.effortDecision }
|
|
457
|
-
: {}),
|
|
458
435
|
};
|
|
459
436
|
}
|
|
460
437
|
function errorMessage(error) {
|
|
@@ -531,21 +508,6 @@ function hookSettingsForJob(job) {
|
|
|
531
508
|
}
|
|
532
509
|
return {};
|
|
533
510
|
}
|
|
534
|
-
/**
|
|
535
|
-
* Which instruction files a job loads as memory. A Session review loads none:
|
|
536
|
-
* its brief has it read the rulebook as the Session had it (`git show
|
|
537
|
-
* <sha>:CLAUDE.md`), since Publish may already have moved the working tree past
|
|
538
|
-
* it, and the auto-loaded copy is ~24k tokens of the marketer's instructions
|
|
539
|
-
* written cold and re-read on every review request. The client's agent loads
|
|
540
|
-
* the workspace's `CLAUDE.md` itself only when it could not be split into the
|
|
541
|
-
* shared system prompt (`prepareSharedInstructions`).
|
|
542
|
-
*/
|
|
543
|
-
function instructionSettingsForJob(job, sharedInstructions) {
|
|
544
|
-
if (job.review) {
|
|
545
|
-
return { claudeMdExcludes: ["**/CLAUDE.md"] };
|
|
546
|
-
}
|
|
547
|
-
return sharedInstructions ? { claudeMdExcludes: [join(bridgeRuntimeFiles.projectRoot(), "CLAUDE.md")] } : {};
|
|
548
|
-
}
|
|
549
511
|
// Carry a Runtime-wide model override down to the fan-out workers.
|
|
550
512
|
//
|
|
551
513
|
// The shared subagents pin themselves to Sonnet 5.5 in their own frontmatter (see
|
|
@@ -1205,9 +1167,9 @@ export class BridgeJobExecutor {
|
|
|
1205
1167
|
settleWorkspace;
|
|
1206
1168
|
catchUpWithMain;
|
|
1207
1169
|
holdsNoWork;
|
|
1170
|
+
settleAfterPublish;
|
|
1208
1171
|
keepCliInStep;
|
|
1209
1172
|
judge;
|
|
1210
|
-
effortJudge;
|
|
1211
1173
|
constructor(dependencies) {
|
|
1212
1174
|
this.sdk = dependencies.sdk;
|
|
1213
1175
|
this.relay = dependencies.relay;
|
|
@@ -1230,15 +1192,13 @@ export class BridgeJobExecutor {
|
|
|
1230
1192
|
this.settleWorkspace = dependencies.settleWorkspace ?? (() => settleWorkspaceAfterTasks());
|
|
1231
1193
|
this.catchUpWithMain = dependencies.catchUpWithMain;
|
|
1232
1194
|
this.holdsNoWork = dependencies.holdsNoWork;
|
|
1195
|
+
this.settleAfterPublish = dependencies.settleAfterPublish;
|
|
1233
1196
|
this.keepCliInStep = dependencies.keepCliInStep;
|
|
1234
1197
|
this.readFlowTree =
|
|
1235
1198
|
dependencies.readFlowTree ?? ((flowSlug) => readRawFlowTree(bridgeRuntimeFiles.flowsDir(), flowSlug));
|
|
1236
1199
|
this.judge =
|
|
1237
1200
|
dependencies.judge ??
|
|
1238
1201
|
jevJudge(process.env.OPENROUTER_API_KEY, runtimeOpenRouterTags(process.env, { service: "bridge", feature: "bridge.toolCallGuard" }));
|
|
1239
|
-
this.effortJudge =
|
|
1240
|
-
dependencies.effortJudge ??
|
|
1241
|
-
jevJudge(process.env.OPENROUTER_API_KEY, runtimeOpenRouterTags(process.env, { service: "bridge", feature: "bridge.effortRoute" }));
|
|
1242
1202
|
}
|
|
1243
1203
|
async execute(job, controls) {
|
|
1244
1204
|
try {
|
|
@@ -1250,26 +1210,6 @@ export class BridgeJobExecutor {
|
|
|
1250
1210
|
await this.inFlightTurns.clear(job.threadId, job.turnId).catch(() => undefined);
|
|
1251
1211
|
}
|
|
1252
1212
|
}
|
|
1253
|
-
/**
|
|
1254
|
-
* How hard the agent works on this turn (see `effort-route.ts`); null for a
|
|
1255
|
-
* Session review, which keeps the default. Never throws: an unanswered judge
|
|
1256
|
-
* is the default level.
|
|
1257
|
-
*/
|
|
1258
|
-
async decideEffort(job, request) {
|
|
1259
|
-
if (job.review) {
|
|
1260
|
-
return null;
|
|
1261
|
-
}
|
|
1262
|
-
const lastReply = (job.history?.entries ?? []).filter((entry) => entry.role === "assistant").at(-1);
|
|
1263
|
-
return await decideTurnEffort({
|
|
1264
|
-
message: job.prompt,
|
|
1265
|
-
previousReply: lastReply?.text ?? "",
|
|
1266
|
-
judge: this.effortJudge,
|
|
1267
|
-
planMode: job.planMode === true,
|
|
1268
|
-
leadingCommand: request.leadingCommand,
|
|
1269
|
-
unattended: job.unattended === true,
|
|
1270
|
-
hasAttachments: (job.attachments?.length ?? 0) > 0,
|
|
1271
|
-
}).catch(() => ({ effort: DEFAULT_TURN_EFFORT, reason: "unjudged" }));
|
|
1272
|
-
}
|
|
1273
1213
|
async executeTurn(job, controls) {
|
|
1274
1214
|
const state = createBridgeJobState();
|
|
1275
1215
|
let result = { costUsd: 0, attemptedRehydration: false };
|
|
@@ -1281,8 +1221,6 @@ export class BridgeJobExecutor {
|
|
|
1281
1221
|
if (!request?.prompt || !controls.isActive()) {
|
|
1282
1222
|
return { kind: "cancelled", costUsd: 0, model: state.model };
|
|
1283
1223
|
}
|
|
1284
|
-
// Asked while the boundary loads, so the answer (~0.3 s) costs the turn no time.
|
|
1285
|
-
const effortDecision = this.decideEffort(job, request);
|
|
1286
1224
|
const loaded = await this.loadTrustedBoundary(job, controls);
|
|
1287
1225
|
if (loaded?.kind !== "clean") {
|
|
1288
1226
|
request = await this.withContinuedAttachments(job, request);
|
|
@@ -1301,7 +1239,6 @@ export class BridgeJobExecutor {
|
|
|
1301
1239
|
state.detachedSession = attempt.detachedSession === true;
|
|
1302
1240
|
result.attemptedRehydration = attempt.attemptedRehydration;
|
|
1303
1241
|
this.recordAttemptContextSource(job, attempt);
|
|
1304
|
-
state.effortDecision = (await effortDecision) ?? undefined;
|
|
1305
1242
|
result = await this.runAttempt(job, controls, state, attempt);
|
|
1306
1243
|
return await this.finishSuccessfulAttempt(job, controls, state, result.costUsd);
|
|
1307
1244
|
}
|
|
@@ -1310,8 +1247,6 @@ export class BridgeJobExecutor {
|
|
|
1310
1247
|
if (repaired && controls.isActive()) {
|
|
1311
1248
|
const repairState = createBridgeJobState();
|
|
1312
1249
|
repairState.detachedSession = repaired.detachedSession === true;
|
|
1313
|
-
// The same turn, so the same level: a changed one would re-write the cache.
|
|
1314
|
-
repairState.effortDecision = state.effortDecision;
|
|
1315
1250
|
let repairResult = { costUsd: 0, attemptedRehydration: repaired.attemptedRehydration };
|
|
1316
1251
|
try {
|
|
1317
1252
|
repairResult = await this.runAttempt(job, controls, repairState, repaired);
|
|
@@ -1514,22 +1449,22 @@ export class BridgeJobExecutor {
|
|
|
1514
1449
|
return { costUsd, attemptedRehydration: attempt.attemptedRehydration };
|
|
1515
1450
|
}
|
|
1516
1451
|
async finishSuccessfulAttempt(job, controls, state, costUsd) {
|
|
1517
|
-
const
|
|
1452
|
+
const modelUsage = turnModelUsageList(state.modelUsageTotals);
|
|
1518
1453
|
if (!controls.isActive()) {
|
|
1519
1454
|
await this.clearIfDirty(job, controls, state, "abort");
|
|
1520
|
-
return { kind: "cancelled", costUsd, model: state.model,
|
|
1455
|
+
return { kind: "cancelled", costUsd, model: state.model, modelUsage };
|
|
1521
1456
|
}
|
|
1522
1457
|
// No boundary is handed back, so the refused exchange never becomes part of
|
|
1523
1458
|
// the conversation the next message resumes.
|
|
1524
1459
|
if (state.refusedWithoutFallback) {
|
|
1525
|
-
return { kind: "errored", costUsd, model: state.model,
|
|
1460
|
+
return { kind: "errored", costUsd, model: state.model, modelUsage, errors: [MODEL_REFUSAL_MESSAGE] };
|
|
1526
1461
|
}
|
|
1527
1462
|
if (!state.postedAssistantEvent && state.turnText.length > 0) {
|
|
1528
1463
|
await this.postSyntheticAssistantEvent(job, state);
|
|
1529
1464
|
}
|
|
1530
1465
|
if (!controls.isActive()) {
|
|
1531
1466
|
await this.clearIfDirty(job, controls, state, "abort");
|
|
1532
|
-
return { kind: "cancelled", costUsd, model: state.model,
|
|
1467
|
+
return { kind: "cancelled", costUsd, model: state.model, modelUsage };
|
|
1533
1468
|
}
|
|
1534
1469
|
// A detached turn (publish) ran in a session of its own. Handing that session
|
|
1535
1470
|
// back as the thread's boundary would make the next chat message resume a
|
|
@@ -1542,11 +1477,17 @@ export class BridgeJobExecutor {
|
|
|
1542
1477
|
// `closeRunThatChangedNothing`), and only the Runtime can vouch for its files.
|
|
1543
1478
|
// Never after a publish turn: that one settles the chat itself.
|
|
1544
1479
|
const workspaceUnchanged = !state.detachedSession && !job.review && this.holdsNoWork !== undefined && (await this.holdsNoWork());
|
|
1480
|
+
// A publish turn's push is settled before the chat goes on: its next turn starts from what went live.
|
|
1481
|
+
if (state.detachedSession) {
|
|
1482
|
+
await this.settleAfterPublish?.().catch((error) => {
|
|
1483
|
+
console.error(`[BridgeJob] could not settle the publish for ${job.threadId}`, error);
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1545
1486
|
return {
|
|
1546
1487
|
kind: "completed",
|
|
1547
1488
|
costUsd,
|
|
1548
1489
|
model: state.model,
|
|
1549
|
-
|
|
1490
|
+
modelUsage,
|
|
1550
1491
|
...(workspaceUnchanged ? { workspaceUnchanged: true } : {}),
|
|
1551
1492
|
cleanBoundary,
|
|
1552
1493
|
...(state.structuredOutput === undefined ? {} : { structuredOutput: state.structuredOutput }),
|
|
@@ -1554,7 +1495,7 @@ export class BridgeJobExecutor {
|
|
|
1554
1495
|
}
|
|
1555
1496
|
errorOutcome(job, controls, state, result, error) {
|
|
1556
1497
|
const model = state.model;
|
|
1557
|
-
const
|
|
1498
|
+
const modelUsage = turnModelUsageList(state.modelUsageTotals);
|
|
1558
1499
|
if (result.attemptedRehydration) {
|
|
1559
1500
|
void this.relay.contextSource({ threadId: job.threadId, turnId: job.turnId }, "rehydration_failed", {
|
|
1560
1501
|
historyEntryCount: job.history?.entries.length ?? 0,
|
|
@@ -1564,7 +1505,7 @@ export class BridgeJobExecutor {
|
|
|
1564
1505
|
});
|
|
1565
1506
|
}
|
|
1566
1507
|
if (!controls.isActive()) {
|
|
1567
|
-
return { kind: "cancelled", costUsd: result.costUsd, model,
|
|
1508
|
+
return { kind: "cancelled", costUsd: result.costUsd, model, modelUsage };
|
|
1568
1509
|
}
|
|
1569
1510
|
const shown = userFacingTurnError(error);
|
|
1570
1511
|
if (shown !== errorMessage(error)) {
|
|
@@ -1574,7 +1515,7 @@ export class BridgeJobExecutor {
|
|
|
1574
1515
|
kind: "errored",
|
|
1575
1516
|
costUsd: result.costUsd,
|
|
1576
1517
|
model,
|
|
1577
|
-
|
|
1518
|
+
modelUsage,
|
|
1578
1519
|
errors: [shown],
|
|
1579
1520
|
};
|
|
1580
1521
|
}
|
|
@@ -1849,12 +1790,6 @@ export class BridgeJobExecutor {
|
|
|
1849
1790
|
await this.alignResumedTranscript(attempt);
|
|
1850
1791
|
const mcpServers = await this.resolveMcpServers(job);
|
|
1851
1792
|
const skills = await readSessionSkills(bridgeRuntimeFiles.projectRoot());
|
|
1852
|
-
const sharedInstructions = job.review
|
|
1853
|
-
? null
|
|
1854
|
-
: await prepareSharedInstructions({
|
|
1855
|
-
projectRoot: bridgeRuntimeFiles.projectRoot(),
|
|
1856
|
-
contextDir: bridgeRuntimeFiles.instructionsDir(),
|
|
1857
|
-
});
|
|
1858
1793
|
const autoCompactWindow = autoCompactWindowForModel(model);
|
|
1859
1794
|
const betas = betasForModel(model);
|
|
1860
1795
|
// No `outputStyle`: the built-in `Concise` style was pinned here against Opus 5's
|
|
@@ -1890,7 +1825,6 @@ export class BridgeJobExecutor {
|
|
|
1890
1825
|
}
|
|
1891
1826
|
: {}),
|
|
1892
1827
|
...hookSettingsForJob(job),
|
|
1893
|
-
...instructionSettingsForJob(job, sharedInstructions),
|
|
1894
1828
|
};
|
|
1895
1829
|
const agentTags = runtimeOpenRouterTags(process.env, {
|
|
1896
1830
|
service: "agent",
|
|
@@ -1910,29 +1844,15 @@ export class BridgeJobExecutor {
|
|
|
1910
1844
|
// more per level than Opus 5, so compare `low` on real Sessions before
|
|
1911
1845
|
// treating this as tuned.
|
|
1912
1846
|
//
|
|
1913
|
-
//
|
|
1914
|
-
//
|
|
1915
|
-
//
|
|
1916
|
-
//
|
|
1917
|
-
|
|
1847
|
+
// MUST stay a single constant. The resolved effort is rendered into the
|
|
1848
|
+
// prompt, so changing it between requests invalidates every cache
|
|
1849
|
+
// breakpoint above it — on a session carrying hundreds of thousands of
|
|
1850
|
+
// tokens that re-write costs far more than any per-turn tuning saves.
|
|
1851
|
+
// Vary it per message only once the route accepts per-message effort
|
|
1852
|
+
// (see `BEDROCK_SERVABLE_CAPABILITIES`); prose is no substitute.
|
|
1853
|
+
effort: "medium",
|
|
1918
1854
|
cwd: process.cwd(),
|
|
1919
1855
|
settingSources: ["project"],
|
|
1920
|
-
// The scaffold's CLAUDE.md, minus its `@COMPANY.md` import, as the system
|
|
1921
|
-
// prompt, so every chat reads one cached copy instead of writing its own;
|
|
1922
|
-
// the import loads from `instructionsDir` (see workspace-instructions.ts).
|
|
1923
|
-
...(sharedInstructions
|
|
1924
|
-
? {
|
|
1925
|
-
systemPrompt: {
|
|
1926
|
-
type: "preset",
|
|
1927
|
-
preset: "claude_code",
|
|
1928
|
-
append: sharedInstructions.shared,
|
|
1929
|
-
// Recorded once per conversation, so a scaffold sync mid-chat cannot
|
|
1930
|
-
// move the cached prefix under it; it lands at the next compaction.
|
|
1931
|
-
snapshot: true,
|
|
1932
|
-
},
|
|
1933
|
-
additionalDirectories: [bridgeRuntimeFiles.instructionsDir()],
|
|
1934
|
-
}
|
|
1935
|
-
: {}),
|
|
1936
1856
|
// `baker_ui` hosts in-process interactive dashboard tools (secure tag
|
|
1937
1857
|
// form). Always present; HTTP (Composio) servers merge alongside it.
|
|
1938
1858
|
mcpServers: { ...(mcpServers ?? {}), baker_ui: createBakerUiServer({ credentials: credentialsEnabled() }) },
|
|
@@ -1984,8 +1904,6 @@ export class BridgeJobExecutor {
|
|
|
1984
1904
|
// they are never TTY-gated, so every help read the agent does inside
|
|
1985
1905
|
// the sandbox pays ~5-10% of its tokens on colour codes it can't see.
|
|
1986
1906
|
NO_COLOR: "1",
|
|
1987
|
-
// Loads the `CLAUDE.md` in `instructionsDir`, which imports COMPANY.md.
|
|
1988
|
-
...(sharedInstructions ? { CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD: "1" } : {}),
|
|
1989
1907
|
// Pin the conversation to one OpenRouter provider instance so the
|
|
1990
1908
|
// instance-scoped prompt cache is actually re-read across the turn's
|
|
1991
1909
|
// many tool-call requests. Merged into every model request body by the
|
|
@@ -1997,8 +1915,12 @@ export class BridgeJobExecutor {
|
|
|
1997
1915
|
ANTHROPIC_CUSTOM_HEADERS: [process.env.ANTHROPIC_CUSTOM_HEADERS, anthropicCustomHeaders(agentTags.headers)]
|
|
1998
1916
|
.filter(Boolean)
|
|
1999
1917
|
.join("\n"),
|
|
2000
|
-
//
|
|
2001
|
-
[MODEL_CAPABILITIES_ENV]:
|
|
1918
|
+
// Without it no Opus 5.5 request can reach Bedrock; see openrouter-session.ts.
|
|
1919
|
+
[MODEL_CAPABILITIES_ENV]: BEDROCK_SERVABLE_CAPABILITIES,
|
|
1920
|
+
// The CLI names each session with a second, structured-output request on the
|
|
1921
|
+
// turn's model. OpenRouter's Bedrock cannot serve that, so it was billed to
|
|
1922
|
+
// OpenRouter credits on Azure or Vertex, and nothing in Baker reads the name.
|
|
1923
|
+
CLAUDE_CODE_DISABLE_TERMINAL_TITLE: "1",
|
|
2002
1924
|
// The turn's message sender, so in-sandbox `baker` calls can scope to the acting user.
|
|
2003
1925
|
...(job.currentSender?.userId ? { BAKER_ACTING_USER_ID: job.currentSender.userId } : {}),
|
|
2004
1926
|
...subagentModelEnv(),
|
|
@@ -2076,7 +1998,6 @@ export class BridgeJobExecutor {
|
|
|
2076
1998
|
for await (const msg of query) {
|
|
2077
1999
|
stallDetector.observeMessage(msg);
|
|
2078
2000
|
turnEnd.observeMessage(msg);
|
|
2079
|
-
state.toolResults.observe(msg);
|
|
2080
2001
|
controls.setWorkInFlight?.(stallDetector.hasPendingToolUses() || turnEnd.hasInFlightWork());
|
|
2081
2002
|
try {
|
|
2082
2003
|
costUsd = await this.consumeSdkMessage(job, controls, state, msg, costUsd);
|