usebeeline 0.0.65 → 0.0.69
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 +578 -926
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -3986,10 +3986,10 @@ __export(self_update_exports, {
|
|
|
3986
3986
|
});
|
|
3987
3987
|
import { createHash as createHash6 } from "node:crypto";
|
|
3988
3988
|
import { constants as fsConstants } from "node:fs";
|
|
3989
|
-
import { access, chmod as chmod4, lstat as lstat2, mkdir as
|
|
3989
|
+
import { access, chmod as chmod4, lstat as lstat2, mkdir as mkdir14, open, readFile as readFile9, rename as rename3, rm as rm5, symlink as symlink2, writeFile as writeFile10 } from "node:fs/promises";
|
|
3990
3990
|
import { spawn as spawn4 } from "node:child_process";
|
|
3991
3991
|
import { homedir as homedir9 } from "node:os";
|
|
3992
|
-
import { dirname as
|
|
3992
|
+
import { dirname as dirname10, join as join8, resolve as resolve21 } from "node:path";
|
|
3993
3993
|
function anchorLayout(rawLibDir) {
|
|
3994
3994
|
const libDir = resolve21(rawLibDir);
|
|
3995
3995
|
const segments = libDir.split(/[/\\]/);
|
|
@@ -4028,7 +4028,7 @@ function discoveredBeelineInstallLayout(env = process.env) {
|
|
|
4028
4028
|
return anchorLayout(explicitAnchor);
|
|
4029
4029
|
const explicitBinDir = env.BEELINE_INSTALL_DIR?.trim();
|
|
4030
4030
|
if (explicitBinDir)
|
|
4031
|
-
return anchorLayout(resolve21(
|
|
4031
|
+
return anchorLayout(resolve21(dirname10(resolve21(explicitBinDir)), "lib", "beeline"));
|
|
4032
4032
|
return defaultBeelineInstallLayout(env);
|
|
4033
4033
|
}
|
|
4034
4034
|
function hostPlatformKey() {
|
|
@@ -4039,7 +4039,7 @@ function hostPlatformKey() {
|
|
|
4039
4039
|
return `${os}-${arch}`;
|
|
4040
4040
|
}
|
|
4041
4041
|
function bundleJsonCandidates(bundleDir) {
|
|
4042
|
-
return [
|
|
4042
|
+
return [join8(bundleDir, "lib", "beeline", "bundle.json"), join8(bundleDir, "bundle.json")];
|
|
4043
4043
|
}
|
|
4044
4044
|
async function readBundleJson(bundleDir) {
|
|
4045
4045
|
let raw;
|
|
@@ -4063,7 +4063,7 @@ async function readBundleJson(bundleDir) {
|
|
|
4063
4063
|
}
|
|
4064
4064
|
}
|
|
4065
4065
|
function updateStatePath(layout) {
|
|
4066
|
-
return
|
|
4066
|
+
return join8(layout.releasesRoot, ".state", "update-state.json");
|
|
4067
4067
|
}
|
|
4068
4068
|
async function readUpdateState(layout) {
|
|
4069
4069
|
try {
|
|
@@ -4073,8 +4073,8 @@ async function readUpdateState(layout) {
|
|
|
4073
4073
|
}
|
|
4074
4074
|
}
|
|
4075
4075
|
async function writeUpdateState(layout, state) {
|
|
4076
|
-
await
|
|
4077
|
-
await
|
|
4076
|
+
await mkdir14(join8(layout.releasesRoot, ".state"), { recursive: true });
|
|
4077
|
+
await writeFile10(updateStatePath(layout), `${JSON.stringify(state, null, 2)}
|
|
4078
4078
|
`, "utf8");
|
|
4079
4079
|
}
|
|
4080
4080
|
async function readInstalledBundleIdentity(layout, _state = {}) {
|
|
@@ -4155,7 +4155,7 @@ function run(command, args, timeoutMs) {
|
|
|
4155
4155
|
});
|
|
4156
4156
|
}
|
|
4157
4157
|
function entrypointCandidates(bundleDir) {
|
|
4158
|
-
return [
|
|
4158
|
+
return [join8(bundleDir, BUNDLE_ENTRYPOINT), join8(bundleDir, "beeline-cli.mjs")];
|
|
4159
4159
|
}
|
|
4160
4160
|
async function resolveBundleEntrypoint(bundleDir) {
|
|
4161
4161
|
for (const candidate of entrypointCandidates(bundleDir)) {
|
|
@@ -4177,8 +4177,8 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
4177
4177
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
4178
4178
|
const log2 = opts.logger ?? ((line) => console.log(`[body] self-update: ${line}`));
|
|
4179
4179
|
const releaseId = sanitizeReleaseId(published.commit ?? published.version ?? `release-${Date.now()}`);
|
|
4180
|
-
const releaseDir =
|
|
4181
|
-
const okMarker =
|
|
4180
|
+
const releaseDir = join8(layout.releasesRoot, releaseId);
|
|
4181
|
+
const okMarker = join8(releaseDir, ".stage-ok");
|
|
4182
4182
|
let previouslyVerified = false;
|
|
4183
4183
|
try {
|
|
4184
4184
|
const recorded = await readFile9(okMarker, "utf8");
|
|
@@ -4187,8 +4187,8 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
4187
4187
|
previouslyVerified = true;
|
|
4188
4188
|
} catch {
|
|
4189
4189
|
}
|
|
4190
|
-
await
|
|
4191
|
-
const tempArchive =
|
|
4190
|
+
await mkdir14(releaseDir, { recursive: true });
|
|
4191
|
+
const tempArchive = join8(layout.releasesRoot, `.download-${releaseId}-${process.pid}.tar.gz`);
|
|
4192
4192
|
try {
|
|
4193
4193
|
log2(`downloading ${published.file}`);
|
|
4194
4194
|
const response = await fetchImpl(archiveUrlFor(manifestUrl, published.file), {
|
|
@@ -4208,7 +4208,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
4208
4208
|
if (actual !== published.sha256.toLowerCase()) {
|
|
4209
4209
|
throw new Error(`checksum mismatch for ${published.file}: expected ${published.sha256}, got ${actual} \u2014 aborting without touching the installed bundle`);
|
|
4210
4210
|
}
|
|
4211
|
-
await
|
|
4211
|
+
await writeFile10(tempArchive, Buffer.concat(chunks), { mode: 384 });
|
|
4212
4212
|
const entries = (await new Promise((resolveList, rejectList) => {
|
|
4213
4213
|
const child = spawn4("tar", ["-tzf", tempArchive], { stdio: ["ignore", "pipe", "inherit"] });
|
|
4214
4214
|
let out = "";
|
|
@@ -4228,18 +4228,18 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
4228
4228
|
throw new Error(`extracting bundle failed: ${extract2.stderr}`);
|
|
4229
4229
|
for (const relative3 of requiredBundlePaths()) {
|
|
4230
4230
|
try {
|
|
4231
|
-
await access(
|
|
4231
|
+
await access(join8(releaseDir, relative3), fsConstants.F_OK);
|
|
4232
4232
|
} catch {
|
|
4233
4233
|
throw new Error(`staged bundle is missing ${relative3}`);
|
|
4234
4234
|
}
|
|
4235
4235
|
}
|
|
4236
4236
|
if (opts.smokeTestCli !== false) {
|
|
4237
|
-
const probe = await run(process.execPath, [
|
|
4237
|
+
const probe = await run(process.execPath, [join8(releaseDir, BUNDLE_ENTRYPOINT), "--version"], 6e4);
|
|
4238
4238
|
if (probe.status !== 0) {
|
|
4239
4239
|
throw new Error(`staged bundle failed its startup smoke test (--version exited ${probe.status})${probe.stderr ? `: ${probe.stderr.trim()}` : ""}`);
|
|
4240
4240
|
}
|
|
4241
4241
|
}
|
|
4242
|
-
await
|
|
4242
|
+
await writeFile10(okMarker, `${published.sha256}
|
|
4243
4243
|
`, "utf8");
|
|
4244
4244
|
log2(`staged release ${releaseId} (sha256 verified)`);
|
|
4245
4245
|
return releaseId;
|
|
@@ -4267,26 +4267,26 @@ function forwarderScript(tool) {
|
|
|
4267
4267
|
}
|
|
4268
4268
|
async function replaceFile(path, contents, mode) {
|
|
4269
4269
|
const temp = `${path}.new-${process.pid}`;
|
|
4270
|
-
await
|
|
4270
|
+
await writeFile10(temp, contents, { mode });
|
|
4271
4271
|
await chmod4(temp, mode);
|
|
4272
4272
|
await rename3(temp, path);
|
|
4273
4273
|
}
|
|
4274
4274
|
async function activateRelease(layout, releaseId) {
|
|
4275
|
-
const releaseDir =
|
|
4276
|
-
await access(
|
|
4277
|
-
await
|
|
4278
|
-
await
|
|
4275
|
+
const releaseDir = join8(layout.releasesRoot, releaseId);
|
|
4276
|
+
await access(join8(releaseDir, BUNDLE_ENTRYPOINT), fsConstants.F_OK);
|
|
4277
|
+
await mkdir14(layout.releasesRoot, { recursive: true });
|
|
4278
|
+
await mkdir14(layout.binDir, { recursive: true });
|
|
4279
4279
|
let previousReleaseId = await activeReleaseId(layout);
|
|
4280
4280
|
const kind = await pathKind(layout.libDir);
|
|
4281
4281
|
if (kind === "directory") {
|
|
4282
4282
|
const legacyIdentity = await readBundleJson(layout.libDir);
|
|
4283
4283
|
const legacyId = sanitizeReleaseId(legacyIdentity?.commit ?? legacyIdentity?.version ?? `legacy-${Date.now()}`);
|
|
4284
|
-
const legacyDir =
|
|
4284
|
+
const legacyDir = join8(layout.releasesRoot, legacyId);
|
|
4285
4285
|
try {
|
|
4286
4286
|
await access(legacyDir, fsConstants.F_OK);
|
|
4287
4287
|
previousReleaseId = `${legacyId}-${Date.now()}`;
|
|
4288
|
-
await rename3(layout.libDir,
|
|
4289
|
-
await normalizeLegacyBundleShape(
|
|
4288
|
+
await rename3(layout.libDir, join8(layout.releasesRoot, previousReleaseId));
|
|
4289
|
+
await normalizeLegacyBundleShape(join8(layout.releasesRoot, previousReleaseId));
|
|
4290
4290
|
} catch {
|
|
4291
4291
|
await rename3(layout.libDir, legacyDir);
|
|
4292
4292
|
await normalizeLegacyBundleShape(legacyDir);
|
|
@@ -4295,18 +4295,18 @@ async function activateRelease(layout, releaseId) {
|
|
|
4295
4295
|
}
|
|
4296
4296
|
const tempLink = `${layout.libDir}.new-${process.pid}`;
|
|
4297
4297
|
await rm5(tempLink, { force: true });
|
|
4298
|
-
await symlink2(
|
|
4298
|
+
await symlink2(join8("beeline-releases", releaseId), tempLink);
|
|
4299
4299
|
await rename3(tempLink, layout.libDir);
|
|
4300
|
-
await fsyncDir(
|
|
4300
|
+
await fsyncDir(dirname10(layout.libDir));
|
|
4301
4301
|
await writeBinForwarders(layout, releaseDir);
|
|
4302
4302
|
return { previousReleaseId };
|
|
4303
4303
|
}
|
|
4304
4304
|
async function normalizeLegacyBundleShape(bundleDir) {
|
|
4305
|
-
const innerLib =
|
|
4305
|
+
const innerLib = join8(bundleDir, "lib", "beeline");
|
|
4306
4306
|
let anyFlat = false;
|
|
4307
4307
|
for (const name of LEGACY_FLAT_BUNDLE_FILES) {
|
|
4308
4308
|
try {
|
|
4309
|
-
await access(
|
|
4309
|
+
await access(join8(bundleDir, name), fsConstants.F_OK);
|
|
4310
4310
|
anyFlat = true;
|
|
4311
4311
|
break;
|
|
4312
4312
|
} catch {
|
|
@@ -4314,14 +4314,14 @@ async function normalizeLegacyBundleShape(bundleDir) {
|
|
|
4314
4314
|
}
|
|
4315
4315
|
if (!anyFlat)
|
|
4316
4316
|
return;
|
|
4317
|
-
await
|
|
4317
|
+
await mkdir14(innerLib, { recursive: true });
|
|
4318
4318
|
for (const name of LEGACY_FLAT_BUNDLE_FILES) {
|
|
4319
4319
|
try {
|
|
4320
|
-
await access(
|
|
4320
|
+
await access(join8(innerLib, name), fsConstants.F_OK);
|
|
4321
4321
|
continue;
|
|
4322
4322
|
} catch {
|
|
4323
4323
|
}
|
|
4324
|
-
await rename3(
|
|
4324
|
+
await rename3(join8(bundleDir, name), join8(innerLib, name)).catch(() => void 0);
|
|
4325
4325
|
}
|
|
4326
4326
|
}
|
|
4327
4327
|
async function writeBinForwarders(layout, activeBundleRoot) {
|
|
@@ -4330,13 +4330,13 @@ async function writeBinForwarders(layout, activeBundleRoot) {
|
|
|
4330
4330
|
...Object.entries(FORWARDER_ALIASES).map(([alias, tool]) => [alias, tool])
|
|
4331
4331
|
];
|
|
4332
4332
|
for (const [name, tool] of entries) {
|
|
4333
|
-
const target =
|
|
4333
|
+
const target = join8(activeBundleRoot, "bin", tool);
|
|
4334
4334
|
try {
|
|
4335
4335
|
await access(target, fsConstants.X_OK);
|
|
4336
4336
|
} catch {
|
|
4337
4337
|
continue;
|
|
4338
4338
|
}
|
|
4339
|
-
await replaceFile(
|
|
4339
|
+
await replaceFile(join8(layout.binDir, name), forwarderScript(tool), 493);
|
|
4340
4340
|
}
|
|
4341
4341
|
}
|
|
4342
4342
|
async function repairInstallForwarders(layout, opts = {}) {
|
|
@@ -4345,7 +4345,7 @@ async function repairInstallForwarders(layout, opts = {}) {
|
|
|
4345
4345
|
const forwarderHealthy = async (name, tool) => {
|
|
4346
4346
|
let current;
|
|
4347
4347
|
try {
|
|
4348
|
-
current = await readFile9(
|
|
4348
|
+
current = await readFile9(join8(layout.binDir, name), "utf8");
|
|
4349
4349
|
} catch {
|
|
4350
4350
|
current = void 0;
|
|
4351
4351
|
}
|
|
@@ -4358,25 +4358,25 @@ async function repairInstallForwarders(layout, opts = {}) {
|
|
|
4358
4358
|
}
|
|
4359
4359
|
if (healthy)
|
|
4360
4360
|
return false;
|
|
4361
|
-
await
|
|
4361
|
+
await mkdir14(layout.binDir, { recursive: true });
|
|
4362
4362
|
await writeBinForwarders(layout, layout.libDir);
|
|
4363
4363
|
opts.logger?.(`[body] self-update: repaired <prefix>/bin forwarders to follow the active-bundle anchor (${layout.libDir})`);
|
|
4364
4364
|
return true;
|
|
4365
4365
|
}
|
|
4366
4366
|
async function rollbackToPreviousRelease(layout, previousReleaseId) {
|
|
4367
|
-
const releaseDir =
|
|
4367
|
+
const releaseDir = join8(layout.releasesRoot, previousReleaseId);
|
|
4368
4368
|
const entrypoint = await resolveBundleEntrypoint(releaseDir);
|
|
4369
4369
|
if (!entrypoint) {
|
|
4370
4370
|
throw new Error(`release ${previousReleaseId} has no runnable CLI entrypoint`);
|
|
4371
4371
|
}
|
|
4372
4372
|
const tempLink = `${layout.libDir}.rollback-${process.pid}`;
|
|
4373
4373
|
await rm5(tempLink, { force: true });
|
|
4374
|
-
await symlink2(
|
|
4374
|
+
await symlink2(join8("beeline-releases", previousReleaseId), tempLink);
|
|
4375
4375
|
await rename3(tempLink, layout.libDir);
|
|
4376
|
-
await fsyncDir(
|
|
4376
|
+
await fsyncDir(dirname10(layout.libDir));
|
|
4377
4377
|
}
|
|
4378
4378
|
function updateAttemptPath(layout) {
|
|
4379
|
-
return
|
|
4379
|
+
return join8(layout.releasesRoot, ".state", "update-attempt.json");
|
|
4380
4380
|
}
|
|
4381
4381
|
async function readUpdateAttempt(layout) {
|
|
4382
4382
|
try {
|
|
@@ -4390,10 +4390,10 @@ async function readUpdateAttempt(layout) {
|
|
|
4390
4390
|
}
|
|
4391
4391
|
}
|
|
4392
4392
|
async function writeUpdateAttempt(layout, record2) {
|
|
4393
|
-
await
|
|
4393
|
+
await mkdir14(join8(layout.releasesRoot, ".state"), { recursive: true });
|
|
4394
4394
|
const path = updateAttemptPath(layout);
|
|
4395
4395
|
const staged = `${path}.${process.pid}.tmp`;
|
|
4396
|
-
await
|
|
4396
|
+
await writeFile10(staged, `${JSON.stringify(record2, null, 2)}
|
|
4397
4397
|
`, { mode: 384 });
|
|
4398
4398
|
await rename3(staged, path);
|
|
4399
4399
|
}
|
|
@@ -4655,8 +4655,8 @@ var init_self_update = __esm({
|
|
|
4655
4655
|
});
|
|
4656
4656
|
|
|
4657
4657
|
// apps/body/dist/cli.js
|
|
4658
|
-
import { dirname as
|
|
4659
|
-
import { readFile as readFile14, unlink as unlink5, writeFile as
|
|
4658
|
+
import { dirname as dirname16, resolve as resolve29 } from "node:path";
|
|
4659
|
+
import { readFile as readFile14, unlink as unlink5, writeFile as writeFile16 } from "node:fs/promises";
|
|
4660
4660
|
import { stdin as stdin4, stdout as stdout5 } from "node:process";
|
|
4661
4661
|
|
|
4662
4662
|
// node_modules/@clack/core/dist/index.mjs
|
|
@@ -6663,20 +6663,6 @@ var ACCESS_NOTICE_WINDOW_MS = 10 * 6e4;
|
|
|
6663
6663
|
var DEFAULT_ACCESS_POLICY = DEFAULT_AGENT_ACCESS_POLICY;
|
|
6664
6664
|
var LEGACY_ACCESS_POLICY = "everyone";
|
|
6665
6665
|
var ACCESS_REFUSAL_WINDOW_MS = 60 * 60 * 1e3;
|
|
6666
|
-
function isSenderPermitted(policy, senderPubkey, ownerPubkey, allowlist = void 0) {
|
|
6667
|
-
if (!senderPubkey)
|
|
6668
|
-
return false;
|
|
6669
|
-
switch (policy) {
|
|
6670
|
-
case "everyone":
|
|
6671
|
-
return true;
|
|
6672
|
-
case "creator":
|
|
6673
|
-
return Boolean(ownerPubkey) && senderPubkey === ownerPubkey;
|
|
6674
|
-
case "allowlist":
|
|
6675
|
-
return Boolean(allowlist?.includes(senderPubkey));
|
|
6676
|
-
default:
|
|
6677
|
-
return false;
|
|
6678
|
-
}
|
|
6679
|
-
}
|
|
6680
6666
|
|
|
6681
6667
|
// apps/body/dist/model-catalog.js
|
|
6682
6668
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
@@ -8129,6 +8115,40 @@ async function syncAgentModelCatalog(input) {
|
|
|
8129
8115
|
}
|
|
8130
8116
|
}
|
|
8131
8117
|
|
|
8118
|
+
// packages/api-contract/dist/daemon-operations.js
|
|
8119
|
+
function isAgentCommand(value) {
|
|
8120
|
+
if (!value || typeof value !== "object")
|
|
8121
|
+
return false;
|
|
8122
|
+
const c2 = value;
|
|
8123
|
+
if (![
|
|
8124
|
+
"id",
|
|
8125
|
+
"roomId",
|
|
8126
|
+
"agentId",
|
|
8127
|
+
"sourceMessageId",
|
|
8128
|
+
"turnRequestId",
|
|
8129
|
+
"rootCommandId",
|
|
8130
|
+
"rootSourceMessageId",
|
|
8131
|
+
"reason"
|
|
8132
|
+
].every((key) => typeof c2[key] === "string" && c2[key].length > 0))
|
|
8133
|
+
return false;
|
|
8134
|
+
if (!["input", "resume", "stop"].includes(String(c2.action)) || !Number.isInteger(c2.agentDepth) || Number(c2.agentDepth) < 0 || Number(c2.agentDepth) > 3)
|
|
8135
|
+
return false;
|
|
8136
|
+
const source = c2.source;
|
|
8137
|
+
return Boolean(source && typeof source.id === "string" && typeof source.authorId === "string" && typeof source.body === "string" && typeof source.createdAt === "number" && Array.isArray(source.attachments) && Array.isArray(source.mentionIds));
|
|
8138
|
+
}
|
|
8139
|
+
|
|
8140
|
+
// packages/api-contract/dist/system-events.js
|
|
8141
|
+
var SERVER_EVENT_KINDS = [
|
|
8142
|
+
"joined",
|
|
8143
|
+
"schedule-ran",
|
|
8144
|
+
"corner-opened",
|
|
8145
|
+
"check-passed",
|
|
8146
|
+
"check-failed",
|
|
8147
|
+
"merged",
|
|
8148
|
+
"grant-decided",
|
|
8149
|
+
"turn-cancelled"
|
|
8150
|
+
];
|
|
8151
|
+
|
|
8132
8152
|
// apps/body/dist/daemon-api-client.js
|
|
8133
8153
|
import { resolve as resolve7 } from "node:path";
|
|
8134
8154
|
import { randomUUID } from "node:crypto";
|
|
@@ -16910,32 +16930,6 @@ var DaemonApiError = class extends Error {
|
|
|
16910
16930
|
}
|
|
16911
16931
|
};
|
|
16912
16932
|
var AGENT_REMOVED_CODE = "agent_removed";
|
|
16913
|
-
function laterInboxCursor(left, right) {
|
|
16914
|
-
if (!left)
|
|
16915
|
-
return right;
|
|
16916
|
-
if (!right)
|
|
16917
|
-
return left;
|
|
16918
|
-
const leftMatch = left.match(/^(\d+),([0-9a-f]{64})$/);
|
|
16919
|
-
const rightMatch = right.match(/^(\d+),([0-9a-f]{64})$/);
|
|
16920
|
-
if (!leftMatch || !rightMatch)
|
|
16921
|
-
return right;
|
|
16922
|
-
const timeOrder = BigInt(leftMatch[1]) - BigInt(rightMatch[1]);
|
|
16923
|
-
if (timeOrder !== 0n)
|
|
16924
|
-
return timeOrder > 0n ? left : right;
|
|
16925
|
-
return leftMatch[2] >= rightMatch[2] ? left : right;
|
|
16926
|
-
}
|
|
16927
|
-
function orderInboxItems(items) {
|
|
16928
|
-
return [...items].sort((left, right) => {
|
|
16929
|
-
const leftMatch = left.cursor?.match(/^(\d+),([0-9a-f]{64})$/);
|
|
16930
|
-
const rightMatch = right.cursor?.match(/^(\d+),([0-9a-f]{64})$/);
|
|
16931
|
-
if (!leftMatch || !rightMatch)
|
|
16932
|
-
return 0;
|
|
16933
|
-
const timeOrder = BigInt(leftMatch[1]) - BigInt(rightMatch[1]);
|
|
16934
|
-
if (timeOrder !== 0n)
|
|
16935
|
-
return timeOrder < 0n ? -1 : 1;
|
|
16936
|
-
return leftMatch[2] < rightMatch[2] ? -1 : leftMatch[2] > rightMatch[2] ? 1 : 0;
|
|
16937
|
-
});
|
|
16938
|
-
}
|
|
16939
16933
|
function isAgentRemovedError(error) {
|
|
16940
16934
|
return error instanceof DaemonApiError && error.status === 403 && error.code === AGENT_REMOVED_CODE;
|
|
16941
16935
|
}
|
|
@@ -16975,20 +16969,23 @@ var DaemonApiClient = class {
|
|
|
16975
16969
|
return { baseUrl: this.baseUrl, daemonToken: this.daemonToken, agentId: this.agentId };
|
|
16976
16970
|
}
|
|
16977
16971
|
/** Add one Room to this agent's shared live socket. */
|
|
16978
|
-
liveSubscribe(roomId, cursor3, onItems, onState, presence) {
|
|
16972
|
+
liveSubscribe(roomId, cursor3, onItems, onState, presence, onCommands) {
|
|
16979
16973
|
const existing = this.liveRooms.get(roomId);
|
|
16980
16974
|
if (existing) {
|
|
16981
16975
|
existing.cursor = cursor3 ?? existing.cursor;
|
|
16982
16976
|
existing.onItems = onItems ?? existing.onItems;
|
|
16983
16977
|
existing.onState = onState ?? existing.onState;
|
|
16984
16978
|
existing.presence = presence ?? existing.presence;
|
|
16979
|
+
existing.onCommands = onCommands ?? existing.onCommands;
|
|
16985
16980
|
} else {
|
|
16986
16981
|
this.liveRooms.set(roomId, {
|
|
16987
16982
|
...cursor3 ? { cursor: cursor3 } : {},
|
|
16988
16983
|
pushedIds: /* @__PURE__ */ new Set(),
|
|
16984
|
+
pushedCommandIds: /* @__PURE__ */ new Set(),
|
|
16989
16985
|
...onItems ? { onItems } : {},
|
|
16990
16986
|
...onState ? { onState } : {},
|
|
16991
|
-
...presence ? { presence } : {}
|
|
16987
|
+
...presence ? { presence } : {},
|
|
16988
|
+
...onCommands ? { onCommands } : {}
|
|
16992
16989
|
});
|
|
16993
16990
|
}
|
|
16994
16991
|
this.ensureLiveSocket();
|
|
@@ -17058,6 +17055,22 @@ var DaemonApiClient = class {
|
|
|
17058
17055
|
});
|
|
17059
17056
|
return;
|
|
17060
17057
|
}
|
|
17058
|
+
if (event.type === "commands" && typeof event.roomId === "string" && event.commandProtocol === 1 && Array.isArray(event.commands)) {
|
|
17059
|
+
const room2 = this.liveRooms.get(event.roomId);
|
|
17060
|
+
if (!room2)
|
|
17061
|
+
return;
|
|
17062
|
+
const commands = event.commands.filter((command) => {
|
|
17063
|
+
if (!isAgentCommand(command) || command.roomId !== event.roomId || command.agentId !== this.agentId || room2.pushedCommandIds.has(command.id))
|
|
17064
|
+
return false;
|
|
17065
|
+
room2.pushedCommandIds.add(command.id);
|
|
17066
|
+
return true;
|
|
17067
|
+
});
|
|
17068
|
+
while (room2.pushedCommandIds.size > 1e4)
|
|
17069
|
+
room2.pushedCommandIds.delete(room2.pushedCommandIds.values().next().value);
|
|
17070
|
+
if (commands.length)
|
|
17071
|
+
room2.onCommands?.(commands);
|
|
17072
|
+
return;
|
|
17073
|
+
}
|
|
17061
17074
|
if (event.type !== "inbox" || typeof event.roomId !== "string" || !Array.isArray(event.items))
|
|
17062
17075
|
return;
|
|
17063
17076
|
const room = this.liveRooms.get(event.roomId);
|
|
@@ -17153,8 +17166,8 @@ async function activateDaemonTransport(path, fetchImpl = fetch) {
|
|
|
17153
17166
|
import { execFile as execFile5 } from "node:child_process";
|
|
17154
17167
|
import { createHash as createHash5 } from "node:crypto";
|
|
17155
17168
|
import { existsSync as existsSync4, mkdirSync } from "node:fs";
|
|
17156
|
-
import { mkdir as
|
|
17157
|
-
import { dirname as
|
|
17169
|
+
import { mkdir as mkdir12, rm as rm4 } from "node:fs/promises";
|
|
17170
|
+
import { dirname as dirname7, resolve as resolve19 } from "node:path";
|
|
17158
17171
|
import { promisify as promisify4 } from "node:util";
|
|
17159
17172
|
|
|
17160
17173
|
// apps/body/dist/grant-runner.js
|
|
@@ -17207,18 +17220,6 @@ function commandGrantMatches(rule, requested) {
|
|
|
17207
17220
|
return rule.argv.every((word, index) => requested[index] === word);
|
|
17208
17221
|
}
|
|
17209
17222
|
var DECISION_LINE = new RegExp(`^(.+?) (approved once|approved|declined) (${AGENT_GRANT_KINDS.join("|")}) (.+)$`, "s");
|
|
17210
|
-
function parseGrantDecisionLine(body) {
|
|
17211
|
-
const match = DECISION_LINE.exec(body);
|
|
17212
|
-
if (!match)
|
|
17213
|
-
return void 0;
|
|
17214
|
-
const decision2 = match[2] === "approved once" ? "once" : match[2] === "approved" ? "always" : "deny";
|
|
17215
|
-
return {
|
|
17216
|
-
deciderName: match[1],
|
|
17217
|
-
decision: decision2,
|
|
17218
|
-
kind: match[3],
|
|
17219
|
-
target: match[4]
|
|
17220
|
-
};
|
|
17221
|
-
}
|
|
17222
17223
|
var AGENT_GRANT_ESCALATION_REASONS = {
|
|
17223
17224
|
"unseen-script": "it runs a script whose contents nobody has read",
|
|
17224
17225
|
credential: "it names a credential or environment file"
|
|
@@ -17798,7 +17799,9 @@ var GrantCommandRunner = class {
|
|
|
17798
17799
|
if (!room)
|
|
17799
17800
|
throw new Error("this daemon is not serving that Room");
|
|
17800
17801
|
const argv = validateGrantArgv(input.argv);
|
|
17801
|
-
const live = await this.options.api.execute("listAgentGrants", {
|
|
17802
|
+
const live = await this.options.api.execute("listAgentGrants", {
|
|
17803
|
+
agentId: this.options.agentId
|
|
17804
|
+
});
|
|
17802
17805
|
const match = matchCommandGrant(live.grants, room.workspaceId, argv);
|
|
17803
17806
|
if (!match) {
|
|
17804
17807
|
throw new Error(`no approved command grant matches: ${argv.join(" ")}. Ask with request_grant kind=command first.`);
|
|
@@ -17861,6 +17864,7 @@ ${ROOM_WRITE_REFUSED_NOTE}` : outcome.output, secrets), cap);
|
|
|
17861
17864
|
agentId: this.options.agentId,
|
|
17862
17865
|
roomId: input.roomId,
|
|
17863
17866
|
requestId: turn?.requestId ?? `grant:${grant.grantId}`,
|
|
17867
|
+
generationId: turn?.generationId,
|
|
17864
17868
|
activity: [
|
|
17865
17869
|
{
|
|
17866
17870
|
kind: "tool",
|
|
@@ -17915,7 +17919,10 @@ function scriptCandidates(cwd, scratch, argv) {
|
|
|
17915
17919
|
const argument = interpreterScriptArgument(argv);
|
|
17916
17920
|
if (!argument)
|
|
17917
17921
|
return [];
|
|
17918
|
-
const paths = [
|
|
17922
|
+
const paths = [
|
|
17923
|
+
resolve10(cwd, argument.path),
|
|
17924
|
+
...scratch ? [resolve10(scratch, argument.path)] : []
|
|
17925
|
+
];
|
|
17919
17926
|
return [...new Set(paths)];
|
|
17920
17927
|
}
|
|
17921
17928
|
function roomSandboxCommand(policy, cwd, argv) {
|
|
@@ -17994,128 +18001,162 @@ var GrantRunnerServer = class {
|
|
|
17994
18001
|
}
|
|
17995
18002
|
};
|
|
17996
18003
|
|
|
18004
|
+
// apps/body/dist/server-command-intake.js
|
|
18005
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
18006
|
+
import { mkdir as mkdir3, writeFile as writeFile4 } from "node:fs/promises";
|
|
18007
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
18008
|
+
import { dirname as dirname5, join as join3 } from "node:path";
|
|
18009
|
+
var CommandExecutionContext = class {
|
|
18010
|
+
generationId = randomUUID2();
|
|
18011
|
+
path;
|
|
18012
|
+
current;
|
|
18013
|
+
constructor(root) {
|
|
18014
|
+
this.path = join3(root ?? tmpdir2(), `beeline-command-${this.generationId}.json`);
|
|
18015
|
+
}
|
|
18016
|
+
async enter(command) {
|
|
18017
|
+
this.current = command;
|
|
18018
|
+
await mkdir3(dirname5(this.path), { recursive: true });
|
|
18019
|
+
await writeFile4(this.path, JSON.stringify({
|
|
18020
|
+
roomId: command.roomId,
|
|
18021
|
+
requestId: command.turnRequestId,
|
|
18022
|
+
generationId: this.generationId
|
|
18023
|
+
}), { mode: 384 });
|
|
18024
|
+
}
|
|
18025
|
+
async leave() {
|
|
18026
|
+
this.current = void 0;
|
|
18027
|
+
await writeFile4(this.path, "{}", { mode: 384 });
|
|
18028
|
+
}
|
|
18029
|
+
bind(api) {
|
|
18030
|
+
return new Proxy(api, {
|
|
18031
|
+
get: (target, key) => {
|
|
18032
|
+
if (key === "execute")
|
|
18033
|
+
return (name, input) => {
|
|
18034
|
+
const turn = this.current;
|
|
18035
|
+
return target.execute(name, {
|
|
18036
|
+
...input,
|
|
18037
|
+
...turn && (input.roomId === turn.roomId || input.cornerId === turn.roomId) ? {
|
|
18038
|
+
generationId: this.generationId,
|
|
18039
|
+
requestId: input.requestId ?? input.turnId ?? turn.turnRequestId
|
|
18040
|
+
} : {}
|
|
18041
|
+
});
|
|
18042
|
+
};
|
|
18043
|
+
const value = Reflect.get(target, key);
|
|
18044
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
18045
|
+
}
|
|
18046
|
+
});
|
|
18047
|
+
}
|
|
18048
|
+
};
|
|
18049
|
+
function validateServerCommand(command, roomId, agentId) {
|
|
18050
|
+
if (!isAgentCommand(command) || command.roomId !== roomId || command.agentId !== agentId)
|
|
18051
|
+
throw new Error("invalid server command");
|
|
18052
|
+
}
|
|
18053
|
+
async function runServerCommandIntake(options) {
|
|
18054
|
+
const { api, roomId, agentId, context, signal } = options;
|
|
18055
|
+
const first = await api.execute("getAgentCommands", { roomId });
|
|
18056
|
+
if (first?.commandProtocol !== 1)
|
|
18057
|
+
throw new Error("server command protocol 1 is required; refusing intake");
|
|
18058
|
+
let busy;
|
|
18059
|
+
let wake;
|
|
18060
|
+
const pending = new Map(first.commands.map((command) => [command.id, command]));
|
|
18061
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
18062
|
+
const notify2 = (commands = []) => {
|
|
18063
|
+
for (const command of commands)
|
|
18064
|
+
if (!claimed.has(command.id))
|
|
18065
|
+
pending.set(command.id, command);
|
|
18066
|
+
wake?.(false);
|
|
18067
|
+
};
|
|
18068
|
+
options.onWake?.(notify2);
|
|
18069
|
+
const off = api.liveSubscribe?.(roomId, void 0, void 0, (connected) => {
|
|
18070
|
+
if (!connected)
|
|
18071
|
+
wake?.(true);
|
|
18072
|
+
}, options.presence, notify2);
|
|
18073
|
+
try {
|
|
18074
|
+
while (!signal?.aborted) {
|
|
18075
|
+
if (options.closed && await options.closed())
|
|
18076
|
+
return;
|
|
18077
|
+
for (const command of [...pending.values()]) {
|
|
18078
|
+
validateServerCommand(command, roomId, agentId);
|
|
18079
|
+
if (busy && command.action !== "stop")
|
|
18080
|
+
continue;
|
|
18081
|
+
pending.delete(command.id);
|
|
18082
|
+
try {
|
|
18083
|
+
await api.execute("claimAgentCommand", {
|
|
18084
|
+
roomId,
|
|
18085
|
+
commandId: command.id,
|
|
18086
|
+
generationId: context.generationId
|
|
18087
|
+
});
|
|
18088
|
+
} catch (error) {
|
|
18089
|
+
options.onError?.(error);
|
|
18090
|
+
continue;
|
|
18091
|
+
}
|
|
18092
|
+
claimed.add(command.id);
|
|
18093
|
+
if (command.action === "stop") {
|
|
18094
|
+
options.stop(command.turnRequestId);
|
|
18095
|
+
await api.execute("acknowledgeAgentCommand", {
|
|
18096
|
+
roomId,
|
|
18097
|
+
commandId: command.id,
|
|
18098
|
+
generationId: context.generationId
|
|
18099
|
+
});
|
|
18100
|
+
} else {
|
|
18101
|
+
await context.enter(command);
|
|
18102
|
+
busy = options.run(command).catch((error) => {
|
|
18103
|
+
claimed.delete(command.id);
|
|
18104
|
+
options.onError?.(error);
|
|
18105
|
+
}).finally(async () => {
|
|
18106
|
+
await context.leave();
|
|
18107
|
+
busy = void 0;
|
|
18108
|
+
notify2();
|
|
18109
|
+
});
|
|
18110
|
+
}
|
|
18111
|
+
}
|
|
18112
|
+
options.onPoll?.();
|
|
18113
|
+
const reconcile = await new Promise((resolve30) => {
|
|
18114
|
+
const done = (needed) => {
|
|
18115
|
+
if (timer)
|
|
18116
|
+
clearTimeout(timer);
|
|
18117
|
+
signal?.removeEventListener("abort", aborted);
|
|
18118
|
+
wake = void 0;
|
|
18119
|
+
resolve30(needed);
|
|
18120
|
+
};
|
|
18121
|
+
const aborted = () => done(false);
|
|
18122
|
+
wake = done;
|
|
18123
|
+
const timer = setTimeout(() => done(true), options.pollMs ?? 1e3);
|
|
18124
|
+
signal?.addEventListener("abort", aborted, { once: true });
|
|
18125
|
+
if (pending.size && !busy)
|
|
18126
|
+
done(false);
|
|
18127
|
+
});
|
|
18128
|
+
if (signal?.aborted)
|
|
18129
|
+
break;
|
|
18130
|
+
if (reconcile) {
|
|
18131
|
+
const page = await api.execute("getAgentCommands", { roomId });
|
|
18132
|
+
if (page.commandProtocol !== 1)
|
|
18133
|
+
throw new Error("server command protocol changed; refusing intake");
|
|
18134
|
+
notify2(page.commands);
|
|
18135
|
+
}
|
|
18136
|
+
}
|
|
18137
|
+
} finally {
|
|
18138
|
+
off?.();
|
|
18139
|
+
options.onWake?.(void 0);
|
|
18140
|
+
if (context.current)
|
|
18141
|
+
options.stop(context.current.turnRequestId);
|
|
18142
|
+
await busy;
|
|
18143
|
+
}
|
|
18144
|
+
}
|
|
18145
|
+
|
|
17997
18146
|
// apps/body/dist/monolith-corner-turn.js
|
|
17998
18147
|
import { execFile as execFile4 } from "node:child_process";
|
|
17999
18148
|
import { createHash as createHash4 } from "node:crypto";
|
|
18000
|
-
import { mkdir as
|
|
18149
|
+
import { mkdir as mkdir11 } from "node:fs/promises";
|
|
18001
18150
|
import { homedir as homedir7 } from "node:os";
|
|
18002
|
-
import { join as
|
|
18151
|
+
import { join as join7 } from "node:path";
|
|
18003
18152
|
import { promisify as promisify3 } from "node:util";
|
|
18004
18153
|
|
|
18005
|
-
// packages/api-contract/dist/daemon-operations.js
|
|
18006
|
-
var AGENT_TO_AGENT_HOP_CAP = 3;
|
|
18007
|
-
|
|
18008
|
-
// packages/api-contract/dist/system-events.js
|
|
18009
|
-
var SERVER_EVENT_KINDS = [
|
|
18010
|
-
"joined",
|
|
18011
|
-
"schedule-ran",
|
|
18012
|
-
"corner-opened",
|
|
18013
|
-
"check-passed",
|
|
18014
|
-
"check-failed",
|
|
18015
|
-
"merged",
|
|
18016
|
-
"grant-decided",
|
|
18017
|
-
"turn-cancelled"
|
|
18018
|
-
];
|
|
18019
|
-
function isServerEventKind(value) {
|
|
18020
|
-
return SERVER_EVENT_KINDS.includes(value);
|
|
18021
|
-
}
|
|
18022
|
-
var RESUME_KINDS = ["grant-decided"];
|
|
18023
|
-
function isResumeKind(value) {
|
|
18024
|
-
return RESUME_KINDS.includes(value);
|
|
18025
|
-
}
|
|
18026
|
-
var CONTROL_KINDS = ["turn-cancelled"];
|
|
18027
|
-
function isControlKind(value) {
|
|
18028
|
-
return CONTROL_KINDS.includes(value);
|
|
18029
|
-
}
|
|
18030
|
-
|
|
18031
|
-
// apps/body/dist/agent-response-rule.js
|
|
18032
|
-
var INBOX_DEDUPLICATION_LIMIT = 1e4;
|
|
18033
|
-
var CONTINUITY_WINDOW_LIMIT = 200;
|
|
18034
|
-
var AgentResponseRule = class {
|
|
18035
|
-
agentIds = /* @__PURE__ */ new Set();
|
|
18036
|
-
lastAgentBySender = /* @__PURE__ */ new Map();
|
|
18037
|
-
observedIds = /* @__PURE__ */ new Set();
|
|
18038
|
-
recentMessages = [];
|
|
18039
|
-
localReplySequence = 0;
|
|
18040
|
-
setAgents(agentIds) {
|
|
18041
|
-
this.agentIds = new Set(agentIds);
|
|
18042
|
-
this.rebuildLastAgentBySender();
|
|
18043
|
-
}
|
|
18044
|
-
observeAll(items) {
|
|
18045
|
-
for (const item of items)
|
|
18046
|
-
this.observe(item);
|
|
18047
|
-
}
|
|
18048
|
-
replaceHistory(items) {
|
|
18049
|
-
this.recentMessages.length = 0;
|
|
18050
|
-
this.lastAgentBySender.clear();
|
|
18051
|
-
for (const item of items)
|
|
18052
|
-
this.record(item);
|
|
18053
|
-
}
|
|
18054
|
-
observe(item) {
|
|
18055
|
-
if (this.observedIds.has(item.id))
|
|
18056
|
-
return;
|
|
18057
|
-
this.observedIds.add(item.id);
|
|
18058
|
-
while (this.observedIds.size > INBOX_DEDUPLICATION_LIMIT)
|
|
18059
|
-
this.observedIds.delete(this.observedIds.values().next().value);
|
|
18060
|
-
this.record(item);
|
|
18061
|
-
}
|
|
18062
|
-
record(item) {
|
|
18063
|
-
if (item.type !== "message")
|
|
18064
|
-
return;
|
|
18065
|
-
this.recentMessages.push(item);
|
|
18066
|
-
while (this.recentMessages.length > CONTINUITY_WINDOW_LIMIT)
|
|
18067
|
-
this.recentMessages.shift();
|
|
18068
|
-
this.rebuildLastAgentBySender();
|
|
18069
|
-
}
|
|
18070
|
-
rebuildLastAgentBySender() {
|
|
18071
|
-
this.lastAgentBySender.clear();
|
|
18072
|
-
for (const recent of this.recentMessages) {
|
|
18073
|
-
if (!recent.agentAuthor && !this.agentIds.has(recent.authorId))
|
|
18074
|
-
continue;
|
|
18075
|
-
const addressed = new Set(recent.mentionIds);
|
|
18076
|
-
if (recent.requestAuthorId)
|
|
18077
|
-
addressed.add(recent.requestAuthorId);
|
|
18078
|
-
if (recent.replyToAuthorId)
|
|
18079
|
-
addressed.add(recent.replyToAuthorId);
|
|
18080
|
-
for (const senderId of addressed) {
|
|
18081
|
-
if (senderId !== recent.authorId)
|
|
18082
|
-
this.lastAgentBySender.set(senderId, recent.authorId);
|
|
18083
|
-
}
|
|
18084
|
-
}
|
|
18085
|
-
}
|
|
18086
|
-
noteReply(agentId, senderIds) {
|
|
18087
|
-
this.record({
|
|
18088
|
-
id: `local-reply-${agentId}-${this.localReplySequence++}`,
|
|
18089
|
-
authorId: agentId,
|
|
18090
|
-
type: "message",
|
|
18091
|
-
mentionIds: [...senderIds],
|
|
18092
|
-
agentAuthor: true
|
|
18093
|
-
});
|
|
18094
|
-
}
|
|
18095
|
-
/** Whether trigger 2 applies. Explicit mention handling stays with each intake loop. */
|
|
18096
|
-
continues(item, agentId) {
|
|
18097
|
-
if (item.type !== "message" || item.authorId === agentId)
|
|
18098
|
-
return false;
|
|
18099
|
-
if (!this.agentIds.has(agentId))
|
|
18100
|
-
return false;
|
|
18101
|
-
if ((item.agentAuthor || this.agentIds.has(item.authorId)) && (item.agentHopCount ?? 0) >= AGENT_TO_AGENT_HOP_CAP)
|
|
18102
|
-
return false;
|
|
18103
|
-
if (item.agentMentionIds?.length || item.mentionIds.some((mentioned) => this.agentIds.has(mentioned)))
|
|
18104
|
-
return false;
|
|
18105
|
-
if (item.replyToMessageId)
|
|
18106
|
-
return item.replyToAuthorId === agentId;
|
|
18107
|
-
if (this.lastAgentBySender.get(item.authorId) !== agentId)
|
|
18108
|
-
return false;
|
|
18109
|
-
return true;
|
|
18110
|
-
}
|
|
18111
|
-
};
|
|
18112
|
-
|
|
18113
18154
|
// apps/body/dist/agent-home.js
|
|
18114
18155
|
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "node:fs";
|
|
18115
|
-
import { createHash as createHash3, randomUUID as
|
|
18116
|
-
import { chmod as chmod2, copyFile, lstat, mkdir as
|
|
18156
|
+
import { createHash as createHash3, randomUUID as randomUUID3 } from "node:crypto";
|
|
18157
|
+
import { chmod as chmod2, copyFile, lstat, mkdir as mkdir5, readFile as readFile6, readdir as readdir2, realpath, rename as rename2, rm as rm2, symlink, unlink, writeFile as writeFile6 } from "node:fs/promises";
|
|
18117
18158
|
import { homedir as homedir5 } from "node:os";
|
|
18118
|
-
import { basename as basename3, dirname as
|
|
18159
|
+
import { basename as basename3, dirname as dirname6, join as join4, relative as relative2, resolve as resolve13, sep } from "node:path";
|
|
18119
18160
|
|
|
18120
18161
|
// apps/body/dist/beeline-skill.js
|
|
18121
18162
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
@@ -18218,7 +18259,7 @@ var SQUIRE_GOVERNED_TOOLS = [
|
|
|
18218
18259
|
var SQUIRE_GOVERNED_TOOL_SET = new Set(SQUIRE_GOVERNED_TOOLS);
|
|
18219
18260
|
|
|
18220
18261
|
// apps/body/dist/openrouter-routing.js
|
|
18221
|
-
import { mkdir as
|
|
18262
|
+
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile5 } from "node:fs/promises";
|
|
18222
18263
|
import { resolve as resolve12 } from "node:path";
|
|
18223
18264
|
var OPENROUTER_ENDPOINTS_BASE_URL = "https://openrouter.ai/api/v1/models";
|
|
18224
18265
|
var OPENROUTER_COMPLETIONS_URL = "https://openrouter.ai/api/v1/chat/completions";
|
|
@@ -18348,8 +18389,8 @@ async function readCache(cacheDir, model) {
|
|
|
18348
18389
|
}
|
|
18349
18390
|
}
|
|
18350
18391
|
async function writeCache(cacheDir, value) {
|
|
18351
|
-
await
|
|
18352
|
-
await
|
|
18392
|
+
await mkdir4(cacheDir, { recursive: true, mode: 448 });
|
|
18393
|
+
await writeFile5(cachePath(cacheDir, value.model), `${JSON.stringify(value, null, 2)}
|
|
18353
18394
|
`, {
|
|
18354
18395
|
mode: 384
|
|
18355
18396
|
});
|
|
@@ -18383,8 +18424,8 @@ async function readProbeCache(cacheDir, model) {
|
|
|
18383
18424
|
}
|
|
18384
18425
|
}
|
|
18385
18426
|
async function writeProbeCache(cacheDir, value) {
|
|
18386
|
-
await
|
|
18387
|
-
await
|
|
18427
|
+
await mkdir4(cacheDir, { recursive: true, mode: 448 });
|
|
18428
|
+
await writeFile5(probeCachePath(cacheDir, value.model), `${JSON.stringify(value, null, 2)}
|
|
18388
18429
|
`, {
|
|
18389
18430
|
mode: 384
|
|
18390
18431
|
});
|
|
@@ -18840,14 +18881,14 @@ async function prepareRoomAgentHome(input) {
|
|
|
18840
18881
|
const root = resolve13(input.root);
|
|
18841
18882
|
const operatorHome = input.operatorHome ?? homedir5();
|
|
18842
18883
|
try {
|
|
18843
|
-
await
|
|
18884
|
+
await mkdir5(root, { recursive: true, mode: 448 });
|
|
18844
18885
|
const rootStats = await lstat(root);
|
|
18845
18886
|
if (!rootStats.isDirectory() || rootStats.isSymbolicLink()) {
|
|
18846
18887
|
throw new AgentHomeSecurityError(`agent home root is not an ordinary directory: ${root}`);
|
|
18847
18888
|
}
|
|
18848
18889
|
for (const subdir of HOME_SUBDIRS) {
|
|
18849
18890
|
const path = resolve13(root, subdir);
|
|
18850
|
-
await
|
|
18891
|
+
await mkdir5(path, { recursive: true, mode: 448 });
|
|
18851
18892
|
await assertRealContainedDirectory(path, root);
|
|
18852
18893
|
}
|
|
18853
18894
|
} catch (error) {
|
|
@@ -18899,7 +18940,7 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
|
|
|
18899
18940
|
}
|
|
18900
18941
|
try {
|
|
18901
18942
|
const gooseConfigDir = resolve13(root, "goose", "config");
|
|
18902
|
-
await
|
|
18943
|
+
await mkdir5(gooseConfigDir, { recursive: true, mode: 448 });
|
|
18903
18944
|
for (const name of GOOSE_SHARED_CONFIG_FILES) {
|
|
18904
18945
|
const source = resolve13(operatorHome, ".config", "goose", name);
|
|
18905
18946
|
const target = resolve13(gooseConfigDir, name);
|
|
@@ -19011,18 +19052,18 @@ function filteredHarnessMcpToml(source) {
|
|
|
19011
19052
|
return extractTomlSections(source, ["mcp_servers"], excluded);
|
|
19012
19053
|
}
|
|
19013
19054
|
async function provisionManagedSkillsDir(target, managedSkills, sharedSkills, optionalShares) {
|
|
19014
|
-
const parent =
|
|
19015
|
-
await assertRealContainedDirectory(parent,
|
|
19055
|
+
const parent = dirname6(target);
|
|
19056
|
+
await assertRealContainedDirectory(parent, dirname6(parent));
|
|
19016
19057
|
const plan = await planManagedSkills(managedSkills, sharedSkills, optionalShares);
|
|
19017
19058
|
if (await materializedSkillManifest(target) === plan.manifest)
|
|
19018
19059
|
return;
|
|
19019
|
-
const staged = resolve13(parent, `.skills.${process.pid}.${
|
|
19020
|
-
await
|
|
19060
|
+
const staged = resolve13(parent, `.skills.${process.pid}.${randomUUID3()}.tmp`);
|
|
19061
|
+
await mkdir5(staged, { mode: 448 });
|
|
19021
19062
|
try {
|
|
19022
19063
|
for (const entry of plan.entries) {
|
|
19023
19064
|
if (entry.kind === "managed") {
|
|
19024
19065
|
const skillDir = resolve13(staged, entry.name);
|
|
19025
|
-
await
|
|
19066
|
+
await mkdir5(skillDir, { recursive: true });
|
|
19026
19067
|
await writeIsolatedHarnessFile(resolve13(skillDir, "SKILL.md"), entry.content);
|
|
19027
19068
|
} else {
|
|
19028
19069
|
await copySafeSkillTree(entry.source, resolve13(staged, entry.name), entry.source);
|
|
@@ -19052,8 +19093,8 @@ async function planManagedSkills(managedSkills, sharedSkills, optionalShares) {
|
|
|
19052
19093
|
try {
|
|
19053
19094
|
const tree = [];
|
|
19054
19095
|
await walkSafeSkillTree(shared.source, shared.source, {
|
|
19055
|
-
directory: async (rel) => void tree.push(`d ${
|
|
19056
|
-
file: async (rel, realPath) => void tree.push(`f ${
|
|
19096
|
+
directory: async (rel) => void tree.push(`d ${join4(shared.name, rel)}`),
|
|
19097
|
+
file: async (rel, realPath) => void tree.push(`f ${join4(shared.name, rel)} ${sha2563(await readFile6(realPath))}`)
|
|
19057
19098
|
});
|
|
19058
19099
|
entries.push({ kind: "shared", name: shared.name, source: shared.source });
|
|
19059
19100
|
lines.push(...tree);
|
|
@@ -19073,7 +19114,7 @@ async function materializedSkillManifest(target) {
|
|
|
19073
19114
|
const visit = async (directory, prefix) => {
|
|
19074
19115
|
for (const entry of await readdir2(directory)) {
|
|
19075
19116
|
const path = resolve13(directory, entry);
|
|
19076
|
-
const rel = prefix ?
|
|
19117
|
+
const rel = prefix ? join4(prefix, entry) : entry;
|
|
19077
19118
|
const entryStats = await lstat(path);
|
|
19078
19119
|
if (entryStats.isSymbolicLink())
|
|
19079
19120
|
return false;
|
|
@@ -19241,7 +19282,7 @@ async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
|
|
|
19241
19282
|
for (const entry of await readdir2(resolvedSource)) {
|
|
19242
19283
|
if (entry === "." || entry === "..")
|
|
19243
19284
|
throw new Error("invalid shared skill entry");
|
|
19244
|
-
await walkSafeSkillTree(resolve13(source, entry), sourceRoot, visitor, rel ?
|
|
19285
|
+
await walkSafeSkillTree(resolve13(source, entry), sourceRoot, visitor, rel ? join4(rel, entry) : entry);
|
|
19245
19286
|
}
|
|
19246
19287
|
return;
|
|
19247
19288
|
}
|
|
@@ -19253,7 +19294,7 @@ async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
|
|
|
19253
19294
|
async function copySafeSkillTree(source, target, sourceRoot) {
|
|
19254
19295
|
await walkSafeSkillTree(source, sourceRoot, {
|
|
19255
19296
|
directory: async (rel) => {
|
|
19256
|
-
await
|
|
19297
|
+
await mkdir5(resolve13(target, rel), { mode: 448 });
|
|
19257
19298
|
},
|
|
19258
19299
|
file: async (rel, realPath) => {
|
|
19259
19300
|
const destination = resolve13(target, rel);
|
|
@@ -19263,14 +19304,14 @@ async function copySafeSkillTree(source, target, sourceRoot) {
|
|
|
19263
19304
|
});
|
|
19264
19305
|
}
|
|
19265
19306
|
async function writeIsolatedHarnessFile(path, content) {
|
|
19266
|
-
const parent =
|
|
19307
|
+
const parent = dirname6(path);
|
|
19267
19308
|
const parentStats = await lstat(parent);
|
|
19268
19309
|
if (!parentStats.isDirectory() || parentStats.isSymbolicLink()) {
|
|
19269
19310
|
throw new Error(`isolated harness parent is not a real directory: ${parent}`);
|
|
19270
19311
|
}
|
|
19271
|
-
const temporary = resolve13(parent, `.${basename3(path)}.${process.pid}.${
|
|
19312
|
+
const temporary = resolve13(parent, `.${basename3(path)}.${process.pid}.${randomUUID3()}.tmp`);
|
|
19272
19313
|
try {
|
|
19273
|
-
await
|
|
19314
|
+
await writeFile6(temporary, content, { mode: 384, flag: "wx" });
|
|
19274
19315
|
await chmod2(temporary, 384);
|
|
19275
19316
|
await rename2(temporary, path);
|
|
19276
19317
|
} finally {
|
|
@@ -19313,8 +19354,8 @@ function harnessStateDirsFromEnv(env) {
|
|
|
19313
19354
|
}
|
|
19314
19355
|
|
|
19315
19356
|
// apps/body/dist/attachment-delivery.js
|
|
19316
|
-
import { mkdir as
|
|
19317
|
-
import { basename as basename4, extname, join as
|
|
19357
|
+
import { mkdir as mkdir6, writeFile as writeFile7 } from "node:fs/promises";
|
|
19358
|
+
import { basename as basename4, extname, join as join5 } from "node:path";
|
|
19318
19359
|
var MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;
|
|
19319
19360
|
var MEDIA_TTL_HOURS = 24;
|
|
19320
19361
|
var EXPIRED_REASON = `expired: attachments are kept for ${MEDIA_TTL_HOURS} hours and these bytes are past that window`;
|
|
@@ -19334,7 +19375,7 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch) {
|
|
|
19334
19375
|
if (!attachments.length)
|
|
19335
19376
|
return [];
|
|
19336
19377
|
const taken = /* @__PURE__ */ new Set();
|
|
19337
|
-
await
|
|
19378
|
+
await mkdir6(dir, { recursive: true });
|
|
19338
19379
|
return Promise.all(attachments.map(async (attachment, index) => {
|
|
19339
19380
|
const tooLarge = (bytes) => ({
|
|
19340
19381
|
attachment,
|
|
@@ -19358,8 +19399,8 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch) {
|
|
|
19358
19399
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
19359
19400
|
if (bytes.length > MAX_ATTACHMENT_BYTES)
|
|
19360
19401
|
return tooLarge(bytes.length);
|
|
19361
|
-
const path =
|
|
19362
|
-
await
|
|
19402
|
+
const path = join5(dir, safeFileName(attachment, index, taken));
|
|
19403
|
+
await writeFile7(path, bytes);
|
|
19363
19404
|
const mimeType = attachment.mimeType ?? response.headers.get("content-type") ?? "";
|
|
19364
19405
|
if (!mimeType.startsWith("image/"))
|
|
19365
19406
|
return { attachment, path };
|
|
@@ -19545,13 +19586,6 @@ function isCornerStatusRestatement(reply, systemLines) {
|
|
|
19545
19586
|
var TurnStoppedError = class extends Error {
|
|
19546
19587
|
name = "TurnStoppedError";
|
|
19547
19588
|
};
|
|
19548
|
-
function turnStopRequestId(item, agentId) {
|
|
19549
|
-
if (item.type !== "system" || !item.mentionIds.includes(agentId))
|
|
19550
|
-
return void 0;
|
|
19551
|
-
if (item.systemEvent?.kind !== "turn-cancelled")
|
|
19552
|
-
return void 0;
|
|
19553
|
-
return item.requestId || void 0;
|
|
19554
|
-
}
|
|
19555
19589
|
|
|
19556
19590
|
// apps/body/dist/turn-stream.js
|
|
19557
19591
|
function durableReplyText(agentText) {
|
|
@@ -19724,7 +19758,7 @@ function sessionConfigFingerprint(input) {
|
|
|
19724
19758
|
}
|
|
19725
19759
|
|
|
19726
19760
|
// apps/body/dist/pi-mcp-bridge.js
|
|
19727
|
-
import { mkdir as
|
|
19761
|
+
import { mkdir as mkdir7 } from "node:fs/promises";
|
|
19728
19762
|
import { resolve as resolve14 } from "node:path";
|
|
19729
19763
|
var PI_MCP_BRIDGE_FILENAME = "beeline-mcp-bridge.js";
|
|
19730
19764
|
function harnessMountsSessionMcpServers(agentCommand) {
|
|
@@ -19748,7 +19782,7 @@ async function installPiMcpBridge(input) {
|
|
|
19748
19782
|
const directory = resolve14(input.piHome, "extensions");
|
|
19749
19783
|
const path = resolve14(directory, PI_MCP_BRIDGE_FILENAME);
|
|
19750
19784
|
try {
|
|
19751
|
-
await
|
|
19785
|
+
await mkdir7(directory, { recursive: true, mode: 448 });
|
|
19752
19786
|
await writeIsolatedHarnessFile(path, piMcpBridgeSource(input.servers));
|
|
19753
19787
|
return path;
|
|
19754
19788
|
} catch (error) {
|
|
@@ -20153,6 +20187,7 @@ function beelineAgentMcpServer(config, api, context) {
|
|
|
20153
20187
|
args: [...config.readonlyMcpArgs ?? []],
|
|
20154
20188
|
env: [
|
|
20155
20189
|
{ name: "BEELINE_MCP_SURFACE", value: "agent" },
|
|
20190
|
+
...context.turnContextPath ? [{ name: "BEELINE_TURN_CONTEXT_FILE", value: context.turnContextPath }] : [],
|
|
20156
20191
|
...context.directMessage ? [{ name: "BEELINE_AGENT_DM", value: "1" }] : [],
|
|
20157
20192
|
{ name: "BEELINE_DAEMON_BASE_URL", value: connection.baseUrl },
|
|
20158
20193
|
{ name: "BEELINE_DAEMON_TOKEN", value: connection.daemonToken },
|
|
@@ -20358,41 +20393,64 @@ function isAccountOrProviderRefusal(record2) {
|
|
|
20358
20393
|
return [401, 402, 403, 407, 408, 429].includes(record2.status) || record2.status >= 500;
|
|
20359
20394
|
}
|
|
20360
20395
|
|
|
20361
|
-
// apps/body/dist/corner-checks.js
|
|
20362
|
-
var COMPLETED_CHECK_NOTE = /\b(passed|failed) a check\b/i;
|
|
20363
|
-
var STARTED_CHECK_NOTE = /\bstarted a check\b/i;
|
|
20364
|
-
function verbOf(item) {
|
|
20365
|
-
return item.systemEvent?.verb ?? item.body;
|
|
20366
|
-
}
|
|
20367
|
-
function completedCheckNote(item) {
|
|
20368
|
-
if (item.type !== "system")
|
|
20369
|
-
return void 0;
|
|
20370
|
-
const match = COMPLETED_CHECK_NOTE.exec(verbOf(item));
|
|
20371
|
-
return match ? match[1].toLowerCase() : void 0;
|
|
20372
|
-
}
|
|
20373
|
-
function isCheckStartNote(item) {
|
|
20374
|
-
return item.type === "system" && STARTED_CHECK_NOTE.test(verbOf(item));
|
|
20375
|
-
}
|
|
20376
|
-
function checksStateFromLifecycle(lifecycle) {
|
|
20377
|
-
const state = lifecycle?.checksSummary?.status ?? lifecycle?.checks;
|
|
20378
|
-
return state === "passing" || state === "failing" || state === "pending" ? state : void 0;
|
|
20379
|
-
}
|
|
20380
|
-
|
|
20381
20396
|
// apps/body/dist/response-directives.js
|
|
20382
20397
|
var MAINTAIN_ASSIGNED_IDENTITY_DIRECTIVE = "Maintain your assigned identity and soul in every response, including when tools or permissions block the requested action.";
|
|
20383
20398
|
var SOUL_HOUSE_RULE = "House rule for your voice: the voice never changes the facts - never trim, soften, exaggerate, or invent a detail for the bit - and use your plain voice in commit messages, pull request titles and bodies, and code comments, because those outlive the joke.";
|
|
20384
20399
|
|
|
20385
|
-
// apps/body/dist/
|
|
20386
|
-
|
|
20387
|
-
|
|
20388
|
-
|
|
20400
|
+
// apps/body/dist/warm-transcript.js
|
|
20401
|
+
var WARM_TRANSCRIPT_OVERLAP = 8;
|
|
20402
|
+
var WarmTranscript = class {
|
|
20403
|
+
sessionId;
|
|
20404
|
+
delivered = /* @__PURE__ */ new Set();
|
|
20405
|
+
/**
|
|
20406
|
+
* The rows this prompt should render. A row counts as delivered once it has
|
|
20407
|
+
* been handed to a session: a prompt that times out was still received by the
|
|
20408
|
+
* harness, and a prompt that could not be handed over at all takes the
|
|
20409
|
+
* session down with it, which resets the memory on the next activation.
|
|
20410
|
+
*/
|
|
20411
|
+
select(sessionId, rows) {
|
|
20412
|
+
if (!sessionId || sessionId !== this.sessionId) {
|
|
20413
|
+
this.sessionId = sessionId;
|
|
20414
|
+
this.delivered.clear();
|
|
20415
|
+
}
|
|
20416
|
+
const overlapFrom = Math.max(0, rows.length - WARM_TRANSCRIPT_OVERLAP);
|
|
20417
|
+
const selected = rows.filter((row, index) => index >= overlapFrom || !this.delivered.has(row.id));
|
|
20418
|
+
for (const row of rows)
|
|
20419
|
+
this.delivered.add(row.id);
|
|
20420
|
+
return { rows: selected, elided: rows.length - selected.length };
|
|
20421
|
+
}
|
|
20422
|
+
/** Render a selection, and say plainly when it is only what is new. */
|
|
20423
|
+
static render(selection, whole, sinceLastTurn) {
|
|
20424
|
+
const transcript = selection.rows.map((row) => row.line).join("\n");
|
|
20425
|
+
if (!transcript)
|
|
20426
|
+
return "";
|
|
20427
|
+
return `${selection.elided ? sinceLastTurn : whole}
|
|
20428
|
+
${transcript}`;
|
|
20429
|
+
}
|
|
20430
|
+
};
|
|
20389
20431
|
|
|
20390
|
-
//
|
|
20391
|
-
var
|
|
20392
|
-
|
|
20432
|
+
// apps/body/dist/turn-receipt-heartbeat.js
|
|
20433
|
+
var TURN_RECEIPT_HEARTBEAT_MS = 3e4;
|
|
20434
|
+
async function withTurnReceiptHeartbeat(api, receipt, task, onHeartbeatError) {
|
|
20435
|
+
let tail = Promise.resolve();
|
|
20436
|
+
const timer = setInterval(() => {
|
|
20437
|
+
tail = tail.catch(() => void 0).then(() => api.execute("postAgentTurnReceipt", {
|
|
20438
|
+
...receipt,
|
|
20439
|
+
status: "working",
|
|
20440
|
+
heartbeat: true
|
|
20441
|
+
})).then(() => void 0).catch(onHeartbeatError);
|
|
20442
|
+
}, TURN_RECEIPT_HEARTBEAT_MS);
|
|
20443
|
+
timer.unref?.();
|
|
20444
|
+
try {
|
|
20445
|
+
return await task();
|
|
20446
|
+
} finally {
|
|
20447
|
+
clearInterval(timer);
|
|
20448
|
+
await tail;
|
|
20449
|
+
}
|
|
20450
|
+
}
|
|
20393
20451
|
|
|
20394
20452
|
// apps/body/dist/turn-trace.js
|
|
20395
|
-
import { appendFile, mkdir as
|
|
20453
|
+
import { appendFile, mkdir as mkdir8, readdir as readdir4, rm as rm3 } from "node:fs/promises";
|
|
20396
20454
|
import { resolve as resolve17 } from "node:path";
|
|
20397
20455
|
import { performance as performance2 } from "node:perf_hooks";
|
|
20398
20456
|
var TURN_PHASES = [
|
|
@@ -20646,7 +20704,7 @@ var TurnTraceFile = class {
|
|
|
20646
20704
|
this.tail = this.tail.catch(() => void 0).then(async () => {
|
|
20647
20705
|
const now2 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))();
|
|
20648
20706
|
const path = this.path(now2);
|
|
20649
|
-
await
|
|
20707
|
+
await mkdir8(this.directory, { recursive: true, mode: 448 });
|
|
20650
20708
|
await appendFile(path, `${JSON.stringify(record2)}
|
|
20651
20709
|
`, { mode: 384 });
|
|
20652
20710
|
await this.prune(now2);
|
|
@@ -20668,58 +20726,65 @@ var TurnTraceFile = class {
|
|
|
20668
20726
|
}
|
|
20669
20727
|
};
|
|
20670
20728
|
|
|
20671
|
-
// apps/body/dist/
|
|
20672
|
-
|
|
20673
|
-
|
|
20674
|
-
|
|
20675
|
-
|
|
20676
|
-
|
|
20677
|
-
|
|
20678
|
-
|
|
20679
|
-
|
|
20680
|
-
|
|
20681
|
-
|
|
20682
|
-
}
|
|
20683
|
-
|
|
20684
|
-
|
|
20685
|
-
|
|
20686
|
-
|
|
20687
|
-
|
|
20688
|
-
|
|
20729
|
+
// apps/body/dist/corner-github-auth.js
|
|
20730
|
+
import { chmod as chmod3, mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
|
|
20731
|
+
import { delimiter as delimiter2, resolve as resolve18 } from "node:path";
|
|
20732
|
+
async function installCornerGitHubWrappers(input) {
|
|
20733
|
+
const bin = resolve18(input.root, "beeline-github-bin");
|
|
20734
|
+
await mkdir9(bin, { recursive: true, mode: 448 });
|
|
20735
|
+
const common = {
|
|
20736
|
+
node: process.execPath,
|
|
20737
|
+
cli: input.cliEntrypoint,
|
|
20738
|
+
config: input.runtimeConfigPath,
|
|
20739
|
+
room: input.roomId
|
|
20740
|
+
};
|
|
20741
|
+
await writeLauncher(resolve18(bin, "git"), { ...common, command: input.gitBinary });
|
|
20742
|
+
if (input.ghBinary)
|
|
20743
|
+
await writeLauncher(resolve18(bin, "gh"), { ...common, command: input.ghBinary });
|
|
20744
|
+
return {
|
|
20745
|
+
PATH: [bin, input.inheritedPath].filter(Boolean).join(delimiter2),
|
|
20746
|
+
// Static startup tokens take precedence over the refreshed token in gh.
|
|
20747
|
+
GH_TOKEN: "",
|
|
20748
|
+
GITHUB_TOKEN: ""
|
|
20749
|
+
};
|
|
20750
|
+
}
|
|
20751
|
+
async function writeLauncher(path, config) {
|
|
20752
|
+
const source = `#!/usr/bin/env node
|
|
20753
|
+
import { spawnSync } from 'node:child_process';
|
|
20754
|
+
const config = ${JSON.stringify(config)};
|
|
20755
|
+
const authFailure = /(?:authentication failed|bad credentials|could not read username|http(?:\\/\\d(?:\\.\\d)?)? 40[13]|status (?:code )?40[13])/i;
|
|
20756
|
+
function token() {
|
|
20757
|
+
const result = spawnSync(config.node, [config.cli, 'corner-read-token', '--config', config.config, '--room', config.room], { encoding: 'utf8' });
|
|
20758
|
+
if (result.status !== 0) {
|
|
20759
|
+
process.stderr.write(result.stderr || 'Beeline could not refresh the repository credential.\\n');
|
|
20760
|
+
process.exit(result.status || 1);
|
|
20689
20761
|
}
|
|
20762
|
+
return result.stdout.trim();
|
|
20763
|
+
}
|
|
20764
|
+
function run(value) {
|
|
20765
|
+
const env = { ...process.env, GH_TOKEN: value, GITHUB_TOKEN: value, GIT_TERMINAL_PROMPT: '0' };
|
|
20766
|
+
return spawnSync(config.command, process.argv.slice(2), { env, encoding: 'buffer', stdio: ['inherit', 'pipe', 'pipe'] });
|
|
20767
|
+
}
|
|
20768
|
+
let result = run(token());
|
|
20769
|
+
const diagnostic = Buffer.concat([result.stdout || Buffer.alloc(0), result.stderr || Buffer.alloc(0)]).toString('utf8');
|
|
20770
|
+
if (result.status !== 0 && authFailure.test(diagnostic)) result = run(token());
|
|
20771
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
20772
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
20773
|
+
if (result.error) throw result.error;
|
|
20774
|
+
process.exit(result.status ?? 1);
|
|
20775
|
+
`;
|
|
20776
|
+
await writeFile8(path, source, { mode: 448 });
|
|
20777
|
+
await chmod3(path, 448);
|
|
20690
20778
|
}
|
|
20691
20779
|
|
|
20692
|
-
// apps/body/dist/
|
|
20693
|
-
|
|
20694
|
-
|
|
20695
|
-
|
|
20696
|
-
|
|
20697
|
-
|
|
20698
|
-
|
|
20699
|
-
|
|
20700
|
-
* harness, and a prompt that could not be handed over at all takes the
|
|
20701
|
-
* session down with it, which resets the memory on the next activation.
|
|
20702
|
-
*/
|
|
20703
|
-
select(sessionId, rows) {
|
|
20704
|
-
if (!sessionId || sessionId !== this.sessionId) {
|
|
20705
|
-
this.sessionId = sessionId;
|
|
20706
|
-
this.delivered.clear();
|
|
20707
|
-
}
|
|
20708
|
-
const overlapFrom = Math.max(0, rows.length - WARM_TRANSCRIPT_OVERLAP);
|
|
20709
|
-
const selected = rows.filter((row, index) => index >= overlapFrom || !this.delivered.has(row.id));
|
|
20710
|
-
for (const row of rows)
|
|
20711
|
-
this.delivered.add(row.id);
|
|
20712
|
-
return { rows: selected, elided: rows.length - selected.length };
|
|
20713
|
-
}
|
|
20714
|
-
/** Render a selection, and say plainly when it is only what is new. */
|
|
20715
|
-
static render(selection, whole, sinceLastTurn) {
|
|
20716
|
-
const transcript = selection.rows.map((row) => row.line).join("\n");
|
|
20717
|
-
if (!transcript)
|
|
20718
|
-
return "";
|
|
20719
|
-
return `${selection.elided ? sinceLastTurn : whole}
|
|
20720
|
-
${transcript}`;
|
|
20721
|
-
}
|
|
20722
|
-
};
|
|
20780
|
+
// apps/body/dist/monolith-room-turn.js
|
|
20781
|
+
import { mkdir as mkdir10 } from "node:fs/promises";
|
|
20782
|
+
import { homedir as homedir6 } from "node:os";
|
|
20783
|
+
import { join as join6 } from "node:path";
|
|
20784
|
+
|
|
20785
|
+
// packages/api-contract/dist/scheduled-prompts.js
|
|
20786
|
+
var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
|
|
20787
|
+
var SCHEDULE_RAN_VERB = "ran a schedule for";
|
|
20723
20788
|
|
|
20724
20789
|
// apps/body/dist/monolith-room-turn.js
|
|
20725
20790
|
function isRoomMcpPermissionRequest(request, mountedServers = ROOM_MOUNTED_MCP_SERVERS) {
|
|
@@ -20727,15 +20792,6 @@ function isRoomMcpPermissionRequest(request, mountedServers = ROOM_MOUNTED_MCP_S
|
|
|
20727
20792
|
return false;
|
|
20728
20793
|
return isMountedMcpToolPermissionRequest(request, mountedServers);
|
|
20729
20794
|
}
|
|
20730
|
-
function roomPrincipalMayAddressAgent(authority, humanPermitted) {
|
|
20731
|
-
if (!authority.member)
|
|
20732
|
-
return false;
|
|
20733
|
-
if (authority.principalKind === "agent")
|
|
20734
|
-
return true;
|
|
20735
|
-
if (authority.principalKind !== "human")
|
|
20736
|
-
return false;
|
|
20737
|
-
return authority.mayAddressAgent ?? humanPermitted;
|
|
20738
|
-
}
|
|
20739
20795
|
function isScheduledPrompt(item, agentId) {
|
|
20740
20796
|
if (item.type !== "system" || !item.mentionIds.includes(agentId))
|
|
20741
20797
|
return false;
|
|
@@ -20754,30 +20810,6 @@ function inboxItemAuthorName(item, agentId, names) {
|
|
|
20754
20810
|
function inboxItemPromptBody(item, agentId) {
|
|
20755
20811
|
return isScheduledPrompt(item, agentId) ? item.systemEvent?.consequence ?? item.body : item.body;
|
|
20756
20812
|
}
|
|
20757
|
-
function isSubscribedEvent(item, agentId) {
|
|
20758
|
-
const kind = item.systemEvent?.kind;
|
|
20759
|
-
return item.type === "system" && kind !== void 0 && !isResumeKind(kind) && !isControlKind(kind) && item.mentionIds.includes(agentId);
|
|
20760
|
-
}
|
|
20761
|
-
function inboxItemSkipsSenderPolicy(item, agentId) {
|
|
20762
|
-
if (isGrantDecisionLine(item, agentId))
|
|
20763
|
-
return true;
|
|
20764
|
-
if (item.type !== "system" || !item.mentionIds.includes(agentId))
|
|
20765
|
-
return false;
|
|
20766
|
-
const kind = item.systemEvent?.kind;
|
|
20767
|
-
return kind === void 0 ? isScheduledPrompt(item, agentId) : isServerEventKind(kind);
|
|
20768
|
-
}
|
|
20769
|
-
function isGrantDecisionLine(item, agentId) {
|
|
20770
|
-
return item.type === "system" && item.mentionIds.includes(agentId) && parseGrantDecisionLine(item.body) !== void 0;
|
|
20771
|
-
}
|
|
20772
|
-
function inboxItemTriggersTurn(item, agentId, continuesExchange = false) {
|
|
20773
|
-
if (item.authorId === agentId)
|
|
20774
|
-
return false;
|
|
20775
|
-
if (item.type === "message" && continuesExchange)
|
|
20776
|
-
return true;
|
|
20777
|
-
if (!item.mentionIds.includes(agentId))
|
|
20778
|
-
return false;
|
|
20779
|
-
return item.type === "message" || isSubscribedEvent(item, agentId) || isScheduledPrompt(item, agentId) || isGrantDecisionLine(item, agentId);
|
|
20780
|
-
}
|
|
20781
20813
|
function pendingGrantToolCall(call) {
|
|
20782
20814
|
if (!/(?:^|[._:/-])request_grant$/i.test(call.title ?? ""))
|
|
20783
20815
|
return false;
|
|
@@ -20800,6 +20832,7 @@ function roomMentionDirectory(roster, selfId) {
|
|
|
20800
20832
|
return "";
|
|
20801
20833
|
return [
|
|
20802
20834
|
"Room members, and the exact spelling that tags each one:",
|
|
20835
|
+
"An exact agent tag assigns that agent work; use it only when you are asking that agent to act.",
|
|
20803
20836
|
...rows,
|
|
20804
20837
|
"Write a tag exactly as spelled here. An @name spelled any other way is plain text: it reaches nobody, and nobody is told it was meant for them. Never invent a handle, shorten one, or copy an @name out of the conversation \u2014 old messages carry spellings that no longer exist."
|
|
20805
20838
|
].join("\n");
|
|
@@ -20812,7 +20845,8 @@ function agentReplyMentionIds(text2, roster, authorId) {
|
|
|
20812
20845
|
for (const member of roster.members) {
|
|
20813
20846
|
if (member.identityId === authorId)
|
|
20814
20847
|
continue;
|
|
20815
|
-
|
|
20848
|
+
const rawAliases = member.kind === "agent" ? [member.handle] : [member.name, member.handle, member.soul?.name];
|
|
20849
|
+
for (const raw of rawAliases) {
|
|
20816
20850
|
const display = raw?.trim().replace(/^@/, "");
|
|
20817
20851
|
if (!display)
|
|
20818
20852
|
continue;
|
|
@@ -20823,7 +20857,7 @@ function agentReplyMentionIds(text2, roster, authorId) {
|
|
|
20823
20857
|
}
|
|
20824
20858
|
}
|
|
20825
20859
|
for (const member of roster.members) {
|
|
20826
|
-
if (member.identityId === authorId || !member.handle)
|
|
20860
|
+
if (member.identityId === authorId || member.kind === "agent" || !member.handle)
|
|
20827
20861
|
continue;
|
|
20828
20862
|
const handle = member.handle.trim().replace(/^@/, "").toLocaleLowerCase();
|
|
20829
20863
|
const canonical = aliases.get(handle);
|
|
@@ -20846,12 +20880,11 @@ function agentReplyMentionIds(text2, roster, authorId) {
|
|
|
20846
20880
|
}
|
|
20847
20881
|
var MonolithRoomTurnLoop = class {
|
|
20848
20882
|
options;
|
|
20883
|
+
commandContext;
|
|
20849
20884
|
agent;
|
|
20850
|
-
reconciliationRequested = true;
|
|
20851
20885
|
wakeIntake;
|
|
20852
20886
|
/** Called by the daemon's one slow workspace reconciliation sweep. */
|
|
20853
20887
|
requestReconciliation() {
|
|
20854
|
-
this.reconciliationRequested = true;
|
|
20855
20888
|
this.wakeIntake?.();
|
|
20856
20889
|
this.wakeIntake = void 0;
|
|
20857
20890
|
}
|
|
@@ -20869,7 +20902,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
20869
20902
|
turnInstructionPrefix = "";
|
|
20870
20903
|
activeTurn;
|
|
20871
20904
|
queuedTurns = [];
|
|
20872
|
-
continuityRebuildRequested = false;
|
|
20873
20905
|
/** Session scratch directory attachments are downloaded into (`TMPDIR/beeline-attachments`). */
|
|
20874
20906
|
attachmentDir;
|
|
20875
20907
|
/** Whether the pinned model takes images; `undefined` when the pin did not say. */
|
|
@@ -20888,18 +20920,21 @@ var MonolithRoomTurnLoop = class {
|
|
|
20888
20920
|
pausedOnGrantRequestId;
|
|
20889
20921
|
/** Operator-local turn traces; built once when the daemon configured a directory. */
|
|
20890
20922
|
turnTraceSink;
|
|
20891
|
-
/** Per-sender continuity, shared in shape with corner intake. */
|
|
20892
|
-
responseRule = new AgentResponseRule();
|
|
20893
20923
|
constructor(options) {
|
|
20894
20924
|
this.options = options;
|
|
20895
20925
|
this.agent = runtimeIdentity(options.runtime.agent);
|
|
20926
|
+
this.commandContext = new CommandExecutionContext(options.config.agentHomeRoot);
|
|
20927
|
+
this.options = { ...options, api: this.commandContext.bind(options.api) };
|
|
20896
20928
|
options.grantRunner?.register(options.roomId, {
|
|
20897
20929
|
workspaceId: options.workspaceId,
|
|
20898
20930
|
cwd: options.cwd,
|
|
20899
20931
|
// A top-level Room keeps its read-only promise for grants too: the runner
|
|
20900
20932
|
// wraps the command in this Room's own mount table (C94).
|
|
20901
20933
|
writePolicy: () => this.grantWritePolicy(),
|
|
20902
|
-
turn: () =>
|
|
20934
|
+
turn: () => {
|
|
20935
|
+
const turn = this.currentTurnForRunner();
|
|
20936
|
+
return turn ? { ...turn, generationId: this.commandContext.generationId } : void 0;
|
|
20937
|
+
}
|
|
20903
20938
|
});
|
|
20904
20939
|
}
|
|
20905
20940
|
isBusy() {
|
|
@@ -20952,9 +20987,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
20952
20987
|
const name = this.memberNames.get(authorId);
|
|
20953
20988
|
return { pubkey: authorId, ...name ? { name } : {} };
|
|
20954
20989
|
}
|
|
20955
|
-
currentPrincipalCanDrive(_workspaceId, principalId) {
|
|
20956
|
-
return Promise.resolve(isSenderPermitted(this.options.config.accessPolicy ?? LEGACY_ACCESS_POLICY, principalId, this.options.config.accessOwnerPubkey, this.options.config.accessAllowlist));
|
|
20957
|
-
}
|
|
20958
20990
|
async refreshPersonaForSoulUpdate() {
|
|
20959
20991
|
await this.options.scheduler.suspend(this.options.roomId);
|
|
20960
20992
|
}
|
|
@@ -20971,7 +21003,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
20971
21003
|
workspaceId: this.options.workspaceId
|
|
20972
21004
|
});
|
|
20973
21005
|
this.memberNames = new Map(roster.members.map((member) => [member.identityId, member.name]));
|
|
20974
|
-
this.responseRule.setAgents(roster.members.filter((member) => member.kind === "agent").map((member) => member.identityId));
|
|
20975
21006
|
return roster;
|
|
20976
21007
|
}
|
|
20977
21008
|
/**
|
|
@@ -20993,7 +21024,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
20993
21024
|
const cached = this.deliveredAttachments.get(item.id);
|
|
20994
21025
|
if (cached)
|
|
20995
21026
|
return cached;
|
|
20996
|
-
const delivered = await deliverAttachments(item.attachments,
|
|
21027
|
+
const delivered = await deliverAttachments(item.attachments, join6(this.attachmentDir, item.id.replace(/[^\w-]/g, "_")), this.options.fetchImpl);
|
|
20997
21028
|
this.deliveredAttachments.set(item.id, withoutImageData(delivered));
|
|
20998
21029
|
return delivered;
|
|
20999
21030
|
}
|
|
@@ -21060,7 +21091,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21060
21091
|
agentName: self?.name ?? this.agent.name
|
|
21061
21092
|
});
|
|
21062
21093
|
const directMessage = Array.isArray(repositoryState.directParticipants) && repositoryState.directParticipants.length === 2;
|
|
21063
|
-
await
|
|
21094
|
+
await mkdir10(this.options.cwd, { recursive: true });
|
|
21064
21095
|
const selection = configuration.model || configuration.effort ? { model: configuration.model, effort: configuration.effort } : this.options.config.modelSelection;
|
|
21065
21096
|
const homeOverlay = this.options.config.agentHomeRoot ? await prepareRoomAgentHome({
|
|
21066
21097
|
root: this.options.config.agentHomeRoot,
|
|
@@ -21086,14 +21117,14 @@ var MonolithRoomTurnLoop = class {
|
|
|
21086
21117
|
}, selection);
|
|
21087
21118
|
const operatorHome = this.options.config.operatorHome ?? homedir6();
|
|
21088
21119
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
21089
|
-
this.attachmentDir = tmpDir ?
|
|
21120
|
+
this.attachmentDir = tmpDir ? join6(tmpDir, "beeline-attachments") : void 0;
|
|
21090
21121
|
this.sessionScratchDir = tmpDir;
|
|
21091
21122
|
this.sessionStateDirs = stateDirs;
|
|
21092
21123
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
21093
|
-
await Promise.all(homeStateDirs.map((dir) =>
|
|
21124
|
+
await Promise.all(homeStateDirs.map((dir) => mkdir10(dir, { recursive: true })));
|
|
21094
21125
|
const attachScratchRoot = this.options.config.agentHomeRoot ?? tmpDir;
|
|
21095
21126
|
if (attachScratchRoot)
|
|
21096
|
-
await
|
|
21127
|
+
await mkdir10(attachScratchRoot, { recursive: true });
|
|
21097
21128
|
const spawnCommand = wrapAgentCommand({
|
|
21098
21129
|
bwrapPath: this.options.config.bwrapPath,
|
|
21099
21130
|
spec: {
|
|
@@ -21119,6 +21150,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21119
21150
|
// images dir, say), so anything inside the overlay it could possibly
|
|
21120
21151
|
// have written must be attachable, whatever subdirectory that is.
|
|
21121
21152
|
attachScratchRoot,
|
|
21153
|
+
turnContextPath: this.commandContext.path,
|
|
21122
21154
|
directMessage,
|
|
21123
21155
|
...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
|
|
21124
21156
|
})
|
|
@@ -21251,8 +21283,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
21251
21283
|
}).finally(() => {
|
|
21252
21284
|
if (this.activeTurn === active) {
|
|
21253
21285
|
this.activeTurn = void 0;
|
|
21254
|
-
if (active.rebuildContinuity)
|
|
21255
|
-
this.continuityRebuildRequested = true;
|
|
21256
21286
|
this.wakeIntake?.();
|
|
21257
21287
|
this.wakeIntake = void 0;
|
|
21258
21288
|
}
|
|
@@ -21279,24 +21309,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
21279
21309
|
if (this.client && this.sessionId)
|
|
21280
21310
|
this.client.sessionCancel(this.sessionId);
|
|
21281
21311
|
}
|
|
21282
|
-
steer(active, item) {
|
|
21283
|
-
active.steers.push(item);
|
|
21284
|
-
active.steerTail = active.steerTail.catch(() => void 0).then(async () => {
|
|
21285
|
-
try {
|
|
21286
|
-
const [roster, delivered] = await Promise.all([this.roster(), this.deliver(item)]);
|
|
21287
|
-
const author = roster.members.find((member) => member.identityId === item.authorId)?.name ?? item.authorId.slice(0, 12);
|
|
21288
|
-
await this.client.sessionSteer(this.sessionId, [
|
|
21289
|
-
`Human steer received while the current turn is running from ${author}:`,
|
|
21290
|
-
roomMessagePrompt("", item.body, item.attachments, delivered, this.acceptsImages()),
|
|
21291
|
-
"Adjust the current work now. Keep the original request and earlier messages as context."
|
|
21292
|
-
].join("\n\n"));
|
|
21293
|
-
} catch (error) {
|
|
21294
|
-
active.resumeRequested = true;
|
|
21295
|
-
this.client?.sessionCancel(this.sessionId);
|
|
21296
|
-
console.warn(`[thin-core] monolith Room ${this.options.roomId} live steer unavailable; cancelling and resuming:`, error);
|
|
21297
|
-
}
|
|
21298
|
-
});
|
|
21299
|
-
}
|
|
21300
21312
|
async prompt(active) {
|
|
21301
21313
|
const { item } = active;
|
|
21302
21314
|
const api = this.options.api;
|
|
@@ -21309,7 +21321,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21309
21321
|
agentId: this.agent.publicKey,
|
|
21310
21322
|
roomId: this.options.roomId,
|
|
21311
21323
|
requestId: item.id,
|
|
21312
|
-
generationId:
|
|
21324
|
+
generationId: this.commandContext.generationId
|
|
21313
21325
|
}, async () => {
|
|
21314
21326
|
await api.execute("postAgentActivity", {
|
|
21315
21327
|
agentId: this.agent.publicKey,
|
|
@@ -21339,7 +21351,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21339
21351
|
id: message.id,
|
|
21340
21352
|
line: roomMessagePrompt(names.get(message.authorId) ?? message.authorId.slice(0, 12), message.body, message.attachments, this.deliveredAttachments.get(message.id), this.acceptsImages())
|
|
21341
21353
|
}));
|
|
21342
|
-
const grantDecision =
|
|
21354
|
+
const grantDecision = this.commandContext.current?.action === "resume";
|
|
21343
21355
|
const resumedRequestId = grantDecision ? this.pausedOnGrantRequestId : void 0;
|
|
21344
21356
|
if (grantDecision)
|
|
21345
21357
|
this.pausedOnGrantRequestId = void 0;
|
|
@@ -21417,8 +21429,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21417
21429
|
}
|
|
21418
21430
|
}
|
|
21419
21431
|
if (active.cancelled) {
|
|
21420
|
-
|
|
21421
|
-
await stream.settle(stoppedText, stoppedText ? { triggerMessageId: item.id } : {});
|
|
21432
|
+
stream.close();
|
|
21422
21433
|
throw new TurnStoppedError("turn stopped by the requester");
|
|
21423
21434
|
}
|
|
21424
21435
|
active.phase = "finishing";
|
|
@@ -21453,21 +21464,10 @@ var MonolithRoomTurnLoop = class {
|
|
|
21453
21464
|
reply = stripCornerOpenEcho(reply);
|
|
21454
21465
|
}
|
|
21455
21466
|
const mentionIds = reply ? agentReplyMentionIds(reply, roster, this.agent.publicKey) : [];
|
|
21456
|
-
const continuitySenders = reply ? [item.authorId, ...mentionIds] : [];
|
|
21457
|
-
if (continuitySenders.length) {
|
|
21458
|
-
active.continuitySenders = new Set(continuitySenders);
|
|
21459
|
-
active.rebuildContinuity = true;
|
|
21460
|
-
}
|
|
21461
21467
|
await trace.measure("publish", () => stream.settle(reply, reply ? {
|
|
21462
21468
|
triggerMessageId: item.id,
|
|
21463
21469
|
mentionIds
|
|
21464
|
-
} : {}
|
|
21465
|
-
this.responseRule.noteReply(this.agent.publicKey, [
|
|
21466
|
-
item.authorId,
|
|
21467
|
-
...posted.mentionIds ?? []
|
|
21468
|
-
]);
|
|
21469
|
-
active.rebuildContinuity = false;
|
|
21470
|
-
} : void 0));
|
|
21470
|
+
} : {}));
|
|
21471
21471
|
}, { priority: "interactive", roomKey: this.options.roomId });
|
|
21472
21472
|
}, (error) => console.error(`[thin-core] monolith Room ${this.options.roomId} receipt heartbeat failed:`, error));
|
|
21473
21473
|
await api.execute("postAgentTurnReceipt", {
|
|
@@ -21475,7 +21475,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21475
21475
|
roomId: this.options.roomId,
|
|
21476
21476
|
requestId: item.id,
|
|
21477
21477
|
status: "complete",
|
|
21478
|
-
generationId:
|
|
21478
|
+
generationId: this.commandContext.generationId
|
|
21479
21479
|
});
|
|
21480
21480
|
await trace.finish("complete");
|
|
21481
21481
|
} catch (error) {
|
|
@@ -21490,7 +21490,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21490
21490
|
roomId: this.options.roomId,
|
|
21491
21491
|
requestId: item.id,
|
|
21492
21492
|
status: "failed",
|
|
21493
|
-
generationId:
|
|
21493
|
+
generationId: this.commandContext.generationId,
|
|
21494
21494
|
reason
|
|
21495
21495
|
});
|
|
21496
21496
|
await trace.finish("failed", reason);
|
|
@@ -21501,137 +21501,37 @@ var MonolithRoomTurnLoop = class {
|
|
|
21501
21501
|
}
|
|
21502
21502
|
async run() {
|
|
21503
21503
|
const { api, roomId, signal } = this.options;
|
|
21504
|
-
let cursor3;
|
|
21505
|
-
const processedInboxIds = /* @__PURE__ */ new Set();
|
|
21506
|
-
const deferredContinuity = /* @__PURE__ */ new Map();
|
|
21507
|
-
const pushedInbox = [];
|
|
21508
|
-
let pendingPushedCursor;
|
|
21509
|
-
let liveConnected = false;
|
|
21510
|
-
let stopLive;
|
|
21511
21504
|
try {
|
|
21512
|
-
|
|
21513
|
-
|
|
21514
|
-
|
|
21515
|
-
|
|
21516
|
-
|
|
21517
|
-
|
|
21518
|
-
|
|
21519
|
-
|
|
21520
|
-
|
|
21521
|
-
|
|
21522
|
-
|
|
21523
|
-
|
|
21524
|
-
|
|
21525
|
-
|
|
21526
|
-
|
|
21527
|
-
|
|
21528
|
-
|
|
21529
|
-
|
|
21530
|
-
|
|
21531
|
-
|
|
21532
|
-
|
|
21533
|
-
|
|
21534
|
-
|
|
21535
|
-
|
|
21536
|
-
|
|
21537
|
-
|
|
21538
|
-
try {
|
|
21539
|
-
if (!this.activeTurn && this.continuityRebuildRequested) {
|
|
21540
|
-
const history2 = await api.execute("getRoomConversation", {
|
|
21541
|
-
roomId,
|
|
21542
|
-
limit: 200,
|
|
21543
|
-
window: "continuity"
|
|
21544
|
-
});
|
|
21545
|
-
this.responseRule.replaceHistory(history2.items);
|
|
21546
|
-
this.continuityRebuildRequested = false;
|
|
21547
|
-
}
|
|
21548
|
-
if (!this.activeTurn && deferredContinuity.size === 0 && this.queuedTurns.length) {
|
|
21549
|
-
this.startPrompt(this.queuedTurns.shift());
|
|
21550
|
-
}
|
|
21551
|
-
const pollNow = pushedInbox.length === 0 && (!liveConnected || this.reconciliationRequested);
|
|
21552
|
-
const inbox = !pollNow ? { items: [], cursor: void 0 } : await api.execute("getRoomInbox", {
|
|
21553
|
-
roomId,
|
|
21554
|
-
...cursor3 ? { after: cursor3 } : {},
|
|
21555
|
-
...rewindSupported ? { rewind: true } : {},
|
|
21556
|
-
limit: 200
|
|
21557
|
-
});
|
|
21558
|
-
if (pollNow) {
|
|
21559
|
-
this.reconciliationRequested = false;
|
|
21560
|
-
}
|
|
21561
|
-
const deferred = this.activeTurn ? [] : [...deferredContinuity.values()];
|
|
21562
|
-
if (!this.activeTurn)
|
|
21563
|
-
deferredContinuity.clear();
|
|
21564
|
-
const delivered = orderInboxItems([
|
|
21565
|
-
...deferred,
|
|
21566
|
-
...pushedInbox.splice(0),
|
|
21567
|
-
...inbox.items
|
|
21568
|
-
]);
|
|
21569
|
-
for (const item of delivered) {
|
|
21570
|
-
if (processedInboxIds.has(item.id) || deferredContinuity.has(item.id))
|
|
21571
|
-
continue;
|
|
21572
|
-
const triggers = inboxItemTriggersTurn(item, this.agent.publicKey, this.responseRule.continues(item, this.agent.publicKey));
|
|
21573
|
-
const finishing = this.activeTurn;
|
|
21574
|
-
if (!triggers && finishing?.phase === "finishing" && finishing.continuitySenders?.has(item.authorId) && item.type === "message" && !item.replyToMessageId) {
|
|
21575
|
-
deferredContinuity.set(item.id, item);
|
|
21576
|
-
continue;
|
|
21577
|
-
}
|
|
21578
|
-
processedInboxIds.add(item.id);
|
|
21579
|
-
while (processedInboxIds.size > INBOX_DEDUPLICATION_LIMIT)
|
|
21580
|
-
processedInboxIds.delete(processedInboxIds.values().next().value);
|
|
21581
|
-
const stopped = turnStopRequestId(item, this.agent.publicKey);
|
|
21582
|
-
if (stopped) {
|
|
21583
|
-
this.stopTurn(stopped);
|
|
21584
|
-
continue;
|
|
21585
|
-
}
|
|
21586
|
-
this.responseRule.observe(item);
|
|
21587
|
-
if (!triggers)
|
|
21588
|
-
continue;
|
|
21589
|
-
if (!inboxItemSkipsSenderPolicy(item, this.agent.publicKey)) {
|
|
21590
|
-
const authority = await api.execute("getRoomAuthority", {
|
|
21591
|
-
roomId,
|
|
21592
|
-
principalId: item.authorId
|
|
21593
|
-
});
|
|
21594
|
-
const humanPermitted = authority.principalKind === "human" ? await this.currentPrincipalCanDrive(this.options.workspaceId, item.authorId) : false;
|
|
21595
|
-
if (!roomPrincipalMayAddressAgent(authority, humanPermitted))
|
|
21596
|
-
continue;
|
|
21597
|
-
}
|
|
21598
|
-
const active = this.activeTurn;
|
|
21599
|
-
if (!active)
|
|
21600
|
-
this.startPrompt(item);
|
|
21601
|
-
else if (active.phase === "prompting")
|
|
21602
|
-
this.steer(active, item);
|
|
21603
|
-
else
|
|
21604
|
-
this.queuedTurns.push(item);
|
|
21605
|
-
}
|
|
21606
|
-
cursor3 = laterInboxCursor(cursor3, laterInboxCursor(inbox.cursor, pendingPushedCursor));
|
|
21607
|
-
pendingPushedCursor = void 0;
|
|
21608
|
-
api.updateLiveCursor?.(roomId, cursor3);
|
|
21609
|
-
if (pollNow)
|
|
21610
|
-
this.options.health.poll();
|
|
21611
|
-
if (!pushedInbox.length) {
|
|
21612
|
-
await Promise.race([
|
|
21613
|
-
wait(liveConnected ? 2147483647 : this.options.pollMs ?? 1e3, signal),
|
|
21614
|
-
new Promise((resolve30) => {
|
|
21615
|
-
this.wakeIntake = resolve30;
|
|
21616
|
-
})
|
|
21617
|
-
]);
|
|
21618
|
-
}
|
|
21619
|
-
} catch (error) {
|
|
21620
|
-
if (signal?.aborted)
|
|
21621
|
-
break;
|
|
21622
|
-
this.options.health.failure(1e3);
|
|
21623
|
-
console.error(`[thin-core] monolith Room ${roomId} turn loop failed:`, error);
|
|
21624
|
-
await wait(1e3, signal);
|
|
21505
|
+
await runServerCommandIntake({
|
|
21506
|
+
api,
|
|
21507
|
+
roomId,
|
|
21508
|
+
agentId: this.agent.publicKey,
|
|
21509
|
+
context: this.commandContext,
|
|
21510
|
+
signal,
|
|
21511
|
+
pollMs: this.options.pollMs,
|
|
21512
|
+
presence: {
|
|
21513
|
+
...this.options.config.daemonReleaseVersion ? { releaseVersion: this.options.config.daemonReleaseVersion } : {},
|
|
21514
|
+
...this.options.config.daemonSourceSha ? { sourceSha: this.options.config.daemonSourceSha } : {},
|
|
21515
|
+
available: !this.options.config.modelUnavailable
|
|
21516
|
+
},
|
|
21517
|
+
onWake: (wake) => {
|
|
21518
|
+
this.wakeIntake = wake;
|
|
21519
|
+
},
|
|
21520
|
+
onPoll: () => this.options.health.poll(),
|
|
21521
|
+
onError: (error) => console.error("[thin-core] Room command failed", error),
|
|
21522
|
+
stop: (requestId) => this.stopTurn(requestId),
|
|
21523
|
+
run: async (command) => {
|
|
21524
|
+
const item = {
|
|
21525
|
+
...command.source,
|
|
21526
|
+
id: command.turnRequestId,
|
|
21527
|
+
body: command.action === "resume" ? `Resume the paused turn. The server supplied this grant decision: ${command.source.body}` : command.source.body
|
|
21528
|
+
};
|
|
21529
|
+
this.startPrompt(item);
|
|
21530
|
+
await this.activeTurn?.promise;
|
|
21625
21531
|
}
|
|
21626
|
-
}
|
|
21532
|
+
});
|
|
21627
21533
|
} finally {
|
|
21628
|
-
stopLive?.();
|
|
21629
|
-
this.wakeIntake = void 0;
|
|
21630
21534
|
this.options.grantRunner?.unregister(roomId);
|
|
21631
|
-
if (this.activeTurn?.phase === "prompting" && this.client && this.sessionId) {
|
|
21632
|
-
this.client.sessionCancel(this.sessionId);
|
|
21633
|
-
}
|
|
21634
|
-
await this.activeTurn?.promise;
|
|
21635
21535
|
await this.options.scheduler.suspend(roomId);
|
|
21636
21536
|
}
|
|
21637
21537
|
}
|
|
@@ -21641,70 +21541,6 @@ function roomMessagePrompt(author, body, attachments, delivered, harnessAcceptsI
|
|
|
21641
21541
|
const rendered = author ? `${author}: ${message}` : message;
|
|
21642
21542
|
return [rendered, ...attachmentPromptLines(attachments, delivered, harnessAcceptsImages)].join("\n");
|
|
21643
21543
|
}
|
|
21644
|
-
async function wait(ms, signal) {
|
|
21645
|
-
if (signal?.aborted)
|
|
21646
|
-
return;
|
|
21647
|
-
await new Promise((resolveWait) => {
|
|
21648
|
-
const done = () => {
|
|
21649
|
-
clearTimeout(timer);
|
|
21650
|
-
signal?.removeEventListener("abort", done);
|
|
21651
|
-
resolveWait();
|
|
21652
|
-
};
|
|
21653
|
-
const timer = setTimeout(done, ms);
|
|
21654
|
-
signal?.addEventListener("abort", done, { once: true });
|
|
21655
|
-
});
|
|
21656
|
-
}
|
|
21657
|
-
|
|
21658
|
-
// apps/body/dist/corner-github-auth.js
|
|
21659
|
-
import { chmod as chmod3, mkdir as mkdir9, writeFile as writeFile7 } from "node:fs/promises";
|
|
21660
|
-
import { delimiter as delimiter2, resolve as resolve18 } from "node:path";
|
|
21661
|
-
async function installCornerGitHubWrappers(input) {
|
|
21662
|
-
const bin = resolve18(input.root, "beeline-github-bin");
|
|
21663
|
-
await mkdir9(bin, { recursive: true, mode: 448 });
|
|
21664
|
-
const common = {
|
|
21665
|
-
node: process.execPath,
|
|
21666
|
-
cli: input.cliEntrypoint,
|
|
21667
|
-
config: input.runtimeConfigPath,
|
|
21668
|
-
room: input.roomId
|
|
21669
|
-
};
|
|
21670
|
-
await writeLauncher(resolve18(bin, "git"), { ...common, command: input.gitBinary });
|
|
21671
|
-
if (input.ghBinary)
|
|
21672
|
-
await writeLauncher(resolve18(bin, "gh"), { ...common, command: input.ghBinary });
|
|
21673
|
-
return {
|
|
21674
|
-
PATH: [bin, input.inheritedPath].filter(Boolean).join(delimiter2),
|
|
21675
|
-
// Static startup tokens take precedence over the refreshed token in gh.
|
|
21676
|
-
GH_TOKEN: "",
|
|
21677
|
-
GITHUB_TOKEN: ""
|
|
21678
|
-
};
|
|
21679
|
-
}
|
|
21680
|
-
async function writeLauncher(path, config) {
|
|
21681
|
-
const source = `#!/usr/bin/env node
|
|
21682
|
-
import { spawnSync } from 'node:child_process';
|
|
21683
|
-
const config = ${JSON.stringify(config)};
|
|
21684
|
-
const authFailure = /(?:authentication failed|bad credentials|could not read username|http(?:\\/\\d(?:\\.\\d)?)? 40[13]|status (?:code )?40[13])/i;
|
|
21685
|
-
function token() {
|
|
21686
|
-
const result = spawnSync(config.node, [config.cli, 'corner-read-token', '--config', config.config, '--room', config.room], { encoding: 'utf8' });
|
|
21687
|
-
if (result.status !== 0) {
|
|
21688
|
-
process.stderr.write(result.stderr || 'Beeline could not refresh the repository credential.\\n');
|
|
21689
|
-
process.exit(result.status || 1);
|
|
21690
|
-
}
|
|
21691
|
-
return result.stdout.trim();
|
|
21692
|
-
}
|
|
21693
|
-
function run(value) {
|
|
21694
|
-
const env = { ...process.env, GH_TOKEN: value, GITHUB_TOKEN: value, GIT_TERMINAL_PROMPT: '0' };
|
|
21695
|
-
return spawnSync(config.command, process.argv.slice(2), { env, encoding: 'buffer', stdio: ['inherit', 'pipe', 'pipe'] });
|
|
21696
|
-
}
|
|
21697
|
-
let result = run(token());
|
|
21698
|
-
const diagnostic = Buffer.concat([result.stdout || Buffer.alloc(0), result.stderr || Buffer.alloc(0)]).toString('utf8');
|
|
21699
|
-
if (result.status !== 0 && authFailure.test(diagnostic)) result = run(token());
|
|
21700
|
-
if (result.stdout) process.stdout.write(result.stdout);
|
|
21701
|
-
if (result.stderr) process.stderr.write(result.stderr);
|
|
21702
|
-
if (result.error) throw result.error;
|
|
21703
|
-
process.exit(result.status ?? 1);
|
|
21704
|
-
`;
|
|
21705
|
-
await writeFile7(path, source, { mode: 448 });
|
|
21706
|
-
await chmod3(path, 448);
|
|
21707
|
-
}
|
|
21708
21544
|
|
|
21709
21545
|
// apps/body/dist/monolith-corner-turn.js
|
|
21710
21546
|
var execFileAsync3 = promisify3(execFile4);
|
|
@@ -21835,18 +21671,13 @@ async function cornerToolActivity(call, worktreePath, requestedBy) {
|
|
|
21835
21671
|
...paths.length ? { files: paths.map((path) => ({ path })) } : {}
|
|
21836
21672
|
};
|
|
21837
21673
|
}
|
|
21838
|
-
var CORNER_CLOSE_POLL_BASE_MS = 12e3;
|
|
21839
|
-
function cornerClosePollMs(random = Math.random) {
|
|
21840
|
-
return CORNER_CLOSE_POLL_BASE_MS + Math.floor(random() * 3e3);
|
|
21841
|
-
}
|
|
21842
21674
|
var MonolithCornerTurnLoop = class {
|
|
21843
21675
|
options;
|
|
21676
|
+
commandContext;
|
|
21844
21677
|
agent;
|
|
21845
|
-
reconciliationRequested = true;
|
|
21846
21678
|
wakeIntake;
|
|
21847
21679
|
/** Called by the daemon's one slow workspace reconciliation sweep. */
|
|
21848
21680
|
requestReconciliation() {
|
|
21849
|
-
this.reconciliationRequested = true;
|
|
21850
21681
|
this.wakeIntake?.();
|
|
21851
21682
|
this.wakeIntake = void 0;
|
|
21852
21683
|
}
|
|
@@ -21878,15 +21709,9 @@ var MonolithCornerTurnLoop = class {
|
|
|
21878
21709
|
turnTraceSink;
|
|
21879
21710
|
memberNames = /* @__PURE__ */ new Map();
|
|
21880
21711
|
/** Agent identities in this Workspace, so a mention can be told from a human's. */
|
|
21881
|
-
agentMembers = /* @__PURE__ */ new Set();
|
|
21882
|
-
rosterAvailable = false;
|
|
21883
21712
|
/** Per-sender continuity, shared in shape with top-level Room intake. */
|
|
21884
|
-
responseRule = new AgentResponseRule();
|
|
21885
|
-
continuityRebuildRequested = false;
|
|
21886
21713
|
/** The member agent that owns corner-wide lifecycle facts such as checks. */
|
|
21887
|
-
carrier;
|
|
21888
21714
|
/** The last server check state that started a turn; the same state never starts another. */
|
|
21889
|
-
lastChecksState;
|
|
21890
21715
|
/**
|
|
21891
21716
|
* Request ids the requester has stopped. A corner's intake is blocked while
|
|
21892
21717
|
* its turn runs, so a stop is recorded from the live-push callback and read
|
|
@@ -21897,6 +21722,8 @@ var MonolithCornerTurnLoop = class {
|
|
|
21897
21722
|
constructor(options) {
|
|
21898
21723
|
this.options = options;
|
|
21899
21724
|
this.agent = runtimeIdentity(options.runtime.agent);
|
|
21725
|
+
this.commandContext = new CommandExecutionContext(options.config.agentHomeRoot);
|
|
21726
|
+
this.options = { ...options, api: this.commandContext.bind(options.api) };
|
|
21900
21727
|
options.grantRunner?.register(options.cornerId, {
|
|
21901
21728
|
workspaceId: options.workspaceId,
|
|
21902
21729
|
cwd: options.worktreePath,
|
|
@@ -21907,15 +21734,12 @@ var MonolithCornerTurnLoop = class {
|
|
|
21907
21734
|
surface: "corner",
|
|
21908
21735
|
...this.sessionScratchDir ? { scratch: this.sessionScratchDir } : {}
|
|
21909
21736
|
}),
|
|
21910
|
-
turn: () => this.currentTurn
|
|
21737
|
+
turn: () => this.currentTurn ? { ...this.currentTurn, generationId: this.commandContext.generationId } : void 0
|
|
21911
21738
|
});
|
|
21912
21739
|
}
|
|
21913
21740
|
isBusy() {
|
|
21914
21741
|
return this.busy;
|
|
21915
21742
|
}
|
|
21916
|
-
currentPrincipalCanDrive(_workspaceId, _principalId) {
|
|
21917
|
-
return Promise.resolve(true);
|
|
21918
|
-
}
|
|
21919
21743
|
refreshPersonaForSoulUpdate() {
|
|
21920
21744
|
return this.options.scheduler.suspend(this.options.cornerId);
|
|
21921
21745
|
}
|
|
@@ -21950,15 +21774,8 @@ var MonolithCornerTurnLoop = class {
|
|
|
21950
21774
|
workspaceId: this.options.workspaceId
|
|
21951
21775
|
});
|
|
21952
21776
|
this.memberNames = new Map(roster.members.map((member) => [member.identityId, member.name]));
|
|
21953
|
-
this.agentMembers = new Set(roster.members.filter((member) => member.kind === "agent").map((member) => member.identityId));
|
|
21954
|
-
this.responseRule.setAgents(this.agentMembers);
|
|
21955
|
-
this.rosterAvailable = true;
|
|
21956
21777
|
return roster;
|
|
21957
21778
|
}
|
|
21958
|
-
async reconcileRoster() {
|
|
21959
|
-
if (!this.rosterAvailable)
|
|
21960
|
-
await this.roster().catch(() => void 0);
|
|
21961
|
-
}
|
|
21962
21779
|
/**
|
|
21963
21780
|
* Drop this corner's live harness process. The next activation starts cold.
|
|
21964
21781
|
* A rotation is a fact about one live session, so the pin goes with it.
|
|
@@ -22011,7 +21828,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
22011
21828
|
soul: configuration.soul ?? self?.soul,
|
|
22012
21829
|
agentName: self?.name ?? this.agent.name
|
|
22013
21830
|
});
|
|
22014
|
-
await
|
|
21831
|
+
await mkdir11(this.options.worktreePath, { recursive: true });
|
|
22015
21832
|
const selection = configuration.model || configuration.effort ? { model: configuration.model, effort: configuration.effort } : this.options.config.modelSelection;
|
|
22016
21833
|
const homeOverlay = this.options.config.agentHomeRoot ? await prepareRoomAgentHome({
|
|
22017
21834
|
root: this.options.config.agentHomeRoot,
|
|
@@ -22056,13 +21873,13 @@ var MonolithCornerTurnLoop = class {
|
|
|
22056
21873
|
}, selection);
|
|
22057
21874
|
const operatorHome = this.options.config.operatorHome ?? homedir7();
|
|
22058
21875
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
22059
|
-
this.attachmentDir = tmpDir ?
|
|
21876
|
+
this.attachmentDir = tmpDir ? join7(tmpDir, "beeline-attachments") : void 0;
|
|
22060
21877
|
this.sessionScratchDir = tmpDir;
|
|
22061
21878
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
22062
|
-
await Promise.all(homeStateDirs.map((dir) =>
|
|
21879
|
+
await Promise.all(homeStateDirs.map((dir) => mkdir11(dir, { recursive: true })));
|
|
22063
21880
|
const attachScratchRoot = this.options.config.agentHomeRoot ?? tmpDir;
|
|
22064
21881
|
if (attachScratchRoot)
|
|
22065
|
-
await
|
|
21882
|
+
await mkdir11(attachScratchRoot, { recursive: true });
|
|
22066
21883
|
const spawnCommand = wrapAgentCommand({
|
|
22067
21884
|
bwrapPath: this.options.config.bwrapPath,
|
|
22068
21885
|
spec: {
|
|
@@ -22115,6 +21932,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
22115
21932
|
// The whole per-session overlay, not an enumerated subset: see
|
|
22116
21933
|
// `monolith-room-turn.ts`'s matching comment.
|
|
22117
21934
|
attachScratchRoot,
|
|
21935
|
+
turnContextPath: this.commandContext.path,
|
|
22118
21936
|
...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
|
|
22119
21937
|
})
|
|
22120
21938
|
];
|
|
@@ -22247,14 +22065,13 @@ var MonolithCornerTurnLoop = class {
|
|
|
22247
22065
|
...this.memberNames.get(requestedById) ? { name: this.memberNames.get(requestedById) } : {}
|
|
22248
22066
|
} : void 0;
|
|
22249
22067
|
this.currentTurn = { requestId, ...requester ? { requester } : {} };
|
|
22250
|
-
this.carrier = this.agent.publicKey;
|
|
22251
22068
|
const trace = this.beginTurnTrace(requestId);
|
|
22252
22069
|
try {
|
|
22253
22070
|
await withTurnReceiptHeartbeat(api, {
|
|
22254
22071
|
agentId: this.agent.publicKey,
|
|
22255
22072
|
roomId: cornerId,
|
|
22256
22073
|
requestId,
|
|
22257
|
-
generationId:
|
|
22074
|
+
generationId: this.commandContext.generationId
|
|
22258
22075
|
}, () => {
|
|
22259
22076
|
trace.noteScheduler("queue", this.options.scheduler.snapshot());
|
|
22260
22077
|
trace.start("queue-wait");
|
|
@@ -22268,7 +22085,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
22268
22085
|
const [conversation, roster, delivered] = await trace.measure("context-fetch", () => Promise.all([
|
|
22269
22086
|
api.execute("getRoomConversation", { roomId: cornerId, limit: 200 }),
|
|
22270
22087
|
this.roster(),
|
|
22271
|
-
this.attachmentDir && attachments.length ? deliverAttachments(attachments,
|
|
22088
|
+
this.attachmentDir && attachments.length ? deliverAttachments(attachments, join7(this.attachmentDir, requestId.replace(/[^\w-]/g, "_")), this.options.fetchImpl) : Promise.resolve([])
|
|
22272
22089
|
]));
|
|
22273
22090
|
const names = new Map(roster.members.map((member) => [member.identityId, member.name]));
|
|
22274
22091
|
const requestedBy = requester && !requester.name && names.get(requester.pubkey) ? { ...requester, name: names.get(requester.pubkey) } : requester;
|
|
@@ -22283,6 +22100,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
22283
22100
|
`Corner objective:
|
|
22284
22101
|
${this.options.objective}`,
|
|
22285
22102
|
WarmTranscript.render(this.warmTranscript.select(this.sessionId, transcriptRows), "Corner transcript:", "New in the corner since your last turn (the earlier transcript is already in this session):"),
|
|
22103
|
+
roomMentionDirectory(roster, this.agent.publicKey),
|
|
22286
22104
|
[
|
|
22287
22105
|
`Newest trigger:
|
|
22288
22106
|
${trigger}`,
|
|
@@ -22414,9 +22232,7 @@ ${trigger}`,
|
|
|
22414
22232
|
}
|
|
22415
22233
|
}
|
|
22416
22234
|
if (this.stoppedTurns.has(requestId)) {
|
|
22417
|
-
|
|
22418
|
-
await flushToolCalls(result.toolCalls, stoppedText);
|
|
22419
|
-
await stream.settle(stoppedText);
|
|
22235
|
+
stream.close();
|
|
22420
22236
|
throw new TurnStoppedError("turn stopped by the requester");
|
|
22421
22237
|
}
|
|
22422
22238
|
let reply = durableReplyText(result.agentText);
|
|
@@ -22436,12 +22252,11 @@ ${trigger}`,
|
|
|
22436
22252
|
console.warn(`[thin-core] corner ${cornerId} turn ${requestId}: ${explained.reason}`);
|
|
22437
22253
|
}
|
|
22438
22254
|
const durableReply = spoken(reply);
|
|
22439
|
-
|
|
22440
|
-
|
|
22441
|
-
|
|
22442
|
-
|
|
22443
|
-
|
|
22444
|
-
} : void 0));
|
|
22255
|
+
const mentionIds = durableReply ? agentReplyMentionIds(durableReply, roster, this.agent.publicKey) : [];
|
|
22256
|
+
await trace.measure("publish", () => stream.settle(durableReply, durableReply ? {
|
|
22257
|
+
...requestedById ? { triggerMessageId: requestId } : {},
|
|
22258
|
+
mentionIds
|
|
22259
|
+
} : {}));
|
|
22445
22260
|
}, { priority: "interactive", roomKey: cornerId });
|
|
22446
22261
|
}, (error) => console.error(`[thin-core] corner ${cornerId} receipt heartbeat failed:`, error));
|
|
22447
22262
|
await api.execute("postAgentTurnReceipt", {
|
|
@@ -22449,7 +22264,7 @@ ${trigger}`,
|
|
|
22449
22264
|
roomId: cornerId,
|
|
22450
22265
|
requestId,
|
|
22451
22266
|
status: "complete",
|
|
22452
|
-
generationId:
|
|
22267
|
+
generationId: this.commandContext.generationId
|
|
22453
22268
|
});
|
|
22454
22269
|
await trace.finish("complete");
|
|
22455
22270
|
} catch (error) {
|
|
@@ -22464,7 +22279,7 @@ ${trigger}`,
|
|
|
22464
22279
|
roomId: cornerId,
|
|
22465
22280
|
requestId,
|
|
22466
22281
|
status: "failed",
|
|
22467
|
-
generationId:
|
|
22282
|
+
generationId: this.commandContext.generationId,
|
|
22468
22283
|
reason
|
|
22469
22284
|
});
|
|
22470
22285
|
await trace.finish("failed", reason);
|
|
@@ -22474,46 +22289,6 @@ ${trigger}`,
|
|
|
22474
22289
|
this.currentTurn = void 0;
|
|
22475
22290
|
}
|
|
22476
22291
|
}
|
|
22477
|
-
/** Whether this agent opened the corner. A corner with no recorded opener
|
|
22478
|
-
* behaves exactly as it did before members could carry it. */
|
|
22479
|
-
isOpener() {
|
|
22480
|
-
return !this.options.openedBy || this.options.openedBy === this.agent.publicKey;
|
|
22481
|
-
}
|
|
22482
|
-
/**
|
|
22483
|
-
* Whether this agent is the one carrying the corner right now.
|
|
22484
|
-
*
|
|
22485
|
-
* Every member agent polls the corner, but its lifecycle — a server check
|
|
22486
|
-
* note, a close request answered with work — is ONE fact and must start ONE
|
|
22487
|
-
* turn, not one per member (the "one check turn per changed server state"
|
|
22488
|
-
* rule). The carrier is whoever answered in the corner last, which is the
|
|
22489
|
-
* opener until a human hands the work to someone else.
|
|
22490
|
-
*/
|
|
22491
|
-
carriesCorner() {
|
|
22492
|
-
return (this.carrier ?? this.options.openedBy ?? this.agent.publicKey) === this.agent.publicKey;
|
|
22493
|
-
}
|
|
22494
|
-
/** Notes an agent's durable message as the corner changing hands. */
|
|
22495
|
-
noteCarrier(authorId) {
|
|
22496
|
-
if (this.agentMembers.has(authorId))
|
|
22497
|
-
this.carrier = authorId;
|
|
22498
|
-
}
|
|
22499
|
-
async noteIncomingCarrier(item) {
|
|
22500
|
-
if (item.agentAuthor && !this.agentMembers.has(item.authorId))
|
|
22501
|
-
await this.roster().catch(() => void 0);
|
|
22502
|
-
this.noteCarrier(item.authorId);
|
|
22503
|
-
}
|
|
22504
|
-
/**
|
|
22505
|
-
* Whether a message in this corner is addressed to THIS agent.
|
|
22506
|
-
*
|
|
22507
|
-
* A corner now runs like a Room — every member agent polls it — so an
|
|
22508
|
-
* A server-resolved mention always routes to its agent. Otherwise the one
|
|
22509
|
-
* agent already exchanging messages with this exact sender continues; the
|
|
22510
|
-
* lifecycle carrier is deliberately not a conversational fallback.
|
|
22511
|
-
*/
|
|
22512
|
-
addressesThisAgent(item) {
|
|
22513
|
-
if (item.mentionIds.includes(this.agent.publicKey))
|
|
22514
|
-
return true;
|
|
22515
|
-
return this.responseRule.continues(item, this.agent.publicKey);
|
|
22516
|
-
}
|
|
22517
22292
|
/**
|
|
22518
22293
|
* Bring this worktree onto the corner's branch as GitHub currently has it,
|
|
22519
22294
|
* before any work is done on top of it.
|
|
@@ -22535,197 +22310,42 @@ ${trigger}`,
|
|
|
22535
22310
|
env: { ...process.env, GH_TOKEN: token, GITHUB_TOKEN: token, GIT_TERMINAL_PROMPT: "0" }
|
|
22536
22311
|
});
|
|
22537
22312
|
}
|
|
22538
|
-
/** The server's check state for this head, or the notes' own verdict when the server carries none. */
|
|
22539
|
-
async checksState(notes) {
|
|
22540
|
-
try {
|
|
22541
|
-
const restore = await this.options.api.execute("getCornerRestoreState", {
|
|
22542
|
-
cornerId: this.options.cornerId
|
|
22543
|
-
});
|
|
22544
|
-
const fromServer = checksStateFromLifecycle(restore.lifecycle);
|
|
22545
|
-
if (fromServer)
|
|
22546
|
-
return fromServer;
|
|
22547
|
-
} catch (error) {
|
|
22548
|
-
console.error(`[thin-core] corner ${this.options.cornerId} check state read failed:`, error);
|
|
22549
|
-
}
|
|
22550
|
-
return notes.some((note) => completedCheckNote(note) === "failed") ? "failing" : "passing";
|
|
22551
|
-
}
|
|
22552
22313
|
async run() {
|
|
22553
22314
|
const { api, cornerId, signal } = this.options;
|
|
22554
|
-
const activation = await api.execute("getRoomInbox", {
|
|
22555
|
-
roomId: cornerId,
|
|
22556
|
-
startAtLatest: true
|
|
22557
|
-
});
|
|
22558
|
-
let cursor3 = activation.cursor;
|
|
22559
|
-
const processedInboxIds = /* @__PURE__ */ new Set();
|
|
22560
|
-
const pushedInbox = [];
|
|
22561
|
-
let pendingPushedCursor;
|
|
22562
|
-
let liveConnected = false;
|
|
22563
|
-
const rewindSupported = Array.isArray(activation.rewindIds);
|
|
22564
|
-
for (const id of activation.rewindIds ?? [])
|
|
22565
|
-
processedInboxIds.add(id);
|
|
22566
|
-
const stopLive = api.liveSubscribe?.(cornerId, cursor3, (items, pushedCursor) => {
|
|
22567
|
-
pushedInbox.push(...items);
|
|
22568
|
-
for (const item of items) {
|
|
22569
|
-
const stopped = turnStopRequestId(item, this.agent.publicKey);
|
|
22570
|
-
if (stopped)
|
|
22571
|
-
this.stopTurn(stopped);
|
|
22572
|
-
}
|
|
22573
|
-
pendingPushedCursor = laterInboxCursor(pendingPushedCursor, pushedCursor);
|
|
22574
|
-
this.wakeIntake?.();
|
|
22575
|
-
this.wakeIntake = void 0;
|
|
22576
|
-
}, (connected, capabilities) => {
|
|
22577
|
-
liveConnected = connected && capabilities?.pushIntake === true;
|
|
22578
|
-
this.wakeIntake?.();
|
|
22579
|
-
this.wakeIntake = void 0;
|
|
22580
|
-
}, {
|
|
22581
|
-
...this.options.config.daemonReleaseVersion ? { releaseVersion: this.options.config.daemonReleaseVersion } : {},
|
|
22582
|
-
...this.options.config.daemonSourceSha ? { sourceSha: this.options.config.daemonSourceSha } : {},
|
|
22583
|
-
available: !this.options.config.modelUnavailable
|
|
22584
|
-
});
|
|
22585
|
-
const history = await api.execute("getRoomConversation", {
|
|
22586
|
-
roomId: cornerId,
|
|
22587
|
-
limit: 200,
|
|
22588
|
-
window: "continuity"
|
|
22589
|
-
});
|
|
22590
|
-
await this.roster().catch(() => void 0);
|
|
22591
|
-
this.responseRule.observeAll(history.items);
|
|
22592
|
-
for (const item of history.items) {
|
|
22593
|
-
if (item.type === "message")
|
|
22594
|
-
await this.noteIncomingCarrier(item);
|
|
22595
|
-
}
|
|
22596
|
-
const durableAgentReplies = history.items.filter((item) => item.type === "message" && item.authorId === this.agent.publicKey && item.body.trim() !== this.options.objective.trim());
|
|
22597
|
-
if (durableAgentReplies.length === 0 && this.isOpener()) {
|
|
22598
|
-
await this.prompt(history.items.find((item) => item.requestId)?.requestId ?? cornerId.replaceAll("-", ""), this.options.objective);
|
|
22599
|
-
}
|
|
22600
22315
|
try {
|
|
22601
|
-
|
|
22602
|
-
|
|
22603
|
-
|
|
22604
|
-
|
|
22605
|
-
|
|
22606
|
-
|
|
22607
|
-
|
|
22608
|
-
|
|
22609
|
-
|
|
22610
|
-
|
|
22611
|
-
|
|
22612
|
-
|
|
22613
|
-
|
|
22614
|
-
|
|
22615
|
-
|
|
22616
|
-
|
|
22617
|
-
|
|
22618
|
-
|
|
22619
|
-
|
|
22620
|
-
|
|
22621
|
-
|
|
22622
|
-
|
|
22623
|
-
|
|
22624
|
-
|
|
22625
|
-
|
|
22626
|
-
|
|
22627
|
-
|
|
22628
|
-
await this.options.onCloseRequested();
|
|
22629
|
-
return;
|
|
22630
|
-
}
|
|
22631
|
-
const checkNotes = [];
|
|
22632
|
-
const delivered = orderInboxItems([...pushedInbox.splice(0), ...inbox.items]);
|
|
22633
|
-
for (const item of delivered) {
|
|
22634
|
-
if (processedInboxIds.has(item.id))
|
|
22635
|
-
continue;
|
|
22636
|
-
processedInboxIds.add(item.id);
|
|
22637
|
-
while (processedInboxIds.size > INBOX_DEDUPLICATION_LIMIT)
|
|
22638
|
-
processedInboxIds.delete(processedInboxIds.values().next().value);
|
|
22639
|
-
const stoppedTurn = turnStopRequestId(item, this.agent.publicKey);
|
|
22640
|
-
if (stoppedTurn) {
|
|
22641
|
-
this.stopTurn(stoppedTurn);
|
|
22642
|
-
continue;
|
|
22643
|
-
}
|
|
22644
|
-
if (item.type === "message") {
|
|
22645
|
-
if (item.authorId !== this.agent.publicKey)
|
|
22646
|
-
await this.reconcileRoster();
|
|
22647
|
-
await this.noteIncomingCarrier(item);
|
|
22648
|
-
if (item.authorId === this.agent.publicKey)
|
|
22649
|
-
continue;
|
|
22650
|
-
const addressed = this.addressesThisAgent(item);
|
|
22651
|
-
this.responseRule.observe(item);
|
|
22652
|
-
if (!addressed)
|
|
22653
|
-
continue;
|
|
22654
|
-
const authority = await api.execute("getRoomAuthority", {
|
|
22655
|
-
roomId: cornerId,
|
|
22656
|
-
principalId: item.authorId
|
|
22657
|
-
});
|
|
22658
|
-
const humanPermitted = authority.principalKind === "human" ? await this.currentPrincipalCanDrive(this.options.workspaceId, item.authorId) : false;
|
|
22659
|
-
if (!roomPrincipalMayAddressAgent(authority, humanPermitted))
|
|
22660
|
-
continue;
|
|
22661
|
-
await this.prompt(item.id, item.body, item.attachments, item.authorId);
|
|
22662
|
-
pollWithoutWait = true;
|
|
22663
|
-
continue;
|
|
22664
|
-
}
|
|
22665
|
-
const grantDecision = item.type === "system" && item.mentionIds.includes(this.agent.publicKey) && parseGrantDecisionLine(item.body) !== void 0;
|
|
22666
|
-
if (grantDecision) {
|
|
22667
|
-
await this.prompt(item.id, `${item.body}
|
|
22668
|
-
This answers your grant request; resume the paused work. If approved and it is a command grant, run it with run_granted_command and the exact argv; if declined, try another way or say what you cannot do.`, [], item.authorId);
|
|
22669
|
-
pollWithoutWait = true;
|
|
22670
|
-
continue;
|
|
22671
|
-
}
|
|
22672
|
-
if (isCheckStartNote(item)) {
|
|
22673
|
-
this.lastChecksState = void 0;
|
|
22674
|
-
continue;
|
|
22675
|
-
}
|
|
22676
|
-
if (completedCheckNote(item))
|
|
22677
|
-
checkNotes.push(item);
|
|
22678
|
-
}
|
|
22679
|
-
if (checkNotes.length && this.carriesCorner()) {
|
|
22680
|
-
const state = await this.checksState(checkNotes);
|
|
22681
|
-
if (state && state !== "pending" && state !== this.lastChecksState) {
|
|
22682
|
-
this.lastChecksState = state;
|
|
22683
|
-
const lines = checkNotes.map((note) => note.body);
|
|
22684
|
-
await this.prompt(checkNotes[checkNotes.length - 1].id, lines.join("\n"), [], void 0, lines);
|
|
22685
|
-
pollWithoutWait = true;
|
|
22686
|
-
}
|
|
22687
|
-
}
|
|
22688
|
-
cursor3 = laterInboxCursor(cursor3, laterInboxCursor(inbox.cursor, pendingPushedCursor));
|
|
22689
|
-
pendingPushedCursor = void 0;
|
|
22690
|
-
api.updateLiveCursor?.(cornerId, cursor3);
|
|
22691
|
-
if (pollNow)
|
|
22692
|
-
this.options.onPoll();
|
|
22693
|
-
await Promise.race([
|
|
22694
|
-
wait2(pollWithoutWait ? 0 : liveConnected ? 2147483647 : this.options.pollMs ?? cornerClosePollMs(), signal),
|
|
22695
|
-
pushedInbox.length ? Promise.resolve() : new Promise((resolve30) => {
|
|
22696
|
-
this.wakeIntake = resolve30;
|
|
22697
|
-
})
|
|
22698
|
-
]);
|
|
22699
|
-
pollWithoutWait = false;
|
|
22700
|
-
} catch (error) {
|
|
22701
|
-
if (signal?.aborted)
|
|
22702
|
-
break;
|
|
22703
|
-
this.options.onFailure(1e3);
|
|
22704
|
-
console.error(`[thin-core] corner ${cornerId} turn loop failed:`, error);
|
|
22705
|
-
await wait2(1e3, signal);
|
|
22706
|
-
}
|
|
22707
|
-
}
|
|
22316
|
+
await runServerCommandIntake({
|
|
22317
|
+
api,
|
|
22318
|
+
roomId: cornerId,
|
|
22319
|
+
agentId: this.agent.publicKey,
|
|
22320
|
+
context: this.commandContext,
|
|
22321
|
+
signal,
|
|
22322
|
+
pollMs: this.options.pollMs,
|
|
22323
|
+
presence: {
|
|
22324
|
+
...this.options.config.daemonReleaseVersion ? { releaseVersion: this.options.config.daemonReleaseVersion } : {},
|
|
22325
|
+
...this.options.config.daemonSourceSha ? { sourceSha: this.options.config.daemonSourceSha } : {},
|
|
22326
|
+
available: !this.options.config.modelUnavailable
|
|
22327
|
+
},
|
|
22328
|
+
onWake: (wake) => {
|
|
22329
|
+
this.wakeIntake = wake;
|
|
22330
|
+
},
|
|
22331
|
+
onPoll: () => this.options.onPoll(),
|
|
22332
|
+
onError: (error) => console.error("[thin-core] corner command failed", error),
|
|
22333
|
+
stop: (requestId) => this.stopTurn(requestId),
|
|
22334
|
+
closed: async () => {
|
|
22335
|
+
const state = await api.execute("getCornerRestoreState", { cornerId });
|
|
22336
|
+
if (!state.closeRequested)
|
|
22337
|
+
return false;
|
|
22338
|
+
await this.options.onCloseRequested();
|
|
22339
|
+
return true;
|
|
22340
|
+
},
|
|
22341
|
+
run: (command) => this.prompt(command.turnRequestId, command.source.body, command.source.attachments, command.source.authorId, command.reason === "corner_check" ? [command.source.body] : void 0)
|
|
22342
|
+
});
|
|
22708
22343
|
} finally {
|
|
22709
|
-
stopLive?.();
|
|
22710
|
-
this.wakeIntake = void 0;
|
|
22711
22344
|
this.options.grantRunner?.unregister(cornerId);
|
|
22712
22345
|
await this.options.scheduler.suspend(cornerId);
|
|
22713
22346
|
}
|
|
22714
22347
|
}
|
|
22715
22348
|
};
|
|
22716
|
-
async function wait2(ms, signal) {
|
|
22717
|
-
if (signal?.aborted)
|
|
22718
|
-
return;
|
|
22719
|
-
await new Promise((resolveWait) => {
|
|
22720
|
-
const done = () => {
|
|
22721
|
-
clearTimeout(timer);
|
|
22722
|
-
signal?.removeEventListener("abort", done);
|
|
22723
|
-
resolveWait();
|
|
22724
|
-
};
|
|
22725
|
-
const timer = setTimeout(done, ms);
|
|
22726
|
-
signal?.addEventListener("abort", done, { once: true });
|
|
22727
|
-
});
|
|
22728
|
-
}
|
|
22729
22349
|
|
|
22730
22350
|
// apps/body/dist/session-scheduler.js
|
|
22731
22351
|
var DEFAULT_PER_ROOM_LIVE_SESSIONS = 10;
|
|
@@ -23145,8 +22765,8 @@ async function materializeCornerWorktree(input) {
|
|
|
23145
22765
|
const repositoryHash = createHash5("sha256").update(remote).digest("hex").slice(0, 24);
|
|
23146
22766
|
const gitCommonDir = resolve19(input.supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
|
|
23147
22767
|
const path = resolve19(input.supervisorRoot, "beeline", "corners", input.cornerId);
|
|
23148
|
-
await
|
|
23149
|
-
await
|
|
22768
|
+
await mkdir12(dirname7(gitCommonDir), { recursive: true, mode: 448 });
|
|
22769
|
+
await mkdir12(dirname7(path), { recursive: true, mode: 448 });
|
|
23150
22770
|
const authEnv = githubGitEnv(input.token);
|
|
23151
22771
|
if (!existsSync4(resolve19(gitCommonDir, "HEAD"))) {
|
|
23152
22772
|
await execFileAsync4("git", ["clone", "--bare", remote, gitCommonDir], {
|
|
@@ -23333,9 +22953,6 @@ var RoomRuntimeCoordinator = class {
|
|
|
23333
22953
|
this.drainDeadlineAt = Math.min(this.drainDeadlineAt ?? Number.POSITIVE_INFINITY, deadlineAt);
|
|
23334
22954
|
}
|
|
23335
22955
|
}
|
|
23336
|
-
async currentPrincipalCanDrive(roomId, workspaceId, principalId) {
|
|
23337
|
-
return this.running.get(roomId)?.body.currentPrincipalCanDrive(workspaceId, principalId);
|
|
23338
|
-
}
|
|
23339
22956
|
async prepareForForcedUpdateRestart() {
|
|
23340
22957
|
const rooms = [...this.running.values()];
|
|
23341
22958
|
await Promise.allSettled(rooms.filter((room) => room.body.isBusy()).map((room) => room.body.prepareForForcedUpdateRestart()));
|
|
@@ -23420,7 +23037,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
23420
23037
|
return this.runtime.rooms.find((room) => room.channelId === roomId);
|
|
23421
23038
|
}
|
|
23422
23039
|
roomRoot(roomId) {
|
|
23423
|
-
return this.roomRecord(roomId)?.root ?? resolve19(
|
|
23040
|
+
return this.roomRecord(roomId)?.root ?? resolve19(dirname7(this.configPath), "rooms", roomId);
|
|
23424
23041
|
}
|
|
23425
23042
|
roomAgentHomeRoot(workspaceRoot, required = false) {
|
|
23426
23043
|
const flag = process.env.BUZZY_BODY_ROOM_HOME;
|
|
@@ -23443,9 +23060,9 @@ var RoomRuntimeCoordinator = class {
|
|
|
23443
23060
|
...this.baseConfig,
|
|
23444
23061
|
workspaceRoot,
|
|
23445
23062
|
agentPrivateRoot: resolve19(workspaceRoot, "agent-private"),
|
|
23446
|
-
agentMemoryRoot: resolve19(
|
|
23447
|
-
openRouterRoutingCacheDir: openRouterRoutingCacheDir(
|
|
23448
|
-
turnTraceDir: turnTraceDirectory(
|
|
23063
|
+
agentMemoryRoot: resolve19(dirname7(this.configPath), "memory"),
|
|
23064
|
+
openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname7(this.configPath)),
|
|
23065
|
+
turnTraceDir: turnTraceDirectory(dirname7(this.configPath)),
|
|
23449
23066
|
...agentHomeRoot ? { agentHomeRoot } : {}
|
|
23450
23067
|
};
|
|
23451
23068
|
}
|
|
@@ -23513,7 +23130,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
23513
23130
|
const targetBranch = repository.targetBranch || "main";
|
|
23514
23131
|
const checkoutId = createHash5("sha256").update(`${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
|
|
23515
23132
|
const path = resolve19(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
|
|
23516
|
-
await
|
|
23133
|
+
await mkdir12(dirname7(path), { recursive: true, mode: 448 });
|
|
23517
23134
|
const token = remote.startsWith("https://github.com/") ? await this.options.daemonApi.execute("getRoomGitHubToken", { roomId }) : void 0;
|
|
23518
23135
|
const env = token ? githubGitEnv(token.token) : process.env;
|
|
23519
23136
|
if (!existsSync4(resolve19(path, ".git"))) {
|
|
@@ -23579,7 +23196,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
23579
23196
|
}) : void 0;
|
|
23580
23197
|
const workspacePath = worktree?.path ?? resolve19(this.roomRoot(corner.cornerId), "scratch");
|
|
23581
23198
|
if (!worktree)
|
|
23582
|
-
await
|
|
23199
|
+
await mkdir12(workspacePath, { recursive: true, mode: 448 });
|
|
23583
23200
|
const isOpener = !corner.openedBy || corner.openedBy === this.agent.publicKey;
|
|
23584
23201
|
if (worktree && shouldPostInitialCornerWorkingState(restore, isOpener)) {
|
|
23585
23202
|
await this.options.daemonApi.execute("postCornerRemoteState", {
|
|
@@ -23878,9 +23495,9 @@ var ThinDaemonCore = class {
|
|
|
23878
23495
|
|
|
23879
23496
|
// apps/body/dist/systemd.js
|
|
23880
23497
|
import { execFile as execFile6 } from "node:child_process";
|
|
23881
|
-
import { mkdir as
|
|
23498
|
+
import { mkdir as mkdir13, readFile as readFile8, writeFile as writeFile9 } from "node:fs/promises";
|
|
23882
23499
|
import { homedir as homedir8 } from "node:os";
|
|
23883
|
-
import { dirname as
|
|
23500
|
+
import { dirname as dirname8, resolve as resolve20 } from "node:path";
|
|
23884
23501
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
23885
23502
|
import { promisify as promisify5 } from "node:util";
|
|
23886
23503
|
var execFileAsync5 = promisify5(execFile6);
|
|
@@ -23951,8 +23568,8 @@ async function installAgentService(publicKey, options = {}) {
|
|
|
23951
23568
|
const content = agentServiceUnit();
|
|
23952
23569
|
const existing = await readFile8(path, "utf8").catch(() => "");
|
|
23953
23570
|
if (existing !== content) {
|
|
23954
|
-
await
|
|
23955
|
-
await
|
|
23571
|
+
await mkdir13(dirname8(path), { recursive: true, mode: 448 });
|
|
23572
|
+
await writeFile9(path, content, { mode: 384 });
|
|
23956
23573
|
}
|
|
23957
23574
|
const run2 = options.run ?? runSystemctl;
|
|
23958
23575
|
await run2(["daemon-reload"]);
|
|
@@ -24032,7 +23649,7 @@ async function retireRemovedAgent(runtime, options = {}) {
|
|
|
24032
23649
|
}
|
|
24033
23650
|
|
|
24034
23651
|
// apps/body/dist/start-command.js
|
|
24035
|
-
import { dirname as
|
|
23652
|
+
import { dirname as dirname9 } from "node:path";
|
|
24036
23653
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
24037
23654
|
var DEFAULT_RESTART_DRAIN_TIMEOUT_MS = 30 * 6e4;
|
|
24038
23655
|
var RESTART_WAIT_REPORT_INTERVAL_MS = 3e4;
|
|
@@ -24107,7 +23724,7 @@ async function runStartCommand(args, interactiveUi) {
|
|
|
24107
23724
|
continue;
|
|
24108
23725
|
}
|
|
24109
23726
|
const spinnerHandle = spinner();
|
|
24110
|
-
spinnerHandle.start(`Starting ${
|
|
23727
|
+
spinnerHandle.start(`Starting ${dirname9(path)}\u2026`);
|
|
24111
23728
|
try {
|
|
24112
23729
|
await startRuntime(path, spinnerHandle);
|
|
24113
23730
|
spinnerHandle.stop(import_picocolors.default.green("Started."));
|
|
@@ -24124,8 +23741,8 @@ async function runStartCommand(args, interactiveUi) {
|
|
|
24124
23741
|
// apps/body/dist/connect-command.js
|
|
24125
23742
|
import { spawn as spawn5 } from "node:child_process";
|
|
24126
23743
|
import { createHash as createHash7 } from "node:crypto";
|
|
24127
|
-
import { chmod as chmod5, mkdir as
|
|
24128
|
-
import { dirname as
|
|
23744
|
+
import { chmod as chmod5, mkdir as mkdir15, readFile as readFile10, unlink as unlink2, writeFile as writeFile11 } from "node:fs/promises";
|
|
23745
|
+
import { dirname as dirname11, resolve as resolve22 } from "node:path";
|
|
24129
23746
|
import { stdin as stdin3, stdout as stdout4 } from "node:process";
|
|
24130
23747
|
|
|
24131
23748
|
// apps/body/dist/clack-support.js
|
|
@@ -24769,8 +24386,8 @@ function providerEnvironment(selection) {
|
|
|
24769
24386
|
};
|
|
24770
24387
|
}
|
|
24771
24388
|
async function writePrivateJson(path, value) {
|
|
24772
|
-
await
|
|
24773
|
-
await
|
|
24389
|
+
await mkdir15(dirname11(path), { recursive: true, mode: 448 });
|
|
24390
|
+
await writeFile11(path, `${JSON.stringify(value, null, 2)}
|
|
24774
24391
|
`, { mode: 384 });
|
|
24775
24392
|
await chmod5(path, 384);
|
|
24776
24393
|
}
|
|
@@ -24779,9 +24396,9 @@ async function writeProviderEnv(selection, agentPubkey) {
|
|
|
24779
24396
|
if (Object.keys(values).length === 0)
|
|
24780
24397
|
return void 0;
|
|
24781
24398
|
const path = resolve22(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
|
|
24782
|
-
await
|
|
24399
|
+
await mkdir15(dirname11(path), { recursive: true, mode: 448 });
|
|
24783
24400
|
const contents = Object.entries(values).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n");
|
|
24784
|
-
await
|
|
24401
|
+
await writeFile11(path, `${contents}
|
|
24785
24402
|
`, { mode: 384 });
|
|
24786
24403
|
await chmod5(path, 384);
|
|
24787
24404
|
return path;
|
|
@@ -24937,7 +24554,7 @@ async function runConnectFinishCommand(path) {
|
|
|
24937
24554
|
if (model) {
|
|
24938
24555
|
const decision2 = await resolveOpenRouterRouting({
|
|
24939
24556
|
model,
|
|
24940
|
-
cacheDir: openRouterRoutingCacheDir(
|
|
24557
|
+
cacheDir: openRouterRoutingCacheDir(dirname11(connected.configPath)),
|
|
24941
24558
|
...apiKey ? { apiKey } : {},
|
|
24942
24559
|
probeTimeoutMs: 1e4
|
|
24943
24560
|
});
|
|
@@ -24959,12 +24576,12 @@ init_self_update_manifest();
|
|
|
24959
24576
|
// apps/body/dist/managed-update.js
|
|
24960
24577
|
init_self_update();
|
|
24961
24578
|
import { spawn as spawn6 } from "node:child_process";
|
|
24962
|
-
import { mkdir as
|
|
24963
|
-
import { dirname as
|
|
24579
|
+
import { mkdir as mkdir17, rm as rm6, stat as stat2, writeFile as writeFile13 } from "node:fs/promises";
|
|
24580
|
+
import { dirname as dirname13, resolve as resolve24 } from "node:path";
|
|
24964
24581
|
|
|
24965
24582
|
// apps/body/dist/update-rollback-alert.js
|
|
24966
|
-
import { mkdir as
|
|
24967
|
-
import { dirname as
|
|
24583
|
+
import { mkdir as mkdir16, readFile as readFile11, rename as rename4, unlink as unlink3, writeFile as writeFile12 } from "node:fs/promises";
|
|
24584
|
+
import { dirname as dirname12, resolve as resolve23 } from "node:path";
|
|
24968
24585
|
var REPORT_INTERVAL_MS = 60 * 60 * 1e3;
|
|
24969
24586
|
var lastLogged = /* @__PURE__ */ new Map();
|
|
24970
24587
|
function updateRollbackAlertPath(runtimeDir) {
|
|
@@ -24973,8 +24590,8 @@ function updateRollbackAlertPath(runtimeDir) {
|
|
|
24973
24590
|
async function writeAlert(runtimeDir, alert) {
|
|
24974
24591
|
const path = updateRollbackAlertPath(runtimeDir);
|
|
24975
24592
|
const staged = `${path}.${process.pid}.tmp`;
|
|
24976
|
-
await
|
|
24977
|
-
await
|
|
24593
|
+
await mkdir16(dirname12(path), { recursive: true });
|
|
24594
|
+
await writeFile12(staged, `${JSON.stringify(alert, null, 2)}
|
|
24978
24595
|
`, { mode: 384 });
|
|
24979
24596
|
await rename4(staged, path);
|
|
24980
24597
|
}
|
|
@@ -25039,11 +24656,11 @@ async function withInstallLock(layout, work, options = {}) {
|
|
|
25039
24656
|
const now2 = options.now ?? Date.now;
|
|
25040
24657
|
const lock = resolve24(layout.releasesRoot, ".state", "install.lock");
|
|
25041
24658
|
const deadline = now2() + (options.waitMs ?? 1e4);
|
|
25042
|
-
await
|
|
24659
|
+
await mkdir17(dirname13(lock), { recursive: true });
|
|
25043
24660
|
for (; ; ) {
|
|
25044
24661
|
try {
|
|
25045
|
-
await
|
|
25046
|
-
await
|
|
24662
|
+
await mkdir17(lock);
|
|
24663
|
+
await writeFile13(resolve24(lock, "owner"), `${process.pid}
|
|
25047
24664
|
${now2()}
|
|
25048
24665
|
`, "utf8");
|
|
25049
24666
|
break;
|
|
@@ -25453,7 +25070,7 @@ async function proveLoadedReleaseReady(layout, runtimeDir, loadedRelease, option
|
|
|
25453
25070
|
});
|
|
25454
25071
|
if (!accepted)
|
|
25455
25072
|
return false;
|
|
25456
|
-
await
|
|
25073
|
+
await writeFile13(resolve24(runtimeDir, "daemon-ready.json"), `${JSON.stringify({
|
|
25457
25074
|
readyAt: (options.now ?? Date.now)(),
|
|
25458
25075
|
loadedRelease,
|
|
25459
25076
|
functionalProof: options.functionalProof
|
|
@@ -25681,8 +25298,8 @@ async function runUpdateCommand(args) {
|
|
|
25681
25298
|
init_self_update();
|
|
25682
25299
|
|
|
25683
25300
|
// apps/body/dist/daemon-failure.js
|
|
25684
|
-
import { mkdir as
|
|
25685
|
-
import { dirname as
|
|
25301
|
+
import { mkdir as mkdir18, readFile as readFile12, rename as rename5, rm as rm7, writeFile as writeFile14 } from "node:fs/promises";
|
|
25302
|
+
import { dirname as dirname14, resolve as resolve25 } from "node:path";
|
|
25686
25303
|
var DAEMON_FAILURE_LIMIT = 3;
|
|
25687
25304
|
var DAEMON_FAILURE_WINDOW_MS = 5 * 6e4;
|
|
25688
25305
|
function daemonFailurePath(runtimeDir) {
|
|
@@ -25702,8 +25319,8 @@ async function readFailureRecord(runtimeDir) {
|
|
|
25702
25319
|
async function writeFailureRecord(runtimeDir, record2) {
|
|
25703
25320
|
const path = daemonFailurePath(runtimeDir);
|
|
25704
25321
|
const staged = `${path}.${process.pid}.tmp`;
|
|
25705
|
-
await
|
|
25706
|
-
await
|
|
25322
|
+
await mkdir18(dirname14(path), { recursive: true, mode: 448 });
|
|
25323
|
+
await writeFile14(staged, `${JSON.stringify(record2, null, 2)}
|
|
25707
25324
|
`, { mode: 384 });
|
|
25708
25325
|
await rename5(staged, path);
|
|
25709
25326
|
}
|
|
@@ -25725,7 +25342,7 @@ async function clearDaemonStartFailures(runtimeDir) {
|
|
|
25725
25342
|
}
|
|
25726
25343
|
|
|
25727
25344
|
// apps/body/dist/update-functional-probe.js
|
|
25728
|
-
import { mkdir as
|
|
25345
|
+
import { mkdir as mkdir19, rm as rm8 } from "node:fs/promises";
|
|
25729
25346
|
import { homedir as homedir10 } from "node:os";
|
|
25730
25347
|
import { resolve as resolve26 } from "node:path";
|
|
25731
25348
|
var UPDATE_PROBE_SESSION_TIMEOUT_MS = 1e4;
|
|
@@ -25771,6 +25388,9 @@ async function probeOutcome(run2) {
|
|
|
25771
25388
|
await run2();
|
|
25772
25389
|
return { kind: "served" };
|
|
25773
25390
|
} catch (error) {
|
|
25391
|
+
if (error instanceof UpdateFunctionalProbeError && error.reason === "sandbox-unavailable") {
|
|
25392
|
+
return { kind: "sandbox-unavailable", reason: error.message };
|
|
25393
|
+
}
|
|
25774
25394
|
if (error instanceof UpdateFunctionalProbeError && error.providerRefusal) {
|
|
25775
25395
|
return { kind: "refused", ...error.providerRefusal };
|
|
25776
25396
|
}
|
|
@@ -25783,6 +25403,8 @@ function describeCurrentReleaseOutcome(outcome) {
|
|
|
25783
25403
|
return "the current release answered";
|
|
25784
25404
|
case "refused":
|
|
25785
25405
|
return `the current release got a different refusal (${outcome.reason})`;
|
|
25406
|
+
case "sandbox-unavailable":
|
|
25407
|
+
return `the current release has the same unavailable sandbox (${outcome.reason})`;
|
|
25786
25408
|
case "unavailable":
|
|
25787
25409
|
return `the current release could not be compared (${outcome.reason})`;
|
|
25788
25410
|
}
|
|
@@ -25794,13 +25416,33 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
25794
25416
|
throw new UpdateFunctionalProbeError("model-unavailable", input.config.modelUnavailable.detail);
|
|
25795
25417
|
}
|
|
25796
25418
|
if (input.sandboxRequired && !input.config.bwrapPath) {
|
|
25797
|
-
|
|
25419
|
+
const detail = input.sandboxUnavailableDetail ?? "the configured bubblewrap boundary did not pass its startup self-test";
|
|
25420
|
+
if (!input.compareWithCurrentRelease) {
|
|
25421
|
+
throw new UpdateFunctionalProbeError("sandbox-unavailable", detail);
|
|
25422
|
+
}
|
|
25423
|
+
const current = await input.compareWithCurrentRelease({
|
|
25424
|
+
kind: "sandbox-unavailable",
|
|
25425
|
+
reason: detail
|
|
25426
|
+
});
|
|
25427
|
+
if (current.kind !== "sandbox-unavailable") {
|
|
25428
|
+
throw new UpdateFunctionalProbeError("sandbox-unavailable", `${detail}; ${describeCurrentReleaseOutcome(current)}`);
|
|
25429
|
+
}
|
|
25430
|
+
console.warn("[body] update probe: the sandbox is unavailable to this release and the current release alike; preserving fail-closed sandboxing and accepting the bundle as inconclusive");
|
|
25431
|
+
return {
|
|
25432
|
+
harness,
|
|
25433
|
+
sandboxed: false,
|
|
25434
|
+
sessionStarted: false,
|
|
25435
|
+
turnCompleted: false,
|
|
25436
|
+
nativeTools: [],
|
|
25437
|
+
modelAnswer: "unavailable",
|
|
25438
|
+
modelAnswerReason: `${detail} (the current release has the same host sandbox failure)`
|
|
25439
|
+
};
|
|
25798
25440
|
}
|
|
25799
25441
|
const root = input.probeRoot ?? resolve26(input.runtimeDir, "update-functional-probe");
|
|
25800
25442
|
const cwd = resolve26(root, "checkout");
|
|
25801
25443
|
const homeRoot = resolve26(root, "agent-home");
|
|
25802
25444
|
await rm8(root, { recursive: true, force: true });
|
|
25803
|
-
await
|
|
25445
|
+
await mkdir19(cwd, { recursive: true, mode: 448 });
|
|
25804
25446
|
let client;
|
|
25805
25447
|
try {
|
|
25806
25448
|
const agentEnv = {
|
|
@@ -25830,7 +25472,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
25830
25472
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
25831
25473
|
const operatorHome = input.config.operatorHome ?? homedir10();
|
|
25832
25474
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
25833
|
-
await Promise.all(homeStateDirs.map((dir) =>
|
|
25475
|
+
await Promise.all(homeStateDirs.map((dir) => mkdir19(dir, { recursive: true })));
|
|
25834
25476
|
spawnCommand = wrapAgentCommand({
|
|
25835
25477
|
bwrapPath: input.config.bwrapPath,
|
|
25836
25478
|
spec: {
|
|
@@ -25980,7 +25622,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
25980
25622
|
|
|
25981
25623
|
// apps/body/dist/current-release-probe.js
|
|
25982
25624
|
import { spawn as spawn7 } from "node:child_process";
|
|
25983
|
-
import { dirname as
|
|
25625
|
+
import { dirname as dirname15, join as join9 } from "node:path";
|
|
25984
25626
|
init_self_update();
|
|
25985
25627
|
var CURRENT_RELEASE_PROBE_TIMEOUT_MS = 12e4;
|
|
25986
25628
|
var UPDATE_PROBE_COMMAND = "update-probe";
|
|
@@ -26002,6 +25644,9 @@ function parseReport(line) {
|
|
|
26002
25644
|
if (report.probe === "failed" && typeof report.reason === "string") {
|
|
26003
25645
|
return { probe: "failed", reason: report.reason };
|
|
26004
25646
|
}
|
|
25647
|
+
if (report.probe === "sandbox-unavailable" && typeof report.reason === "string") {
|
|
25648
|
+
return { probe: "sandbox-unavailable", reason: report.reason };
|
|
25649
|
+
}
|
|
26005
25650
|
return void 0;
|
|
26006
25651
|
}
|
|
26007
25652
|
function outcomeFromReport(report) {
|
|
@@ -26010,12 +25655,17 @@ function outcomeFromReport(report) {
|
|
|
26010
25655
|
return { kind: "served" };
|
|
26011
25656
|
case "refused":
|
|
26012
25657
|
return { kind: "refused", status: report.status, reason: report.reason };
|
|
25658
|
+
case "sandbox-unavailable":
|
|
25659
|
+
return { kind: "sandbox-unavailable", reason: report.reason };
|
|
26013
25660
|
case "failed":
|
|
25661
|
+
if (report.reason.startsWith("functional update probe failed (sandbox-unavailable):")) {
|
|
25662
|
+
return { kind: "sandbox-unavailable", reason: report.reason };
|
|
25663
|
+
}
|
|
26014
25664
|
return { kind: "unavailable", reason: report.reason };
|
|
26015
25665
|
}
|
|
26016
25666
|
}
|
|
26017
25667
|
async function probeReleaseInSubprocess(input) {
|
|
26018
|
-
const bundleDir =
|
|
25668
|
+
const bundleDir = join9(input.layout.releasesRoot, input.releaseId);
|
|
26019
25669
|
const entrypoint = await resolveBundleEntrypoint(bundleDir);
|
|
26020
25670
|
if (!entrypoint) {
|
|
26021
25671
|
return { kind: "unavailable", reason: `release ${input.releaseId} has no runnable CLI entrypoint` };
|
|
@@ -26078,7 +25728,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
26078
25728
|
const runtime = await readRuntimeRecord(configPath);
|
|
26079
25729
|
const agent = runtimeAgentCommand(runtime);
|
|
26080
25730
|
const config = loadBodyConfig({
|
|
26081
|
-
workspaceRoot:
|
|
25731
|
+
workspaceRoot: join9(dirname15(configPath), "workspace"),
|
|
26082
25732
|
llmEnvFile: runtime.llmEnvFile,
|
|
26083
25733
|
env: { ...env, BUZZ_AGENT_BIN: agent.command, BUZZ_DEV_MCP_BIN: runtime.mcpBinary },
|
|
26084
25734
|
agent
|
|
@@ -26096,21 +25746,22 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
26096
25746
|
}
|
|
26097
25747
|
const layout = beelineInstallLayout(env);
|
|
26098
25748
|
const releaseId = (layout && await activeReleaseId(layout).catch(() => void 0)) ?? "unknown";
|
|
26099
|
-
const runtimeDir =
|
|
25749
|
+
const runtimeDir = dirname15(configPath);
|
|
26100
25750
|
const outcome = await probeOutcome(() => (options.probe ?? runUpdateFunctionalProbe)({
|
|
26101
25751
|
config,
|
|
26102
25752
|
runtimeDir,
|
|
26103
25753
|
releaseId,
|
|
26104
25754
|
sandboxRequired: runtime.sandbox !== "off",
|
|
25755
|
+
sandboxUnavailableDetail: sandbox.advisory,
|
|
26105
25756
|
// The successor's probe still holds `<runtimeDir>/update-functional-probe`.
|
|
26106
|
-
probeRoot:
|
|
25757
|
+
probeRoot: join9(runtimeDir, "current-release-probe")
|
|
26107
25758
|
}));
|
|
26108
|
-
const report = outcome.kind === "served" ? { probe: "served" } : outcome.kind === "refused" ? { probe: "refused", status: outcome.status, reason: outcome.reason } : { probe: "failed", reason: outcome.reason };
|
|
25759
|
+
const report = outcome.kind === "served" ? { probe: "served" } : outcome.kind === "refused" ? { probe: "refused", status: outcome.status, reason: outcome.reason } : outcome.kind === "sandbox-unavailable" ? { probe: "sandbox-unavailable", reason: outcome.reason } : { probe: "failed", reason: outcome.reason };
|
|
26109
25760
|
write(JSON.stringify(report));
|
|
26110
25761
|
}
|
|
26111
25762
|
|
|
26112
25763
|
// apps/body/dist/release-status.js
|
|
26113
|
-
import { readFile as readFile13, readdir as readdir5, rename as rename6, writeFile as
|
|
25764
|
+
import { readFile as readFile13, readdir as readdir5, rename as rename6, writeFile as writeFile15 } from "node:fs/promises";
|
|
26114
25765
|
import { resolve as resolve27 } from "node:path";
|
|
26115
25766
|
var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
|
|
26116
25767
|
var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
|
|
@@ -26130,7 +25781,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
|
|
|
26130
25781
|
};
|
|
26131
25782
|
const target = resolve27(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
|
|
26132
25783
|
const temporary = `${target}.${status.pid}.tmp`;
|
|
26133
|
-
await
|
|
25784
|
+
await writeFile15(temporary, `${JSON.stringify(status, null, 2)}
|
|
26134
25785
|
`, { mode: 384 });
|
|
26135
25786
|
await rename6(temporary, target);
|
|
26136
25787
|
return status;
|
|
@@ -26264,7 +25915,7 @@ var DaemonExitError = class extends Error {
|
|
|
26264
25915
|
};
|
|
26265
25916
|
async function runStoredDaemon(pathOrPointer) {
|
|
26266
25917
|
const configPath = await resolveRuntimeConfigPath(pathOrPointer);
|
|
26267
|
-
daemonFailureRuntimeDir =
|
|
25918
|
+
daemonFailureRuntimeDir = dirname16(configPath);
|
|
26268
25919
|
const accessMigration = await migrateRuntimeRecordAccessPolicy(configPath);
|
|
26269
25920
|
let runtime = accessMigration.runtime;
|
|
26270
25921
|
if (!runtime.transport) {
|
|
@@ -26276,7 +25927,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
26276
25927
|
runtime = activated.runtime;
|
|
26277
25928
|
const daemonApi = activated.client;
|
|
26278
25929
|
const agent = runtimeAgentCommand(runtime);
|
|
26279
|
-
await
|
|
25930
|
+
await writeFile16(resolve29(dirname16(configPath), "daemon.pid"), `${process.pid}
|
|
26280
25931
|
`, { mode: 384 });
|
|
26281
25932
|
const env = {
|
|
26282
25933
|
...process.env,
|
|
@@ -26284,7 +25935,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
26284
25935
|
BUZZ_DEV_MCP_BIN: runtime.mcpBinary
|
|
26285
25936
|
};
|
|
26286
25937
|
const config = loadBodyConfig({
|
|
26287
|
-
workspaceRoot: resolve29(
|
|
25938
|
+
workspaceRoot: resolve29(dirname16(configPath), "workspace"),
|
|
26288
25939
|
llmEnvFile: runtime.llmEnvFile,
|
|
26289
25940
|
env,
|
|
26290
25941
|
agent
|
|
@@ -26319,7 +25970,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
26319
25970
|
const stop = () => controller.abort();
|
|
26320
25971
|
process.once("SIGINT", stop);
|
|
26321
25972
|
process.once("SIGTERM", stop);
|
|
26322
|
-
const runtimeDir =
|
|
25973
|
+
const runtimeDir = dirname16(configPath);
|
|
26323
25974
|
const layout = beelineInstallLayout(process.env);
|
|
26324
25975
|
const notifier = new SystemdNotifier();
|
|
26325
25976
|
let rollbackAlertDrain;
|
|
@@ -26401,6 +26052,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
26401
26052
|
runtimeDir,
|
|
26402
26053
|
releaseId: loadedRelease ?? "unknown",
|
|
26403
26054
|
sandboxRequired: runtime.sandbox !== "off",
|
|
26055
|
+
sandboxUnavailableDetail: sandbox.advisory,
|
|
26404
26056
|
...currentReleaseId ? {
|
|
26405
26057
|
compareWithCurrentRelease: async (appeal) => {
|
|
26406
26058
|
console.warn(`[thin-core] successor probe got no answer from the provider (${appeal.reason}); probing the current release ${currentReleaseId} for the same outcome`);
|
|
@@ -26465,7 +26117,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
26465
26117
|
} finally {
|
|
26466
26118
|
clearInterval(scratchSweepTimer);
|
|
26467
26119
|
await notifier.stopping(stoppingStatus).catch(() => void 0);
|
|
26468
|
-
const pidPath = resolve29(
|
|
26120
|
+
const pidPath = resolve29(dirname16(configPath), "daemon.pid");
|
|
26469
26121
|
const recorded = Number((await readFile14(pidPath, "utf8").catch(() => "")).trim());
|
|
26470
26122
|
if (recorded === process.pid) {
|
|
26471
26123
|
await unlink5(pidPath).catch(() => void 0);
|
|
@@ -26542,7 +26194,7 @@ async function main() {
|
|
|
26542
26194
|
const agentPubkey = agentFlag >= 0 ? args[agentFlag + 1] : void 0;
|
|
26543
26195
|
if (!configPath && agentPubkey) {
|
|
26544
26196
|
const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
|
|
26545
|
-
configPath = configs.find((candidate) =>
|
|
26197
|
+
configPath = configs.find((candidate) => dirname16(candidate).endsWith(agentPubkey));
|
|
26546
26198
|
}
|
|
26547
26199
|
if (!configPath && agentPubkey) {
|
|
26548
26200
|
throw new DaemonExitError(`unknown agent ${agentPubkey}: no durable runtime exists; refusing systemd restart loop`, UNKNOWN_AGENT_EXIT_STATUS);
|
|
@@ -26570,7 +26222,7 @@ async function main() {
|
|
|
26570
26222
|
if (!agentPubkey)
|
|
26571
26223
|
throw new Error("stop requires --agent <pubkey>");
|
|
26572
26224
|
const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
|
|
26573
|
-
const configPath = configs.find((candidate) =>
|
|
26225
|
+
const configPath = configs.find((candidate) => dirname16(candidate).endsWith(agentPubkey));
|
|
26574
26226
|
if (!configPath)
|
|
26575
26227
|
throw new Error(`no stored runtime found for agent ${agentPubkey}`);
|
|
26576
26228
|
const runtime = await readRuntimeRecord(configPath);
|