usebeeline 0.0.104 → 0.0.106
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 +1 -1
- package/dist/usebeeline.mjs +644 -59
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -141,7 +141,7 @@ Two MCP surfaces are mounted into every agent session.
|
|
|
141
141
|
| ------------------------------------------------------ | --------------- | ------------------------------------------------------------- |
|
|
142
142
|
| `open_corner` | Top-level Rooms | Open one write-enabled corner with a ≤24-word objective |
|
|
143
143
|
| `pr_checks_status` | Corners | Read checks, human hold, and PR/head-bound merge approval |
|
|
144
|
-
| `
|
|
144
|
+
| `post_artifact` | Everywhere | Upload one file (path or html/bytes) as an attachment |
|
|
145
145
|
| `create_schedule`, `list_schedules`, `delete_schedule` | Everywhere | Run a prompt again later — interval minutes or a 5-field cron |
|
|
146
146
|
| `request_grant` | Everywhere | Ask the owner for reach outside the sandbox |
|
|
147
147
|
| `run_granted_command` | Everywhere | Run a command an approved grant covers, outside the sandbox |
|
package/dist/usebeeline.mjs
CHANGED
|
@@ -3987,7 +3987,7 @@ __export(self_update_exports, {
|
|
|
3987
3987
|
import { createHash as createHash7 } from "node:crypto";
|
|
3988
3988
|
import { constants as fsConstants2 } from "node:fs";
|
|
3989
3989
|
import { access, chmod as chmod5, lstat as lstat3, mkdir as mkdir15, open, readFile as readFile10, rename as rename4, rm as rm6, symlink as symlink3, writeFile as writeFile10 } from "node:fs/promises";
|
|
3990
|
-
import { spawn as
|
|
3990
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
3991
3991
|
import { homedir as homedir9 } from "node:os";
|
|
3992
3992
|
import { dirname as dirname11, join as join9, resolve as resolve22 } from "node:path";
|
|
3993
3993
|
function anchorLayout(rawLibDir) {
|
|
@@ -4137,7 +4137,7 @@ async function fetchText(url, fetchImpl) {
|
|
|
4137
4137
|
}
|
|
4138
4138
|
function run(command, args, timeoutMs) {
|
|
4139
4139
|
return new Promise((resolveRun) => {
|
|
4140
|
-
const child =
|
|
4140
|
+
const child = spawn6(command, args, { stdio: ["ignore", "ignore", "pipe"] });
|
|
4141
4141
|
let stderr = "";
|
|
4142
4142
|
child.stderr?.setEncoding("utf8");
|
|
4143
4143
|
child.stderr?.on("data", (chunk) => {
|
|
@@ -4210,7 +4210,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
4210
4210
|
}
|
|
4211
4211
|
await writeFile10(tempArchive, Buffer.concat(chunks), { mode: 384 });
|
|
4212
4212
|
const entries = (await new Promise((resolveList, rejectList) => {
|
|
4213
|
-
const child =
|
|
4213
|
+
const child = spawn6("tar", ["-tzf", tempArchive], { stdio: ["ignore", "pipe", "inherit"] });
|
|
4214
4214
|
let out = "";
|
|
4215
4215
|
child.stdout?.on("data", (chunk) => {
|
|
4216
4216
|
out += chunk.toString("utf8");
|
|
@@ -6898,14 +6898,8 @@ var PI_ACP_HARNESS = /(^|[/\\])pi-acp(?:\.[a-z]+)?$/i;
|
|
|
6898
6898
|
function isPiAcpHarness(agentLabel) {
|
|
6899
6899
|
return Boolean(agentLabel && PI_ACP_HARNESS.test(agentLabel));
|
|
6900
6900
|
}
|
|
6901
|
-
function
|
|
6902
|
-
|
|
6903
|
-
return text2;
|
|
6904
|
-
const stripped = text2.replace(/\r?\n$/, "");
|
|
6905
|
-
return stripped || text2;
|
|
6906
|
-
}
|
|
6907
|
-
function normalizeStreamDelta(text2, agentLabel) {
|
|
6908
|
-
return agentLabel && PI_ACP_HARNESS.test(agentLabel) ? withoutOneTrailingLineEnding(text2) : text2;
|
|
6901
|
+
function normalizeStreamDelta(text2, _agentLabel) {
|
|
6902
|
+
return text2;
|
|
6909
6903
|
}
|
|
6910
6904
|
function agentMessageRuns(updates, agentLabel) {
|
|
6911
6905
|
const runs = [];
|
|
@@ -8162,6 +8156,534 @@ async function syncAgentModelCatalog(input) {
|
|
|
8162
8156
|
}
|
|
8163
8157
|
}
|
|
8164
8158
|
|
|
8159
|
+
// apps/body/dist/connector-squire.js
|
|
8160
|
+
import { execFile, spawn as spawn2 } from "node:child_process";
|
|
8161
|
+
var REMOTE_LOGIN_BINARIES = ["xvfb-run", "Xvfb", "x11vnc", "websockify", "cloudflared"];
|
|
8162
|
+
var SQUIRE_CONNECT_PACKAGE = "@trusty-squire/mcp";
|
|
8163
|
+
var defaultShellRunner = (command, args) => new Promise((resolve31) => {
|
|
8164
|
+
execFile(command, [...args], { timeout: 12e4, maxBuffer: 4 * 1024 * 1024, encoding: "utf8" }, (error, stdout6, stderr) => {
|
|
8165
|
+
const code = error?.code;
|
|
8166
|
+
resolve31({
|
|
8167
|
+
code: typeof code === "number" ? code : error ? 1 : 0,
|
|
8168
|
+
stdout: String(stdout6 ?? ""),
|
|
8169
|
+
stderr: String(stderr ?? "")
|
|
8170
|
+
});
|
|
8171
|
+
});
|
|
8172
|
+
});
|
|
8173
|
+
var CONNECT_TIMEOUT_MS = 3e5;
|
|
8174
|
+
var defaultStreamedRunner = (command, args) => new Promise((resolve31) => {
|
|
8175
|
+
const child = spawn2(command, args, {
|
|
8176
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
8177
|
+
});
|
|
8178
|
+
let stdout6 = "";
|
|
8179
|
+
let stderr = "";
|
|
8180
|
+
let resolved = false;
|
|
8181
|
+
const safetyTimer = setTimeout(() => {
|
|
8182
|
+
if (!resolved) {
|
|
8183
|
+
resolved = true;
|
|
8184
|
+
resolve31({ stdout: stdout6, stderr, signIn: void 0, abort: () => {
|
|
8185
|
+
} });
|
|
8186
|
+
}
|
|
8187
|
+
child.kill();
|
|
8188
|
+
}, CONNECT_TIMEOUT_MS);
|
|
8189
|
+
const abort = () => {
|
|
8190
|
+
clearTimeout(safetyTimer);
|
|
8191
|
+
child.kill();
|
|
8192
|
+
};
|
|
8193
|
+
const finish = (result) => {
|
|
8194
|
+
if (!resolved) {
|
|
8195
|
+
resolved = true;
|
|
8196
|
+
clearTimeout(safetyTimer);
|
|
8197
|
+
resolve31(result);
|
|
8198
|
+
}
|
|
8199
|
+
};
|
|
8200
|
+
const checkOutput = () => {
|
|
8201
|
+
const combined = `${stdout6}
|
|
8202
|
+
${stderr}`;
|
|
8203
|
+
const signIn = parseConnectOutput(combined);
|
|
8204
|
+
if (signIn) {
|
|
8205
|
+
finish({ stdout: stdout6, stderr, signIn, abort });
|
|
8206
|
+
}
|
|
8207
|
+
};
|
|
8208
|
+
child.stdout?.on("data", (chunk) => {
|
|
8209
|
+
stdout6 += String(chunk);
|
|
8210
|
+
checkOutput();
|
|
8211
|
+
});
|
|
8212
|
+
child.stderr?.on("data", (chunk) => {
|
|
8213
|
+
stderr += String(chunk);
|
|
8214
|
+
checkOutput();
|
|
8215
|
+
});
|
|
8216
|
+
child.on("close", () => {
|
|
8217
|
+
finish({ stdout: stdout6, stderr, signIn: void 0, abort: () => {
|
|
8218
|
+
} });
|
|
8219
|
+
});
|
|
8220
|
+
child.on("error", () => {
|
|
8221
|
+
finish({ stdout: stdout6, stderr, signIn: void 0, abort: () => {
|
|
8222
|
+
} });
|
|
8223
|
+
});
|
|
8224
|
+
});
|
|
8225
|
+
var step = (label, status, reason) => ({
|
|
8226
|
+
label,
|
|
8227
|
+
status,
|
|
8228
|
+
...reason ? { reason } : {}
|
|
8229
|
+
});
|
|
8230
|
+
function binaryExists(binary) {
|
|
8231
|
+
return new Promise((resolve31) => {
|
|
8232
|
+
execFile("sh", ["-c", `command -v ${JSON.stringify(binary)}`], (error, stdout6) => {
|
|
8233
|
+
const path = String(stdout6 ?? "").trim();
|
|
8234
|
+
resolve31({ binary, found: !error && path.length > 0, ...path ? { path } : {} });
|
|
8235
|
+
});
|
|
8236
|
+
});
|
|
8237
|
+
}
|
|
8238
|
+
async function checkRemoteLoginPrerequisites(probe = binaryExists) {
|
|
8239
|
+
return Promise.all(REMOTE_LOGIN_BINARIES.map(probe));
|
|
8240
|
+
}
|
|
8241
|
+
function missingPrerequisiteStep(checks) {
|
|
8242
|
+
const missing = checks.filter((check) => !check.found).map((check) => check.binary);
|
|
8243
|
+
return step("remote sign-in prerequisites", "failed", `missing on this helper: ${missing.join(", ")}`);
|
|
8244
|
+
}
|
|
8245
|
+
function parseConnectOutput(output) {
|
|
8246
|
+
const url = output.match(/https:\/\/[^\s"'<>]+/)?.[0];
|
|
8247
|
+
if (!url)
|
|
8248
|
+
return void 0;
|
|
8249
|
+
if (/oauth|authorize/i.test(url) || /oauth/i.test(output)) {
|
|
8250
|
+
return { method: "oauth", url };
|
|
8251
|
+
}
|
|
8252
|
+
if (/novnc|vnc\.html|remote|stream/i.test(url) || /novnc|remote login|vnc/i.test(output)) {
|
|
8253
|
+
return { method: "streamed-page", url };
|
|
8254
|
+
}
|
|
8255
|
+
return { method: "streamed-page", url };
|
|
8256
|
+
}
|
|
8257
|
+
async function installedSquireVersion(run2) {
|
|
8258
|
+
const probe = await run2("npx", ["-y", SQUIRE_CONNECT_PACKAGE, "--version"]);
|
|
8259
|
+
const version = probe.stdout.match(/\d+\.\d+\.\d+[^\s]*/)?.[0];
|
|
8260
|
+
return version;
|
|
8261
|
+
}
|
|
8262
|
+
function parseSignedInAs(output) {
|
|
8263
|
+
return output.match(/signed in as ([^\s,;]+)/i)?.[1];
|
|
8264
|
+
}
|
|
8265
|
+
async function installSquire(options) {
|
|
8266
|
+
const run2 = options.run ?? defaultShellRunner;
|
|
8267
|
+
const streamRun = options.streamRun ?? defaultStreamedRunner;
|
|
8268
|
+
const steps = [step("helper reached", "done")];
|
|
8269
|
+
const emit = () => options.onProgress?.([...steps]);
|
|
8270
|
+
const push = (next) => {
|
|
8271
|
+
steps.push(next);
|
|
8272
|
+
emit();
|
|
8273
|
+
};
|
|
8274
|
+
const fail = (reason) => {
|
|
8275
|
+
steps.push(step("waiting for sign-in", "pending"));
|
|
8276
|
+
emit();
|
|
8277
|
+
return { status: "error", steps, errorMessage: reason };
|
|
8278
|
+
};
|
|
8279
|
+
emit();
|
|
8280
|
+
const checks = await checkRemoteLoginPrerequisites(options.probeBinary);
|
|
8281
|
+
if (checks.some((check) => !check.found)) {
|
|
8282
|
+
push(missingPrerequisiteStep(checks));
|
|
8283
|
+
return fail("this helper cannot host the remote sign-in surface");
|
|
8284
|
+
}
|
|
8285
|
+
push(step("remote sign-in prerequisites", "done"));
|
|
8286
|
+
const install = await streamRun("xvfb-run", [
|
|
8287
|
+
"-a",
|
|
8288
|
+
"npx",
|
|
8289
|
+
"-y",
|
|
8290
|
+
SQUIRE_CONNECT_PACKAGE,
|
|
8291
|
+
"connect",
|
|
8292
|
+
"--force-relogin=google",
|
|
8293
|
+
"--target=codex"
|
|
8294
|
+
]);
|
|
8295
|
+
if (!install.signIn) {
|
|
8296
|
+
const stderr = install.stderr.trim();
|
|
8297
|
+
push(step("trusty-squire installed", "failed", stderr || "connect printed no sign-in URL"));
|
|
8298
|
+
return fail(stderr || "the trusty-squire connect command printed no sign-in surface");
|
|
8299
|
+
}
|
|
8300
|
+
const version = await installedSquireVersion(run2);
|
|
8301
|
+
push(step(`trusty-squire${version ? ` ${version}` : ""} installed`, "done"));
|
|
8302
|
+
const signIn = install.signIn;
|
|
8303
|
+
const signedInAs = parseSignedInAs(`${install.stdout}
|
|
8304
|
+
${install.stderr}`);
|
|
8305
|
+
push(step("waiting for sign-in", "done"));
|
|
8306
|
+
const pair = await pairSquire(options.mcp, options.workspaceId);
|
|
8307
|
+
if (!pair.ok) {
|
|
8308
|
+
push(step("paired to workspace", "failed", pair.reason));
|
|
8309
|
+
return {
|
|
8310
|
+
status: "installing",
|
|
8311
|
+
steps,
|
|
8312
|
+
signIn,
|
|
8313
|
+
...version ? { squireVersion: version } : {},
|
|
8314
|
+
...signedInAs ? { signedInAs } : {}
|
|
8315
|
+
};
|
|
8316
|
+
}
|
|
8317
|
+
push(step("paired to workspace", "done"));
|
|
8318
|
+
return {
|
|
8319
|
+
status: "connected",
|
|
8320
|
+
steps,
|
|
8321
|
+
signIn,
|
|
8322
|
+
...version ? { squireVersion: version } : {},
|
|
8323
|
+
...signedInAs ? { signedInAs } : {}
|
|
8324
|
+
};
|
|
8325
|
+
}
|
|
8326
|
+
async function pairSquire(mcp, _workspaceId) {
|
|
8327
|
+
if (!mcp)
|
|
8328
|
+
return { ok: false, reason: "the Squire MCP surface is not mounted on this helper" };
|
|
8329
|
+
try {
|
|
8330
|
+
await mcp.call("list_credentials", { fields: "summary" });
|
|
8331
|
+
return { ok: true };
|
|
8332
|
+
} catch (error) {
|
|
8333
|
+
return { ok: false, reason: error instanceof Error ? error.message : String(error) };
|
|
8334
|
+
}
|
|
8335
|
+
}
|
|
8336
|
+
function asRecord(value) {
|
|
8337
|
+
return value && typeof value === "object" ? value : {};
|
|
8338
|
+
}
|
|
8339
|
+
function asArray(value) {
|
|
8340
|
+
return Array.isArray(value) ? value : [];
|
|
8341
|
+
}
|
|
8342
|
+
function stringList(value) {
|
|
8343
|
+
return asArray(value).filter((entry) => typeof entry === "string");
|
|
8344
|
+
}
|
|
8345
|
+
function numberOrNull(value) {
|
|
8346
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
8347
|
+
}
|
|
8348
|
+
function vaultConnectionMeta(raw) {
|
|
8349
|
+
const record3 = asRecord(raw);
|
|
8350
|
+
const reference = String(record3.reference ?? record3.id ?? "");
|
|
8351
|
+
return {
|
|
8352
|
+
reference,
|
|
8353
|
+
service: typeof record3.service === "string" ? record3.service : null,
|
|
8354
|
+
label: String(record3.label ?? record3.service ?? reference),
|
|
8355
|
+
fieldNames: stringList(record3.field_names ?? record3.fieldNames),
|
|
8356
|
+
allowedHosts: stringList(record3.allowed_hosts ?? record3.allowedHosts ?? record3.login_hosts),
|
|
8357
|
+
createdAt: numberOrNull(record3.created_at ?? record3.createdAt) ?? 0,
|
|
8358
|
+
stale: record3.stale === true,
|
|
8359
|
+
state: record3.state === "error" ? "error" : "active"
|
|
8360
|
+
};
|
|
8361
|
+
}
|
|
8362
|
+
async function readVault(mcp) {
|
|
8363
|
+
const result = asRecord(await mcp.call("list_credentials"));
|
|
8364
|
+
return asArray(result.credentials ?? result.items ?? result).map(vaultConnectionMeta);
|
|
8365
|
+
}
|
|
8366
|
+
function connectionGrant(raw) {
|
|
8367
|
+
const record3 = asRecord(raw);
|
|
8368
|
+
return {
|
|
8369
|
+
grantId: String(record3.grant_id ?? record3.grantId ?? record3.id ?? ""),
|
|
8370
|
+
credentialRef: String(record3.credential_ref ?? record3.credentialRef ?? record3.reference ?? ""),
|
|
8371
|
+
createdAt: numberOrNull(record3.created_at ?? record3.createdAt) ?? 0,
|
|
8372
|
+
...numberOrNull(record3.revoked_at ?? record3.revokedAt) !== null ? { revokedAt: numberOrNull(record3.revoked_at ?? record3.revokedAt) } : {},
|
|
8373
|
+
...numberOrNull(record3.rate_limit_per_hour) !== null ? { rateLimitPerHour: numberOrNull(record3.rate_limit_per_hour) } : {},
|
|
8374
|
+
...numberOrNull(record3.spend_cap_usd) !== null ? { spendCapUsd: numberOrNull(record3.spend_cap_usd) } : {}
|
|
8375
|
+
};
|
|
8376
|
+
}
|
|
8377
|
+
async function readGrants(mcp, ref) {
|
|
8378
|
+
const result = asRecord(await mcp.call("list_app_access", {}));
|
|
8379
|
+
return asArray(result.grants ?? result.items ?? result).map(connectionGrant).filter((grant) => grant.credentialRef === ref && grant.revokedAt === void 0);
|
|
8380
|
+
}
|
|
8381
|
+
async function revokeGrants(mcp, ref) {
|
|
8382
|
+
const grants = await readGrants(mcp, ref);
|
|
8383
|
+
let revoked = 0;
|
|
8384
|
+
let failed = 0;
|
|
8385
|
+
for (const grant of grants) {
|
|
8386
|
+
try {
|
|
8387
|
+
const result = asRecord(await mcp.call("revoke_app_access", { grant_id: grant.grantId }));
|
|
8388
|
+
if (result.revoked === false)
|
|
8389
|
+
failed += 1;
|
|
8390
|
+
else
|
|
8391
|
+
revoked += 1;
|
|
8392
|
+
} catch {
|
|
8393
|
+
failed += 1;
|
|
8394
|
+
}
|
|
8395
|
+
}
|
|
8396
|
+
return { revoked, failed };
|
|
8397
|
+
}
|
|
8398
|
+
|
|
8399
|
+
// apps/body/dist/squire-mcp-client.js
|
|
8400
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
8401
|
+
var INITIALIZE_TIMEOUT_MS = 3e4;
|
|
8402
|
+
var CALL_TIMEOUT_MS = 12e4;
|
|
8403
|
+
var StdioSquireMcpClient = class {
|
|
8404
|
+
options;
|
|
8405
|
+
child;
|
|
8406
|
+
nextId = 1;
|
|
8407
|
+
pending = /* @__PURE__ */ new Map();
|
|
8408
|
+
buffer = "";
|
|
8409
|
+
initialized;
|
|
8410
|
+
closed = false;
|
|
8411
|
+
log;
|
|
8412
|
+
constructor(options = {}) {
|
|
8413
|
+
this.options = options;
|
|
8414
|
+
this.log = options.log ?? (() => {
|
|
8415
|
+
});
|
|
8416
|
+
}
|
|
8417
|
+
/** One Squire MCP tool call; resolves with the tool's parsed result. */
|
|
8418
|
+
async call(tool, args = {}) {
|
|
8419
|
+
await this.ensureSession();
|
|
8420
|
+
const response = await this.request("tools/call", { name: tool, arguments: args });
|
|
8421
|
+
if (response.isError) {
|
|
8422
|
+
const text3 = response.content?.find((entry) => entry.type === "text")?.text ?? "tool error";
|
|
8423
|
+
throw new Error(`${tool} failed: ${text3}`);
|
|
8424
|
+
}
|
|
8425
|
+
const text2 = response.content?.find((entry) => entry.type === "text")?.text;
|
|
8426
|
+
if (typeof text2 !== "string")
|
|
8427
|
+
return response;
|
|
8428
|
+
try {
|
|
8429
|
+
return JSON.parse(text2);
|
|
8430
|
+
} catch {
|
|
8431
|
+
return response;
|
|
8432
|
+
}
|
|
8433
|
+
}
|
|
8434
|
+
/** Tear the session down; safe to call repeatedly. */
|
|
8435
|
+
close() {
|
|
8436
|
+
this.closed = true;
|
|
8437
|
+
this.initialized = void 0;
|
|
8438
|
+
for (const entry of this.pending.values()) {
|
|
8439
|
+
clearTimeout(entry.timer);
|
|
8440
|
+
entry.reject(new Error("Squire MCP session closed"));
|
|
8441
|
+
}
|
|
8442
|
+
this.pending.clear();
|
|
8443
|
+
this.child?.kill();
|
|
8444
|
+
this.child = void 0;
|
|
8445
|
+
}
|
|
8446
|
+
ensureSession() {
|
|
8447
|
+
if (this.closed)
|
|
8448
|
+
throw new Error("Squire MCP client is closed");
|
|
8449
|
+
this.initialized ??= this.initialize().catch((error) => {
|
|
8450
|
+
this.initialized = void 0;
|
|
8451
|
+
throw error;
|
|
8452
|
+
});
|
|
8453
|
+
return this.initialized;
|
|
8454
|
+
}
|
|
8455
|
+
initialize() {
|
|
8456
|
+
const child = (this.options.spawn ?? spawn3)(this.options.command ?? "npx", [
|
|
8457
|
+
...this.options.args ?? ["-y", "@trusty-squire/mcp"]
|
|
8458
|
+
]);
|
|
8459
|
+
this.child = child;
|
|
8460
|
+
this.buffer = "";
|
|
8461
|
+
child.stdout.setEncoding("utf8");
|
|
8462
|
+
child.stderr.setEncoding("utf8");
|
|
8463
|
+
child.stdout.on("data", (chunk) => this.onData(chunk));
|
|
8464
|
+
child.stderr.on("data", (chunk) => this.log(`squire mcp stderr: ${chunk.trim()}`));
|
|
8465
|
+
child.on("exit", (code) => {
|
|
8466
|
+
this.log(`squire mcp exited (${String(code)})`);
|
|
8467
|
+
this.initialized = void 0;
|
|
8468
|
+
this.child = void 0;
|
|
8469
|
+
for (const entry of this.pending.values()) {
|
|
8470
|
+
clearTimeout(entry.timer);
|
|
8471
|
+
entry.reject(new Error("Squire MCP server exited"));
|
|
8472
|
+
}
|
|
8473
|
+
this.pending.clear();
|
|
8474
|
+
});
|
|
8475
|
+
return this.request("initialize", {
|
|
8476
|
+
protocolVersion: "2024-11-05",
|
|
8477
|
+
capabilities: {},
|
|
8478
|
+
clientInfo: { name: "beeline-helper", version: "1.0.0" }
|
|
8479
|
+
}).then(() => {
|
|
8480
|
+
this.notify("notifications/initialized");
|
|
8481
|
+
});
|
|
8482
|
+
}
|
|
8483
|
+
notify(method, params) {
|
|
8484
|
+
this.child?.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", method, ...params ? { params } : {} })}
|
|
8485
|
+
`);
|
|
8486
|
+
}
|
|
8487
|
+
request(method, params) {
|
|
8488
|
+
const id = this.nextId++;
|
|
8489
|
+
const child = this.child;
|
|
8490
|
+
if (!child)
|
|
8491
|
+
return Promise.reject(new Error("Squire MCP session is not running"));
|
|
8492
|
+
return new Promise((resolve31, reject) => {
|
|
8493
|
+
const timer = setTimeout(() => {
|
|
8494
|
+
this.pending.delete(id);
|
|
8495
|
+
reject(new Error(`${method} timed out`));
|
|
8496
|
+
}, method === "initialize" ? INITIALIZE_TIMEOUT_MS : CALL_TIMEOUT_MS);
|
|
8497
|
+
this.pending.set(id, { resolve: resolve31, reject, timer });
|
|
8498
|
+
child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}
|
|
8499
|
+
`);
|
|
8500
|
+
});
|
|
8501
|
+
}
|
|
8502
|
+
onData(chunk) {
|
|
8503
|
+
this.buffer += chunk;
|
|
8504
|
+
for (; ; ) {
|
|
8505
|
+
const newline = this.buffer.indexOf("\n");
|
|
8506
|
+
if (newline < 0)
|
|
8507
|
+
return;
|
|
8508
|
+
const line = this.buffer.slice(0, newline).trim();
|
|
8509
|
+
this.buffer = this.buffer.slice(newline + 1);
|
|
8510
|
+
if (!line)
|
|
8511
|
+
continue;
|
|
8512
|
+
let message;
|
|
8513
|
+
try {
|
|
8514
|
+
message = JSON.parse(line);
|
|
8515
|
+
} catch {
|
|
8516
|
+
continue;
|
|
8517
|
+
}
|
|
8518
|
+
const id = typeof message.id === "number" ? message.id : void 0;
|
|
8519
|
+
if (id === void 0)
|
|
8520
|
+
continue;
|
|
8521
|
+
const entry = this.pending.get(id);
|
|
8522
|
+
if (!entry)
|
|
8523
|
+
continue;
|
|
8524
|
+
this.pending.delete(id);
|
|
8525
|
+
clearTimeout(entry.timer);
|
|
8526
|
+
if (message.error) {
|
|
8527
|
+
const error = message.error;
|
|
8528
|
+
entry.reject(new Error(error.message ?? "Squire MCP error"));
|
|
8529
|
+
} else {
|
|
8530
|
+
entry.resolve(message.result);
|
|
8531
|
+
}
|
|
8532
|
+
}
|
|
8533
|
+
}
|
|
8534
|
+
};
|
|
8535
|
+
function defaultSquireMcpClient() {
|
|
8536
|
+
return new StdioSquireMcpClient();
|
|
8537
|
+
}
|
|
8538
|
+
|
|
8539
|
+
// apps/body/dist/connector-assignments.js
|
|
8540
|
+
var CONNECTOR_POLL_INTERVAL_MS = 1e4;
|
|
8541
|
+
var ConnectorAssignmentLoop = class {
|
|
8542
|
+
agentId;
|
|
8543
|
+
api;
|
|
8544
|
+
intervalMs;
|
|
8545
|
+
log;
|
|
8546
|
+
install;
|
|
8547
|
+
readVaultFn;
|
|
8548
|
+
revokeGrantsFn;
|
|
8549
|
+
schedule;
|
|
8550
|
+
cancel;
|
|
8551
|
+
timer;
|
|
8552
|
+
started = false;
|
|
8553
|
+
stopped = false;
|
|
8554
|
+
/** One install at a time per connector; other polls skip it. */
|
|
8555
|
+
inFlight = /* @__PURE__ */ new Set();
|
|
8556
|
+
mcp;
|
|
8557
|
+
constructor(options) {
|
|
8558
|
+
this.agentId = options.agentId;
|
|
8559
|
+
this.api = options.api;
|
|
8560
|
+
this.intervalMs = options.intervalMs ?? CONNECTOR_POLL_INTERVAL_MS;
|
|
8561
|
+
this.log = options.log ?? (() => {
|
|
8562
|
+
});
|
|
8563
|
+
this.install = options.install ?? installSquire;
|
|
8564
|
+
this.readVaultFn = options.readVault ?? readVault;
|
|
8565
|
+
this.revokeGrantsFn = options.revokeGrants ?? revokeGrants;
|
|
8566
|
+
this.schedule = options.schedule ?? ((fn, ms) => {
|
|
8567
|
+
const timer = setTimeout(fn, ms);
|
|
8568
|
+
timer.unref?.();
|
|
8569
|
+
return timer;
|
|
8570
|
+
});
|
|
8571
|
+
this.cancel = options.cancel ?? ((handle) => clearTimeout(handle));
|
|
8572
|
+
}
|
|
8573
|
+
start() {
|
|
8574
|
+
if (this.stopped || this.started)
|
|
8575
|
+
return;
|
|
8576
|
+
this.started = true;
|
|
8577
|
+
void this.runOnce();
|
|
8578
|
+
this.timer = this.schedule(() => this.poll(), this.intervalMs);
|
|
8579
|
+
}
|
|
8580
|
+
stop() {
|
|
8581
|
+
this.stopped = true;
|
|
8582
|
+
if (this.timer !== void 0) {
|
|
8583
|
+
this.cancel(this.timer);
|
|
8584
|
+
this.timer = void 0;
|
|
8585
|
+
}
|
|
8586
|
+
}
|
|
8587
|
+
/** One interval tick: poll, then re-arm. */
|
|
8588
|
+
poll() {
|
|
8589
|
+
if (this.stopped)
|
|
8590
|
+
return;
|
|
8591
|
+
void this.runOnce();
|
|
8592
|
+
this.timer = this.schedule(() => this.poll(), this.intervalMs);
|
|
8593
|
+
}
|
|
8594
|
+
/** Drain the queue once; every failure is logged, never raised. */
|
|
8595
|
+
async runOnce() {
|
|
8596
|
+
let assignments;
|
|
8597
|
+
try {
|
|
8598
|
+
const result = await this.api.execute("getConnectorAssignments", { agentId: this.agentId });
|
|
8599
|
+
assignments = result.assignments;
|
|
8600
|
+
} catch (error) {
|
|
8601
|
+
this.log(`connector assignments unavailable: ${describe(error)}`);
|
|
8602
|
+
return;
|
|
8603
|
+
}
|
|
8604
|
+
for (const assignment of assignments) {
|
|
8605
|
+
const key = `${assignment.kind}:${assignment.connectorId}`;
|
|
8606
|
+
if (assignment.kind === "uninstall")
|
|
8607
|
+
continue;
|
|
8608
|
+
if (this.inFlight.has(key))
|
|
8609
|
+
continue;
|
|
8610
|
+
this.inFlight.add(key);
|
|
8611
|
+
void this.handle(assignment).catch((error) => this.log(`connector assignment ${key} failed: ${describe(error)}`)).finally(() => this.inFlight.delete(key));
|
|
8612
|
+
}
|
|
8613
|
+
}
|
|
8614
|
+
squire() {
|
|
8615
|
+
this.mcp ??= defaultSquireMcpClient();
|
|
8616
|
+
return this.mcp;
|
|
8617
|
+
}
|
|
8618
|
+
async handle(assignment) {
|
|
8619
|
+
if (assignment.kind === "install")
|
|
8620
|
+
await this.runInstall(assignment.connectorId);
|
|
8621
|
+
else if (assignment.kind === "sync")
|
|
8622
|
+
await this.runSync();
|
|
8623
|
+
else if (assignment.kind === "revoke-grants")
|
|
8624
|
+
await this.runRevoke(assignment.connectorId, assignment.reference);
|
|
8625
|
+
}
|
|
8626
|
+
/** Install Trusty Squire, reporting every step as it settles. */
|
|
8627
|
+
async runInstall(connectorId) {
|
|
8628
|
+
const report = async (steps) => {
|
|
8629
|
+
try {
|
|
8630
|
+
await this.api.execute("postConnectorStatus", { agentId: this.agentId, connectorId, steps });
|
|
8631
|
+
} catch (error) {
|
|
8632
|
+
this.log(`step report failed: ${describe(error)}`);
|
|
8633
|
+
}
|
|
8634
|
+
};
|
|
8635
|
+
const result = await this.install({
|
|
8636
|
+
workspaceId: this.agentId,
|
|
8637
|
+
mcp: this.squire(),
|
|
8638
|
+
onProgress: report
|
|
8639
|
+
});
|
|
8640
|
+
if (result.status === "error") {
|
|
8641
|
+
await this.api.execute("postConnectorStatus", {
|
|
8642
|
+
agentId: this.agentId,
|
|
8643
|
+
connectorId,
|
|
8644
|
+
steps: result.steps,
|
|
8645
|
+
errorMessage: result.errorMessage
|
|
8646
|
+
});
|
|
8647
|
+
return;
|
|
8648
|
+
}
|
|
8649
|
+
if (result.status === "connected") {
|
|
8650
|
+
await this.api.execute("installConnector", {
|
|
8651
|
+
agentId: this.agentId,
|
|
8652
|
+
connectorId,
|
|
8653
|
+
...result.squireVersion ? { squireVersion: result.squireVersion } : {},
|
|
8654
|
+
...result.signedInAs ? { signedInAs: result.signedInAs } : {},
|
|
8655
|
+
...result.signIn ? { signIn: result.signIn } : {}
|
|
8656
|
+
});
|
|
8657
|
+
await this.reportVault(connectorId);
|
|
8658
|
+
return;
|
|
8659
|
+
}
|
|
8660
|
+
await this.api.execute("postConnectorStatus", {
|
|
8661
|
+
agentId: this.agentId,
|
|
8662
|
+
connectorId,
|
|
8663
|
+
steps: result.steps,
|
|
8664
|
+
...result.squireVersion ? { squireVersion: result.squireVersion } : {},
|
|
8665
|
+
...result.signedInAs ? { signedInAs: result.signedInAs } : {},
|
|
8666
|
+
...result.signIn ? { signIn: result.signIn } : {}
|
|
8667
|
+
});
|
|
8668
|
+
}
|
|
8669
|
+
/** One vault report covers every live trusty-squire connector on this helper. */
|
|
8670
|
+
async runSync() {
|
|
8671
|
+
await this.reportVault();
|
|
8672
|
+
}
|
|
8673
|
+
async runRevoke(connectorId, reference) {
|
|
8674
|
+
const outcome = await this.revokeGrantsFn(this.squire(), reference);
|
|
8675
|
+
this.log(`revoked ${outcome.revoked} grant(s) on ${reference}` + (outcome.failed ? `, ${outcome.failed} failed` : ""));
|
|
8676
|
+
void connectorId;
|
|
8677
|
+
}
|
|
8678
|
+
async reportVault(_connectorId) {
|
|
8679
|
+
const connections = await this.readVaultFn(this.squire());
|
|
8680
|
+
await this.api.execute("postConnectorVault", { agentId: this.agentId, connections });
|
|
8681
|
+
}
|
|
8682
|
+
};
|
|
8683
|
+
function describe(error) {
|
|
8684
|
+
return error instanceof Error ? error.message : String(error);
|
|
8685
|
+
}
|
|
8686
|
+
|
|
8165
8687
|
// packages/api-contract/dist/daemon-operations.js
|
|
8166
8688
|
function isAgentCommand(value) {
|
|
8167
8689
|
if (!value || typeof value !== "object")
|
|
@@ -8185,7 +8707,7 @@ function isAgentCommand(value) {
|
|
|
8185
8707
|
}
|
|
8186
8708
|
|
|
8187
8709
|
// packages/api-contract/dist/artifacts.js
|
|
8188
|
-
var ARTIFACT_MAXIMUM_BYTES =
|
|
8710
|
+
var ARTIFACT_MAXIMUM_BYTES = 25 * 1024 * 1024;
|
|
8189
8711
|
|
|
8190
8712
|
// packages/api-contract/dist/system-events.js
|
|
8191
8713
|
var SERVER_EVENT_KINDS = [
|
|
@@ -8216,12 +8738,12 @@ var wrapper_default = import_websocket.default;
|
|
|
8216
8738
|
|
|
8217
8739
|
// apps/body/dist/runtime.js
|
|
8218
8740
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
8219
|
-
import { execFile } from "node:child_process";
|
|
8741
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
8220
8742
|
import { closeSync, openSync } from "node:fs";
|
|
8221
8743
|
import { mkdir, readFile as readFile2, readdir, rename, stat, writeFile as writeFile2 } from "node:fs/promises";
|
|
8222
8744
|
import { homedir as homedir2 } from "node:os";
|
|
8223
8745
|
import { dirname as dirname2, resolve as resolve6 } from "node:path";
|
|
8224
|
-
import { spawn as
|
|
8746
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
8225
8747
|
import { promisify } from "node:util";
|
|
8226
8748
|
|
|
8227
8749
|
// node_modules/@noble/hashes/_u64.js
|
|
@@ -16344,13 +16866,13 @@ var NegentropyStorageVector = class {
|
|
|
16344
16866
|
let count = last - first;
|
|
16345
16867
|
while (count > 0) {
|
|
16346
16868
|
let it = first;
|
|
16347
|
-
let
|
|
16348
|
-
it +=
|
|
16869
|
+
let step2 = Math.floor(count / 2);
|
|
16870
|
+
it += step2;
|
|
16349
16871
|
if (cmp(arr[it])) {
|
|
16350
16872
|
first = ++it;
|
|
16351
|
-
count -=
|
|
16873
|
+
count -= step2 + 1;
|
|
16352
16874
|
} else {
|
|
16353
|
-
count =
|
|
16875
|
+
count = step2;
|
|
16354
16876
|
}
|
|
16355
16877
|
}
|
|
16356
16878
|
return first;
|
|
@@ -16752,7 +17274,7 @@ function decodeNsec(nsec) {
|
|
|
16752
17274
|
}
|
|
16753
17275
|
|
|
16754
17276
|
// apps/body/dist/runtime.js
|
|
16755
|
-
var execFileAsync = promisify(
|
|
17277
|
+
var execFileAsync = promisify(execFile2);
|
|
16756
17278
|
var DEFAULT_AGENT_IDENTITY_NAME = "beeline-agent";
|
|
16757
17279
|
var DEFAULT_BODY_IDENTITY_NAME = "beeline-body";
|
|
16758
17280
|
var DEFAULT_DAEMON_MONOLITH_BASE_URL = "https://server.usebeeline.app";
|
|
@@ -16942,7 +17464,7 @@ async function launchRuntimeDaemon(configPath, opts = {}) {
|
|
|
16942
17464
|
const entrypoint = opts.entrypoint ?? process.argv[1];
|
|
16943
17465
|
if (!entrypoint)
|
|
16944
17466
|
throw new Error("cannot resolve daemon CLI entrypoint");
|
|
16945
|
-
const child =
|
|
17467
|
+
const child = spawn4(process.execPath, [...opts.execArgv ?? [], entrypoint, "daemon", "--config", resolve6(configPath)], {
|
|
16946
17468
|
cwd: directory,
|
|
16947
17469
|
env: opts.env ?? process.env,
|
|
16948
17470
|
detached: !foreground,
|
|
@@ -17213,7 +17735,7 @@ async function activateDaemonTransport(path, fetchImpl = fetch) {
|
|
|
17213
17735
|
}
|
|
17214
17736
|
|
|
17215
17737
|
// apps/body/dist/room-runtime.js
|
|
17216
|
-
import { execFile as
|
|
17738
|
+
import { execFile as execFile6 } from "node:child_process";
|
|
17217
17739
|
import { createHash as createHash6 } from "node:crypto";
|
|
17218
17740
|
import { existsSync as existsSync4, mkdirSync } from "node:fs";
|
|
17219
17741
|
import { mkdir as mkdir13, rm as rm5 } from "node:fs/promises";
|
|
@@ -17221,7 +17743,7 @@ import { dirname as dirname8, resolve as resolve20 } from "node:path";
|
|
|
17221
17743
|
import { promisify as promisify4 } from "node:util";
|
|
17222
17744
|
|
|
17223
17745
|
// apps/body/dist/grant-runner.js
|
|
17224
|
-
import { execFile as
|
|
17746
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
17225
17747
|
import { createHash as createHash2, randomBytes as randomBytes6 } from "node:crypto";
|
|
17226
17748
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
17227
17749
|
import { createServer } from "node:http";
|
|
@@ -17880,9 +18402,9 @@ var GrantCommandRunner = class {
|
|
|
17880
18402
|
...Object.fromEntries(secrets)
|
|
17881
18403
|
};
|
|
17882
18404
|
const cap = this.options.outputCapBytes ?? GRANT_COMMAND_OUTPUT_CAP_BYTES;
|
|
17883
|
-
const
|
|
18405
|
+
const spawn10 = surfaceAllows(policy.surface, "run-host-command") ? { command: argv[0], args: argv.slice(1) } : roomSandboxCommand(policy, room.cwd, argv);
|
|
17884
18406
|
const outcome = await new Promise((resolveRun) => {
|
|
17885
|
-
const child =
|
|
18407
|
+
const child = execFile3(spawn10.command, spawn10.args, {
|
|
17886
18408
|
cwd: room.cwd,
|
|
17887
18409
|
env,
|
|
17888
18410
|
timeout: this.options.timeoutMs ?? GRANT_COMMAND_TIMEOUT_MS,
|
|
@@ -18318,7 +18840,7 @@ async function runServerCommandIntake(options) {
|
|
|
18318
18840
|
}
|
|
18319
18841
|
|
|
18320
18842
|
// apps/body/dist/monolith-corner-turn.js
|
|
18321
|
-
import { execFile as
|
|
18843
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
18322
18844
|
import { createHash as createHash5 } from "node:crypto";
|
|
18323
18845
|
import { mkdir as mkdir12 } from "node:fs/promises";
|
|
18324
18846
|
import { homedir as homedir7 } from "node:os";
|
|
@@ -18352,6 +18874,9 @@ function isAgentPairingCode(value) {
|
|
|
18352
18874
|
// apps/body/dist/beeline-skill.js
|
|
18353
18875
|
var USING_BEELINE_SKILL_NAME = "using-beeline";
|
|
18354
18876
|
var BEELINE_REVIEW_SKILL_NAME = "beeline-review";
|
|
18877
|
+
function isConfiguredReviewer(agentHandle, reviewerHandle) {
|
|
18878
|
+
return Boolean(agentHandle && reviewerHandle && agentHandle.replace(/^@/, "") === reviewerHandle.replace(/^@/, ""));
|
|
18879
|
+
}
|
|
18355
18880
|
var BEELINE_ROOM_CAPABILITIES = [
|
|
18356
18881
|
"The repository filesystem is read-only in this Room session.",
|
|
18357
18882
|
"You may address any Room member, including another agent, by writing @name in your reply; the server routes that mention to them. Each turn prompt lists the Room members and the exact spelling that tags each one - use those spellings, and never guess or reuse one from an older message.",
|
|
@@ -18359,7 +18884,7 @@ var BEELINE_ROOM_CAPABILITIES = [
|
|
|
18359
18884
|
"Tag the user only when you need a decision or input, or when the task they asked for is finished. Never tag for progress, acknowledgement, or questions the transcript already answers.",
|
|
18360
18885
|
"Every MCP server mounted into this session is approved tool by tool - use operator and host tools freely; the read-only filesystem sandbox is the boundary, not a tool list. Network web search is enabled.",
|
|
18361
18886
|
"Files and photos people share are downloaded for you: read them at the local path named in the prompt (photos may also arrive inline); never fetch the reference URL.",
|
|
18362
|
-
"To create a file (this Room has no other way to write one), 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
|
|
18887
|
+
"To create a file (this Room has no other way to write one), 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 - turning it into a raster image needs a converter, which needs shell, which this Room does not have.",
|
|
18363
18888
|
"To run something later or repeatedly, call beeline-agent create_schedule (interval in minutes or a 5-field cron, optional maxRuns); list_schedules / delete_schedule manage them.",
|
|
18364
18889
|
`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 (${SERVER_EVENT_KINDS.join(", ")}); each one then wakes you for a turn. 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. grant-decided carries the grant id and status and resumes the turn that asked for the grant.`,
|
|
18365
18890
|
"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.",
|
|
@@ -18375,7 +18900,7 @@ var BEELINE_DM_CAPABILITIES = [
|
|
|
18375
18900
|
"The repository filesystem is read-only in this session.",
|
|
18376
18901
|
"Every MCP server mounted into this session is approved tool by tool - use operator and host tools freely; the read-only filesystem sandbox is the boundary, not a tool list. Network web search is enabled.",
|
|
18377
18902
|
"Files and photos people share are downloaded for you: read them at the local path named in the prompt (photos may also arrive inline); never fetch the reference URL.",
|
|
18378
|
-
"To create a file (this Room has no other way to write one), 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
|
|
18903
|
+
"To create a file (this Room has no other way to write one), 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 - turning it into a raster image needs a converter, which needs shell, which this Room does not have.",
|
|
18379
18904
|
"Tag the person only when you need a decision or input, or when the task they asked for is finished.",
|
|
18380
18905
|
"Never claim an action or reply happened unless the prompt or a tool result proves it."
|
|
18381
18906
|
].join(" ");
|
|
@@ -18417,6 +18942,8 @@ description: How to answer inside a Beeline Room.
|
|
|
18417
18942
|
|
|
18418
18943
|
You are answering inside a Room whose filesystem is read-only. ${BEELINE_ROOM_CAPABILITIES}
|
|
18419
18944
|
|
|
18945
|
+
When your corner's pull request is ready, merging is your step: once the configured reviewer approves and tags you, you run \`gh pr merge\` yourself - nothing merges it for you.
|
|
18946
|
+
|
|
18420
18947
|
## Tools and the Workbench
|
|
18421
18948
|
|
|
18422
18949
|
A **tool** is something you can use once a human pairs it; a **key** is the credential that tool holds for that human. You spend a key through the mounted connector and never see the credential itself.
|
|
@@ -18507,7 +19034,7 @@ Then take exactly one action:
|
|
|
18507
19034
|
|
|
18508
19035
|
- FAIL: reply \`@author\` with the confirmed findings to fix.
|
|
18509
19036
|
- PASS: call \`approve_merge\` with the reviewed head SHA, then reply \`@author approved <reviewed sha>, merge\`.
|
|
18510
|
-
-
|
|
19037
|
+
- Approving is your last step as reviewer. The author merges it; you never do, and nothing merges it automatically.
|
|
18511
19038
|
`;
|
|
18512
19039
|
}
|
|
18513
19040
|
|
|
@@ -19177,7 +19704,7 @@ async function prepareRoomAgentHome(input) {
|
|
|
19177
19704
|
await symlink(source, target).catch(() => void 0);
|
|
19178
19705
|
}
|
|
19179
19706
|
const prior = agentHomeProvisionQueues.get(root) ?? Promise.resolve();
|
|
19180
|
-
const provision = prior.catch(() => void 0).then(() => provisionAgentSkillsAndMcp(root, operatorHome, input.skillReleaseId ?? runningBeelineReleaseId(), input.failClosed ?? false, input.sharedSkills ?? [], agentSkillDir(input.agentKind), input.openRouterRouting));
|
|
19707
|
+
const provision = prior.catch(() => void 0).then(() => provisionAgentSkillsAndMcp(root, operatorHome, input.skillReleaseId ?? runningBeelineReleaseId(), input.failClosed ?? false, input.sharedSkills ?? [], agentSkillDir(input.agentKind), input.openRouterRouting, input.isReviewer ?? false));
|
|
19181
19708
|
agentHomeProvisionQueues.set(root, provision);
|
|
19182
19709
|
try {
|
|
19183
19710
|
await provision;
|
|
@@ -19187,10 +19714,10 @@ async function prepareRoomAgentHome(input) {
|
|
|
19187
19714
|
}
|
|
19188
19715
|
return roomAgentHomeEnv(root);
|
|
19189
19716
|
}
|
|
19190
|
-
async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, failClosed, sharedSkills, skillDir, openRouterRouting) {
|
|
19717
|
+
async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, failClosed, sharedSkills, skillDir, openRouterRouting, isReviewer) {
|
|
19191
19718
|
const managedSkills = [
|
|
19192
19719
|
{ name: USING_BEELINE_SKILL_NAME, content: usingBeelineSkillMarkdown(skillReleaseId) },
|
|
19193
|
-
{ name: BEELINE_REVIEW_SKILL_NAME, content: beelineReviewSkillMarkdown(skillReleaseId) }
|
|
19720
|
+
...isReviewer ? [{ name: BEELINE_REVIEW_SKILL_NAME, content: beelineReviewSkillMarkdown(skillReleaseId) }] : []
|
|
19194
19721
|
];
|
|
19195
19722
|
const shared = await resolveSharedSkillSources(operatorHome, sharedSkills);
|
|
19196
19723
|
await provisionManagedSkillsDir(resolve13(root, skillDir, "skills"), managedSkills, shared, sharedSkills.length === 0);
|
|
@@ -20245,9 +20772,9 @@ export default async function (pi) {
|
|
|
20245
20772
|
`;
|
|
20246
20773
|
|
|
20247
20774
|
// apps/body/dist/corner-branch-sync.js
|
|
20248
|
-
import { execFile as
|
|
20775
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
20249
20776
|
import { promisify as promisify2 } from "node:util";
|
|
20250
|
-
var execFileAsync2 = promisify2(
|
|
20777
|
+
var execFileAsync2 = promisify2(execFile4);
|
|
20251
20778
|
async function syncCornerBranch(input) {
|
|
20252
20779
|
const git = input.git ?? (async (args) => (await execFileAsync2("git", ["-C", input.worktreePath, ...args], {
|
|
20253
20780
|
...input.env ? { env: input.env } : {},
|
|
@@ -20426,7 +20953,7 @@ function isMountedMcpToolPermissionRequest(request, mountedServers = ROOM_MOUNTE
|
|
|
20426
20953
|
var AGENT_SURFACE_TOOL_NAMES = [
|
|
20427
20954
|
"open_corner",
|
|
20428
20955
|
"pr_checks_status",
|
|
20429
|
-
"
|
|
20956
|
+
"post_artifact",
|
|
20430
20957
|
"write_scratch_file"
|
|
20431
20958
|
];
|
|
20432
20959
|
var SQUIRE_TITLE_PREFIXES = [
|
|
@@ -21267,7 +21794,7 @@ async function seedWarmNodeModules(input) {
|
|
|
21267
21794
|
for (const target of placed) {
|
|
21268
21795
|
await rm4(target, { recursive: true, force: true }).catch(() => void 0);
|
|
21269
21796
|
}
|
|
21270
|
-
return { reason: "failed", key: plan.key, detail:
|
|
21797
|
+
return { reason: "failed", key: plan.key, detail: describe2(error) };
|
|
21271
21798
|
} finally {
|
|
21272
21799
|
await rm4(staging, { recursive: true, force: true }).catch(() => void 0);
|
|
21273
21800
|
}
|
|
@@ -21310,7 +21837,7 @@ async function harvestWarmNodeModules(input) {
|
|
|
21310
21837
|
} catch (error) {
|
|
21311
21838
|
if (await pathExists(entry))
|
|
21312
21839
|
return { reason: "already-warm", key: plan.key };
|
|
21313
|
-
return { reason: "failed", key: plan.key, detail:
|
|
21840
|
+
return { reason: "failed", key: plan.key, detail: describe2(error) };
|
|
21314
21841
|
} finally {
|
|
21315
21842
|
await rm4(staging, { recursive: true, force: true }).catch(() => void 0);
|
|
21316
21843
|
}
|
|
@@ -21453,7 +21980,7 @@ async function deviceOf(path) {
|
|
|
21453
21980
|
async function isDirectory(path) {
|
|
21454
21981
|
return stat2(path).then((info) => info.isDirectory(), () => false);
|
|
21455
21982
|
}
|
|
21456
|
-
function
|
|
21983
|
+
function describe2(error) {
|
|
21457
21984
|
return error instanceof Error ? error.message : String(error);
|
|
21458
21985
|
}
|
|
21459
21986
|
|
|
@@ -21731,10 +22258,13 @@ var MonolithRoomTurnLoop = class {
|
|
|
21731
22258
|
});
|
|
21732
22259
|
const directMessage = Array.isArray(repositoryState.directParticipants) && repositoryState.directParticipants.length === 2;
|
|
21733
22260
|
await mkdir11(this.options.cwd, { recursive: true });
|
|
21734
|
-
const
|
|
22261
|
+
const selectionModel = configuration.model ?? this.options.config.modelSelection?.model;
|
|
22262
|
+
const selectionEffort = configuration.effort ?? this.options.config.modelSelection?.effort;
|
|
22263
|
+
const selection = selectionModel || selectionEffort ? { model: selectionModel, effort: selectionEffort } : void 0;
|
|
21735
22264
|
const homeOverlay = this.options.config.agentHomeRoot ? await prepareRoomAgentHome({
|
|
21736
22265
|
root: this.options.config.agentHomeRoot,
|
|
21737
22266
|
sharedSkills: this.options.config.sharedSkills ?? [],
|
|
22267
|
+
isReviewer: isConfiguredReviewer(self?.handle, configuration.reviewerHandle),
|
|
21738
22268
|
...this.options.config.agentKind ? { agentKind: this.options.config.agentKind } : {},
|
|
21739
22269
|
...this.options.config.operatorHome ? { operatorHome: this.options.config.operatorHome } : {},
|
|
21740
22270
|
...openRouterRoutingInput(this.options.config, selection, this.options.fetchImpl, {
|
|
@@ -21957,6 +22487,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21957
22487
|
this.busy = true;
|
|
21958
22488
|
const trace = this.beginTurnTrace(item.id);
|
|
21959
22489
|
let liveStream;
|
|
22490
|
+
let liveCornerOpened = false;
|
|
21960
22491
|
try {
|
|
21961
22492
|
if (!this.memberNames.has(item.authorId))
|
|
21962
22493
|
await this.roster().catch(() => void 0);
|
|
@@ -22038,7 +22569,11 @@ ${JSON.stringify((corners.corners ?? []).filter((corner) => !corner.archived))}`
|
|
|
22038
22569
|
result2 = await this.client.sessionPrompt(this.sessionId, nextPrompt, ROOM_PROMPT_INACTIVITY_TIMEOUT_MS, (delta, full) => {
|
|
22039
22570
|
trace.firstModelOutput();
|
|
22040
22571
|
stream.onChunk(delta, full);
|
|
22041
|
-
}, void 0, (calls) =>
|
|
22572
|
+
}, void 0, (calls) => {
|
|
22573
|
+
trace.toolCalls(calls);
|
|
22574
|
+
if (openedACorner(openCornerToolCall(calls)))
|
|
22575
|
+
liveCornerOpened = true;
|
|
22576
|
+
});
|
|
22042
22577
|
} catch (error) {
|
|
22043
22578
|
promptError = error;
|
|
22044
22579
|
}
|
|
@@ -22132,6 +22667,22 @@ ${JSON.stringify((corners.corners ?? []).filter((corner) => !corner.archived))}`
|
|
|
22132
22667
|
await trace.finish("cancelled");
|
|
22133
22668
|
return;
|
|
22134
22669
|
}
|
|
22670
|
+
if (liveCornerOpened && error instanceof AcpRequestTimeoutError && error.inactivity && error.method === "session/prompt") {
|
|
22671
|
+
console.log(`[thin-core] monolith Room ${this.options.roomId} turn ${item.id}: inactivity timeout after opening a corner; the work continues in the corner`);
|
|
22672
|
+
this.options.onCornerOpened?.();
|
|
22673
|
+
await liveStream?.retract().catch((retractError) => {
|
|
22674
|
+
console.error(`[thin-core] monolith Room ${this.options.roomId} draft retract failed:`, retractError);
|
|
22675
|
+
});
|
|
22676
|
+
await api.execute("postAgentTurnReceipt", {
|
|
22677
|
+
agentId: this.agent.publicKey,
|
|
22678
|
+
roomId: this.options.roomId,
|
|
22679
|
+
requestId: item.id,
|
|
22680
|
+
status: "complete",
|
|
22681
|
+
generationId: this.commandContext.generationId
|
|
22682
|
+
});
|
|
22683
|
+
await trace.finish("complete");
|
|
22684
|
+
return;
|
|
22685
|
+
}
|
|
22135
22686
|
await liveStream?.retract().catch((retractError) => {
|
|
22136
22687
|
console.error(`[thin-core] monolith Room ${this.options.roomId} draft retract failed:`, retractError);
|
|
22137
22688
|
});
|
|
@@ -22201,7 +22752,7 @@ function roomMessagePrompt(author, body, attachments, delivered, harnessAcceptsI
|
|
|
22201
22752
|
}
|
|
22202
22753
|
|
|
22203
22754
|
// apps/body/dist/monolith-corner-turn.js
|
|
22204
|
-
var execFileAsync3 = promisify3(
|
|
22755
|
+
var execFileAsync3 = promisify3(execFile5);
|
|
22205
22756
|
var TOOL_ARGUMENT_MAX_BYTES = 1200;
|
|
22206
22757
|
var TOOL_OUTPUT_MAX_BYTES = 3200;
|
|
22207
22758
|
var TOOL_PATH_LIMIT = 12;
|
|
@@ -22592,6 +23143,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
22592
23143
|
const homeOverlay = this.options.config.agentHomeRoot ? await prepareRoomAgentHome({
|
|
22593
23144
|
root: this.options.config.agentHomeRoot,
|
|
22594
23145
|
sharedSkills: this.options.config.sharedSkills ?? [],
|
|
23146
|
+
isReviewer: isConfiguredReviewer(self?.handle, configuration.reviewerHandle),
|
|
22595
23147
|
...this.options.config.agentKind ? { agentKind: this.options.config.agentKind } : {},
|
|
22596
23148
|
...this.options.config.operatorHome ? { operatorHome: this.options.config.operatorHome } : {},
|
|
22597
23149
|
...openRouterRoutingInput(this.options.config, selection, this.options.fetchImpl, {
|
|
@@ -22742,7 +23294,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
22742
23294
|
"Never restate server check or merge notes. On a checks turn, say nothing unless you merge or push a fix, then use one short line. Never merge while approvalPending is true. When approval is pending, wait for the reviewer to tag you. Never merge another pull request. Never create a schedule to poll pr_checks_status or the merge gate: the green transition wakes the reviewer and the reviewer's approval tag wakes you, and tagging any agent other than the configured reviewer cannot clear the gate. If a schedule wakes you in this corner anyway, follow the same rule as a checks turn: say nothing unless you merge, push a fix, or report a genuinely new blocker."
|
|
22743
23295
|
] : [
|
|
22744
23296
|
"This is a chat-only corner with no repository or GitHub workflow.",
|
|
22745
|
-
"Work in this corner's writable workspace. Use write_scratch_file or ordinary tools to create files, then
|
|
23297
|
+
"Work in this corner's writable workspace. Use write_scratch_file or ordinary tools to create files, then post_artifact with the path to send them back to the corner.",
|
|
22746
23298
|
"Do not initialize a repository, create a branch, push, open a pull request, or wait for GitHub checks."
|
|
22747
23299
|
]
|
|
22748
23300
|
].filter(Boolean).join("\n\n")
|
|
@@ -23729,7 +24281,7 @@ async function removeCornerWorktreeAndBranches(worktree) {
|
|
|
23729
24281
|
]);
|
|
23730
24282
|
}
|
|
23731
24283
|
}
|
|
23732
|
-
var execFileAsync4 = promisify4(
|
|
24284
|
+
var execFileAsync4 = promisify4(execFile6);
|
|
23733
24285
|
async function removeCornerScratchWorkspace(input) {
|
|
23734
24286
|
const expected = resolve20(input.roomRoot, "scratch");
|
|
23735
24287
|
if (resolve20(input.scratchPath) !== expected) {
|
|
@@ -24464,13 +25016,13 @@ var ThinDaemonCore = class {
|
|
|
24464
25016
|
};
|
|
24465
25017
|
|
|
24466
25018
|
// apps/body/dist/systemd.js
|
|
24467
|
-
import { execFile as
|
|
25019
|
+
import { execFile as execFile7 } from "node:child_process";
|
|
24468
25020
|
import { mkdir as mkdir14, readFile as readFile9, writeFile as writeFile9 } from "node:fs/promises";
|
|
24469
25021
|
import { homedir as homedir8 } from "node:os";
|
|
24470
25022
|
import { dirname as dirname9, resolve as resolve21 } from "node:path";
|
|
24471
25023
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
24472
25024
|
import { promisify as promisify5 } from "node:util";
|
|
24473
|
-
var execFileAsync5 = promisify5(
|
|
25025
|
+
var execFileAsync5 = promisify5(execFile7);
|
|
24474
25026
|
var DELIBERATE_REMOVAL_EXIT_STATUS = 78;
|
|
24475
25027
|
var DAEMON_DISTRESS_EXIT_STATUS = 77;
|
|
24476
25028
|
var UNKNOWN_AGENT_EXIT_STATUS = 79;
|
|
@@ -24709,9 +25261,10 @@ async function runStartCommand(args, interactiveUi) {
|
|
|
24709
25261
|
}
|
|
24710
25262
|
|
|
24711
25263
|
// apps/body/dist/connect-command.js
|
|
24712
|
-
import { spawn as
|
|
24713
|
-
import { createHash as createHash8 } from "node:crypto";
|
|
25264
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
25265
|
+
import { createHash as createHash8, randomUUID as randomUUID5 } from "node:crypto";
|
|
24714
25266
|
import { chmod as chmod6, mkdir as mkdir16, readFile as readFile11, unlink as unlink2, writeFile as writeFile11 } from "node:fs/promises";
|
|
25267
|
+
import { homedir as homedir10, hostname } from "node:os";
|
|
24715
25268
|
import { dirname as dirname12, resolve as resolve23 } from "node:path";
|
|
24716
25269
|
import { stdin as stdin3, stdout as stdout4 } from "node:process";
|
|
24717
25270
|
|
|
@@ -24796,7 +25349,7 @@ async function verifyProviderKey(input) {
|
|
|
24796
25349
|
}
|
|
24797
25350
|
|
|
24798
25351
|
// apps/body/dist/pair-agent-selection.js
|
|
24799
|
-
import { spawn as
|
|
25352
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
24800
25353
|
import { stdin as stdin2, stdout as stdout3 } from "node:process";
|
|
24801
25354
|
var NO_AGENT_MESSAGE = `No supported ACP-capable coding agent was detected.
|
|
24802
25355
|
Install one of these supported agents:
|
|
@@ -24824,7 +25377,7 @@ async function clackSelectAgent(candidates) {
|
|
|
24824
25377
|
}
|
|
24825
25378
|
async function installAdapter(install, opts) {
|
|
24826
25379
|
await new Promise((resolveInstall, rejectInstall) => {
|
|
24827
|
-
const child =
|
|
25380
|
+
const child = spawn5(install.command, install.args, {
|
|
24828
25381
|
cwd: opts.cwd,
|
|
24829
25382
|
env: opts.env ?? process.env,
|
|
24830
25383
|
stdio: "inherit"
|
|
@@ -25325,7 +25878,29 @@ function parseConnectSubscriptions(value) {
|
|
|
25325
25878
|
...new Set((value ?? "").split(",").map((entry) => entry.trim().toLowerCase()).filter(Boolean))
|
|
25326
25879
|
];
|
|
25327
25880
|
}
|
|
25328
|
-
function
|
|
25881
|
+
async function readMachineId(env = process.env) {
|
|
25882
|
+
const configDir = resolve23(env.XDG_CONFIG_HOME ?? resolve23(homedir10(), ".config"), "beeline");
|
|
25883
|
+
const machineIdPath = resolve23(configDir, "machine-id");
|
|
25884
|
+
let machineId;
|
|
25885
|
+
let machineName = hostname();
|
|
25886
|
+
try {
|
|
25887
|
+
const existing = await readFile11(machineIdPath, "utf8");
|
|
25888
|
+
machineId = existing.trim();
|
|
25889
|
+
if (!/^[0-9a-f-]{32,}$/.test(machineId))
|
|
25890
|
+
throw new Error("invalid persisted machine id");
|
|
25891
|
+
} catch {
|
|
25892
|
+
machineId = randomUUID5();
|
|
25893
|
+
try {
|
|
25894
|
+
await mkdir16(configDir, { recursive: true, mode: 448 });
|
|
25895
|
+
await writeFile11(machineIdPath, `${machineId}
|
|
25896
|
+
`, { mode: 384 });
|
|
25897
|
+
} catch {
|
|
25898
|
+
machineId = createHash8("sha256").update(machineName).digest("hex").slice(0, 36);
|
|
25899
|
+
}
|
|
25900
|
+
}
|
|
25901
|
+
return { machineId, machineName };
|
|
25902
|
+
}
|
|
25903
|
+
function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl, machineInfo) {
|
|
25329
25904
|
const normalizedPairingCode = normalizeAgentPairingCode(pairingCode);
|
|
25330
25905
|
if (!normalizedPairingCode)
|
|
25331
25906
|
throw new Error("invalid pairing code");
|
|
@@ -25340,7 +25915,8 @@ function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl) {
|
|
|
25340
25915
|
// This wizard always finishes the join itself (`finishConnectedAgentPairing`,
|
|
25341
25916
|
// called once the rename prompt below settles), so the claim must not
|
|
25342
25917
|
// join Rooms or announce yet.
|
|
25343
|
-
defer_join: true
|
|
25918
|
+
defer_join: true,
|
|
25919
|
+
...machineInfo ? { machine_id: machineInfo.machineId, machine_name: machineInfo.machineName } : {}
|
|
25344
25920
|
}, fetchImpl);
|
|
25345
25921
|
}
|
|
25346
25922
|
async function renameConnectedAgent(baseUrl, pairingCode, name, fetchImpl) {
|
|
@@ -25419,7 +25995,7 @@ async function writeProviderEnv(selection, agentPubkey) {
|
|
|
25419
25995
|
}
|
|
25420
25996
|
async function runInstalledFinish(binary, grantPath) {
|
|
25421
25997
|
await new Promise((resolveRun, rejectRun) => {
|
|
25422
|
-
const child =
|
|
25998
|
+
const child = spawn7(binary, ["connect-finish", grantPath], {
|
|
25423
25999
|
stdio: ["ignore", "pipe", "pipe"]
|
|
25424
26000
|
});
|
|
25425
26001
|
let diagnostic = "";
|
|
@@ -25470,7 +26046,8 @@ async function runConnectWizard(code, fetchImpl, eventSubscriptions, accessPolic
|
|
|
25470
26046
|
});
|
|
25471
26047
|
const selection = await collectConnectWizard(clackPrompts, loadConnectModelCatalog, fileConnectKeyStore, process.env, (input) => verifyProviderKey({ ...input, fetchImpl }));
|
|
25472
26048
|
const baseUrl = (process.env.BEELINE_AUTH_URL ?? "https://server.usebeeline.app").replace(/\/$/, "");
|
|
25473
|
-
const
|
|
26049
|
+
const machineInfo = await readMachineId(process.env);
|
|
26050
|
+
const claimed = await brassSpinner("Connecting to your Beeline Workspace\u2026", () => requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl, machineInfo), (connectedGrant) => `Connected to ${connectedGrant.workspace_name}`);
|
|
25474
26051
|
const grant = { ...claimed, agent_name: await confirmSeededName(baseUrl, pairingCode, claimed, fetchImpl) };
|
|
25475
26052
|
await finishConnectedAgentPairing(baseUrl, pairingCode, grant.workspace_joined, eventSubscriptions, fetchImpl);
|
|
25476
26053
|
const installedRelease = await brassSpinner("Installing the Beeline daemon\u2026", () => installCurrentRelease(fetchImpl), (release) => `Installed Beeline helper ${release.version}`);
|
|
@@ -25592,7 +26169,7 @@ init_self_update_manifest();
|
|
|
25592
26169
|
|
|
25593
26170
|
// apps/body/dist/managed-update.js
|
|
25594
26171
|
init_self_update();
|
|
25595
|
-
import { spawn as
|
|
26172
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
25596
26173
|
import { mkdir as mkdir18, rm as rm7, stat as stat3, writeFile as writeFile13 } from "node:fs/promises";
|
|
25597
26174
|
import { dirname as dirname14, resolve as resolve25 } from "node:path";
|
|
25598
26175
|
|
|
@@ -26006,7 +26583,7 @@ async function runManagedUpdateWorkerProcess() {
|
|
|
26006
26583
|
if (!entrypoint)
|
|
26007
26584
|
throw new Error("cannot resolve the current Beeline entrypoint");
|
|
26008
26585
|
await new Promise((resolveWorker, rejectWorker) => {
|
|
26009
|
-
const child =
|
|
26586
|
+
const child = spawn8(process.execPath, [entrypoint, "managed-update-worker"], {
|
|
26010
26587
|
detached: true,
|
|
26011
26588
|
env: { ...process.env, BEELINE_INTERNAL_UPDATE_WORKER: "1" },
|
|
26012
26589
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -26360,7 +26937,7 @@ async function clearDaemonStartFailures(runtimeDir) {
|
|
|
26360
26937
|
|
|
26361
26938
|
// apps/body/dist/update-functional-probe.js
|
|
26362
26939
|
import { mkdir as mkdir20, rm as rm9 } from "node:fs/promises";
|
|
26363
|
-
import { homedir as
|
|
26940
|
+
import { homedir as homedir11 } from "node:os";
|
|
26364
26941
|
import { resolve as resolve27 } from "node:path";
|
|
26365
26942
|
var UPDATE_PROBE_SESSION_TIMEOUT_MS = 1e4;
|
|
26366
26943
|
var UPDATE_PROBE_SESSION_OPEN_TIMEOUT_MS = 2e4;
|
|
@@ -26466,7 +27043,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
26466
27043
|
...input.config.agentEnv,
|
|
26467
27044
|
...await prepareRoomAgentHome({
|
|
26468
27045
|
root: homeRoot,
|
|
26469
|
-
operatorHome: input.config.operatorHome ??
|
|
27046
|
+
operatorHome: input.config.operatorHome ?? homedir11(),
|
|
26470
27047
|
sharedSkills: input.config.sharedSkills ?? [],
|
|
26471
27048
|
...input.config.agentKind ? { agentKind: input.config.agentKind } : {},
|
|
26472
27049
|
skillReleaseId: input.releaseId,
|
|
@@ -26487,7 +27064,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
26487
27064
|
let turnCompleted = true;
|
|
26488
27065
|
if (input.config.bwrapPath) {
|
|
26489
27066
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
26490
|
-
const operatorHome = input.config.operatorHome ??
|
|
27067
|
+
const operatorHome = input.config.operatorHome ?? homedir11();
|
|
26491
27068
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
26492
27069
|
await Promise.all(homeStateDirs.map((dir) => mkdir20(dir, { recursive: true })));
|
|
26493
27070
|
spawnCommand = wrapAgentCommand({
|
|
@@ -26638,7 +27215,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
26638
27215
|
}
|
|
26639
27216
|
|
|
26640
27217
|
// apps/body/dist/current-release-probe.js
|
|
26641
|
-
import { spawn as
|
|
27218
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
26642
27219
|
import { dirname as dirname16, join as join10 } from "node:path";
|
|
26643
27220
|
init_self_update();
|
|
26644
27221
|
var CURRENT_RELEASE_PROBE_TIMEOUT_MS = 12e4;
|
|
@@ -26689,7 +27266,7 @@ async function probeReleaseInSubprocess(input) {
|
|
|
26689
27266
|
}
|
|
26690
27267
|
const timeoutMs = input.timeoutMs ?? CURRENT_RELEASE_PROBE_TIMEOUT_MS;
|
|
26691
27268
|
return new Promise((resolve31) => {
|
|
26692
|
-
const child =
|
|
27269
|
+
const child = spawn9(input.execPath ?? process.execPath, [entrypoint, UPDATE_PROBE_COMMAND, "--config", input.runtimeConfigPath], { env: input.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] });
|
|
26693
27270
|
let stdout6 = "";
|
|
26694
27271
|
let stderr = "";
|
|
26695
27272
|
let settled = false;
|
|
@@ -27034,6 +27611,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
27034
27611
|
const scratchSweepTimer = setInterval(() => runScratchSweepLogged(runtimeDir), SCRATCH_SWEEP_INTERVAL_MS);
|
|
27035
27612
|
scratchSweepTimer.unref();
|
|
27036
27613
|
let ready = false;
|
|
27614
|
+
let connectorLoop;
|
|
27037
27615
|
let stoppingStatus = "daemon stopped";
|
|
27038
27616
|
try {
|
|
27039
27617
|
const core = new ThinDaemonCore(runtime, configPath, config, { daemonApi });
|
|
@@ -27106,6 +27684,13 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
27106
27684
|
...runtime.modelSelection ? { runtimeSelection: runtime.modelSelection } : {},
|
|
27107
27685
|
...config.modelUnavailable ? { startupUnavailable: config.modelUnavailable.unavailable.label } : {}
|
|
27108
27686
|
});
|
|
27687
|
+
void readMachineId(process.env).then(({ machineId, machineName }) => daemonApi.execute("postAgentMachineReport", { machineId, machineName }));
|
|
27688
|
+
connectorLoop ??= new ConnectorAssignmentLoop({
|
|
27689
|
+
api: daemonApi,
|
|
27690
|
+
agentId: runtime.agent.publicKey,
|
|
27691
|
+
log: (message) => console.log(`[body] connector: ${message}`)
|
|
27692
|
+
});
|
|
27693
|
+
connectorLoop.start();
|
|
27109
27694
|
},
|
|
27110
27695
|
onProgress: async (status) => {
|
|
27111
27696
|
void drainRollbackAlert(core.activeRoomIds()[0] ?? runtime.rooms[0]?.channelId);
|