usebeeline 0.0.134 → 0.1.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/usebeeline.mjs +1765 -1463
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -9071,7 +9071,7 @@ var init_access_policy = __esm({
|
|
|
9071
9071
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
9072
9072
|
import { execFile } from "node:child_process";
|
|
9073
9073
|
import { closeSync, openSync, readFileSync } from "node:fs";
|
|
9074
|
-
import { mkdir, readFile as readFile2, readdir, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
9074
|
+
import { chmod, mkdir, readFile as readFile2, readdir, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
9075
9075
|
import { homedir } from "node:os";
|
|
9076
9076
|
import { dirname, resolve } from "node:path";
|
|
9077
9077
|
import { spawn as spawn2 } from "node:child_process";
|
|
@@ -9138,6 +9138,10 @@ async function readRuntimeRecord(path) {
|
|
|
9138
9138
|
runtimeIdentity(parsed.body);
|
|
9139
9139
|
return parsed;
|
|
9140
9140
|
}
|
|
9141
|
+
async function convergeRuntimeRecordFileModes(path) {
|
|
9142
|
+
await chmod(dirname(path), 448).catch(() => void 0);
|
|
9143
|
+
await chmod(path, 384).catch(() => void 0);
|
|
9144
|
+
}
|
|
9141
9145
|
async function migrateRuntimeRecordAccessPolicy(path) {
|
|
9142
9146
|
const runtime = await readRuntimeRecord(path);
|
|
9143
9147
|
if (runtime.accessPolicy)
|
|
@@ -9983,7 +9987,7 @@ var init_systemd = __esm({
|
|
|
9983
9987
|
// apps/body/dist/launchd.js
|
|
9984
9988
|
import { execFile as execFile3 } from "node:child_process";
|
|
9985
9989
|
import { realpathSync } from "node:fs";
|
|
9986
|
-
import { chmod, mkdir as mkdir3, readFile as readFile4, readdir as readdir2, rename as rename2, rm, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
|
|
9990
|
+
import { chmod as chmod2, mkdir as mkdir3, readFile as readFile4, readdir as readdir2, rename as rename2, rm, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
|
|
9987
9991
|
import { homedir as homedir4 } from "node:os";
|
|
9988
9992
|
import { dirname as dirname4, resolve as resolve4 } from "node:path";
|
|
9989
9993
|
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
@@ -10150,7 +10154,7 @@ async function writeManagedFile(path, content, mode) {
|
|
|
10150
10154
|
await mkdir3(dirname4(path), { recursive: true, mode: 448 });
|
|
10151
10155
|
const pending = `${path}.${process.pid}.pending`;
|
|
10152
10156
|
await writeFile3(pending, content, { mode });
|
|
10153
|
-
await
|
|
10157
|
+
await chmod2(pending, mode);
|
|
10154
10158
|
await rename2(pending, path);
|
|
10155
10159
|
return true;
|
|
10156
10160
|
}
|
|
@@ -10402,7 +10406,7 @@ __export(self_update_exports, {
|
|
|
10402
10406
|
});
|
|
10403
10407
|
import { createHash } from "node:crypto";
|
|
10404
10408
|
import { constants as fsConstants2 } from "node:fs";
|
|
10405
|
-
import { access, chmod as
|
|
10409
|
+
import { access, chmod as chmod3, lstat, mkdir as mkdir4, open, readFile as readFile5, rename as rename3, rm as rm2, symlink, writeFile as writeFile4 } from "node:fs/promises";
|
|
10406
10410
|
import { spawn as spawn4 } from "node:child_process";
|
|
10407
10411
|
import { homedir as homedir5 } from "node:os";
|
|
10408
10412
|
import { dirname as dirname5, join as join3, resolve as resolve5 } from "node:path";
|
|
@@ -10704,7 +10708,7 @@ function forwarderScript(tool) {
|
|
|
10704
10708
|
async function replaceFile(path, contents, mode) {
|
|
10705
10709
|
const temp = `${path}.new-${process.pid}`;
|
|
10706
10710
|
await writeFile4(temp, contents, { mode });
|
|
10707
|
-
await
|
|
10711
|
+
await chmod3(temp, mode);
|
|
10708
10712
|
await rename3(temp, path);
|
|
10709
10713
|
}
|
|
10710
10714
|
async function activateRelease(layout, releaseId) {
|
|
@@ -11244,7 +11248,7 @@ var init_cursor_models = __esm({
|
|
|
11244
11248
|
// apps/body/dist/cursor-acp-bridge.js
|
|
11245
11249
|
import { spawn as spawn6 } from "node:child_process";
|
|
11246
11250
|
import { existsSync as existsSync3 } from "node:fs";
|
|
11247
|
-
import { chmod as
|
|
11251
|
+
import { chmod as chmod4, lstat as lstat2, mkdir as mkdir6, rename as rename4, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
|
|
11248
11252
|
import { createRequire as createRequire3 } from "node:module";
|
|
11249
11253
|
import { createInterface as createInterface3 } from "node:readline";
|
|
11250
11254
|
import { basename, dirname as dirname7, resolve as resolvePath } from "node:path";
|
|
@@ -11316,7 +11320,7 @@ async function writeIsolatedCursorFile(path, content) {
|
|
|
11316
11320
|
const temporary = resolvePath(parent, `.${basename(path)}.${process.pid}.${randomUUID2()}.tmp`);
|
|
11317
11321
|
try {
|
|
11318
11322
|
await writeFile5(temporary, content, { mode: 384, flag: "wx" });
|
|
11319
|
-
await
|
|
11323
|
+
await chmod4(temporary, 384);
|
|
11320
11324
|
await rename4(temporary, path);
|
|
11321
11325
|
} finally {
|
|
11322
11326
|
await unlink3(temporary).catch(() => void 0);
|
|
@@ -23288,6 +23292,8 @@ function isSquireApprovalUrl(value) {
|
|
|
23288
23292
|
const host = url.hostname;
|
|
23289
23293
|
if (!["trustysquire.ai", "trustysquire.test"].some((domain) => host === domain || host.endsWith(`.${domain}`)))
|
|
23290
23294
|
return false;
|
|
23295
|
+
if (url.pathname === "/" || url.pathname === "/install")
|
|
23296
|
+
return true;
|
|
23291
23297
|
return /^\/(?:vault\/(?:pay|fetch|mutate|mutate-card)|approval|passkey|vouch)\/[^/]+\/?$/.test(url.pathname);
|
|
23292
23298
|
}
|
|
23293
23299
|
function linkKindFor(key, url) {
|
|
@@ -23479,6 +23485,56 @@ function squireApprovalFromMcp(request, response) {
|
|
|
23479
23485
|
const args = record(params?.arguments) ?? {};
|
|
23480
23486
|
return { tool, ...squireApprovalCopy(tool, args), ...link2 };
|
|
23481
23487
|
}
|
|
23488
|
+
function squireLoginWallIn(value, depth = 0) {
|
|
23489
|
+
if (depth > 6)
|
|
23490
|
+
return void 0;
|
|
23491
|
+
if (typeof value === "string") {
|
|
23492
|
+
const trimmed = value.trim();
|
|
23493
|
+
if (trimmed.length > 2e4 || !/^[{[]/.test(trimmed))
|
|
23494
|
+
return void 0;
|
|
23495
|
+
try {
|
|
23496
|
+
return squireLoginWallIn(JSON.parse(trimmed), depth + 1);
|
|
23497
|
+
} catch {
|
|
23498
|
+
return void 0;
|
|
23499
|
+
}
|
|
23500
|
+
}
|
|
23501
|
+
if (Array.isArray(value)) {
|
|
23502
|
+
for (const entry of value) {
|
|
23503
|
+
const found = squireLoginWallIn(entry, depth + 1);
|
|
23504
|
+
if (found)
|
|
23505
|
+
return found;
|
|
23506
|
+
}
|
|
23507
|
+
return void 0;
|
|
23508
|
+
}
|
|
23509
|
+
const item = record(value);
|
|
23510
|
+
if (!item)
|
|
23511
|
+
return void 0;
|
|
23512
|
+
const needsUser = record(item.needs_user);
|
|
23513
|
+
if (needsUser?.wall === "google_session") {
|
|
23514
|
+
const message = shortString(needsUser.message);
|
|
23515
|
+
if (message)
|
|
23516
|
+
return { wall: "google_session", message };
|
|
23517
|
+
}
|
|
23518
|
+
const oauth = record(item.oauth);
|
|
23519
|
+
if (oauth?.state === "awaiting_human") {
|
|
23520
|
+
const reason = shortString(oauth.reason);
|
|
23521
|
+
if (reason)
|
|
23522
|
+
return { wall: "awaiting_human", message: reason };
|
|
23523
|
+
}
|
|
23524
|
+
for (const entry of Object.values(item)) {
|
|
23525
|
+
const found = squireLoginWallIn(entry, depth + 1);
|
|
23526
|
+
if (found)
|
|
23527
|
+
return found;
|
|
23528
|
+
}
|
|
23529
|
+
return void 0;
|
|
23530
|
+
}
|
|
23531
|
+
function squireLoginWallFromMcp(request, response) {
|
|
23532
|
+
if (!request || request.method !== "tools/call" || request.id !== response.id)
|
|
23533
|
+
return void 0;
|
|
23534
|
+
if (!("result" in response))
|
|
23535
|
+
return void 0;
|
|
23536
|
+
return squireLoginWallIn(response.result);
|
|
23537
|
+
}
|
|
23482
23538
|
async function postSquireApproval(approval, authFile, signInUrl, fetchImpl = fetch) {
|
|
23483
23539
|
const auth = JSON.parse(await readFile(authFile, "utf8"));
|
|
23484
23540
|
const context = JSON.parse(await readFile(auth.turnContextPath, "utf8"));
|
|
@@ -23495,6 +23551,22 @@ async function postSquireApproval(approval, authFile, signInUrl, fetchImpl = fet
|
|
|
23495
23551
|
signal: AbortSignal.timeout(2e4)
|
|
23496
23552
|
});
|
|
23497
23553
|
}
|
|
23554
|
+
async function postSquireLoginWall(wall, authFile, fetchImpl = fetch) {
|
|
23555
|
+
const auth = JSON.parse(await readFile(authFile, "utf8"));
|
|
23556
|
+
const context = JSON.parse(await readFile(auth.turnContextPath, "utf8"));
|
|
23557
|
+
if (![context.roomId, context.requestId, context.generationId].every((value) => typeof value === "string" && value.length > 0))
|
|
23558
|
+
return;
|
|
23559
|
+
await fetchImpl(new URL("/v1/daemon/operations/postSquireLoginWall", auth.baseUrl), {
|
|
23560
|
+
method: "POST",
|
|
23561
|
+
headers: {
|
|
23562
|
+
authorization: `Bearer ${auth.daemonToken}`,
|
|
23563
|
+
"content-type": "application/json",
|
|
23564
|
+
"x-beeline-helper-version": auth.helperVersion ?? "v0.0.0"
|
|
23565
|
+
},
|
|
23566
|
+
body: JSON.stringify({ ...context, wall: wall.wall, message: wall.message }),
|
|
23567
|
+
signal: AbortSignal.timeout(2e4)
|
|
23568
|
+
});
|
|
23569
|
+
}
|
|
23498
23570
|
function resourceCallFacts(message, target) {
|
|
23499
23571
|
if (message.method !== "tools/call")
|
|
23500
23572
|
return {};
|
|
@@ -23560,6 +23632,11 @@ function runResourceFacade(env = process.env) {
|
|
|
23560
23632
|
if (request?.drivenUrl && activeSquireBrowserUrl === request.drivenUrl)
|
|
23561
23633
|
activeSquireBrowserUrl = void 0;
|
|
23562
23634
|
}
|
|
23635
|
+
const loginWall = squireLoginWallFromMcp(request?.message, message);
|
|
23636
|
+
if (loginWall) {
|
|
23637
|
+
await postSquireLoginWall(loginWall, authFile).catch(() => {
|
|
23638
|
+
});
|
|
23639
|
+
}
|
|
23563
23640
|
};
|
|
23564
23641
|
const authorizedResponseIds = /* @__PURE__ */ new Set();
|
|
23565
23642
|
let child;
|
|
@@ -23725,7 +23802,7 @@ function configureNetworkFamilyDefaults(network = net) {
|
|
|
23725
23802
|
configureNetworkFamilyDefaults();
|
|
23726
23803
|
|
|
23727
23804
|
// apps/body/dist/cli.js
|
|
23728
|
-
import { dirname as
|
|
23805
|
+
import { dirname as dirname27, resolve as resolve39 } from "node:path";
|
|
23729
23806
|
import { stdin as stdin4, stdout as stdout5 } from "node:process";
|
|
23730
23807
|
|
|
23731
23808
|
// node_modules/@clack/core/dist/index.mjs
|
|
@@ -25808,7 +25885,13 @@ async function installSquire(options) {
|
|
|
25808
25885
|
if (resolution.reResolved) {
|
|
25809
25886
|
log2(`trusty-squire stale copy ${resolution.resolvedVersion ?? "unknown"} re-resolved against current release ${resolution.currentRelease}`);
|
|
25810
25887
|
}
|
|
25811
|
-
const install = await streamRun("npx", [
|
|
25888
|
+
const install = await streamRun("npx", [
|
|
25889
|
+
...resolution.npxArgs,
|
|
25890
|
+
"connect",
|
|
25891
|
+
"--target=codex",
|
|
25892
|
+
"--json",
|
|
25893
|
+
...options.forceReloginProvider ? [`--force-relogin=${options.forceReloginProvider}`] : []
|
|
25894
|
+
], squireConnectProcessEnv(profileDir));
|
|
25812
25895
|
const report = install.report;
|
|
25813
25896
|
const version = resolution.resolvedVersion;
|
|
25814
25897
|
if (!report) {
|
|
@@ -26543,549 +26626,1143 @@ function isAllowedAgentModelConfigCategory(category, id) {
|
|
|
26543
26626
|
// apps/body/dist/model-config.js
|
|
26544
26627
|
import { lstatSync, readFileSync as readFileSync3 } from "node:fs";
|
|
26545
26628
|
import { basename as basename3, resolve as resolve9 } from "node:path";
|
|
26546
|
-
|
|
26547
|
-
|
|
26548
|
-
function
|
|
26549
|
-
if (
|
|
26550
|
-
return true;
|
|
26551
|
-
if (agent.kind && agent.kind !== "custom")
|
|
26629
|
+
|
|
26630
|
+
// packages/api-contract/dist/daemon-operations.js
|
|
26631
|
+
function isAgentCommand(value) {
|
|
26632
|
+
if (!value || typeof value !== "object")
|
|
26552
26633
|
return false;
|
|
26553
|
-
|
|
26554
|
-
|
|
26555
|
-
|
|
26556
|
-
|
|
26557
|
-
|
|
26558
|
-
|
|
26559
|
-
|
|
26560
|
-
|
|
26561
|
-
|
|
26562
|
-
|
|
26563
|
-
|
|
26564
|
-
|
|
26565
|
-
|
|
26566
|
-
|
|
26567
|
-
|
|
26568
|
-
|
|
26569
|
-
}
|
|
26570
|
-
stripped.push(arg);
|
|
26571
|
-
}
|
|
26572
|
-
const stdioIndex = stripped.lastIndexOf("stdio");
|
|
26573
|
-
const configured = [
|
|
26574
|
-
...selection.model ? ["--model", selection.model] : [],
|
|
26575
|
-
...selection.effort ? ["--reasoning-effort", selection.effort] : []
|
|
26576
|
-
];
|
|
26577
|
-
stripped.splice(stdioIndex, 0, ...configured);
|
|
26578
|
-
return stripped;
|
|
26579
|
-
}
|
|
26580
|
-
function advertisedChoiceId(choice) {
|
|
26581
|
-
if (typeof choice.id === "string" && choice.id.length > 0)
|
|
26582
|
-
return choice.id;
|
|
26583
|
-
if (typeof choice.value === "string" && choice.value.length > 0)
|
|
26584
|
-
return choice.value;
|
|
26585
|
-
return void 0;
|
|
26634
|
+
const c2 = value;
|
|
26635
|
+
if (![
|
|
26636
|
+
"id",
|
|
26637
|
+
"roomId",
|
|
26638
|
+
"agentId",
|
|
26639
|
+
"sourceMessageId",
|
|
26640
|
+
"turnRequestId",
|
|
26641
|
+
"rootCommandId",
|
|
26642
|
+
"rootSourceMessageId",
|
|
26643
|
+
"reason"
|
|
26644
|
+
].every((key) => typeof c2[key] === "string" && c2[key].length > 0))
|
|
26645
|
+
return false;
|
|
26646
|
+
if (!["input", "resume", "stop", "restart"].includes(String(c2.action)) || !Number.isInteger(c2.agentDepth) || Number(c2.agentDepth) < 0 || Number(c2.agentDepth) > 3)
|
|
26647
|
+
return false;
|
|
26648
|
+
const source = c2.source;
|
|
26649
|
+
return Boolean(source && typeof source.id === "string" && typeof source.authorId === "string" && typeof source.body === "string" && typeof source.createdAt === "number" && Array.isArray(source.attachments));
|
|
26586
26650
|
}
|
|
26587
|
-
|
|
26588
|
-
|
|
26589
|
-
|
|
26590
|
-
|
|
26591
|
-
|
|
26592
|
-
|
|
26593
|
-
|
|
26594
|
-
|
|
26595
|
-
|
|
26596
|
-
|
|
26597
|
-
|
|
26651
|
+
|
|
26652
|
+
// packages/api-contract/dist/artifacts.js
|
|
26653
|
+
var ARTIFACT_EXTENSIONS_BY_MIME = {
|
|
26654
|
+
"text/html": [".html", ".htm"],
|
|
26655
|
+
"image/svg+xml": [".svg"],
|
|
26656
|
+
"application/pdf": [".pdf"],
|
|
26657
|
+
"text/markdown": [".md"],
|
|
26658
|
+
"image/png": [".png"],
|
|
26659
|
+
"image/jpeg": [".jpg", ".jpeg"],
|
|
26660
|
+
"image/gif": [".gif"],
|
|
26661
|
+
"image/webp": [".webp"],
|
|
26662
|
+
"text/plain": [".txt", ".log"],
|
|
26663
|
+
"application/json": [".json"],
|
|
26664
|
+
"text/csv": [".csv"],
|
|
26665
|
+
"application/zip": [".zip"],
|
|
26666
|
+
"application/octet-stream": []
|
|
26667
|
+
};
|
|
26668
|
+
var ARTIFACT_MIME_BY_EXTENSION = Object.fromEntries(Object.entries(ARTIFACT_EXTENSIONS_BY_MIME).flatMap(([mime, extensions]) => extensions.map((extension2) => [extension2, mime])));
|
|
26669
|
+
var ARTIFACT_MAXIMUM_BYTES = 25 * 1024 * 1024;
|
|
26670
|
+
|
|
26671
|
+
// packages/api-contract/dist/daemon.js
|
|
26672
|
+
init_agent_access();
|
|
26673
|
+
|
|
26674
|
+
// packages/api-contract/dist/system-events.js
|
|
26675
|
+
var SERVER_EVENT_KINDS = [
|
|
26676
|
+
"joined",
|
|
26677
|
+
"schedule-ran",
|
|
26678
|
+
"corner-opened",
|
|
26679
|
+
"check-passed",
|
|
26680
|
+
"check-failed",
|
|
26681
|
+
"merged",
|
|
26682
|
+
"grant-decided",
|
|
26683
|
+
"connector-offer-decided",
|
|
26684
|
+
"turn-cancelled",
|
|
26685
|
+
"choice-answered",
|
|
26686
|
+
"choice-skipped",
|
|
26687
|
+
"poll-closed",
|
|
26688
|
+
"workflow-handoff"
|
|
26689
|
+
];
|
|
26690
|
+
|
|
26691
|
+
// packages/api-contract/dist/turn-silence.js
|
|
26692
|
+
var HICCUP_BACKOFF_MS = [0, 5e3, 2e4];
|
|
26693
|
+
var TURN_SILENCE_KINDS = [
|
|
26694
|
+
"hiccup",
|
|
26695
|
+
"wrong-model",
|
|
26696
|
+
"allowance-spent",
|
|
26697
|
+
"not-signed-in",
|
|
26698
|
+
"workspace-failure",
|
|
26699
|
+
"helper-out-of-date",
|
|
26700
|
+
"update-interrupted",
|
|
26701
|
+
"offline"
|
|
26702
|
+
];
|
|
26703
|
+
var TURN_RECEIPT_REASON_KINDS = [
|
|
26704
|
+
"hiccup",
|
|
26705
|
+
"wrong-model",
|
|
26706
|
+
"allowance-spent",
|
|
26707
|
+
"not-signed-in",
|
|
26708
|
+
"workspace-failure",
|
|
26709
|
+
"helper-out-of-date",
|
|
26710
|
+
"update-interrupted",
|
|
26711
|
+
"offline",
|
|
26712
|
+
"model-selection-unavailable"
|
|
26713
|
+
];
|
|
26714
|
+
function isTurnReceiptReasonKind(value) {
|
|
26715
|
+
return typeof value === "string" && TURN_RECEIPT_REASON_KINDS.includes(value);
|
|
26598
26716
|
}
|
|
26599
|
-
function
|
|
26600
|
-
|
|
26601
|
-
|
|
26602
|
-
|
|
26603
|
-
|
|
26604
|
-
|
|
26605
|
-
const record6 = entry;
|
|
26606
|
-
const id = record6.id;
|
|
26607
|
-
const category = record6.category;
|
|
26608
|
-
if (typeof id !== "string" || typeof category !== "string")
|
|
26609
|
-
continue;
|
|
26610
|
-
const rawChoices = Array.isArray(record6.options) ? record6.options : [];
|
|
26611
|
-
const choices = [];
|
|
26612
|
-
for (const rawChoice of rawChoices) {
|
|
26613
|
-
if (!rawChoice || typeof rawChoice !== "object")
|
|
26614
|
-
continue;
|
|
26615
|
-
const choice = rawChoice;
|
|
26616
|
-
const choiceId = advertisedChoiceId(choice);
|
|
26617
|
-
if (!choiceId)
|
|
26618
|
-
continue;
|
|
26619
|
-
choices.push({
|
|
26620
|
-
id: choiceId,
|
|
26621
|
-
...typeof choice.name === "string" ? { name: choice.name } : {}
|
|
26622
|
-
});
|
|
26623
|
-
}
|
|
26624
|
-
result.push({
|
|
26625
|
-
id,
|
|
26626
|
-
category,
|
|
26627
|
-
...typeof record6.currentValue === "string" ? { currentValue: record6.currentValue } : {},
|
|
26628
|
-
options: category === "model" ? sortModelChoicesNewestFirst(choices) : choices
|
|
26629
|
-
});
|
|
26630
|
-
}
|
|
26631
|
-
const models = raw?.models;
|
|
26632
|
-
if (!models || typeof models !== "object")
|
|
26633
|
-
return result;
|
|
26634
|
-
const modelState = models;
|
|
26635
|
-
const availableModels = Array.isArray(modelState.availableModels) ? modelState.availableModels : [];
|
|
26636
|
-
const modelChoices = [];
|
|
26637
|
-
for (const entry of availableModels) {
|
|
26638
|
-
if (!entry || typeof entry !== "object")
|
|
26639
|
-
continue;
|
|
26640
|
-
const model = entry;
|
|
26641
|
-
if (typeof model.modelId !== "string" || !model.modelId)
|
|
26642
|
-
continue;
|
|
26643
|
-
modelChoices.push({
|
|
26644
|
-
id: model.modelId,
|
|
26645
|
-
...typeof model.name === "string" ? { name: model.name } : {}
|
|
26646
|
-
});
|
|
26647
|
-
}
|
|
26648
|
-
const currentModelId = typeof modelState.currentModelId === "string" ? modelState.currentModelId : void 0;
|
|
26649
|
-
if (modelChoices.length > 0 && !result.some((axis) => axis.category === "model")) {
|
|
26650
|
-
result.push({
|
|
26651
|
-
id: GROK_SESSION_MODEL_AXIS_ID,
|
|
26652
|
-
category: "model",
|
|
26653
|
-
...currentModelId ? { currentValue: currentModelId } : {},
|
|
26654
|
-
options: sortModelChoicesNewestFirst(modelChoices)
|
|
26655
|
-
});
|
|
26656
|
-
}
|
|
26657
|
-
const effortModelId = preferredModelId ?? currentModelId;
|
|
26658
|
-
const currentModel = availableModels.find((entry) => entry && typeof entry === "object" && entry.modelId === effortModelId);
|
|
26659
|
-
const meta = currentModel?._meta;
|
|
26660
|
-
const modelMeta = meta && typeof meta === "object" ? meta : void 0;
|
|
26661
|
-
const efforts = Array.isArray(modelMeta?.reasoningEfforts) ? modelMeta.reasoningEfforts : [];
|
|
26662
|
-
const effortChoices = [];
|
|
26663
|
-
for (const entry of efforts) {
|
|
26664
|
-
if (!entry || typeof entry !== "object")
|
|
26665
|
-
continue;
|
|
26666
|
-
const effort = entry;
|
|
26667
|
-
const id = advertisedChoiceId(effort);
|
|
26668
|
-
if (!id)
|
|
26669
|
-
continue;
|
|
26670
|
-
effortChoices.push({
|
|
26671
|
-
id,
|
|
26672
|
-
...typeof effort.label === "string" ? { name: effort.label } : typeof effort.name === "string" ? { name: effort.name } : {}
|
|
26673
|
-
});
|
|
26674
|
-
}
|
|
26675
|
-
const hasEffortAxis = result.some((axis) => ["thought_level", "effort", "reasoning_effort"].includes(axis.category));
|
|
26676
|
-
if (includeLaunchEffort && effortChoices.length > 0 && !hasEffortAxis) {
|
|
26677
|
-
const currentEffort = typeof modelMeta?.reasoningEffort === "string" ? modelMeta.reasoningEffort : efforts.find((entry) => entry && typeof entry === "object" && entry.default)?.value;
|
|
26678
|
-
result.push({
|
|
26679
|
-
id: GROK_LAUNCH_EFFORT_AXIS_ID,
|
|
26680
|
-
category: "reasoning_effort",
|
|
26681
|
-
...typeof currentEffort === "string" ? { currentValue: currentEffort } : {},
|
|
26682
|
-
options: effortChoices
|
|
26683
|
-
});
|
|
26684
|
-
}
|
|
26685
|
-
return result;
|
|
26717
|
+
function receiptKindToSilenceKind(kind) {
|
|
26718
|
+
if (kind === "model-selection-unavailable" || kind === "wrong-model")
|
|
26719
|
+
return "wrong-model";
|
|
26720
|
+
if (kind && TURN_SILENCE_KINDS.includes(kind))
|
|
26721
|
+
return kind;
|
|
26722
|
+
return "hiccup";
|
|
26686
26723
|
}
|
|
26687
|
-
|
|
26688
|
-
|
|
26724
|
+
var ALLOWANCE_UNTIL = /(?:try again at|until|resets?(?: at)?|available(?: again)?(?: at)?)\s+([A-Z][a-z]{2,9}\s+\d{1,2}(?:st|nd|rd|th)?,?\s+\d{4}(?:\s+\d{1,2}:\d{2}(?:\s*[AP]M)?)?)/i;
|
|
26725
|
+
var REPO_FROM_URL = /github\.com[:/]([^/\s]+\/[^/\s.]+?)(?:\.git)?(?:[/\s]|$)/i;
|
|
26726
|
+
var REPO_FROM_SLUG = /\b([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)\b/;
|
|
26727
|
+
function firstMatch(value, pattern) {
|
|
26728
|
+
const match = value.match(pattern);
|
|
26729
|
+
const captured = match?.[1]?.trim();
|
|
26730
|
+
return captured || void 0;
|
|
26689
26731
|
}
|
|
26690
|
-
|
|
26691
|
-
|
|
26692
|
-
openrouter: ["OPENROUTER_API_KEY"],
|
|
26693
|
-
anthropic: ["ANTHROPIC_API_KEY"],
|
|
26694
|
-
google: ["GOOGLE_API_KEY", "GEMINI_API_KEY"],
|
|
26695
|
-
groq: ["GROQ_API_KEY"],
|
|
26696
|
-
mistral: ["MISTRAL_API_KEY"],
|
|
26697
|
-
deepseek: ["DEEPSEEK_API_KEY"],
|
|
26698
|
-
xai: ["XAI_API_KEY"],
|
|
26699
|
-
cohere: ["COHERE_API_KEY"],
|
|
26700
|
-
together: ["TOGETHER_API_KEY"],
|
|
26701
|
-
fireworks: ["FIREWORKS_API_KEY"]
|
|
26702
|
-
};
|
|
26703
|
-
function credentialedProviders(env) {
|
|
26704
|
-
const held = /* @__PURE__ */ new Set();
|
|
26705
|
-
for (const [provider, names] of Object.entries(PROVIDER_CREDENTIAL_ENV_HINTS)) {
|
|
26706
|
-
if (names.some((name) => Boolean(env[name]?.trim())))
|
|
26707
|
-
held.add(provider);
|
|
26708
|
-
}
|
|
26709
|
-
for (const provider of credentialedPiCustomProviders(env))
|
|
26710
|
-
held.add(provider);
|
|
26711
|
-
return held;
|
|
26732
|
+
function isAuthShapedFault(text2) {
|
|
26733
|
+
return /authentication required/i.test(text2) || /not signed in/i.test(text2) || /isn't signed in/i.test(text2) || /invalid api[_ -]?key/i.test(text2) || /\b401\b/.test(text2);
|
|
26712
26734
|
}
|
|
26713
|
-
function
|
|
26714
|
-
|
|
26715
|
-
|
|
26716
|
-
|
|
26717
|
-
|
|
26718
|
-
const path = resolve9(agentDir, "models.json");
|
|
26719
|
-
try {
|
|
26720
|
-
const stats = lstatSync(path);
|
|
26721
|
-
if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1 || stats.size > 1048576) {
|
|
26722
|
-
return held;
|
|
26735
|
+
function classifyTurnSilence(reason, reasonKind) {
|
|
26736
|
+
if (isTurnReceiptReasonKind(reasonKind)) {
|
|
26737
|
+
const kind = receiptKindToSilenceKind(reasonKind);
|
|
26738
|
+
if (kind === "hiccup") {
|
|
26739
|
+
return { kind, fault: (reason ?? "").trim() || "the turn stalled" };
|
|
26723
26740
|
}
|
|
26724
|
-
|
|
26725
|
-
|
|
26726
|
-
|
|
26727
|
-
|
|
26728
|
-
return;
|
|
26729
|
-
const apiKey = config.apiKey;
|
|
26730
|
-
if (typeof apiKey === "string" && apiKey.trim())
|
|
26731
|
-
held.add(name.trim());
|
|
26741
|
+
return {
|
|
26742
|
+
kind,
|
|
26743
|
+
...kind === "allowance-spent" ? { allowanceUntil: firstMatch(reason ?? "", ALLOWANCE_UNTIL) } : {},
|
|
26744
|
+
...kind === "workspace-failure" ? { repo: repoFromReason(reason ?? "") } : {}
|
|
26732
26745
|
};
|
|
26733
|
-
if (Array.isArray(providers)) {
|
|
26734
|
-
for (const provider of providers) {
|
|
26735
|
-
const record6 = provider;
|
|
26736
|
-
remember(record6?.name ?? record6?.id, record6);
|
|
26737
|
-
}
|
|
26738
|
-
} else if (providers && typeof providers === "object") {
|
|
26739
|
-
for (const [name, config] of Object.entries(providers)) {
|
|
26740
|
-
remember(name, config);
|
|
26741
|
-
}
|
|
26742
|
-
}
|
|
26743
|
-
} catch {
|
|
26744
26746
|
}
|
|
26745
|
-
|
|
26746
|
-
|
|
26747
|
-
|
|
26748
|
-
|
|
26749
|
-
|
|
26750
|
-
|
|
26751
|
-
|
|
26747
|
+
const text2 = (reason ?? "").trim();
|
|
26748
|
+
if (!text2)
|
|
26749
|
+
return { kind: "hiccup", fault: "the turn stalled" };
|
|
26750
|
+
if (/model selection unavailable/i.test(text2) || /isn't available/i.test(text2) || /not advertised/i.test(text2)) {
|
|
26751
|
+
return { kind: "wrong-model" };
|
|
26752
|
+
}
|
|
26753
|
+
if (/\b402\b/.test(text2) || /usage limit/i.test(text2) || /more credits/i.test(text2) || /quota/i.test(text2) || /allowance is spent/i.test(text2)) {
|
|
26752
26754
|
return {
|
|
26753
|
-
|
|
26754
|
-
|
|
26755
|
-
const slash = choice.id.indexOf("/");
|
|
26756
|
-
if (slash < 0)
|
|
26757
|
-
return true;
|
|
26758
|
-
return held.has(choice.id.slice(0, slash));
|
|
26759
|
-
})
|
|
26755
|
+
kind: "allowance-spent",
|
|
26756
|
+
allowanceUntil: firstMatch(text2, ALLOWANCE_UNTIL)
|
|
26760
26757
|
};
|
|
26761
|
-
});
|
|
26762
|
-
}
|
|
26763
|
-
var DisallowedModelConfigOptionError = class extends Error {
|
|
26764
|
-
constructor(configId) {
|
|
26765
|
-
super(`model config option "${configId}" is not in the allow-listed catalog`);
|
|
26766
|
-
this.name = "DisallowedModelConfigOptionError";
|
|
26767
|
-
}
|
|
26768
|
-
};
|
|
26769
|
-
function supportsFastMode(options) {
|
|
26770
|
-
const axis = options.find((option) => option.id === "fast-mode" && option.category === "model_config");
|
|
26771
|
-
return Boolean(axis?.options.some((choice) => choice.id === "on") && axis.options.some((choice) => choice.id === "off"));
|
|
26772
|
-
}
|
|
26773
|
-
var ModelSelectionUnavailableError = class extends Error {
|
|
26774
|
-
label;
|
|
26775
|
-
value;
|
|
26776
|
-
reason;
|
|
26777
|
-
guidance;
|
|
26778
|
-
constructor(input) {
|
|
26779
|
-
const recovery = input.guidance ? ` ${input.guidance}` : " Choose one of the values in the live harness catalog.";
|
|
26780
|
-
super(`${input.label} "${input.value}" is unavailable.${recovery}`);
|
|
26781
|
-
this.name = "ModelSelectionUnavailableError";
|
|
26782
|
-
this.label = input.label;
|
|
26783
|
-
this.value = input.value;
|
|
26784
|
-
this.reason = input.reason;
|
|
26785
|
-
this.guidance = input.guidance;
|
|
26786
26758
|
}
|
|
26787
|
-
|
|
26788
|
-
|
|
26789
|
-
if (!selection || !selection.model && !selection.effort)
|
|
26790
|
-
return options;
|
|
26791
|
-
return options.map((option) => {
|
|
26792
|
-
const target = modelSelectionTargets(selection).find((entry) => entry.categories.includes(option.category));
|
|
26793
|
-
if (!target?.value || option.currentValue === target.value)
|
|
26794
|
-
return option;
|
|
26795
|
-
return { ...option, currentValue: target.value };
|
|
26796
|
-
});
|
|
26797
|
-
}
|
|
26798
|
-
function modelSelectionTargets(selection) {
|
|
26799
|
-
return [
|
|
26800
|
-
{ categories: ["model"], label: "model", value: selection.model },
|
|
26801
|
-
{
|
|
26802
|
-
categories: ["thought_level", "effort", "reasoning_effort"],
|
|
26803
|
-
label: "effort",
|
|
26804
|
-
value: selection.effort
|
|
26805
|
-
}
|
|
26806
|
-
];
|
|
26807
|
-
}
|
|
26808
|
-
function assertModelConfigAxisAllowed(configId, advertisedOptions) {
|
|
26809
|
-
const axis = advertisedOptions.find((option) => option.id === configId);
|
|
26810
|
-
if (!axis || !isAllowedAgentModelConfigCategory(axis.category, axis.id)) {
|
|
26811
|
-
throw new DisallowedModelConfigOptionError(configId);
|
|
26759
|
+
if (isAuthShapedFault(text2)) {
|
|
26760
|
+
return { kind: "not-signed-in" };
|
|
26812
26761
|
}
|
|
26813
|
-
|
|
26814
|
-
|
|
26815
|
-
let currentOptions = advertisedOptions;
|
|
26816
|
-
for (const target of modelSelectionTargets(selection)) {
|
|
26817
|
-
if (!target.value)
|
|
26818
|
-
continue;
|
|
26819
|
-
const axis = currentOptions.find((option) => target.categories.includes(option.category));
|
|
26820
|
-
if (!axis)
|
|
26821
|
-
continue;
|
|
26822
|
-
assertModelConfigAxisAllowed(axis.id, currentOptions);
|
|
26823
|
-
if (!axis.options.some((choice) => choice.id === target.value)) {
|
|
26824
|
-
throw new ModelSelectionUnavailableError({
|
|
26825
|
-
label: target.label,
|
|
26826
|
-
value: target.value,
|
|
26827
|
-
reason: "not-advertised"
|
|
26828
|
-
});
|
|
26829
|
-
}
|
|
26830
|
-
try {
|
|
26831
|
-
if (axis.id === GROK_SESSION_MODEL_AXIS_ID) {
|
|
26832
|
-
if (!client.setModel)
|
|
26833
|
-
throw new Error("ACP client does not support session/set_model");
|
|
26834
|
-
await client.setModel(sessionId, target.value);
|
|
26835
|
-
} else if (axis.id === GROK_LAUNCH_EFFORT_AXIS_ID) {
|
|
26836
|
-
if (axis.currentValue !== target.value) {
|
|
26837
|
-
throw new Error(`Grok started with reasoning effort "${axis.currentValue ?? "unknown"}", not "${target.value}"`);
|
|
26838
|
-
}
|
|
26839
|
-
} else {
|
|
26840
|
-
const updated = await client.setConfigOption(sessionId, axis.id, target.value);
|
|
26841
|
-
const refreshed = filterAllowedModelConfigOptions(parseAdvertisedConfigOptions(updated, selection.model));
|
|
26842
|
-
if (refreshed.length > 0)
|
|
26843
|
-
currentOptions = refreshed;
|
|
26844
|
-
}
|
|
26845
|
-
} catch (error) {
|
|
26846
|
-
throw new ModelSelectionUnavailableError({
|
|
26847
|
-
label: target.label,
|
|
26848
|
-
value: target.value,
|
|
26849
|
-
reason: "provider-refused",
|
|
26850
|
-
guidance: error instanceof Error ? error.message : String(error)
|
|
26851
|
-
});
|
|
26852
|
-
}
|
|
26762
|
+
if (/command protocol/i.test(text2) || /refusing intake/i.test(text2) || /helper is out of date/i.test(text2)) {
|
|
26763
|
+
return { kind: "helper-out-of-date" };
|
|
26853
26764
|
}
|
|
26854
|
-
if (
|
|
26855
|
-
|
|
26765
|
+
if (/working copy/i.test(text2) || /could not (?:clone|fetch|checkout)/i.test(text2) || /repository not found/i.test(text2) || /could not resolve host/i.test(text2) || /failed to start corner/i.test(text2) || /unable to access/i.test(text2) || /\bgit clone\b/i.test(text2) || /repository state is not verified/i.test(text2) || /incomplete repository binding/i.test(text2) || /no authoritative objective fact/i.test(text2) || /profile_busy/i.test(text2) || /broker unavailable/i.test(text2)) {
|
|
26766
|
+
return { kind: "workspace-failure", repo: repoFromReason(text2) };
|
|
26856
26767
|
}
|
|
26857
|
-
if (
|
|
26858
|
-
|
|
26768
|
+
if (/helper isn't running/i.test(text2) || /helper is offline/i.test(text2)) {
|
|
26769
|
+
return { kind: "offline" };
|
|
26859
26770
|
}
|
|
26860
|
-
|
|
26771
|
+
const fault = text2 || "the turn stalled";
|
|
26772
|
+
return { kind: "hiccup", fault };
|
|
26861
26773
|
}
|
|
26862
|
-
|
|
26863
|
-
|
|
26774
|
+
function repoFromReason(text2) {
|
|
26775
|
+
return firstMatch(text2, REPO_FROM_URL) ?? firstMatch(text2, REPO_FROM_SLUG) ?? "the repository";
|
|
26776
|
+
}
|
|
26777
|
+
function isStandingWorkspaceConfigurationFault(text2) {
|
|
26778
|
+
return /repository state is not verified/i.test(text2) || /incomplete repository binding/i.test(text2) || /no authoritative objective fact/i.test(text2);
|
|
26779
|
+
}
|
|
26780
|
+
function hiccupBackoffMs(attempt) {
|
|
26781
|
+
const index = Math.max(1, attempt) - 1;
|
|
26782
|
+
return HICCUP_BACKOFF_MS[Math.min(index, HICCUP_BACKOFF_MS.length - 1)] ?? 0;
|
|
26864
26783
|
}
|
|
26865
26784
|
|
|
26866
|
-
//
|
|
26867
|
-
|
|
26868
|
-
|
|
26869
|
-
|
|
26870
|
-
|
|
26871
|
-
|
|
26872
|
-
|
|
26873
|
-
|
|
26874
|
-
|
|
26875
|
-
|
|
26876
|
-
|
|
26877
|
-
|
|
26878
|
-
|
|
26879
|
-
|
|
26880
|
-
|
|
26881
|
-
|
|
26882
|
-
|
|
26883
|
-
|
|
26884
|
-
|
|
26885
|
-
|
|
26886
|
-
|
|
26887
|
-
|
|
26888
|
-
|
|
26889
|
-
|
|
26890
|
-
|
|
26891
|
-
|
|
26892
|
-
|
|
26893
|
-
|
|
26894
|
-
|
|
26895
|
-
|
|
26896
|
-
|
|
26897
|
-
|
|
26898
|
-
|
|
26899
|
-
|
|
26900
|
-
|
|
26901
|
-
|
|
26902
|
-
|
|
26903
|
-
|
|
26904
|
-
|
|
26905
|
-
|
|
26906
|
-
|
|
26907
|
-
|
|
26908
|
-
|
|
26909
|
-
|
|
26910
|
-
|
|
26911
|
-
|
|
26912
|
-
|
|
26913
|
-
|
|
26914
|
-
|
|
26915
|
-
|
|
26916
|
-
|
|
26917
|
-
|
|
26918
|
-
|
|
26919
|
-
|
|
26920
|
-
|
|
26921
|
-
|
|
26922
|
-
|
|
26923
|
-
|
|
26924
|
-
|
|
26925
|
-
|
|
26926
|
-
|
|
26927
|
-
|
|
26785
|
+
// packages/api-contract/dist/institutional-memory.js
|
|
26786
|
+
var INSTITUTIONAL_MEMORY_PROPOSAL_VERSION = 1;
|
|
26787
|
+
var INSTITUTIONAL_MEMORY_BODY_MAX_BYTES = 200;
|
|
26788
|
+
var INSTITUTIONAL_MEMORY_KEYWORDS_MIN = 1;
|
|
26789
|
+
var INSTITUTIONAL_MEMORY_KEYWORDS_MAX = 6;
|
|
26790
|
+
var INSTITUTIONAL_MEMORY_KEYWORD_PATTERN = /^[a-z0-9][a-z0-9_./-]{2,31}$/;
|
|
26791
|
+
var INSTITUTIONAL_MEMORY_STOPWORDS = /* @__PURE__ */ new Set([
|
|
26792
|
+
"the",
|
|
26793
|
+
"and",
|
|
26794
|
+
"you",
|
|
26795
|
+
"your",
|
|
26796
|
+
"for",
|
|
26797
|
+
"with",
|
|
26798
|
+
"that",
|
|
26799
|
+
"this",
|
|
26800
|
+
"are",
|
|
26801
|
+
"was",
|
|
26802
|
+
"were",
|
|
26803
|
+
"but",
|
|
26804
|
+
"not",
|
|
26805
|
+
"have",
|
|
26806
|
+
"has",
|
|
26807
|
+
"had",
|
|
26808
|
+
"can",
|
|
26809
|
+
"all",
|
|
26810
|
+
"any",
|
|
26811
|
+
"our",
|
|
26812
|
+
"out",
|
|
26813
|
+
"use",
|
|
26814
|
+
"get",
|
|
26815
|
+
"got",
|
|
26816
|
+
"how",
|
|
26817
|
+
"what",
|
|
26818
|
+
"when",
|
|
26819
|
+
"who",
|
|
26820
|
+
"why",
|
|
26821
|
+
"will",
|
|
26822
|
+
"just",
|
|
26823
|
+
"from",
|
|
26824
|
+
"they",
|
|
26825
|
+
"them",
|
|
26826
|
+
"then",
|
|
26827
|
+
"than",
|
|
26828
|
+
"there",
|
|
26829
|
+
"here",
|
|
26830
|
+
"about",
|
|
26831
|
+
"into",
|
|
26832
|
+
"also",
|
|
26833
|
+
"its",
|
|
26834
|
+
"it's",
|
|
26835
|
+
"please",
|
|
26836
|
+
"should",
|
|
26837
|
+
"would",
|
|
26838
|
+
"could",
|
|
26839
|
+
"some",
|
|
26840
|
+
"more",
|
|
26841
|
+
"most",
|
|
26842
|
+
"very",
|
|
26843
|
+
"only",
|
|
26844
|
+
"one",
|
|
26845
|
+
"now",
|
|
26846
|
+
"yes",
|
|
26847
|
+
"okay",
|
|
26848
|
+
"let",
|
|
26849
|
+
"make",
|
|
26850
|
+
"want",
|
|
26851
|
+
"need",
|
|
26852
|
+
"does",
|
|
26853
|
+
"did",
|
|
26854
|
+
"done",
|
|
26855
|
+
"like",
|
|
26856
|
+
"know",
|
|
26857
|
+
"think",
|
|
26858
|
+
"see",
|
|
26859
|
+
"look",
|
|
26860
|
+
"thing",
|
|
26861
|
+
"things",
|
|
26862
|
+
"way"
|
|
26863
|
+
]);
|
|
26864
|
+
var INSTITUTIONAL_STANDING_PREFERENCE_KEY = "standing";
|
|
26865
|
+
var INSTITUTIONAL_MEMORY_CANONICAL_KEY_MAX_LENGTH = 160;
|
|
26866
|
+
var INSTITUTIONAL_MEMORY_RATIONALE_MAX_LENGTH = 500;
|
|
26867
|
+
var INSTITUTIONAL_MEMORY_SOURCE_MESSAGE_MAX = 16;
|
|
26868
|
+
var INSTITUTIONAL_MEMORY_JOB_ERROR_MAX_LENGTH = 1e3;
|
|
26869
|
+
var WORKSPACE_SKILL_DESCRIPTION_MAX_LENGTH = 60;
|
|
26870
|
+
var WORKSPACE_SKILL_MARKDOWN_MAX_BYTES = 32 * 1024;
|
|
26871
|
+
var WORKSPACE_SKILL_SLUG_MAX_LENGTH = 64;
|
|
26872
|
+
var INSTITUTIONAL_REVIEW_FINDING_MAX = 20;
|
|
26873
|
+
var INSTITUTIONAL_CURATOR_ACTION_MAX = 50;
|
|
26874
|
+
function record2(value, label) {
|
|
26875
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
26876
|
+
throw new Error(`${label} must be an object`);
|
|
26928
26877
|
}
|
|
26929
|
-
return
|
|
26930
|
-
enforcement: "unknown",
|
|
26931
|
-
note: `'${agentCommand}' has not been verified to send session/request_permission for mutating tools`
|
|
26932
|
-
};
|
|
26878
|
+
return value;
|
|
26933
26879
|
}
|
|
26934
|
-
function
|
|
26935
|
-
|
|
26880
|
+
function exactKeys(value, allowed, label) {
|
|
26881
|
+
const unknown = Object.keys(value).find((key) => !allowed.includes(key));
|
|
26882
|
+
if (unknown)
|
|
26883
|
+
throw new Error(`${label} has unknown field ${unknown}`);
|
|
26936
26884
|
}
|
|
26937
|
-
|
|
26938
|
-
|
|
26939
|
-
|
|
26940
|
-
|
|
26885
|
+
function omitted(value) {
|
|
26886
|
+
return value === void 0 || value === null;
|
|
26887
|
+
}
|
|
26888
|
+
function boundedText(value, label, maximum, bytes = false) {
|
|
26889
|
+
if (typeof value !== "string" || value.includes("\0"))
|
|
26890
|
+
throw new Error(`${label} is invalid`);
|
|
26891
|
+
const normalized = value.trim();
|
|
26892
|
+
const size = bytes ? new TextEncoder().encode(normalized).length : normalized.length;
|
|
26893
|
+
if (!normalized || size > maximum)
|
|
26894
|
+
throw new Error(`${label} is invalid`);
|
|
26895
|
+
return normalized;
|
|
26896
|
+
}
|
|
26897
|
+
var FILLER_OPENINGS = /^(?:the user|user|this user|the requester|requester|it is|it's|note that|please|remember that|keep in mind)\b/i;
|
|
26898
|
+
var HEDGES = /\b(?:maybe|perhaps|probably|possibly|might|seems?|i think|apparently|likely)\b/i;
|
|
26899
|
+
function conciseInstitutionalMemoryBody(value) {
|
|
26900
|
+
const body = boundedText(value, `institutional memory body (at most ${INSTITUTIONAL_MEMORY_BODY_MAX_BYTES} bytes)`, INSTITUTIONAL_MEMORY_BODY_MAX_BYTES, true);
|
|
26901
|
+
if (FILLER_OPENINGS.test(body)) {
|
|
26902
|
+
throw new Error("institutional memory body must state the fact itself, without a filler opening");
|
|
26941
26903
|
}
|
|
26942
|
-
if (
|
|
26943
|
-
|
|
26904
|
+
if (/[.!?;]\s+\S/.test(body) || /\n/.test(body)) {
|
|
26905
|
+
throw new Error("institutional memory body must be one sentence");
|
|
26944
26906
|
}
|
|
26945
|
-
if (
|
|
26946
|
-
|
|
26947
|
-
|
|
26948
|
-
|
|
26949
|
-
return ["agent", "edit", "code"];
|
|
26907
|
+
if (HEDGES.test(body)) {
|
|
26908
|
+
throw new Error("institutional memory body must not hedge; save only what is known");
|
|
26909
|
+
}
|
|
26910
|
+
return body;
|
|
26950
26911
|
}
|
|
26951
|
-
function
|
|
26952
|
-
if (
|
|
26953
|
-
|
|
26912
|
+
function institutionalMemoryKeywords(value) {
|
|
26913
|
+
if (!Array.isArray(value) || value.length < INSTITUTIONAL_MEMORY_KEYWORDS_MIN || value.length > INSTITUTIONAL_MEMORY_KEYWORDS_MAX) {
|
|
26914
|
+
throw new Error(`institutional memory needs ${INSTITUTIONAL_MEMORY_KEYWORDS_MIN} to ${INSTITUTIONAL_MEMORY_KEYWORDS_MAX} keywords`);
|
|
26954
26915
|
}
|
|
26955
|
-
|
|
26916
|
+
const keywords = value.map((keyword) => typeof keyword === "string" ? keyword.trim().toLocaleLowerCase("en-US") : "");
|
|
26917
|
+
if (keywords.some((keyword) => !INSTITUTIONAL_MEMORY_KEYWORD_PATTERN.test(keyword) || INSTITUTIONAL_MEMORY_STOPWORDS.has(keyword))) {
|
|
26918
|
+
throw new Error("institutional memory keywords are distinctive single lower-case words of 3 to 32 letters, digits, or _./-");
|
|
26919
|
+
}
|
|
26920
|
+
if (new Set(keywords).size !== keywords.length) {
|
|
26921
|
+
throw new Error("institutional memory keywords must be unique");
|
|
26922
|
+
}
|
|
26923
|
+
return keywords;
|
|
26956
26924
|
}
|
|
26957
|
-
function
|
|
26958
|
-
|
|
26925
|
+
function parseInstitutionalMemoryProposal(value) {
|
|
26926
|
+
const proposal = record2(value, "institutional memory proposal");
|
|
26927
|
+
exactKeys(proposal, [
|
|
26928
|
+
"proposalVersion",
|
|
26929
|
+
"candidateType",
|
|
26930
|
+
"memoryKind",
|
|
26931
|
+
"subjectIdentityId",
|
|
26932
|
+
"canonicalKey",
|
|
26933
|
+
"body",
|
|
26934
|
+
"keywords",
|
|
26935
|
+
"source",
|
|
26936
|
+
"audience",
|
|
26937
|
+
"confidence",
|
|
26938
|
+
"classification",
|
|
26939
|
+
"cas"
|
|
26940
|
+
], "institutional memory proposal");
|
|
26941
|
+
if (proposal.proposalVersion !== INSTITUTIONAL_MEMORY_PROPOSAL_VERSION) {
|
|
26942
|
+
throw new Error("institutional memory proposal version is unsupported");
|
|
26943
|
+
}
|
|
26944
|
+
if (proposal.candidateType !== "correction_candidate" && proposal.candidateType !== "fact_candidate" && proposal.candidateType !== "preference_candidate") {
|
|
26945
|
+
throw new Error("institutional memory candidate type is invalid");
|
|
26946
|
+
}
|
|
26947
|
+
if (proposal.memoryKind !== "workspace_fact" && proposal.memoryKind !== "human_profile_fact") {
|
|
26948
|
+
throw new Error("institutional memory kind is invalid");
|
|
26949
|
+
}
|
|
26950
|
+
if (proposal.audience !== "workspace" && proposal.audience !== "human_profile") {
|
|
26951
|
+
throw new Error("institutional memory audience is invalid");
|
|
26952
|
+
}
|
|
26953
|
+
if (typeof proposal.confidence !== "number" || !Number.isFinite(proposal.confidence) || proposal.confidence < 0 || proposal.confidence > 1) {
|
|
26954
|
+
throw new Error("institutional memory confidence is invalid");
|
|
26955
|
+
}
|
|
26956
|
+
const source = record2(proposal.source, "institutional memory source");
|
|
26957
|
+
exactKeys(source, ["roomId", "messageIds"], "institutional memory source");
|
|
26958
|
+
const roomId = boundedText(source.roomId, "institutional memory source room", 200);
|
|
26959
|
+
if (!Array.isArray(source.messageIds) || source.messageIds.length === 0 || source.messageIds.length > INSTITUTIONAL_MEMORY_SOURCE_MESSAGE_MAX) {
|
|
26960
|
+
throw new Error("institutional memory source messages are invalid");
|
|
26961
|
+
}
|
|
26962
|
+
const messageIds = source.messageIds.map((messageId) => boundedText(messageId, "institutional memory source message", 200));
|
|
26963
|
+
if (new Set(messageIds).size !== messageIds.length) {
|
|
26964
|
+
throw new Error("institutional memory source messages must be unique");
|
|
26965
|
+
}
|
|
26966
|
+
const classification = record2(proposal.classification, "institutional memory classification");
|
|
26967
|
+
exactKeys(classification, ["stillTrueForAnotherRequester", "subjectIsRequester", "rationale"], "institutional memory classification");
|
|
26968
|
+
if (classification.stillTrueForAnotherRequester !== void 0 && typeof classification.stillTrueForAnotherRequester !== "boolean") {
|
|
26969
|
+
throw new Error("institutional memory classification test is invalid");
|
|
26970
|
+
}
|
|
26971
|
+
if (classification.subjectIsRequester !== void 0 && typeof classification.subjectIsRequester !== "boolean") {
|
|
26972
|
+
throw new Error("institutional memory subject classification is invalid");
|
|
26973
|
+
}
|
|
26974
|
+
const canonicalKey = boundedText(proposal.canonicalKey, "institutional memory canonical key", INSTITUTIONAL_MEMORY_CANONICAL_KEY_MAX_LENGTH);
|
|
26975
|
+
if (canonicalKey === INSTITUTIONAL_STANDING_PREFERENCE_KEY) {
|
|
26976
|
+
throw new Error("the standing preference key is reserved for owner-confirmed preferences");
|
|
26977
|
+
}
|
|
26978
|
+
const rationale = boundedText(classification.rationale, "institutional memory classification rationale", INSTITUTIONAL_MEMORY_RATIONALE_MAX_LENGTH);
|
|
26979
|
+
const cas = record2(proposal.cas, "institutional memory CAS");
|
|
26980
|
+
exactKeys(cas, ["baseVersion", "supersedesItemId"], "institutional memory CAS");
|
|
26981
|
+
if (cas.baseVersion !== null && (!Number.isSafeInteger(cas.baseVersion) || cas.baseVersion < 0)) {
|
|
26982
|
+
throw new Error("institutional memory base version is invalid");
|
|
26983
|
+
}
|
|
26984
|
+
const supersedesItemId = cas.supersedesItemId === void 0 ? void 0 : boundedText(cas.supersedesItemId, "institutional memory supersedes item", 200);
|
|
26985
|
+
const workspaceFact = proposal.memoryKind === "workspace_fact";
|
|
26986
|
+
if (classification.subjectIsRequester !== void 0 && classification.subjectIsRequester === workspaceFact) {
|
|
26987
|
+
throw new Error("institutional memory kind contradicts its subject");
|
|
26988
|
+
}
|
|
26989
|
+
if (proposal.audience === "workspace" !== workspaceFact) {
|
|
26990
|
+
throw new Error("institutional memory audience contradicts its kind");
|
|
26991
|
+
}
|
|
26992
|
+
const subjectIdentityId = proposal.subjectIdentityId === void 0 ? void 0 : boundedText(proposal.subjectIdentityId, "institutional memory profile subject", 200);
|
|
26993
|
+
if (workspaceFact === Boolean(subjectIdentityId)) {
|
|
26994
|
+
throw new Error(workspaceFact ? "workspace facts cannot name a profile subject" : "human profile facts require a subject");
|
|
26995
|
+
}
|
|
26996
|
+
return {
|
|
26997
|
+
proposalVersion: INSTITUTIONAL_MEMORY_PROPOSAL_VERSION,
|
|
26998
|
+
candidateType: proposal.candidateType,
|
|
26999
|
+
memoryKind: proposal.memoryKind,
|
|
27000
|
+
...subjectIdentityId ? { subjectIdentityId } : {},
|
|
27001
|
+
canonicalKey,
|
|
27002
|
+
body: conciseInstitutionalMemoryBody(proposal.body),
|
|
27003
|
+
keywords: institutionalMemoryKeywords(proposal.keywords),
|
|
27004
|
+
source: { roomId, messageIds },
|
|
27005
|
+
audience: proposal.audience,
|
|
27006
|
+
confidence: proposal.confidence,
|
|
27007
|
+
classification: {
|
|
27008
|
+
...classification.stillTrueForAnotherRequester === void 0 ? {} : {
|
|
27009
|
+
stillTrueForAnotherRequester: classification.stillTrueForAnotherRequester
|
|
27010
|
+
},
|
|
27011
|
+
...classification.subjectIsRequester === void 0 ? {} : {
|
|
27012
|
+
subjectIsRequester: classification.subjectIsRequester
|
|
27013
|
+
},
|
|
27014
|
+
rationale
|
|
27015
|
+
},
|
|
27016
|
+
cas: {
|
|
27017
|
+
baseVersion: cas.baseVersion,
|
|
27018
|
+
...supersedesItemId ? { supersedesItemId } : {}
|
|
27019
|
+
}
|
|
27020
|
+
};
|
|
26959
27021
|
}
|
|
26960
|
-
function
|
|
26961
|
-
|
|
26962
|
-
|
|
26963
|
-
|
|
26964
|
-
|
|
26965
|
-
|
|
26966
|
-
|
|
26967
|
-
return "unknown";
|
|
26968
|
-
return options.osSandbox ? "runs" : "refused";
|
|
27022
|
+
function repositoryRelativePath(value) {
|
|
27023
|
+
if (typeof value !== "string" || value.length === 0 || value.length > 500)
|
|
27024
|
+
return void 0;
|
|
27025
|
+
if (value.startsWith("/") || value.includes("\\") || value.split("/").some((segment) => segment === ".." || segment === "")) {
|
|
27026
|
+
return void 0;
|
|
27027
|
+
}
|
|
27028
|
+
return value;
|
|
26969
27029
|
}
|
|
26970
|
-
|
|
26971
|
-
|
|
26972
|
-
|
|
26973
|
-
|
|
26974
|
-
|
|
26975
|
-
|
|
26976
|
-
|
|
26977
|
-
|
|
26978
|
-
|
|
26979
|
-
|
|
26980
|
-
|
|
26981
|
-
|
|
26982
|
-
|
|
26983
|
-
|
|
26984
|
-
|
|
26985
|
-
|
|
26986
|
-
|
|
26987
|
-
|
|
26988
|
-
|
|
27030
|
+
function optionalAnchorField(key, value) {
|
|
27031
|
+
return value === void 0 ? {} : { [key]: value };
|
|
27032
|
+
}
|
|
27033
|
+
function parseInstitutionalMergeReviewProposal(value) {
|
|
27034
|
+
const proposal = record2(value, "institutional merge review proposal");
|
|
27035
|
+
exactKeys(proposal, ["proposalVersion", "skill", "findings"], "institutional merge review proposal");
|
|
27036
|
+
if (proposal.proposalVersion !== 1) {
|
|
27037
|
+
throw new Error("institutional merge review proposal version is unsupported");
|
|
27038
|
+
}
|
|
27039
|
+
let skill = null;
|
|
27040
|
+
if (!omitted(proposal.skill)) {
|
|
27041
|
+
const rawSkill = record2(proposal.skill, "workspace skill proposal");
|
|
27042
|
+
exactKeys(rawSkill, ["slug", "description", "markdown", "baseVersion", "anchor"], "workspace skill proposal");
|
|
27043
|
+
const slug = boundedText(rawSkill.slug, "workspace skill slug", WORKSPACE_SKILL_SLUG_MAX_LENGTH);
|
|
27044
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug)) {
|
|
27045
|
+
throw new Error("workspace skill slug is invalid");
|
|
27046
|
+
}
|
|
27047
|
+
const anchor = record2(rawSkill.anchor, "workspace skill code anchor");
|
|
27048
|
+
exactKeys(anchor, ["repository", "targetCommit", "path"], "workspace skill code anchor");
|
|
27049
|
+
if (rawSkill.baseVersion !== null && (!Number.isSafeInteger(rawSkill.baseVersion) || rawSkill.baseVersion <= 0)) {
|
|
27050
|
+
throw new Error("workspace skill base version is invalid");
|
|
27051
|
+
}
|
|
27052
|
+
skill = {
|
|
27053
|
+
slug,
|
|
27054
|
+
description: boundedText(rawSkill.description, "workspace skill description", WORKSPACE_SKILL_DESCRIPTION_MAX_LENGTH),
|
|
27055
|
+
markdown: boundedText(rawSkill.markdown, "workspace skill markdown", WORKSPACE_SKILL_MARKDOWN_MAX_BYTES, true),
|
|
27056
|
+
baseVersion: rawSkill.baseVersion,
|
|
27057
|
+
anchor: {
|
|
27058
|
+
repository: boundedText(anchor.repository, "workspace skill repository", 300),
|
|
27059
|
+
targetCommit: boundedText(anchor.targetCommit, "workspace skill target commit", 160),
|
|
27060
|
+
...optionalAnchorField("path", repositoryRelativePath(anchor.path))
|
|
26989
27061
|
}
|
|
27062
|
+
};
|
|
27063
|
+
}
|
|
27064
|
+
if (!Array.isArray(proposal.findings) || proposal.findings.length > INSTITUTIONAL_REVIEW_FINDING_MAX) {
|
|
27065
|
+
throw new Error("institutional review findings are invalid");
|
|
27066
|
+
}
|
|
27067
|
+
const findings = proposal.findings.map((value2) => {
|
|
27068
|
+
const finding = record2(value2, "institutional review finding");
|
|
27069
|
+
exactKeys(finding, ["taxonomy", "summary", "severity", "confidence", "path"], "institutional review finding");
|
|
27070
|
+
if (finding.severity !== "info" && finding.severity !== "warning" && finding.severity !== "error") {
|
|
27071
|
+
throw new Error("institutional review finding severity is invalid");
|
|
26990
27072
|
}
|
|
26991
|
-
|
|
26992
|
-
|
|
26993
|
-
|
|
26994
|
-
var PROFILES2 = [
|
|
26995
|
-
{ match: /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i, profile: CLAUDE_PROFILE },
|
|
26996
|
-
{
|
|
26997
|
-
match: /(^|[/\\])codex-acp(\.[a-z]+)?$/i,
|
|
26998
|
-
profile: {
|
|
26999
|
-
enforcement: "config-isolated",
|
|
27000
|
-
note: "codex-acp merges the session's MCP servers into $CODEX_HOME/config.toml's own [mcp_servers] instead of replacing them, so only an isolated CODEX_HOME scopes the session; the ChatGPT account's codex_apps connectors survive either way"
|
|
27073
|
+
const severity = finding.severity;
|
|
27074
|
+
if (typeof finding.confidence !== "number" || !Number.isFinite(finding.confidence) || finding.confidence < 0 || finding.confidence > 1) {
|
|
27075
|
+
throw new Error("institutional review finding confidence is invalid");
|
|
27001
27076
|
}
|
|
27002
|
-
|
|
27003
|
-
|
|
27004
|
-
|
|
27005
|
-
|
|
27006
|
-
|
|
27007
|
-
|
|
27077
|
+
return {
|
|
27078
|
+
taxonomy: boundedText(finding.taxonomy, "institutional review finding taxonomy", 120),
|
|
27079
|
+
summary: boundedText(finding.summary, "institutional review finding summary", 1e3),
|
|
27080
|
+
severity,
|
|
27081
|
+
confidence: finding.confidence,
|
|
27082
|
+
...omitted(finding.path) ? {} : { path: boundedText(finding.path, "institutional review finding path", 500) }
|
|
27083
|
+
};
|
|
27084
|
+
});
|
|
27085
|
+
return { proposalVersion: 1, skill, findings };
|
|
27086
|
+
}
|
|
27087
|
+
function parseInstitutionalCuratorProposal(value) {
|
|
27088
|
+
const proposal = record2(value, "institutional curator proposal");
|
|
27089
|
+
exactKeys(proposal, ["proposalVersion", "partition", "actions"], "institutional curator proposal");
|
|
27090
|
+
if (proposal.proposalVersion !== 1) {
|
|
27091
|
+
throw new Error("institutional curator proposal version is unsupported");
|
|
27092
|
+
}
|
|
27093
|
+
const partition = boundedText(proposal.partition, "institutional curator partition", 300);
|
|
27094
|
+
if (!Array.isArray(proposal.actions) || proposal.actions.length > INSTITUTIONAL_CURATOR_ACTION_MAX) {
|
|
27095
|
+
throw new Error("institutional curator actions are invalid");
|
|
27096
|
+
}
|
|
27097
|
+
const actions = proposal.actions.map((value2) => {
|
|
27098
|
+
const action = record2(value2, "institutional curator action");
|
|
27099
|
+
exactKeys(action, [
|
|
27100
|
+
"action",
|
|
27101
|
+
"targetType",
|
|
27102
|
+
"targetId",
|
|
27103
|
+
"baseVersion",
|
|
27104
|
+
"duplicateIds",
|
|
27105
|
+
"body",
|
|
27106
|
+
"description",
|
|
27107
|
+
"markdown",
|
|
27108
|
+
"rationale"
|
|
27109
|
+
], "institutional curator action");
|
|
27110
|
+
if (action.action !== "retain" && action.action !== "stale" && action.action !== "archive" && action.action !== "consolidate") {
|
|
27111
|
+
throw new Error("institutional curator action kind is invalid");
|
|
27008
27112
|
}
|
|
27009
|
-
|
|
27010
|
-
|
|
27011
|
-
match: /(^|[/\\])grok(\.[a-z]+)?$/i,
|
|
27012
|
-
profile: {
|
|
27013
|
-
enforcement: "config-isolated",
|
|
27014
|
-
note: "grok loads the operator's own ~/.grok MCP servers even when session/new passes an empty mcpServers list (measured live), so only an isolated GROK_HOME scopes the session; no account-bound connector surface was found"
|
|
27113
|
+
if (action.targetType !== "memory_item" && action.targetType !== "workspace_skill") {
|
|
27114
|
+
throw new Error("institutional curator target type is invalid");
|
|
27015
27115
|
}
|
|
27016
|
-
|
|
27017
|
-
|
|
27018
|
-
match: /(^|[/\\])buzz-agent(\.[a-z]+)?$/i,
|
|
27019
|
-
profile: {
|
|
27020
|
-
enforcement: "allowlisted",
|
|
27021
|
-
note: "buzz-agent mounts only the MCP servers the daemon passes; it has no operator-global tool config"
|
|
27116
|
+
if (!Number.isSafeInteger(action.baseVersion) || action.baseVersion <= 0) {
|
|
27117
|
+
throw new Error("institutional curator base version is invalid");
|
|
27022
27118
|
}
|
|
27023
|
-
|
|
27024
|
-
|
|
27025
|
-
match: CURSOR_HARNESS_COMMAND,
|
|
27026
|
-
profile: {
|
|
27027
|
-
enforcement: "config-isolated",
|
|
27028
|
-
note: "cursor-acp-bridge writes session/new mcpServers into the isolated CURSOR_HOME mcp.json and the isolated $HOME/.cursor/mcp.json cursor-agent loads; it never writes the operator ~/.cursor"
|
|
27119
|
+
if (!Array.isArray(action.duplicateIds) || action.duplicateIds.length > 20 || action.duplicateIds.some((id) => typeof id !== "string" || !id || id.length > 100)) {
|
|
27120
|
+
throw new Error("institutional curator duplicate ids are invalid");
|
|
27029
27121
|
}
|
|
27030
|
-
|
|
27031
|
-
|
|
27032
|
-
|
|
27033
|
-
|
|
27034
|
-
|
|
27035
|
-
}
|
|
27036
|
-
|
|
27037
|
-
|
|
27122
|
+
if (action.action === "consolidate" && action.duplicateIds.length === 0) {
|
|
27123
|
+
throw new Error("institutional curator consolidation needs duplicates");
|
|
27124
|
+
}
|
|
27125
|
+
if (action.action !== "consolidate" && action.duplicateIds.length !== 0) {
|
|
27126
|
+
throw new Error("institutional curator lifecycle action cannot carry duplicates");
|
|
27127
|
+
}
|
|
27128
|
+
const body = omitted(action.body) ? void 0 : action.targetType === "memory_item" ? conciseInstitutionalMemoryBody(action.body) : boundedText(action.body, "institutional curator body", INSTITUTIONAL_MEMORY_BODY_MAX_BYTES, true);
|
|
27129
|
+
const description = omitted(action.description) ? void 0 : boundedText(action.description, "institutional curator skill description", WORKSPACE_SKILL_DESCRIPTION_MAX_LENGTH);
|
|
27130
|
+
const markdown = omitted(action.markdown) ? void 0 : boundedText(action.markdown, "institutional curator skill markdown", WORKSPACE_SKILL_MARKDOWN_MAX_BYTES, true);
|
|
27131
|
+
if (action.action === "consolidate" && (action.targetType === "memory_item" && (!body || description || markdown) || action.targetType === "workspace_skill" && (!description || !markdown || body))) {
|
|
27132
|
+
throw new Error("institutional curator consolidation content is invalid");
|
|
27133
|
+
}
|
|
27134
|
+
if (action.action !== "consolidate" && (body || description || markdown)) {
|
|
27135
|
+
throw new Error("institutional curator lifecycle action cannot replace content");
|
|
27136
|
+
}
|
|
27137
|
+
return {
|
|
27138
|
+
action: action.action,
|
|
27139
|
+
targetType: action.targetType,
|
|
27140
|
+
targetId: boundedText(action.targetId, "institutional curator target id", 100),
|
|
27141
|
+
baseVersion: action.baseVersion,
|
|
27142
|
+
duplicateIds: [...new Set(action.duplicateIds)],
|
|
27143
|
+
...body ? { body } : {},
|
|
27144
|
+
...description ? { description } : {},
|
|
27145
|
+
...markdown ? { markdown } : {},
|
|
27146
|
+
rationale: boundedText(action.rationale, "institutional curator rationale", 500)
|
|
27147
|
+
};
|
|
27148
|
+
});
|
|
27149
|
+
return { proposalVersion: 1, partition, actions };
|
|
27038
27150
|
}
|
|
27039
|
-
|
|
27040
|
-
|
|
27041
|
-
|
|
27042
|
-
|
|
27043
|
-
|
|
27044
|
-
|
|
27045
|
-
|
|
27046
|
-
|
|
27151
|
+
|
|
27152
|
+
// packages/api-contract/dist/workflow-contracts.js
|
|
27153
|
+
var WORKFLOW_TIMEOUT_SECONDS_MAX = 30 * 24 * 60 * 60;
|
|
27154
|
+
|
|
27155
|
+
// packages/api-contract/dist/agent-classes.js
|
|
27156
|
+
var WEIGHT_TIER_RULE_PATTERN_MAX_LENGTH = 32;
|
|
27157
|
+
var RULE_PATTERN_SHAPE = new RegExp(`^[a-z0-9*.-]{1,${WEIGHT_TIER_RULE_PATTERN_MAX_LENGTH}}$`);
|
|
27158
|
+
|
|
27159
|
+
// apps/body/dist/transient-provider-error.js
|
|
27160
|
+
var TRANSIENT_PATTERNS = [
|
|
27161
|
+
/\b429\b/,
|
|
27162
|
+
/\b529\b/,
|
|
27163
|
+
/overloaded/i,
|
|
27164
|
+
/rate.?limit/i,
|
|
27165
|
+
/\bETIMEDOUT\b/,
|
|
27166
|
+
/\bECONNRESET\b/,
|
|
27167
|
+
/\bECONNREFUSED\b/,
|
|
27168
|
+
/timed out/i,
|
|
27169
|
+
/\btimeout\b/i
|
|
27170
|
+
];
|
|
27171
|
+
function isTransientProviderText(text2) {
|
|
27172
|
+
return TRANSIENT_PATTERNS.some((pattern) => pattern.test(text2));
|
|
27047
27173
|
}
|
|
27048
27174
|
|
|
27049
|
-
// apps/body/dist/
|
|
27050
|
-
var
|
|
27051
|
-
|
|
27052
|
-
|
|
27053
|
-
|
|
27054
|
-
|
|
27055
|
-
|
|
27056
|
-
|
|
27057
|
-
|
|
27058
|
-
}
|
|
27059
|
-
return delta;
|
|
27175
|
+
// apps/body/dist/model-config.js
|
|
27176
|
+
var GROK_SESSION_MODEL_AXIS_ID = "beeline:grok-session-model";
|
|
27177
|
+
var GROK_LAUNCH_EFFORT_AXIS_ID = "beeline:grok-launch-reasoning-effort";
|
|
27178
|
+
function isGrokAgentCommand(agent) {
|
|
27179
|
+
if (agent.kind === "grok")
|
|
27180
|
+
return true;
|
|
27181
|
+
if (agent.kind && agent.kind !== "custom")
|
|
27182
|
+
return false;
|
|
27183
|
+
return /^grok(?:\.[a-z0-9]+)?$/i.test(basename3(agent.command));
|
|
27060
27184
|
}
|
|
27061
|
-
function
|
|
27062
|
-
const
|
|
27063
|
-
|
|
27064
|
-
|
|
27065
|
-
|
|
27066
|
-
|
|
27067
|
-
|
|
27068
|
-
|
|
27069
|
-
|
|
27070
|
-
const block2 = [line];
|
|
27071
|
-
let depth = braceDelta(line);
|
|
27072
|
-
if (depth === 0 && lines[index + 1]?.trimStart().startsWith("{")) {
|
|
27185
|
+
function agentArgsWithModelSelection(agent, selection) {
|
|
27186
|
+
const original = [...agent.args];
|
|
27187
|
+
if (!selection || !selection.model && !selection.effort || !isGrokAgentCommand(agent) || !original.includes("agent") || !original.includes("stdio")) {
|
|
27188
|
+
return original;
|
|
27189
|
+
}
|
|
27190
|
+
const stripped = [];
|
|
27191
|
+
for (let index = 0; index < original.length; index += 1) {
|
|
27192
|
+
const arg = original[index];
|
|
27193
|
+
if (arg === "-m" || arg === "--model" || arg === "--reasoning-effort") {
|
|
27073
27194
|
index += 1;
|
|
27074
|
-
|
|
27075
|
-
depth = braceDelta(lines[index]);
|
|
27195
|
+
continue;
|
|
27076
27196
|
}
|
|
27077
|
-
|
|
27078
|
-
|
|
27079
|
-
block2.push(lines[index]);
|
|
27080
|
-
depth += braceDelta(lines[index]);
|
|
27197
|
+
if (arg.startsWith("--model=") || arg.startsWith("--reasoning-effort=") || /^-m=/.test(arg)) {
|
|
27198
|
+
continue;
|
|
27081
27199
|
}
|
|
27082
|
-
|
|
27083
|
-
kept.push(...block2);
|
|
27200
|
+
stripped.push(arg);
|
|
27084
27201
|
}
|
|
27085
|
-
|
|
27086
|
-
|
|
27087
|
-
|
|
27088
|
-
|
|
27202
|
+
const stdioIndex = stripped.lastIndexOf("stdio");
|
|
27203
|
+
const configured = [
|
|
27204
|
+
...selection.model ? ["--model", selection.model] : [],
|
|
27205
|
+
...selection.effort ? ["--reasoning-effort", selection.effort] : []
|
|
27206
|
+
];
|
|
27207
|
+
stripped.splice(stdioIndex, 0, ...configured);
|
|
27208
|
+
return stripped;
|
|
27209
|
+
}
|
|
27210
|
+
function advertisedChoiceId(choice) {
|
|
27211
|
+
if (typeof choice.id === "string" && choice.id.length > 0)
|
|
27212
|
+
return choice.id;
|
|
27213
|
+
if (typeof choice.value === "string" && choice.value.length > 0)
|
|
27214
|
+
return choice.value;
|
|
27215
|
+
return void 0;
|
|
27216
|
+
}
|
|
27217
|
+
function modelFamilyKey(choice) {
|
|
27218
|
+
return (/^\s*[\p{L}]+/u.exec(choice.name ?? "")?.[0] ?? "").toLowerCase();
|
|
27219
|
+
}
|
|
27220
|
+
function modelVersionKey(choice) {
|
|
27221
|
+
const digits = choice.name?.match(/\d+/g) ?? choice.id.match(/\d+/g) ?? [];
|
|
27222
|
+
return digits.map(Number);
|
|
27223
|
+
}
|
|
27224
|
+
function sortModelChoicesNewestFirst(choices) {
|
|
27225
|
+
const indexed = choices.map((choice, index) => ({ choice, index }));
|
|
27226
|
+
const families = /* @__PURE__ */ new Map();
|
|
27227
|
+
for (const entry of indexed) {
|
|
27228
|
+
const key = modelFamilyKey(entry.choice);
|
|
27229
|
+
const bucket = families.get(key);
|
|
27230
|
+
if (bucket)
|
|
27231
|
+
bucket.push(entry);
|
|
27232
|
+
else
|
|
27233
|
+
families.set(key, [entry]);
|
|
27234
|
+
}
|
|
27235
|
+
const result = [];
|
|
27236
|
+
for (const bucket of families.values()) {
|
|
27237
|
+
bucket.sort((left, right) => {
|
|
27238
|
+
const leftParts = modelVersionKey(left.choice);
|
|
27239
|
+
const rightParts = modelVersionKey(right.choice);
|
|
27240
|
+
for (let index = 0; index < Math.max(leftParts.length, rightParts.length); index += 1) {
|
|
27241
|
+
const delta = (rightParts[index] ?? -1) - (leftParts[index] ?? -1);
|
|
27242
|
+
if (delta !== 0)
|
|
27243
|
+
return delta;
|
|
27244
|
+
}
|
|
27245
|
+
return left.index - right.index;
|
|
27246
|
+
});
|
|
27247
|
+
result.push(...bucket.map(({ choice }) => choice));
|
|
27248
|
+
}
|
|
27249
|
+
return result;
|
|
27250
|
+
}
|
|
27251
|
+
function resolveModelFamilyFallback(options, missingId) {
|
|
27252
|
+
const family = (/^\s*[\p{L}]+/u.exec(missingId)?.[0] ?? "").toLowerCase();
|
|
27253
|
+
if (!family)
|
|
27254
|
+
return void 0;
|
|
27255
|
+
return options.find((choice) => modelFamilyKey(choice) === family);
|
|
27256
|
+
}
|
|
27257
|
+
function parseAdvertisedConfigOptions(raw, preferredModelId, includeLaunchEffort = false) {
|
|
27258
|
+
const configOptions = raw?.configOptions;
|
|
27259
|
+
const result = [];
|
|
27260
|
+
for (const entry of Array.isArray(configOptions) ? configOptions : []) {
|
|
27261
|
+
if (!entry || typeof entry !== "object")
|
|
27262
|
+
continue;
|
|
27263
|
+
const record6 = entry;
|
|
27264
|
+
const id = record6.id;
|
|
27265
|
+
const category = record6.category;
|
|
27266
|
+
if (typeof id !== "string" || typeof category !== "string")
|
|
27267
|
+
continue;
|
|
27268
|
+
const rawChoices = Array.isArray(record6.options) ? record6.options : [];
|
|
27269
|
+
const choices = [];
|
|
27270
|
+
for (const rawChoice of rawChoices) {
|
|
27271
|
+
if (!rawChoice || typeof rawChoice !== "object")
|
|
27272
|
+
continue;
|
|
27273
|
+
const choice = rawChoice;
|
|
27274
|
+
const choiceId = advertisedChoiceId(choice);
|
|
27275
|
+
if (!choiceId)
|
|
27276
|
+
continue;
|
|
27277
|
+
choices.push({
|
|
27278
|
+
id: choiceId,
|
|
27279
|
+
...typeof choice.name === "string" ? { name: choice.name } : {}
|
|
27280
|
+
});
|
|
27281
|
+
}
|
|
27282
|
+
result.push({
|
|
27283
|
+
id,
|
|
27284
|
+
category,
|
|
27285
|
+
...typeof record6.currentValue === "string" ? { currentValue: record6.currentValue } : {},
|
|
27286
|
+
options: category === "model" ? sortModelChoicesNewestFirst(choices) : choices
|
|
27287
|
+
});
|
|
27288
|
+
}
|
|
27289
|
+
const models = raw?.models;
|
|
27290
|
+
if (!models || typeof models !== "object")
|
|
27291
|
+
return result;
|
|
27292
|
+
const modelState = models;
|
|
27293
|
+
const availableModels = Array.isArray(modelState.availableModels) ? modelState.availableModels : [];
|
|
27294
|
+
const modelChoices = [];
|
|
27295
|
+
for (const entry of availableModels) {
|
|
27296
|
+
if (!entry || typeof entry !== "object")
|
|
27297
|
+
continue;
|
|
27298
|
+
const model = entry;
|
|
27299
|
+
if (typeof model.modelId !== "string" || !model.modelId)
|
|
27300
|
+
continue;
|
|
27301
|
+
modelChoices.push({
|
|
27302
|
+
id: model.modelId,
|
|
27303
|
+
...typeof model.name === "string" ? { name: model.name } : {}
|
|
27304
|
+
});
|
|
27305
|
+
}
|
|
27306
|
+
const currentModelId = typeof modelState.currentModelId === "string" ? modelState.currentModelId : void 0;
|
|
27307
|
+
if (modelChoices.length > 0 && !result.some((axis) => axis.category === "model")) {
|
|
27308
|
+
result.push({
|
|
27309
|
+
id: GROK_SESSION_MODEL_AXIS_ID,
|
|
27310
|
+
category: "model",
|
|
27311
|
+
...currentModelId ? { currentValue: currentModelId } : {},
|
|
27312
|
+
options: sortModelChoicesNewestFirst(modelChoices)
|
|
27313
|
+
});
|
|
27314
|
+
}
|
|
27315
|
+
const effortModelId = preferredModelId ?? currentModelId;
|
|
27316
|
+
const currentModel = availableModels.find((entry) => entry && typeof entry === "object" && entry.modelId === effortModelId);
|
|
27317
|
+
const meta = currentModel?._meta;
|
|
27318
|
+
const modelMeta = meta && typeof meta === "object" ? meta : void 0;
|
|
27319
|
+
const efforts = Array.isArray(modelMeta?.reasoningEfforts) ? modelMeta.reasoningEfforts : [];
|
|
27320
|
+
const effortChoices = [];
|
|
27321
|
+
for (const entry of efforts) {
|
|
27322
|
+
if (!entry || typeof entry !== "object")
|
|
27323
|
+
continue;
|
|
27324
|
+
const effort = entry;
|
|
27325
|
+
const id = advertisedChoiceId(effort);
|
|
27326
|
+
if (!id)
|
|
27327
|
+
continue;
|
|
27328
|
+
effortChoices.push({
|
|
27329
|
+
id,
|
|
27330
|
+
...typeof effort.label === "string" ? { name: effort.label } : typeof effort.name === "string" ? { name: effort.name } : {}
|
|
27331
|
+
});
|
|
27332
|
+
}
|
|
27333
|
+
const hasEffortAxis = result.some((axis) => ["thought_level", "effort", "reasoning_effort"].includes(axis.category));
|
|
27334
|
+
if (includeLaunchEffort && effortChoices.length > 0 && !hasEffortAxis) {
|
|
27335
|
+
const currentEffort = typeof modelMeta?.reasoningEffort === "string" ? modelMeta.reasoningEffort : efforts.find((entry) => entry && typeof entry === "object" && entry.default)?.value;
|
|
27336
|
+
result.push({
|
|
27337
|
+
id: GROK_LAUNCH_EFFORT_AXIS_ID,
|
|
27338
|
+
category: "reasoning_effort",
|
|
27339
|
+
...typeof currentEffort === "string" ? { currentValue: currentEffort } : {},
|
|
27340
|
+
options: effortChoices
|
|
27341
|
+
});
|
|
27342
|
+
}
|
|
27343
|
+
return result;
|
|
27344
|
+
}
|
|
27345
|
+
function filterAllowedModelConfigOptions(options) {
|
|
27346
|
+
return options.filter((option) => isAllowedAgentModelConfigCategory(option.category, option.id));
|
|
27347
|
+
}
|
|
27348
|
+
var PROVIDER_CREDENTIAL_ENV_HINTS = {
|
|
27349
|
+
openai: ["OPENAI_API_KEY", "OPENAI_COMPAT_API_KEY"],
|
|
27350
|
+
openrouter: ["OPENROUTER_API_KEY"],
|
|
27351
|
+
anthropic: ["ANTHROPIC_API_KEY"],
|
|
27352
|
+
google: ["GOOGLE_API_KEY", "GEMINI_API_KEY"],
|
|
27353
|
+
groq: ["GROQ_API_KEY"],
|
|
27354
|
+
mistral: ["MISTRAL_API_KEY"],
|
|
27355
|
+
deepseek: ["DEEPSEEK_API_KEY"],
|
|
27356
|
+
xai: ["XAI_API_KEY"],
|
|
27357
|
+
cohere: ["COHERE_API_KEY"],
|
|
27358
|
+
together: ["TOGETHER_API_KEY"],
|
|
27359
|
+
fireworks: ["FIREWORKS_API_KEY"]
|
|
27360
|
+
};
|
|
27361
|
+
function credentialedProviders(env) {
|
|
27362
|
+
const held = /* @__PURE__ */ new Set();
|
|
27363
|
+
for (const [provider, names] of Object.entries(PROVIDER_CREDENTIAL_ENV_HINTS)) {
|
|
27364
|
+
if (names.some((name) => Boolean(env[name]?.trim())))
|
|
27365
|
+
held.add(provider);
|
|
27366
|
+
}
|
|
27367
|
+
for (const provider of credentialedPiCustomProviders(env))
|
|
27368
|
+
held.add(provider);
|
|
27369
|
+
return held;
|
|
27370
|
+
}
|
|
27371
|
+
function credentialedPiCustomProviders(env) {
|
|
27372
|
+
const agentDir = env.PI_CODING_AGENT_DIR?.trim() ? resolve9(env.PI_CODING_AGENT_DIR) : env.HOME?.trim() ? resolve9(env.HOME, ".pi/agent") : void 0;
|
|
27373
|
+
const held = /* @__PURE__ */ new Set();
|
|
27374
|
+
if (!agentDir)
|
|
27375
|
+
return held;
|
|
27376
|
+
const path = resolve9(agentDir, "models.json");
|
|
27377
|
+
try {
|
|
27378
|
+
const stats = lstatSync(path);
|
|
27379
|
+
if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1 || stats.size > 1048576) {
|
|
27380
|
+
return held;
|
|
27381
|
+
}
|
|
27382
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
27383
|
+
const providers = parsed.providers;
|
|
27384
|
+
const remember = (name, config) => {
|
|
27385
|
+
if (typeof name !== "string" || !name.trim() || !config || typeof config !== "object")
|
|
27386
|
+
return;
|
|
27387
|
+
const apiKey = config.apiKey;
|
|
27388
|
+
if (typeof apiKey === "string" && apiKey.trim())
|
|
27389
|
+
held.add(name.trim());
|
|
27390
|
+
};
|
|
27391
|
+
if (Array.isArray(providers)) {
|
|
27392
|
+
for (const provider of providers) {
|
|
27393
|
+
const record6 = provider;
|
|
27394
|
+
remember(record6?.name ?? record6?.id, record6);
|
|
27395
|
+
}
|
|
27396
|
+
} else if (providers && typeof providers === "object") {
|
|
27397
|
+
for (const [name, config] of Object.entries(providers)) {
|
|
27398
|
+
remember(name, config);
|
|
27399
|
+
}
|
|
27400
|
+
}
|
|
27401
|
+
} catch {
|
|
27402
|
+
}
|
|
27403
|
+
return held;
|
|
27404
|
+
}
|
|
27405
|
+
function filterModelOptionsByCredentials(options, env) {
|
|
27406
|
+
const held = credentialedProviders(env);
|
|
27407
|
+
return options.map((option) => {
|
|
27408
|
+
if (option.category !== "model")
|
|
27409
|
+
return option;
|
|
27410
|
+
return {
|
|
27411
|
+
...option,
|
|
27412
|
+
options: option.options.filter((choice) => {
|
|
27413
|
+
const slash = choice.id.indexOf("/");
|
|
27414
|
+
if (slash < 0)
|
|
27415
|
+
return true;
|
|
27416
|
+
return held.has(choice.id.slice(0, slash));
|
|
27417
|
+
})
|
|
27418
|
+
};
|
|
27419
|
+
});
|
|
27420
|
+
}
|
|
27421
|
+
var DisallowedModelConfigOptionError = class extends Error {
|
|
27422
|
+
constructor(configId) {
|
|
27423
|
+
super(`model config option "${configId}" is not in the allow-listed catalog`);
|
|
27424
|
+
this.name = "DisallowedModelConfigOptionError";
|
|
27425
|
+
}
|
|
27426
|
+
};
|
|
27427
|
+
function supportsFastMode(options) {
|
|
27428
|
+
const axis = options.find((option) => option.id === "fast-mode" && option.category === "model_config");
|
|
27429
|
+
return Boolean(axis?.options.some((choice) => choice.id === "on") && axis.options.some((choice) => choice.id === "off"));
|
|
27430
|
+
}
|
|
27431
|
+
var ModelSelectionUnavailableError = class extends Error {
|
|
27432
|
+
label;
|
|
27433
|
+
value;
|
|
27434
|
+
reason;
|
|
27435
|
+
guidance;
|
|
27436
|
+
constructor(input) {
|
|
27437
|
+
const recovery = input.guidance ? ` ${input.guidance}` : " Choose one of the values in the live harness catalog.";
|
|
27438
|
+
super(`${input.label} "${input.value}" is unavailable.${recovery}`);
|
|
27439
|
+
this.name = "ModelSelectionUnavailableError";
|
|
27440
|
+
this.label = input.label;
|
|
27441
|
+
this.value = input.value;
|
|
27442
|
+
this.reason = input.reason;
|
|
27443
|
+
this.guidance = input.guidance;
|
|
27444
|
+
}
|
|
27445
|
+
};
|
|
27446
|
+
function withEffectiveCurrentValues(options, selection) {
|
|
27447
|
+
if (!selection || !selection.model && !selection.effort)
|
|
27448
|
+
return options;
|
|
27449
|
+
return options.map((option) => {
|
|
27450
|
+
const target = modelSelectionTargets(selection).find((entry) => entry.categories.includes(option.category));
|
|
27451
|
+
if (!target?.value || option.currentValue === target.value)
|
|
27452
|
+
return option;
|
|
27453
|
+
return { ...option, currentValue: target.value };
|
|
27454
|
+
});
|
|
27455
|
+
}
|
|
27456
|
+
function modelSelectionTargets(selection) {
|
|
27457
|
+
return [
|
|
27458
|
+
{ categories: ["model"], label: "model", value: selection.model },
|
|
27459
|
+
{
|
|
27460
|
+
categories: ["thought_level", "effort", "reasoning_effort"],
|
|
27461
|
+
label: "effort",
|
|
27462
|
+
value: selection.effort
|
|
27463
|
+
}
|
|
27464
|
+
];
|
|
27465
|
+
}
|
|
27466
|
+
function assertModelConfigAxisAllowed(configId, advertisedOptions) {
|
|
27467
|
+
const axis = advertisedOptions.find((option) => option.id === configId);
|
|
27468
|
+
if (!axis || !isAllowedAgentModelConfigCategory(axis.category, axis.id)) {
|
|
27469
|
+
throw new DisallowedModelConfigOptionError(configId);
|
|
27470
|
+
}
|
|
27471
|
+
}
|
|
27472
|
+
async function applyAgentModelSelectionWithUpdatedCatalog(client, sessionId, advertisedOptions, selection) {
|
|
27473
|
+
let currentOptions = advertisedOptions;
|
|
27474
|
+
const appliedSelection = {};
|
|
27475
|
+
let modelWasSubstituted = false;
|
|
27476
|
+
for (const target of modelSelectionTargets(selection)) {
|
|
27477
|
+
if (!target.value)
|
|
27478
|
+
continue;
|
|
27479
|
+
const axis = currentOptions.find((option) => target.categories.includes(option.category));
|
|
27480
|
+
if (!axis)
|
|
27481
|
+
continue;
|
|
27482
|
+
assertModelConfigAxisAllowed(axis.id, currentOptions);
|
|
27483
|
+
let value = target.value;
|
|
27484
|
+
if (!axis.options.some((choice) => choice.id === value)) {
|
|
27485
|
+
const fallback = target.label === "model" ? resolveModelFamilyFallback(axis.options, value) : void 0;
|
|
27486
|
+
if (fallback) {
|
|
27487
|
+
value = fallback.id;
|
|
27488
|
+
modelWasSubstituted = true;
|
|
27489
|
+
} else if (target.label === "effort" && modelWasSubstituted) {
|
|
27490
|
+
continue;
|
|
27491
|
+
} else {
|
|
27492
|
+
throw new ModelSelectionUnavailableError({
|
|
27493
|
+
label: target.label,
|
|
27494
|
+
value: target.value,
|
|
27495
|
+
reason: "not-advertised"
|
|
27496
|
+
});
|
|
27497
|
+
}
|
|
27498
|
+
}
|
|
27499
|
+
try {
|
|
27500
|
+
if (axis.id === GROK_SESSION_MODEL_AXIS_ID) {
|
|
27501
|
+
if (!client.setModel)
|
|
27502
|
+
throw new Error("ACP client does not support session/set_model");
|
|
27503
|
+
await client.setModel(sessionId, value);
|
|
27504
|
+
} else if (axis.id === GROK_LAUNCH_EFFORT_AXIS_ID) {
|
|
27505
|
+
if (axis.currentValue !== value) {
|
|
27506
|
+
throw new Error(`Grok started with reasoning effort "${axis.currentValue ?? "unknown"}", not "${value}"`);
|
|
27507
|
+
}
|
|
27508
|
+
} else {
|
|
27509
|
+
const updated = await client.setConfigOption(sessionId, axis.id, value);
|
|
27510
|
+
const refreshed = filterAllowedModelConfigOptions(parseAdvertisedConfigOptions(updated, target.label === "model" ? value : selection.model));
|
|
27511
|
+
if (refreshed.length > 0)
|
|
27512
|
+
currentOptions = refreshed;
|
|
27513
|
+
}
|
|
27514
|
+
} catch (error) {
|
|
27515
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
27516
|
+
if (isTransientProviderText(message) || isAuthShapedFault(message)) {
|
|
27517
|
+
throw error instanceof Error ? error : new Error(message);
|
|
27518
|
+
}
|
|
27519
|
+
throw new ModelSelectionUnavailableError({
|
|
27520
|
+
label: target.label,
|
|
27521
|
+
value: target.value,
|
|
27522
|
+
reason: "provider-refused",
|
|
27523
|
+
guidance: message
|
|
27524
|
+
});
|
|
27525
|
+
}
|
|
27526
|
+
if (target.label === "model")
|
|
27527
|
+
appliedSelection.model = value;
|
|
27528
|
+
else
|
|
27529
|
+
appliedSelection.effort = value;
|
|
27530
|
+
}
|
|
27531
|
+
if (selection.fastMode && !supportsFastMode(currentOptions)) {
|
|
27532
|
+
throw new Error("Fast mode is unavailable for the selected model and harness");
|
|
27533
|
+
}
|
|
27534
|
+
if (supportsFastMode(currentOptions)) {
|
|
27535
|
+
await client.setConfigOption(sessionId, "fast-mode", selection.fastMode ? "on" : "off");
|
|
27536
|
+
}
|
|
27537
|
+
return { options: currentOptions, appliedSelection };
|
|
27538
|
+
}
|
|
27539
|
+
async function applyAgentModelSelection(client, sessionId, advertisedOptions, selection) {
|
|
27540
|
+
return applyAgentModelSelectionWithUpdatedCatalog(client, sessionId, advertisedOptions, selection);
|
|
27541
|
+
}
|
|
27542
|
+
|
|
27543
|
+
// apps/body/dist/model-catalog.js
|
|
27544
|
+
import { mkdtemp, rm as rm3 } from "node:fs/promises";
|
|
27545
|
+
import { tmpdir } from "node:os";
|
|
27546
|
+
import { resolve as resolve10 } from "node:path";
|
|
27547
|
+
|
|
27548
|
+
// apps/body/dist/acp.js
|
|
27549
|
+
init_adapter_install_lock();
|
|
27550
|
+
import { spawn as spawn10 } from "node:child_process";
|
|
27551
|
+
import { EventEmitter } from "node:events";
|
|
27552
|
+
|
|
27553
|
+
// apps/body/dist/harness-capabilities.js
|
|
27554
|
+
init_cursor_acp_bridge();
|
|
27555
|
+
var PROFILES = [
|
|
27556
|
+
{
|
|
27557
|
+
match: /(^|[/\\])codex-acp(\.[a-z]+)?$/i,
|
|
27558
|
+
profile: {
|
|
27559
|
+
enforcement: "sandboxed",
|
|
27560
|
+
note: "codex-acp asks for every command/file change and enforces an offline read-only OS sandbox in read-only mode; under bubblewrap a Room runs it in agent-full-access and bwrap holds the filesystem rule"
|
|
27561
|
+
}
|
|
27562
|
+
},
|
|
27563
|
+
{
|
|
27564
|
+
match: /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i,
|
|
27565
|
+
profile: {
|
|
27566
|
+
enforcement: "permission-callback",
|
|
27567
|
+
note: "claude-agent-acp asks for every tool call; it advertises no read-only mode, so the daemon callback is the only boundary"
|
|
27568
|
+
}
|
|
27569
|
+
},
|
|
27570
|
+
{
|
|
27571
|
+
match: /(^|[/\\])pi-acp(\.[a-z]+)?$/i,
|
|
27572
|
+
profile: {
|
|
27573
|
+
enforcement: "none",
|
|
27574
|
+
note: "pi-acp never sends session/request_permission for a tool call: pi executes reads, writes, edits, and shell commands before the daemon sees them, and exposes no sandbox or permission flag to pass at spawn"
|
|
27575
|
+
}
|
|
27576
|
+
},
|
|
27577
|
+
{
|
|
27578
|
+
match: /(^|[/\\])grok(\.[a-z]+)?$/i,
|
|
27579
|
+
profile: {
|
|
27580
|
+
enforcement: "permission-callback",
|
|
27581
|
+
note: "grok sends standard session/request_permission requests for mutating tools in its default ask mode; it advertises no read-only ACP mode, so the daemon callback is the only boundary unless the OS sandbox wraps it"
|
|
27582
|
+
}
|
|
27583
|
+
},
|
|
27584
|
+
{
|
|
27585
|
+
match: /(^|[/\\])buzz-agent(\.[a-z]+)?$/i,
|
|
27586
|
+
profile: {
|
|
27587
|
+
enforcement: "permission-callback",
|
|
27588
|
+
note: "buzz-agent sends session/request_permission for mutating tools"
|
|
27589
|
+
}
|
|
27590
|
+
},
|
|
27591
|
+
{
|
|
27592
|
+
match: CURSOR_HARNESS_COMMAND,
|
|
27593
|
+
profile: {
|
|
27594
|
+
enforcement: "none",
|
|
27595
|
+
note: "cursor-acp-bridge drives cursor-agent with --force --approve-mcps in non-interactive stream-json mode, so cursor-agent never sends session/request_permission; Beeline already sandboxes the child"
|
|
27596
|
+
}
|
|
27597
|
+
}
|
|
27598
|
+
];
|
|
27599
|
+
function harnessEnforcement(agentCommand) {
|
|
27600
|
+
if (!agentCommand)
|
|
27601
|
+
return { enforcement: "unknown", note: "no ACP command configured" };
|
|
27602
|
+
for (const { match, profile } of PROFILES) {
|
|
27603
|
+
if (match.test(agentCommand))
|
|
27604
|
+
return profile;
|
|
27605
|
+
}
|
|
27606
|
+
return {
|
|
27607
|
+
enforcement: "unknown",
|
|
27608
|
+
note: `'${agentCommand}' has not been verified to send session/request_permission for mutating tools`
|
|
27609
|
+
};
|
|
27610
|
+
}
|
|
27611
|
+
function harnessHonorsSessionSystemPrompt(agentCommand) {
|
|
27612
|
+
return Boolean(agentCommand && /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i.test(agentCommand));
|
|
27613
|
+
}
|
|
27614
|
+
var GROK_WARM_SESSION_IDLE_MS = 30 * 6e4;
|
|
27615
|
+
function cornerAutonomyModeCandidates(agentCommand) {
|
|
27616
|
+
if (agentCommand && /(^|[/\\])codex-acp(\.[a-z]+)?$/i.test(agentCommand)) {
|
|
27617
|
+
return ["agent-full-access"];
|
|
27618
|
+
}
|
|
27619
|
+
if (agentCommand && /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i.test(agentCommand)) {
|
|
27620
|
+
return ["bypassPermissions"];
|
|
27621
|
+
}
|
|
27622
|
+
if (agentCommand && /(^|[/\\])grok(\.[a-z]+)?$/i.test(agentCommand))
|
|
27623
|
+
return [];
|
|
27624
|
+
if (agentCommand && /(^|[/\\])pi-acp(\.[a-z]+)?$/i.test(agentCommand))
|
|
27625
|
+
return [];
|
|
27626
|
+
return ["agent", "edit", "code"];
|
|
27627
|
+
}
|
|
27628
|
+
function roomModeCandidates(agentCommand, options = {}) {
|
|
27629
|
+
if (options.osSandbox && agentCommand && /(^|[/\\])codex-acp(\.[a-z]+)?$/i.test(agentCommand)) {
|
|
27630
|
+
return ["agent-full-access"];
|
|
27631
|
+
}
|
|
27632
|
+
return ["read-only", "readonly"];
|
|
27633
|
+
}
|
|
27634
|
+
function harnessDeclaresShellExecuteKind(agentCommand) {
|
|
27635
|
+
return Boolean(agentCommand && (/(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i.test(agentCommand) || /(^|[/\\])grok(\.[a-z]+)?$/i.test(agentCommand)));
|
|
27636
|
+
}
|
|
27637
|
+
function roomShellCapability(agentCommand, options = {}) {
|
|
27638
|
+
const { enforcement } = harnessEnforcement(agentCommand);
|
|
27639
|
+
if (enforcement === "sandboxed" || enforcement === "none")
|
|
27640
|
+
return "runs";
|
|
27641
|
+
if (enforcement === "unknown")
|
|
27642
|
+
return "unknown";
|
|
27643
|
+
if (!harnessDeclaresShellExecuteKind(agentCommand))
|
|
27644
|
+
return "unknown";
|
|
27645
|
+
return options.osSandbox ? "runs" : "refused";
|
|
27646
|
+
}
|
|
27647
|
+
|
|
27648
|
+
// apps/body/dist/harness-tool-scope.js
|
|
27649
|
+
init_cursor_acp_bridge();
|
|
27650
|
+
var CLAUDE_TOOL_SCOPE_SETTINGS = { disableClaudeAiConnectors: true };
|
|
27651
|
+
var CLAUDE_PROFILE = {
|
|
27652
|
+
// `settingSources: ['user']` admits the sanitized user MCP copy
|
|
27653
|
+
// while rejecting repository/local/plugin MCP. `strictMcpConfig` cannot be
|
|
27654
|
+
// used because it would reject the user copy too. Account-bound claude.ai
|
|
27655
|
+
// cloud connectors remain off independently.
|
|
27656
|
+
enforcement: "config-isolated",
|
|
27657
|
+
note: "claude-agent-acp forwards _meta.claudeCode.options to the Claude Agent SDK; user-only settingSources loads MCP from the isolated CLAUDE_CONFIG_DIR without repository/local settings, while disableClaudeAiConnectors keeps account-bound connectors off",
|
|
27658
|
+
sessionMeta: {
|
|
27659
|
+
claudeCode: {
|
|
27660
|
+
options: {
|
|
27661
|
+
// Only the sanitized user config in the isolated CLAUDE_CONFIG_DIR;
|
|
27662
|
+
// never a repository's .mcp.json, local settings, or plugins.
|
|
27663
|
+
settingSources: ["user"],
|
|
27664
|
+
// Account-bound claude.ai cloud connectors are not fetched at all.
|
|
27665
|
+
settings: CLAUDE_TOOL_SCOPE_SETTINGS
|
|
27666
|
+
}
|
|
27667
|
+
}
|
|
27668
|
+
},
|
|
27669
|
+
metaSystemPrompt: true
|
|
27670
|
+
};
|
|
27671
|
+
var PROFILES2 = [
|
|
27672
|
+
{ match: /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i, profile: CLAUDE_PROFILE },
|
|
27673
|
+
{
|
|
27674
|
+
match: /(^|[/\\])codex-acp(\.[a-z]+)?$/i,
|
|
27675
|
+
profile: {
|
|
27676
|
+
enforcement: "config-isolated",
|
|
27677
|
+
note: "codex-acp merges the session's MCP servers into $CODEX_HOME/config.toml's own [mcp_servers] instead of replacing them, so only an isolated CODEX_HOME scopes the session; the ChatGPT account's codex_apps connectors survive either way"
|
|
27678
|
+
}
|
|
27679
|
+
},
|
|
27680
|
+
{
|
|
27681
|
+
match: /(^|[/\\])pi-acp(\.[a-z]+)?$/i,
|
|
27682
|
+
profile: {
|
|
27683
|
+
enforcement: "config-isolated",
|
|
27684
|
+
note: "pi-acp 0.0.33 still stores session/new mcpServers and never reads them; pi 0.85.1 itself has no MCP client, while optional pi-mcp-adapter reads $PI_CODING_AGENT_DIR/mcp.json and isolated homes exclude the settings.json that would load it"
|
|
27685
|
+
}
|
|
27686
|
+
},
|
|
27687
|
+
{
|
|
27688
|
+
match: /(^|[/\\])grok(\.[a-z]+)?$/i,
|
|
27689
|
+
profile: {
|
|
27690
|
+
enforcement: "config-isolated",
|
|
27691
|
+
note: "grok loads the operator's own ~/.grok MCP servers even when session/new passes an empty mcpServers list (measured live), so only an isolated GROK_HOME scopes the session; no account-bound connector surface was found"
|
|
27692
|
+
}
|
|
27693
|
+
},
|
|
27694
|
+
{
|
|
27695
|
+
match: /(^|[/\\])buzz-agent(\.[a-z]+)?$/i,
|
|
27696
|
+
profile: {
|
|
27697
|
+
enforcement: "allowlisted",
|
|
27698
|
+
note: "buzz-agent mounts only the MCP servers the daemon passes; it has no operator-global tool config"
|
|
27699
|
+
}
|
|
27700
|
+
},
|
|
27701
|
+
{
|
|
27702
|
+
match: CURSOR_HARNESS_COMMAND,
|
|
27703
|
+
profile: {
|
|
27704
|
+
enforcement: "config-isolated",
|
|
27705
|
+
note: "cursor-acp-bridge writes session/new mcpServers into the isolated CURSOR_HOME mcp.json and the isolated $HOME/.cursor/mcp.json cursor-agent loads; it never writes the operator ~/.cursor"
|
|
27706
|
+
}
|
|
27707
|
+
}
|
|
27708
|
+
];
|
|
27709
|
+
function sessionToolScopeMeta(agentCommand) {
|
|
27710
|
+
const meta = matchProfile(agentCommand)?.sessionMeta;
|
|
27711
|
+
return meta ? JSON.parse(JSON.stringify(meta)) : void 0;
|
|
27712
|
+
}
|
|
27713
|
+
function harnessReadsMetaSystemPrompt(agentCommand) {
|
|
27714
|
+
return matchProfile(agentCommand)?.metaSystemPrompt === true;
|
|
27715
|
+
}
|
|
27716
|
+
function matchProfile(agentCommand) {
|
|
27717
|
+
if (!agentCommand)
|
|
27718
|
+
return void 0;
|
|
27719
|
+
for (const { match, profile } of PROFILES2) {
|
|
27720
|
+
if (match.test(agentCommand))
|
|
27721
|
+
return profile;
|
|
27722
|
+
}
|
|
27723
|
+
return void 0;
|
|
27724
|
+
}
|
|
27725
|
+
|
|
27726
|
+
// apps/body/dist/acp.js
|
|
27727
|
+
var STDERR_TAIL_MAX_CHARS2 = 2e3;
|
|
27728
|
+
function braceDelta(line) {
|
|
27729
|
+
let delta = 0;
|
|
27730
|
+
for (const char of line) {
|
|
27731
|
+
if (char === "{")
|
|
27732
|
+
delta += 1;
|
|
27733
|
+
else if (char === "}")
|
|
27734
|
+
delta -= 1;
|
|
27735
|
+
}
|
|
27736
|
+
return delta;
|
|
27737
|
+
}
|
|
27738
|
+
function meaningfulHarnessStderr(tail) {
|
|
27739
|
+
const lines = tail.split(/\r?\n/);
|
|
27740
|
+
const kept = [];
|
|
27741
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
27742
|
+
const line = lines[index];
|
|
27743
|
+
if (!/error handling notification/i.test(line)) {
|
|
27744
|
+
kept.push(line);
|
|
27745
|
+
continue;
|
|
27746
|
+
}
|
|
27747
|
+
const block2 = [line];
|
|
27748
|
+
let depth = braceDelta(line);
|
|
27749
|
+
if (depth === 0 && lines[index + 1]?.trimStart().startsWith("{")) {
|
|
27750
|
+
index += 1;
|
|
27751
|
+
block2.push(lines[index]);
|
|
27752
|
+
depth = braceDelta(lines[index]);
|
|
27753
|
+
}
|
|
27754
|
+
while (depth > 0 && index + 1 < lines.length) {
|
|
27755
|
+
index += 1;
|
|
27756
|
+
block2.push(lines[index]);
|
|
27757
|
+
depth += braceDelta(lines[index]);
|
|
27758
|
+
}
|
|
27759
|
+
if (!/notifications\/initialized/.test(block2.join("\n")))
|
|
27760
|
+
kept.push(...block2);
|
|
27761
|
+
}
|
|
27762
|
+
return kept.join("\n").trim();
|
|
27763
|
+
}
|
|
27764
|
+
function flattenHarnessCause(tail) {
|
|
27765
|
+
return meaningfulHarnessStderr(tail).replace(/\s+/g, " ").trim();
|
|
27089
27766
|
}
|
|
27090
27767
|
var AcpRequestTimeoutError = class extends Error {
|
|
27091
27768
|
method;
|
|
@@ -27972,9 +28649,17 @@ function filterAgentModelCatalog(agent, raw, agentEnv) {
|
|
|
27972
28649
|
const allowed = filterAllowedModelConfigOptions(raw).filter((axis) => axis.id !== "fast-mode" || agent.kind === "codex");
|
|
27973
28650
|
return agent.kind === "goose" || agent.kind === "opencode" ? allowed : filterModelOptionsByCredentials(allowed, agentEnv);
|
|
27974
28651
|
}
|
|
27975
|
-
|
|
27976
|
-
|
|
27977
|
-
const
|
|
28652
|
+
function withDeadline(work, ms, what) {
|
|
28653
|
+
let timer;
|
|
28654
|
+
const expired = new Promise((_, reject) => {
|
|
28655
|
+
timer = setTimeout(() => reject(new Error(`${what} timed out after ${ms}ms`)), ms);
|
|
28656
|
+
timer.unref?.();
|
|
28657
|
+
});
|
|
28658
|
+
return Promise.race([work, expired]).finally(() => clearTimeout(timer));
|
|
28659
|
+
}
|
|
28660
|
+
async function withAgentModelCatalog(agent, agentEnv, selection, inspect, limits = {}) {
|
|
28661
|
+
const deadline = limits.timeoutMs === void 0 ? void 0 : Date.now() + limits.timeoutMs;
|
|
28662
|
+
const remaining = () => deadline === void 0 ? void 0 : Math.max(1, deadline - Date.now());
|
|
27978
28663
|
const scratchCwd = await mkdtemp(resolve10(tmpdir(), "beeline-pair-model-check-"));
|
|
27979
28664
|
const probeEnv = modelCatalogProbeEnvironment(agent, agentEnv, scratchCwd);
|
|
27980
28665
|
const client = new AcpClient({
|
|
@@ -27998,7 +28683,9 @@ async function withAgentModelCatalog(agent, agentEnv, selection, inspect, limits
|
|
|
27998
28683
|
});
|
|
27999
28684
|
const raw = parseAdvertisedConfigOptions(sessionRaw, selection?.model, isGrokAgentCommand(agent));
|
|
28000
28685
|
const catalog = filterAgentModelCatalog(agent, raw, probeEnv);
|
|
28001
|
-
|
|
28686
|
+
const inspected = inspect({ client, sessionId, raw, catalog });
|
|
28687
|
+
const inspectDeadline = remaining();
|
|
28688
|
+
return inspectDeadline === void 0 ? await inspected : await withDeadline(inspected, inspectDeadline, "model catalog probe");
|
|
28002
28689
|
} finally {
|
|
28003
28690
|
await client.stop().catch(() => void 0);
|
|
28004
28691
|
await rm3(scratchCwd, { recursive: true, force: true }).catch(() => void 0);
|
|
@@ -28024,7 +28711,7 @@ async function filterModelChoicesByLiveValidation(client, sessionId, catalog, pr
|
|
|
28024
28711
|
});
|
|
28025
28712
|
available.push(choice);
|
|
28026
28713
|
if (choice.id === preferred)
|
|
28027
|
-
preferredCatalog = updated;
|
|
28714
|
+
preferredCatalog = updated.options;
|
|
28028
28715
|
} catch {
|
|
28029
28716
|
}
|
|
28030
28717
|
}
|
|
@@ -28034,7 +28721,7 @@ async function filterModelChoicesByLiveValidation(client, sessionId, catalog, pr
|
|
|
28034
28721
|
async function validateAgentModelSelection(agent, agentEnv, selection) {
|
|
28035
28722
|
return withAgentModelCatalog(agent, agentEnv, selection, async ({ client, sessionId, raw, catalog }) => {
|
|
28036
28723
|
const applied = await applyAgentModelSelectionWithUpdatedCatalog(client, sessionId, catalog, selection);
|
|
28037
|
-
return { raw, catalog: applied };
|
|
28724
|
+
return { raw, catalog: applied.options };
|
|
28038
28725
|
});
|
|
28039
28726
|
}
|
|
28040
28727
|
|
|
@@ -28064,6 +28751,9 @@ function modelUnavailableState(selection, error) {
|
|
|
28064
28751
|
}
|
|
28065
28752
|
|
|
28066
28753
|
// apps/body/dist/runtime-model-validation.js
|
|
28754
|
+
function resolvePreflightModelSelection(local, server) {
|
|
28755
|
+
return server ?? local;
|
|
28756
|
+
}
|
|
28067
28757
|
async function revalidateRuntimeModelSelection(agent, agentEnv, selection, validate = validateAgentModelSelection, refreshAdapter) {
|
|
28068
28758
|
if (!selection.model && !selection.effort)
|
|
28069
28759
|
return void 0;
|
|
@@ -28142,7 +28832,8 @@ async function syncAgentModelCatalog(input) {
|
|
|
28142
28832
|
// `fetchAgentModelCatalog` already applied the category allow-list.
|
|
28143
28833
|
options: effectiveCatalog,
|
|
28144
28834
|
...selection ? { selection } : {},
|
|
28145
|
-
...input.startupUnavailable ? { unavailable: input.startupUnavailable } : {}
|
|
28835
|
+
...input.startupUnavailable ? { unavailable: input.startupUnavailable } : {},
|
|
28836
|
+
...input.agent.kind ? { harness: input.agent.kind } : {}
|
|
28146
28837
|
});
|
|
28147
28838
|
await writeFile6(hashPath, `${hash}
|
|
28148
28839
|
`, { mode: 384 });
|
|
@@ -28439,7 +29130,7 @@ function isHostMcpIdentity(candidate, hostNames = CODE_OWNED_HOST_MCP_NAMES) {
|
|
|
28439
29130
|
|
|
28440
29131
|
// apps/body/dist/registry-mcp.js
|
|
28441
29132
|
var REGISTRY_MCP_BROKER_FLAG = "--registry-mcp-broker";
|
|
28442
|
-
function
|
|
29133
|
+
function record3(value) {
|
|
28443
29134
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
28444
29135
|
}
|
|
28445
29136
|
function safeUrl(value) {
|
|
@@ -28535,7 +29226,7 @@ async function jsonResponse(response) {
|
|
|
28535
29226
|
if (bytes.byteLength > 256 * 1024)
|
|
28536
29227
|
throw new Error("provider metadata is too large");
|
|
28537
29228
|
const parsed = JSON.parse(new TextDecoder().decode(bytes));
|
|
28538
|
-
const result =
|
|
29229
|
+
const result = record3(parsed);
|
|
28539
29230
|
if (!result)
|
|
28540
29231
|
throw new Error("provider metadata is invalid");
|
|
28541
29232
|
return result;
|
|
@@ -29109,878 +29800,363 @@ var ConnectorAssignmentLoop = class {
|
|
|
29109
29800
|
* to a new generation, and a ceremony latched to the old one must never
|
|
29110
29801
|
* swallow it. */
|
|
29111
29802
|
registryCeremonies = /* @__PURE__ */ new Map();
|
|
29112
|
-
readVaultFn;
|
|
29113
|
-
revokeGrantsFn;
|
|
29114
|
-
/** Armed only while this helper owns a live sign-in ceremony. */
|
|
29115
|
-
connectWatch;
|
|
29116
|
-
started = false;
|
|
29117
|
-
stopped = false;
|
|
29118
|
-
/** One install at a time per connector; concurrent wakes skip it. */
|
|
29119
|
-
inFlight = /* @__PURE__ */ new Set();
|
|
29120
|
-
mcp;
|
|
29121
|
-
constructor(options) {
|
|
29122
|
-
this.agentId = options.agentId;
|
|
29123
|
-
this.api = options.api;
|
|
29124
|
-
this.log = options.log ?? (() => {
|
|
29125
|
-
});
|
|
29126
|
-
this.install = options.install ?? installSquire;
|
|
29127
|
-
this.installTailscale = options.installTailscale ?? installTailscale;
|
|
29128
|
-
this.watchTailscaleSignIn = options.watchTailscaleSignIn ?? watchTailscaleSignIn;
|
|
29129
|
-
this.registryHomeDir = options.registryHome ?? process.env.HOME ?? process.cwd();
|
|
29130
|
-
this.installRegistry = options.installRegistry ?? installRegistryMcp;
|
|
29131
|
-
this.readVaultFn = options.readVault ?? readVault;
|
|
29132
|
-
this.revokeGrantsFn = options.revokeGrants ?? revokeGrants;
|
|
29133
|
-
}
|
|
29134
|
-
start() {
|
|
29135
|
-
if (this.stopped || this.started)
|
|
29136
|
-
return;
|
|
29137
|
-
this.started = true;
|
|
29138
|
-
void this.runOnce();
|
|
29139
|
-
}
|
|
29140
|
-
/** Event-driven drain, also called when the socket reconnects. */
|
|
29141
|
-
wake() {
|
|
29142
|
-
if (this.stopped)
|
|
29143
|
-
return;
|
|
29144
|
-
void this.runOnce();
|
|
29145
|
-
}
|
|
29146
|
-
stop() {
|
|
29147
|
-
this.stopped = true;
|
|
29148
|
-
this.connectWatch?.();
|
|
29149
|
-
this.connectWatch = void 0;
|
|
29150
|
-
this.tailscaleWatch?.();
|
|
29151
|
-
this.tailscaleWatch = void 0;
|
|
29152
|
-
}
|
|
29153
|
-
/**
|
|
29154
|
-
* Watch the sign-in this helper is holding open. The phone paints
|
|
29155
|
-
* `installing` for the whole ceremony and only a drain that reaches
|
|
29156
|
-
* Squire's already-connected short-circuit flips the row to `connected`;
|
|
29157
|
-
* nothing on the wire announces that the human finished, so the connect
|
|
29158
|
-
* process exiting is the signal. Drain on that, and the row settles on the
|
|
29159
|
-
* process exit event without waiting for a server read timer.
|
|
29160
|
-
*/
|
|
29161
|
-
watchConnectSignIn() {
|
|
29162
|
-
if (this.stopped || this.connectWatch)
|
|
29163
|
-
return;
|
|
29164
|
-
const claim = squireConnectSession();
|
|
29165
|
-
this.connectWatch = claim?.onExit?.(() => {
|
|
29166
|
-
this.connectWatch = void 0;
|
|
29167
|
-
if (!this.stopped)
|
|
29168
|
-
void this.runOnce();
|
|
29169
|
-
});
|
|
29170
|
-
}
|
|
29171
|
-
/** Drain the queue once; every failure is logged, never raised. */
|
|
29172
|
-
async runOnce() {
|
|
29173
|
-
let assignments;
|
|
29174
|
-
try {
|
|
29175
|
-
const result = await this.api.execute("getConnectorAssignments", { agentId: this.agentId });
|
|
29176
|
-
assignments = result.assignments;
|
|
29177
|
-
} catch (error) {
|
|
29178
|
-
this.log(`connector assignments unavailable: ${describe(error)}`);
|
|
29179
|
-
return;
|
|
29180
|
-
}
|
|
29181
|
-
for (const assignment of assignments) {
|
|
29182
|
-
const key = `${assignment.kind}:${assignment.connectorId}`;
|
|
29183
|
-
if (assignment.kind === "uninstall")
|
|
29184
|
-
continue;
|
|
29185
|
-
if (this.inFlight.has(key))
|
|
29186
|
-
continue;
|
|
29187
|
-
this.inFlight.add(key);
|
|
29188
|
-
void this.handle(assignment).catch((error) => this.log(`connector assignment ${key} failed: ${describe(error)}`)).finally(() => this.inFlight.delete(key));
|
|
29189
|
-
}
|
|
29190
|
-
}
|
|
29191
|
-
squire() {
|
|
29192
|
-
this.mcp ??= defaultSquireMcpClient({ agentId: this.agentId, roomId: "connector" });
|
|
29193
|
-
return this.mcp;
|
|
29194
|
-
}
|
|
29195
|
-
async handle(assignment) {
|
|
29196
|
-
const pairingGeneration = assignment.kind === "install" || assignment.kind === "uninstall" ? assignment.pairingGeneration : void 0;
|
|
29197
|
-
if (assignment.kind === "install") {
|
|
29198
|
-
if (assignment.connectorType?.startsWith("google-")) {
|
|
29199
|
-
await this.api.execute("postConnectorStatus", {
|
|
29200
|
-
agentId: this.agentId,
|
|
29201
|
-
connectorId: assignment.connectorId,
|
|
29202
|
-
steps: [{
|
|
29203
|
-
label: "Connect app",
|
|
29204
|
-
status: "failed",
|
|
29205
|
-
reason: "Reconnect through Connect an app"
|
|
29206
|
-
}],
|
|
29207
|
-
errorMessage: "Reconnect through Connect an app",
|
|
29208
|
-
...pairingGeneration !== void 0 ? { pairingGeneration } : {}
|
|
29209
|
-
});
|
|
29210
|
-
} else if (assignment.connectorType === "registry-mcp") {
|
|
29211
|
-
await this.runRegistryMcpInstall(assignment);
|
|
29212
|
-
} else if (assignment.connectorType === "tailscale") {
|
|
29213
|
-
await this.runTailscaleInstall(assignment.connectorId, pairingGeneration);
|
|
29214
|
-
} else {
|
|
29215
|
-
await this.runInstall(assignment.connectorId, pairingGeneration);
|
|
29216
|
-
}
|
|
29217
|
-
} else if (assignment.kind === "sync" && assignment.connectorType === "tailscale") {
|
|
29218
|
-
await this.runTailscaleInstall(assignment.connectorId);
|
|
29219
|
-
} else if (assignment.kind === "sync") {
|
|
29220
|
-
await this.runSync();
|
|
29221
|
-
} else if (assignment.kind === "refresh-google-grant") {
|
|
29222
|
-
this.log("retired Google grant assignment ignored; reconnect through Connect an app");
|
|
29223
|
-
} else if (assignment.kind === "revoke-grants")
|
|
29224
|
-
await this.runRevoke(assignment.connectorId, assignment.reference);
|
|
29225
|
-
}
|
|
29226
|
-
ceremonyKey(assignment) {
|
|
29227
|
-
return `${assignment.connectorId}:${assignment.pairingGeneration ?? 1}`;
|
|
29228
|
-
}
|
|
29229
|
-
async runRegistryMcpInstall(assignment) {
|
|
29230
|
-
const generation = assignment.pairingGeneration !== void 0 ? { pairingGeneration: assignment.pairingGeneration } : {};
|
|
29231
|
-
const ceremonyKey = this.ceremonyKey(assignment);
|
|
29232
|
-
const result = await this.installRegistry({
|
|
29233
|
-
api: this.api,
|
|
29234
|
-
agentId: this.agentId,
|
|
29235
|
-
assignment,
|
|
29236
|
-
home: this.registryHomeDir
|
|
29237
|
-
});
|
|
29238
|
-
const stopWatch = () => {
|
|
29239
|
-
};
|
|
29240
|
-
if (result.status === "connected") {
|
|
29241
|
-
stopWatch();
|
|
29242
|
-
this.registryCeremonies.delete(ceremonyKey);
|
|
29243
|
-
await this.api.execute("installConnector", {
|
|
29244
|
-
agentId: this.agentId,
|
|
29245
|
-
connectorId: assignment.connectorId,
|
|
29246
|
-
...generation
|
|
29247
|
-
});
|
|
29248
|
-
return;
|
|
29249
|
-
}
|
|
29250
|
-
if (result.status === "installing") {
|
|
29251
|
-
const ceremony = this.registryCeremonies.get(ceremonyKey);
|
|
29252
|
-
if (!ceremony || ceremony.attemptId !== result.attemptId) {
|
|
29253
|
-
this.registryCeremonies.set(ceremonyKey, {
|
|
29254
|
-
attemptId: result.attemptId,
|
|
29255
|
-
endsAt: result.attemptExpiresAt
|
|
29256
|
-
});
|
|
29257
|
-
} else if (ceremony.expired) {
|
|
29258
|
-
return;
|
|
29259
|
-
} else if (Date.now() >= ceremony.endsAt) {
|
|
29260
|
-
stopWatch();
|
|
29261
|
-
this.registryCeremonies.set(ceremonyKey, { ...ceremony, expired: true });
|
|
29262
|
-
await this.api.execute("postConnectorStatus", {
|
|
29263
|
-
agentId: this.agentId,
|
|
29264
|
-
connectorId: assignment.connectorId,
|
|
29265
|
-
steps: [
|
|
29266
|
-
{ label: "Connect provider account", status: "failed", reason: CEREMONY_EXPIRED }
|
|
29267
|
-
],
|
|
29268
|
-
signIn: null,
|
|
29269
|
-
errorMessage: CEREMONY_EXPIRED,
|
|
29270
|
-
...generation
|
|
29271
|
-
});
|
|
29272
|
-
return;
|
|
29273
|
-
}
|
|
29274
|
-
} else {
|
|
29275
|
-
this.registryCeremonies.delete(ceremonyKey);
|
|
29276
|
-
}
|
|
29277
|
-
await this.api.execute("postConnectorStatus", {
|
|
29278
|
-
agentId: this.agentId,
|
|
29279
|
-
connectorId: assignment.connectorId,
|
|
29280
|
-
steps: result.steps,
|
|
29281
|
-
...result.status === "installing" ? {
|
|
29282
|
-
signIn: {
|
|
29283
|
-
method: "oauth",
|
|
29284
|
-
url: result.authorizationUrl,
|
|
29285
|
-
attemptId: result.attemptId
|
|
29286
|
-
}
|
|
29287
|
-
} : { signIn: null, errorMessage: result.errorMessage },
|
|
29288
|
-
...generation
|
|
29289
|
-
});
|
|
29290
|
-
}
|
|
29291
|
-
/** Install Tailscale and publish its browser login URL until the tailnet is connected. */
|
|
29292
|
-
async runTailscaleInstall(connectorId, pairingGeneration) {
|
|
29293
|
-
const generation = pairingGeneration !== void 0 ? { pairingGeneration } : {};
|
|
29294
|
-
const report = async (steps2) => {
|
|
29295
|
-
try {
|
|
29296
|
-
await this.api.execute("postConnectorStatus", {
|
|
29297
|
-
agentId: this.agentId,
|
|
29298
|
-
connectorId,
|
|
29299
|
-
steps: steps2,
|
|
29300
|
-
...generation
|
|
29301
|
-
});
|
|
29302
|
-
} catch (error) {
|
|
29303
|
-
this.log(`step report failed: ${describe(error)}`);
|
|
29304
|
-
}
|
|
29305
|
-
};
|
|
29306
|
-
const existing = await this.connectorRow(connectorId);
|
|
29307
|
-
const result = await this.installTailscale({
|
|
29308
|
-
onProgress: report,
|
|
29309
|
-
...existing?.signIn ? { signIn: existing.signIn } : {}
|
|
29310
|
-
});
|
|
29311
|
-
if (result.status === "connected") {
|
|
29312
|
-
this.tailscaleWatch?.();
|
|
29313
|
-
this.tailscaleWatch = void 0;
|
|
29314
|
-
await this.api.execute("installConnector", {
|
|
29315
|
-
agentId: this.agentId,
|
|
29316
|
-
connectorId,
|
|
29317
|
-
...result.signedInAs ? { signedInAs: result.signedInAs } : {},
|
|
29318
|
-
...generation
|
|
29319
|
-
});
|
|
29320
|
-
return;
|
|
29321
|
-
}
|
|
29322
|
-
await this.api.execute("postConnectorStatus", {
|
|
29323
|
-
agentId: this.agentId,
|
|
29324
|
-
connectorId,
|
|
29325
|
-
steps: result.steps,
|
|
29326
|
-
signIn: result.status === "installing" ? result.signIn : null,
|
|
29327
|
-
...result.status === "error" ? { errorMessage: result.errorMessage } : {},
|
|
29328
|
-
...generation
|
|
29329
|
-
});
|
|
29330
|
-
if (result.status === "installing" && !this.tailscaleWatch)
|
|
29331
|
-
this.tailscaleWatch = this.watchTailscaleSignIn(() => {
|
|
29332
|
-
this.tailscaleWatch = void 0;
|
|
29333
|
-
if (!this.stopped)
|
|
29334
|
-
this.wake();
|
|
29335
|
-
});
|
|
29336
|
-
}
|
|
29337
|
-
/** Install Trusty Squire, reporting every step as it settles. */
|
|
29338
|
-
async runInstall(connectorId, pairingGeneration) {
|
|
29339
|
-
const generation = pairingGeneration !== void 0 ? { pairingGeneration } : {};
|
|
29340
|
-
const claim = squireConnectSession();
|
|
29341
|
-
const spent = claim ? Date.now() - claim.claimedAt >= CONNECT_TIMEOUT_MS : false;
|
|
29342
|
-
if (claim && !spent && isProcessAlive(claim.pid)) {
|
|
29343
|
-
if (!await this.rearmedByHuman(connectorId)) {
|
|
29344
|
-
this.log(`trusty-squire connect still waiting for sign-in (pid ${String(claim.pid)}); leaving it alone`);
|
|
29345
|
-
this.watchConnectSignIn();
|
|
29346
|
-
return;
|
|
29347
|
-
}
|
|
29348
|
-
this.log("trusty-squire re-pair requested; superseding the connect holding the browser");
|
|
29349
|
-
} else if (spent && (await this.connectorRow(connectorId))?.signIn) {
|
|
29350
|
-
releaseSquireConnectSession((message) => this.log(`[trusty-squire] ${message}`));
|
|
29351
|
-
await this.api.execute("postConnectorStatus", {
|
|
29352
|
-
agentId: this.agentId,
|
|
29353
|
-
connectorId,
|
|
29354
|
-
steps: [{ label: "waiting for sign-in", status: "failed", reason: CEREMONY_EXPIRED }],
|
|
29355
|
-
signIn: null,
|
|
29356
|
-
errorMessage: CEREMONY_EXPIRED,
|
|
29357
|
-
...generation
|
|
29358
|
-
});
|
|
29359
|
-
return;
|
|
29360
|
-
}
|
|
29361
|
-
const report = async (steps2) => {
|
|
29362
|
-
try {
|
|
29363
|
-
await this.api.execute("postConnectorStatus", {
|
|
29364
|
-
agentId: this.agentId,
|
|
29365
|
-
connectorId,
|
|
29366
|
-
steps: steps2,
|
|
29367
|
-
...generation
|
|
29368
|
-
});
|
|
29369
|
-
} catch (error) {
|
|
29370
|
-
this.log(`step report failed: ${describe(error)}`);
|
|
29371
|
-
}
|
|
29372
|
-
};
|
|
29373
|
-
const result = await this.install({
|
|
29374
|
-
workspaceId: this.agentId,
|
|
29375
|
-
mcp: this.squire(),
|
|
29376
|
-
onProgress: report,
|
|
29377
|
-
log: (message) => this.log(`[trusty-squire] ${message}`)
|
|
29378
|
-
});
|
|
29379
|
-
if (result.status === "error") {
|
|
29380
|
-
await this.api.execute("postConnectorStatus", {
|
|
29381
|
-
agentId: this.agentId,
|
|
29382
|
-
connectorId,
|
|
29383
|
-
steps: result.steps,
|
|
29384
|
-
signIn: null,
|
|
29385
|
-
errorMessage: result.errorMessage,
|
|
29386
|
-
...generation
|
|
29387
|
-
});
|
|
29388
|
-
return;
|
|
29389
|
-
}
|
|
29390
|
-
if (result.status === "connected") {
|
|
29391
|
-
await this.api.execute("installConnector", {
|
|
29392
|
-
agentId: this.agentId,
|
|
29393
|
-
connectorId,
|
|
29394
|
-
...result.squireVersion ? { squireVersion: result.squireVersion } : {},
|
|
29395
|
-
...generation
|
|
29396
|
-
});
|
|
29397
|
-
await this.reportVault(connectorId);
|
|
29398
|
-
return;
|
|
29399
|
-
}
|
|
29400
|
-
await this.api.execute("postConnectorStatus", {
|
|
29401
|
-
agentId: this.agentId,
|
|
29402
|
-
connectorId,
|
|
29403
|
-
steps: result.steps,
|
|
29404
|
-
signIn: result.signIn ?? null,
|
|
29405
|
-
...result.squireVersion ? { squireVersion: result.squireVersion } : {},
|
|
29406
|
-
...generation
|
|
29407
|
-
});
|
|
29408
|
-
this.watchConnectSignIn();
|
|
29409
|
-
}
|
|
29410
|
-
/** This connector's own row, or undefined when the server cannot answer. */
|
|
29411
|
-
async connectorRow(connectorId) {
|
|
29412
|
-
try {
|
|
29413
|
-
const status = await this.api.execute("getConnectorStatus", {
|
|
29414
|
-
agentId: this.agentId,
|
|
29415
|
-
connectorId
|
|
29416
|
-
});
|
|
29417
|
-
return status.connectorId === connectorId ? status : void 0;
|
|
29418
|
-
} catch (error) {
|
|
29419
|
-
this.log(`connector status unavailable: ${describe(error)}`);
|
|
29420
|
-
return void 0;
|
|
29421
|
-
}
|
|
29422
|
-
}
|
|
29423
|
-
/**
|
|
29424
|
-
* True when a human asked for this connector again while a connect of ours
|
|
29425
|
-
* still holds the browser. `pairConnector` re-arms the row to its default
|
|
29426
|
-
* all-pending steps, so a row whose every step is still pending is a fresh
|
|
29427
|
-
* request; the row carrying the ceremony this helper published has settled
|
|
29428
|
-
* ones. An unreadable row is not evidence of a retry.
|
|
29429
|
-
*/
|
|
29430
|
-
async rearmedByHuman(connectorId) {
|
|
29431
|
-
const status = await this.connectorRow(connectorId);
|
|
29432
|
-
if (!status)
|
|
29433
|
-
return false;
|
|
29434
|
-
return status.steps.length > 0 && status.steps.every((step3) => step3.status === "pending");
|
|
29435
|
-
}
|
|
29436
|
-
/** One vault report covers every live trusty-squire connector on this helper. */
|
|
29437
|
-
async runSync() {
|
|
29438
|
-
await this.reportVault();
|
|
29439
|
-
}
|
|
29440
|
-
async runRevoke(connectorId, reference) {
|
|
29441
|
-
const outcome = await this.revokeGrantsFn(this.squire(), reference);
|
|
29442
|
-
this.log(`revoked ${outcome.revoked} grant(s) on ${reference}` + (outcome.failed ? `, ${outcome.failed} failed` : ""));
|
|
29443
|
-
if (outcome.failed)
|
|
29444
|
-
return;
|
|
29445
|
-
await this.api.execute("revokeConnectionGrants", {
|
|
29446
|
-
agentId: this.agentId,
|
|
29447
|
-
ref: reference
|
|
29448
|
-
});
|
|
29449
|
-
void connectorId;
|
|
29450
|
-
}
|
|
29451
|
-
async reportVault(_connectorId) {
|
|
29452
|
-
const connections = await this.readVaultFn(this.squire());
|
|
29453
|
-
await this.api.execute("postConnectorVault", { agentId: this.agentId, connections });
|
|
29454
|
-
}
|
|
29455
|
-
};
|
|
29456
|
-
function describe(error) {
|
|
29457
|
-
return error instanceof Error ? error.message : String(error);
|
|
29458
|
-
}
|
|
29459
|
-
|
|
29460
|
-
// apps/body/dist/institutional-memory-shadow-worker.js
|
|
29461
|
-
import { mkdtemp as mkdtemp2, rm as rm5 } from "node:fs/promises";
|
|
29462
|
-
import { tmpdir as tmpdir3 } from "node:os";
|
|
29463
|
-
import { resolve as resolve12 } from "node:path";
|
|
29464
|
-
|
|
29465
|
-
// packages/api-contract/dist/daemon-operations.js
|
|
29466
|
-
function isAgentCommand(value) {
|
|
29467
|
-
if (!value || typeof value !== "object")
|
|
29468
|
-
return false;
|
|
29469
|
-
const c2 = value;
|
|
29470
|
-
if (![
|
|
29471
|
-
"id",
|
|
29472
|
-
"roomId",
|
|
29473
|
-
"agentId",
|
|
29474
|
-
"sourceMessageId",
|
|
29475
|
-
"turnRequestId",
|
|
29476
|
-
"rootCommandId",
|
|
29477
|
-
"rootSourceMessageId",
|
|
29478
|
-
"reason"
|
|
29479
|
-
].every((key) => typeof c2[key] === "string" && c2[key].length > 0))
|
|
29480
|
-
return false;
|
|
29481
|
-
if (!["input", "resume", "stop", "restart"].includes(String(c2.action)) || !Number.isInteger(c2.agentDepth) || Number(c2.agentDepth) < 0 || Number(c2.agentDepth) > 3)
|
|
29482
|
-
return false;
|
|
29483
|
-
const source = c2.source;
|
|
29484
|
-
return Boolean(source && typeof source.id === "string" && typeof source.authorId === "string" && typeof source.body === "string" && typeof source.createdAt === "number" && Array.isArray(source.attachments));
|
|
29485
|
-
}
|
|
29486
|
-
|
|
29487
|
-
// packages/api-contract/dist/artifacts.js
|
|
29488
|
-
var ARTIFACT_EXTENSIONS_BY_MIME = {
|
|
29489
|
-
"text/html": [".html", ".htm"],
|
|
29490
|
-
"image/svg+xml": [".svg"],
|
|
29491
|
-
"application/pdf": [".pdf"],
|
|
29492
|
-
"text/markdown": [".md"],
|
|
29493
|
-
"image/png": [".png"],
|
|
29494
|
-
"image/jpeg": [".jpg", ".jpeg"],
|
|
29495
|
-
"image/gif": [".gif"],
|
|
29496
|
-
"image/webp": [".webp"],
|
|
29497
|
-
"text/plain": [".txt", ".log"],
|
|
29498
|
-
"application/json": [".json"],
|
|
29499
|
-
"text/csv": [".csv"],
|
|
29500
|
-
"application/zip": [".zip"],
|
|
29501
|
-
"application/octet-stream": []
|
|
29502
|
-
};
|
|
29503
|
-
var ARTIFACT_MIME_BY_EXTENSION = Object.fromEntries(Object.entries(ARTIFACT_EXTENSIONS_BY_MIME).flatMap(([mime, extensions]) => extensions.map((extension2) => [extension2, mime])));
|
|
29504
|
-
var ARTIFACT_MAXIMUM_BYTES = 25 * 1024 * 1024;
|
|
29505
|
-
|
|
29506
|
-
// packages/api-contract/dist/daemon.js
|
|
29507
|
-
init_agent_access();
|
|
29508
|
-
|
|
29509
|
-
// packages/api-contract/dist/system-events.js
|
|
29510
|
-
var SERVER_EVENT_KINDS = [
|
|
29511
|
-
"joined",
|
|
29512
|
-
"schedule-ran",
|
|
29513
|
-
"corner-opened",
|
|
29514
|
-
"check-passed",
|
|
29515
|
-
"check-failed",
|
|
29516
|
-
"merged",
|
|
29517
|
-
"grant-decided",
|
|
29518
|
-
"connector-offer-decided",
|
|
29519
|
-
"turn-cancelled",
|
|
29520
|
-
"choice-answered",
|
|
29521
|
-
"choice-skipped",
|
|
29522
|
-
"poll-closed"
|
|
29523
|
-
];
|
|
29524
|
-
|
|
29525
|
-
// packages/api-contract/dist/turn-silence.js
|
|
29526
|
-
var HICCUP_BACKOFF_MS = [0, 5e3, 2e4];
|
|
29527
|
-
var TURN_SILENCE_KINDS = [
|
|
29528
|
-
"hiccup",
|
|
29529
|
-
"wrong-model",
|
|
29530
|
-
"allowance-spent",
|
|
29531
|
-
"not-signed-in",
|
|
29532
|
-
"workspace-failure",
|
|
29533
|
-
"helper-out-of-date",
|
|
29534
|
-
"update-interrupted",
|
|
29535
|
-
"offline"
|
|
29536
|
-
];
|
|
29537
|
-
var TURN_RECEIPT_REASON_KINDS = [
|
|
29538
|
-
"hiccup",
|
|
29539
|
-
"wrong-model",
|
|
29540
|
-
"allowance-spent",
|
|
29541
|
-
"not-signed-in",
|
|
29542
|
-
"workspace-failure",
|
|
29543
|
-
"helper-out-of-date",
|
|
29544
|
-
"update-interrupted",
|
|
29545
|
-
"offline",
|
|
29546
|
-
"model-selection-unavailable"
|
|
29547
|
-
];
|
|
29548
|
-
function isTurnReceiptReasonKind(value) {
|
|
29549
|
-
return typeof value === "string" && TURN_RECEIPT_REASON_KINDS.includes(value);
|
|
29550
|
-
}
|
|
29551
|
-
function receiptKindToSilenceKind(kind) {
|
|
29552
|
-
if (kind === "model-selection-unavailable" || kind === "wrong-model")
|
|
29553
|
-
return "wrong-model";
|
|
29554
|
-
if (kind && TURN_SILENCE_KINDS.includes(kind))
|
|
29555
|
-
return kind;
|
|
29556
|
-
return "hiccup";
|
|
29557
|
-
}
|
|
29558
|
-
var ALLOWANCE_UNTIL = /(?:try again at|until|resets?(?: at)?|available(?: again)?(?: at)?)\s+([A-Z][a-z]{2,9}\s+\d{1,2}(?:st|nd|rd|th)?,?\s+\d{4}(?:\s+\d{1,2}:\d{2}(?:\s*[AP]M)?)?)/i;
|
|
29559
|
-
var REPO_FROM_URL = /github\.com[:/]([^/\s]+\/[^/\s.]+?)(?:\.git)?(?:[/\s]|$)/i;
|
|
29560
|
-
var REPO_FROM_SLUG = /\b([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)\b/;
|
|
29561
|
-
function firstMatch(value, pattern) {
|
|
29562
|
-
const match = value.match(pattern);
|
|
29563
|
-
const captured = match?.[1]?.trim();
|
|
29564
|
-
return captured || void 0;
|
|
29565
|
-
}
|
|
29566
|
-
function classifyTurnSilence(reason, reasonKind) {
|
|
29567
|
-
if (isTurnReceiptReasonKind(reasonKind)) {
|
|
29568
|
-
const kind = receiptKindToSilenceKind(reasonKind);
|
|
29569
|
-
if (kind === "hiccup") {
|
|
29570
|
-
return { kind, fault: (reason ?? "").trim() || "the turn stalled" };
|
|
29571
|
-
}
|
|
29572
|
-
return {
|
|
29573
|
-
kind,
|
|
29574
|
-
...kind === "allowance-spent" ? { allowanceUntil: firstMatch(reason ?? "", ALLOWANCE_UNTIL) } : {},
|
|
29575
|
-
...kind === "workspace-failure" ? { repo: repoFromReason(reason ?? "") } : {}
|
|
29576
|
-
};
|
|
29577
|
-
}
|
|
29578
|
-
const text2 = (reason ?? "").trim();
|
|
29579
|
-
if (!text2)
|
|
29580
|
-
return { kind: "hiccup", fault: "the turn stalled" };
|
|
29581
|
-
if (/model selection unavailable/i.test(text2) || /isn't available/i.test(text2) || /not advertised/i.test(text2)) {
|
|
29582
|
-
return { kind: "wrong-model" };
|
|
29583
|
-
}
|
|
29584
|
-
if (/\b402\b/.test(text2) || /usage limit/i.test(text2) || /more credits/i.test(text2) || /quota/i.test(text2) || /allowance is spent/i.test(text2)) {
|
|
29585
|
-
return {
|
|
29586
|
-
kind: "allowance-spent",
|
|
29587
|
-
allowanceUntil: firstMatch(text2, ALLOWANCE_UNTIL)
|
|
29588
|
-
};
|
|
29589
|
-
}
|
|
29590
|
-
if (/authentication required/i.test(text2) || /not signed in/i.test(text2) || /isn't signed in/i.test(text2) || /invalid api[_ -]?key/i.test(text2) || /\b401\b/.test(text2)) {
|
|
29591
|
-
return { kind: "not-signed-in" };
|
|
29592
|
-
}
|
|
29593
|
-
if (/command protocol/i.test(text2) || /refusing intake/i.test(text2) || /helper is out of date/i.test(text2)) {
|
|
29594
|
-
return { kind: "helper-out-of-date" };
|
|
29595
|
-
}
|
|
29596
|
-
if (/working copy/i.test(text2) || /could not (?:clone|fetch|checkout)/i.test(text2) || /repository not found/i.test(text2) || /could not resolve host/i.test(text2) || /failed to start corner/i.test(text2) || /unable to access/i.test(text2) || /\bgit clone\b/i.test(text2) || /repository state is not verified/i.test(text2) || /incomplete repository binding/i.test(text2) || /no authoritative objective fact/i.test(text2) || /profile_busy/i.test(text2) || /broker unavailable/i.test(text2)) {
|
|
29597
|
-
return { kind: "workspace-failure", repo: repoFromReason(text2) };
|
|
29598
|
-
}
|
|
29599
|
-
if (/helper isn't running/i.test(text2) || /helper is offline/i.test(text2)) {
|
|
29600
|
-
return { kind: "offline" };
|
|
29601
|
-
}
|
|
29602
|
-
const fault = text2 || "the turn stalled";
|
|
29603
|
-
return { kind: "hiccup", fault };
|
|
29604
|
-
}
|
|
29605
|
-
function repoFromReason(text2) {
|
|
29606
|
-
return firstMatch(text2, REPO_FROM_URL) ?? firstMatch(text2, REPO_FROM_SLUG) ?? "the repository";
|
|
29607
|
-
}
|
|
29608
|
-
function isStandingWorkspaceConfigurationFault(text2) {
|
|
29609
|
-
return /repository state is not verified/i.test(text2) || /incomplete repository binding/i.test(text2) || /no authoritative objective fact/i.test(text2);
|
|
29610
|
-
}
|
|
29611
|
-
function hiccupBackoffMs(attempt) {
|
|
29612
|
-
const index = Math.max(1, attempt) - 1;
|
|
29613
|
-
return HICCUP_BACKOFF_MS[Math.min(index, HICCUP_BACKOFF_MS.length - 1)] ?? 0;
|
|
29614
|
-
}
|
|
29615
|
-
|
|
29616
|
-
// packages/api-contract/dist/institutional-memory.js
|
|
29617
|
-
var INSTITUTIONAL_MEMORY_PROPOSAL_VERSION = 1;
|
|
29618
|
-
var INSTITUTIONAL_MEMORY_BODY_MAX_BYTES = 200;
|
|
29619
|
-
var INSTITUTIONAL_MEMORY_KEYWORDS_MIN = 1;
|
|
29620
|
-
var INSTITUTIONAL_MEMORY_KEYWORDS_MAX = 6;
|
|
29621
|
-
var INSTITUTIONAL_MEMORY_KEYWORD_PATTERN = /^[a-z0-9][a-z0-9_./-]{2,31}$/;
|
|
29622
|
-
var INSTITUTIONAL_MEMORY_STOPWORDS = /* @__PURE__ */ new Set([
|
|
29623
|
-
"the",
|
|
29624
|
-
"and",
|
|
29625
|
-
"you",
|
|
29626
|
-
"your",
|
|
29627
|
-
"for",
|
|
29628
|
-
"with",
|
|
29629
|
-
"that",
|
|
29630
|
-
"this",
|
|
29631
|
-
"are",
|
|
29632
|
-
"was",
|
|
29633
|
-
"were",
|
|
29634
|
-
"but",
|
|
29635
|
-
"not",
|
|
29636
|
-
"have",
|
|
29637
|
-
"has",
|
|
29638
|
-
"had",
|
|
29639
|
-
"can",
|
|
29640
|
-
"all",
|
|
29641
|
-
"any",
|
|
29642
|
-
"our",
|
|
29643
|
-
"out",
|
|
29644
|
-
"use",
|
|
29645
|
-
"get",
|
|
29646
|
-
"got",
|
|
29647
|
-
"how",
|
|
29648
|
-
"what",
|
|
29649
|
-
"when",
|
|
29650
|
-
"who",
|
|
29651
|
-
"why",
|
|
29652
|
-
"will",
|
|
29653
|
-
"just",
|
|
29654
|
-
"from",
|
|
29655
|
-
"they",
|
|
29656
|
-
"them",
|
|
29657
|
-
"then",
|
|
29658
|
-
"than",
|
|
29659
|
-
"there",
|
|
29660
|
-
"here",
|
|
29661
|
-
"about",
|
|
29662
|
-
"into",
|
|
29663
|
-
"also",
|
|
29664
|
-
"its",
|
|
29665
|
-
"it's",
|
|
29666
|
-
"please",
|
|
29667
|
-
"should",
|
|
29668
|
-
"would",
|
|
29669
|
-
"could",
|
|
29670
|
-
"some",
|
|
29671
|
-
"more",
|
|
29672
|
-
"most",
|
|
29673
|
-
"very",
|
|
29674
|
-
"only",
|
|
29675
|
-
"one",
|
|
29676
|
-
"now",
|
|
29677
|
-
"yes",
|
|
29678
|
-
"okay",
|
|
29679
|
-
"let",
|
|
29680
|
-
"make",
|
|
29681
|
-
"want",
|
|
29682
|
-
"need",
|
|
29683
|
-
"does",
|
|
29684
|
-
"did",
|
|
29685
|
-
"done",
|
|
29686
|
-
"like",
|
|
29687
|
-
"know",
|
|
29688
|
-
"think",
|
|
29689
|
-
"see",
|
|
29690
|
-
"look",
|
|
29691
|
-
"thing",
|
|
29692
|
-
"things",
|
|
29693
|
-
"way"
|
|
29694
|
-
]);
|
|
29695
|
-
var INSTITUTIONAL_STANDING_PREFERENCE_KEY = "standing";
|
|
29696
|
-
var INSTITUTIONAL_MEMORY_CANONICAL_KEY_MAX_LENGTH = 160;
|
|
29697
|
-
var INSTITUTIONAL_MEMORY_RATIONALE_MAX_LENGTH = 500;
|
|
29698
|
-
var INSTITUTIONAL_MEMORY_SOURCE_MESSAGE_MAX = 16;
|
|
29699
|
-
var INSTITUTIONAL_MEMORY_JOB_ERROR_MAX_LENGTH = 1e3;
|
|
29700
|
-
var WORKSPACE_SKILL_DESCRIPTION_MAX_LENGTH = 60;
|
|
29701
|
-
var WORKSPACE_SKILL_MARKDOWN_MAX_BYTES = 32 * 1024;
|
|
29702
|
-
var WORKSPACE_SKILL_SLUG_MAX_LENGTH = 64;
|
|
29703
|
-
var INSTITUTIONAL_REVIEW_FINDING_MAX = 20;
|
|
29704
|
-
var INSTITUTIONAL_CURATOR_ACTION_MAX = 50;
|
|
29705
|
-
function record3(value, label) {
|
|
29706
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
29707
|
-
throw new Error(`${label} must be an object`);
|
|
29708
|
-
}
|
|
29709
|
-
return value;
|
|
29710
|
-
}
|
|
29711
|
-
function exactKeys(value, allowed, label) {
|
|
29712
|
-
const unknown = Object.keys(value).find((key) => !allowed.includes(key));
|
|
29713
|
-
if (unknown)
|
|
29714
|
-
throw new Error(`${label} has unknown field ${unknown}`);
|
|
29715
|
-
}
|
|
29716
|
-
function omitted(value) {
|
|
29717
|
-
return value === void 0 || value === null;
|
|
29718
|
-
}
|
|
29719
|
-
function boundedText(value, label, maximum, bytes = false) {
|
|
29720
|
-
if (typeof value !== "string" || value.includes("\0"))
|
|
29721
|
-
throw new Error(`${label} is invalid`);
|
|
29722
|
-
const normalized = value.trim();
|
|
29723
|
-
const size = bytes ? new TextEncoder().encode(normalized).length : normalized.length;
|
|
29724
|
-
if (!normalized || size > maximum)
|
|
29725
|
-
throw new Error(`${label} is invalid`);
|
|
29726
|
-
return normalized;
|
|
29727
|
-
}
|
|
29728
|
-
var FILLER_OPENINGS = /^(?:the user|user|this user|the requester|requester|it is|it's|note that|please|remember that|keep in mind)\b/i;
|
|
29729
|
-
var HEDGES = /\b(?:maybe|perhaps|probably|possibly|might|seems?|i think|apparently|likely)\b/i;
|
|
29730
|
-
function conciseInstitutionalMemoryBody(value) {
|
|
29731
|
-
const body = boundedText(value, `institutional memory body (at most ${INSTITUTIONAL_MEMORY_BODY_MAX_BYTES} bytes)`, INSTITUTIONAL_MEMORY_BODY_MAX_BYTES, true);
|
|
29732
|
-
if (FILLER_OPENINGS.test(body)) {
|
|
29733
|
-
throw new Error("institutional memory body must state the fact itself, without a filler opening");
|
|
29734
|
-
}
|
|
29735
|
-
if (/[.!?;]\s+\S/.test(body) || /\n/.test(body)) {
|
|
29736
|
-
throw new Error("institutional memory body must be one sentence");
|
|
29737
|
-
}
|
|
29738
|
-
if (HEDGES.test(body)) {
|
|
29739
|
-
throw new Error("institutional memory body must not hedge; save only what is known");
|
|
29740
|
-
}
|
|
29741
|
-
return body;
|
|
29742
|
-
}
|
|
29743
|
-
function institutionalMemoryKeywords(value) {
|
|
29744
|
-
if (!Array.isArray(value) || value.length < INSTITUTIONAL_MEMORY_KEYWORDS_MIN || value.length > INSTITUTIONAL_MEMORY_KEYWORDS_MAX) {
|
|
29745
|
-
throw new Error(`institutional memory needs ${INSTITUTIONAL_MEMORY_KEYWORDS_MIN} to ${INSTITUTIONAL_MEMORY_KEYWORDS_MAX} keywords`);
|
|
29746
|
-
}
|
|
29747
|
-
const keywords = value.map((keyword) => typeof keyword === "string" ? keyword.trim().toLocaleLowerCase("en-US") : "");
|
|
29748
|
-
if (keywords.some((keyword) => !INSTITUTIONAL_MEMORY_KEYWORD_PATTERN.test(keyword) || INSTITUTIONAL_MEMORY_STOPWORDS.has(keyword))) {
|
|
29749
|
-
throw new Error("institutional memory keywords are distinctive single lower-case words of 3 to 32 letters, digits, or _./-");
|
|
29750
|
-
}
|
|
29751
|
-
if (new Set(keywords).size !== keywords.length) {
|
|
29752
|
-
throw new Error("institutional memory keywords must be unique");
|
|
29753
|
-
}
|
|
29754
|
-
return keywords;
|
|
29755
|
-
}
|
|
29756
|
-
function parseInstitutionalMemoryProposal(value) {
|
|
29757
|
-
const proposal = record3(value, "institutional memory proposal");
|
|
29758
|
-
exactKeys(proposal, [
|
|
29759
|
-
"proposalVersion",
|
|
29760
|
-
"candidateType",
|
|
29761
|
-
"memoryKind",
|
|
29762
|
-
"subjectIdentityId",
|
|
29763
|
-
"canonicalKey",
|
|
29764
|
-
"body",
|
|
29765
|
-
"keywords",
|
|
29766
|
-
"source",
|
|
29767
|
-
"audience",
|
|
29768
|
-
"confidence",
|
|
29769
|
-
"classification",
|
|
29770
|
-
"cas"
|
|
29771
|
-
], "institutional memory proposal");
|
|
29772
|
-
if (proposal.proposalVersion !== INSTITUTIONAL_MEMORY_PROPOSAL_VERSION) {
|
|
29773
|
-
throw new Error("institutional memory proposal version is unsupported");
|
|
29774
|
-
}
|
|
29775
|
-
if (proposal.candidateType !== "correction_candidate" && proposal.candidateType !== "fact_candidate" && proposal.candidateType !== "preference_candidate") {
|
|
29776
|
-
throw new Error("institutional memory candidate type is invalid");
|
|
29777
|
-
}
|
|
29778
|
-
if (proposal.memoryKind !== "workspace_fact" && proposal.memoryKind !== "human_profile_fact") {
|
|
29779
|
-
throw new Error("institutional memory kind is invalid");
|
|
29780
|
-
}
|
|
29781
|
-
if (proposal.audience !== "workspace" && proposal.audience !== "human_profile") {
|
|
29782
|
-
throw new Error("institutional memory audience is invalid");
|
|
29783
|
-
}
|
|
29784
|
-
if (typeof proposal.confidence !== "number" || !Number.isFinite(proposal.confidence) || proposal.confidence < 0 || proposal.confidence > 1) {
|
|
29785
|
-
throw new Error("institutional memory confidence is invalid");
|
|
29786
|
-
}
|
|
29787
|
-
const source = record3(proposal.source, "institutional memory source");
|
|
29788
|
-
exactKeys(source, ["roomId", "messageIds"], "institutional memory source");
|
|
29789
|
-
const roomId = boundedText(source.roomId, "institutional memory source room", 200);
|
|
29790
|
-
if (!Array.isArray(source.messageIds) || source.messageIds.length === 0 || source.messageIds.length > INSTITUTIONAL_MEMORY_SOURCE_MESSAGE_MAX) {
|
|
29791
|
-
throw new Error("institutional memory source messages are invalid");
|
|
29792
|
-
}
|
|
29793
|
-
const messageIds = source.messageIds.map((messageId) => boundedText(messageId, "institutional memory source message", 200));
|
|
29794
|
-
if (new Set(messageIds).size !== messageIds.length) {
|
|
29795
|
-
throw new Error("institutional memory source messages must be unique");
|
|
29796
|
-
}
|
|
29797
|
-
const classification = record3(proposal.classification, "institutional memory classification");
|
|
29798
|
-
exactKeys(classification, ["stillTrueForAnotherRequester", "subjectIsRequester", "rationale"], "institutional memory classification");
|
|
29799
|
-
if (classification.stillTrueForAnotherRequester !== void 0 && typeof classification.stillTrueForAnotherRequester !== "boolean") {
|
|
29800
|
-
throw new Error("institutional memory classification test is invalid");
|
|
29801
|
-
}
|
|
29802
|
-
if (classification.subjectIsRequester !== void 0 && typeof classification.subjectIsRequester !== "boolean") {
|
|
29803
|
-
throw new Error("institutional memory subject classification is invalid");
|
|
29804
|
-
}
|
|
29805
|
-
const canonicalKey = boundedText(proposal.canonicalKey, "institutional memory canonical key", INSTITUTIONAL_MEMORY_CANONICAL_KEY_MAX_LENGTH);
|
|
29806
|
-
if (canonicalKey === INSTITUTIONAL_STANDING_PREFERENCE_KEY) {
|
|
29807
|
-
throw new Error("the standing preference key is reserved for owner-confirmed preferences");
|
|
29803
|
+
readVaultFn;
|
|
29804
|
+
revokeGrantsFn;
|
|
29805
|
+
/** Armed only while this helper owns a live sign-in ceremony. */
|
|
29806
|
+
connectWatch;
|
|
29807
|
+
started = false;
|
|
29808
|
+
stopped = false;
|
|
29809
|
+
/** One install at a time per connector; concurrent wakes skip it. */
|
|
29810
|
+
inFlight = /* @__PURE__ */ new Set();
|
|
29811
|
+
mcp;
|
|
29812
|
+
constructor(options) {
|
|
29813
|
+
this.agentId = options.agentId;
|
|
29814
|
+
this.api = options.api;
|
|
29815
|
+
this.log = options.log ?? (() => {
|
|
29816
|
+
});
|
|
29817
|
+
this.install = options.install ?? installSquire;
|
|
29818
|
+
this.installTailscale = options.installTailscale ?? installTailscale;
|
|
29819
|
+
this.watchTailscaleSignIn = options.watchTailscaleSignIn ?? watchTailscaleSignIn;
|
|
29820
|
+
this.registryHomeDir = options.registryHome ?? process.env.HOME ?? process.cwd();
|
|
29821
|
+
this.installRegistry = options.installRegistry ?? installRegistryMcp;
|
|
29822
|
+
this.readVaultFn = options.readVault ?? readVault;
|
|
29823
|
+
this.revokeGrantsFn = options.revokeGrants ?? revokeGrants;
|
|
29808
29824
|
}
|
|
29809
|
-
|
|
29810
|
-
|
|
29811
|
-
|
|
29812
|
-
|
|
29813
|
-
|
|
29825
|
+
start() {
|
|
29826
|
+
if (this.stopped || this.started)
|
|
29827
|
+
return;
|
|
29828
|
+
this.started = true;
|
|
29829
|
+
void this.runOnce();
|
|
29814
29830
|
}
|
|
29815
|
-
|
|
29816
|
-
|
|
29817
|
-
|
|
29818
|
-
|
|
29831
|
+
/** Event-driven drain, also called when the socket reconnects. */
|
|
29832
|
+
wake() {
|
|
29833
|
+
if (this.stopped)
|
|
29834
|
+
return;
|
|
29835
|
+
void this.runOnce();
|
|
29819
29836
|
}
|
|
29820
|
-
|
|
29821
|
-
|
|
29837
|
+
stop() {
|
|
29838
|
+
this.stopped = true;
|
|
29839
|
+
this.connectWatch?.();
|
|
29840
|
+
this.connectWatch = void 0;
|
|
29841
|
+
this.tailscaleWatch?.();
|
|
29842
|
+
this.tailscaleWatch = void 0;
|
|
29822
29843
|
}
|
|
29823
|
-
|
|
29824
|
-
|
|
29825
|
-
|
|
29844
|
+
/**
|
|
29845
|
+
* Watch the sign-in this helper is holding open. The phone paints
|
|
29846
|
+
* `installing` for the whole ceremony and only a drain that reaches
|
|
29847
|
+
* Squire's already-connected short-circuit flips the row to `connected`;
|
|
29848
|
+
* nothing on the wire announces that the human finished, so the connect
|
|
29849
|
+
* process exiting is the signal. Drain on that, and the row settles on the
|
|
29850
|
+
* process exit event without waiting for a server read timer.
|
|
29851
|
+
*/
|
|
29852
|
+
watchConnectSignIn() {
|
|
29853
|
+
if (this.stopped || this.connectWatch)
|
|
29854
|
+
return;
|
|
29855
|
+
const claim = squireConnectSession();
|
|
29856
|
+
this.connectWatch = claim?.onExit?.(() => {
|
|
29857
|
+
this.connectWatch = void 0;
|
|
29858
|
+
if (!this.stopped)
|
|
29859
|
+
void this.runOnce();
|
|
29860
|
+
});
|
|
29826
29861
|
}
|
|
29827
|
-
|
|
29828
|
-
|
|
29829
|
-
|
|
29830
|
-
|
|
29831
|
-
|
|
29832
|
-
|
|
29833
|
-
|
|
29834
|
-
|
|
29835
|
-
|
|
29836
|
-
|
|
29837
|
-
|
|
29838
|
-
|
|
29839
|
-
|
|
29840
|
-
|
|
29841
|
-
|
|
29842
|
-
|
|
29843
|
-
|
|
29844
|
-
}
|
|
29845
|
-
rationale
|
|
29846
|
-
},
|
|
29847
|
-
cas: {
|
|
29848
|
-
baseVersion: cas.baseVersion,
|
|
29849
|
-
...supersedesItemId ? { supersedesItemId } : {}
|
|
29862
|
+
/** Drain the queue once; every failure is logged, never raised. */
|
|
29863
|
+
async runOnce() {
|
|
29864
|
+
let assignments;
|
|
29865
|
+
try {
|
|
29866
|
+
const result = await this.api.execute("getConnectorAssignments", { agentId: this.agentId });
|
|
29867
|
+
assignments = result.assignments;
|
|
29868
|
+
} catch (error) {
|
|
29869
|
+
this.log(`connector assignments unavailable: ${describe(error)}`);
|
|
29870
|
+
return;
|
|
29871
|
+
}
|
|
29872
|
+
for (const assignment of assignments) {
|
|
29873
|
+
const key = `${assignment.kind}:${assignment.connectorId}`;
|
|
29874
|
+
if (assignment.kind === "uninstall")
|
|
29875
|
+
continue;
|
|
29876
|
+
if (this.inFlight.has(key))
|
|
29877
|
+
continue;
|
|
29878
|
+
this.inFlight.add(key);
|
|
29879
|
+
void this.handle(assignment).catch((error) => this.log(`connector assignment ${key} failed: ${describe(error)}`)).finally(() => this.inFlight.delete(key));
|
|
29850
29880
|
}
|
|
29851
|
-
};
|
|
29852
|
-
}
|
|
29853
|
-
function repositoryRelativePath(value) {
|
|
29854
|
-
if (typeof value !== "string" || value.length === 0 || value.length > 500)
|
|
29855
|
-
return void 0;
|
|
29856
|
-
if (value.startsWith("/") || value.includes("\\") || value.split("/").some((segment) => segment === ".." || segment === "")) {
|
|
29857
|
-
return void 0;
|
|
29858
29881
|
}
|
|
29859
|
-
|
|
29860
|
-
}
|
|
29861
|
-
|
|
29862
|
-
return value === void 0 ? {} : { [key]: value };
|
|
29863
|
-
}
|
|
29864
|
-
function parseInstitutionalMergeReviewProposal(value) {
|
|
29865
|
-
const proposal = record3(value, "institutional merge review proposal");
|
|
29866
|
-
exactKeys(proposal, ["proposalVersion", "skill", "findings"], "institutional merge review proposal");
|
|
29867
|
-
if (proposal.proposalVersion !== 1) {
|
|
29868
|
-
throw new Error("institutional merge review proposal version is unsupported");
|
|
29882
|
+
squire() {
|
|
29883
|
+
this.mcp ??= defaultSquireMcpClient({ agentId: this.agentId, roomId: "connector" });
|
|
29884
|
+
return this.mcp;
|
|
29869
29885
|
}
|
|
29870
|
-
|
|
29871
|
-
|
|
29872
|
-
|
|
29873
|
-
|
|
29874
|
-
|
|
29875
|
-
|
|
29876
|
-
|
|
29877
|
-
|
|
29878
|
-
|
|
29879
|
-
|
|
29880
|
-
|
|
29881
|
-
|
|
29882
|
-
|
|
29883
|
-
|
|
29884
|
-
|
|
29885
|
-
|
|
29886
|
-
|
|
29887
|
-
|
|
29888
|
-
|
|
29889
|
-
|
|
29890
|
-
|
|
29891
|
-
...optionalAnchorField("path", repositoryRelativePath(anchor.path))
|
|
29886
|
+
async handle(assignment) {
|
|
29887
|
+
const pairingGeneration = assignment.kind === "install" || assignment.kind === "uninstall" ? assignment.pairingGeneration : void 0;
|
|
29888
|
+
if (assignment.kind === "install") {
|
|
29889
|
+
if (assignment.connectorType?.startsWith("google-")) {
|
|
29890
|
+
await this.api.execute("postConnectorStatus", {
|
|
29891
|
+
agentId: this.agentId,
|
|
29892
|
+
connectorId: assignment.connectorId,
|
|
29893
|
+
steps: [{
|
|
29894
|
+
label: "Connect app",
|
|
29895
|
+
status: "failed",
|
|
29896
|
+
reason: "Reconnect through Connect an app"
|
|
29897
|
+
}],
|
|
29898
|
+
errorMessage: "Reconnect through Connect an app",
|
|
29899
|
+
...pairingGeneration !== void 0 ? { pairingGeneration } : {}
|
|
29900
|
+
});
|
|
29901
|
+
} else if (assignment.connectorType === "registry-mcp") {
|
|
29902
|
+
await this.runRegistryMcpInstall(assignment);
|
|
29903
|
+
} else if (assignment.connectorType === "tailscale") {
|
|
29904
|
+
await this.runTailscaleInstall(assignment.connectorId, pairingGeneration);
|
|
29905
|
+
} else {
|
|
29906
|
+
await this.runInstall(assignment.connectorId, pairingGeneration, assignment.forceReloginProvider);
|
|
29892
29907
|
}
|
|
29893
|
-
}
|
|
29908
|
+
} else if (assignment.kind === "sync" && assignment.connectorType === "tailscale") {
|
|
29909
|
+
await this.runTailscaleInstall(assignment.connectorId);
|
|
29910
|
+
} else if (assignment.kind === "sync") {
|
|
29911
|
+
await this.runSync();
|
|
29912
|
+
} else if (assignment.kind === "refresh-google-grant") {
|
|
29913
|
+
this.log("retired Google grant assignment ignored; reconnect through Connect an app");
|
|
29914
|
+
} else if (assignment.kind === "revoke-grants")
|
|
29915
|
+
await this.runRevoke(assignment.connectorId, assignment.reference);
|
|
29894
29916
|
}
|
|
29895
|
-
|
|
29896
|
-
|
|
29917
|
+
ceremonyKey(assignment) {
|
|
29918
|
+
return `${assignment.connectorId}:${assignment.pairingGeneration ?? 1}`;
|
|
29897
29919
|
}
|
|
29898
|
-
|
|
29899
|
-
const
|
|
29900
|
-
|
|
29901
|
-
|
|
29902
|
-
|
|
29903
|
-
|
|
29904
|
-
|
|
29905
|
-
|
|
29906
|
-
|
|
29907
|
-
|
|
29908
|
-
return {
|
|
29909
|
-
taxonomy: boundedText(finding.taxonomy, "institutional review finding taxonomy", 120),
|
|
29910
|
-
summary: boundedText(finding.summary, "institutional review finding summary", 1e3),
|
|
29911
|
-
severity,
|
|
29912
|
-
confidence: finding.confidence,
|
|
29913
|
-
...omitted(finding.path) ? {} : { path: boundedText(finding.path, "institutional review finding path", 500) }
|
|
29920
|
+
async runRegistryMcpInstall(assignment) {
|
|
29921
|
+
const generation = assignment.pairingGeneration !== void 0 ? { pairingGeneration: assignment.pairingGeneration } : {};
|
|
29922
|
+
const ceremonyKey = this.ceremonyKey(assignment);
|
|
29923
|
+
const result = await this.installRegistry({
|
|
29924
|
+
api: this.api,
|
|
29925
|
+
agentId: this.agentId,
|
|
29926
|
+
assignment,
|
|
29927
|
+
home: this.registryHomeDir
|
|
29928
|
+
});
|
|
29929
|
+
const stopWatch = () => {
|
|
29914
29930
|
};
|
|
29915
|
-
|
|
29916
|
-
|
|
29917
|
-
|
|
29918
|
-
|
|
29919
|
-
|
|
29920
|
-
|
|
29921
|
-
|
|
29922
|
-
|
|
29923
|
-
|
|
29924
|
-
const partition = boundedText(proposal.partition, "institutional curator partition", 300);
|
|
29925
|
-
if (!Array.isArray(proposal.actions) || proposal.actions.length > INSTITUTIONAL_CURATOR_ACTION_MAX) {
|
|
29926
|
-
throw new Error("institutional curator actions are invalid");
|
|
29927
|
-
}
|
|
29928
|
-
const actions = proposal.actions.map((value2) => {
|
|
29929
|
-
const action = record3(value2, "institutional curator action");
|
|
29930
|
-
exactKeys(action, [
|
|
29931
|
-
"action",
|
|
29932
|
-
"targetType",
|
|
29933
|
-
"targetId",
|
|
29934
|
-
"baseVersion",
|
|
29935
|
-
"duplicateIds",
|
|
29936
|
-
"body",
|
|
29937
|
-
"description",
|
|
29938
|
-
"markdown",
|
|
29939
|
-
"rationale"
|
|
29940
|
-
], "institutional curator action");
|
|
29941
|
-
if (action.action !== "retain" && action.action !== "stale" && action.action !== "archive" && action.action !== "consolidate") {
|
|
29942
|
-
throw new Error("institutional curator action kind is invalid");
|
|
29943
|
-
}
|
|
29944
|
-
if (action.targetType !== "memory_item" && action.targetType !== "workspace_skill") {
|
|
29945
|
-
throw new Error("institutional curator target type is invalid");
|
|
29931
|
+
if (result.status === "connected") {
|
|
29932
|
+
stopWatch();
|
|
29933
|
+
this.registryCeremonies.delete(ceremonyKey);
|
|
29934
|
+
await this.api.execute("installConnector", {
|
|
29935
|
+
agentId: this.agentId,
|
|
29936
|
+
connectorId: assignment.connectorId,
|
|
29937
|
+
...generation
|
|
29938
|
+
});
|
|
29939
|
+
return;
|
|
29946
29940
|
}
|
|
29947
|
-
if (
|
|
29948
|
-
|
|
29941
|
+
if (result.status === "installing") {
|
|
29942
|
+
const ceremony = this.registryCeremonies.get(ceremonyKey);
|
|
29943
|
+
if (!ceremony || ceremony.attemptId !== result.attemptId) {
|
|
29944
|
+
this.registryCeremonies.set(ceremonyKey, {
|
|
29945
|
+
attemptId: result.attemptId,
|
|
29946
|
+
endsAt: result.attemptExpiresAt
|
|
29947
|
+
});
|
|
29948
|
+
} else if (ceremony.expired) {
|
|
29949
|
+
return;
|
|
29950
|
+
} else if (Date.now() >= ceremony.endsAt) {
|
|
29951
|
+
stopWatch();
|
|
29952
|
+
this.registryCeremonies.set(ceremonyKey, { ...ceremony, expired: true });
|
|
29953
|
+
await this.api.execute("postConnectorStatus", {
|
|
29954
|
+
agentId: this.agentId,
|
|
29955
|
+
connectorId: assignment.connectorId,
|
|
29956
|
+
steps: [
|
|
29957
|
+
{ label: "Connect provider account", status: "failed", reason: CEREMONY_EXPIRED }
|
|
29958
|
+
],
|
|
29959
|
+
signIn: null,
|
|
29960
|
+
errorMessage: CEREMONY_EXPIRED,
|
|
29961
|
+
...generation
|
|
29962
|
+
});
|
|
29963
|
+
return;
|
|
29964
|
+
}
|
|
29965
|
+
} else {
|
|
29966
|
+
this.registryCeremonies.delete(ceremonyKey);
|
|
29949
29967
|
}
|
|
29950
|
-
|
|
29951
|
-
|
|
29968
|
+
await this.api.execute("postConnectorStatus", {
|
|
29969
|
+
agentId: this.agentId,
|
|
29970
|
+
connectorId: assignment.connectorId,
|
|
29971
|
+
steps: result.steps,
|
|
29972
|
+
...result.status === "installing" ? {
|
|
29973
|
+
signIn: {
|
|
29974
|
+
method: "oauth",
|
|
29975
|
+
url: result.authorizationUrl,
|
|
29976
|
+
attemptId: result.attemptId
|
|
29977
|
+
}
|
|
29978
|
+
} : { signIn: null, errorMessage: result.errorMessage },
|
|
29979
|
+
...generation
|
|
29980
|
+
});
|
|
29981
|
+
}
|
|
29982
|
+
/** Install Tailscale and publish its browser login URL until the tailnet is connected. */
|
|
29983
|
+
async runTailscaleInstall(connectorId, pairingGeneration) {
|
|
29984
|
+
const generation = pairingGeneration !== void 0 ? { pairingGeneration } : {};
|
|
29985
|
+
const report = async (steps2) => {
|
|
29986
|
+
try {
|
|
29987
|
+
await this.api.execute("postConnectorStatus", {
|
|
29988
|
+
agentId: this.agentId,
|
|
29989
|
+
connectorId,
|
|
29990
|
+
steps: steps2,
|
|
29991
|
+
...generation
|
|
29992
|
+
});
|
|
29993
|
+
} catch (error) {
|
|
29994
|
+
this.log(`step report failed: ${describe(error)}`);
|
|
29995
|
+
}
|
|
29996
|
+
};
|
|
29997
|
+
const existing = await this.connectorRow(connectorId);
|
|
29998
|
+
const result = await this.installTailscale({
|
|
29999
|
+
onProgress: report,
|
|
30000
|
+
...existing?.signIn ? { signIn: existing.signIn } : {}
|
|
30001
|
+
});
|
|
30002
|
+
if (result.status === "connected") {
|
|
30003
|
+
this.tailscaleWatch?.();
|
|
30004
|
+
this.tailscaleWatch = void 0;
|
|
30005
|
+
await this.api.execute("installConnector", {
|
|
30006
|
+
agentId: this.agentId,
|
|
30007
|
+
connectorId,
|
|
30008
|
+
...result.signedInAs ? { signedInAs: result.signedInAs } : {},
|
|
30009
|
+
...generation
|
|
30010
|
+
});
|
|
30011
|
+
return;
|
|
29952
30012
|
}
|
|
29953
|
-
|
|
29954
|
-
|
|
30013
|
+
await this.api.execute("postConnectorStatus", {
|
|
30014
|
+
agentId: this.agentId,
|
|
30015
|
+
connectorId,
|
|
30016
|
+
steps: result.steps,
|
|
30017
|
+
signIn: result.status === "installing" ? result.signIn : null,
|
|
30018
|
+
...result.status === "error" ? { errorMessage: result.errorMessage } : {},
|
|
30019
|
+
...generation
|
|
30020
|
+
});
|
|
30021
|
+
if (result.status === "installing" && !this.tailscaleWatch)
|
|
30022
|
+
this.tailscaleWatch = this.watchTailscaleSignIn(() => {
|
|
30023
|
+
this.tailscaleWatch = void 0;
|
|
30024
|
+
if (!this.stopped)
|
|
30025
|
+
this.wake();
|
|
30026
|
+
});
|
|
30027
|
+
}
|
|
30028
|
+
/** Install Trusty Squire, reporting every step as it settles.
|
|
30029
|
+
* `forceReloginProvider` is set only for a login-wall reconnect. */
|
|
30030
|
+
async runInstall(connectorId, pairingGeneration, forceReloginProvider) {
|
|
30031
|
+
const generation = pairingGeneration !== void 0 ? { pairingGeneration } : {};
|
|
30032
|
+
const claim = squireConnectSession();
|
|
30033
|
+
const spent = claim ? Date.now() - claim.claimedAt >= CONNECT_TIMEOUT_MS : false;
|
|
30034
|
+
if (claim && !spent && isProcessAlive(claim.pid)) {
|
|
30035
|
+
if (!await this.rearmedByHuman(connectorId)) {
|
|
30036
|
+
this.log(`trusty-squire connect still waiting for sign-in (pid ${String(claim.pid)}); leaving it alone`);
|
|
30037
|
+
this.watchConnectSignIn();
|
|
30038
|
+
return;
|
|
30039
|
+
}
|
|
30040
|
+
this.log("trusty-squire re-pair requested; superseding the connect holding the browser");
|
|
30041
|
+
} else if (spent && (await this.connectorRow(connectorId))?.signIn) {
|
|
30042
|
+
releaseSquireConnectSession((message) => this.log(`[trusty-squire] ${message}`));
|
|
30043
|
+
await this.api.execute("postConnectorStatus", {
|
|
30044
|
+
agentId: this.agentId,
|
|
30045
|
+
connectorId,
|
|
30046
|
+
steps: [{ label: "waiting for sign-in", status: "failed", reason: CEREMONY_EXPIRED }],
|
|
30047
|
+
signIn: null,
|
|
30048
|
+
errorMessage: CEREMONY_EXPIRED,
|
|
30049
|
+
...generation
|
|
30050
|
+
});
|
|
30051
|
+
return;
|
|
29955
30052
|
}
|
|
29956
|
-
|
|
29957
|
-
|
|
30053
|
+
const report = async (steps2) => {
|
|
30054
|
+
try {
|
|
30055
|
+
await this.api.execute("postConnectorStatus", {
|
|
30056
|
+
agentId: this.agentId,
|
|
30057
|
+
connectorId,
|
|
30058
|
+
steps: steps2,
|
|
30059
|
+
...generation
|
|
30060
|
+
});
|
|
30061
|
+
} catch (error) {
|
|
30062
|
+
this.log(`step report failed: ${describe(error)}`);
|
|
30063
|
+
}
|
|
30064
|
+
};
|
|
30065
|
+
const result = await this.install({
|
|
30066
|
+
workspaceId: this.agentId,
|
|
30067
|
+
mcp: this.squire(),
|
|
30068
|
+
onProgress: report,
|
|
30069
|
+
log: (message) => this.log(`[trusty-squire] ${message}`),
|
|
30070
|
+
...forceReloginProvider ? { forceReloginProvider } : {}
|
|
30071
|
+
});
|
|
30072
|
+
if (result.status === "error") {
|
|
30073
|
+
await this.api.execute("postConnectorStatus", {
|
|
30074
|
+
agentId: this.agentId,
|
|
30075
|
+
connectorId,
|
|
30076
|
+
steps: result.steps,
|
|
30077
|
+
signIn: null,
|
|
30078
|
+
errorMessage: result.errorMessage,
|
|
30079
|
+
...generation
|
|
30080
|
+
});
|
|
30081
|
+
return;
|
|
29958
30082
|
}
|
|
29959
|
-
|
|
29960
|
-
|
|
29961
|
-
|
|
29962
|
-
|
|
29963
|
-
|
|
30083
|
+
if (result.status === "connected") {
|
|
30084
|
+
await this.api.execute("installConnector", {
|
|
30085
|
+
agentId: this.agentId,
|
|
30086
|
+
connectorId,
|
|
30087
|
+
...result.squireVersion ? { squireVersion: result.squireVersion } : {},
|
|
30088
|
+
...generation
|
|
30089
|
+
});
|
|
30090
|
+
await this.reportVault(connectorId);
|
|
30091
|
+
return;
|
|
29964
30092
|
}
|
|
29965
|
-
|
|
29966
|
-
|
|
30093
|
+
await this.api.execute("postConnectorStatus", {
|
|
30094
|
+
agentId: this.agentId,
|
|
30095
|
+
connectorId,
|
|
30096
|
+
steps: result.steps,
|
|
30097
|
+
signIn: result.signIn ?? null,
|
|
30098
|
+
...result.squireVersion ? { squireVersion: result.squireVersion } : {},
|
|
30099
|
+
...generation
|
|
30100
|
+
});
|
|
30101
|
+
this.watchConnectSignIn();
|
|
30102
|
+
}
|
|
30103
|
+
/** This connector's own row, or undefined when the server cannot answer. */
|
|
30104
|
+
async connectorRow(connectorId) {
|
|
30105
|
+
try {
|
|
30106
|
+
const status = await this.api.execute("getConnectorStatus", {
|
|
30107
|
+
agentId: this.agentId,
|
|
30108
|
+
connectorId
|
|
30109
|
+
});
|
|
30110
|
+
return status.connectorId === connectorId ? status : void 0;
|
|
30111
|
+
} catch (error) {
|
|
30112
|
+
this.log(`connector status unavailable: ${describe(error)}`);
|
|
30113
|
+
return void 0;
|
|
29967
30114
|
}
|
|
29968
|
-
|
|
29969
|
-
|
|
29970
|
-
|
|
29971
|
-
|
|
29972
|
-
|
|
29973
|
-
|
|
29974
|
-
|
|
29975
|
-
|
|
29976
|
-
|
|
29977
|
-
|
|
29978
|
-
|
|
29979
|
-
|
|
29980
|
-
|
|
30115
|
+
}
|
|
30116
|
+
/**
|
|
30117
|
+
* True when a human asked for this connector again while a connect of ours
|
|
30118
|
+
* still holds the browser. `pairConnector` re-arms the row to its default
|
|
30119
|
+
* all-pending steps, so a row whose every step is still pending is a fresh
|
|
30120
|
+
* request; the row carrying the ceremony this helper published has settled
|
|
30121
|
+
* ones. An unreadable row is not evidence of a retry.
|
|
30122
|
+
*/
|
|
30123
|
+
async rearmedByHuman(connectorId) {
|
|
30124
|
+
const status = await this.connectorRow(connectorId);
|
|
30125
|
+
if (!status)
|
|
30126
|
+
return false;
|
|
30127
|
+
return status.steps.length > 0 && status.steps.every((step3) => step3.status === "pending");
|
|
30128
|
+
}
|
|
30129
|
+
/** One vault report covers every live trusty-squire connector on this helper. */
|
|
30130
|
+
async runSync() {
|
|
30131
|
+
await this.reportVault();
|
|
30132
|
+
}
|
|
30133
|
+
async runRevoke(connectorId, reference) {
|
|
30134
|
+
const outcome = await this.revokeGrantsFn(this.squire(), reference);
|
|
30135
|
+
this.log(`revoked ${outcome.revoked} grant(s) on ${reference}` + (outcome.failed ? `, ${outcome.failed} failed` : ""));
|
|
30136
|
+
if (outcome.failed)
|
|
30137
|
+
return;
|
|
30138
|
+
await this.api.execute("revokeConnectionGrants", {
|
|
30139
|
+
agentId: this.agentId,
|
|
30140
|
+
ref: reference
|
|
30141
|
+
});
|
|
30142
|
+
void connectorId;
|
|
30143
|
+
}
|
|
30144
|
+
async reportVault(_connectorId) {
|
|
30145
|
+
const connections = await this.readVaultFn(this.squire());
|
|
30146
|
+
await this.api.execute("postConnectorVault", { agentId: this.agentId, connections });
|
|
30147
|
+
}
|
|
30148
|
+
};
|
|
30149
|
+
function describe(error) {
|
|
30150
|
+
return error instanceof Error ? error.message : String(error);
|
|
29981
30151
|
}
|
|
29982
30152
|
|
|
30153
|
+
// apps/body/dist/institutional-memory-shadow-worker.js
|
|
30154
|
+
import { mkdtemp as mkdtemp2, rm as rm5 } from "node:fs/promises";
|
|
30155
|
+
import { tmpdir as tmpdir3 } from "node:os";
|
|
30156
|
+
import { resolve as resolve12 } from "node:path";
|
|
30157
|
+
|
|
29983
30158
|
// apps/body/dist/institutional-context.js
|
|
30159
|
+
import { performance as performance2 } from "node:perf_hooks";
|
|
29984
30160
|
var INSTITUTIONAL_CONTEXT_TIMEOUT_MS = 200;
|
|
29985
30161
|
var INSTITUTIONAL_MEMORY_LIVE_FLAG = "BEELINE_INSTITUTIONAL_MEMORY_ENABLED";
|
|
29986
30162
|
function institutionalMemoryFlagEnabled(env, flag) {
|
|
@@ -29993,21 +30169,34 @@ var EMPTY_INSTITUTIONAL_CONTEXT = {
|
|
|
29993
30169
|
totalBytes: 0,
|
|
29994
30170
|
omitted: {}
|
|
29995
30171
|
};
|
|
29996
|
-
|
|
29997
|
-
|
|
29998
|
-
|
|
30172
|
+
var INSTITUTIONAL_CONTEXT_MISSED_TEXT = "institutional memory did not load this turn; use search_memory before concluding anything is not stored.";
|
|
30173
|
+
function startInstitutionalContextFetch(api, roomId, enabled = institutionalMemoryFlagEnabled(process.env, INSTITUTIONAL_MEMORY_LIVE_FLAG), now2 = () => performance2.now()) {
|
|
30174
|
+
const startedAt = now2();
|
|
30175
|
+
const promise = enabled ? api.execute("getInstitutionalContext", { roomId }) : Promise.resolve(EMPTY_INSTITUTIONAL_CONTEXT);
|
|
30176
|
+
promise.catch(() => {
|
|
30177
|
+
});
|
|
30178
|
+
return { promise, startedAt };
|
|
30179
|
+
}
|
|
30180
|
+
async function awaitInstitutionalContext(fetch2, log2 = console.warn, budgetMs = INSTITUTIONAL_CONTEXT_TIMEOUT_MS, now2 = () => performance2.now()) {
|
|
30181
|
+
const remainingMs = budgetMs - (now2() - fetch2.startedAt);
|
|
29999
30182
|
let timer;
|
|
30000
30183
|
try {
|
|
30001
|
-
|
|
30002
|
-
|
|
30184
|
+
const snapshot = await Promise.race([
|
|
30185
|
+
fetch2.promise,
|
|
30003
30186
|
new Promise((_, reject) => {
|
|
30004
|
-
timer = setTimeout(() => reject(new Error("institutional context timed out")),
|
|
30187
|
+
timer = setTimeout(() => reject(new Error("institutional context timed out")), Math.max(0, remainingMs));
|
|
30005
30188
|
timer.unref?.();
|
|
30006
30189
|
})
|
|
30007
30190
|
]);
|
|
30191
|
+
const served = snapshot.text !== "" || snapshot.standingPreference !== void 0;
|
|
30192
|
+
return { ...snapshot, outcome: served ? "served" : "empty" };
|
|
30008
30193
|
} catch (error) {
|
|
30009
30194
|
log2(`institutional context unavailable: ${error instanceof Error ? error.message : String(error)}`);
|
|
30010
|
-
return
|
|
30195
|
+
return {
|
|
30196
|
+
...EMPTY_INSTITUTIONAL_CONTEXT,
|
|
30197
|
+
text: INSTITUTIONAL_CONTEXT_MISSED_TEXT,
|
|
30198
|
+
outcome: "timed-out"
|
|
30199
|
+
};
|
|
30011
30200
|
} finally {
|
|
30012
30201
|
if (timer)
|
|
30013
30202
|
clearTimeout(timer);
|
|
@@ -30927,7 +31116,7 @@ import { execFile as execFile12 } from "node:child_process";
|
|
|
30927
31116
|
import { createHash as createHash10 } from "node:crypto";
|
|
30928
31117
|
import { existsSync as existsSync8, mkdirSync as mkdirSync3 } from "node:fs";
|
|
30929
31118
|
import { cp, mkdir as mkdir20, readdir as readdir8, realpath as realpath2, rm as rm9 } from "node:fs/promises";
|
|
30930
|
-
import { dirname as
|
|
31119
|
+
import { dirname as dirname19, relative as relative3, resolve as resolve29, sep as sep2 } from "node:path";
|
|
30931
31120
|
import { promisify as promisify8 } from "node:util";
|
|
30932
31121
|
|
|
30933
31122
|
// apps/body/dist/grant-runner.js
|
|
@@ -30935,7 +31124,7 @@ import { execFile as execFile8 } from "node:child_process";
|
|
|
30935
31124
|
import { createHash as createHash6, randomBytes as randomBytes7 } from "node:crypto";
|
|
30936
31125
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
30937
31126
|
import { createServer as createServer3 } from "node:http";
|
|
30938
|
-
import { dirname as
|
|
31127
|
+
import { dirname as dirname12, resolve as resolve16 } from "node:path";
|
|
30939
31128
|
|
|
30940
31129
|
// packages/api-contract/dist/agent-grants.js
|
|
30941
31130
|
var AGENT_GRANT_KINDS = [
|
|
@@ -31182,9 +31371,9 @@ function surfaceAllows(surface, capability) {
|
|
|
31182
31371
|
init_agent_command();
|
|
31183
31372
|
init_cursor_acp_bridge();
|
|
31184
31373
|
import { execFile as execFile7, spawnSync } from "node:child_process";
|
|
31185
|
-
import { lstatSync as lstatSync2, readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
31374
|
+
import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
31186
31375
|
import { homedir as homedir11 } from "node:os";
|
|
31187
|
-
import { isAbsolute as isAbsolute2, relative, resolve as resolve14 } from "node:path";
|
|
31376
|
+
import { basename as basename4, dirname as dirname10, isAbsolute as isAbsolute2, relative, resolve as resolve14 } from "node:path";
|
|
31188
31377
|
var DEFAULT_SANDBOX_POLICY = "bwrap";
|
|
31189
31378
|
function isSandboxPolicy(value) {
|
|
31190
31379
|
return value === "bwrap" || value === "off";
|
|
@@ -31270,6 +31459,18 @@ function credentialMaskPaths(extraPaths, home = homedir11(), stat8 = (path) => {
|
|
|
31270
31459
|
}
|
|
31271
31460
|
return masks.sort((a2, b) => a2.path.localeCompare(b.path));
|
|
31272
31461
|
}
|
|
31462
|
+
function siblingAgentMaskPaths(ownRuntimeDir, listAgentDirs = (agentsRoot) => {
|
|
31463
|
+
try {
|
|
31464
|
+
return readdirSync2(agentsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
31465
|
+
} catch {
|
|
31466
|
+
return [];
|
|
31467
|
+
}
|
|
31468
|
+
}) {
|
|
31469
|
+
const own = resolve14(ownRuntimeDir);
|
|
31470
|
+
const agentsRoot = dirname10(own);
|
|
31471
|
+
const ownName = basename4(own).toLowerCase();
|
|
31472
|
+
return listAgentDirs(agentsRoot).filter((name) => name.toLowerCase() !== ownName).map((name) => ({ path: resolve14(agentsRoot, name), kind: "dir" })).sort((a2, b) => a2.path.localeCompare(b.path));
|
|
31473
|
+
}
|
|
31273
31474
|
function isUnderTmp(path) {
|
|
31274
31475
|
const rel = relative("/tmp", path);
|
|
31275
31476
|
return rel === "" || !rel.startsWith("..") && !isAbsolute2(rel);
|
|
@@ -31584,9 +31785,9 @@ async function ensureBwrapSandbox(options = {}) {
|
|
|
31584
31785
|
}
|
|
31585
31786
|
|
|
31586
31787
|
// apps/body/dist/provider-key-store.js
|
|
31587
|
-
import { chmod as
|
|
31788
|
+
import { chmod as chmod5, mkdir as mkdir8, readFile as readFile11, writeFile as writeFile8 } from "node:fs/promises";
|
|
31588
31789
|
import { homedir as homedir12 } from "node:os";
|
|
31589
|
-
import { dirname as
|
|
31790
|
+
import { dirname as dirname11, resolve as resolve15 } from "node:path";
|
|
31590
31791
|
var PROVIDER_KEY_ENV_VARS = {
|
|
31591
31792
|
openrouter: "OPENROUTER_API_KEY",
|
|
31592
31793
|
openai: "OPENAI_API_KEY",
|
|
@@ -31620,10 +31821,10 @@ async function readSavedProviderKey(provider, env = process.env) {
|
|
|
31620
31821
|
async function saveProviderKey(provider, key, env = process.env) {
|
|
31621
31822
|
const path = providerKeyStorePath(env);
|
|
31622
31823
|
const store = { ...await readProviderKeyStore(env), [provider]: key };
|
|
31623
|
-
await mkdir8(
|
|
31824
|
+
await mkdir8(dirname11(path), { recursive: true, mode: 448 });
|
|
31624
31825
|
await writeFile8(path, `${JSON.stringify(store, null, 2)}
|
|
31625
31826
|
`, { mode: 384 });
|
|
31626
|
-
await
|
|
31827
|
+
await chmod5(path, 384);
|
|
31627
31828
|
}
|
|
31628
31829
|
function providerKeyFromEnvironment(provider, env = process.env) {
|
|
31629
31830
|
const primary = env[PROVIDER_KEY_ENV_VARS[provider]]?.trim();
|
|
@@ -31658,7 +31859,7 @@ function operatorSecretResolver(env = process.env) {
|
|
|
31658
31859
|
if (saved)
|
|
31659
31860
|
return saved;
|
|
31660
31861
|
}
|
|
31661
|
-
const raw = await readFile12(resolve16(
|
|
31862
|
+
const raw = await readFile12(resolve16(dirname12(providerKeyStorePath(env)), "secrets.json"), "utf8").catch(() => void 0);
|
|
31662
31863
|
if (!raw)
|
|
31663
31864
|
return void 0;
|
|
31664
31865
|
try {
|
|
@@ -32230,7 +32431,7 @@ async function readHarnessTurnUsage(input) {
|
|
|
32230
32431
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
32231
32432
|
import { mkdir as mkdir9, writeFile as writeFile9 } from "node:fs/promises";
|
|
32232
32433
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
32233
|
-
import { dirname as
|
|
32434
|
+
import { dirname as dirname13, join as join8 } from "node:path";
|
|
32234
32435
|
var CommandExecutionContext = class {
|
|
32235
32436
|
generationId = randomUUID7();
|
|
32236
32437
|
path;
|
|
@@ -32240,7 +32441,7 @@ var CommandExecutionContext = class {
|
|
|
32240
32441
|
}
|
|
32241
32442
|
async enter(command) {
|
|
32242
32443
|
this.current = command;
|
|
32243
|
-
await mkdir9(
|
|
32444
|
+
await mkdir9(dirname13(this.path), { recursive: true });
|
|
32244
32445
|
await writeFile9(this.path, JSON.stringify({
|
|
32245
32446
|
roomId: command.roomId,
|
|
32246
32447
|
requestId: command.turnRequestId,
|
|
@@ -32337,6 +32538,9 @@ async function runServerCommandIntake(options) {
|
|
|
32337
32538
|
continue;
|
|
32338
32539
|
pending.delete(command.id);
|
|
32339
32540
|
claimed.add(command.id);
|
|
32541
|
+
const startingTurn = command.action !== "restart" && command.action !== "stop";
|
|
32542
|
+
if (startingTurn)
|
|
32543
|
+
options.onClaiming?.(command);
|
|
32340
32544
|
try {
|
|
32341
32545
|
await api.execute("claimAgentCommand", {
|
|
32342
32546
|
roomId,
|
|
@@ -32345,6 +32549,8 @@ async function runServerCommandIntake(options) {
|
|
|
32345
32549
|
});
|
|
32346
32550
|
} catch (error) {
|
|
32347
32551
|
claimed.delete(command.id);
|
|
32552
|
+
if (startingTurn)
|
|
32553
|
+
options.onClaimFailed?.(command);
|
|
32348
32554
|
options.onError?.(error);
|
|
32349
32555
|
continue;
|
|
32350
32556
|
}
|
|
@@ -32408,7 +32614,7 @@ import { execFile as execFile11 } from "node:child_process";
|
|
|
32408
32614
|
import { createHash as createHash9 } from "node:crypto";
|
|
32409
32615
|
import { mkdir as mkdir18, readFile as readFile19, writeFile as writeFile14 } from "node:fs/promises";
|
|
32410
32616
|
import { homedir as homedir14, hostname } from "node:os";
|
|
32411
|
-
import { dirname as
|
|
32617
|
+
import { dirname as dirname17, join as join13, resolve as resolve28 } from "node:path";
|
|
32412
32618
|
import { promisify as promisify7 } from "node:util";
|
|
32413
32619
|
|
|
32414
32620
|
// apps/body/dist/agent-home.js
|
|
@@ -33211,9 +33417,9 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
|
|
|
33211
33417
|
|
|
33212
33418
|
// apps/body/dist/agent-home.js
|
|
33213
33419
|
import { createHash as createHash7, randomUUID as randomUUID8 } from "node:crypto";
|
|
33214
|
-
import { chmod as
|
|
33420
|
+
import { chmod as chmod6, copyFile, lstat as lstat3, mkdir as mkdir11, readFile as readFile16, readlink, readdir as readdir5, realpath, rename as rename5, rm as rm6, symlink as symlink2, unlink as unlink5, writeFile as writeFile11 } from "node:fs/promises";
|
|
33215
33421
|
import { homedir as homedir13 } from "node:os";
|
|
33216
|
-
import { basename as
|
|
33422
|
+
import { basename as basename5, dirname as dirname14, join as join10, relative as relative2, resolve as resolve21, sep } from "node:path";
|
|
33217
33423
|
|
|
33218
33424
|
// apps/body/dist/draw-avatar-skill.js
|
|
33219
33425
|
var DRAW_AVATAR_SKILL_NAME = "draw-avatar";
|
|
@@ -34534,7 +34740,7 @@ async function repairRoomAgentCredentialLinks(input) {
|
|
|
34534
34740
|
if (!existsSync7(source))
|
|
34535
34741
|
continue;
|
|
34536
34742
|
const target = resolve21(root, credential.dir, credential.target);
|
|
34537
|
-
await mkdir11(
|
|
34743
|
+
await mkdir11(dirname14(target), { recursive: true, mode: 448 });
|
|
34538
34744
|
const stats = await lstat3(target).catch((error) => {
|
|
34539
34745
|
if (isMissingPathError(error))
|
|
34540
34746
|
return void 0;
|
|
@@ -34542,7 +34748,7 @@ async function repairRoomAgentCredentialLinks(input) {
|
|
|
34542
34748
|
});
|
|
34543
34749
|
if (stats?.isSymbolicLink()) {
|
|
34544
34750
|
const linked = await readlink(target);
|
|
34545
|
-
if (resolve21(
|
|
34751
|
+
if (resolve21(dirname14(target), linked) === source)
|
|
34546
34752
|
continue;
|
|
34547
34753
|
}
|
|
34548
34754
|
if (stats) {
|
|
@@ -34999,8 +35205,8 @@ function readJsonObject(path) {
|
|
|
34999
35205
|
}
|
|
35000
35206
|
}
|
|
35001
35207
|
async function provisionManagedSkillsDir(target, managedSkills, sharedSkills, optionalShares) {
|
|
35002
|
-
const parent =
|
|
35003
|
-
await assertRealContainedDirectory(parent,
|
|
35208
|
+
const parent = dirname14(target);
|
|
35209
|
+
await assertRealContainedDirectory(parent, dirname14(parent));
|
|
35004
35210
|
const plan = await planManagedSkills(managedSkills, sharedSkills, optionalShares);
|
|
35005
35211
|
if (await materializedSkillManifest(target) === plan.manifest)
|
|
35006
35212
|
return;
|
|
@@ -35221,7 +35427,7 @@ async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
|
|
|
35221
35427
|
const stats = await lstat3(resolvedSource);
|
|
35222
35428
|
if (stats.isSymbolicLink())
|
|
35223
35429
|
throw new Error(`shared skill contains a symlink: ${source}`);
|
|
35224
|
-
if (BLOCKED_SHARED_FILENAMES.test(
|
|
35430
|
+
if (BLOCKED_SHARED_FILENAMES.test(basename5(source))) {
|
|
35225
35431
|
throw new Error(`shared skill contains credential or configuration material: ${source}`);
|
|
35226
35432
|
}
|
|
35227
35433
|
if (stats.isDirectory()) {
|
|
@@ -35246,20 +35452,20 @@ async function copySafeSkillTree(source, target, sourceRoot) {
|
|
|
35246
35452
|
file: async (rel, realPath) => {
|
|
35247
35453
|
const destination = resolve21(target, rel);
|
|
35248
35454
|
await copyFile(realPath, destination);
|
|
35249
|
-
await
|
|
35455
|
+
await chmod6(destination, 384);
|
|
35250
35456
|
}
|
|
35251
35457
|
});
|
|
35252
35458
|
}
|
|
35253
35459
|
async function writeIsolatedHarnessFile(path, content) {
|
|
35254
|
-
const parent =
|
|
35460
|
+
const parent = dirname14(path);
|
|
35255
35461
|
const parentStats = await lstat3(parent);
|
|
35256
35462
|
if (!parentStats.isDirectory() || parentStats.isSymbolicLink()) {
|
|
35257
35463
|
throw new Error(`isolated harness parent is not a real directory: ${parent}`);
|
|
35258
35464
|
}
|
|
35259
|
-
const temporary = resolve21(parent, `.${
|
|
35465
|
+
const temporary = resolve21(parent, `.${basename5(path)}.${process.pid}.${randomUUID8()}.tmp`);
|
|
35260
35466
|
try {
|
|
35261
35467
|
await writeFile11(temporary, content, { mode: 384, flag: "wx" });
|
|
35262
|
-
await
|
|
35468
|
+
await chmod6(temporary, 384);
|
|
35263
35469
|
await rename5(temporary, path);
|
|
35264
35470
|
} finally {
|
|
35265
35471
|
await unlink5(temporary).catch(() => void 0);
|
|
@@ -35324,7 +35530,7 @@ function agentCommandCatalogPublisher(input) {
|
|
|
35324
35530
|
|
|
35325
35531
|
// apps/body/dist/attachment-delivery.js
|
|
35326
35532
|
import { mkdir as mkdir12, writeFile as writeFile12 } from "node:fs/promises";
|
|
35327
|
-
import { basename as
|
|
35533
|
+
import { basename as basename6, extname, join as join11 } from "node:path";
|
|
35328
35534
|
var MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;
|
|
35329
35535
|
var EXPIRED_REASON = "expired: these attachment bytes are past their retention window";
|
|
35330
35536
|
var FETCH_TIMEOUT_MS = 3e4;
|
|
@@ -35354,7 +35560,7 @@ async function fetchBoundedBytes(url, fetchImpl = fetch) {
|
|
|
35354
35560
|
}
|
|
35355
35561
|
var MAX_INLINE_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
35356
35562
|
function safeFileName(attachment, index, taken) {
|
|
35357
|
-
const raw =
|
|
35563
|
+
const raw = basename6(attachment.name ?? "").replace(/[^\w.-]+/g, "_").replace(/^\.+/, "");
|
|
35358
35564
|
let name = raw || `attachment-${index + 1}`;
|
|
35359
35565
|
if (taken.has(name)) {
|
|
35360
35566
|
const ext = extname(name);
|
|
@@ -35807,7 +36013,7 @@ function distillTurnFailureReason(error) {
|
|
|
35807
36013
|
const clean4 = redactToolDetail(stripped).trim();
|
|
35808
36014
|
const text2 = !clean4 ? "turn failed" : clean4.length > TURN_FAILURE_REASON_MAX ? `${clean4.slice(0, TURN_FAILURE_REASON_MAX - 1)}\u2026` : clean4;
|
|
35809
36015
|
const classified = classifyTurnSilence(redactToolDetail(informative.join(" ")).replace(/\s+/g, " ") || text2);
|
|
35810
|
-
const kind = classified.kind === "wrong-model" ? "model-selection-unavailable" : classified.kind;
|
|
36016
|
+
const kind = classified.kind === "wrong-model" ? "model-selection-unavailable" : classified.kind === "not-signed-in" ? "hiccup" : classified.kind;
|
|
35811
36017
|
return { text: text2, kind };
|
|
35812
36018
|
}
|
|
35813
36019
|
|
|
@@ -36379,14 +36585,14 @@ function readOnlyMcpServer(config, cwd, agentMemoryDir) {
|
|
|
36379
36585
|
// apps/body/dist/codegraph.js
|
|
36380
36586
|
import { execFile as execFile10 } from "node:child_process";
|
|
36381
36587
|
import { access as access2, appendFile, mkdir as mkdir14, readFile as readFile17 } from "node:fs/promises";
|
|
36382
|
-
import { dirname as
|
|
36588
|
+
import { dirname as dirname15, isAbsolute as isAbsolute3, resolve as resolve24 } from "node:path";
|
|
36383
36589
|
import { promisify as promisify6 } from "node:util";
|
|
36384
36590
|
var execFileAsync6 = promisify6(execFile10);
|
|
36385
36591
|
var CODEGRAPH_MCP_SERVER_NAME = "codegraph";
|
|
36386
36592
|
var CODEGRAPH_INDEX_PATH = ".codegraph/codegraph.db";
|
|
36387
36593
|
var CODEGRAPH_PREPARE_TIMEOUT_MS = 12e4;
|
|
36388
36594
|
function codegraphIndexDirectory(cwd) {
|
|
36389
|
-
return resolve24(cwd,
|
|
36595
|
+
return resolve24(cwd, dirname15(CODEGRAPH_INDEX_PATH));
|
|
36390
36596
|
}
|
|
36391
36597
|
function codegraphMcpServer(config, cwd, options) {
|
|
36392
36598
|
if (!config.codegraphCommand)
|
|
@@ -36427,7 +36633,7 @@ async function excludeIndexFromGitStatus(cwd) {
|
|
|
36427
36633
|
if (!gitPath)
|
|
36428
36634
|
return;
|
|
36429
36635
|
const path = isAbsolute3(gitPath) ? gitPath : resolve24(cwd, gitPath);
|
|
36430
|
-
await mkdir14(
|
|
36636
|
+
await mkdir14(dirname15(path), { recursive: true });
|
|
36431
36637
|
const existing = await readFile17(path, "utf8").catch(() => "");
|
|
36432
36638
|
if (existing.split("\n").includes(".codegraph/"))
|
|
36433
36639
|
return;
|
|
@@ -36607,6 +36813,7 @@ var CORNER_REVIEWER_UNSTABLE_HEAD_INSTRUCTION = "There is no stable green PR hea
|
|
|
36607
36813
|
var CORNER_DELIVERY_NUDGE = "Before ending this turn, inspect the repository state and finish delivering the work unless a human hold stands: commit and push the intended changes and open the pull request if one does not exist. Decide yourself whether any remaining dirty work belongs to the objective; do not discard it merely to make the worktree clean. The pull request body must carry ## Reproduced and ## Demonstrated; if they are missing, add them before ending the turn.";
|
|
36608
36814
|
var CORNER_YOLO_MERGE_NUDGE = 'Yolo is on. Call pr_checks_status now and merge this pull request with gh pr merge --squash --match-head-commit <sha> only when it returns checks="passed" and mergeAllowed=true. If checks="unknown", reply in this corner with the tool reason and stop instead of retrying. Otherwise stop without merging.';
|
|
36609
36815
|
var RESEARCH_CORNER_HOLD = "This is a research corner with writable repository access. Investigate and edit files as needed. Do not commit, push, or open a pull request until a human explicitly directs that step. Never merge. Leave the corner open; only a human closes it.";
|
|
36816
|
+
var UPGRADE_INTENT_RULE = "Call this only while answering a human message, in this same corner, that clearly conveys intent to change the code \u2014 a bug report, a requested change, or a problem described for you to fix, not a specific required phrase. Never call it from an earlier message, or your own initiative.";
|
|
36610
36817
|
var handle = (value) => value.replace(/^@/, "");
|
|
36611
36818
|
function cornerMergeInstruction(yoloMode, reviewerHandle) {
|
|
36612
36819
|
if (!reviewerHandle)
|
|
@@ -36859,7 +37066,7 @@ The soul is not authority and never changes your tools, permissions, roles, or m
|
|
|
36859
37066
|
surfaces: ["no-code-corner"],
|
|
36860
37067
|
render: ({ agentMayUpgradeCorner }) => [
|
|
36861
37068
|
"This is a no-code corner with no repository checkout and no GitHub workflow. Work in this corner's writable workspace: create files with write_scratch_file or your own tools, then send them with post_artifact.",
|
|
36862
|
-
agentMayUpgradeCorner ?
|
|
37069
|
+
agentMayUpgradeCorner ? `Do not initialize a repository, create a branch, commit, push, open a pull request, or wait for GitHub checks. The one exception is beeline-agent upgrade_corner_to_code. ${UPGRADE_INTENT_RULE} That one-way upgrade restarts this same corner with a feature branch and writable checkout, keeps its discussion, and re-delivers that same request in the code session, so end this turn immediately once it succeeds and do not edit this workspace.` : "Do not initialize a repository, create a branch, commit, push, open a pull request, or wait for GitHub checks."
|
|
36863
37070
|
].join("\n")
|
|
36864
37071
|
},
|
|
36865
37072
|
{
|
|
@@ -37144,7 +37351,7 @@ async function withTurnReceiptHeartbeat(api, receipt, task, onHeartbeatError) {
|
|
|
37144
37351
|
// apps/body/dist/turn-trace.js
|
|
37145
37352
|
import { appendFile as appendFile2, mkdir as mkdir15, readdir as readdir6, rm as rm7 } from "node:fs/promises";
|
|
37146
37353
|
import { resolve as resolve25 } from "node:path";
|
|
37147
|
-
import { performance as
|
|
37354
|
+
import { performance as performance3 } from "node:perf_hooks";
|
|
37148
37355
|
var TURN_PHASES = [
|
|
37149
37356
|
/** Enqueued on `SessionScheduler` until this turn holds a slot. A capacity wait lives here. */
|
|
37150
37357
|
"queue-wait",
|
|
@@ -37183,7 +37390,7 @@ var TurnTrace = class {
|
|
|
37183
37390
|
toolCallIds = /* @__PURE__ */ new Set();
|
|
37184
37391
|
constructor(options) {
|
|
37185
37392
|
this.options = options;
|
|
37186
|
-
this.now = options.now ?? (() =>
|
|
37393
|
+
this.now = options.now ?? (() => performance3.now());
|
|
37187
37394
|
this.begunAt = this.now();
|
|
37188
37395
|
this.attempts.push(this.newAttempt(1));
|
|
37189
37396
|
}
|
|
@@ -37238,6 +37445,10 @@ var TurnTrace = class {
|
|
|
37238
37445
|
noteActivation(kind) {
|
|
37239
37446
|
this.current.activation = kind;
|
|
37240
37447
|
}
|
|
37448
|
+
/** How this turn's institutional-memory snapshot fetch resolved (see the field's own doc). */
|
|
37449
|
+
noteInstitutionalMemory(outcome) {
|
|
37450
|
+
this.current.institutionalMemory = outcome;
|
|
37451
|
+
}
|
|
37241
37452
|
/** What each section of the assembled prompt cost, so growth shows in the trace. */
|
|
37242
37453
|
notePromptSections(report) {
|
|
37243
37454
|
this.promptSections = Object.fromEntries(report.map((entry) => [entry.id, entry.bytes]));
|
|
@@ -37335,6 +37546,7 @@ var TurnTrace = class {
|
|
|
37335
37546
|
...attempt.capacityWait ? { capacityWait: true } : {},
|
|
37336
37547
|
...attempt.provider ? { provider: attempt.provider } : {},
|
|
37337
37548
|
...attempt.retryReason ? { retryReason: attempt.retryReason } : {},
|
|
37549
|
+
...attempt.institutionalMemory ? { institutionalMemory: attempt.institutionalMemory } : {},
|
|
37338
37550
|
phases: Object.fromEntries(TURN_PHASES.filter((phase) => attempt.phases.has(phase)).map((phase) => [
|
|
37339
37551
|
phase,
|
|
37340
37552
|
round(attempt.phases.get(phase))
|
|
@@ -37379,6 +37591,8 @@ function formatTurnAttempt(attempt) {
|
|
|
37379
37591
|
parts.push("capacity-wait");
|
|
37380
37592
|
if (attempt.provider)
|
|
37381
37593
|
parts.push(`provider ${attempt.provider}`);
|
|
37594
|
+
if (attempt.institutionalMemory)
|
|
37595
|
+
parts.push(`memory ${attempt.institutionalMemory}`);
|
|
37382
37596
|
for (const phase of TURN_PHASES) {
|
|
37383
37597
|
const value = attempt.phases[phase];
|
|
37384
37598
|
if (value === void 0)
|
|
@@ -37440,7 +37654,7 @@ var TurnTraceFile = class {
|
|
|
37440
37654
|
};
|
|
37441
37655
|
|
|
37442
37656
|
// apps/body/dist/corner-github-auth.js
|
|
37443
|
-
import { chmod as
|
|
37657
|
+
import { chmod as chmod7, mkdir as mkdir16, writeFile as writeFile13 } from "node:fs/promises";
|
|
37444
37658
|
import { delimiter as delimiter2, resolve as resolve26 } from "node:path";
|
|
37445
37659
|
async function installCornerGitHubWrappers(input) {
|
|
37446
37660
|
const bin = resolve26(input.root, "beeline-github-bin");
|
|
@@ -37592,14 +37806,14 @@ if (result.error) throw result.error;
|
|
|
37592
37806
|
process.exit(result.status ?? 1);
|
|
37593
37807
|
`;
|
|
37594
37808
|
await writeFile13(path, source, { mode: 448 });
|
|
37595
|
-
await
|
|
37809
|
+
await chmod7(path, 448);
|
|
37596
37810
|
}
|
|
37597
37811
|
|
|
37598
37812
|
// apps/body/dist/warm-node-modules.js
|
|
37599
37813
|
import { createHash as createHash8, randomUUID as randomUUID9 } from "node:crypto";
|
|
37600
37814
|
import { constants as fsConstants3 } from "node:fs";
|
|
37601
|
-
import { chmod as
|
|
37602
|
-
import { dirname as
|
|
37815
|
+
import { chmod as chmod8, copyFile as copyFile2, link, lstat as lstat4, mkdir as mkdir17, readdir as readdir7, readFile as readFile18, readlink as readlink2, rename as rename6, rm as rm8, stat as stat6, symlink as symlink3, utimes } from "node:fs/promises";
|
|
37816
|
+
import { dirname as dirname16, join as join12, resolve as resolve27 } from "node:path";
|
|
37603
37817
|
var STORE_FORMAT = "v1";
|
|
37604
37818
|
var STAGING_PREFIX = ".beeline-warm-";
|
|
37605
37819
|
var STAGING_SWEEP_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -37684,7 +37898,7 @@ async function seedWarmNodeModules(input) {
|
|
|
37684
37898
|
}
|
|
37685
37899
|
for (const tree of plan.trees) {
|
|
37686
37900
|
const target = resolve27(input.worktreePath, tree);
|
|
37687
|
-
await mkdir17(
|
|
37901
|
+
await mkdir17(dirname16(target), { recursive: true });
|
|
37688
37902
|
await rename6(resolve27(staging, tree), target);
|
|
37689
37903
|
placed.push(target);
|
|
37690
37904
|
}
|
|
@@ -37834,7 +38048,7 @@ async function cloneTree(source, target, file, topLevel = true) {
|
|
|
37834
38048
|
var harvestFile = async (source, target) => {
|
|
37835
38049
|
await copyFile2(source, target, fsConstants3.COPYFILE_FICLONE);
|
|
37836
38050
|
const info = await stat6(source);
|
|
37837
|
-
await
|
|
38051
|
+
await chmod8(target, info.mode & 4095 & ~146);
|
|
37838
38052
|
};
|
|
37839
38053
|
var seedFile = async (source, target, topLevel) => {
|
|
37840
38054
|
if (!topLevel) {
|
|
@@ -37842,7 +38056,7 @@ var seedFile = async (source, target, topLevel) => {
|
|
|
37842
38056
|
return;
|
|
37843
38057
|
}
|
|
37844
38058
|
await copyFile2(source, target);
|
|
37845
|
-
await
|
|
38059
|
+
await chmod8(target, 420);
|
|
37846
38060
|
};
|
|
37847
38061
|
async function pruneWarmStore(storeRoot, keep) {
|
|
37848
38062
|
const names = (await readdir7(storeRoot).catch(() => [])).filter((name) => !name.startsWith(STAGING_PREFIX));
|
|
@@ -38403,7 +38617,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
38403
38617
|
}) ? { relay: await this.squireRelay.listen() } : {}
|
|
38404
38618
|
};
|
|
38405
38619
|
const resourceAuthFile = `${this.commandContext.path}.resource-auth.json`;
|
|
38406
|
-
await mkdir18(
|
|
38620
|
+
await mkdir18(dirname17(resourceAuthFile), { recursive: true, mode: 448 });
|
|
38407
38621
|
await writeFile14(resourceAuthFile, JSON.stringify({
|
|
38408
38622
|
...this.options.api.connection(),
|
|
38409
38623
|
turnContextPath: this.commandContext.path
|
|
@@ -38498,7 +38712,10 @@ var MonolithCornerTurnLoop = class {
|
|
|
38498
38712
|
cargoTargetDir,
|
|
38499
38713
|
...registryMcpHostBindPaths(configuration.registryMcpRoutes)
|
|
38500
38714
|
],
|
|
38501
|
-
maskPaths:
|
|
38715
|
+
maskPaths: [
|
|
38716
|
+
...credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome),
|
|
38717
|
+
...siblingAgentMaskPaths(runtimeDirectory(this.options.runtime.supervisorRoot, this.options.runtime.agent.publicKey))
|
|
38718
|
+
]
|
|
38502
38719
|
},
|
|
38503
38720
|
command,
|
|
38504
38721
|
args: agentArgs
|
|
@@ -38617,13 +38834,35 @@ var MonolithCornerTurnLoop = class {
|
|
|
38617
38834
|
this.sessionId = opened.sessionId;
|
|
38618
38835
|
this.sessionFingerprint = fingerprint;
|
|
38619
38836
|
this.sessionCodegraphReady = codegraphReady;
|
|
38837
|
+
let appliedModel;
|
|
38620
38838
|
if (selection) {
|
|
38621
38839
|
const options = filterAllowedModelConfigOptions(parseAdvertisedConfigOptions(opened.raw, selection.model));
|
|
38622
|
-
await applyAgentModelSelection(this.client, opened.sessionId, options, selection);
|
|
38840
|
+
const applied = await applyAgentModelSelection(this.client, opened.sessionId, options, selection);
|
|
38841
|
+
appliedModel = applied.appliedSelection.model;
|
|
38842
|
+
if (selection.model && appliedModel && appliedModel !== selection.model) {
|
|
38843
|
+
this.recordModelFallback(applied.appliedSelection, applied.options);
|
|
38844
|
+
}
|
|
38623
38845
|
}
|
|
38624
|
-
this.sessionModel = selection?.model ?? null;
|
|
38846
|
+
this.sessionModel = appliedModel ?? selection?.model ?? null;
|
|
38625
38847
|
return opened.sessionId;
|
|
38626
38848
|
}
|
|
38849
|
+
/**
|
|
38850
|
+
* A vanished model id was just substituted for a same-family replacement
|
|
38851
|
+
* (`resolveModelFamilyFallback`) so THIS turn could proceed instead of
|
|
38852
|
+
* failing it. Persist the correction so the phone stops offering the dead
|
|
38853
|
+
* id and the durable `model_unavailable` flag stays clear, and let the
|
|
38854
|
+
* server (`daemon-service.ts`'s `modelCatalog`) name the change in the
|
|
38855
|
+
* agent's DM — fire-and-forget: a slow or failed report must never hold up
|
|
38856
|
+
* or fail a turn that already succeeded with the fallback model applied.
|
|
38857
|
+
*/
|
|
38858
|
+
recordModelFallback(appliedSelection, options) {
|
|
38859
|
+
this.options.api.execute("postAgentModelCatalog", {
|
|
38860
|
+
agentId: this.agent.publicKey,
|
|
38861
|
+
workspaceId: this.options.workspaceId,
|
|
38862
|
+
options,
|
|
38863
|
+
selection: appliedSelection
|
|
38864
|
+
}).catch((error) => console.error(`[thin-core] failed to persist automatic model fallback for corner ${this.options.cornerId}:`, error));
|
|
38865
|
+
}
|
|
38627
38866
|
/**
|
|
38628
38867
|
* Resolve the review target at prompt time, not session activation time.
|
|
38629
38868
|
*
|
|
@@ -38769,6 +39008,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
38769
39008
|
} : void 0;
|
|
38770
39009
|
this.currentTurn = { requestId, ...requester ? { requester } : {} };
|
|
38771
39010
|
const trace = this.beginTurnTrace(requestId);
|
|
39011
|
+
const institutionalContextFetch = startInstitutionalContextFetch(api, cornerId);
|
|
38772
39012
|
let deliberateNoReply = false;
|
|
38773
39013
|
let laneUpgraded = false;
|
|
38774
39014
|
try {
|
|
@@ -38797,8 +39037,9 @@ var MonolithCornerTurnLoop = class {
|
|
|
38797
39037
|
this.roster(),
|
|
38798
39038
|
api.execute("getCornerRestoreState", { cornerId }),
|
|
38799
39039
|
this.activeReviewerInstruction(),
|
|
38800
|
-
|
|
39040
|
+
awaitInstitutionalContext(institutionalContextFetch, (message) => console.warn(`[thin-core] corner ${cornerId}: ${message}`))
|
|
38801
39041
|
]));
|
|
39042
|
+
trace.noteInstitutionalMemory(institutionalContext.outcome);
|
|
38802
39043
|
const briefAttachments = (restored.brief?.attachments ?? []).map((file) => ({
|
|
38803
39044
|
url: new URL(`/v1/media/${file.objectId}`, api.baseUrl).toString(),
|
|
38804
39045
|
name: file.title,
|
|
@@ -39240,6 +39481,17 @@ var MonolithCornerTurnLoop = class {
|
|
|
39240
39481
|
this.options.onIntakeError?.(error);
|
|
39241
39482
|
console.error("[thin-core] corner command failed", error);
|
|
39242
39483
|
},
|
|
39484
|
+
// See monolith-room-turn.ts (C112): mark busy the instant a claim
|
|
39485
|
+
// attempt starts, before its own network round trip and before
|
|
39486
|
+
// context.enter()'s own file I/O, so a reconcile busy-check landing
|
|
39487
|
+
// anywhere in that window can never see this corner as idle when a
|
|
39488
|
+
// turn was already claimed (or about to be).
|
|
39489
|
+
onClaiming: () => {
|
|
39490
|
+
this.busy = true;
|
|
39491
|
+
},
|
|
39492
|
+
onClaimFailed: () => {
|
|
39493
|
+
this.busy = false;
|
|
39494
|
+
},
|
|
39243
39495
|
onEnter: (command) => this.squireRelay.activate(command, this.commandContext.generationId),
|
|
39244
39496
|
onLeave: (command) => this.squireRelay.deactivate(command.turnRequestId),
|
|
39245
39497
|
stop: (requestId) => this.stopTurn(requestId),
|
|
@@ -39280,7 +39532,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
39280
39532
|
// apps/body/dist/monolith-room-turn.js
|
|
39281
39533
|
import { mkdir as mkdir19, writeFile as writeFile15 } from "node:fs/promises";
|
|
39282
39534
|
import { homedir as homedir15, hostname as hostname2 } from "node:os";
|
|
39283
|
-
import { dirname as
|
|
39535
|
+
import { dirname as dirname18, join as join15 } from "node:path";
|
|
39284
39536
|
|
|
39285
39537
|
// packages/api-contract/dist/scheduled-prompts.js
|
|
39286
39538
|
var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
|
|
@@ -39478,7 +39730,10 @@ var MonolithRoomTurnLoop = class {
|
|
|
39478
39730
|
...this.options.config.bwrapPath ? { bwrapPath: this.options.config.bwrapPath } : {},
|
|
39479
39731
|
...this.sessionScratchDir ? { scratch: this.sessionScratchDir } : {},
|
|
39480
39732
|
...this.sessionStateDirs.length ? { harnessStateDirs: this.sessionStateDirs } : {},
|
|
39481
|
-
maskPaths:
|
|
39733
|
+
maskPaths: [
|
|
39734
|
+
...credentialMaskPaths(this.options.config.sandboxMaskPaths, this.options.config.operatorHome ?? homedir15()),
|
|
39735
|
+
...siblingAgentMaskPaths(runtimeDirectory(this.options.runtime.supervisorRoot, this.options.runtime.agent.publicKey))
|
|
39736
|
+
]
|
|
39482
39737
|
};
|
|
39483
39738
|
}
|
|
39484
39739
|
/**
|
|
@@ -39728,7 +39983,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
39728
39983
|
}) ? { relay: await this.squireRelay.listen() } : {}
|
|
39729
39984
|
};
|
|
39730
39985
|
const resourceAuthFile = `${this.commandContext.path}.resource-auth.json`;
|
|
39731
|
-
await mkdir19(
|
|
39986
|
+
await mkdir19(dirname18(resourceAuthFile), { recursive: true, mode: 448 });
|
|
39732
39987
|
await writeFile15(resourceAuthFile, JSON.stringify({
|
|
39733
39988
|
...this.options.api.connection(),
|
|
39734
39989
|
turnContextPath: this.commandContext.path
|
|
@@ -39803,7 +40058,10 @@ var MonolithRoomTurnLoop = class {
|
|
|
39803
40058
|
...codegraphReady ? [codegraphIndexDirectory(this.options.cwd)] : [],
|
|
39804
40059
|
...registryMcpHostBindPaths(configuration.registryMcpRoutes)
|
|
39805
40060
|
],
|
|
39806
|
-
maskPaths:
|
|
40061
|
+
maskPaths: [
|
|
40062
|
+
...credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome),
|
|
40063
|
+
...siblingAgentMaskPaths(runtimeDirectory(this.options.runtime.supervisorRoot, this.options.runtime.agent.publicKey))
|
|
40064
|
+
]
|
|
39807
40065
|
},
|
|
39808
40066
|
command,
|
|
39809
40067
|
args: agentArgs
|
|
@@ -39909,10 +40167,30 @@ var MonolithRoomTurnLoop = class {
|
|
|
39909
40167
|
this.sessionCodegraphReady = codegraphReady;
|
|
39910
40168
|
if (selection) {
|
|
39911
40169
|
const options = filterAllowedModelConfigOptions(parseAdvertisedConfigOptions(opened.raw, selection.model));
|
|
39912
|
-
await applyAgentModelSelection(this.client, opened.sessionId, options, selection);
|
|
40170
|
+
const applied = await applyAgentModelSelection(this.client, opened.sessionId, options, selection);
|
|
40171
|
+
if (selection.model && applied.appliedSelection.model && applied.appliedSelection.model !== selection.model) {
|
|
40172
|
+
this.recordModelFallback(applied.appliedSelection, applied.options);
|
|
40173
|
+
}
|
|
39913
40174
|
}
|
|
39914
40175
|
return opened.sessionId;
|
|
39915
40176
|
}
|
|
40177
|
+
/**
|
|
40178
|
+
* A vanished model id was just substituted for a same-family replacement
|
|
40179
|
+
* (`resolveModelFamilyFallback`) so THIS turn could proceed instead of
|
|
40180
|
+
* failing it. Persist the correction so the phone stops offering the dead
|
|
40181
|
+
* id and the durable `model_unavailable` flag stays clear, and let the
|
|
40182
|
+
* server (`daemon-service.ts`'s `modelCatalog`) name the change in the
|
|
40183
|
+
* agent's DM — fire-and-forget: a slow or failed report must never hold up
|
|
40184
|
+
* or fail a turn that already succeeded with the fallback model applied.
|
|
40185
|
+
*/
|
|
40186
|
+
recordModelFallback(appliedSelection, options) {
|
|
40187
|
+
this.options.api.execute("postAgentModelCatalog", {
|
|
40188
|
+
agentId: this.agent.publicKey,
|
|
40189
|
+
workspaceId: this.options.workspaceId,
|
|
40190
|
+
options,
|
|
40191
|
+
selection: appliedSelection
|
|
40192
|
+
}).catch((error) => console.error(`[thin-core] failed to persist automatic model fallback for Room ${this.options.roomId}:`, error));
|
|
40193
|
+
}
|
|
39916
40194
|
/**
|
|
39917
40195
|
* The scheduler seam, and the only place that can see the boundary between
|
|
39918
40196
|
* waiting for a slot and spawning a harness: `queue-wait` closes the instant
|
|
@@ -40031,6 +40309,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
40031
40309
|
this.busy = true;
|
|
40032
40310
|
this.turnMetrics = {};
|
|
40033
40311
|
const trace = this.beginTurnTrace(item.id);
|
|
40312
|
+
const institutionalContextFetch = startInstitutionalContextFetch(api, this.options.roomId);
|
|
40034
40313
|
let liveStream;
|
|
40035
40314
|
let liveCornerOpened = false;
|
|
40036
40315
|
try {
|
|
@@ -40070,8 +40349,9 @@ var MonolithRoomTurnLoop = class {
|
|
|
40070
40349
|
this.roster(),
|
|
40071
40350
|
this.deliver(item),
|
|
40072
40351
|
api.execute("listRoomCorners", { roomId: this.options.roomId }),
|
|
40073
|
-
|
|
40352
|
+
awaitInstitutionalContext(institutionalContextFetch, (message) => console.warn(`[thin-core] Room ${this.options.roomId}: ${message}`))
|
|
40074
40353
|
]));
|
|
40354
|
+
trace.noteInstitutionalMemory(institutionalContext.outcome);
|
|
40075
40355
|
const names = new Map(roster.members.map((member) => [member.identityId, member.name]));
|
|
40076
40356
|
const transcriptRows = conversation.items.filter((message) => message.type === "message" && message.id !== item.id && !active.steers.some((steerItem) => steerItem.id === message.id)).slice(-80).map((message) => ({
|
|
40077
40357
|
id: message.id,
|
|
@@ -40327,6 +40607,18 @@ var MonolithRoomTurnLoop = class {
|
|
|
40327
40607
|
this.options.onIntakeError?.(error);
|
|
40328
40608
|
console.error("[thin-core] Room command failed", error);
|
|
40329
40609
|
},
|
|
40610
|
+
// Marks this loop busy the instant it attempts to claim a real
|
|
40611
|
+
// turn, before the claim's own network round trip and before
|
|
40612
|
+
// context.enter()'s own file I/O - closing the window where
|
|
40613
|
+
// RoomRuntimeCoordinator.reconcile's repository-revision restart
|
|
40614
|
+
// could see a claiming-but-not-yet-`busy` Room as idle and stop it,
|
|
40615
|
+
// cancelling a turn that had already begun (or was about to) (C112).
|
|
40616
|
+
onClaiming: () => {
|
|
40617
|
+
this.busy = true;
|
|
40618
|
+
},
|
|
40619
|
+
onClaimFailed: () => {
|
|
40620
|
+
this.busy = false;
|
|
40621
|
+
},
|
|
40330
40622
|
onEnter: (command) => this.squireRelay.activate(command, this.commandContext.generationId),
|
|
40331
40623
|
onLeave: (command) => this.squireRelay.deactivate(command.turnRequestId, this.pausedOnGrantRequestId),
|
|
40332
40624
|
stop: (requestId) => this.stopTurn(requestId),
|
|
@@ -40913,8 +41205,8 @@ async function materializeCornerWorktree(input) {
|
|
|
40913
41205
|
const remote = roomCheckoutRemote(input.remote);
|
|
40914
41206
|
const gitCommonDir = cornerRepositoryCacheDir(input.supervisorRoot, remote);
|
|
40915
41207
|
const path = resolve29(input.supervisorRoot, "beeline", "corners", input.cornerId);
|
|
40916
|
-
await mkdir20(
|
|
40917
|
-
await mkdir20(
|
|
41208
|
+
await mkdir20(dirname19(gitCommonDir), { recursive: true, mode: 448 });
|
|
41209
|
+
await mkdir20(dirname19(path), { recursive: true, mode: 448 });
|
|
40918
41210
|
const authEnv = githubGitEnv(input.token);
|
|
40919
41211
|
if (!existsSync8(resolve29(gitCommonDir, "HEAD"))) {
|
|
40920
41212
|
await execFileAsync8("git", ["clone", "--bare", remote, gitCommonDir], {
|
|
@@ -41035,7 +41327,7 @@ async function mapWithConcurrency(values, limit, visit) {
|
|
|
41035
41327
|
async function discoverCornerWorktree(supervisorRoot, cornerId) {
|
|
41036
41328
|
const cornersRoot = resolve29(supervisorRoot, "beeline", "corners");
|
|
41037
41329
|
const path = resolve29(cornersRoot, cornerId);
|
|
41038
|
-
if (
|
|
41330
|
+
if (dirname19(path) !== cornersRoot || !existsSync8(resolve29(path, ".git")))
|
|
41039
41331
|
return void 0;
|
|
41040
41332
|
const [canonicalRoot, canonicalPath] = await Promise.all([
|
|
41041
41333
|
realpath2(cornersRoot),
|
|
@@ -41605,7 +41897,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
41605
41897
|
return this.runtime.rooms.find((room) => room.channelId === roomId);
|
|
41606
41898
|
}
|
|
41607
41899
|
roomRoot(roomId) {
|
|
41608
|
-
return this.roomRecord(roomId)?.root ?? resolve29(
|
|
41900
|
+
return this.roomRecord(roomId)?.root ?? resolve29(dirname19(this.configPath), "rooms", roomId);
|
|
41609
41901
|
}
|
|
41610
41902
|
roomAgentHomeRoot(workspaceRoot, required = false) {
|
|
41611
41903
|
const flag = process.env.BUZZY_BODY_ROOM_HOME;
|
|
@@ -41628,9 +41920,9 @@ var RoomRuntimeCoordinator = class {
|
|
|
41628
41920
|
...this.baseConfig,
|
|
41629
41921
|
workspaceRoot,
|
|
41630
41922
|
agentPrivateRoot: resolve29(workspaceRoot, "agent-private"),
|
|
41631
|
-
agentMemoryRoot: resolve29(
|
|
41632
|
-
openRouterRoutingCacheDir: openRouterRoutingCacheDir(
|
|
41633
|
-
turnTraceDir: turnTraceDirectory(
|
|
41923
|
+
agentMemoryRoot: resolve29(dirname19(this.configPath), "memory"),
|
|
41924
|
+
openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname19(this.configPath)),
|
|
41925
|
+
turnTraceDir: turnTraceDirectory(dirname19(this.configPath)),
|
|
41634
41926
|
...agentHomeRoot ? { agentHomeRoot } : {}
|
|
41635
41927
|
};
|
|
41636
41928
|
}
|
|
@@ -41726,7 +42018,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
41726
42018
|
const targetBranch = repository.targetBranch || "main";
|
|
41727
42019
|
const checkoutId = createHash10("sha256").update(`${roomId}\0${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
|
|
41728
42020
|
const path = resolve29(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
|
|
41729
|
-
await mkdir20(
|
|
42021
|
+
await mkdir20(dirname19(path), { recursive: true, mode: 448 });
|
|
41730
42022
|
const token = remote.startsWith("https://github.com/") ? await this.parentRepositoryToken(roomId) : void 0;
|
|
41731
42023
|
const env = token ? githubGitEnv(token.token) : process.env;
|
|
41732
42024
|
if (!existsSync8(resolve29(path, ".git"))) {
|
|
@@ -42638,7 +42930,7 @@ init_systemd();
|
|
|
42638
42930
|
import { spawn as spawn11 } from "node:child_process";
|
|
42639
42931
|
import { createHash as createHash11 } from "node:crypto";
|
|
42640
42932
|
import { mkdir as mkdir23, rm as rm11, stat as stat7, writeFile as writeFile17 } from "node:fs/promises";
|
|
42641
|
-
import { dirname as
|
|
42933
|
+
import { dirname as dirname21, resolve as resolve33 } from "node:path";
|
|
42642
42934
|
|
|
42643
42935
|
// apps/body/dist/update-functional-probe.js
|
|
42644
42936
|
import { mkdir as mkdir21, rm as rm10 } from "node:fs/promises";
|
|
@@ -42825,7 +43117,10 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
42825
43117
|
cwd,
|
|
42826
43118
|
harnessStateDirs: stateDirs,
|
|
42827
43119
|
harnessHomeStateDirs: homeStateDirs,
|
|
42828
|
-
maskPaths:
|
|
43120
|
+
maskPaths: [
|
|
43121
|
+
...credentialMaskPaths(input.config.sandboxMaskPaths, operatorHome),
|
|
43122
|
+
...siblingAgentMaskPaths(input.runtimeDir)
|
|
43123
|
+
],
|
|
42829
43124
|
...tmpDir ? { tmpDir } : {}
|
|
42830
43125
|
},
|
|
42831
43126
|
command,
|
|
@@ -42972,7 +43267,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
42972
43267
|
|
|
42973
43268
|
// apps/body/dist/update-rollback-alert.js
|
|
42974
43269
|
import { mkdir as mkdir22, readFile as readFile21, rename as rename7, unlink as unlink6, writeFile as writeFile16 } from "node:fs/promises";
|
|
42975
|
-
import { dirname as
|
|
43270
|
+
import { dirname as dirname20, resolve as resolve32 } from "node:path";
|
|
42976
43271
|
var REPORT_INTERVAL_MS = 60 * 60 * 1e3;
|
|
42977
43272
|
var lastLogged = /* @__PURE__ */ new Map();
|
|
42978
43273
|
function updateRollbackAlertPath(runtimeDir) {
|
|
@@ -42981,7 +43276,7 @@ function updateRollbackAlertPath(runtimeDir) {
|
|
|
42981
43276
|
async function writeAlert(runtimeDir, alert) {
|
|
42982
43277
|
const path = updateRollbackAlertPath(runtimeDir);
|
|
42983
43278
|
const staged = `${path}.${process.pid}.tmp`;
|
|
42984
|
-
await mkdir22(
|
|
43279
|
+
await mkdir22(dirname20(path), { recursive: true });
|
|
42985
43280
|
await writeFile16(staged, `${JSON.stringify(alert, null, 2)}
|
|
42986
43281
|
`, { mode: 384 });
|
|
42987
43282
|
await rename7(staged, path);
|
|
@@ -43054,7 +43349,7 @@ async function withInstallLock(layout, work, options = {}) {
|
|
|
43054
43349
|
const now2 = options.now ?? Date.now;
|
|
43055
43350
|
const lock = resolve33(layout.releasesRoot, ".state", "install.lock");
|
|
43056
43351
|
const deadline = now2() + (options.waitMs ?? 1e4);
|
|
43057
|
-
await mkdir23(
|
|
43352
|
+
await mkdir23(dirname21(lock), { recursive: true });
|
|
43058
43353
|
for (; ; ) {
|
|
43059
43354
|
try {
|
|
43060
43355
|
await mkdir23(lock);
|
|
@@ -43680,7 +43975,7 @@ init_launchd();
|
|
|
43680
43975
|
init_systemd();
|
|
43681
43976
|
init_runtime();
|
|
43682
43977
|
import { mkdir as mkdir24, rename as rename8 } from "node:fs/promises";
|
|
43683
|
-
import { dirname as
|
|
43978
|
+
import { dirname as dirname22, resolve as resolve34 } from "node:path";
|
|
43684
43979
|
async function retireRemovedAgent(runtime, options = {}) {
|
|
43685
43980
|
const deletedRoot = resolve34(runtime.supervisorRoot, "beeline", "deleted-runtimes");
|
|
43686
43981
|
const target = resolve34(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
|
|
@@ -43703,13 +43998,13 @@ async function relocateAgentRuntime(runtime, target, options = {}) {
|
|
|
43703
43998
|
...options.run ? { run: options.run } : {}
|
|
43704
43999
|
});
|
|
43705
44000
|
}
|
|
43706
|
-
await mkdir24(
|
|
44001
|
+
await mkdir24(dirname22(destination), { recursive: true, mode: 448 });
|
|
43707
44002
|
await rename8(source, destination);
|
|
43708
44003
|
return destination;
|
|
43709
44004
|
}
|
|
43710
44005
|
|
|
43711
44006
|
// apps/body/dist/start-command.js
|
|
43712
|
-
import { basename as
|
|
44007
|
+
import { basename as basename7, dirname as dirname23 } from "node:path";
|
|
43713
44008
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
43714
44009
|
init_agent_command();
|
|
43715
44010
|
init_runtime();
|
|
@@ -43924,7 +44219,7 @@ async function startStoredRuntime(configPath, opts = {}, dependencyOverrides = {
|
|
|
43924
44219
|
return { status: "started", pid };
|
|
43925
44220
|
}
|
|
43926
44221
|
function agentStartId(configPath) {
|
|
43927
|
-
return
|
|
44222
|
+
return basename7(dirname23(configPath));
|
|
43928
44223
|
}
|
|
43929
44224
|
async function startRuntime(configPath, spinnerHandle) {
|
|
43930
44225
|
const report = (text2) => spinnerHandle ? spinnerHandle.message(text2) : console.log(text2);
|
|
@@ -44005,7 +44300,7 @@ async function runStartCommand(args, interactiveUi, dependencyOverrides = {}) {
|
|
|
44005
44300
|
for (const path of unique) {
|
|
44006
44301
|
const id = agentStartId(path);
|
|
44007
44302
|
const spinnerHandle = interactiveUi ? spinner() : void 0;
|
|
44008
|
-
spinnerHandle?.start(`Starting ${
|
|
44303
|
+
spinnerHandle?.start(`Starting ${dirname23(path)}\u2026`);
|
|
44009
44304
|
try {
|
|
44010
44305
|
const outcome = await deps.startOne(path, spinnerHandle);
|
|
44011
44306
|
const report = { id, path, ...outcome };
|
|
@@ -44039,9 +44334,9 @@ async function runStartCommand(args, interactiveUi, dependencyOverrides = {}) {
|
|
|
44039
44334
|
// apps/body/dist/connect-command.js
|
|
44040
44335
|
import { spawn as spawn12 } from "node:child_process";
|
|
44041
44336
|
import { createHash as createHash12, randomUUID as randomUUID10 } from "node:crypto";
|
|
44042
|
-
import { chmod as
|
|
44337
|
+
import { chmod as chmod9, mkdir as mkdir25, readFile as readFile22, unlink as unlink7, writeFile as writeFile18 } from "node:fs/promises";
|
|
44043
44338
|
import { homedir as homedir17, hostname as hostname3 } from "node:os";
|
|
44044
|
-
import { dirname as
|
|
44339
|
+
import { dirname as dirname24, resolve as resolve35 } from "node:path";
|
|
44045
44340
|
import { stdin as stdin3, stdout as stdout4 } from "node:process";
|
|
44046
44341
|
init_access_policy();
|
|
44047
44342
|
init_agent_command();
|
|
@@ -44530,7 +44825,7 @@ async function loadConnectModelCatalog(input, dependencies = {}) {
|
|
|
44530
44825
|
...effort ? { effort } : {}
|
|
44531
44826
|
};
|
|
44532
44827
|
}
|
|
44533
|
-
var CONNECT_PROBE_TIMEOUT_MS =
|
|
44828
|
+
var CONNECT_PROBE_TIMEOUT_MS = 25e3;
|
|
44534
44829
|
function connectProbeFoundModels(catalog) {
|
|
44535
44830
|
return catalog.note === void 0 && catalog.options.length > 0;
|
|
44536
44831
|
}
|
|
@@ -44588,13 +44883,17 @@ async function collectConnectWizard(prompts = clackPrompts, loadModels = loadCon
|
|
|
44588
44883
|
return (picked ?? "").trim();
|
|
44589
44884
|
};
|
|
44590
44885
|
const probe = async (candidate) => {
|
|
44886
|
+
const spinner2 = spinner({ output: clackPromptOutput() });
|
|
44887
|
+
spinner2.start(brass(`Checking ${connectHarnessLabel(candidate)}\u2026`));
|
|
44591
44888
|
try {
|
|
44592
44889
|
const catalog2 = await loadModels({
|
|
44593
44890
|
harness: candidate,
|
|
44594
44891
|
timeoutMs: CONNECT_PROBE_TIMEOUT_MS
|
|
44595
44892
|
});
|
|
44893
|
+
spinner2.stop();
|
|
44596
44894
|
return connectProbeFoundModels(catalog2) ? catalog2 : void 0;
|
|
44597
44895
|
} catch {
|
|
44896
|
+
spinner2.stop();
|
|
44598
44897
|
return void 0;
|
|
44599
44898
|
}
|
|
44600
44899
|
};
|
|
@@ -44805,21 +45104,21 @@ function providerEnvironment(selection) {
|
|
|
44805
45104
|
};
|
|
44806
45105
|
}
|
|
44807
45106
|
async function writePrivateJson(path, value) {
|
|
44808
|
-
await mkdir25(
|
|
45107
|
+
await mkdir25(dirname24(path), { recursive: true, mode: 448 });
|
|
44809
45108
|
await writeFile18(path, `${JSON.stringify(value, null, 2)}
|
|
44810
45109
|
`, { mode: 384 });
|
|
44811
|
-
await
|
|
45110
|
+
await chmod9(path, 384);
|
|
44812
45111
|
}
|
|
44813
45112
|
async function writeProviderEnv(selection, agentPubkey) {
|
|
44814
45113
|
const values = providerEnvironment(selection);
|
|
44815
45114
|
if (Object.keys(values).length === 0)
|
|
44816
45115
|
return void 0;
|
|
44817
45116
|
const path = resolve35(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
|
|
44818
|
-
await mkdir25(
|
|
45117
|
+
await mkdir25(dirname24(path), { recursive: true, mode: 448 });
|
|
44819
45118
|
const contents = Object.entries(values).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n");
|
|
44820
45119
|
await writeFile18(path, `${contents}
|
|
44821
45120
|
`, { mode: 384 });
|
|
44822
|
-
await
|
|
45121
|
+
await chmod9(path, 384);
|
|
44823
45122
|
return path;
|
|
44824
45123
|
}
|
|
44825
45124
|
async function runInstalledFinish(binary, grantPath) {
|
|
@@ -44980,7 +45279,7 @@ async function runConnectFinishCommand(path) {
|
|
|
44980
45279
|
if (model) {
|
|
44981
45280
|
const decision2 = await resolveOpenRouterRouting({
|
|
44982
45281
|
model,
|
|
44983
|
-
cacheDir: openRouterRoutingCacheDir(
|
|
45282
|
+
cacheDir: openRouterRoutingCacheDir(dirname24(connected.configPath)),
|
|
44984
45283
|
...apiKey ? { apiKey } : {},
|
|
44985
45284
|
probeTimeoutMs: 1e4
|
|
44986
45285
|
});
|
|
@@ -44999,7 +45298,7 @@ init_self_update();
|
|
|
44999
45298
|
|
|
45000
45299
|
// apps/body/dist/daemon-failure.js
|
|
45001
45300
|
import { mkdir as mkdir26, readFile as readFile23, rename as rename9, rm as rm12, writeFile as writeFile19 } from "node:fs/promises";
|
|
45002
|
-
import { dirname as
|
|
45301
|
+
import { dirname as dirname25, resolve as resolve36 } from "node:path";
|
|
45003
45302
|
var DAEMON_FAILURE_LIMIT = 3;
|
|
45004
45303
|
var DAEMON_FAILURE_WINDOW_MS = 5 * 6e4;
|
|
45005
45304
|
function daemonFailurePath(runtimeDir) {
|
|
@@ -45019,7 +45318,7 @@ async function readFailureRecord(runtimeDir) {
|
|
|
45019
45318
|
async function writeFailureRecord(runtimeDir, record6) {
|
|
45020
45319
|
const path = daemonFailurePath(runtimeDir);
|
|
45021
45320
|
const staged = `${path}.${process.pid}.tmp`;
|
|
45022
|
-
await mkdir26(
|
|
45321
|
+
await mkdir26(dirname25(path), { recursive: true, mode: 448 });
|
|
45023
45322
|
await writeFile19(staged, `${JSON.stringify(record6, null, 2)}
|
|
45024
45323
|
`, { mode: 384 });
|
|
45025
45324
|
await rename9(staged, path);
|
|
@@ -45046,7 +45345,7 @@ init_systemd();
|
|
|
45046
45345
|
|
|
45047
45346
|
// apps/body/dist/current-release-probe.js
|
|
45048
45347
|
import { spawn as spawn13 } from "node:child_process";
|
|
45049
|
-
import { dirname as
|
|
45348
|
+
import { dirname as dirname26, join as join16 } from "node:path";
|
|
45050
45349
|
init_runtime();
|
|
45051
45350
|
init_self_update();
|
|
45052
45351
|
var CURRENT_RELEASE_PROBE_TIMEOUT_MS = 12e4;
|
|
@@ -45153,7 +45452,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
45153
45452
|
const runtime = await readRuntimeRecord(configPath);
|
|
45154
45453
|
const agent = runtimeAgentCommand(runtime);
|
|
45155
45454
|
const config = loadBodyConfig({
|
|
45156
|
-
workspaceRoot: join16(
|
|
45455
|
+
workspaceRoot: join16(dirname26(configPath), "workspace"),
|
|
45157
45456
|
llmEnvFile: runtime.llmEnvFile,
|
|
45158
45457
|
env: { ...env, BUZZ_AGENT_BIN: agent.command, BUZZ_DEV_MCP_BIN: runtime.mcpBinary },
|
|
45159
45458
|
agent
|
|
@@ -45171,7 +45470,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
45171
45470
|
}
|
|
45172
45471
|
const layout = beelineInstallLayout(env);
|
|
45173
45472
|
const releaseId = (layout && await activeReleaseId(layout).catch(() => void 0)) ?? "unknown";
|
|
45174
|
-
const runtimeDir =
|
|
45473
|
+
const runtimeDir = dirname26(configPath);
|
|
45175
45474
|
const outcome = await probeOutcome(() => (options.probe ?? runUpdateFunctionalProbe)({
|
|
45176
45475
|
config,
|
|
45177
45476
|
runtimeDir,
|
|
@@ -45342,7 +45641,8 @@ var DaemonExitError = class extends Error {
|
|
|
45342
45641
|
};
|
|
45343
45642
|
async function runStoredDaemon(pathOrPointer) {
|
|
45344
45643
|
const configPath = await resolveRuntimeConfigPath(pathOrPointer);
|
|
45345
|
-
daemonFailureRuntimeDir =
|
|
45644
|
+
daemonFailureRuntimeDir = dirname27(configPath);
|
|
45645
|
+
await convergeRuntimeRecordFileModes(configPath);
|
|
45346
45646
|
const accessMigration = await migrateRuntimeRecordAccessPolicy(configPath);
|
|
45347
45647
|
let runtime = accessMigration.runtime;
|
|
45348
45648
|
if (!runtime.transport) {
|
|
@@ -45376,7 +45676,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
45376
45676
|
BUZZ_DEV_MCP_BIN: runtime.mcpBinary
|
|
45377
45677
|
};
|
|
45378
45678
|
const config = loadBodyConfig({
|
|
45379
|
-
workspaceRoot: resolve39(
|
|
45679
|
+
workspaceRoot: resolve39(dirname27(configPath), "workspace"),
|
|
45380
45680
|
llmEnvFile: runtime.llmEnvFile,
|
|
45381
45681
|
env,
|
|
45382
45682
|
agent
|
|
@@ -45392,8 +45692,10 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
45392
45692
|
}
|
|
45393
45693
|
if (runtime.sharedSkills)
|
|
45394
45694
|
config.sharedSkills = [...runtime.sharedSkills];
|
|
45395
|
-
|
|
45396
|
-
|
|
45695
|
+
const serverModelSelection = await daemonApi.execute("getAgentConfiguration", { agentId: runtime.agent.publicKey }).then((result) => result.model || result.effort ? { ...result.model ? { model: result.model } : {}, ...result.effort ? { effort: result.effort } : {} } : void 0).catch(() => void 0);
|
|
45696
|
+
const preflightModelSelection = resolvePreflightModelSelection(runtime.modelSelection, serverModelSelection);
|
|
45697
|
+
if (preflightModelSelection) {
|
|
45698
|
+
await applyRuntimeModelPreflight(config, agent, preflightModelSelection, void 0, refreshRuntimeAdapter);
|
|
45397
45699
|
if (!config.modelUnavailable) {
|
|
45398
45700
|
console.log("[body] persisted model/effort selection passed live startup validation");
|
|
45399
45701
|
} else {
|
|
@@ -45403,7 +45705,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
45403
45705
|
config.runtimeConfigPath = configPath;
|
|
45404
45706
|
const sandbox = await ensureBwrapSandbox({
|
|
45405
45707
|
...runtime.sandbox ? { policy: runtime.sandbox } : {},
|
|
45406
|
-
stateDir:
|
|
45708
|
+
stateDir: dirname27(configPath),
|
|
45407
45709
|
beforeInstall: () => extendSystemdStartTimeout(BUBBLEWRAP_INSTALL_BUDGET_MS)
|
|
45408
45710
|
});
|
|
45409
45711
|
if (sandbox.path)
|
|
@@ -45415,7 +45717,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
45415
45717
|
}
|
|
45416
45718
|
const controller = new AbortController();
|
|
45417
45719
|
const disposeStopSignals = installDaemonStopSignals(controller);
|
|
45418
|
-
const runtimeDir =
|
|
45720
|
+
const runtimeDir = dirname27(configPath);
|
|
45419
45721
|
const layout = beelineInstallLayout(process.env);
|
|
45420
45722
|
const notifier = new SystemdNotifier();
|
|
45421
45723
|
let rollbackAlertDrain;
|
|
@@ -45862,7 +46164,7 @@ async function main() {
|
|
|
45862
46164
|
}
|
|
45863
46165
|
if (!configPath && agentPubkey) {
|
|
45864
46166
|
const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
|
|
45865
|
-
configPath = configs.find((candidate) =>
|
|
46167
|
+
configPath = configs.find((candidate) => dirname27(candidate).endsWith(agentPubkey));
|
|
45866
46168
|
}
|
|
45867
46169
|
if (!configPath && agentPubkey) {
|
|
45868
46170
|
throw new DaemonExitError(`unknown agent ${agentPubkey}: no durable runtime exists; refusing service restart loop`, UNKNOWN_AGENT_EXIT_STATUS);
|
|
@@ -45890,7 +46192,7 @@ async function main() {
|
|
|
45890
46192
|
if (!agentPubkey)
|
|
45891
46193
|
throw new Error("stop requires --agent <pubkey>");
|
|
45892
46194
|
const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
|
|
45893
|
-
const configPath = configs.find((candidate) =>
|
|
46195
|
+
const configPath = configs.find((candidate) => dirname27(candidate).endsWith(agentPubkey));
|
|
45894
46196
|
if (!configPath)
|
|
45895
46197
|
throw new Error(`no stored runtime found for agent ${agentPubkey}`);
|
|
45896
46198
|
const runtime = await readRuntimeRecord(configPath);
|