usebeeline 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/usebeeline.mjs +621 -330
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -212,8 +212,8 @@ async function runSquireBrokerLink(options) {
|
|
|
212
212
|
const pending = /* @__PURE__ */ new Map();
|
|
213
213
|
const queued = [];
|
|
214
214
|
let resolveDone;
|
|
215
|
-
const done = new Promise((
|
|
216
|
-
resolveDone =
|
|
215
|
+
const done = new Promise((resolve43) => {
|
|
216
|
+
resolveDone = resolve43;
|
|
217
217
|
});
|
|
218
218
|
const failResponse = (id) => `${JSON.stringify({
|
|
219
219
|
jsonrpc: "2.0",
|
|
@@ -13834,10 +13834,10 @@ function squireLoginWallIn(value, depth = 0) {
|
|
|
13834
13834
|
if (!item)
|
|
13835
13835
|
return void 0;
|
|
13836
13836
|
const needsUser = record(item.needs_user);
|
|
13837
|
-
if (needsUser?.wall === "google_session") {
|
|
13837
|
+
if (needsUser?.wall === "google_session" || needsUser?.wall === "oauth_sign_in") {
|
|
13838
13838
|
const message = shortString(needsUser.message);
|
|
13839
13839
|
if (message)
|
|
13840
|
-
return { wall:
|
|
13840
|
+
return { wall: needsUser.wall, message };
|
|
13841
13841
|
}
|
|
13842
13842
|
const oauth = record(item.oauth);
|
|
13843
13843
|
if (oauth?.state === "awaiting_human") {
|
|
@@ -14126,7 +14126,7 @@ function configureNetworkFamilyDefaults(network = net) {
|
|
|
14126
14126
|
configureNetworkFamilyDefaults();
|
|
14127
14127
|
|
|
14128
14128
|
// apps/body/dist/cli.js
|
|
14129
|
-
import { dirname as dirname30, resolve as
|
|
14129
|
+
import { dirname as dirname30, resolve as resolve42 } from "node:path";
|
|
14130
14130
|
import { stdin as stdin4, stdout as stdout5 } from "node:process";
|
|
14131
14131
|
|
|
14132
14132
|
// node_modules/@clack/core/dist/index.mjs
|
|
@@ -15566,7 +15566,7 @@ function parseCursorModelsOutput(output) {
|
|
|
15566
15566
|
};
|
|
15567
15567
|
}
|
|
15568
15568
|
async function enumerateCursorModels(env = process.env) {
|
|
15569
|
-
return new Promise((
|
|
15569
|
+
return new Promise((resolve43) => {
|
|
15570
15570
|
const child = spawn2("cursor-agent", ["models"], {
|
|
15571
15571
|
env,
|
|
15572
15572
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -15580,11 +15580,11 @@ async function enumerateCursorModels(env = process.env) {
|
|
|
15580
15580
|
});
|
|
15581
15581
|
child.on("error", () => {
|
|
15582
15582
|
clearTimeout(timer);
|
|
15583
|
-
|
|
15583
|
+
resolve43(void 0);
|
|
15584
15584
|
});
|
|
15585
15585
|
child.on("close", (code) => {
|
|
15586
15586
|
clearTimeout(timer);
|
|
15587
|
-
|
|
15587
|
+
resolve43(code === 0 ? parseCursorModelsOutput(output) : void 0);
|
|
15588
15588
|
});
|
|
15589
15589
|
});
|
|
15590
15590
|
}
|
|
@@ -16011,13 +16011,13 @@ var CursorAcpServer = class {
|
|
|
16011
16011
|
consumeLine(line);
|
|
16012
16012
|
});
|
|
16013
16013
|
try {
|
|
16014
|
-
const { code, signal } = await new Promise((
|
|
16014
|
+
const { code, signal } = await new Promise((resolve43) => {
|
|
16015
16015
|
let settled = false;
|
|
16016
16016
|
const finish = (exitCode, exitSignal) => {
|
|
16017
16017
|
if (settled)
|
|
16018
16018
|
return;
|
|
16019
16019
|
settled = true;
|
|
16020
|
-
|
|
16020
|
+
resolve43({ code: exitCode, signal: exitSignal });
|
|
16021
16021
|
};
|
|
16022
16022
|
child.once("error", (error) => {
|
|
16023
16023
|
spawnError = error instanceof Error ? error.message : String(error);
|
|
@@ -16162,10 +16162,10 @@ function releaseSquireConnectSession(log2, owner = "") {
|
|
|
16162
16162
|
function squireChromeProfileDir() {
|
|
16163
16163
|
return process.env.TRUSTY_SQUIRE_PROFILE_DIR ?? squireHostPaths(homedir2()).profileDir;
|
|
16164
16164
|
}
|
|
16165
|
-
var defaultShellRunner = (command, args) => new Promise((
|
|
16165
|
+
var defaultShellRunner = (command, args) => new Promise((resolve43) => {
|
|
16166
16166
|
execFile(command, [...args], { timeout: 12e4, maxBuffer: 4 * 1024 * 1024, encoding: "utf8" }, (error, stdout6, stderr) => {
|
|
16167
16167
|
const code = error?.code;
|
|
16168
|
-
|
|
16168
|
+
resolve43({
|
|
16169
16169
|
code: typeof code === "number" ? code : error ? 1 : 0,
|
|
16170
16170
|
stdout: String(stdout6 ?? ""),
|
|
16171
16171
|
stderr: String(stderr ?? "")
|
|
@@ -16190,7 +16190,7 @@ function killConnectTree(child) {
|
|
|
16190
16190
|
}
|
|
16191
16191
|
child.kill();
|
|
16192
16192
|
}
|
|
16193
|
-
var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((
|
|
16193
|
+
var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((resolve43) => {
|
|
16194
16194
|
const child = spawn5(command, args, {
|
|
16195
16195
|
stdio: ["ignore", "pipe", "pipe"],
|
|
16196
16196
|
env: env ?? squireConnectProcessEnv(),
|
|
@@ -16204,7 +16204,7 @@ var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((res
|
|
|
16204
16204
|
const safetyTimer = setTimeout(() => {
|
|
16205
16205
|
if (!resolved) {
|
|
16206
16206
|
resolved = true;
|
|
16207
|
-
|
|
16207
|
+
resolve43({ stdout: stdout6, stderr, pid: child.pid ?? void 0, report, abort: () => {
|
|
16208
16208
|
} });
|
|
16209
16209
|
}
|
|
16210
16210
|
killConnectTree(child);
|
|
@@ -16239,7 +16239,7 @@ var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((res
|
|
|
16239
16239
|
const finish = (result) => {
|
|
16240
16240
|
if (!resolved) {
|
|
16241
16241
|
resolved = true;
|
|
16242
|
-
|
|
16242
|
+
resolve43(result);
|
|
16243
16243
|
}
|
|
16244
16244
|
};
|
|
16245
16245
|
const settle = (result) => {
|
|
@@ -16729,12 +16729,12 @@ var StdioSquireMcpClient = class {
|
|
|
16729
16729
|
const child = this.child;
|
|
16730
16730
|
if (!child)
|
|
16731
16731
|
return Promise.reject(new Error("Squire MCP session is not running"));
|
|
16732
|
-
return new Promise((
|
|
16732
|
+
return new Promise((resolve43, reject) => {
|
|
16733
16733
|
const timer = setTimeout(() => {
|
|
16734
16734
|
this.pending.delete(id);
|
|
16735
16735
|
reject(new Error(`${method} timed out`));
|
|
16736
16736
|
}, method === "initialize" ? INITIALIZE_TIMEOUT_MS : CALL_TIMEOUT_MS);
|
|
16737
|
-
this.pending.set(id, { resolve:
|
|
16737
|
+
this.pending.set(id, { resolve: resolve43, reject, timer });
|
|
16738
16738
|
child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}
|
|
16739
16739
|
`);
|
|
16740
16740
|
});
|
|
@@ -16756,8 +16756,10 @@ var StdioSquireMcpClient = class {
|
|
|
16756
16756
|
continue;
|
|
16757
16757
|
}
|
|
16758
16758
|
const id = typeof message.id === "number" ? message.id : void 0;
|
|
16759
|
-
if (id === void 0)
|
|
16759
|
+
if (id === void 0) {
|
|
16760
|
+
this.options.onNotification?.(message);
|
|
16760
16761
|
continue;
|
|
16762
|
+
}
|
|
16761
16763
|
const entry = this.pending.get(id);
|
|
16762
16764
|
if (!entry)
|
|
16763
16765
|
continue;
|
|
@@ -16845,6 +16847,7 @@ var SquireTaskRelay = class {
|
|
|
16845
16847
|
contextFile;
|
|
16846
16848
|
authorize;
|
|
16847
16849
|
makeClient;
|
|
16850
|
+
onApprovalDecided;
|
|
16848
16851
|
server;
|
|
16849
16852
|
url;
|
|
16850
16853
|
token = randomUUID3();
|
|
@@ -16860,13 +16863,16 @@ var SquireTaskRelay = class {
|
|
|
16860
16863
|
processGroup: true,
|
|
16861
16864
|
onSpawn: callbacks.onSpawn,
|
|
16862
16865
|
onExit: callbacks.onExit,
|
|
16863
|
-
log: callbacks.onDiagnostic
|
|
16864
|
-
|
|
16866
|
+
log: callbacks.onDiagnostic,
|
|
16867
|
+
onNotification: callbacks.onNotification
|
|
16868
|
+
}), onApprovalDecided = () => {
|
|
16869
|
+
}) {
|
|
16865
16870
|
this.agentId = agentId;
|
|
16866
16871
|
this.roomId = roomId;
|
|
16867
16872
|
this.contextFile = contextFile;
|
|
16868
16873
|
this.authorize = authorize;
|
|
16869
16874
|
this.makeClient = makeClient;
|
|
16875
|
+
this.onApprovalDecided = onApprovalDecided;
|
|
16870
16876
|
}
|
|
16871
16877
|
async listen() {
|
|
16872
16878
|
if (this.closed)
|
|
@@ -16890,9 +16896,9 @@ var SquireTaskRelay = class {
|
|
|
16890
16896
|
response.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ error: error instanceof Error ? error.message : "Squire relay failed" }));
|
|
16891
16897
|
}
|
|
16892
16898
|
});
|
|
16893
|
-
await new Promise((
|
|
16899
|
+
await new Promise((resolve43, reject) => {
|
|
16894
16900
|
server.once("error", reject);
|
|
16895
|
-
server.listen(0, "127.0.0.1",
|
|
16901
|
+
server.listen(0, "127.0.0.1", resolve43);
|
|
16896
16902
|
});
|
|
16897
16903
|
this.server = server;
|
|
16898
16904
|
const address = server.address();
|
|
@@ -16992,6 +16998,7 @@ var SquireTaskRelay = class {
|
|
|
16992
16998
|
};
|
|
16993
16999
|
task.client = this.makeClient({
|
|
16994
17000
|
onSpawn: (pid) => this.log("relay-spawn", task, { pid }),
|
|
17001
|
+
onNotification: (message) => this.handleApprovalNotification(task, message),
|
|
16995
17002
|
onDiagnostic: (message) => {
|
|
16996
17003
|
if (message.startsWith("squire mcp exited"))
|
|
16997
17004
|
return;
|
|
@@ -17128,7 +17135,10 @@ var SquireTaskRelay = class {
|
|
|
17128
17135
|
if (pending && ids.length) {
|
|
17129
17136
|
task.pendingApprovals.set(approvalKey, {
|
|
17130
17137
|
requestId: active.requestId,
|
|
17131
|
-
sessionIds: new Set(ids)
|
|
17138
|
+
sessionIds: new Set(ids),
|
|
17139
|
+
tool: approval.tool,
|
|
17140
|
+
title: approval.title,
|
|
17141
|
+
detail: approval.detail
|
|
17132
17142
|
});
|
|
17133
17143
|
this.log("approval-pending", task, {
|
|
17134
17144
|
tool: safeToolName ?? null,
|
|
@@ -17169,6 +17179,37 @@ var SquireTaskRelay = class {
|
|
|
17169
17179
|
task.pendingApprovals.delete(id);
|
|
17170
17180
|
}
|
|
17171
17181
|
}
|
|
17182
|
+
/**
|
|
17183
|
+
* Squire's own unsolicited decision on an approval this task is still
|
|
17184
|
+
* holding a connection open for. Matched back to the pending entry by the
|
|
17185
|
+
* same hash `handleSerial` keyed it under (the approval id Squire itself
|
|
17186
|
+
* returned), so a notification for an approval this relay never tracked —
|
|
17187
|
+
* or one already released — is silently ignored, never trusted blind.
|
|
17188
|
+
*/
|
|
17189
|
+
handleApprovalNotification(task, message) {
|
|
17190
|
+
if (message.method !== "notifications/approval_decided")
|
|
17191
|
+
return;
|
|
17192
|
+
const params = message.params;
|
|
17193
|
+
const approvalId = params?.approval_id;
|
|
17194
|
+
const status = params?.status;
|
|
17195
|
+
if (typeof approvalId !== "string" || !approvalId || status !== "approved" && status !== "denied")
|
|
17196
|
+
return;
|
|
17197
|
+
const approvalKey = createHash("sha256").update(approvalId).digest("hex");
|
|
17198
|
+
const pending = task.pendingApprovals.get(approvalKey);
|
|
17199
|
+
if (!pending)
|
|
17200
|
+
return;
|
|
17201
|
+
task.pendingApprovals.delete(approvalKey);
|
|
17202
|
+
this.onApprovalDecided({
|
|
17203
|
+
requestId: pending.requestId,
|
|
17204
|
+
approvalId,
|
|
17205
|
+
status,
|
|
17206
|
+
tool: pending.tool,
|
|
17207
|
+
title: pending.title,
|
|
17208
|
+
detail: pending.detail
|
|
17209
|
+
});
|
|
17210
|
+
if (!this.active && !this.approvalRequestId && !task.pendingApprovals.size)
|
|
17211
|
+
this.scheduleIdle();
|
|
17212
|
+
}
|
|
17172
17213
|
};
|
|
17173
17214
|
function runSquireTaskProxy(env = process.env) {
|
|
17174
17215
|
const url = env.BEELINE_SQUIRE_RELAY_URL;
|
|
@@ -17864,11 +17905,11 @@ var RegistryMcpHostBroker = class {
|
|
|
17864
17905
|
})();
|
|
17865
17906
|
});
|
|
17866
17907
|
});
|
|
17867
|
-
await new Promise((
|
|
17908
|
+
await new Promise((resolve43, reject) => {
|
|
17868
17909
|
this.server.once("error", reject);
|
|
17869
17910
|
this.server.listen(this.socketPath, () => {
|
|
17870
17911
|
this.server.off("error", reject);
|
|
17871
|
-
|
|
17912
|
+
resolve43();
|
|
17872
17913
|
});
|
|
17873
17914
|
});
|
|
17874
17915
|
chmodSync(this.socketPath, 384);
|
|
@@ -17877,12 +17918,12 @@ var RegistryMcpHostBroker = class {
|
|
|
17877
17918
|
const server = this.server;
|
|
17878
17919
|
this.server = void 0;
|
|
17879
17920
|
if (server)
|
|
17880
|
-
await new Promise((
|
|
17921
|
+
await new Promise((resolve43) => server.close(() => resolve43()));
|
|
17881
17922
|
rmSync(this.socketPath, { force: true });
|
|
17882
17923
|
}
|
|
17883
17924
|
};
|
|
17884
17925
|
async function brokerRequest(socketPath, request) {
|
|
17885
|
-
return new Promise((
|
|
17926
|
+
return new Promise((resolve43, reject) => {
|
|
17886
17927
|
const socket = createConnection3(socketPath);
|
|
17887
17928
|
let output = "";
|
|
17888
17929
|
socket.setEncoding("utf8");
|
|
@@ -17899,7 +17940,7 @@ async function brokerRequest(socketPath, request) {
|
|
|
17899
17940
|
throw new Error(parsed.error);
|
|
17900
17941
|
if (!Array.isArray(parsed.messages) || !parsed.messages.every((entry) => typeof entry === "string"))
|
|
17901
17942
|
throw new Error("Registry MCP broker returned an invalid response");
|
|
17902
|
-
|
|
17943
|
+
resolve43(parsed.messages);
|
|
17903
17944
|
} catch (error) {
|
|
17904
17945
|
reject(error);
|
|
17905
17946
|
}
|
|
@@ -18013,6 +18054,7 @@ var SERVER_EVENT_KINDS = [
|
|
|
18013
18054
|
"check-failed",
|
|
18014
18055
|
"merged",
|
|
18015
18056
|
"grant-decided",
|
|
18057
|
+
"squire-approval-decided",
|
|
18016
18058
|
"connector-offer-decided",
|
|
18017
18059
|
"turn-cancelled",
|
|
18018
18060
|
"choice-answered",
|
|
@@ -18020,6 +18062,25 @@ var SERVER_EVENT_KINDS = [
|
|
|
18020
18062
|
"poll-closed",
|
|
18021
18063
|
"workflow-handoff"
|
|
18022
18064
|
];
|
|
18065
|
+
var SERVER_EVENT_KIND_DETAIL = {
|
|
18066
|
+
"joined": "fires when a person or agent joins this Room, or when a Workspace arrival projects into it",
|
|
18067
|
+
"schedule-ran": "fires when a schedule you created runs",
|
|
18068
|
+
"corner-opened": "fires when a corner opens under this Room",
|
|
18069
|
+
"check-passed": "fires when a corner's pull request checks turn green",
|
|
18070
|
+
"check-failed": "fires when a corner's pull request checks turn red",
|
|
18071
|
+
"merged": "fires when a corner's pull request merges",
|
|
18072
|
+
"grant-decided": "carries the grant id and status and resumes the turn that asked for the grant",
|
|
18073
|
+
"squire-approval-decided": "carries what was approved or denied and the Squire approval id, and resumes the turn that asked",
|
|
18074
|
+
"connector-offer-decided": "fires when a human accepts or declines an offered connector, or a reconnect ceremony finishes, and resumes the turn that offered it",
|
|
18075
|
+
"turn-cancelled": "fires when a running turn is stopped",
|
|
18076
|
+
"choice-answered": "fires when a human answers a posted choice, starting a new turn for the asking agent",
|
|
18077
|
+
"choice-skipped": "fires when a posted choice's window closes unanswered, starting a new turn for the asking agent",
|
|
18078
|
+
"poll-closed": "fires when a posted poll closes, starting a new turn for the asking agent",
|
|
18079
|
+
"workflow-handoff": "fires when a workflow run starts or hands off to its next role"
|
|
18080
|
+
};
|
|
18081
|
+
function eventKindCatalogLines(kinds = SERVER_EVENT_KINDS) {
|
|
18082
|
+
return kinds.map((kind) => `${kind} ${SERVER_EVENT_KIND_DETAIL[kind]}`);
|
|
18083
|
+
}
|
|
18023
18084
|
|
|
18024
18085
|
// packages/api-contract/dist/turn-silence.js
|
|
18025
18086
|
var TURN_SILENCE_KINDS = [
|
|
@@ -28531,13 +28592,13 @@ var RoomSupervisor = class {
|
|
|
28531
28592
|
*/
|
|
28532
28593
|
retryDelay(failures, signal, since = this.#wakes) {
|
|
28533
28594
|
const delay = this.delaysMs[failures - 1];
|
|
28534
|
-
return new Promise((
|
|
28595
|
+
return new Promise((resolve43) => {
|
|
28535
28596
|
let timer;
|
|
28536
28597
|
const done = () => {
|
|
28537
28598
|
clearTimeout(timer);
|
|
28538
28599
|
this.#parked.delete(done);
|
|
28539
28600
|
signal?.removeEventListener("abort", done);
|
|
28540
|
-
|
|
28601
|
+
resolve43();
|
|
28541
28602
|
};
|
|
28542
28603
|
this.#parked.add(done);
|
|
28543
28604
|
signal?.addEventListener("abort", done, { once: true });
|
|
@@ -28729,12 +28790,12 @@ async function retryBeforeReady(work, options) {
|
|
|
28729
28790
|
if (wait2 <= 0)
|
|
28730
28791
|
break;
|
|
28731
28792
|
await options.extendStartTimeout(wait2 + 15e3);
|
|
28732
|
-
await new Promise((
|
|
28793
|
+
await new Promise((resolve43) => {
|
|
28733
28794
|
const timer = setTimeout(done, wait2);
|
|
28734
28795
|
function done() {
|
|
28735
28796
|
clearTimeout(timer);
|
|
28736
28797
|
options.signal?.removeEventListener("abort", done);
|
|
28737
|
-
|
|
28798
|
+
resolve43();
|
|
28738
28799
|
}
|
|
28739
28800
|
wake = done;
|
|
28740
28801
|
options.signal?.addEventListener("abort", done, { once: true });
|
|
@@ -29195,9 +29256,26 @@ var AcpRequestTimeoutError = class extends Error {
|
|
|
29195
29256
|
this.name = "AcpRequestTimeoutError";
|
|
29196
29257
|
}
|
|
29197
29258
|
};
|
|
29198
|
-
|
|
29199
|
-
|
|
29200
|
-
|
|
29259
|
+
var TURN_BACKSTOP_MS = 30 * 6e4;
|
|
29260
|
+
var AcpTurnBackstopError = class extends Error {
|
|
29261
|
+
timeoutMs;
|
|
29262
|
+
lastActivity;
|
|
29263
|
+
cause = "turn_backstop";
|
|
29264
|
+
constructor(timeoutMs, lastActivity, stderrTail = "", detail = "") {
|
|
29265
|
+
const meaningful = flattenHarnessCause(stderrTail);
|
|
29266
|
+
super(`turn_backstop: no ACP traffic for ${timeoutMs / 6e4} minutes; last activity: ${lastActivity}${detail ? ` (${detail})` : ""}${meaningful ? `; harness stderr: ${meaningful}` : ""}`);
|
|
29267
|
+
this.timeoutMs = timeoutMs;
|
|
29268
|
+
this.lastActivity = lastActivity;
|
|
29269
|
+
this.name = "AcpTurnBackstopError";
|
|
29270
|
+
}
|
|
29271
|
+
};
|
|
29272
|
+
var AcpRuntimeExitedError = class extends Error {
|
|
29273
|
+
cause = "runtime_exited";
|
|
29274
|
+
constructor(detail) {
|
|
29275
|
+
super(`runtime_exited: ${detail}`);
|
|
29276
|
+
this.name = "AcpRuntimeExitedError";
|
|
29277
|
+
}
|
|
29278
|
+
};
|
|
29201
29279
|
function killChildProcessGroup(child, signal) {
|
|
29202
29280
|
if (!child.pid)
|
|
29203
29281
|
return;
|
|
@@ -29247,9 +29325,16 @@ function parseAvailableCommands(value) {
|
|
|
29247
29325
|
}
|
|
29248
29326
|
return result;
|
|
29249
29327
|
}
|
|
29328
|
+
function isHarnessNotifyChunk(update) {
|
|
29329
|
+
const meta = update._meta;
|
|
29330
|
+
const piAcp = meta?.piAcp;
|
|
29331
|
+
return Boolean(piAcp?.notify);
|
|
29332
|
+
}
|
|
29250
29333
|
function agentMessageChunkText(update) {
|
|
29251
29334
|
if (update.sessionUpdate !== "agent_message_chunk")
|
|
29252
29335
|
return "";
|
|
29336
|
+
if (isHarnessNotifyChunk(update))
|
|
29337
|
+
return "";
|
|
29253
29338
|
const content = update.content;
|
|
29254
29339
|
if (content?.type === "text")
|
|
29255
29340
|
return content.text ?? "";
|
|
@@ -29521,16 +29606,26 @@ var AcpClient = class extends EventEmitter {
|
|
|
29521
29606
|
});
|
|
29522
29607
|
this.child.stdout.setEncoding("utf8");
|
|
29523
29608
|
this.child.stdout.on("data", (chunk) => this.onData(chunk));
|
|
29609
|
+
const child = this.child;
|
|
29610
|
+
const pipeClosed = (pipe) => {
|
|
29611
|
+
setTimeout(() => {
|
|
29612
|
+
if (this.child === child && this.alive) {
|
|
29613
|
+
const stderr = flattenHarnessCause(this.stderrTail);
|
|
29614
|
+
this.failRuntime(`ACP agent ${this.agentLabel} ${pipe} pipe closed${stderr ? `: ${stderr}` : ""}`);
|
|
29615
|
+
}
|
|
29616
|
+
}, 25);
|
|
29617
|
+
};
|
|
29618
|
+
this.child.stdout.on("end", () => pipeClosed("stdout"));
|
|
29619
|
+
this.child.stdout.on("close", () => pipeClosed("stdout"));
|
|
29620
|
+
this.child.stdout.on("error", (error) => this.failRuntime(`stdout: ${error.message}`));
|
|
29621
|
+
this.child.stdin.on("close", () => pipeClosed("stdin"));
|
|
29622
|
+
this.child.stdin.on("error", (error) => this.failRuntime(`stdin: ${error.message}`));
|
|
29524
29623
|
this.child.on("exit", (code, signal) => {
|
|
29525
|
-
|
|
29624
|
+
if (this.child === child)
|
|
29625
|
+
void this.handleChildExit(code, signal);
|
|
29526
29626
|
});
|
|
29527
29627
|
this.child.on("error", (err) => {
|
|
29528
|
-
this.
|
|
29529
|
-
for (const [, p] of this.pending) {
|
|
29530
|
-
clearTimeout(p.timer);
|
|
29531
|
-
p.reject(err);
|
|
29532
|
-
}
|
|
29533
|
-
this.pending.clear();
|
|
29628
|
+
this.failRuntime(`ACP agent ${this.agentLabel}: ${err.message}`);
|
|
29534
29629
|
if (this.listenerCount("error") > 0)
|
|
29535
29630
|
this.emit("error", err);
|
|
29536
29631
|
});
|
|
@@ -29556,13 +29651,28 @@ var AcpClient = class extends EventEmitter {
|
|
|
29556
29651
|
*/
|
|
29557
29652
|
async handleChildExit(code, signal) {
|
|
29558
29653
|
this.alive = false;
|
|
29559
|
-
const
|
|
29654
|
+
for (const p of this.pending.values())
|
|
29655
|
+
this.clearTimer(p);
|
|
29656
|
+
let oomKilled = false;
|
|
29657
|
+
if (signal === "SIGKILL" && !this.stopping) {
|
|
29658
|
+
let diagnosticTimer;
|
|
29659
|
+
try {
|
|
29660
|
+
oomKilled = await Promise.race([
|
|
29661
|
+
this.oomKills.consume().catch(() => false),
|
|
29662
|
+
new Promise((resolve43) => {
|
|
29663
|
+
diagnosticTimer = setTimeout(() => resolve43(false), 100);
|
|
29664
|
+
})
|
|
29665
|
+
]);
|
|
29666
|
+
} finally {
|
|
29667
|
+
clearTimeout(diagnosticTimer);
|
|
29668
|
+
}
|
|
29669
|
+
}
|
|
29560
29670
|
const exitText = oomKilled ? `ACP agent ${this.agentLabel} was killed by the kernel OOM killer (signal=SIGKILL)` : `ACP agent ${this.agentLabel} exited code=${code} signal=${signal}`;
|
|
29561
29671
|
const meaningful = flattenHarnessCause(this.stderrTail);
|
|
29562
29672
|
const stderrSuffix = meaningful ? `: ${meaningful}` : "";
|
|
29563
29673
|
for (const [, p] of this.pending) {
|
|
29564
29674
|
this.clearTimer(p);
|
|
29565
|
-
p.reject(new
|
|
29675
|
+
p.reject(new AcpRuntimeExitedError(`${exitText}${stderrSuffix}`));
|
|
29566
29676
|
}
|
|
29567
29677
|
this.pending.clear();
|
|
29568
29678
|
this.activeRunIds.clear();
|
|
@@ -29571,9 +29681,15 @@ var AcpClient = class extends EventEmitter {
|
|
|
29571
29681
|
this.sessionCommands.clear();
|
|
29572
29682
|
this.emit("exit", { code, signal });
|
|
29573
29683
|
}
|
|
29684
|
+
failRuntime(detail) {
|
|
29685
|
+
this.alive = false;
|
|
29686
|
+
for (const p of this.pending.values()) {
|
|
29687
|
+
this.clearTimer(p);
|
|
29688
|
+
p.reject(new AcpRuntimeExitedError(detail));
|
|
29689
|
+
}
|
|
29690
|
+
this.pending.clear();
|
|
29691
|
+
}
|
|
29574
29692
|
async stop() {
|
|
29575
|
-
if (!this.alive)
|
|
29576
|
-
return;
|
|
29577
29693
|
const child = this.child;
|
|
29578
29694
|
if (!child)
|
|
29579
29695
|
return;
|
|
@@ -29705,10 +29821,10 @@ var AcpClient = class extends EventEmitter {
|
|
|
29705
29821
|
}
|
|
29706
29822
|
/**
|
|
29707
29823
|
* Run one prompt turn. `timeoutMs` is an idle window, not a hard cap on
|
|
29708
|
-
* turn length: every
|
|
29709
|
-
* tool
|
|
29710
|
-
*
|
|
29711
|
-
* `
|
|
29824
|
+
* turn length: every inbound ACP message for this session re-arms it.
|
|
29825
|
+
* Open tool calls suspend the backstop until completion. A silent session
|
|
29826
|
+
* with no open tool is cancelled without stopping the runtime.
|
|
29827
|
+
* `onChunk` is the ACP-boundary
|
|
29712
29828
|
* streaming hook: called for every incremental `agent_message_chunk`
|
|
29713
29829
|
* delta as it arrives, so a caller can project live text without waiting
|
|
29714
29830
|
* for the turn to finish. A harness that only emits a final message
|
|
@@ -29723,18 +29839,15 @@ var AcpClient = class extends EventEmitter {
|
|
|
29723
29839
|
get lastPromptBytes() {
|
|
29724
29840
|
return this.lastPromptByteCount;
|
|
29725
29841
|
}
|
|
29726
|
-
async sessionPrompt(sessionId, text2, timeoutMs =
|
|
29842
|
+
async sessionPrompt(sessionId, text2, timeoutMs = TURN_BACKSTOP_MS, onChunk, onActivity, onToolCalls) {
|
|
29727
29843
|
this.lastPromptByteCount = typeof text2 === "string" ? Buffer.byteLength(text2, "utf8") : void 0;
|
|
29728
29844
|
const updates = [];
|
|
29729
29845
|
let promptRunId;
|
|
29730
|
-
let requestId;
|
|
29731
29846
|
const onUpdate = (u4) => {
|
|
29732
29847
|
if (u4.sessionId !== sessionId)
|
|
29733
29848
|
return;
|
|
29734
29849
|
updates.push(u4);
|
|
29735
29850
|
promptRunId ??= this.activeRunIdFromUpdate(u4.update);
|
|
29736
|
-
if (requestId !== void 0)
|
|
29737
|
-
this.resetPendingIdleTimeout(requestId);
|
|
29738
29851
|
onActivity?.(agentStreamSnapshot(updates, this.agentLabel));
|
|
29739
29852
|
onToolCalls?.(toolCallEntries(updates));
|
|
29740
29853
|
if (onChunk) {
|
|
@@ -29751,9 +29864,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
29751
29864
|
const result = await this.request("session/prompt", {
|
|
29752
29865
|
sessionId,
|
|
29753
29866
|
prompt: typeof text2 === "string" ? [{ type: "text", text: text2 }] : [...text2]
|
|
29754
|
-
}, timeoutMs, (
|
|
29755
|
-
requestId = id;
|
|
29756
|
-
}, promptPayloadNote(text2));
|
|
29867
|
+
}, timeoutMs, true, promptPayloadNote(text2));
|
|
29757
29868
|
const agentText = finalAgentMessageText(updates, this.agentLabel);
|
|
29758
29869
|
const toolCalls = toolCallEntries(updates);
|
|
29759
29870
|
return {
|
|
@@ -29836,22 +29947,22 @@ var AcpClient = class extends EventEmitter {
|
|
|
29836
29947
|
}
|
|
29837
29948
|
}
|
|
29838
29949
|
/**
|
|
29839
|
-
*
|
|
29840
|
-
*
|
|
29841
|
-
* delta, session/update, tool call). A request only times out after this
|
|
29842
|
-
* much wall-clock time with zero activity, not after a fixed deadline —
|
|
29843
|
-
* so an actively-working turn can run indefinitely while a genuinely
|
|
29844
|
-
* wedged one still gets caught.
|
|
29950
|
+
* A tool owns its deadline. Silence while it is open is never a turn failure.
|
|
29951
|
+
* After the last tool closes, start a full backstop window for this session.
|
|
29845
29952
|
*/
|
|
29846
29953
|
resetPendingIdleTimeout(id) {
|
|
29847
29954
|
const p = this.pending.get(id);
|
|
29848
29955
|
if (!p || p.idleTimeoutMs === void 0)
|
|
29849
29956
|
return;
|
|
29850
29957
|
this.clearTimer(p);
|
|
29851
|
-
|
|
29958
|
+
if (p.openToolCalls?.size)
|
|
29959
|
+
return;
|
|
29960
|
+
const { idleTimeoutMs, reject, detail, sessionId, lastActivity } = p;
|
|
29852
29961
|
p.timer = setTimeout(() => {
|
|
29853
29962
|
this.pending.delete(id);
|
|
29854
|
-
|
|
29963
|
+
if (sessionId)
|
|
29964
|
+
this.sessionCancel(sessionId);
|
|
29965
|
+
reject(new AcpTurnBackstopError(idleTimeoutMs, lastActivity ?? "session/prompt", this.stderrTail, detail));
|
|
29855
29966
|
}, idleTimeoutMs);
|
|
29856
29967
|
}
|
|
29857
29968
|
onData(chunk) {
|
|
@@ -29874,6 +29985,25 @@ var AcpClient = class extends EventEmitter {
|
|
|
29874
29985
|
handleMessage(msg) {
|
|
29875
29986
|
const id = msg.id;
|
|
29876
29987
|
const method = msg.method;
|
|
29988
|
+
const params = msg.params;
|
|
29989
|
+
const response = !method && id !== void 0 ? this.pending.get(Number(id)) : void 0;
|
|
29990
|
+
const sessionId = params?.sessionId ?? response?.sessionId;
|
|
29991
|
+
if (sessionId) {
|
|
29992
|
+
for (const [requestId, pending] of this.pending) {
|
|
29993
|
+
if (pending.method !== "session/prompt" || pending.sessionId !== sessionId)
|
|
29994
|
+
continue;
|
|
29995
|
+
const update = params?.update;
|
|
29996
|
+
pending.lastActivity = typeof update?.sessionUpdate === "string" ? update.sessionUpdate : method ?? `response:${response?.method ?? "request"}`;
|
|
29997
|
+
if (typeof update?.toolCallId === "string" && (update.sessionUpdate === "tool_call" || update.sessionUpdate === "tool_call_update")) {
|
|
29998
|
+
if (update.status === "pending" || update.status === "in_progress") {
|
|
29999
|
+
pending.openToolCalls?.add(update.toolCallId);
|
|
30000
|
+
} else if (update.status === "completed" || update.status === "failed") {
|
|
30001
|
+
pending.openToolCalls?.delete(update.toolCallId);
|
|
30002
|
+
}
|
|
30003
|
+
}
|
|
30004
|
+
this.resetPendingIdleTimeout(requestId);
|
|
30005
|
+
}
|
|
30006
|
+
}
|
|
29877
30007
|
if (id !== void 0 && !method) {
|
|
29878
30008
|
const n3 = Number(id);
|
|
29879
30009
|
const p = this.pending.get(n3);
|
|
@@ -29901,19 +30031,19 @@ var AcpClient = class extends EventEmitter {
|
|
|
29901
30031
|
return;
|
|
29902
30032
|
}
|
|
29903
30033
|
if (method === "session/update") {
|
|
29904
|
-
const
|
|
29905
|
-
if (
|
|
29906
|
-
if (
|
|
29907
|
-
const commands = parseAvailableCommands(
|
|
29908
|
-
this.sessionCommands.set(
|
|
30034
|
+
const params2 = msg.params;
|
|
30035
|
+
if (params2?.sessionId && params2.update) {
|
|
30036
|
+
if (params2.update.sessionUpdate === "available_commands_update") {
|
|
30037
|
+
const commands = parseAvailableCommands(params2.update.availableCommands);
|
|
30038
|
+
this.sessionCommands.set(params2.sessionId, commands);
|
|
29909
30039
|
this.commandsHandler?.(commands);
|
|
29910
|
-
this.emit("commands", { sessionId:
|
|
30040
|
+
this.emit("commands", { sessionId: params2.sessionId, commands });
|
|
29911
30041
|
}
|
|
29912
|
-
const toolCallId =
|
|
29913
|
-
const sessionUpdate =
|
|
30042
|
+
const toolCallId = params2.update.toolCallId;
|
|
30043
|
+
const sessionUpdate = params2.update.sessionUpdate;
|
|
29914
30044
|
if (typeof toolCallId === "string" && (sessionUpdate === "tool_call" || sessionUpdate === "tool_call_update")) {
|
|
29915
|
-
const metadataKey = `${
|
|
29916
|
-
const status =
|
|
30045
|
+
const metadataKey = `${params2.sessionId}\0${toolCallId}`;
|
|
30046
|
+
const status = params2.update.status;
|
|
29917
30047
|
if (status === "completed" || status === "failed") {
|
|
29918
30048
|
this.toolCallMetadata.delete(metadataKey);
|
|
29919
30049
|
} else {
|
|
@@ -29921,25 +30051,25 @@ var AcpClient = class extends EventEmitter {
|
|
|
29921
30051
|
this.toolCallMetadata.set(metadataKey, {
|
|
29922
30052
|
...existing,
|
|
29923
30053
|
toolCallId,
|
|
29924
|
-
...typeof
|
|
29925
|
-
...typeof
|
|
29926
|
-
..."rawInput" in
|
|
30054
|
+
...typeof params2.update.title === "string" ? { title: params2.update.title } : {},
|
|
30055
|
+
...typeof params2.update.kind === "string" ? { kind: params2.update.kind } : {},
|
|
30056
|
+
..."rawInput" in params2.update ? { rawInput: params2.update.rawInput } : {},
|
|
29927
30057
|
// `content`/`locations` carry the touched file paths for adapters
|
|
29928
30058
|
// whose permission request omits them (codex-acp's file-change
|
|
29929
30059
|
// request has no rawInput at all) — the corner worktree guard in
|
|
29930
30060
|
// `session-sandbox.ts` reads them.
|
|
29931
|
-
..."content" in
|
|
29932
|
-
..."locations" in
|
|
30061
|
+
..."content" in params2.update ? { content: params2.update.content } : {},
|
|
30062
|
+
..."locations" in params2.update ? { locations: params2.update.locations } : {}
|
|
29933
30063
|
});
|
|
29934
30064
|
}
|
|
29935
30065
|
}
|
|
29936
30066
|
const u4 = {
|
|
29937
|
-
sessionId:
|
|
29938
|
-
update:
|
|
30067
|
+
sessionId: params2.sessionId,
|
|
30068
|
+
update: params2.update
|
|
29939
30069
|
};
|
|
29940
|
-
const activeRunId = this.activeRunIdFromUpdate(
|
|
30070
|
+
const activeRunId = this.activeRunIdFromUpdate(params2.update);
|
|
29941
30071
|
if (activeRunId)
|
|
29942
|
-
this.activeRunIds.set(
|
|
30072
|
+
this.activeRunIds.set(params2.sessionId, activeRunId);
|
|
29943
30073
|
this.emit("session/update", u4);
|
|
29944
30074
|
}
|
|
29945
30075
|
return;
|
|
@@ -29954,7 +30084,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
29954
30084
|
const current = this.activeRunIds.get(sessionId);
|
|
29955
30085
|
if (current)
|
|
29956
30086
|
return Promise.resolve(current);
|
|
29957
|
-
return new Promise((
|
|
30087
|
+
return new Promise((resolve43, reject) => {
|
|
29958
30088
|
const onUpdate = (update) => {
|
|
29959
30089
|
if (update.sessionId !== sessionId)
|
|
29960
30090
|
return;
|
|
@@ -29962,7 +30092,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
29962
30092
|
if (!runId)
|
|
29963
30093
|
return;
|
|
29964
30094
|
cleanup();
|
|
29965
|
-
|
|
30095
|
+
resolve43(runId);
|
|
29966
30096
|
};
|
|
29967
30097
|
const timer = setTimeout(() => {
|
|
29968
30098
|
cleanup();
|
|
@@ -30034,32 +30164,30 @@ var AcpClient = class extends EventEmitter {
|
|
|
30034
30164
|
result: { outcome: { outcome: "cancelled" } }
|
|
30035
30165
|
});
|
|
30036
30166
|
}
|
|
30037
|
-
/**
|
|
30038
|
-
|
|
30039
|
-
* and marks the request as idle-resettable at `timeoutMs`: callers can
|
|
30040
|
-
* then call `resetPendingIdleTimeout(id)` on activity to defer the
|
|
30041
|
-
* timeout instead of it firing at a fixed deadline.
|
|
30042
|
-
*/
|
|
30043
|
-
request(method, params, timeoutMs = 6e4, onStart, detail = "") {
|
|
30167
|
+
/** Prompt backstops reset on session traffic; other requests use a fixed deadline. */
|
|
30168
|
+
request(method, params, timeoutMs = 6e4, backstop = false, detail = "") {
|
|
30044
30169
|
if (!this.child || !this.alive) {
|
|
30045
30170
|
return Promise.reject(new Error("AcpClient not started"));
|
|
30046
30171
|
}
|
|
30047
30172
|
const id = this.nextId++;
|
|
30048
30173
|
const payload = { jsonrpc: "2.0", id, method, params };
|
|
30049
|
-
return new Promise((
|
|
30050
|
-
const timer = setTimeout(() => {
|
|
30174
|
+
return new Promise((resolve43, reject) => {
|
|
30175
|
+
const timer = backstop ? void 0 : setTimeout(() => {
|
|
30051
30176
|
this.pending.delete(id);
|
|
30052
|
-
reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail,
|
|
30177
|
+
reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail, false, detail));
|
|
30053
30178
|
}, timeoutMs);
|
|
30179
|
+
const sessionId = params?.sessionId;
|
|
30054
30180
|
this.pending.set(id, {
|
|
30055
|
-
resolve:
|
|
30181
|
+
resolve: resolve43,
|
|
30056
30182
|
reject,
|
|
30057
30183
|
timer,
|
|
30058
30184
|
method,
|
|
30185
|
+
...sessionId ? { sessionId } : {},
|
|
30059
30186
|
...detail ? { detail } : {},
|
|
30060
|
-
...
|
|
30187
|
+
...backstop ? { idleTimeoutMs: timeoutMs, lastActivity: method, openToolCalls: /* @__PURE__ */ new Set() } : {}
|
|
30061
30188
|
});
|
|
30062
|
-
|
|
30189
|
+
if (backstop)
|
|
30190
|
+
this.resetPendingIdleTimeout(id);
|
|
30063
30191
|
this.write(payload);
|
|
30064
30192
|
});
|
|
30065
30193
|
}
|
|
@@ -30067,9 +30195,15 @@ var AcpClient = class extends EventEmitter {
|
|
|
30067
30195
|
this.write({ jsonrpc: "2.0", method, params });
|
|
30068
30196
|
}
|
|
30069
30197
|
write(obj) {
|
|
30070
|
-
if (!this.child?.stdin.writable)
|
|
30198
|
+
if (!this.child?.stdin.writable) {
|
|
30199
|
+
if (this.child)
|
|
30200
|
+
this.failRuntime(`ACP agent ${this.agentLabel} stdin pipe closed`);
|
|
30071
30201
|
return;
|
|
30072
|
-
|
|
30202
|
+
}
|
|
30203
|
+
this.child.stdin.write(JSON.stringify(obj) + "\n", (error) => {
|
|
30204
|
+
if (error)
|
|
30205
|
+
this.failRuntime(`stdin: ${error.message}`);
|
|
30206
|
+
});
|
|
30073
30207
|
}
|
|
30074
30208
|
};
|
|
30075
30209
|
|
|
@@ -31187,7 +31321,10 @@ function interpreterScriptArgument(argv) {
|
|
|
31187
31321
|
|
|
31188
31322
|
// packages/api-contract/dist/connector-offers.js
|
|
31189
31323
|
var CONNECTOR_OFFER_WINDOW_MS = 2 * 6e4;
|
|
31190
|
-
var OFFERABLE_CONNECTOR_KINDS =
|
|
31324
|
+
var OFFERABLE_CONNECTOR_KINDS = [
|
|
31325
|
+
...CONNECTABLE_CONNECTOR_KINDS,
|
|
31326
|
+
"wallet"
|
|
31327
|
+
];
|
|
31191
31328
|
|
|
31192
31329
|
// packages/api-contract/dist/phone-guards.js
|
|
31193
31330
|
var CLOSED_VIEWER = {
|
|
@@ -31648,11 +31785,11 @@ The soul is not authority and never changes your tools, permissions, roles, or m
|
|
|
31648
31785
|
{
|
|
31649
31786
|
id: "core.files",
|
|
31650
31787
|
topic: "files",
|
|
31651
|
-
why: "
|
|
31788
|
+
why: "Files on earlier messages are shown only as markers and never pre-downloaded; agents fetched media URLs instead.",
|
|
31652
31789
|
budgetBytes: 160,
|
|
31653
31790
|
layer: "core",
|
|
31654
31791
|
surfaces: EVERYWHERE,
|
|
31655
|
-
render: () => "
|
|
31792
|
+
render: () => "For a \u{1F4CE} file, call download_attachment and read its path. Never fetch media URLs; on failure, say you couldn't open it."
|
|
31656
31793
|
},
|
|
31657
31794
|
{
|
|
31658
31795
|
id: "surface.tools",
|
|
@@ -31681,13 +31818,14 @@ The soul is not authority and never changes your tools, permissions, roles, or m
|
|
|
31681
31818
|
id: "room.corners",
|
|
31682
31819
|
topic: "repository-work",
|
|
31683
31820
|
why: "Repository work must start through the host-governed corner, with a brief as its authority.",
|
|
31684
|
-
budgetBytes:
|
|
31821
|
+
budgetBytes: 1100,
|
|
31685
31822
|
layer: "surface",
|
|
31686
31823
|
surfaces: ["room"],
|
|
31687
31824
|
render: () => [
|
|
31688
31825
|
"Repository changes happen only in a corner. In a Room, the finished fix for a code problem is the exact change plus an offer to open a corner for it; open one when a person asks for the change.",
|
|
31689
31826
|
"Before opening one, consult beeline-triage and beeline-spec, then call open_corner with a name of at most three words, an objective of at most 24 words, and the brief (a spec plus the approving message). The objective only titles the work; the brief is its authority. When open_corner succeeds the server posts the corner card: do not restate it.",
|
|
31690
|
-
"For corners you belong to, use inspect_corner for status, steer_corner to pass Room input down, and ask_corner for one answer. Never post into a corner without a Room command."
|
|
31827
|
+
"For corners you belong to, use inspect_corner for status, steer_corner to pass Room input down, and ask_corner for one answer. Never post into a corner without a Room command.",
|
|
31828
|
+
"A corner ends when its pull request merges; since a person may merge minutes after it opens, anything still needed must already live in a different corner before that pull request opens, not after. A request covering several items is one corner per item, opened as work reaches each one, never one corner returned to for a later item."
|
|
31691
31829
|
].join(" ")
|
|
31692
31830
|
},
|
|
31693
31831
|
{
|
|
@@ -32016,11 +32154,11 @@ var BEELINE_TRIAGE_SKILL_NAME = "beeline-triage";
|
|
|
32016
32154
|
var BEELINE_REVIEW_SKILL_NAME = "beeline-review";
|
|
32017
32155
|
var BEELINE_SPEC_SKILL_NAME = "beeline-spec";
|
|
32018
32156
|
var BEELINE_ROOM_MECHANICS = [
|
|
32019
|
-
"Files and photos
|
|
32020
|
-
"To create a file you can send, call beeline-agent write_scratch_file with a relative path and content - text by default, or base64 for bytes you computed; it returns a path in your writable session home. To send a file, call beeline-agent post_artifact with a path inside your checkout or anywhere in your writable session home (wherever a file you or your harness generated actually landed, including one you just wrote), or with html/bytes content directly; it is uploaded and attached to your reply, and title and mime default from the file when you post by path. write_scratch_file produces the file, not a picture.
|
|
32157
|
+
"Files and photos on the message you are answering are downloaded for you: read them at the local path named in the prompt (photos may also arrive inline). A file on an earlier message shows only as a \u{1F4CE} marker with an id; call beeline-agent download_attachment with that message id and attachment id, then read the returned path. Never fetch a media URL; if the download fails, tell the requester you could not open the file.",
|
|
32158
|
+
"To create a file you can send, call beeline-agent write_scratch_file with a relative path and content - text by default, or base64 for bytes you computed; it returns a path in your writable session home. To send a file, call beeline-agent post_artifact with a path inside your checkout or anywhere in your writable session home (wherever a file you or your harness generated actually landed, including one you just wrote), or with html/bytes content directly; it is uploaded and attached to your reply, and title and mime default from the file when you post by path. write_scratch_file produces the file, not a picture.",
|
|
32021
32159
|
"To run something later or repeatedly, call beeline-agent create_schedule (interval in minutes or a 5-field cron, optional maxRuns); list_schedules / update_schedule / delete_schedule manage them, including schedules other agents created for themselves.",
|
|
32022
32160
|
`To react to a message in this Room, call beeline-agent react_to_message with its message id and one supported emoji (${MESSAGE_REACTION_EMOJIS.join(" ")}).`,
|
|
32023
|
-
`To react to things that HAPPEN in this Room rather than only to what is said to you, call beeline-agent subscribe_events with the kinds you want
|
|
32161
|
+
`To react to things that HAPPEN in this Room rather than only to what is said to you, call beeline-agent subscribe_events with the kinds you want; each one then wakes you for a turn. Available kinds: ${eventKindCatalogLines().join("; ")}. Subscriptions are per Room and cover every way the event lands: joining a Room you subscribed to wakes you, and so does a person arriving in the Workspace when that arrival projects into this Room - subscribe to joined in an onboarding Room and every newcomer wakes you, exactly like a greeter. It replaces your list, so send every kind you want - list_event_subscriptions shows the current one. You do this yourself: nobody has to configure it for you. A corner merging wakes nobody in its parent Room by default. If you still have work to do after a corner merges (a hand-off, a release step, a reply that has to describe landed code), subscribe to merged in the parent Room, from a turn there, before the merge. Each merge in that Room then wakes you and names the corner and pull request: act only on the corner you are waiting for, post nothing for any other merge, and take merged back out of your list once nothing is left to wait for. Never post just to acknowledge a merge: the merge card already announces it. If you are waiting on a human decision - a grant, a connector offer, a posted choice or poll, or a Squire approval (payment, credential, sign-in, or vouch) - subscribe to its kind instead of asking them to type a confirmation in the Room; the decision wakes you with the answer.`,
|
|
32024
32162
|
"If you need reach outside the sandbox, call beeline-agent request_grant. If you already know discrete options, call beeline-agent ask_choice (one human, optional) or open_poll (every human in this Room, required deadline). A poll is refused below two electors and above fifty, and in a DM. A plurality is a fact, never permission to deploy, delete, merge, or spend. Open-ended asks stay tagged prose. Never put Always / Once / No on a preference.",
|
|
32025
32163
|
"To state something that happened so the Room and other agents can act on it, call beeline-agent emit_event with your own agent:<slug> kind, one sentence, and optionally the agent members to wake. Chains of events are bounded and a refused emit posts nothing."
|
|
32026
32164
|
].join(" ");
|
|
@@ -32057,6 +32195,10 @@ A **tool** is something you can use once a human adds it; a **key** is the crede
|
|
|
32057
32195
|
|
|
32058
32196
|
The tools this build knows, what each is for, and which the owner of this machine already has are one call away: beeline-agent workbench_status. That read is the Workbench of the machine and owner you actually run on, not the person who asked. Connected apps are listed once per app with a stable ID. Their sign-in and credentials stay with the server. Trusty Squire is vaulted credentials plus a browser for the separate key and browser routes. Tailscale installs its CLI on the selected helper and opens Tailscale's own browser sign-in; once connected, use the CLI for tailnet resources and tailscale file cp or tailscale file get for Taildrop. The wallet is created only from the Workbench page. When you cannot reach a tool, say: I can't reach X on this machine because Y; to fix it, Z. Give one explanation, then take or offer Z.
|
|
32059
32197
|
|
|
32198
|
+
**Inspect your own host before answering.** When a question is about a system on the machine you run on, inspect its live state with the tools you have: processes, logs, local endpoints or service status. Say what you checked. Memory and Room history are not evidence of current state.
|
|
32199
|
+
|
|
32200
|
+
**Use available tools before asking the person.** Before asking a person for a code, a status or a file, call workbench_status and check whether a tool or connected app you already have can get it, then use it. This includes an emailed verification code in an already-connected inbox. Ask only when none can, and say why. The key-ownership and grant rules still apply.
|
|
32201
|
+
|
|
32060
32202
|
**Offer the tool at the moment you need it.** When the work in front of you needs a tool the person does not have, do not send them to a settings page and do not stop at naming it. Call workbench_status first - a tool they already have is used, not offered. In a Room or DM, call offer_connector with the connectorType and one short reason: a card appears there, spoken by you, addressed to the person you are answering, with one action. Connector offers are unavailable in corners; use a Room or DM for those. Your turn pauses on the card - say in prose what you are waiting for and end the turn; you are woken when it is added, and then you carry on.
|
|
32061
32203
|
|
|
32062
32204
|
**Research before you offer, and say so.** Never offer a tool you cannot describe. If someone asks you to install or add something you do not already know - by name, by purpose, or by what it will hold - say plainly that you are looking it up first, find out what it is and what it does with credentials, and state what you learned in your reply BEFORE the card appears. A person reading "Add X?" must already have read, in your own words, what X is. Refusing to act blind is part of being trusted with keys.
|
|
@@ -32067,9 +32209,9 @@ Keys belong to the human who provisioned them. Your owner's keys serve whoever a
|
|
|
32067
32209
|
|
|
32068
32210
|
## Connect an app
|
|
32069
32211
|
|
|
32070
|
-
When a request needs an app or service, call beeline-agent \`workbench_status\` first. For a connected app, use its ID with \`list_app_tools\`, then call \`execute_app_tool\` with the selected tool slug and arguments. The server executes against that person\u2019s account and decides permission on every call.
|
|
32212
|
+
When a request needs an app or service, call beeline-agent \`workbench_status\` first. For a connected app, use its ID with \`list_app_tools\`, then call \`execute_app_tool\` with the selected tool slug and arguments. The server executes against that person\u2019s account and decides permission on every call. If tool discovery reports an error, follow its cause; \`needs_connection\` means the account must be reconnected, and \`needs_permission\` means wait for the connected person's decision. Do not switch paths after denial or provider unavailability. No app token, provider key, or sign-in URL belongs in chat or a model prompt.
|
|
32071
32213
|
|
|
32072
|
-
For an app that is not connected, call \`connect_app\` with its name, one short reason, and a request-specific \`continuation\`: one sentence stating what you will do right after sign-in. Do not include a link, credential, account identifier, or private data in that sentence. The server chooses the route and returns \`next\`. In a corner, call it from that corner so the sign-in card and connection wake return there. A managed OAuth app presents a sign-in card to its owner; end the turn and wait for the connection wake. If the provider reports managed OAuth unsupported, follow the server's Squire route and its instructions. A provider outage is unavailable, not permission to change routes. After the person connects, read Workbench again and use the app ID.
|
|
32214
|
+
For an app that is not connected, call \`connect_app\` with its name, one short reason, and a request-specific \`continuation\`: one sentence stating what you will do right after sign-in. Do not include a link, credential, account identifier, or private data in that sentence. The server chooses the route and returns \`next\`. In a corner, call it from that corner so the sign-in card and connection wake return there. A managed OAuth app presents a sign-in card to its owner; end the turn and wait for the connection wake. If the provider reports managed OAuth unsupported, follow the server's Squire route and its instructions. A provider outage is unavailable, not permission to change routes. After the person connects, read Workbench again and use the app ID. Every use is authorized as \`app:<key>\` and recorded once.
|
|
32073
32215
|
|
|
32074
32216
|
## Showing a mock
|
|
32075
32217
|
|
|
@@ -32135,6 +32277,15 @@ The record informs the verdict but never replaces approve_merge or pr_checks_sta
|
|
|
32135
32277
|
- Record every command and exit code.
|
|
32136
32278
|
- A review with no executed command is invalid and must FAIL.
|
|
32137
32279
|
|
|
32280
|
+
### Design rules
|
|
32281
|
+
|
|
32282
|
+
When the diff touches UI and the repository has a DESIGN.md, check every changed style against its rules: colours from theme tokens only, the type roles, the spacing scale, the allowed radii, elevation, the shared components, and touch targets.
|
|
32283
|
+
|
|
32284
|
+
- Run the repository's design lints. In Beeline, from \`apps/mobile\`: \`npx vitest run sources/buzz/calm-lint sources/buzz/design-lint\`.
|
|
32285
|
+
- FAIL when a design baseline count grows, or when an allowlist entry is added without naming the design decision behind it.
|
|
32286
|
+
- Require a screenshot or rendered proof of every visual change in each theme the app ships (in Beeline, Obsidian and Bone).
|
|
32287
|
+
- A design-rule violation is an engineering finding and blocks PASS.
|
|
32288
|
+
|
|
32138
32289
|
## 4. Adversarial pass
|
|
32139
32290
|
|
|
32140
32291
|
- For every changed function, name one concrete input or sequence that breaks it.
|
|
@@ -33409,6 +33560,14 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
|
|
|
33409
33560
|
}
|
|
33410
33561
|
await applyGrantedHostRoutes(root, operatorHome, grantedHostRoutes, agentKind, failClosed, resourceAuthFile, extraHostRoutes, squireScope);
|
|
33411
33562
|
await provisionPiCustomModelConfig(root, operatorHome, failClosed, openRouterRouting);
|
|
33563
|
+
if (appliesToHarness(agentKind, "pi")) {
|
|
33564
|
+
const settings2 = {
|
|
33565
|
+
httpIdleTimeoutMs: 3e5,
|
|
33566
|
+
retry: { enabled: true, maxRetries: 3, baseDelayMs: 2e3 }
|
|
33567
|
+
};
|
|
33568
|
+
await writeIsolatedHarnessFile(resolve15(root, "pi", "settings.json"), `${JSON.stringify(settings2, null, 2)}
|
|
33569
|
+
`);
|
|
33570
|
+
}
|
|
33412
33571
|
}
|
|
33413
33572
|
function appliesToHarness(selected, harness) {
|
|
33414
33573
|
return !selected || selected === harness;
|
|
@@ -34390,7 +34549,7 @@ function clearInstallFailure(stateDir) {
|
|
|
34390
34549
|
} catch {
|
|
34391
34550
|
}
|
|
34392
34551
|
}
|
|
34393
|
-
var runSandboxInstallCommand = (command, args) => new Promise((
|
|
34552
|
+
var runSandboxInstallCommand = (command, args) => new Promise((resolve43) => {
|
|
34394
34553
|
execFile6(command, [...args], {
|
|
34395
34554
|
timeout: INSTALL_TIMEOUT_MS,
|
|
34396
34555
|
maxBuffer: INSTALL_OUTPUT_LIMIT * 2,
|
|
@@ -34400,7 +34559,7 @@ var runSandboxInstallCommand = (command, args) => new Promise((resolve42) => {
|
|
|
34400
34559
|
}, (error, stdout6, stderr) => {
|
|
34401
34560
|
const code = error && "code" in error && typeof error.code === "number" ? error.code : error ? null : 0;
|
|
34402
34561
|
const output = [stdout6, stderr].join("").trim();
|
|
34403
|
-
|
|
34562
|
+
resolve43({ code, output: output || (error ? error.message : "") });
|
|
34404
34563
|
});
|
|
34405
34564
|
});
|
|
34406
34565
|
function lastLine(output, fallback) {
|
|
@@ -35073,6 +35232,7 @@ var UPDATE_PROBE_TURN_TIMEOUT_MS = 45e3;
|
|
|
35073
35232
|
var UPDATE_PROBE_RETRY_DELAY_MS = 2e3;
|
|
35074
35233
|
var ACP_ERROR_CODE = /\bACP error (-\d+):/;
|
|
35075
35234
|
var ACP_PROMPT_INACTIVITY = /\bACP session\/prompt timed out after \d+ms of inactivity\b/;
|
|
35235
|
+
var ACP_TURN_BACKSTOP = /\bturn_backstop: no ACP traffic for [\d.]+ minutes; last activity:/;
|
|
35076
35236
|
function isServerInternalCode(code) {
|
|
35077
35237
|
return code === -32603 || code <= -32e3 && code >= -32099;
|
|
35078
35238
|
}
|
|
@@ -35080,8 +35240,9 @@ function classifyAcpTurnFailure(error) {
|
|
|
35080
35240
|
const message = error instanceof Error ? error.message : typeof error === "string" ? error : void 0;
|
|
35081
35241
|
if (!message)
|
|
35082
35242
|
return void 0;
|
|
35083
|
-
if (ACP_PROMPT_INACTIVITY.test(message))
|
|
35243
|
+
if (ACP_TURN_BACKSTOP.test(message) || ACP_PROMPT_INACTIVITY.test(message)) {
|
|
35084
35244
|
return { kind: "prompt-inactivity" };
|
|
35245
|
+
}
|
|
35085
35246
|
const code = Number(ACP_ERROR_CODE.exec(message)?.[1]);
|
|
35086
35247
|
if (Number.isFinite(code) && isServerInternalCode(code))
|
|
35087
35248
|
return { kind: "server-internal", code };
|
|
@@ -35136,7 +35297,7 @@ function describeCurrentReleaseOutcome(outcome) {
|
|
|
35136
35297
|
async function retryWhileAdapterReinstalls(run2, options = {}) {
|
|
35137
35298
|
const attempts = options.attempts ?? 12;
|
|
35138
35299
|
const delayMs = options.delayMs ?? 5e3;
|
|
35139
|
-
const sleep4 = options.sleep ?? ((ms) => new Promise((
|
|
35300
|
+
const sleep4 = options.sleep ?? ((ms) => new Promise((resolve43) => setTimeout(resolve43, ms)));
|
|
35140
35301
|
for (let attempt = 1; ; attempt += 1) {
|
|
35141
35302
|
try {
|
|
35142
35303
|
return await run2();
|
|
@@ -37809,7 +37970,7 @@ async function probeReleaseInSubprocess(input) {
|
|
|
37809
37970
|
return { kind: "unavailable", reason: `release ${input.releaseId} has no runnable CLI entrypoint` };
|
|
37810
37971
|
}
|
|
37811
37972
|
const timeoutMs = input.timeoutMs ?? CURRENT_RELEASE_PROBE_TIMEOUT_MS;
|
|
37812
|
-
return new Promise((
|
|
37973
|
+
return new Promise((resolve43) => {
|
|
37813
37974
|
const child = spawn13(input.execPath ?? process.execPath, [entrypoint, UPDATE_PROBE_COMMAND, "--config", input.runtimeConfigPath], { env: input.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] });
|
|
37814
37975
|
let stdout6 = "";
|
|
37815
37976
|
let stderr = "";
|
|
@@ -37819,7 +37980,7 @@ async function probeReleaseInSubprocess(input) {
|
|
|
37819
37980
|
return;
|
|
37820
37981
|
settled = true;
|
|
37821
37982
|
clearTimeout(timer);
|
|
37822
|
-
|
|
37983
|
+
resolve43(outcome);
|
|
37823
37984
|
};
|
|
37824
37985
|
const timer = setTimeout(() => {
|
|
37825
37986
|
child.kill("SIGKILL");
|
|
@@ -37903,8 +38064,8 @@ import { mkdir as mkdir28, rename as rename12, stat as stat9, writeFile as write
|
|
|
37903
38064
|
import { dirname as dirname29 } from "node:path";
|
|
37904
38065
|
|
|
37905
38066
|
// apps/body/dist/agent-runtime.js
|
|
37906
|
-
import { homedir as
|
|
37907
|
-
import { dirname as dirname28, join as join19, resolve as
|
|
38067
|
+
import { homedir as homedir19 } from "node:os";
|
|
38068
|
+
import { dirname as dirname28, join as join19, resolve as resolve41 } from "node:path";
|
|
37908
38069
|
|
|
37909
38070
|
// apps/body/dist/model-availability.js
|
|
37910
38071
|
var SECRET_VALUE = /(?:token|key|secret|password)=?[^\s,;]*/gi;
|
|
@@ -38038,10 +38199,10 @@ var LOGIN_URL = /https:\/\/login\.tailscale\.com\/[A-Za-z0-9_/-]+/u;
|
|
|
38038
38199
|
function clipped(value) {
|
|
38039
38200
|
return value.length <= OUTPUT_LIMIT ? value : value.slice(value.length - OUTPUT_LIMIT);
|
|
38040
38201
|
}
|
|
38041
|
-
var runTailscaleCommand = (command, args) => new Promise((
|
|
38202
|
+
var runTailscaleCommand = (command, args) => new Promise((resolve43) => {
|
|
38042
38203
|
execFile7(command, [...args], { timeout: COMMAND_TIMEOUT_MS, maxBuffer: OUTPUT_LIMIT * 2 }, (error, stdout6, stderr) => {
|
|
38043
38204
|
const code = error && "code" in error && typeof error.code === "number" ? error.code : error ? null : 0;
|
|
38044
|
-
|
|
38205
|
+
resolve43({ code, stdout: clipped(stdout6), stderr: clipped(stderr) });
|
|
38045
38206
|
});
|
|
38046
38207
|
});
|
|
38047
38208
|
function loginUrlFrom(status, output) {
|
|
@@ -38605,7 +38766,7 @@ import { execFile as execFile13 } from "node:child_process";
|
|
|
38605
38766
|
import { createHash as createHash13 } from "node:crypto";
|
|
38606
38767
|
import { existsSync as existsSync8, mkdirSync as mkdirSync3 } from "node:fs";
|
|
38607
38768
|
import { mkdir as mkdir26, readdir as readdir9, realpath as realpath2, rm as rm14 } from "node:fs/promises";
|
|
38608
|
-
import { dirname as dirname26, relative as relative3, resolve as
|
|
38769
|
+
import { dirname as dirname26, relative as relative3, resolve as resolve36, sep as sep2 } from "node:path";
|
|
38609
38770
|
import { promisify as promisify8 } from "node:util";
|
|
38610
38771
|
|
|
38611
38772
|
// apps/body/dist/grant-runner.js
|
|
@@ -39066,8 +39227,30 @@ function captureConnectionUsage(recorder, turn, calls) {
|
|
|
39066
39227
|
}
|
|
39067
39228
|
}
|
|
39068
39229
|
|
|
39069
|
-
// apps/body/dist/
|
|
39230
|
+
// apps/body/dist/model-context-window.js
|
|
39070
39231
|
import { readFile as readFile21 } from "node:fs/promises";
|
|
39232
|
+
import { join as join13 } from "node:path";
|
|
39233
|
+
async function modelContextWindowTokens(model, piHome) {
|
|
39234
|
+
if (!model || !piHome)
|
|
39235
|
+
return void 0;
|
|
39236
|
+
try {
|
|
39237
|
+
const catalog = JSON.parse(await readFile21(join13(piHome, "models.json"), "utf8"));
|
|
39238
|
+
const parts = model.split("/");
|
|
39239
|
+
const preferredProvider = parts.length > 2 ? parts.shift() : void 0;
|
|
39240
|
+
const modelId = parts.join("/");
|
|
39241
|
+
const providers = preferredProvider ? [catalog.providers?.[preferredProvider]].filter(Boolean) : Object.values(catalog.providers ?? {});
|
|
39242
|
+
for (const provider of providers) {
|
|
39243
|
+
const window = provider?.models?.find((entry) => entry.id === modelId)?.contextWindow;
|
|
39244
|
+
if (window && Number.isFinite(window) && window > 0)
|
|
39245
|
+
return Math.floor(window);
|
|
39246
|
+
}
|
|
39247
|
+
} catch {
|
|
39248
|
+
}
|
|
39249
|
+
return void 0;
|
|
39250
|
+
}
|
|
39251
|
+
|
|
39252
|
+
// apps/body/dist/turn-usage.js
|
|
39253
|
+
import { readFile as readFile22 } from "node:fs/promises";
|
|
39071
39254
|
function tokenCount(value) {
|
|
39072
39255
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
39073
39256
|
}
|
|
@@ -39079,61 +39262,77 @@ function promptTokens(usage2) {
|
|
|
39079
39262
|
const cacheWrite = tokenCount(usage2.cacheWrite) ?? tokenCount(usage2.cache_write) ?? 0;
|
|
39080
39263
|
return input + cacheRead + cacheWrite;
|
|
39081
39264
|
}
|
|
39082
|
-
async function
|
|
39265
|
+
async function readUsageCalls(input, latestTurn) {
|
|
39083
39266
|
const file = await piSessionFilePath(input.agentEnv, input.sessionId);
|
|
39084
39267
|
if (!file)
|
|
39268
|
+
return latestTurn ? void 0 : [];
|
|
39269
|
+
const raw = await readFile22(file, "utf8").catch(() => void 0);
|
|
39270
|
+
if (raw === void 0)
|
|
39085
39271
|
return void 0;
|
|
39086
|
-
|
|
39087
|
-
try {
|
|
39088
|
-
raw = await readFile21(file, "utf8");
|
|
39089
|
-
} catch {
|
|
39090
|
-
return void 0;
|
|
39091
|
-
}
|
|
39092
|
-
let latest;
|
|
39272
|
+
const calls = [];
|
|
39093
39273
|
for (const line of raw.split(/\r?\n/)) {
|
|
39094
|
-
if (!line.trim())
|
|
39095
|
-
continue;
|
|
39096
39274
|
let entry;
|
|
39097
39275
|
try {
|
|
39098
39276
|
entry = JSON.parse(line);
|
|
39099
39277
|
} catch {
|
|
39100
39278
|
continue;
|
|
39101
39279
|
}
|
|
39102
|
-
if (entry.type !== "message" || !entry.message)
|
|
39280
|
+
if (!entry || entry.type !== "message" || !entry.message)
|
|
39103
39281
|
continue;
|
|
39104
|
-
if (entry.message.role === "user")
|
|
39105
|
-
|
|
39106
|
-
continue;
|
|
39107
|
-
}
|
|
39282
|
+
if (entry.message.role === "user" && latestTurn)
|
|
39283
|
+
calls.length = 0;
|
|
39108
39284
|
if (entry.message.role !== "assistant")
|
|
39109
39285
|
continue;
|
|
39110
39286
|
const usage2 = entry.message.usage;
|
|
39111
|
-
|
|
39112
|
-
continue;
|
|
39113
|
-
const tokens = promptTokens(usage2);
|
|
39114
|
-
if (tokens === void 0)
|
|
39115
|
-
continue;
|
|
39287
|
+
const tokens = usage2 && typeof usage2 === "object" && !Array.isArray(usage2) ? promptTokens(usage2) : void 0;
|
|
39116
39288
|
const model = entry.message.model;
|
|
39117
|
-
|
|
39118
|
-
inputTokens: tokens,
|
|
39289
|
+
calls.push({
|
|
39290
|
+
...tokens !== void 0 ? { inputTokens: tokens } : {},
|
|
39119
39291
|
...typeof model === "string" && model ? { model } : {}
|
|
39120
|
-
};
|
|
39292
|
+
});
|
|
39121
39293
|
}
|
|
39122
|
-
return
|
|
39294
|
+
return calls;
|
|
39295
|
+
}
|
|
39296
|
+
function summarize(calls) {
|
|
39297
|
+
if (!calls.length)
|
|
39298
|
+
return void 0;
|
|
39299
|
+
const measured = calls.filter((call) => call.inputTokens !== void 0);
|
|
39300
|
+
return {
|
|
39301
|
+
...calls[calls.length - 1],
|
|
39302
|
+
...measured.length ? { totalInputTokens: measured.reduce((sum, call) => sum + call.inputTokens, 0) } : {},
|
|
39303
|
+
modelCalls: measured.length,
|
|
39304
|
+
modelCallsWithoutUsage: calls.length - measured.length
|
|
39305
|
+
};
|
|
39123
39306
|
}
|
|
39307
|
+
var TurnUsageAccumulator = class {
|
|
39308
|
+
calls = [];
|
|
39309
|
+
async measure(input, run2) {
|
|
39310
|
+
const before = await readUsageCalls(input, false);
|
|
39311
|
+
try {
|
|
39312
|
+
return await run2();
|
|
39313
|
+
} finally {
|
|
39314
|
+
const after = await readUsageCalls(input, false);
|
|
39315
|
+
if (before && after)
|
|
39316
|
+
this.calls.push(...after.slice(before.length));
|
|
39317
|
+
}
|
|
39318
|
+
}
|
|
39319
|
+
get usage() {
|
|
39320
|
+
return summarize(this.calls);
|
|
39321
|
+
}
|
|
39322
|
+
};
|
|
39124
39323
|
|
|
39125
39324
|
// apps/body/dist/server-command-intake.js
|
|
39126
39325
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
39127
39326
|
import { mkdir as mkdir17, writeFile as writeFile16 } from "node:fs/promises";
|
|
39128
39327
|
import { writeFileSync as writeFileSync4 } from "node:fs";
|
|
39129
39328
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
39130
|
-
import { dirname as dirname21, join as
|
|
39329
|
+
import { dirname as dirname21, join as join14 } from "node:path";
|
|
39131
39330
|
var CommandExecutionContext = class {
|
|
39132
39331
|
generationId = randomUUID10();
|
|
39133
39332
|
path;
|
|
39134
39333
|
current;
|
|
39135
39334
|
constructor(root) {
|
|
39136
|
-
this.path =
|
|
39335
|
+
this.path = join14(root ?? tmpdir4(), `beeline-command-${this.generationId}.json`);
|
|
39137
39336
|
}
|
|
39138
39337
|
async enter(command) {
|
|
39139
39338
|
this.current = command;
|
|
@@ -39281,11 +39480,11 @@ async function runServerCommandIntake(options) {
|
|
|
39281
39480
|
if (attempt === 3)
|
|
39282
39481
|
throw error;
|
|
39283
39482
|
const waitMs = Math.max(250 * 2 ** attempt, error instanceof DaemonApiError ? error.retryAfterMs ?? 0 : 0);
|
|
39284
|
-
await new Promise((
|
|
39483
|
+
await new Promise((resolve43) => {
|
|
39285
39484
|
const done = () => {
|
|
39286
39485
|
clearTimeout(timer);
|
|
39287
39486
|
signal?.removeEventListener("abort", done);
|
|
39288
|
-
|
|
39487
|
+
resolve43();
|
|
39289
39488
|
};
|
|
39290
39489
|
const timer = setTimeout(done, waitMs);
|
|
39291
39490
|
signal?.addEventListener("abort", done, { once: true });
|
|
@@ -39376,11 +39575,11 @@ async function runServerCommandIntake(options) {
|
|
|
39376
39575
|
}
|
|
39377
39576
|
}
|
|
39378
39577
|
options.onPoll?.();
|
|
39379
|
-
const reconcile = await new Promise((
|
|
39578
|
+
const reconcile = await new Promise((resolve43) => {
|
|
39380
39579
|
const done = (needed) => {
|
|
39381
39580
|
signal?.removeEventListener("abort", aborted);
|
|
39382
39581
|
wake = void 0;
|
|
39383
|
-
|
|
39582
|
+
resolve43(needed);
|
|
39384
39583
|
};
|
|
39385
39584
|
const aborted = () => done(false);
|
|
39386
39585
|
wake = done;
|
|
@@ -39422,9 +39621,9 @@ async function runServerCommandIntake(options) {
|
|
|
39422
39621
|
// apps/body/dist/monolith-corner-turn.js
|
|
39423
39622
|
import { execFile as execFile12 } from "node:child_process";
|
|
39424
39623
|
import { createHash as createHash12 } from "node:crypto";
|
|
39425
|
-
import { mkdir as mkdir25, readFile as
|
|
39426
|
-
import { homedir as
|
|
39427
|
-
import { dirname as dirname25, join as join18, resolve as
|
|
39624
|
+
import { mkdir as mkdir25, readFile as readFile27, writeFile as writeFile20 } from "node:fs/promises";
|
|
39625
|
+
import { homedir as homedir18, hostname as hostname3 } from "node:os";
|
|
39626
|
+
import { dirname as dirname25, join as join18, resolve as resolve35 } from "node:path";
|
|
39428
39627
|
import { promisify as promisify7 } from "node:util";
|
|
39429
39628
|
|
|
39430
39629
|
// apps/body/dist/agent-command-catalog.js
|
|
@@ -39443,7 +39642,7 @@ function agentCommandCatalogPublisher(input) {
|
|
|
39443
39642
|
|
|
39444
39643
|
// apps/body/dist/attachment-delivery.js
|
|
39445
39644
|
import { mkdir as mkdir18, writeFile as writeFile17 } from "node:fs/promises";
|
|
39446
|
-
import { basename as basename8, extname, join as
|
|
39645
|
+
import { basename as basename8, extname, join as join15 } from "node:path";
|
|
39447
39646
|
var MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;
|
|
39448
39647
|
var EXPIRED_REASON = "expired: these attachment bytes are past their retention window";
|
|
39449
39648
|
var FETCH_TIMEOUT_MS = 3e4;
|
|
@@ -39493,6 +39692,10 @@ async function fetchBoundedBytes(url, fetchImpl = fetch) {
|
|
|
39493
39692
|
return { status: response.status, ok: true, bytes, mimeType };
|
|
39494
39693
|
}
|
|
39495
39694
|
var MAX_INLINE_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
39695
|
+
function safeAttachmentNames(attachments) {
|
|
39696
|
+
const taken = /* @__PURE__ */ new Set();
|
|
39697
|
+
return attachments.map((attachment, index) => safeFileName(attachment, index, taken));
|
|
39698
|
+
}
|
|
39496
39699
|
function safeFileName(attachment, index, taken) {
|
|
39497
39700
|
const raw = basename8(attachment.name ?? "").replace(/[^\w.-]+/g, "_").replace(/^\.+/, "");
|
|
39498
39701
|
let name = raw || `attachment-${index + 1}`;
|
|
@@ -39506,8 +39709,7 @@ function safeFileName(attachment, index, taken) {
|
|
|
39506
39709
|
async function deliverAttachments(attachments, dir, fetchImpl = fetch, cached = []) {
|
|
39507
39710
|
if (!attachments.length)
|
|
39508
39711
|
return [];
|
|
39509
|
-
const
|
|
39510
|
-
const names = attachments.map((attachment, index) => safeFileName(attachment, index, taken));
|
|
39712
|
+
const names = safeAttachmentNames(attachments);
|
|
39511
39713
|
return Promise.all(attachments.map(async (attachment, index) => {
|
|
39512
39714
|
const tooLarge = (bytes) => ({
|
|
39513
39715
|
attachment,
|
|
@@ -39540,7 +39742,7 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch, cached =
|
|
|
39540
39742
|
return { attachment, reason: EXPIRED_REASON };
|
|
39541
39743
|
if (!fetched.ok)
|
|
39542
39744
|
throw new Error(`HTTP ${fetched.status}`);
|
|
39543
|
-
const path =
|
|
39745
|
+
const path = join15(dir, names[index]);
|
|
39544
39746
|
await writeFile17(path, fetched.bytes);
|
|
39545
39747
|
const bytes = fetched.bytes;
|
|
39546
39748
|
const mimeType = attachment.mimeType ?? fetched.mimeType;
|
|
@@ -39564,6 +39766,24 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch, cached =
|
|
|
39564
39766
|
}
|
|
39565
39767
|
}));
|
|
39566
39768
|
}
|
|
39769
|
+
var MEDIA_ID = /\/v1\/media\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:[?#]|$)/i;
|
|
39770
|
+
function attachmentId(attachment) {
|
|
39771
|
+
return MEDIA_ID.exec(attachment.url)?.[1]?.toLowerCase();
|
|
39772
|
+
}
|
|
39773
|
+
function readableSize(bytes) {
|
|
39774
|
+
if (bytes < 1024)
|
|
39775
|
+
return `${bytes} B`;
|
|
39776
|
+
if (bytes < 1024 * 1024)
|
|
39777
|
+
return `${Math.round(bytes / 1024)} KB`;
|
|
39778
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
39779
|
+
}
|
|
39780
|
+
function attachmentMarkerLines(attachments) {
|
|
39781
|
+
return attachments.map((attachment) => {
|
|
39782
|
+
const metadata = [attachment.mimeType, attachment.size ? readableSize(attachment.size) : ""].filter(Boolean).join(", ");
|
|
39783
|
+
const id = attachmentId(attachment);
|
|
39784
|
+
return `\u{1F4CE} ${attachment.name ?? "attachment"}${metadata ? ` (${metadata})` : ""} ${id ? `id=${id}` : "id unavailable"}${attachment.expired ? " (expired)" : ""}`;
|
|
39785
|
+
});
|
|
39786
|
+
}
|
|
39567
39787
|
function withoutImageData(delivered) {
|
|
39568
39788
|
return delivered.map(({ image: _image, ...rest }) => rest);
|
|
39569
39789
|
}
|
|
@@ -39742,6 +39962,7 @@ var AgentTurnStream = class {
|
|
|
39742
39962
|
* one bounds the lane at ONE write in flight plus ONE waiting.
|
|
39743
39963
|
*/
|
|
39744
39964
|
pending;
|
|
39965
|
+
latestChunk = "";
|
|
39745
39966
|
/**
|
|
39746
39967
|
* The stream as it stood when a corner handed everything up to that point to
|
|
39747
39968
|
* its durable work ledger — this turn's persisted stream offset. Held as the
|
|
@@ -39773,6 +39994,7 @@ var AgentTurnStream = class {
|
|
|
39773
39994
|
* it has.
|
|
39774
39995
|
*/
|
|
39775
39996
|
onChunk = (_delta, full, currentRun) => {
|
|
39997
|
+
this.latestChunk = sanitizeAgentReply(currentRun ?? "");
|
|
39776
39998
|
this.latest = full;
|
|
39777
39999
|
this.latestRun = currentRun ?? "";
|
|
39778
40000
|
const text2 = sanitizeAgentReply(this.tailOf(full));
|
|
@@ -39854,9 +40076,10 @@ var AgentTurnStream = class {
|
|
|
39854
40076
|
if (this.inFlight || this.pending === void 0)
|
|
39855
40077
|
return;
|
|
39856
40078
|
const text2 = this.pending;
|
|
40079
|
+
const latestChunk = this.latestChunk;
|
|
39857
40080
|
this.pending = void 0;
|
|
39858
40081
|
const { api, agentId, roomId, requestId, label } = this.options;
|
|
39859
|
-
this.inFlight = api.execute("postAgentDraft", { agentId, roomId, turnId: requestId, text: text2 }).then(() => void 0).catch((error) => console.error(`[thin-core] ${label} draft publish failed:`, error)).then(() => {
|
|
40082
|
+
this.inFlight = api.execute("postAgentDraft", { agentId, roomId, turnId: requestId, text: text2, latestChunk }).then(() => void 0).catch((error) => console.error(`[thin-core] ${label} draft publish failed:`, error)).then(() => {
|
|
39860
40083
|
this.inFlight = void 0;
|
|
39861
40084
|
this.publishPending();
|
|
39862
40085
|
});
|
|
@@ -39884,6 +40107,7 @@ var AgentTurnStream = class {
|
|
|
39884
40107
|
beginRun() {
|
|
39885
40108
|
this.latest = "";
|
|
39886
40109
|
this.latestRun = "";
|
|
40110
|
+
this.latestChunk = "";
|
|
39887
40111
|
this.persisted = "";
|
|
39888
40112
|
this.pending = void 0;
|
|
39889
40113
|
}
|
|
@@ -40034,15 +40258,17 @@ function mountedMcpSet(servers) {
|
|
|
40034
40258
|
|
|
40035
40259
|
// apps/body/dist/pi-mcp-bridge.js
|
|
40036
40260
|
import { execFile as execFile9 } from "node:child_process";
|
|
40037
|
-
import { mkdtemp as mkdtemp2, mkdir as mkdir19, readFile as
|
|
40261
|
+
import { mkdtemp as mkdtemp2, mkdir as mkdir19, readFile as readFile23, rm as rm11, unlink as unlink8 } from "node:fs/promises";
|
|
40038
40262
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
40039
40263
|
import { resolve as resolve28 } from "node:path";
|
|
40040
40264
|
import { promisify as promisify5 } from "node:util";
|
|
40041
40265
|
var PI_MCP_BRIDGE_FILENAME = "beeline-mcp-bridge.js";
|
|
40042
40266
|
var execFileAsync5 = promisify5(execFile9);
|
|
40043
40267
|
var nativeMcpProbes = /* @__PURE__ */ new Map();
|
|
40044
|
-
async function piHasNativeMcp(command) {
|
|
40045
|
-
|
|
40268
|
+
async function piHasNativeMcp(command, env) {
|
|
40269
|
+
const path = env?.PATH ?? process.env.PATH ?? "";
|
|
40270
|
+
const cacheKey = `${command}\0${path}`;
|
|
40271
|
+
let probe = nativeMcpProbes.get(cacheKey);
|
|
40046
40272
|
if (!probe) {
|
|
40047
40273
|
probe = (async () => {
|
|
40048
40274
|
const home = await mkdtemp2(resolve28(tmpdir5(), "beeline-pi-mcp-probe-"));
|
|
@@ -40050,7 +40276,7 @@ async function piHasNativeMcp(command) {
|
|
|
40050
40276
|
const { stdout: stdout6 } = await execFileAsync5(command, ["mcp", "list", "--json"], {
|
|
40051
40277
|
cwd: home,
|
|
40052
40278
|
timeout: 1200,
|
|
40053
|
-
env: { PATH:
|
|
40279
|
+
env: { PATH: path, HOME: home, PI_CODING_AGENT_DIR: home, PI_OFFLINE: "1" }
|
|
40054
40280
|
});
|
|
40055
40281
|
const result = JSON.parse(stdout6);
|
|
40056
40282
|
return Array.isArray(result.servers) && Array.isArray(result.errors);
|
|
@@ -40060,13 +40286,13 @@ async function piHasNativeMcp(command) {
|
|
|
40060
40286
|
await rm11(home, { recursive: true, force: true });
|
|
40061
40287
|
}
|
|
40062
40288
|
})();
|
|
40063
|
-
nativeMcpProbes.set(
|
|
40289
|
+
nativeMcpProbes.set(cacheKey, probe);
|
|
40064
40290
|
}
|
|
40065
40291
|
return probe;
|
|
40066
40292
|
}
|
|
40067
40293
|
async function isolatedPiConfig(piHome) {
|
|
40068
40294
|
try {
|
|
40069
|
-
const parsed = JSON.parse(await
|
|
40295
|
+
const parsed = JSON.parse(await readFile23(resolve28(piHome, "mcp.json"), "utf8"));
|
|
40070
40296
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
40071
40297
|
} catch (error) {
|
|
40072
40298
|
if (error.code !== "ENOENT")
|
|
@@ -40124,7 +40350,7 @@ async function installPiMcpBridge(input) {
|
|
|
40124
40350
|
const path = resolve28(directory, PI_MCP_BRIDGE_FILENAME);
|
|
40125
40351
|
try {
|
|
40126
40352
|
const config = await isolatedPiConfig(input.piHome);
|
|
40127
|
-
const nativeMcp = input.nativeMcp ?? await piHasNativeMcp(input.piCommand ?? "pi");
|
|
40353
|
+
const nativeMcp = input.nativeMcp ?? await piHasNativeMcp(input.piCommand ?? "pi", input.agentEnv);
|
|
40128
40354
|
if (nativeMcp) {
|
|
40129
40355
|
const mcpServers2 = { ...config.mcpServers };
|
|
40130
40356
|
for (const server of input.servers)
|
|
@@ -40345,20 +40571,22 @@ export default async function (pi) {
|
|
|
40345
40571
|
|
|
40346
40572
|
// apps/body/dist/corner-branch-sync.js
|
|
40347
40573
|
import { execFile as execFile10 } from "node:child_process";
|
|
40574
|
+
import { access as access2, readFile as readFile24 } from "node:fs/promises";
|
|
40575
|
+
import { resolve as resolve29 } from "node:path";
|
|
40348
40576
|
var CORNER_GIT_SYNC_TIMEOUT_MS = 12e4;
|
|
40349
40577
|
var CORNER_GIT_SYNC_KILL_GRACE_MS = 1e3;
|
|
40350
40578
|
var CornerGitSyncInterruptedError = class extends Error {
|
|
40351
40579
|
};
|
|
40352
40580
|
async function syncCornerBranch(input) {
|
|
40353
|
-
const git = async (args) => {
|
|
40581
|
+
const git = async (args, cleanup = false) => {
|
|
40354
40582
|
const controller = new AbortController();
|
|
40355
|
-
const signal = input.signal ? AbortSignal.any([input.signal, controller.signal]) : controller.signal;
|
|
40583
|
+
const signal = input.signal && !cleanup ? AbortSignal.any([input.signal, controller.signal]) : controller.signal;
|
|
40356
40584
|
const timer = setTimeout(() => controller.abort(), CORNER_GIT_SYNC_TIMEOUT_MS);
|
|
40357
40585
|
const interrupted = () => new CornerGitSyncInterruptedError(`corner git sync ${args[0]} ${controller.signal.aborted ? `timed out after ${CORNER_GIT_SYNC_TIMEOUT_MS}ms` : "stopped"}`);
|
|
40358
40586
|
try {
|
|
40359
40587
|
if (signal.aborted)
|
|
40360
40588
|
throw interrupted();
|
|
40361
|
-
return await new Promise((
|
|
40589
|
+
return await new Promise((resolve43, reject) => {
|
|
40362
40590
|
let killTimer;
|
|
40363
40591
|
let stdout6 = "";
|
|
40364
40592
|
let failure = null;
|
|
@@ -40372,35 +40600,41 @@ async function syncCornerBranch(input) {
|
|
|
40372
40600
|
});
|
|
40373
40601
|
const abort = () => {
|
|
40374
40602
|
if (!child) {
|
|
40375
|
-
|
|
40603
|
+
cleanup2();
|
|
40376
40604
|
reject(interrupted());
|
|
40377
40605
|
} else {
|
|
40378
40606
|
killTimer = setTimeout(() => child.kill("SIGKILL"), CORNER_GIT_SYNC_KILL_GRACE_MS);
|
|
40379
40607
|
}
|
|
40380
40608
|
};
|
|
40381
40609
|
signal.addEventListener("abort", abort, { once: true });
|
|
40382
|
-
const
|
|
40610
|
+
const cleanup2 = () => {
|
|
40383
40611
|
signal.removeEventListener("abort", abort);
|
|
40384
40612
|
if (killTimer)
|
|
40385
40613
|
clearTimeout(killTimer);
|
|
40386
40614
|
};
|
|
40387
40615
|
if (child)
|
|
40388
40616
|
child.once("close", () => {
|
|
40389
|
-
|
|
40617
|
+
cleanup2();
|
|
40390
40618
|
if (signal.aborted)
|
|
40391
40619
|
reject(interrupted());
|
|
40392
40620
|
else if (failure)
|
|
40393
40621
|
reject(failure);
|
|
40394
40622
|
else
|
|
40395
|
-
|
|
40623
|
+
resolve43(stdout6);
|
|
40396
40624
|
});
|
|
40397
40625
|
else
|
|
40398
|
-
input.git(args).then(
|
|
40626
|
+
input.git(args).then(resolve43, reject).finally(cleanup2);
|
|
40399
40627
|
});
|
|
40400
40628
|
} finally {
|
|
40401
40629
|
clearTimeout(timer);
|
|
40402
40630
|
}
|
|
40403
40631
|
};
|
|
40632
|
+
const marker = await readFile24(resolve29(input.worktreePath, ".git"), "utf8").catch(() => "");
|
|
40633
|
+
const gitDir = resolve29(input.worktreePath, marker.startsWith("gitdir: ") ? marker.slice(8).trim() : ".git");
|
|
40634
|
+
for (const directory of ["rebase-merge", "rebase-apply"]) {
|
|
40635
|
+
if (await access2(resolve29(gitDir, directory)).then(() => true, () => false))
|
|
40636
|
+
await git(["rebase", "--abort"], true);
|
|
40637
|
+
}
|
|
40404
40638
|
const remoteRef = `refs/remotes/origin/${input.featureBranch}`;
|
|
40405
40639
|
const fetched = await git([
|
|
40406
40640
|
"fetch",
|
|
@@ -40427,12 +40661,12 @@ async function syncCornerBranch(input) {
|
|
|
40427
40661
|
await git(behind ? ["merge", "--ff-only", remote] : ["rebase", remote]);
|
|
40428
40662
|
return behind ? "fast-forwarded" : "rebased";
|
|
40429
40663
|
} catch (error) {
|
|
40430
|
-
|
|
40431
|
-
throw error;
|
|
40432
|
-
await git(["rebase", "--abort"]).catch((error2) => {
|
|
40664
|
+
await git(["rebase", "--abort"], true).catch((error2) => {
|
|
40433
40665
|
if (error2 instanceof CornerGitSyncInterruptedError)
|
|
40434
40666
|
throw error2;
|
|
40435
40667
|
});
|
|
40668
|
+
if (error instanceof CornerGitSyncInterruptedError)
|
|
40669
|
+
throw error;
|
|
40436
40670
|
await git(["reset", "--hard", remote]);
|
|
40437
40671
|
return "realigned";
|
|
40438
40672
|
}
|
|
@@ -40446,7 +40680,8 @@ async function contains(git, head, ancestor) {
|
|
|
40446
40680
|
}
|
|
40447
40681
|
|
|
40448
40682
|
// apps/body/dist/room-session.js
|
|
40449
|
-
import { resolve as
|
|
40683
|
+
import { resolve as resolve30 } from "node:path";
|
|
40684
|
+
import { homedir as homedir16 } from "node:os";
|
|
40450
40685
|
|
|
40451
40686
|
// apps/body/dist/read-only-policy.js
|
|
40452
40687
|
var READ_ONLY_MCP_SERVER_NAME = "beeline-readonly-mcp";
|
|
@@ -40655,6 +40890,7 @@ function beelineAgentMcpServer(config, api, context) {
|
|
|
40655
40890
|
{ name: "BEELINE_DAEMON_TOKEN", value: connection.daemonToken },
|
|
40656
40891
|
{ name: "BEELINE_HELPER_VERSION", value: connection.helperVersion },
|
|
40657
40892
|
{ name: "BEELINE_DAEMON_AGENT_ID", value: connection.agentId },
|
|
40893
|
+
{ name: "BEELINE_OPERATOR_HOME", value: config.operatorHome ?? homedir16() },
|
|
40658
40894
|
{ name: "BEELINE_DAEMON_ROOM_ID", value: context.roomId },
|
|
40659
40895
|
{ name: "BEELINE_DAEMON_WORKSPACE_ID", value: context.workspaceId },
|
|
40660
40896
|
...context.cornerId ? [{ name: "BEELINE_DAEMON_CORNER_ID", value: context.cornerId }] : [],
|
|
@@ -40681,21 +40917,21 @@ function readOnlyMcpServer(config, cwd, agentMemoryDir) {
|
|
|
40681
40917
|
command: config.readonlyMcpCommand,
|
|
40682
40918
|
args: [...config.readonlyMcpArgs ?? []],
|
|
40683
40919
|
env: [
|
|
40684
|
-
{ name: "BEELINE_READONLY_ROOT", value:
|
|
40920
|
+
{ name: "BEELINE_READONLY_ROOT", value: resolve30(cwd) },
|
|
40685
40921
|
...config.agentHomeRoot ? [
|
|
40686
40922
|
{
|
|
40687
40923
|
name: "BEELINE_READONLY_AGENT_SKILLS_ROOT",
|
|
40688
|
-
value:
|
|
40924
|
+
value: resolve30(config.agentHomeRoot, skillDir, "skills")
|
|
40689
40925
|
}
|
|
40690
40926
|
] : [],
|
|
40691
|
-
...agentMemoryDir ? [{ name: "BEELINE_READONLY_AGENT_MEMORY_ROOT", value:
|
|
40927
|
+
...agentMemoryDir ? [{ name: "BEELINE_READONLY_AGENT_MEMORY_ROOT", value: resolve30(agentMemoryDir) }] : []
|
|
40692
40928
|
]
|
|
40693
40929
|
};
|
|
40694
40930
|
}
|
|
40695
40931
|
|
|
40696
40932
|
// apps/body/dist/institutional-context.js
|
|
40697
40933
|
import { performance as performance2 } from "node:perf_hooks";
|
|
40698
|
-
var INSTITUTIONAL_CONTEXT_TIMEOUT_MS =
|
|
40934
|
+
var INSTITUTIONAL_CONTEXT_TIMEOUT_MS = 500;
|
|
40699
40935
|
var INSTITUTIONAL_MEMORY_LIVE_FLAG = "BEELINE_INSTITUTIONAL_MEMORY_ENABLED";
|
|
40700
40936
|
function institutionalMemoryFlagEnabled(env, flag) {
|
|
40701
40937
|
return env[flag] !== "false";
|
|
@@ -40742,15 +40978,15 @@ async function awaitInstitutionalContext(fetch2, log2 = console.warn, budgetMs =
|
|
|
40742
40978
|
|
|
40743
40979
|
// apps/body/dist/codegraph.js
|
|
40744
40980
|
import { execFile as execFile11 } from "node:child_process";
|
|
40745
|
-
import { access as
|
|
40746
|
-
import { dirname as dirname22, isAbsolute as isAbsolute3, resolve as
|
|
40981
|
+
import { access as access3, appendFile, mkdir as mkdir20, readFile as readFile25 } from "node:fs/promises";
|
|
40982
|
+
import { dirname as dirname22, isAbsolute as isAbsolute3, resolve as resolve31 } from "node:path";
|
|
40747
40983
|
import { promisify as promisify6 } from "node:util";
|
|
40748
40984
|
var execFileAsync6 = promisify6(execFile11);
|
|
40749
40985
|
var CODEGRAPH_MCP_SERVER_NAME = "codegraph";
|
|
40750
40986
|
var CODEGRAPH_INDEX_PATH = ".codegraph/codegraph.db";
|
|
40751
40987
|
var CODEGRAPH_PREPARE_TIMEOUT_MS = 12e4;
|
|
40752
40988
|
function codegraphIndexDirectory(cwd) {
|
|
40753
|
-
return
|
|
40989
|
+
return resolve31(cwd, dirname22(CODEGRAPH_INDEX_PATH));
|
|
40754
40990
|
}
|
|
40755
40991
|
function codegraphMcpServer(config, cwd, options) {
|
|
40756
40992
|
if (!config.codegraphCommand)
|
|
@@ -40758,7 +40994,7 @@ function codegraphMcpServer(config, cwd, options) {
|
|
|
40758
40994
|
return {
|
|
40759
40995
|
name: CODEGRAPH_MCP_SERVER_NAME,
|
|
40760
40996
|
command: config.codegraphCommand,
|
|
40761
|
-
args: ["serve", "--mcp", "--path",
|
|
40997
|
+
args: ["serve", "--mcp", "--path", resolve31(cwd), ...options.readonly ? ["--no-watch"] : []],
|
|
40762
40998
|
env: [
|
|
40763
40999
|
{ name: "CODEGRAPH_TELEMETRY", value: "0" },
|
|
40764
41000
|
// One MCP child per harness session is easier to contain than a daemon
|
|
@@ -40776,7 +41012,7 @@ async function isGitWorktree(cwd) {
|
|
|
40776
41012
|
cwd,
|
|
40777
41013
|
timeout: 1e4
|
|
40778
41014
|
});
|
|
40779
|
-
return
|
|
41015
|
+
return resolve31(stdout6.trim()) === resolve31(cwd);
|
|
40780
41016
|
} catch {
|
|
40781
41017
|
return false;
|
|
40782
41018
|
}
|
|
@@ -40790,9 +41026,9 @@ async function excludeIndexFromGitStatus(cwd) {
|
|
|
40790
41026
|
const gitPath = stdout6.trim();
|
|
40791
41027
|
if (!gitPath)
|
|
40792
41028
|
return;
|
|
40793
|
-
const path = isAbsolute3(gitPath) ? gitPath :
|
|
41029
|
+
const path = isAbsolute3(gitPath) ? gitPath : resolve31(cwd, gitPath);
|
|
40794
41030
|
await mkdir20(dirname22(path), { recursive: true });
|
|
40795
|
-
const existing = await
|
|
41031
|
+
const existing = await readFile25(path, "utf8").catch(() => "");
|
|
40796
41032
|
if (existing.split("\n").includes(".codegraph/"))
|
|
40797
41033
|
return;
|
|
40798
41034
|
await appendFile(path, `${existing && !existing.endsWith("\n") ? "\n" : ""}.codegraph/
|
|
@@ -40805,8 +41041,8 @@ async function prepareCodegraphIndex(config, cwd) {
|
|
|
40805
41041
|
if (!command || !await isGitWorktree(cwd))
|
|
40806
41042
|
return false;
|
|
40807
41043
|
await excludeIndexFromGitStatus(cwd);
|
|
40808
|
-
const indexPath =
|
|
40809
|
-
const indexed = await
|
|
41044
|
+
const indexPath = resolve31(cwd, CODEGRAPH_INDEX_PATH);
|
|
41045
|
+
const indexed = await access3(indexPath).then(() => true, () => false);
|
|
40810
41046
|
const args = indexed ? ["sync", "--quiet", cwd] : ["init", "--yes", cwd];
|
|
40811
41047
|
try {
|
|
40812
41048
|
await execFileAsync6(command, args, {
|
|
@@ -40824,38 +41060,16 @@ async function prepareCodegraphIndex(config, cwd) {
|
|
|
40824
41060
|
|
|
40825
41061
|
// apps/body/dist/monolith-room-turn.js
|
|
40826
41062
|
import { mkdir as mkdir22, writeFile as writeFile18 } from "node:fs/promises";
|
|
40827
|
-
import { homedir as
|
|
41063
|
+
import { homedir as homedir17, hostname as hostname2 } from "node:os";
|
|
40828
41064
|
import { dirname as dirname23, join as join16 } from "node:path";
|
|
40829
41065
|
|
|
40830
41066
|
// packages/api-contract/dist/scheduled-prompts.js
|
|
40831
41067
|
var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
|
|
40832
41068
|
var SCHEDULE_RAN_VERB = "ran a schedule for";
|
|
40833
41069
|
|
|
40834
|
-
// apps/body/dist/model-context-window.js
|
|
40835
|
-
import { readFile as readFile24 } from "node:fs/promises";
|
|
40836
|
-
import { join as join15 } from "node:path";
|
|
40837
|
-
async function modelContextWindowTokens(model, piHome) {
|
|
40838
|
-
if (!model || !piHome)
|
|
40839
|
-
return void 0;
|
|
40840
|
-
try {
|
|
40841
|
-
const catalog = JSON.parse(await readFile24(join15(piHome, "models.json"), "utf8"));
|
|
40842
|
-
const parts = model.split("/");
|
|
40843
|
-
const preferredProvider = parts.length > 2 ? parts.shift() : void 0;
|
|
40844
|
-
const modelId = parts.join("/");
|
|
40845
|
-
const providers = preferredProvider ? [catalog.providers?.[preferredProvider]].filter(Boolean) : Object.values(catalog.providers ?? {});
|
|
40846
|
-
for (const provider of providers) {
|
|
40847
|
-
const window = provider?.models?.find((entry) => entry.id === modelId)?.contextWindow;
|
|
40848
|
-
if (window && Number.isFinite(window) && window > 0)
|
|
40849
|
-
return Math.floor(window);
|
|
40850
|
-
}
|
|
40851
|
-
} catch {
|
|
40852
|
-
}
|
|
40853
|
-
return void 0;
|
|
40854
|
-
}
|
|
40855
|
-
|
|
40856
41070
|
// apps/body/dist/turn-trace.js
|
|
40857
41071
|
import { appendFile as appendFile2, mkdir as mkdir21, readdir as readdir7, rm as rm12 } from "node:fs/promises";
|
|
40858
|
-
import { resolve as
|
|
41072
|
+
import { resolve as resolve32 } from "node:path";
|
|
40859
41073
|
import { performance as performance3 } from "node:perf_hooks";
|
|
40860
41074
|
var TURN_PHASES = [
|
|
40861
41075
|
/** Enqueued on `SessionScheduler` until this turn holds a slot. A capacity wait lives here. */
|
|
@@ -40891,6 +41105,7 @@ var TurnTrace = class {
|
|
|
40891
41105
|
atAdmission;
|
|
40892
41106
|
finished = false;
|
|
40893
41107
|
promptSections;
|
|
41108
|
+
promptWindow;
|
|
40894
41109
|
searchMemoryCalls;
|
|
40895
41110
|
searchMemoryMisses;
|
|
40896
41111
|
/** Every distinct tool call id this turn has seen, across retries. */
|
|
@@ -40972,6 +41187,10 @@ var TurnTrace = class {
|
|
|
40972
41187
|
notePromptSections(report) {
|
|
40973
41188
|
this.promptSections = Object.fromEntries(report.map((entry) => [entry.id, entry.bytes]));
|
|
40974
41189
|
}
|
|
41190
|
+
/** Assembled text only; the harness's tool schema is outside this measurement. */
|
|
41191
|
+
notePromptWindow(prompt, modelContextTokens) {
|
|
41192
|
+
this.promptWindow = modelContextTokens === void 0 ? void 0 : { promptBytes: Buffer.byteLength(prompt), modelContextTokens };
|
|
41193
|
+
}
|
|
40975
41194
|
/** The prompt left for the harness. Idempotent: a steer resume is the same attempt. */
|
|
40976
41195
|
promptSent() {
|
|
40977
41196
|
this.current.promptSentAt ??= this.now();
|
|
@@ -41081,6 +41300,7 @@ var TurnTrace = class {
|
|
|
41081
41300
|
...this.atAdmission ? { atAdmission: this.atAdmission } : {}
|
|
41082
41301
|
},
|
|
41083
41302
|
...this.promptSections ? { promptSections: this.promptSections } : {},
|
|
41303
|
+
...this.promptWindow ? { promptWindow: this.promptWindow } : {},
|
|
41084
41304
|
...this.searchMemoryCalls !== void 0 ? { searchMemoryCalls: this.searchMemoryCalls, searchMemoryMisses: this.searchMemoryMisses ?? 0 } : {}
|
|
41085
41305
|
};
|
|
41086
41306
|
}
|
|
@@ -41135,7 +41355,7 @@ function formatTurnTraceLine(record5) {
|
|
|
41135
41355
|
return [head, ...record5.attempts.map((attempt) => formatTurnAttempt(attempt))].join("\n ");
|
|
41136
41356
|
}
|
|
41137
41357
|
function turnTraceDirectory(runtimeDir) {
|
|
41138
|
-
return
|
|
41358
|
+
return resolve32(runtimeDir, "turn-traces");
|
|
41139
41359
|
}
|
|
41140
41360
|
var TURN_TRACE_RETENTION_DAYS = 7;
|
|
41141
41361
|
function traceFileName(date) {
|
|
@@ -41152,7 +41372,7 @@ var TurnTraceFile = class {
|
|
|
41152
41372
|
this.options = options;
|
|
41153
41373
|
}
|
|
41154
41374
|
path(now2 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))()) {
|
|
41155
|
-
return
|
|
41375
|
+
return resolve32(this.directory, traceFileName(now2));
|
|
41156
41376
|
}
|
|
41157
41377
|
write(record5) {
|
|
41158
41378
|
this.tail = this.tail.catch(() => void 0).then(async () => {
|
|
@@ -41176,7 +41396,7 @@ var TurnTraceFile = class {
|
|
|
41176
41396
|
this.prunedDay = day;
|
|
41177
41397
|
const cutoff = traceFileName(new Date(now2.getTime() - TURN_TRACE_RETENTION_DAYS * 864e5));
|
|
41178
41398
|
const names = await readdir7(this.directory).catch(() => []);
|
|
41179
|
-
await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm12(
|
|
41399
|
+
await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm12(resolve32(this.directory, name), { force: true })));
|
|
41180
41400
|
}
|
|
41181
41401
|
};
|
|
41182
41402
|
|
|
@@ -41224,7 +41444,7 @@ var WarmTranscript = class {
|
|
|
41224
41444
|
};
|
|
41225
41445
|
|
|
41226
41446
|
// apps/body/dist/monolith-room-turn.js
|
|
41227
|
-
var
|
|
41447
|
+
var ROOM_PROMPT_BACKSTOP_MS = TURN_BACKSTOP_MS;
|
|
41228
41448
|
function isRoomMcpPermissionRequest(request, mountedServers = ROOM_MOUNTED_MCP_SERVERS, hostServers = CODE_OWNED_HOST_MCP_NAMES) {
|
|
41229
41449
|
if (isHostMcpPermissionRequest(request, hostServers))
|
|
41230
41450
|
return false;
|
|
@@ -41288,6 +41508,14 @@ function deviceGrantResumePrompt(device, earlierReply) {
|
|
|
41288
41508
|
].join(" ");
|
|
41289
41509
|
}
|
|
41290
41510
|
function resumePrompt(item) {
|
|
41511
|
+
if (item.systemEvent?.kind === "squire-approval-decided") {
|
|
41512
|
+
return [
|
|
41513
|
+
`This is Trusty Squire's answer to the approval you were waiting on: ${item.body}.`,
|
|
41514
|
+
"Your paused work resumes now.",
|
|
41515
|
+
"If it was approved, continue exactly where you left off with Trusty Squire; do not ask the person to approve again, and do not restart the task.",
|
|
41516
|
+
"If it was denied, stop that Trusty Squire action and say plainly what you cannot do."
|
|
41517
|
+
].join(" ");
|
|
41518
|
+
}
|
|
41291
41519
|
if (item.systemEvent?.kind === "connector-offer-decided") {
|
|
41292
41520
|
return [
|
|
41293
41521
|
`This is the answer to your connector offer: ${item.body}.`,
|
|
@@ -41344,6 +41572,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
41344
41572
|
* and the terminal receipt is posted on a path that may run after it.
|
|
41345
41573
|
*/
|
|
41346
41574
|
turnMetrics = {};
|
|
41575
|
+
turnUsage = new TurnUsageAccumulator();
|
|
41347
41576
|
/** OpenRouter providers this activation pinned, in order (C92). */
|
|
41348
41577
|
pinnedProviders = [];
|
|
41349
41578
|
/** The one provider re-pinned after an empty completion, until the session ends. */
|
|
@@ -41385,7 +41614,10 @@ var MonolithRoomTurnLoop = class {
|
|
|
41385
41614
|
generationId: call.generationId,
|
|
41386
41615
|
target: "squire",
|
|
41387
41616
|
...resourceCallFacts({ method: "tools/call", params: { name: call.tool, arguments: call.args } }, "squire")
|
|
41388
|
-
})).allowed, options.config.operatorHome ??
|
|
41617
|
+
})).allowed, options.config.operatorHome ?? homedir17(), void 0, (decision2) => {
|
|
41618
|
+
options.api.execute("postSquireApprovalDecision", { roomId: options.roomId, ...decision2 }).catch(() => {
|
|
41619
|
+
});
|
|
41620
|
+
});
|
|
41389
41621
|
this.options = { ...options, api: this.commandContext.bind(options.api) };
|
|
41390
41622
|
options.grantRunner?.register(options.roomId, {
|
|
41391
41623
|
workspaceId: options.workspaceId,
|
|
@@ -41420,7 +41652,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
41420
41652
|
...this.sessionScratchDir ? { scratch: this.sessionScratchDir } : {},
|
|
41421
41653
|
...this.sessionStateDirs.length ? { harnessStateDirs: this.sessionStateDirs } : {},
|
|
41422
41654
|
maskPaths: [
|
|
41423
|
-
...credentialMaskPaths(this.options.config.sandboxMaskPaths, this.options.config.operatorHome ??
|
|
41655
|
+
...credentialMaskPaths(this.options.config.sandboxMaskPaths, this.options.config.operatorHome ?? homedir17()),
|
|
41424
41656
|
...siblingAgentMaskPaths(runtimeDirectory(this.options.runtime.supervisorRoot, this.options.runtime.agent.publicKey))
|
|
41425
41657
|
]
|
|
41426
41658
|
};
|
|
@@ -41523,10 +41755,10 @@ var MonolithRoomTurnLoop = class {
|
|
|
41523
41755
|
* Missing numbers are omitted rather than zeroed.
|
|
41524
41756
|
*/
|
|
41525
41757
|
async captureTurnMetrics() {
|
|
41526
|
-
const
|
|
41758
|
+
const { model: _model, ...usage2 } = this.turnUsage.usage ?? {};
|
|
41527
41759
|
const promptBytes = this.client?.lastPromptBytes;
|
|
41528
41760
|
return {
|
|
41529
|
-
...usage2
|
|
41761
|
+
...usage2,
|
|
41530
41762
|
...promptBytes ? { promptBytes } : {}
|
|
41531
41763
|
};
|
|
41532
41764
|
}
|
|
@@ -41668,7 +41900,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
41668
41900
|
effort: selectionEffort,
|
|
41669
41901
|
fastMode: configuration.fastMode
|
|
41670
41902
|
};
|
|
41671
|
-
const operatorHome = this.options.config.operatorHome ??
|
|
41903
|
+
const operatorHome = this.options.config.operatorHome ?? homedir17();
|
|
41672
41904
|
const registryHostDeclarations = registryMcpHostDeclarations(configuration.registryMcpRoutes, this.commandContext.path, this.options.config.registryMcpBrokerSocket);
|
|
41673
41905
|
const mountedHostRoutes = [...grantedHostRoutes, ...Object.keys(registryHostDeclarations)];
|
|
41674
41906
|
const squireScope = {
|
|
@@ -41802,6 +42034,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
41802
42034
|
agentCommand: harnessLabel,
|
|
41803
42035
|
piHome: agentEnv.PI_CODING_AGENT_DIR,
|
|
41804
42036
|
piCommand: agentEnv.PI_ACP_PI_COMMAND ?? process.env.PI_ACP_PI_COMMAND,
|
|
42037
|
+
agentEnv,
|
|
41805
42038
|
servers: [...servers, ...grantedRouteServers]
|
|
41806
42039
|
});
|
|
41807
42040
|
const mountedServers = [
|
|
@@ -42013,6 +42246,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
42013
42246
|
const api = this.options.api;
|
|
42014
42247
|
this.busy = true;
|
|
42015
42248
|
this.turnMetrics = {};
|
|
42249
|
+
this.turnUsage = new TurnUsageAccumulator();
|
|
42016
42250
|
const trace = this.beginTurnTrace(item.id);
|
|
42017
42251
|
const institutionalContextFetch = startInstitutionalContextFetch(api, this.options.roomId);
|
|
42018
42252
|
let statsStartedAt = 0;
|
|
@@ -42033,8 +42267,8 @@ var MonolithRoomTurnLoop = class {
|
|
|
42033
42267
|
let timer;
|
|
42034
42268
|
const stats = statsPromise && remaining > 0 ? await Promise.race([
|
|
42035
42269
|
statsPromise,
|
|
42036
|
-
new Promise((
|
|
42037
|
-
timer = setTimeout(() =>
|
|
42270
|
+
new Promise((resolve43) => {
|
|
42271
|
+
timer = setTimeout(() => resolve43(void 0), remaining);
|
|
42038
42272
|
})
|
|
42039
42273
|
]).finally(() => {
|
|
42040
42274
|
if (timer)
|
|
@@ -42095,7 +42329,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
42095
42329
|
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) => ({
|
|
42096
42330
|
id: message.id,
|
|
42097
42331
|
authorId: message.authorId,
|
|
42098
|
-
line:
|
|
42332
|
+
line: transcriptMessagePrompt(names.get(message.authorId) ?? message.authorId.slice(0, 12), message.body, message.attachments, message.id)
|
|
42099
42333
|
}));
|
|
42100
42334
|
const command = this.commandContext.current;
|
|
42101
42335
|
const grantDecision = command?.action === "resume";
|
|
@@ -42133,6 +42367,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
42133
42367
|
}
|
|
42134
42368
|
});
|
|
42135
42369
|
trace.notePromptSections(assembled.report);
|
|
42370
|
+
trace.notePromptWindow(assembled.text, this.modelContextTokens);
|
|
42136
42371
|
this.commandContext.notePromptSections([
|
|
42137
42372
|
...this.sessionPromptSectionIds,
|
|
42138
42373
|
...assembled.report.map((section) => section.id)
|
|
@@ -42156,14 +42391,14 @@ var MonolithRoomTurnLoop = class {
|
|
|
42156
42391
|
try {
|
|
42157
42392
|
stream.beginRun();
|
|
42158
42393
|
trace.promptSent();
|
|
42159
|
-
result2 = await this.client.sessionPrompt(this.sessionId, nextPrompt,
|
|
42394
|
+
result2 = await this.turnUsage.measure({ agentEnv: this.agentEnv, sessionId: this.sessionId }, () => this.client.sessionPrompt(this.sessionId, nextPrompt, ROOM_PROMPT_BACKSTOP_MS, (delta, full, currentRun) => {
|
|
42160
42395
|
trace.firstModelOutput();
|
|
42161
42396
|
stream.onChunk(delta, full, currentRun);
|
|
42162
42397
|
}, void 0, (calls) => {
|
|
42163
42398
|
trace.toolCalls(calls);
|
|
42164
42399
|
if (openedACorner(openCornerToolCall(calls)))
|
|
42165
42400
|
liveCornerOpened = true;
|
|
42166
|
-
});
|
|
42401
|
+
}));
|
|
42167
42402
|
} catch (error) {
|
|
42168
42403
|
promptError = error;
|
|
42169
42404
|
}
|
|
@@ -42306,8 +42541,8 @@ var MonolithRoomTurnLoop = class {
|
|
|
42306
42541
|
void finishTrace("cancelled").catch(() => void 0);
|
|
42307
42542
|
return;
|
|
42308
42543
|
}
|
|
42309
|
-
if (liveCornerOpened && error instanceof
|
|
42310
|
-
console.log(`[thin-core] monolith Room ${this.options.roomId} turn ${item.id}:
|
|
42544
|
+
if (liveCornerOpened && error instanceof AcpTurnBackstopError) {
|
|
42545
|
+
console.log(`[thin-core] monolith Room ${this.options.roomId} turn ${item.id}: turn_backstop after opening a corner; the work continues in the corner`);
|
|
42311
42546
|
this.options.onCornerOpened?.();
|
|
42312
42547
|
const lastRun = liveStream?.lastRunText ?? "";
|
|
42313
42548
|
const streamed = isPureRetryNarration(lastRun) ? "" : durableReplyText(lastRun);
|
|
@@ -42330,8 +42565,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
42330
42565
|
void finishTrace("complete").catch(() => void 0);
|
|
42331
42566
|
return;
|
|
42332
42567
|
}
|
|
42333
|
-
if (isSilentPromptTimeout(error))
|
|
42334
|
-
await this.discardSession().catch(() => void 0);
|
|
42335
42568
|
await liveStream?.retract().catch((retractError) => {
|
|
42336
42569
|
console.error(`[thin-core] monolith Room ${this.options.roomId} draft retract failed:`, retractError);
|
|
42337
42570
|
});
|
|
@@ -42422,6 +42655,13 @@ function openCornerToolCall(calls) {
|
|
|
42422
42655
|
function openedACorner(call) {
|
|
42423
42656
|
return !!call && isCompletedToolCall(call);
|
|
42424
42657
|
}
|
|
42658
|
+
function transcriptMessagePrompt(author, body, attachments, messageId) {
|
|
42659
|
+
return [
|
|
42660
|
+
`[message id: ${messageId}]`,
|
|
42661
|
+
`${author}: ${body.trim() || "(shared attachments)"}`,
|
|
42662
|
+
...attachmentMarkerLines(attachments)
|
|
42663
|
+
].join("\n");
|
|
42664
|
+
}
|
|
42425
42665
|
function roomMessagePrompt(author, body, attachments, delivered, harnessAcceptsImages = true, messageId) {
|
|
42426
42666
|
const message = body.trim() || "(shared attachments)";
|
|
42427
42667
|
const rendered = author ? `${author}: ${message}` : message;
|
|
@@ -42434,9 +42674,9 @@ function roomMessagePrompt(author, body, attachments, delivered, harnessAcceptsI
|
|
|
42434
42674
|
|
|
42435
42675
|
// apps/body/dist/corner-github-auth.js
|
|
42436
42676
|
import { chmod as chmod9, mkdir as mkdir23, writeFile as writeFile19 } from "node:fs/promises";
|
|
42437
|
-
import { delimiter as delimiter2, resolve as
|
|
42677
|
+
import { delimiter as delimiter2, resolve as resolve33 } from "node:path";
|
|
42438
42678
|
async function installCornerGitHubWrappers(input) {
|
|
42439
|
-
const bin =
|
|
42679
|
+
const bin = resolve33(input.root, "beeline-github-bin");
|
|
42440
42680
|
await mkdir23(bin, { recursive: true, mode: 448 });
|
|
42441
42681
|
const common = {
|
|
42442
42682
|
node: process.execPath,
|
|
@@ -42446,13 +42686,13 @@ async function installCornerGitHubWrappers(input) {
|
|
|
42446
42686
|
featureBranch: input.featureBranch,
|
|
42447
42687
|
targetBranch: input.targetBranch
|
|
42448
42688
|
};
|
|
42449
|
-
await writeLauncher(
|
|
42689
|
+
await writeLauncher(resolve33(bin, "git"), {
|
|
42450
42690
|
...common,
|
|
42451
42691
|
command: input.gitBinary,
|
|
42452
42692
|
launcher: "git"
|
|
42453
42693
|
});
|
|
42454
42694
|
if (input.ghBinary)
|
|
42455
|
-
await writeLauncher(
|
|
42695
|
+
await writeLauncher(resolve33(bin, "gh"), {
|
|
42456
42696
|
...common,
|
|
42457
42697
|
command: input.ghBinary,
|
|
42458
42698
|
launcher: "gh"
|
|
@@ -42546,7 +42786,7 @@ function cornerGitHubCommandRefusal(launcher, argv, featureBranch, targetBranch,
|
|
|
42546
42786
|
}
|
|
42547
42787
|
async function writeLauncher(path, config) {
|
|
42548
42788
|
const source = `#!/usr/bin/env node
|
|
42549
|
-
import { spawnSync } from 'node:child_process';
|
|
42789
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
42550
42790
|
const config = ${JSON.stringify(config)};
|
|
42551
42791
|
const cornerGitHubCommandRefusal = ${cornerGitHubCommandRefusal.toString()};
|
|
42552
42792
|
const authFailure = /(?:authentication failed|bad credentials|could not read username|http(?:\\/\\d(?:\\.\\d)?)? 40[13]|status (?:code )?40[13])/i;
|
|
@@ -42561,7 +42801,28 @@ function resolvePushBranch(source) {
|
|
|
42561
42801
|
return current.status === 0 ? { branch: current.stdout.trim() } : {};
|
|
42562
42802
|
}
|
|
42563
42803
|
const refusal = cornerGitHubCommandRefusal(config.launcher, process.argv.slice(2), config.featureBranch, config.targetBranch, resolvePushBranch);
|
|
42564
|
-
if (refusal) { process.stderr.write(refusal + '\\n'); process.
|
|
42804
|
+
if (refusal) { process.stderr.write(refusal + '\\n'); process.exitCode = 1; }
|
|
42805
|
+
function needsToken(argv) {
|
|
42806
|
+
if (config.launcher === 'gh') return true;
|
|
42807
|
+
const optionsWithValue = new Set(['-C', '-c', '--git-dir', '--work-tree', '--namespace', '--super-prefix', '--config-env']);
|
|
42808
|
+
let index = 0;
|
|
42809
|
+
while (index < argv.length && argv[index].startsWith('-')) {
|
|
42810
|
+
if (argv[index] === '--version' || argv[index] === '--help') return false;
|
|
42811
|
+
index += optionsWithValue.has(argv[index]) ? 2 : 1;
|
|
42812
|
+
}
|
|
42813
|
+
// Unknown commands (including aliases) may contact a remote.
|
|
42814
|
+
const local = new Set([
|
|
42815
|
+
'add', 'am', 'apply', 'bisect', 'blame', 'branch', 'cat-file', 'check-attr',
|
|
42816
|
+
'check-ignore', 'check-ref-format', 'checkout', 'cherry-pick', 'clean', 'commit',
|
|
42817
|
+
'config', 'describe', 'diff', 'diff-files', 'diff-index', 'diff-tree', 'for-each-ref',
|
|
42818
|
+
'format-patch', 'fsck', 'gc', 'grep', 'hash-object', 'help', 'init', 'log', 'ls-files',
|
|
42819
|
+
'ls-tree', 'merge', 'merge-base', 'mv', 'notes', 'rebase', 'reflog', 'reset',
|
|
42820
|
+
'restore', 'rev-list', 'rev-parse', 'revert', 'rm', 'show', 'show-ref', 'stash',
|
|
42821
|
+
'status', 'switch', 'symbolic-ref', 'tag', 'update-index', 'update-ref',
|
|
42822
|
+
'verify-commit', 'verify-tag', 'worktree',
|
|
42823
|
+
]);
|
|
42824
|
+
return !local.has(argv[index]);
|
|
42825
|
+
}
|
|
42565
42826
|
function token() {
|
|
42566
42827
|
let result;
|
|
42567
42828
|
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
@@ -42570,19 +42831,40 @@ function token() {
|
|
|
42570
42831
|
if (attempt < 2) Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 250 * (attempt + 1));
|
|
42571
42832
|
}
|
|
42572
42833
|
process.stderr.write(result.stderr || 'Beeline could not refresh the repository credential.\\n');
|
|
42573
|
-
process.
|
|
42834
|
+
process.exitCode = result.status || 1;
|
|
42835
|
+
return undefined;
|
|
42574
42836
|
}
|
|
42575
|
-
function run(value) {
|
|
42837
|
+
async function run(value) {
|
|
42576
42838
|
const env = { ...process.env, GH_TOKEN: value, GITHUB_TOKEN: value, GIT_TERMINAL_PROMPT: '0' };
|
|
42577
|
-
|
|
42578
|
-
|
|
42579
|
-
|
|
42580
|
-
const
|
|
42581
|
-
|
|
42582
|
-
|
|
42583
|
-
|
|
42584
|
-
|
|
42585
|
-
|
|
42839
|
+
const child = spawn(config.command, process.argv.slice(2), { env, stdio: ['inherit', 'pipe', 'pipe'] });
|
|
42840
|
+
let authenticationFailed = false;
|
|
42841
|
+
// Keep only enough diagnostic overlap to recognize an auth failure across chunks.
|
|
42842
|
+
for (const [source, destination] of [[child.stdout, process.stdout], [child.stderr, process.stderr]]) {
|
|
42843
|
+
let tail = '';
|
|
42844
|
+
source.on('data', (chunk) => {
|
|
42845
|
+
const diagnostic = tail + chunk.toString('utf8');
|
|
42846
|
+
authenticationFailed ||= authFailure.test(diagnostic);
|
|
42847
|
+
tail = diagnostic.slice(-1024);
|
|
42848
|
+
});
|
|
42849
|
+
source.pipe(destination, { end: false });
|
|
42850
|
+
}
|
|
42851
|
+
return new Promise((resolve, reject) => {
|
|
42852
|
+
child.once('error', reject);
|
|
42853
|
+
child.once('close', (status) => resolve({ status, authenticationFailed }));
|
|
42854
|
+
});
|
|
42855
|
+
}
|
|
42856
|
+
if (!refusal) {
|
|
42857
|
+
const authenticated = needsToken(process.argv.slice(2));
|
|
42858
|
+
const value = authenticated ? token() : '';
|
|
42859
|
+
if (value !== undefined) {
|
|
42860
|
+
let result = await run(value);
|
|
42861
|
+
if (authenticated && result.status !== 0 && result.authenticationFailed) {
|
|
42862
|
+
const refreshed = token();
|
|
42863
|
+
if (refreshed !== undefined) result = await run(refreshed);
|
|
42864
|
+
}
|
|
42865
|
+
process.exitCode ??= result.status ?? 1;
|
|
42866
|
+
}
|
|
42867
|
+
}
|
|
42586
42868
|
`;
|
|
42587
42869
|
await writeFile19(path, source, { mode: 448 });
|
|
42588
42870
|
await chmod9(path, 448);
|
|
@@ -42591,29 +42873,29 @@ process.exit(result.status ?? 1);
|
|
|
42591
42873
|
// apps/body/dist/warm-node-modules.js
|
|
42592
42874
|
import { createHash as createHash11, randomUUID as randomUUID11 } from "node:crypto";
|
|
42593
42875
|
import { constants as fsConstants3 } from "node:fs";
|
|
42594
|
-
import { chmod as chmod10, copyFile as copyFile2, link, lstat as lstat4, mkdir as mkdir24, readdir as readdir8, readFile as
|
|
42595
|
-
import { dirname as dirname24, join as join17, resolve as
|
|
42876
|
+
import { chmod as chmod10, copyFile as copyFile2, link, lstat as lstat4, mkdir as mkdir24, readdir as readdir8, readFile as readFile26, readlink as readlink2, rename as rename9, rm as rm13, stat as stat8, symlink as symlink3, utimes } from "node:fs/promises";
|
|
42877
|
+
import { dirname as dirname24, join as join17, resolve as resolve34 } from "node:path";
|
|
42596
42878
|
var STORE_FORMAT = "v1";
|
|
42597
42879
|
var STAGING_PREFIX = ".beeline-warm-";
|
|
42598
42880
|
var STAGING_SWEEP_MS = 24 * 60 * 60 * 1e3;
|
|
42599
42881
|
var WARM_STORE_MAX_ENTRIES = 3;
|
|
42600
42882
|
function sharedNpmCacheDir(supervisorRoot) {
|
|
42601
|
-
return
|
|
42883
|
+
return resolve34(supervisorRoot, "beeline", "npm-cache");
|
|
42602
42884
|
}
|
|
42603
42885
|
function sharedPnpmStoreDir(supervisorRoot) {
|
|
42604
|
-
return
|
|
42886
|
+
return resolve34(supervisorRoot, "beeline", "pnpm-store");
|
|
42605
42887
|
}
|
|
42606
42888
|
function sharedCargoTargetDir(supervisorRoot) {
|
|
42607
|
-
return
|
|
42889
|
+
return resolve34(supervisorRoot, "beeline", "cargo-target");
|
|
42608
42890
|
}
|
|
42609
42891
|
function warmNodeModulesStoreDir(supervisorRoot) {
|
|
42610
|
-
return
|
|
42892
|
+
return resolve34(supervisorRoot, "beeline", "node-modules");
|
|
42611
42893
|
}
|
|
42612
42894
|
function isPlanRefusal(value) {
|
|
42613
42895
|
return "failure" in value;
|
|
42614
42896
|
}
|
|
42615
42897
|
async function readWarmPlan(worktreePath) {
|
|
42616
|
-
const lockfile = await
|
|
42898
|
+
const lockfile = await readFile26(resolve34(worktreePath, "package-lock.json")).catch(() => void 0);
|
|
42617
42899
|
if (!lockfile)
|
|
42618
42900
|
return { failure: "no-lockfile" };
|
|
42619
42901
|
const packages = parseLockfilePackages(lockfile);
|
|
@@ -42652,11 +42934,11 @@ async function seedWarmNodeModules(input) {
|
|
|
42652
42934
|
return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
|
|
42653
42935
|
}
|
|
42654
42936
|
for (const tree of plan.trees) {
|
|
42655
|
-
if (await pathExists(
|
|
42937
|
+
if (await pathExists(resolve34(input.worktreePath, tree))) {
|
|
42656
42938
|
return { reason: "present", key: plan.key };
|
|
42657
42939
|
}
|
|
42658
42940
|
}
|
|
42659
|
-
const entry =
|
|
42941
|
+
const entry = resolve34(input.storeRoot, plan.key);
|
|
42660
42942
|
if (!await isDirectory(entry))
|
|
42661
42943
|
return { reason: "cold", key: plan.key };
|
|
42662
42944
|
const [storeDevice, checkoutDevice] = await Promise.all([
|
|
@@ -42666,19 +42948,19 @@ async function seedWarmNodeModules(input) {
|
|
|
42666
42948
|
if (storeDevice === void 0 || storeDevice !== checkoutDevice) {
|
|
42667
42949
|
return { reason: "cross-device", key: plan.key };
|
|
42668
42950
|
}
|
|
42669
|
-
const staging =
|
|
42951
|
+
const staging = resolve34(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID11()}`);
|
|
42670
42952
|
const placed = [];
|
|
42671
42953
|
const now2 = (input.now ?? Date.now)();
|
|
42672
42954
|
try {
|
|
42673
42955
|
await sweepStaleStaging(input.storeRoot, now2);
|
|
42674
42956
|
await utimes(entry, now2 / 1e3, now2 / 1e3).catch(() => void 0);
|
|
42675
42957
|
for (const tree of plan.trees) {
|
|
42676
|
-
await cloneTree(
|
|
42958
|
+
await cloneTree(resolve34(entry, tree), resolve34(staging, tree), seedFile);
|
|
42677
42959
|
}
|
|
42678
42960
|
for (const tree of plan.trees) {
|
|
42679
|
-
const target =
|
|
42961
|
+
const target = resolve34(input.worktreePath, tree);
|
|
42680
42962
|
await mkdir24(dirname24(target), { recursive: true });
|
|
42681
|
-
await rename9(
|
|
42963
|
+
await rename9(resolve34(staging, tree), target);
|
|
42682
42964
|
placed.push(target);
|
|
42683
42965
|
}
|
|
42684
42966
|
return { reason: "seeded", key: plan.key };
|
|
@@ -42696,11 +42978,11 @@ async function harvestWarmNodeModules(input) {
|
|
|
42696
42978
|
if (isPlanRefusal(plan)) {
|
|
42697
42979
|
return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
|
|
42698
42980
|
}
|
|
42699
|
-
const entry =
|
|
42981
|
+
const entry = resolve34(input.storeRoot, plan.key);
|
|
42700
42982
|
if (await pathExists(entry))
|
|
42701
42983
|
return { reason: "already-warm", key: plan.key };
|
|
42702
42984
|
for (const tree of plan.trees) {
|
|
42703
|
-
if (!await isDirectory(
|
|
42985
|
+
if (!await isDirectory(resolve34(input.worktreePath, tree))) {
|
|
42704
42986
|
return { reason: "no-node-modules", key: plan.key, detail: tree };
|
|
42705
42987
|
}
|
|
42706
42988
|
}
|
|
@@ -42712,12 +42994,12 @@ async function harvestWarmNodeModules(input) {
|
|
|
42712
42994
|
detail: `${missing.length} absent, e.g. ${missing.slice(0, 3).join(", ")}`
|
|
42713
42995
|
};
|
|
42714
42996
|
}
|
|
42715
|
-
const staging =
|
|
42997
|
+
const staging = resolve34(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID11()}`);
|
|
42716
42998
|
try {
|
|
42717
42999
|
await mkdir24(input.storeRoot, { recursive: true, mode: 493 });
|
|
42718
43000
|
await sweepStaleStaging(input.storeRoot, (input.now ?? Date.now)());
|
|
42719
43001
|
for (const tree of plan.trees) {
|
|
42720
|
-
await cloneTree(
|
|
43002
|
+
await cloneTree(resolve34(input.worktreePath, tree), resolve34(staging, tree), harvestFile);
|
|
42721
43003
|
}
|
|
42722
43004
|
await input.onCopied?.();
|
|
42723
43005
|
if (!await stagedTreeIsPublishable(input.worktreePath, staging, plan.key)) {
|
|
@@ -42740,16 +43022,16 @@ async function stagedTreeIsPublishable(worktreePath, staging, key) {
|
|
|
42740
43022
|
return false;
|
|
42741
43023
|
const hidden = join17("node_modules", ".package-lock.json");
|
|
42742
43024
|
const [copied, current] = await Promise.all([
|
|
42743
|
-
|
|
42744
|
-
|
|
43025
|
+
readFile26(resolve34(staging, hidden)).catch(() => void 0),
|
|
43026
|
+
readFile26(resolve34(worktreePath, hidden)).catch(() => void 0)
|
|
42745
43027
|
]);
|
|
42746
43028
|
if (!copied || !current || !copied.equals(current))
|
|
42747
43029
|
return false;
|
|
42748
43030
|
return (await missingInstalledPackages(worktreePath, staging)).length === 0;
|
|
42749
43031
|
}
|
|
42750
43032
|
async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
|
|
42751
|
-
const wanted = parseLockfilePackages(await
|
|
42752
|
-
const installed = parseLockfilePackages(await
|
|
43033
|
+
const wanted = parseLockfilePackages(await readFile26(resolve34(worktreePath, "package-lock.json")).catch(() => void 0));
|
|
43034
|
+
const installed = parseLockfilePackages(await readFile26(resolve34(treeRoot, "node_modules", ".package-lock.json")).catch(() => void 0));
|
|
42753
43035
|
if (!wanted)
|
|
42754
43036
|
return ["package-lock.json is unreadable"];
|
|
42755
43037
|
if (!installed)
|
|
@@ -42769,7 +43051,7 @@ async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
|
|
|
42769
43051
|
required.push(path);
|
|
42770
43052
|
}
|
|
42771
43053
|
await mapWithLimit(required, INTEGRITY_READ_CONCURRENCY, async (path) => {
|
|
42772
|
-
if (!(path in installed) || !await isInstalledPackage(
|
|
43054
|
+
if (!(path in installed) || !await isInstalledPackage(resolve34(treeRoot, path))) {
|
|
42773
43055
|
missing.push(path);
|
|
42774
43056
|
}
|
|
42775
43057
|
});
|
|
@@ -43119,6 +43401,8 @@ var MonolithCornerTurnLoop = class {
|
|
|
43119
43401
|
* and the terminal receipt is posted on a path that may run after it.
|
|
43120
43402
|
*/
|
|
43121
43403
|
turnMetrics = {};
|
|
43404
|
+
turnUsage = new TurnUsageAccumulator();
|
|
43405
|
+
modelContextTokens;
|
|
43122
43406
|
/** OpenRouter providers this activation pinned, in order (C92). */
|
|
43123
43407
|
pinnedProviders = [];
|
|
43124
43408
|
/** Whether the pinned model takes images; `undefined` when the pin did not say. */
|
|
@@ -43178,7 +43462,10 @@ var MonolithCornerTurnLoop = class {
|
|
|
43178
43462
|
generationId: call.generationId,
|
|
43179
43463
|
target: "squire",
|
|
43180
43464
|
...resourceCallFacts({ method: "tools/call", params: { name: call.tool, arguments: call.args } }, "squire")
|
|
43181
|
-
})).allowed, options.config.operatorHome ??
|
|
43465
|
+
})).allowed, options.config.operatorHome ?? homedir18(), void 0, (decision2) => {
|
|
43466
|
+
options.api.execute("postSquireApprovalDecision", { roomId: options.cornerId, ...decision2 }).catch(() => {
|
|
43467
|
+
});
|
|
43468
|
+
});
|
|
43182
43469
|
this.options = { ...options, api: this.commandContext.bind(options.api) };
|
|
43183
43470
|
options.grantRunner?.register(options.cornerId, {
|
|
43184
43471
|
workspaceId: options.workspaceId,
|
|
@@ -43266,10 +43553,10 @@ var MonolithCornerTurnLoop = class {
|
|
|
43266
43553
|
* Missing numbers are omitted rather than zeroed.
|
|
43267
43554
|
*/
|
|
43268
43555
|
async captureTurnMetrics() {
|
|
43269
|
-
const
|
|
43556
|
+
const { model: _model, ...usage2 } = this.turnUsage.usage ?? {};
|
|
43270
43557
|
const promptBytes = this.client?.lastPromptBytes;
|
|
43271
43558
|
return {
|
|
43272
|
-
...usage2
|
|
43559
|
+
...usage2,
|
|
43273
43560
|
...promptBytes ? { promptBytes } : {}
|
|
43274
43561
|
};
|
|
43275
43562
|
}
|
|
@@ -43393,7 +43680,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
43393
43680
|
effort: configuration.effort ?? this.options.config.modelSelection?.effort,
|
|
43394
43681
|
fastMode: configuration.fastMode
|
|
43395
43682
|
};
|
|
43396
|
-
const operatorHome = this.options.config.operatorHome ??
|
|
43683
|
+
const operatorHome = this.options.config.operatorHome ?? homedir18();
|
|
43397
43684
|
const registryHostDeclarations = registryMcpHostDeclarations(configuration.registryMcpRoutes, this.commandContext.path, this.options.config.registryMcpBrokerSocket);
|
|
43398
43685
|
const mountedHostRoutes = [...grantedHostRoutes, ...Object.keys(registryHostDeclarations)];
|
|
43399
43686
|
const squireScope = {
|
|
@@ -43466,6 +43753,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
43466
43753
|
CARGO_TARGET_DIR: cargoTargetDir
|
|
43467
43754
|
};
|
|
43468
43755
|
this.agentEnv = agentEnv;
|
|
43756
|
+
this.modelContextTokens = await modelContextWindowTokens(selection.model, agentEnv.PI_CODING_AGENT_DIR);
|
|
43469
43757
|
const agentArgs = agentArgsWithModelSelection({
|
|
43470
43758
|
kind: this.options.config.agentKind,
|
|
43471
43759
|
command,
|
|
@@ -43605,6 +43893,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
43605
43893
|
agentCommand: harnessLabel,
|
|
43606
43894
|
piHome: agentEnv.PI_CODING_AGENT_DIR,
|
|
43607
43895
|
piCommand: agentEnv.PI_ACP_PI_COMMAND ?? process.env.PI_ACP_PI_COMMAND,
|
|
43896
|
+
agentEnv,
|
|
43608
43897
|
servers: [...servers, ...grantedRouteServers]
|
|
43609
43898
|
});
|
|
43610
43899
|
const persona = configuration.soul ?? self?.soul;
|
|
@@ -43693,7 +43982,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
43693
43982
|
briefRevision: restore.brief?.revision
|
|
43694
43983
|
}),
|
|
43695
43984
|
...this.options.config.agentHomeRoot && this.options.config.agentKind && !AGENT_SKILL_DIRS.includes(this.options.config.agentKind) ? [
|
|
43696
|
-
`This harness has no verified native skill discovery. Read the release-managed review procedure at ${
|
|
43985
|
+
`This harness has no verified native skill discovery. Read the release-managed review procedure at ${resolve35(this.options.config.agentHomeRoot, "codex", "skills", "beeline-review", "SKILL.md")} before the verdict.`
|
|
43697
43986
|
] : []
|
|
43698
43987
|
].join("\n");
|
|
43699
43988
|
} catch {
|
|
@@ -43825,8 +44114,8 @@ var MonolithCornerTurnLoop = class {
|
|
|
43825
44114
|
let timer;
|
|
43826
44115
|
const stats = statsPromise && remaining > 0 ? await Promise.race([
|
|
43827
44116
|
statsPromise,
|
|
43828
|
-
new Promise((
|
|
43829
|
-
timer = setTimeout(() =>
|
|
44117
|
+
new Promise((resolve43) => {
|
|
44118
|
+
timer = setTimeout(() => resolve43(void 0), remaining);
|
|
43830
44119
|
})
|
|
43831
44120
|
]).finally(() => {
|
|
43832
44121
|
if (timer)
|
|
@@ -43856,6 +44145,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
43856
44145
|
throw new Error("corner turn stopped for daemon handoff");
|
|
43857
44146
|
this.busy = true;
|
|
43858
44147
|
this.turnMetrics = {};
|
|
44148
|
+
this.turnUsage = new TurnUsageAccumulator();
|
|
43859
44149
|
await this.syncBranch();
|
|
43860
44150
|
const [conversation, roster, restored, activeReviewerInstruction, institutionalContext, memberCorners] = await trace.measure("context-fetch", () => Promise.all([
|
|
43861
44151
|
api.execute("getRoomConversation", {
|
|
@@ -43883,7 +44173,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
43883
44173
|
const delivered = this.attachmentDir && allAttachments.length ? await deliverAttachments(allAttachments, join18(this.attachmentDir, requestId.replace(/[^\w-]/g, "_")), this.options.fetchImpl) : [];
|
|
43884
44174
|
const briefFileLines = await Promise.all((restored.brief?.attachments ?? []).map(async (file, index) => {
|
|
43885
44175
|
const entry = delivered.find((item) => item.attachment === briefAttachments[index]);
|
|
43886
|
-
const verified = entry?.path && createHash12("sha256").update(await
|
|
44176
|
+
const verified = entry?.path && createHash12("sha256").update(await readFile27(entry.path)).digest("hex") === file.sha256;
|
|
43887
44177
|
return `- ${file.title} (${file.purpose}; ${file.required ? "required" : "optional"}; sha256 ${file.sha256}): ${verified ? entry.path : "UNAVAILABLE OR CONTENT MISMATCH"}`;
|
|
43888
44178
|
}));
|
|
43889
44179
|
const missingRequiredBriefFile = (restored.brief?.attachments ?? []).some((file, index) => file.required && briefFileLines[index]?.includes("UNAVAILABLE OR CONTENT MISMATCH"));
|
|
@@ -43891,18 +44181,20 @@ var MonolithCornerTurnLoop = class {
|
|
|
43891
44181
|
const requestedBy = requester && !requester.name && names.get(requester.pubkey) ? { ...requester, name: names.get(requester.pubkey) } : requester;
|
|
43892
44182
|
if (requestedBy)
|
|
43893
44183
|
this.currentTurn = { requestId, requester: requestedBy };
|
|
43894
|
-
const transcriptRows = conversation.items.filter((message) => message.id !== requestId && message.id !== sourceMessageId && message.body.trim()).slice(-120).map((message) => ({
|
|
44184
|
+
const transcriptRows = conversation.items.filter((message) => message.id !== requestId && message.id !== sourceMessageId && (message.body.trim() || message.attachments?.length)).slice(-120).map((message) => ({
|
|
43895
44185
|
id: message.id,
|
|
43896
44186
|
authorId: message.authorId,
|
|
43897
44187
|
line: [
|
|
43898
44188
|
...message.type === "message" ? [`[message id: ${message.id}]`] : [],
|
|
43899
|
-
`${names.get(message.authorId) ?? "Beeline"} [${message.type}]: ${message.body}
|
|
44189
|
+
`${names.get(message.authorId) ?? "Beeline"} [${message.type}]: ${message.body.trim() ? message.body : "(shared attachments)"}`,
|
|
44190
|
+
...attachmentMarkerLines(message.attachments ?? [])
|
|
43900
44191
|
].join("\n")
|
|
43901
44192
|
}));
|
|
43902
44193
|
const buildPrompt = () => {
|
|
43903
44194
|
const transcript = this.warmTranscript.select(this.sessionId, transcriptRows, this.agent.publicKey);
|
|
43904
44195
|
const assembled = assembleTurnPrompt({
|
|
43905
44196
|
surface: this.sessionSurface,
|
|
44197
|
+
modelContextTokens: this.modelContextTokens,
|
|
43906
44198
|
sessionPrefix: this.turnSessionPrefix,
|
|
43907
44199
|
objective: this.options.objective,
|
|
43908
44200
|
...restored.titleGenerated && restored.title ? { generatedTitle: restored.title } : {},
|
|
@@ -43928,6 +44220,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
43928
44220
|
}
|
|
43929
44221
|
});
|
|
43930
44222
|
trace.notePromptSections(assembled.report);
|
|
44223
|
+
trace.notePromptWindow(assembled.text, this.modelContextTokens);
|
|
43931
44224
|
this.commandContext.notePromptSections([
|
|
43932
44225
|
...this.sessionPromptSectionIds,
|
|
43933
44226
|
...assembled.report.map((section) => section.id)
|
|
@@ -44042,7 +44335,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
44042
44335
|
narrationRunBoundary = 0;
|
|
44043
44336
|
currentNarrationRun = "";
|
|
44044
44337
|
trace.promptSent();
|
|
44045
|
-
return this.client.sessionPrompt(this.sessionId, promptWithImages(prompt, attachmentImageBlocks(delivered, this.acceptsImages())),
|
|
44338
|
+
return this.turnUsage.measure({ agentEnv: this.agentEnv, sessionId: this.sessionId }, () => this.client.sessionPrompt(this.sessionId, promptWithImages(prompt, attachmentImageBlocks(delivered, this.acceptsImages())), ROOM_PROMPT_BACKSTOP_MS, (delta, full, currentRun, runs) => {
|
|
44046
44339
|
trace.firstModelOutput();
|
|
44047
44340
|
if (runs) {
|
|
44048
44341
|
completedNarrationRuns = runs.slice(narrationRunBoundary);
|
|
@@ -44059,7 +44352,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
44059
44352
|
trace.toolCalls(calls);
|
|
44060
44353
|
publishToolCalls(calls, true);
|
|
44061
44354
|
publishToolCalls(calls, false, lastNarratedToolCall);
|
|
44062
|
-
});
|
|
44355
|
+
}));
|
|
44063
44356
|
};
|
|
44064
44357
|
let loginRetryUsed = false;
|
|
44065
44358
|
const runPrompt = async (prompt = buildPrompt()) => {
|
|
@@ -44205,7 +44498,7 @@ ${deviceGrantResumePrompt(grantedDevice, result.agentText)}`);
|
|
|
44205
44498
|
await trace.measure("publish", () => stream.settle(repeatedNarration ? "" : durableReply, durableReply && !repeatedNarration ? {
|
|
44206
44499
|
...requestedById ? { triggerMessageId: requestId } : {}
|
|
44207
44500
|
} : {}));
|
|
44208
|
-
}, { priority: "interactive", roomKey:
|
|
44501
|
+
}, { priority: "interactive", roomKey: this.options.parentRoomId });
|
|
44209
44502
|
}, (error) => console.error(`[thin-core] corner ${cornerId} receipt heartbeat failed:`, error));
|
|
44210
44503
|
if (laneUpgraded) {
|
|
44211
44504
|
void finishTrace("complete").catch(() => void 0);
|
|
@@ -44235,8 +44528,6 @@ ${deviceGrantResumePrompt(grantedDevice, result.agentText)}`);
|
|
|
44235
44528
|
void finishTrace("complete").catch(() => void 0);
|
|
44236
44529
|
return;
|
|
44237
44530
|
}
|
|
44238
|
-
if (isSilentPromptTimeout(error))
|
|
44239
|
-
await this.discardSession().catch(() => void 0);
|
|
44240
44531
|
const reason = distillTurnFailureReason(error);
|
|
44241
44532
|
startTraceStats();
|
|
44242
44533
|
await api.execute("postAgentTurnReceipt", {
|
|
@@ -44312,7 +44603,7 @@ ${deviceGrantResumePrompt(grantedDevice, result.agentText)}`);
|
|
|
44312
44603
|
} catch (error) {
|
|
44313
44604
|
if (attempt === 2)
|
|
44314
44605
|
throw error;
|
|
44315
|
-
await new Promise((
|
|
44606
|
+
await new Promise((resolve43) => setTimeout(resolve43, 250 * (attempt + 1)));
|
|
44316
44607
|
}
|
|
44317
44608
|
}
|
|
44318
44609
|
if (!token)
|
|
@@ -44924,7 +45215,7 @@ function cornerStartConfigKey(repository, objective) {
|
|
|
44924
45215
|
function cornerRepositoryCacheDir(supervisorRoot, remote) {
|
|
44925
45216
|
const normalizedRemote = roomCheckoutRemote(remote);
|
|
44926
45217
|
const repositoryHash = createHash13("sha256").update(normalizedRemote).digest("hex").slice(0, 24);
|
|
44927
|
-
return
|
|
45218
|
+
return resolve36(supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
|
|
44928
45219
|
}
|
|
44929
45220
|
function isStandingCornerStartFault(error) {
|
|
44930
45221
|
const text2 = error instanceof Error ? error.message : String(error);
|
|
@@ -44933,11 +45224,11 @@ function isStandingCornerStartFault(error) {
|
|
|
44933
45224
|
async function materializeCornerWorktree(input) {
|
|
44934
45225
|
const remote = roomCheckoutRemote(input.remote);
|
|
44935
45226
|
const gitCommonDir = cornerRepositoryCacheDir(input.supervisorRoot, remote);
|
|
44936
|
-
const path =
|
|
45227
|
+
const path = resolve36(input.supervisorRoot, "beeline", "corners", input.cornerId);
|
|
44937
45228
|
await mkdir26(dirname26(gitCommonDir), { recursive: true, mode: 448 });
|
|
44938
45229
|
await mkdir26(dirname26(path), { recursive: true, mode: 448 });
|
|
44939
45230
|
const authEnv = githubGitEnv(input.token);
|
|
44940
|
-
if (!existsSync8(
|
|
45231
|
+
if (!existsSync8(resolve36(gitCommonDir, "HEAD"))) {
|
|
44941
45232
|
await execFileAsync8("git", ["clone", "--bare", remote, gitCommonDir], {
|
|
44942
45233
|
env: authEnv,
|
|
44943
45234
|
maxBuffer: 4 * 1024 * 1024
|
|
@@ -44960,7 +45251,7 @@ async function materializeCornerWorktree(input) {
|
|
|
44960
45251
|
return false;
|
|
44961
45252
|
throw error;
|
|
44962
45253
|
});
|
|
44963
|
-
if (!existsSync8(
|
|
45254
|
+
if (!existsSync8(resolve36(path, ".git"))) {
|
|
44964
45255
|
await rm14(path, { recursive: true, force: true });
|
|
44965
45256
|
await execFileAsync8("git", [
|
|
44966
45257
|
`--git-dir=${gitCommonDir}`,
|
|
@@ -45026,9 +45317,9 @@ async function mapWithConcurrency(values, limit, visit) {
|
|
|
45026
45317
|
}));
|
|
45027
45318
|
}
|
|
45028
45319
|
async function discoverCornerWorktree(supervisorRoot, cornerId) {
|
|
45029
|
-
const cornersRoot =
|
|
45030
|
-
const path =
|
|
45031
|
-
if (dirname26(path) !== cornersRoot || !existsSync8(
|
|
45320
|
+
const cornersRoot = resolve36(supervisorRoot, "beeline", "corners");
|
|
45321
|
+
const path = resolve36(cornersRoot, cornerId);
|
|
45322
|
+
if (dirname26(path) !== cornersRoot || !existsSync8(resolve36(path, ".git")))
|
|
45032
45323
|
return void 0;
|
|
45033
45324
|
const [canonicalRoot, canonicalPath] = await Promise.all([
|
|
45034
45325
|
realpath2(cornersRoot),
|
|
@@ -45040,8 +45331,8 @@ async function discoverCornerWorktree(supervisorRoot, cornerId) {
|
|
|
45040
45331
|
const common = await execFileAsync8("git", ["-C", path, "rev-parse", "--git-common-dir"]).catch(() => void 0);
|
|
45041
45332
|
if (!common)
|
|
45042
45333
|
return void 0;
|
|
45043
|
-
const gitCommonDir =
|
|
45044
|
-
const repositoriesRoot =
|
|
45334
|
+
const gitCommonDir = resolve36(path, common.stdout.trim());
|
|
45335
|
+
const repositoriesRoot = resolve36(supervisorRoot, "beeline", "repositories");
|
|
45045
45336
|
const commonRelative = relative3(repositoriesRoot, gitCommonDir);
|
|
45046
45337
|
if (!commonRelative || commonRelative === ".." || commonRelative.startsWith(`..${sep2}`) || commonRelative.startsWith(sep2)) {
|
|
45047
45338
|
throw new Error(`refusing corner ${cornerId} with git directory outside repository cache`);
|
|
@@ -45049,7 +45340,7 @@ async function discoverCornerWorktree(supervisorRoot, cornerId) {
|
|
|
45049
45340
|
return { path, gitCommonDir };
|
|
45050
45341
|
}
|
|
45051
45342
|
async function localCornerWorktreeIds(supervisorRoot) {
|
|
45052
|
-
const root =
|
|
45343
|
+
const root = resolve36(supervisorRoot, "beeline", "corners");
|
|
45053
45344
|
const entries = await readdir9(root, { withFileTypes: true }).catch((error) => {
|
|
45054
45345
|
if (error.code === "ENOENT")
|
|
45055
45346
|
return [];
|
|
@@ -45139,8 +45430,8 @@ async function originContains(gitCommonDir, head) {
|
|
|
45139
45430
|
}
|
|
45140
45431
|
var execFileAsync8 = promisify8(execFile13);
|
|
45141
45432
|
async function removeCornerScratchWorkspace(input) {
|
|
45142
|
-
const expected =
|
|
45143
|
-
if (
|
|
45433
|
+
const expected = resolve36(input.roomRoot, "scratch");
|
|
45434
|
+
if (resolve36(input.scratchPath) !== expected) {
|
|
45144
45435
|
throw new Error(`refusing to remove scratch outside corner ${input.cornerId}`);
|
|
45145
45436
|
}
|
|
45146
45437
|
await rm14(expected, { recursive: true, force: true });
|
|
@@ -45252,7 +45543,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
45252
45543
|
...fixedWorkspaceCeiling ? { maxLiveSessions: Number(fixedWorkspaceCeiling) } : {},
|
|
45253
45544
|
perRoomLiveSessions: resolvePerRoomLiveSessions(process.env),
|
|
45254
45545
|
workspaceFloor: Number(process.env.BUZZY_BODY_MAX_SESSIONS_FLOOR ?? String(DEFAULT_WORKSPACE_LIVE_SESSIONS_FLOOR)),
|
|
45255
|
-
activeRoomCount: () => this.
|
|
45546
|
+
activeRoomCount: () => this.activeRoomCount(),
|
|
45256
45547
|
idleMs: resolveSessionIdleMs(process.env),
|
|
45257
45548
|
maxWarmSessions: resolveMaxWarmSessions(process.env),
|
|
45258
45549
|
reserveInteractiveSlot: true
|
|
@@ -45282,7 +45573,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
45282
45573
|
this.discoveryWakeListener?.();
|
|
45283
45574
|
}
|
|
45284
45575
|
activeRoomCount() {
|
|
45285
|
-
return this.running.size;
|
|
45576
|
+
return new Set([...this.running.keys()].map((id) => this.monolithCornerParents.get(id) ?? id)).size;
|
|
45286
45577
|
}
|
|
45287
45578
|
surfaceHealthSnapshot() {
|
|
45288
45579
|
return this.surfaceHealth.snapshot();
|
|
@@ -45589,13 +45880,13 @@ var RoomRuntimeCoordinator = class {
|
|
|
45589
45880
|
return this.runtime.rooms.find((room) => room.channelId === roomId);
|
|
45590
45881
|
}
|
|
45591
45882
|
roomRoot(roomId) {
|
|
45592
|
-
return this.roomRecord(roomId)?.root ??
|
|
45883
|
+
return this.roomRecord(roomId)?.root ?? resolve36(dirname26(this.configPath), "rooms", roomId);
|
|
45593
45884
|
}
|
|
45594
45885
|
roomAgentHomeRoot(workspaceRoot, required = false) {
|
|
45595
45886
|
const flag = process.env.BUZZY_BODY_ROOM_HOME;
|
|
45596
45887
|
if (!required && flag === "0")
|
|
45597
45888
|
return void 0;
|
|
45598
|
-
const home =
|
|
45889
|
+
const home = resolve36(workspaceRoot, "agent-home");
|
|
45599
45890
|
if (!required && flag !== "1" && !existsSync8(home) && existsSync8(workspaceRoot))
|
|
45600
45891
|
return void 0;
|
|
45601
45892
|
try {
|
|
@@ -45611,8 +45902,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
45611
45902
|
return {
|
|
45612
45903
|
...this.baseConfig,
|
|
45613
45904
|
workspaceRoot,
|
|
45614
|
-
agentPrivateRoot:
|
|
45615
|
-
agentMemoryRoot:
|
|
45905
|
+
agentPrivateRoot: resolve36(workspaceRoot, "agent-private"),
|
|
45906
|
+
agentMemoryRoot: resolve36(dirname26(this.configPath), "memory"),
|
|
45616
45907
|
openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname26(this.configPath)),
|
|
45617
45908
|
turnTraceDir: turnTraceDirectory(dirname26(this.configPath)),
|
|
45618
45909
|
...agentHomeRoot ? { agentHomeRoot } : {}
|
|
@@ -45695,11 +45986,11 @@ var RoomRuntimeCoordinator = class {
|
|
|
45695
45986
|
const remote = roomCheckoutRemote(repository.remote);
|
|
45696
45987
|
const targetBranch = repository.targetBranch || "main";
|
|
45697
45988
|
const checkoutId = createHash13("sha256").update(`${roomId}\0${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
|
|
45698
|
-
const path =
|
|
45989
|
+
const path = resolve36(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
|
|
45699
45990
|
await mkdir26(dirname26(path), { recursive: true, mode: 448 });
|
|
45700
45991
|
const token = remote.startsWith("https://github.com/") ? await this.parentRepositoryToken(roomId) : void 0;
|
|
45701
45992
|
const env = token ? githubGitEnv(token.token) : process.env;
|
|
45702
|
-
if (!existsSync8(
|
|
45993
|
+
if (!existsSync8(resolve36(path, ".git"))) {
|
|
45703
45994
|
await execFileAsync8("git", ["clone", "--no-checkout", remote, path], {
|
|
45704
45995
|
env,
|
|
45705
45996
|
maxBuffer: 4 * 1024 * 1024
|
|
@@ -45776,7 +46067,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
45776
46067
|
if (!objective)
|
|
45777
46068
|
throw new Error("corner has no authoritative objective fact");
|
|
45778
46069
|
const repositoryBacked = repository.resolution === "repository" && restore.lane !== "no_code";
|
|
45779
|
-
const scratchPath =
|
|
46070
|
+
const scratchPath = resolve36(this.roomRoot(corner.cornerId), "scratch");
|
|
45780
46071
|
if (repositoryBacked && existsSync8(scratchPath) && !restore.featureBranch)
|
|
45781
46072
|
throw new Error("promoted corner has no server-assigned feature branch");
|
|
45782
46073
|
const targetBranch = repositoryBacked ? repository.targetBranch || "main" : void 0;
|
|
@@ -45791,7 +46082,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
45791
46082
|
}) : void 0;
|
|
45792
46083
|
if (worktree && existsSync8(scratchPath))
|
|
45793
46084
|
await this.reapCornerScratch({ path: scratchPath, cornerId: corner.cornerId });
|
|
45794
|
-
const workspacePath = worktree?.path ??
|
|
46085
|
+
const workspacePath = worktree?.path ?? resolve36(this.roomRoot(corner.cornerId), "scratch");
|
|
45795
46086
|
if (!worktree)
|
|
45796
46087
|
await mkdir26(workspacePath, { recursive: true, mode: 448 });
|
|
45797
46088
|
if (worktree && shouldPostInitialCornerWorkingState(restore)) {
|
|
@@ -46114,7 +46405,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
46114
46405
|
throw new Error(`archived corner ${corner.cornerId} has no authoritative repository`);
|
|
46115
46406
|
}
|
|
46116
46407
|
const expectedCommonDir = cornerRepositoryCacheDir(this.runtime.supervisorRoot, repository.remote);
|
|
46117
|
-
if (
|
|
46408
|
+
if (resolve36(discovered.gitCommonDir) !== expectedCommonDir) {
|
|
46118
46409
|
throw new Error(`archived corner ${corner.cornerId} repository cache does not match`);
|
|
46119
46410
|
}
|
|
46120
46411
|
if (!restore.featureBranch) {
|
|
@@ -46465,10 +46756,10 @@ var ThinDaemonCore = class {
|
|
|
46465
46756
|
|
|
46466
46757
|
// apps/body/dist/force-update-journal.js
|
|
46467
46758
|
import { mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync, writeFileSync as writeFileSync5 } from "node:fs";
|
|
46468
|
-
import { resolve as
|
|
46759
|
+
import { resolve as resolve37 } from "node:path";
|
|
46469
46760
|
var NAME = "force-update-interruptions.json";
|
|
46470
46761
|
function pathFor(runtimeDir) {
|
|
46471
|
-
return
|
|
46762
|
+
return resolve37(runtimeDir, NAME);
|
|
46472
46763
|
}
|
|
46473
46764
|
function read(runtimeDir) {
|
|
46474
46765
|
try {
|
|
@@ -46546,17 +46837,17 @@ function staleGeneration(error) {
|
|
|
46546
46837
|
init_launchd();
|
|
46547
46838
|
init_systemd();
|
|
46548
46839
|
import { mkdir as mkdir27, rename as rename10 } from "node:fs/promises";
|
|
46549
|
-
import { dirname as dirname27, resolve as
|
|
46840
|
+
import { dirname as dirname27, resolve as resolve38 } from "node:path";
|
|
46550
46841
|
async function retireRemovedAgent(runtime, options = {}) {
|
|
46551
|
-
const deletedRoot =
|
|
46552
|
-
const target =
|
|
46842
|
+
const deletedRoot = resolve38(runtime.supervisorRoot, "beeline", "deleted-runtimes");
|
|
46843
|
+
const target = resolve38(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
|
|
46553
46844
|
return relocateAgentRuntime(runtime, target, {
|
|
46554
46845
|
...options.run ? { run: options.run } : {}
|
|
46555
46846
|
});
|
|
46556
46847
|
}
|
|
46557
46848
|
async function relocateAgentRuntime(runtime, target, options = {}) {
|
|
46558
46849
|
const source = runtimeDirectory(runtime.supervisorRoot, runtime.agent.publicKey);
|
|
46559
|
-
const destination =
|
|
46850
|
+
const destination = resolve38(target);
|
|
46560
46851
|
if (destination === source || destination.startsWith(`${source}/`)) {
|
|
46561
46852
|
throw new Error("agent runtime destination must be outside the live runtime");
|
|
46562
46853
|
}
|
|
@@ -46579,8 +46870,8 @@ init_self_update();
|
|
|
46579
46870
|
init_systemd();
|
|
46580
46871
|
|
|
46581
46872
|
// apps/body/dist/release-status.js
|
|
46582
|
-
import { readFile as
|
|
46583
|
-
import { resolve as
|
|
46873
|
+
import { readFile as readFile28, readdir as readdir10, rename as rename11, writeFile as writeFile21 } from "node:fs/promises";
|
|
46874
|
+
import { resolve as resolve39 } from "node:path";
|
|
46584
46875
|
var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
|
|
46585
46876
|
var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
|
|
46586
46877
|
var SOURCE_SHA = /^[0-9a-f]{7,64}$/;
|
|
@@ -46597,7 +46888,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
|
|
|
46597
46888
|
pid: options.pid ?? process.pid,
|
|
46598
46889
|
readyAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString()
|
|
46599
46890
|
};
|
|
46600
|
-
const target =
|
|
46891
|
+
const target = resolve39(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
|
|
46601
46892
|
const temporary = `${target}.${status.pid}.tmp`;
|
|
46602
46893
|
await writeFile21(temporary, `${JSON.stringify(status, null, 2)}
|
|
46603
46894
|
`, { mode: 384 });
|
|
@@ -46607,7 +46898,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
|
|
|
46607
46898
|
|
|
46608
46899
|
// apps/body/dist/scratch-sweep.js
|
|
46609
46900
|
import { lstat as lstat5, readdir as readdir11, rmdir as rmdir2, unlink as unlink9 } from "node:fs/promises";
|
|
46610
|
-
import { resolve as
|
|
46901
|
+
import { resolve as resolve40 } from "node:path";
|
|
46611
46902
|
var DEFAULT_SCRATCH_TTL_HOURS = 72;
|
|
46612
46903
|
var NEVER_SWEEP_SUBDIR_NAMES = new Set(HOME_SUBDIRS.filter((name) => name !== "tmp"));
|
|
46613
46904
|
function scratchTtlMs(env = process.env) {
|
|
@@ -46616,7 +46907,7 @@ function scratchTtlMs(env = process.env) {
|
|
|
46616
46907
|
return (Number.isFinite(hours) && hours > 0 ? hours : DEFAULT_SCRATCH_TTL_HOURS) * 60 * 60 * 1e3;
|
|
46617
46908
|
}
|
|
46618
46909
|
async function discoverAttachScratchRoots(runtimeDir) {
|
|
46619
|
-
const roomsDir =
|
|
46910
|
+
const roomsDir = resolve40(runtimeDir, "rooms");
|
|
46620
46911
|
let entries;
|
|
46621
46912
|
try {
|
|
46622
46913
|
entries = await readdir11(roomsDir, { withFileTypes: true });
|
|
@@ -46627,7 +46918,7 @@ async function discoverAttachScratchRoots(runtimeDir) {
|
|
|
46627
46918
|
for (const entry of entries) {
|
|
46628
46919
|
if (!entry.isDirectory())
|
|
46629
46920
|
continue;
|
|
46630
|
-
const home =
|
|
46921
|
+
const home = resolve40(roomsDir, entry.name, "agent-home");
|
|
46631
46922
|
const stats = await lstat5(home).catch(() => void 0);
|
|
46632
46923
|
if (stats?.isDirectory())
|
|
46633
46924
|
roots.push(home);
|
|
@@ -46646,7 +46937,7 @@ async function removeStaleFiles(dir, cutoffMs, protectNamesHere) {
|
|
|
46646
46937
|
for (const entry of entries) {
|
|
46647
46938
|
if (protectNamesHere && NEVER_SWEEP_SUBDIR_NAMES.has(entry.name))
|
|
46648
46939
|
continue;
|
|
46649
|
-
const path =
|
|
46940
|
+
const path = resolve40(dir, entry.name);
|
|
46650
46941
|
const stats = await lstat5(path).catch(() => void 0);
|
|
46651
46942
|
if (!stats || stats.isSymbolicLink())
|
|
46652
46943
|
continue;
|
|
@@ -46731,7 +47022,7 @@ async function runAgentRuntime(configPath, host, signal) {
|
|
|
46731
47022
|
BUZZ_DEV_MCP_BIN: runtime.mcpBinary
|
|
46732
47023
|
};
|
|
46733
47024
|
const config = loadBodyConfig({
|
|
46734
|
-
workspaceRoot:
|
|
47025
|
+
workspaceRoot: resolve41(runtimeDir, "workspace"),
|
|
46735
47026
|
llmEnvFile: runtime.llmEnvFile,
|
|
46736
47027
|
env,
|
|
46737
47028
|
agent
|
|
@@ -47021,7 +47312,7 @@ async function runAgentRuntime(configPath, host, signal) {
|
|
|
47021
47312
|
return exitReason ?? lifecycle.stopReason ?? "stopped";
|
|
47022
47313
|
}
|
|
47023
47314
|
function registryBrokerSocketPath(home, agentId) {
|
|
47024
|
-
return join19(home ??
|
|
47315
|
+
return join19(home ?? homedir19(), ".beeline", "registry-mcp-broker", `${process.pid}-${agentId.slice(0, 8)}.sock`);
|
|
47025
47316
|
}
|
|
47026
47317
|
function interruptHostedAgent(agent) {
|
|
47027
47318
|
agent.lifecycle.quiesce("force-update");
|
|
@@ -47591,7 +47882,7 @@ async function main() {
|
|
|
47591
47882
|
const roomId = roomFlag >= 0 ? args[roomFlag + 1] : void 0;
|
|
47592
47883
|
if (!configPath || !roomId)
|
|
47593
47884
|
throw new Error("corner-read-token requires --config and --room");
|
|
47594
|
-
const activated = await activateDaemonTransport(
|
|
47885
|
+
const activated = await activateDaemonTransport(resolve42(configPath));
|
|
47595
47886
|
if (!activated)
|
|
47596
47887
|
throw new Error("corner-read-token requires monolith transport");
|
|
47597
47888
|
const credential = await activated.client.execute("getRoomGitHubToken", { roomId });
|
|
@@ -47646,7 +47937,7 @@ async function main() {
|
|
|
47646
47937
|
}
|
|
47647
47938
|
if (!configPath && !args.includes("--machine"))
|
|
47648
47939
|
throw new Error("daemon requires --machine, or --config <runtime.json> for one agent");
|
|
47649
|
-
const { reason, lifecycle } = await runMachineHelper(configPath ? { configPaths: [
|
|
47940
|
+
const { reason, lifecycle } = await runMachineHelper(configPath ? { configPaths: [resolve42(configPath)] } : {});
|
|
47650
47941
|
daemonLifecycle = lifecycle;
|
|
47651
47942
|
lifecycle.exit(reason);
|
|
47652
47943
|
return;
|