usebeeline 0.0.65 → 0.0.71
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 +584 -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,168 @@ 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
|
+
let pushIntakeAcknowledged = false;
|
|
18061
|
+
const pending = new Map(first.commands.map((command) => [command.id, command]));
|
|
18062
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
18063
|
+
const notify2 = (commands = []) => {
|
|
18064
|
+
for (const command of commands)
|
|
18065
|
+
if (!claimed.has(command.id))
|
|
18066
|
+
pending.set(command.id, command);
|
|
18067
|
+
wake?.(false);
|
|
18068
|
+
};
|
|
18069
|
+
options.onWake?.(notify2);
|
|
18070
|
+
const off = api.liveSubscribe?.(roomId, void 0, void 0, (connected, capabilities) => {
|
|
18071
|
+
const acknowledged = connected && capabilities?.pushIntake === true;
|
|
18072
|
+
if (pushIntakeAcknowledged !== acknowledged) {
|
|
18073
|
+
pushIntakeAcknowledged = acknowledged;
|
|
18074
|
+
wake?.(!connected);
|
|
18075
|
+
} else if (!connected) {
|
|
18076
|
+
wake?.(true);
|
|
18077
|
+
}
|
|
18078
|
+
}, options.presence, notify2);
|
|
18079
|
+
try {
|
|
18080
|
+
while (!signal?.aborted) {
|
|
18081
|
+
if (options.closed && await options.closed())
|
|
18082
|
+
return;
|
|
18083
|
+
for (const command of [...pending.values()]) {
|
|
18084
|
+
validateServerCommand(command, roomId, agentId);
|
|
18085
|
+
if (busy && command.action !== "stop")
|
|
18086
|
+
continue;
|
|
18087
|
+
pending.delete(command.id);
|
|
18088
|
+
try {
|
|
18089
|
+
await api.execute("claimAgentCommand", {
|
|
18090
|
+
roomId,
|
|
18091
|
+
commandId: command.id,
|
|
18092
|
+
generationId: context.generationId
|
|
18093
|
+
});
|
|
18094
|
+
} catch (error) {
|
|
18095
|
+
options.onError?.(error);
|
|
18096
|
+
continue;
|
|
18097
|
+
}
|
|
18098
|
+
claimed.add(command.id);
|
|
18099
|
+
if (command.action === "stop") {
|
|
18100
|
+
options.stop(command.turnRequestId);
|
|
18101
|
+
await api.execute("acknowledgeAgentCommand", {
|
|
18102
|
+
roomId,
|
|
18103
|
+
commandId: command.id,
|
|
18104
|
+
generationId: context.generationId
|
|
18105
|
+
});
|
|
18106
|
+
} else {
|
|
18107
|
+
await context.enter(command);
|
|
18108
|
+
busy = options.run(command).catch((error) => {
|
|
18109
|
+
claimed.delete(command.id);
|
|
18110
|
+
options.onError?.(error);
|
|
18111
|
+
}).finally(async () => {
|
|
18112
|
+
await context.leave();
|
|
18113
|
+
busy = void 0;
|
|
18114
|
+
notify2();
|
|
18115
|
+
});
|
|
18116
|
+
}
|
|
18117
|
+
}
|
|
18118
|
+
options.onPoll?.();
|
|
18119
|
+
const reconcile = await new Promise((resolve30) => {
|
|
18120
|
+
const done = (needed) => {
|
|
18121
|
+
if (timer)
|
|
18122
|
+
clearTimeout(timer);
|
|
18123
|
+
signal?.removeEventListener("abort", aborted);
|
|
18124
|
+
wake = void 0;
|
|
18125
|
+
resolve30(needed);
|
|
18126
|
+
};
|
|
18127
|
+
const aborted = () => done(false);
|
|
18128
|
+
wake = done;
|
|
18129
|
+
const timer = setTimeout(() => done(true), pushIntakeAcknowledged ? 6e4 : options.pollMs ?? 1e3);
|
|
18130
|
+
signal?.addEventListener("abort", aborted, { once: true });
|
|
18131
|
+
if (pending.size && !busy)
|
|
18132
|
+
done(false);
|
|
18133
|
+
});
|
|
18134
|
+
if (signal?.aborted)
|
|
18135
|
+
break;
|
|
18136
|
+
if (reconcile) {
|
|
18137
|
+
const page = await api.execute("getAgentCommands", { roomId });
|
|
18138
|
+
if (page.commandProtocol !== 1)
|
|
18139
|
+
throw new Error("server command protocol changed; refusing intake");
|
|
18140
|
+
notify2(page.commands);
|
|
18141
|
+
}
|
|
18142
|
+
}
|
|
18143
|
+
} finally {
|
|
18144
|
+
off?.();
|
|
18145
|
+
options.onWake?.(void 0);
|
|
18146
|
+
if (context.current)
|
|
18147
|
+
options.stop(context.current.turnRequestId);
|
|
18148
|
+
await busy;
|
|
18149
|
+
}
|
|
18150
|
+
}
|
|
18151
|
+
|
|
17997
18152
|
// apps/body/dist/monolith-corner-turn.js
|
|
17998
18153
|
import { execFile as execFile4 } from "node:child_process";
|
|
17999
18154
|
import { createHash as createHash4 } from "node:crypto";
|
|
18000
|
-
import { mkdir as
|
|
18155
|
+
import { mkdir as mkdir11 } from "node:fs/promises";
|
|
18001
18156
|
import { homedir as homedir7 } from "node:os";
|
|
18002
|
-
import { join as
|
|
18157
|
+
import { join as join7 } from "node:path";
|
|
18003
18158
|
import { promisify as promisify3 } from "node:util";
|
|
18004
18159
|
|
|
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
18160
|
// apps/body/dist/agent-home.js
|
|
18114
18161
|
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
|
|
18162
|
+
import { createHash as createHash3, randomUUID as randomUUID3 } from "node:crypto";
|
|
18163
|
+
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
18164
|
import { homedir as homedir5 } from "node:os";
|
|
18118
|
-
import { basename as basename3, dirname as
|
|
18165
|
+
import { basename as basename3, dirname as dirname6, join as join4, relative as relative2, resolve as resolve13, sep } from "node:path";
|
|
18119
18166
|
|
|
18120
18167
|
// apps/body/dist/beeline-skill.js
|
|
18121
18168
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
@@ -18218,7 +18265,7 @@ var SQUIRE_GOVERNED_TOOLS = [
|
|
|
18218
18265
|
var SQUIRE_GOVERNED_TOOL_SET = new Set(SQUIRE_GOVERNED_TOOLS);
|
|
18219
18266
|
|
|
18220
18267
|
// apps/body/dist/openrouter-routing.js
|
|
18221
|
-
import { mkdir as
|
|
18268
|
+
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile5 } from "node:fs/promises";
|
|
18222
18269
|
import { resolve as resolve12 } from "node:path";
|
|
18223
18270
|
var OPENROUTER_ENDPOINTS_BASE_URL = "https://openrouter.ai/api/v1/models";
|
|
18224
18271
|
var OPENROUTER_COMPLETIONS_URL = "https://openrouter.ai/api/v1/chat/completions";
|
|
@@ -18348,8 +18395,8 @@ async function readCache(cacheDir, model) {
|
|
|
18348
18395
|
}
|
|
18349
18396
|
}
|
|
18350
18397
|
async function writeCache(cacheDir, value) {
|
|
18351
|
-
await
|
|
18352
|
-
await
|
|
18398
|
+
await mkdir4(cacheDir, { recursive: true, mode: 448 });
|
|
18399
|
+
await writeFile5(cachePath(cacheDir, value.model), `${JSON.stringify(value, null, 2)}
|
|
18353
18400
|
`, {
|
|
18354
18401
|
mode: 384
|
|
18355
18402
|
});
|
|
@@ -18383,8 +18430,8 @@ async function readProbeCache(cacheDir, model) {
|
|
|
18383
18430
|
}
|
|
18384
18431
|
}
|
|
18385
18432
|
async function writeProbeCache(cacheDir, value) {
|
|
18386
|
-
await
|
|
18387
|
-
await
|
|
18433
|
+
await mkdir4(cacheDir, { recursive: true, mode: 448 });
|
|
18434
|
+
await writeFile5(probeCachePath(cacheDir, value.model), `${JSON.stringify(value, null, 2)}
|
|
18388
18435
|
`, {
|
|
18389
18436
|
mode: 384
|
|
18390
18437
|
});
|
|
@@ -18840,14 +18887,14 @@ async function prepareRoomAgentHome(input) {
|
|
|
18840
18887
|
const root = resolve13(input.root);
|
|
18841
18888
|
const operatorHome = input.operatorHome ?? homedir5();
|
|
18842
18889
|
try {
|
|
18843
|
-
await
|
|
18890
|
+
await mkdir5(root, { recursive: true, mode: 448 });
|
|
18844
18891
|
const rootStats = await lstat(root);
|
|
18845
18892
|
if (!rootStats.isDirectory() || rootStats.isSymbolicLink()) {
|
|
18846
18893
|
throw new AgentHomeSecurityError(`agent home root is not an ordinary directory: ${root}`);
|
|
18847
18894
|
}
|
|
18848
18895
|
for (const subdir of HOME_SUBDIRS) {
|
|
18849
18896
|
const path = resolve13(root, subdir);
|
|
18850
|
-
await
|
|
18897
|
+
await mkdir5(path, { recursive: true, mode: 448 });
|
|
18851
18898
|
await assertRealContainedDirectory(path, root);
|
|
18852
18899
|
}
|
|
18853
18900
|
} catch (error) {
|
|
@@ -18899,7 +18946,7 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
|
|
|
18899
18946
|
}
|
|
18900
18947
|
try {
|
|
18901
18948
|
const gooseConfigDir = resolve13(root, "goose", "config");
|
|
18902
|
-
await
|
|
18949
|
+
await mkdir5(gooseConfigDir, { recursive: true, mode: 448 });
|
|
18903
18950
|
for (const name of GOOSE_SHARED_CONFIG_FILES) {
|
|
18904
18951
|
const source = resolve13(operatorHome, ".config", "goose", name);
|
|
18905
18952
|
const target = resolve13(gooseConfigDir, name);
|
|
@@ -19011,18 +19058,18 @@ function filteredHarnessMcpToml(source) {
|
|
|
19011
19058
|
return extractTomlSections(source, ["mcp_servers"], excluded);
|
|
19012
19059
|
}
|
|
19013
19060
|
async function provisionManagedSkillsDir(target, managedSkills, sharedSkills, optionalShares) {
|
|
19014
|
-
const parent =
|
|
19015
|
-
await assertRealContainedDirectory(parent,
|
|
19061
|
+
const parent = dirname6(target);
|
|
19062
|
+
await assertRealContainedDirectory(parent, dirname6(parent));
|
|
19016
19063
|
const plan = await planManagedSkills(managedSkills, sharedSkills, optionalShares);
|
|
19017
19064
|
if (await materializedSkillManifest(target) === plan.manifest)
|
|
19018
19065
|
return;
|
|
19019
|
-
const staged = resolve13(parent, `.skills.${process.pid}.${
|
|
19020
|
-
await
|
|
19066
|
+
const staged = resolve13(parent, `.skills.${process.pid}.${randomUUID3()}.tmp`);
|
|
19067
|
+
await mkdir5(staged, { mode: 448 });
|
|
19021
19068
|
try {
|
|
19022
19069
|
for (const entry of plan.entries) {
|
|
19023
19070
|
if (entry.kind === "managed") {
|
|
19024
19071
|
const skillDir = resolve13(staged, entry.name);
|
|
19025
|
-
await
|
|
19072
|
+
await mkdir5(skillDir, { recursive: true });
|
|
19026
19073
|
await writeIsolatedHarnessFile(resolve13(skillDir, "SKILL.md"), entry.content);
|
|
19027
19074
|
} else {
|
|
19028
19075
|
await copySafeSkillTree(entry.source, resolve13(staged, entry.name), entry.source);
|
|
@@ -19052,8 +19099,8 @@ async function planManagedSkills(managedSkills, sharedSkills, optionalShares) {
|
|
|
19052
19099
|
try {
|
|
19053
19100
|
const tree = [];
|
|
19054
19101
|
await walkSafeSkillTree(shared.source, shared.source, {
|
|
19055
|
-
directory: async (rel) => void tree.push(`d ${
|
|
19056
|
-
file: async (rel, realPath) => void tree.push(`f ${
|
|
19102
|
+
directory: async (rel) => void tree.push(`d ${join4(shared.name, rel)}`),
|
|
19103
|
+
file: async (rel, realPath) => void tree.push(`f ${join4(shared.name, rel)} ${sha2563(await readFile6(realPath))}`)
|
|
19057
19104
|
});
|
|
19058
19105
|
entries.push({ kind: "shared", name: shared.name, source: shared.source });
|
|
19059
19106
|
lines.push(...tree);
|
|
@@ -19073,7 +19120,7 @@ async function materializedSkillManifest(target) {
|
|
|
19073
19120
|
const visit = async (directory, prefix) => {
|
|
19074
19121
|
for (const entry of await readdir2(directory)) {
|
|
19075
19122
|
const path = resolve13(directory, entry);
|
|
19076
|
-
const rel = prefix ?
|
|
19123
|
+
const rel = prefix ? join4(prefix, entry) : entry;
|
|
19077
19124
|
const entryStats = await lstat(path);
|
|
19078
19125
|
if (entryStats.isSymbolicLink())
|
|
19079
19126
|
return false;
|
|
@@ -19241,7 +19288,7 @@ async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
|
|
|
19241
19288
|
for (const entry of await readdir2(resolvedSource)) {
|
|
19242
19289
|
if (entry === "." || entry === "..")
|
|
19243
19290
|
throw new Error("invalid shared skill entry");
|
|
19244
|
-
await walkSafeSkillTree(resolve13(source, entry), sourceRoot, visitor, rel ?
|
|
19291
|
+
await walkSafeSkillTree(resolve13(source, entry), sourceRoot, visitor, rel ? join4(rel, entry) : entry);
|
|
19245
19292
|
}
|
|
19246
19293
|
return;
|
|
19247
19294
|
}
|
|
@@ -19253,7 +19300,7 @@ async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
|
|
|
19253
19300
|
async function copySafeSkillTree(source, target, sourceRoot) {
|
|
19254
19301
|
await walkSafeSkillTree(source, sourceRoot, {
|
|
19255
19302
|
directory: async (rel) => {
|
|
19256
|
-
await
|
|
19303
|
+
await mkdir5(resolve13(target, rel), { mode: 448 });
|
|
19257
19304
|
},
|
|
19258
19305
|
file: async (rel, realPath) => {
|
|
19259
19306
|
const destination = resolve13(target, rel);
|
|
@@ -19263,14 +19310,14 @@ async function copySafeSkillTree(source, target, sourceRoot) {
|
|
|
19263
19310
|
});
|
|
19264
19311
|
}
|
|
19265
19312
|
async function writeIsolatedHarnessFile(path, content) {
|
|
19266
|
-
const parent =
|
|
19313
|
+
const parent = dirname6(path);
|
|
19267
19314
|
const parentStats = await lstat(parent);
|
|
19268
19315
|
if (!parentStats.isDirectory() || parentStats.isSymbolicLink()) {
|
|
19269
19316
|
throw new Error(`isolated harness parent is not a real directory: ${parent}`);
|
|
19270
19317
|
}
|
|
19271
|
-
const temporary = resolve13(parent, `.${basename3(path)}.${process.pid}.${
|
|
19318
|
+
const temporary = resolve13(parent, `.${basename3(path)}.${process.pid}.${randomUUID3()}.tmp`);
|
|
19272
19319
|
try {
|
|
19273
|
-
await
|
|
19320
|
+
await writeFile6(temporary, content, { mode: 384, flag: "wx" });
|
|
19274
19321
|
await chmod2(temporary, 384);
|
|
19275
19322
|
await rename2(temporary, path);
|
|
19276
19323
|
} finally {
|
|
@@ -19313,8 +19360,8 @@ function harnessStateDirsFromEnv(env) {
|
|
|
19313
19360
|
}
|
|
19314
19361
|
|
|
19315
19362
|
// apps/body/dist/attachment-delivery.js
|
|
19316
|
-
import { mkdir as
|
|
19317
|
-
import { basename as basename4, extname, join as
|
|
19363
|
+
import { mkdir as mkdir6, writeFile as writeFile7 } from "node:fs/promises";
|
|
19364
|
+
import { basename as basename4, extname, join as join5 } from "node:path";
|
|
19318
19365
|
var MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;
|
|
19319
19366
|
var MEDIA_TTL_HOURS = 24;
|
|
19320
19367
|
var EXPIRED_REASON = `expired: attachments are kept for ${MEDIA_TTL_HOURS} hours and these bytes are past that window`;
|
|
@@ -19334,7 +19381,7 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch) {
|
|
|
19334
19381
|
if (!attachments.length)
|
|
19335
19382
|
return [];
|
|
19336
19383
|
const taken = /* @__PURE__ */ new Set();
|
|
19337
|
-
await
|
|
19384
|
+
await mkdir6(dir, { recursive: true });
|
|
19338
19385
|
return Promise.all(attachments.map(async (attachment, index) => {
|
|
19339
19386
|
const tooLarge = (bytes) => ({
|
|
19340
19387
|
attachment,
|
|
@@ -19358,8 +19405,8 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch) {
|
|
|
19358
19405
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
19359
19406
|
if (bytes.length > MAX_ATTACHMENT_BYTES)
|
|
19360
19407
|
return tooLarge(bytes.length);
|
|
19361
|
-
const path =
|
|
19362
|
-
await
|
|
19408
|
+
const path = join5(dir, safeFileName(attachment, index, taken));
|
|
19409
|
+
await writeFile7(path, bytes);
|
|
19363
19410
|
const mimeType = attachment.mimeType ?? response.headers.get("content-type") ?? "";
|
|
19364
19411
|
if (!mimeType.startsWith("image/"))
|
|
19365
19412
|
return { attachment, path };
|
|
@@ -19545,13 +19592,6 @@ function isCornerStatusRestatement(reply, systemLines) {
|
|
|
19545
19592
|
var TurnStoppedError = class extends Error {
|
|
19546
19593
|
name = "TurnStoppedError";
|
|
19547
19594
|
};
|
|
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
19595
|
|
|
19556
19596
|
// apps/body/dist/turn-stream.js
|
|
19557
19597
|
function durableReplyText(agentText) {
|
|
@@ -19724,7 +19764,7 @@ function sessionConfigFingerprint(input) {
|
|
|
19724
19764
|
}
|
|
19725
19765
|
|
|
19726
19766
|
// apps/body/dist/pi-mcp-bridge.js
|
|
19727
|
-
import { mkdir as
|
|
19767
|
+
import { mkdir as mkdir7 } from "node:fs/promises";
|
|
19728
19768
|
import { resolve as resolve14 } from "node:path";
|
|
19729
19769
|
var PI_MCP_BRIDGE_FILENAME = "beeline-mcp-bridge.js";
|
|
19730
19770
|
function harnessMountsSessionMcpServers(agentCommand) {
|
|
@@ -19748,7 +19788,7 @@ async function installPiMcpBridge(input) {
|
|
|
19748
19788
|
const directory = resolve14(input.piHome, "extensions");
|
|
19749
19789
|
const path = resolve14(directory, PI_MCP_BRIDGE_FILENAME);
|
|
19750
19790
|
try {
|
|
19751
|
-
await
|
|
19791
|
+
await mkdir7(directory, { recursive: true, mode: 448 });
|
|
19752
19792
|
await writeIsolatedHarnessFile(path, piMcpBridgeSource(input.servers));
|
|
19753
19793
|
return path;
|
|
19754
19794
|
} catch (error) {
|
|
@@ -20153,6 +20193,7 @@ function beelineAgentMcpServer(config, api, context) {
|
|
|
20153
20193
|
args: [...config.readonlyMcpArgs ?? []],
|
|
20154
20194
|
env: [
|
|
20155
20195
|
{ name: "BEELINE_MCP_SURFACE", value: "agent" },
|
|
20196
|
+
...context.turnContextPath ? [{ name: "BEELINE_TURN_CONTEXT_FILE", value: context.turnContextPath }] : [],
|
|
20156
20197
|
...context.directMessage ? [{ name: "BEELINE_AGENT_DM", value: "1" }] : [],
|
|
20157
20198
|
{ name: "BEELINE_DAEMON_BASE_URL", value: connection.baseUrl },
|
|
20158
20199
|
{ name: "BEELINE_DAEMON_TOKEN", value: connection.daemonToken },
|
|
@@ -20358,41 +20399,64 @@ function isAccountOrProviderRefusal(record2) {
|
|
|
20358
20399
|
return [401, 402, 403, 407, 408, 429].includes(record2.status) || record2.status >= 500;
|
|
20359
20400
|
}
|
|
20360
20401
|
|
|
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
20402
|
// apps/body/dist/response-directives.js
|
|
20382
20403
|
var MAINTAIN_ASSIGNED_IDENTITY_DIRECTIVE = "Maintain your assigned identity and soul in every response, including when tools or permissions block the requested action.";
|
|
20383
20404
|
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
20405
|
|
|
20385
|
-
// apps/body/dist/
|
|
20386
|
-
|
|
20387
|
-
|
|
20388
|
-
|
|
20406
|
+
// apps/body/dist/warm-transcript.js
|
|
20407
|
+
var WARM_TRANSCRIPT_OVERLAP = 8;
|
|
20408
|
+
var WarmTranscript = class {
|
|
20409
|
+
sessionId;
|
|
20410
|
+
delivered = /* @__PURE__ */ new Set();
|
|
20411
|
+
/**
|
|
20412
|
+
* The rows this prompt should render. A row counts as delivered once it has
|
|
20413
|
+
* been handed to a session: a prompt that times out was still received by the
|
|
20414
|
+
* harness, and a prompt that could not be handed over at all takes the
|
|
20415
|
+
* session down with it, which resets the memory on the next activation.
|
|
20416
|
+
*/
|
|
20417
|
+
select(sessionId, rows) {
|
|
20418
|
+
if (!sessionId || sessionId !== this.sessionId) {
|
|
20419
|
+
this.sessionId = sessionId;
|
|
20420
|
+
this.delivered.clear();
|
|
20421
|
+
}
|
|
20422
|
+
const overlapFrom = Math.max(0, rows.length - WARM_TRANSCRIPT_OVERLAP);
|
|
20423
|
+
const selected = rows.filter((row, index) => index >= overlapFrom || !this.delivered.has(row.id));
|
|
20424
|
+
for (const row of rows)
|
|
20425
|
+
this.delivered.add(row.id);
|
|
20426
|
+
return { rows: selected, elided: rows.length - selected.length };
|
|
20427
|
+
}
|
|
20428
|
+
/** Render a selection, and say plainly when it is only what is new. */
|
|
20429
|
+
static render(selection, whole, sinceLastTurn) {
|
|
20430
|
+
const transcript = selection.rows.map((row) => row.line).join("\n");
|
|
20431
|
+
if (!transcript)
|
|
20432
|
+
return "";
|
|
20433
|
+
return `${selection.elided ? sinceLastTurn : whole}
|
|
20434
|
+
${transcript}`;
|
|
20435
|
+
}
|
|
20436
|
+
};
|
|
20389
20437
|
|
|
20390
|
-
//
|
|
20391
|
-
var
|
|
20392
|
-
|
|
20438
|
+
// apps/body/dist/turn-receipt-heartbeat.js
|
|
20439
|
+
var TURN_RECEIPT_HEARTBEAT_MS = 3e4;
|
|
20440
|
+
async function withTurnReceiptHeartbeat(api, receipt, task, onHeartbeatError) {
|
|
20441
|
+
let tail = Promise.resolve();
|
|
20442
|
+
const timer = setInterval(() => {
|
|
20443
|
+
tail = tail.catch(() => void 0).then(() => api.execute("postAgentTurnReceipt", {
|
|
20444
|
+
...receipt,
|
|
20445
|
+
status: "working",
|
|
20446
|
+
heartbeat: true
|
|
20447
|
+
})).then(() => void 0).catch(onHeartbeatError);
|
|
20448
|
+
}, TURN_RECEIPT_HEARTBEAT_MS);
|
|
20449
|
+
timer.unref?.();
|
|
20450
|
+
try {
|
|
20451
|
+
return await task();
|
|
20452
|
+
} finally {
|
|
20453
|
+
clearInterval(timer);
|
|
20454
|
+
await tail;
|
|
20455
|
+
}
|
|
20456
|
+
}
|
|
20393
20457
|
|
|
20394
20458
|
// apps/body/dist/turn-trace.js
|
|
20395
|
-
import { appendFile, mkdir as
|
|
20459
|
+
import { appendFile, mkdir as mkdir8, readdir as readdir4, rm as rm3 } from "node:fs/promises";
|
|
20396
20460
|
import { resolve as resolve17 } from "node:path";
|
|
20397
20461
|
import { performance as performance2 } from "node:perf_hooks";
|
|
20398
20462
|
var TURN_PHASES = [
|
|
@@ -20646,7 +20710,7 @@ var TurnTraceFile = class {
|
|
|
20646
20710
|
this.tail = this.tail.catch(() => void 0).then(async () => {
|
|
20647
20711
|
const now2 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))();
|
|
20648
20712
|
const path = this.path(now2);
|
|
20649
|
-
await
|
|
20713
|
+
await mkdir8(this.directory, { recursive: true, mode: 448 });
|
|
20650
20714
|
await appendFile(path, `${JSON.stringify(record2)}
|
|
20651
20715
|
`, { mode: 384 });
|
|
20652
20716
|
await this.prune(now2);
|
|
@@ -20668,58 +20732,65 @@ var TurnTraceFile = class {
|
|
|
20668
20732
|
}
|
|
20669
20733
|
};
|
|
20670
20734
|
|
|
20671
|
-
// apps/body/dist/
|
|
20672
|
-
|
|
20673
|
-
|
|
20674
|
-
|
|
20675
|
-
|
|
20676
|
-
|
|
20677
|
-
|
|
20678
|
-
|
|
20679
|
-
|
|
20680
|
-
|
|
20681
|
-
|
|
20682
|
-
}
|
|
20683
|
-
|
|
20684
|
-
|
|
20685
|
-
|
|
20686
|
-
|
|
20687
|
-
|
|
20688
|
-
|
|
20735
|
+
// apps/body/dist/corner-github-auth.js
|
|
20736
|
+
import { chmod as chmod3, mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
|
|
20737
|
+
import { delimiter as delimiter2, resolve as resolve18 } from "node:path";
|
|
20738
|
+
async function installCornerGitHubWrappers(input) {
|
|
20739
|
+
const bin = resolve18(input.root, "beeline-github-bin");
|
|
20740
|
+
await mkdir9(bin, { recursive: true, mode: 448 });
|
|
20741
|
+
const common = {
|
|
20742
|
+
node: process.execPath,
|
|
20743
|
+
cli: input.cliEntrypoint,
|
|
20744
|
+
config: input.runtimeConfigPath,
|
|
20745
|
+
room: input.roomId
|
|
20746
|
+
};
|
|
20747
|
+
await writeLauncher(resolve18(bin, "git"), { ...common, command: input.gitBinary });
|
|
20748
|
+
if (input.ghBinary)
|
|
20749
|
+
await writeLauncher(resolve18(bin, "gh"), { ...common, command: input.ghBinary });
|
|
20750
|
+
return {
|
|
20751
|
+
PATH: [bin, input.inheritedPath].filter(Boolean).join(delimiter2),
|
|
20752
|
+
// Static startup tokens take precedence over the refreshed token in gh.
|
|
20753
|
+
GH_TOKEN: "",
|
|
20754
|
+
GITHUB_TOKEN: ""
|
|
20755
|
+
};
|
|
20756
|
+
}
|
|
20757
|
+
async function writeLauncher(path, config) {
|
|
20758
|
+
const source = `#!/usr/bin/env node
|
|
20759
|
+
import { spawnSync } from 'node:child_process';
|
|
20760
|
+
const config = ${JSON.stringify(config)};
|
|
20761
|
+
const authFailure = /(?:authentication failed|bad credentials|could not read username|http(?:\\/\\d(?:\\.\\d)?)? 40[13]|status (?:code )?40[13])/i;
|
|
20762
|
+
function token() {
|
|
20763
|
+
const result = spawnSync(config.node, [config.cli, 'corner-read-token', '--config', config.config, '--room', config.room], { encoding: 'utf8' });
|
|
20764
|
+
if (result.status !== 0) {
|
|
20765
|
+
process.stderr.write(result.stderr || 'Beeline could not refresh the repository credential.\\n');
|
|
20766
|
+
process.exit(result.status || 1);
|
|
20689
20767
|
}
|
|
20768
|
+
return result.stdout.trim();
|
|
20769
|
+
}
|
|
20770
|
+
function run(value) {
|
|
20771
|
+
const env = { ...process.env, GH_TOKEN: value, GITHUB_TOKEN: value, GIT_TERMINAL_PROMPT: '0' };
|
|
20772
|
+
return spawnSync(config.command, process.argv.slice(2), { env, encoding: 'buffer', stdio: ['inherit', 'pipe', 'pipe'] });
|
|
20773
|
+
}
|
|
20774
|
+
let result = run(token());
|
|
20775
|
+
const diagnostic = Buffer.concat([result.stdout || Buffer.alloc(0), result.stderr || Buffer.alloc(0)]).toString('utf8');
|
|
20776
|
+
if (result.status !== 0 && authFailure.test(diagnostic)) result = run(token());
|
|
20777
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
20778
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
20779
|
+
if (result.error) throw result.error;
|
|
20780
|
+
process.exit(result.status ?? 1);
|
|
20781
|
+
`;
|
|
20782
|
+
await writeFile8(path, source, { mode: 448 });
|
|
20783
|
+
await chmod3(path, 448);
|
|
20690
20784
|
}
|
|
20691
20785
|
|
|
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
|
-
};
|
|
20786
|
+
// apps/body/dist/monolith-room-turn.js
|
|
20787
|
+
import { mkdir as mkdir10 } from "node:fs/promises";
|
|
20788
|
+
import { homedir as homedir6 } from "node:os";
|
|
20789
|
+
import { join as join6 } from "node:path";
|
|
20790
|
+
|
|
20791
|
+
// packages/api-contract/dist/scheduled-prompts.js
|
|
20792
|
+
var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
|
|
20793
|
+
var SCHEDULE_RAN_VERB = "ran a schedule for";
|
|
20723
20794
|
|
|
20724
20795
|
// apps/body/dist/monolith-room-turn.js
|
|
20725
20796
|
function isRoomMcpPermissionRequest(request, mountedServers = ROOM_MOUNTED_MCP_SERVERS) {
|
|
@@ -20727,15 +20798,6 @@ function isRoomMcpPermissionRequest(request, mountedServers = ROOM_MOUNTED_MCP_S
|
|
|
20727
20798
|
return false;
|
|
20728
20799
|
return isMountedMcpToolPermissionRequest(request, mountedServers);
|
|
20729
20800
|
}
|
|
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
20801
|
function isScheduledPrompt(item, agentId) {
|
|
20740
20802
|
if (item.type !== "system" || !item.mentionIds.includes(agentId))
|
|
20741
20803
|
return false;
|
|
@@ -20754,30 +20816,6 @@ function inboxItemAuthorName(item, agentId, names) {
|
|
|
20754
20816
|
function inboxItemPromptBody(item, agentId) {
|
|
20755
20817
|
return isScheduledPrompt(item, agentId) ? item.systemEvent?.consequence ?? item.body : item.body;
|
|
20756
20818
|
}
|
|
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
20819
|
function pendingGrantToolCall(call) {
|
|
20782
20820
|
if (!/(?:^|[._:/-])request_grant$/i.test(call.title ?? ""))
|
|
20783
20821
|
return false;
|
|
@@ -20800,6 +20838,7 @@ function roomMentionDirectory(roster, selfId) {
|
|
|
20800
20838
|
return "";
|
|
20801
20839
|
return [
|
|
20802
20840
|
"Room members, and the exact spelling that tags each one:",
|
|
20841
|
+
"An exact agent tag assigns that agent work; use it only when you are asking that agent to act.",
|
|
20803
20842
|
...rows,
|
|
20804
20843
|
"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
20844
|
].join("\n");
|
|
@@ -20812,7 +20851,8 @@ function agentReplyMentionIds(text2, roster, authorId) {
|
|
|
20812
20851
|
for (const member of roster.members) {
|
|
20813
20852
|
if (member.identityId === authorId)
|
|
20814
20853
|
continue;
|
|
20815
|
-
|
|
20854
|
+
const rawAliases = member.kind === "agent" ? [member.handle] : [member.name, member.handle, member.soul?.name];
|
|
20855
|
+
for (const raw of rawAliases) {
|
|
20816
20856
|
const display = raw?.trim().replace(/^@/, "");
|
|
20817
20857
|
if (!display)
|
|
20818
20858
|
continue;
|
|
@@ -20823,7 +20863,7 @@ function agentReplyMentionIds(text2, roster, authorId) {
|
|
|
20823
20863
|
}
|
|
20824
20864
|
}
|
|
20825
20865
|
for (const member of roster.members) {
|
|
20826
|
-
if (member.identityId === authorId || !member.handle)
|
|
20866
|
+
if (member.identityId === authorId || member.kind === "agent" || !member.handle)
|
|
20827
20867
|
continue;
|
|
20828
20868
|
const handle = member.handle.trim().replace(/^@/, "").toLocaleLowerCase();
|
|
20829
20869
|
const canonical = aliases.get(handle);
|
|
@@ -20846,12 +20886,11 @@ function agentReplyMentionIds(text2, roster, authorId) {
|
|
|
20846
20886
|
}
|
|
20847
20887
|
var MonolithRoomTurnLoop = class {
|
|
20848
20888
|
options;
|
|
20889
|
+
commandContext;
|
|
20849
20890
|
agent;
|
|
20850
|
-
reconciliationRequested = true;
|
|
20851
20891
|
wakeIntake;
|
|
20852
20892
|
/** Called by the daemon's one slow workspace reconciliation sweep. */
|
|
20853
20893
|
requestReconciliation() {
|
|
20854
|
-
this.reconciliationRequested = true;
|
|
20855
20894
|
this.wakeIntake?.();
|
|
20856
20895
|
this.wakeIntake = void 0;
|
|
20857
20896
|
}
|
|
@@ -20869,7 +20908,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
20869
20908
|
turnInstructionPrefix = "";
|
|
20870
20909
|
activeTurn;
|
|
20871
20910
|
queuedTurns = [];
|
|
20872
|
-
continuityRebuildRequested = false;
|
|
20873
20911
|
/** Session scratch directory attachments are downloaded into (`TMPDIR/beeline-attachments`). */
|
|
20874
20912
|
attachmentDir;
|
|
20875
20913
|
/** Whether the pinned model takes images; `undefined` when the pin did not say. */
|
|
@@ -20888,18 +20926,21 @@ var MonolithRoomTurnLoop = class {
|
|
|
20888
20926
|
pausedOnGrantRequestId;
|
|
20889
20927
|
/** Operator-local turn traces; built once when the daemon configured a directory. */
|
|
20890
20928
|
turnTraceSink;
|
|
20891
|
-
/** Per-sender continuity, shared in shape with corner intake. */
|
|
20892
|
-
responseRule = new AgentResponseRule();
|
|
20893
20929
|
constructor(options) {
|
|
20894
20930
|
this.options = options;
|
|
20895
20931
|
this.agent = runtimeIdentity(options.runtime.agent);
|
|
20932
|
+
this.commandContext = new CommandExecutionContext(options.config.agentHomeRoot);
|
|
20933
|
+
this.options = { ...options, api: this.commandContext.bind(options.api) };
|
|
20896
20934
|
options.grantRunner?.register(options.roomId, {
|
|
20897
20935
|
workspaceId: options.workspaceId,
|
|
20898
20936
|
cwd: options.cwd,
|
|
20899
20937
|
// A top-level Room keeps its read-only promise for grants too: the runner
|
|
20900
20938
|
// wraps the command in this Room's own mount table (C94).
|
|
20901
20939
|
writePolicy: () => this.grantWritePolicy(),
|
|
20902
|
-
turn: () =>
|
|
20940
|
+
turn: () => {
|
|
20941
|
+
const turn = this.currentTurnForRunner();
|
|
20942
|
+
return turn ? { ...turn, generationId: this.commandContext.generationId } : void 0;
|
|
20943
|
+
}
|
|
20903
20944
|
});
|
|
20904
20945
|
}
|
|
20905
20946
|
isBusy() {
|
|
@@ -20952,9 +20993,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
20952
20993
|
const name = this.memberNames.get(authorId);
|
|
20953
20994
|
return { pubkey: authorId, ...name ? { name } : {} };
|
|
20954
20995
|
}
|
|
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
20996
|
async refreshPersonaForSoulUpdate() {
|
|
20959
20997
|
await this.options.scheduler.suspend(this.options.roomId);
|
|
20960
20998
|
}
|
|
@@ -20971,7 +21009,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
20971
21009
|
workspaceId: this.options.workspaceId
|
|
20972
21010
|
});
|
|
20973
21011
|
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
21012
|
return roster;
|
|
20976
21013
|
}
|
|
20977
21014
|
/**
|
|
@@ -20993,7 +21030,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
20993
21030
|
const cached = this.deliveredAttachments.get(item.id);
|
|
20994
21031
|
if (cached)
|
|
20995
21032
|
return cached;
|
|
20996
|
-
const delivered = await deliverAttachments(item.attachments,
|
|
21033
|
+
const delivered = await deliverAttachments(item.attachments, join6(this.attachmentDir, item.id.replace(/[^\w-]/g, "_")), this.options.fetchImpl);
|
|
20997
21034
|
this.deliveredAttachments.set(item.id, withoutImageData(delivered));
|
|
20998
21035
|
return delivered;
|
|
20999
21036
|
}
|
|
@@ -21060,7 +21097,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21060
21097
|
agentName: self?.name ?? this.agent.name
|
|
21061
21098
|
});
|
|
21062
21099
|
const directMessage = Array.isArray(repositoryState.directParticipants) && repositoryState.directParticipants.length === 2;
|
|
21063
|
-
await
|
|
21100
|
+
await mkdir10(this.options.cwd, { recursive: true });
|
|
21064
21101
|
const selection = configuration.model || configuration.effort ? { model: configuration.model, effort: configuration.effort } : this.options.config.modelSelection;
|
|
21065
21102
|
const homeOverlay = this.options.config.agentHomeRoot ? await prepareRoomAgentHome({
|
|
21066
21103
|
root: this.options.config.agentHomeRoot,
|
|
@@ -21086,14 +21123,14 @@ var MonolithRoomTurnLoop = class {
|
|
|
21086
21123
|
}, selection);
|
|
21087
21124
|
const operatorHome = this.options.config.operatorHome ?? homedir6();
|
|
21088
21125
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
21089
|
-
this.attachmentDir = tmpDir ?
|
|
21126
|
+
this.attachmentDir = tmpDir ? join6(tmpDir, "beeline-attachments") : void 0;
|
|
21090
21127
|
this.sessionScratchDir = tmpDir;
|
|
21091
21128
|
this.sessionStateDirs = stateDirs;
|
|
21092
21129
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
21093
|
-
await Promise.all(homeStateDirs.map((dir) =>
|
|
21130
|
+
await Promise.all(homeStateDirs.map((dir) => mkdir10(dir, { recursive: true })));
|
|
21094
21131
|
const attachScratchRoot = this.options.config.agentHomeRoot ?? tmpDir;
|
|
21095
21132
|
if (attachScratchRoot)
|
|
21096
|
-
await
|
|
21133
|
+
await mkdir10(attachScratchRoot, { recursive: true });
|
|
21097
21134
|
const spawnCommand = wrapAgentCommand({
|
|
21098
21135
|
bwrapPath: this.options.config.bwrapPath,
|
|
21099
21136
|
spec: {
|
|
@@ -21119,6 +21156,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21119
21156
|
// images dir, say), so anything inside the overlay it could possibly
|
|
21120
21157
|
// have written must be attachable, whatever subdirectory that is.
|
|
21121
21158
|
attachScratchRoot,
|
|
21159
|
+
turnContextPath: this.commandContext.path,
|
|
21122
21160
|
directMessage,
|
|
21123
21161
|
...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
|
|
21124
21162
|
})
|
|
@@ -21251,8 +21289,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
21251
21289
|
}).finally(() => {
|
|
21252
21290
|
if (this.activeTurn === active) {
|
|
21253
21291
|
this.activeTurn = void 0;
|
|
21254
|
-
if (active.rebuildContinuity)
|
|
21255
|
-
this.continuityRebuildRequested = true;
|
|
21256
21292
|
this.wakeIntake?.();
|
|
21257
21293
|
this.wakeIntake = void 0;
|
|
21258
21294
|
}
|
|
@@ -21279,24 +21315,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
21279
21315
|
if (this.client && this.sessionId)
|
|
21280
21316
|
this.client.sessionCancel(this.sessionId);
|
|
21281
21317
|
}
|
|
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
21318
|
async prompt(active) {
|
|
21301
21319
|
const { item } = active;
|
|
21302
21320
|
const api = this.options.api;
|
|
@@ -21309,7 +21327,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21309
21327
|
agentId: this.agent.publicKey,
|
|
21310
21328
|
roomId: this.options.roomId,
|
|
21311
21329
|
requestId: item.id,
|
|
21312
|
-
generationId:
|
|
21330
|
+
generationId: this.commandContext.generationId
|
|
21313
21331
|
}, async () => {
|
|
21314
21332
|
await api.execute("postAgentActivity", {
|
|
21315
21333
|
agentId: this.agent.publicKey,
|
|
@@ -21339,7 +21357,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21339
21357
|
id: message.id,
|
|
21340
21358
|
line: roomMessagePrompt(names.get(message.authorId) ?? message.authorId.slice(0, 12), message.body, message.attachments, this.deliveredAttachments.get(message.id), this.acceptsImages())
|
|
21341
21359
|
}));
|
|
21342
|
-
const grantDecision =
|
|
21360
|
+
const grantDecision = this.commandContext.current?.action === "resume";
|
|
21343
21361
|
const resumedRequestId = grantDecision ? this.pausedOnGrantRequestId : void 0;
|
|
21344
21362
|
if (grantDecision)
|
|
21345
21363
|
this.pausedOnGrantRequestId = void 0;
|
|
@@ -21417,8 +21435,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21417
21435
|
}
|
|
21418
21436
|
}
|
|
21419
21437
|
if (active.cancelled) {
|
|
21420
|
-
|
|
21421
|
-
await stream.settle(stoppedText, stoppedText ? { triggerMessageId: item.id } : {});
|
|
21438
|
+
stream.close();
|
|
21422
21439
|
throw new TurnStoppedError("turn stopped by the requester");
|
|
21423
21440
|
}
|
|
21424
21441
|
active.phase = "finishing";
|
|
@@ -21453,21 +21470,10 @@ var MonolithRoomTurnLoop = class {
|
|
|
21453
21470
|
reply = stripCornerOpenEcho(reply);
|
|
21454
21471
|
}
|
|
21455
21472
|
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
21473
|
await trace.measure("publish", () => stream.settle(reply, reply ? {
|
|
21462
21474
|
triggerMessageId: item.id,
|
|
21463
21475
|
mentionIds
|
|
21464
|
-
} : {}
|
|
21465
|
-
this.responseRule.noteReply(this.agent.publicKey, [
|
|
21466
|
-
item.authorId,
|
|
21467
|
-
...posted.mentionIds ?? []
|
|
21468
|
-
]);
|
|
21469
|
-
active.rebuildContinuity = false;
|
|
21470
|
-
} : void 0));
|
|
21476
|
+
} : {}));
|
|
21471
21477
|
}, { priority: "interactive", roomKey: this.options.roomId });
|
|
21472
21478
|
}, (error) => console.error(`[thin-core] monolith Room ${this.options.roomId} receipt heartbeat failed:`, error));
|
|
21473
21479
|
await api.execute("postAgentTurnReceipt", {
|
|
@@ -21475,7 +21481,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21475
21481
|
roomId: this.options.roomId,
|
|
21476
21482
|
requestId: item.id,
|
|
21477
21483
|
status: "complete",
|
|
21478
|
-
generationId:
|
|
21484
|
+
generationId: this.commandContext.generationId
|
|
21479
21485
|
});
|
|
21480
21486
|
await trace.finish("complete");
|
|
21481
21487
|
} catch (error) {
|
|
@@ -21490,7 +21496,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
21490
21496
|
roomId: this.options.roomId,
|
|
21491
21497
|
requestId: item.id,
|
|
21492
21498
|
status: "failed",
|
|
21493
|
-
generationId:
|
|
21499
|
+
generationId: this.commandContext.generationId,
|
|
21494
21500
|
reason
|
|
21495
21501
|
});
|
|
21496
21502
|
await trace.finish("failed", reason);
|
|
@@ -21501,137 +21507,37 @@ var MonolithRoomTurnLoop = class {
|
|
|
21501
21507
|
}
|
|
21502
21508
|
async run() {
|
|
21503
21509
|
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
21510
|
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);
|
|
21511
|
+
await runServerCommandIntake({
|
|
21512
|
+
api,
|
|
21513
|
+
roomId,
|
|
21514
|
+
agentId: this.agent.publicKey,
|
|
21515
|
+
context: this.commandContext,
|
|
21516
|
+
signal,
|
|
21517
|
+
pollMs: this.options.pollMs,
|
|
21518
|
+
presence: {
|
|
21519
|
+
...this.options.config.daemonReleaseVersion ? { releaseVersion: this.options.config.daemonReleaseVersion } : {},
|
|
21520
|
+
...this.options.config.daemonSourceSha ? { sourceSha: this.options.config.daemonSourceSha } : {},
|
|
21521
|
+
available: !this.options.config.modelUnavailable
|
|
21522
|
+
},
|
|
21523
|
+
onWake: (wake) => {
|
|
21524
|
+
this.wakeIntake = wake;
|
|
21525
|
+
},
|
|
21526
|
+
onPoll: () => this.options.health.poll(),
|
|
21527
|
+
onError: (error) => console.error("[thin-core] Room command failed", error),
|
|
21528
|
+
stop: (requestId) => this.stopTurn(requestId),
|
|
21529
|
+
run: async (command) => {
|
|
21530
|
+
const item = {
|
|
21531
|
+
...command.source,
|
|
21532
|
+
id: command.turnRequestId,
|
|
21533
|
+
body: command.action === "resume" ? `Resume the paused turn. The server supplied this grant decision: ${command.source.body}` : command.source.body
|
|
21534
|
+
};
|
|
21535
|
+
this.startPrompt(item);
|
|
21536
|
+
await this.activeTurn?.promise;
|
|
21625
21537
|
}
|
|
21626
|
-
}
|
|
21538
|
+
});
|
|
21627
21539
|
} finally {
|
|
21628
|
-
stopLive?.();
|
|
21629
|
-
this.wakeIntake = void 0;
|
|
21630
21540
|
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
21541
|
await this.options.scheduler.suspend(roomId);
|
|
21636
21542
|
}
|
|
21637
21543
|
}
|
|
@@ -21641,70 +21547,6 @@ function roomMessagePrompt(author, body, attachments, delivered, harnessAcceptsI
|
|
|
21641
21547
|
const rendered = author ? `${author}: ${message}` : message;
|
|
21642
21548
|
return [rendered, ...attachmentPromptLines(attachments, delivered, harnessAcceptsImages)].join("\n");
|
|
21643
21549
|
}
|
|
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
21550
|
|
|
21709
21551
|
// apps/body/dist/monolith-corner-turn.js
|
|
21710
21552
|
var execFileAsync3 = promisify3(execFile4);
|
|
@@ -21835,18 +21677,13 @@ async function cornerToolActivity(call, worktreePath, requestedBy) {
|
|
|
21835
21677
|
...paths.length ? { files: paths.map((path) => ({ path })) } : {}
|
|
21836
21678
|
};
|
|
21837
21679
|
}
|
|
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
21680
|
var MonolithCornerTurnLoop = class {
|
|
21843
21681
|
options;
|
|
21682
|
+
commandContext;
|
|
21844
21683
|
agent;
|
|
21845
|
-
reconciliationRequested = true;
|
|
21846
21684
|
wakeIntake;
|
|
21847
21685
|
/** Called by the daemon's one slow workspace reconciliation sweep. */
|
|
21848
21686
|
requestReconciliation() {
|
|
21849
|
-
this.reconciliationRequested = true;
|
|
21850
21687
|
this.wakeIntake?.();
|
|
21851
21688
|
this.wakeIntake = void 0;
|
|
21852
21689
|
}
|
|
@@ -21878,15 +21715,9 @@ var MonolithCornerTurnLoop = class {
|
|
|
21878
21715
|
turnTraceSink;
|
|
21879
21716
|
memberNames = /* @__PURE__ */ new Map();
|
|
21880
21717
|
/** Agent identities in this Workspace, so a mention can be told from a human's. */
|
|
21881
|
-
agentMembers = /* @__PURE__ */ new Set();
|
|
21882
|
-
rosterAvailable = false;
|
|
21883
21718
|
/** Per-sender continuity, shared in shape with top-level Room intake. */
|
|
21884
|
-
responseRule = new AgentResponseRule();
|
|
21885
|
-
continuityRebuildRequested = false;
|
|
21886
21719
|
/** The member agent that owns corner-wide lifecycle facts such as checks. */
|
|
21887
|
-
carrier;
|
|
21888
21720
|
/** The last server check state that started a turn; the same state never starts another. */
|
|
21889
|
-
lastChecksState;
|
|
21890
21721
|
/**
|
|
21891
21722
|
* Request ids the requester has stopped. A corner's intake is blocked while
|
|
21892
21723
|
* its turn runs, so a stop is recorded from the live-push callback and read
|
|
@@ -21897,6 +21728,8 @@ var MonolithCornerTurnLoop = class {
|
|
|
21897
21728
|
constructor(options) {
|
|
21898
21729
|
this.options = options;
|
|
21899
21730
|
this.agent = runtimeIdentity(options.runtime.agent);
|
|
21731
|
+
this.commandContext = new CommandExecutionContext(options.config.agentHomeRoot);
|
|
21732
|
+
this.options = { ...options, api: this.commandContext.bind(options.api) };
|
|
21900
21733
|
options.grantRunner?.register(options.cornerId, {
|
|
21901
21734
|
workspaceId: options.workspaceId,
|
|
21902
21735
|
cwd: options.worktreePath,
|
|
@@ -21907,15 +21740,12 @@ var MonolithCornerTurnLoop = class {
|
|
|
21907
21740
|
surface: "corner",
|
|
21908
21741
|
...this.sessionScratchDir ? { scratch: this.sessionScratchDir } : {}
|
|
21909
21742
|
}),
|
|
21910
|
-
turn: () => this.currentTurn
|
|
21743
|
+
turn: () => this.currentTurn ? { ...this.currentTurn, generationId: this.commandContext.generationId } : void 0
|
|
21911
21744
|
});
|
|
21912
21745
|
}
|
|
21913
21746
|
isBusy() {
|
|
21914
21747
|
return this.busy;
|
|
21915
21748
|
}
|
|
21916
|
-
currentPrincipalCanDrive(_workspaceId, _principalId) {
|
|
21917
|
-
return Promise.resolve(true);
|
|
21918
|
-
}
|
|
21919
21749
|
refreshPersonaForSoulUpdate() {
|
|
21920
21750
|
return this.options.scheduler.suspend(this.options.cornerId);
|
|
21921
21751
|
}
|
|
@@ -21950,15 +21780,8 @@ var MonolithCornerTurnLoop = class {
|
|
|
21950
21780
|
workspaceId: this.options.workspaceId
|
|
21951
21781
|
});
|
|
21952
21782
|
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
21783
|
return roster;
|
|
21957
21784
|
}
|
|
21958
|
-
async reconcileRoster() {
|
|
21959
|
-
if (!this.rosterAvailable)
|
|
21960
|
-
await this.roster().catch(() => void 0);
|
|
21961
|
-
}
|
|
21962
21785
|
/**
|
|
21963
21786
|
* Drop this corner's live harness process. The next activation starts cold.
|
|
21964
21787
|
* A rotation is a fact about one live session, so the pin goes with it.
|
|
@@ -22011,7 +21834,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
22011
21834
|
soul: configuration.soul ?? self?.soul,
|
|
22012
21835
|
agentName: self?.name ?? this.agent.name
|
|
22013
21836
|
});
|
|
22014
|
-
await
|
|
21837
|
+
await mkdir11(this.options.worktreePath, { recursive: true });
|
|
22015
21838
|
const selection = configuration.model || configuration.effort ? { model: configuration.model, effort: configuration.effort } : this.options.config.modelSelection;
|
|
22016
21839
|
const homeOverlay = this.options.config.agentHomeRoot ? await prepareRoomAgentHome({
|
|
22017
21840
|
root: this.options.config.agentHomeRoot,
|
|
@@ -22056,13 +21879,13 @@ var MonolithCornerTurnLoop = class {
|
|
|
22056
21879
|
}, selection);
|
|
22057
21880
|
const operatorHome = this.options.config.operatorHome ?? homedir7();
|
|
22058
21881
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
22059
|
-
this.attachmentDir = tmpDir ?
|
|
21882
|
+
this.attachmentDir = tmpDir ? join7(tmpDir, "beeline-attachments") : void 0;
|
|
22060
21883
|
this.sessionScratchDir = tmpDir;
|
|
22061
21884
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
22062
|
-
await Promise.all(homeStateDirs.map((dir) =>
|
|
21885
|
+
await Promise.all(homeStateDirs.map((dir) => mkdir11(dir, { recursive: true })));
|
|
22063
21886
|
const attachScratchRoot = this.options.config.agentHomeRoot ?? tmpDir;
|
|
22064
21887
|
if (attachScratchRoot)
|
|
22065
|
-
await
|
|
21888
|
+
await mkdir11(attachScratchRoot, { recursive: true });
|
|
22066
21889
|
const spawnCommand = wrapAgentCommand({
|
|
22067
21890
|
bwrapPath: this.options.config.bwrapPath,
|
|
22068
21891
|
spec: {
|
|
@@ -22115,6 +21938,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
22115
21938
|
// The whole per-session overlay, not an enumerated subset: see
|
|
22116
21939
|
// `monolith-room-turn.ts`'s matching comment.
|
|
22117
21940
|
attachScratchRoot,
|
|
21941
|
+
turnContextPath: this.commandContext.path,
|
|
22118
21942
|
...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
|
|
22119
21943
|
})
|
|
22120
21944
|
];
|
|
@@ -22247,14 +22071,13 @@ var MonolithCornerTurnLoop = class {
|
|
|
22247
22071
|
...this.memberNames.get(requestedById) ? { name: this.memberNames.get(requestedById) } : {}
|
|
22248
22072
|
} : void 0;
|
|
22249
22073
|
this.currentTurn = { requestId, ...requester ? { requester } : {} };
|
|
22250
|
-
this.carrier = this.agent.publicKey;
|
|
22251
22074
|
const trace = this.beginTurnTrace(requestId);
|
|
22252
22075
|
try {
|
|
22253
22076
|
await withTurnReceiptHeartbeat(api, {
|
|
22254
22077
|
agentId: this.agent.publicKey,
|
|
22255
22078
|
roomId: cornerId,
|
|
22256
22079
|
requestId,
|
|
22257
|
-
generationId:
|
|
22080
|
+
generationId: this.commandContext.generationId
|
|
22258
22081
|
}, () => {
|
|
22259
22082
|
trace.noteScheduler("queue", this.options.scheduler.snapshot());
|
|
22260
22083
|
trace.start("queue-wait");
|
|
@@ -22268,7 +22091,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
22268
22091
|
const [conversation, roster, delivered] = await trace.measure("context-fetch", () => Promise.all([
|
|
22269
22092
|
api.execute("getRoomConversation", { roomId: cornerId, limit: 200 }),
|
|
22270
22093
|
this.roster(),
|
|
22271
|
-
this.attachmentDir && attachments.length ? deliverAttachments(attachments,
|
|
22094
|
+
this.attachmentDir && attachments.length ? deliverAttachments(attachments, join7(this.attachmentDir, requestId.replace(/[^\w-]/g, "_")), this.options.fetchImpl) : Promise.resolve([])
|
|
22272
22095
|
]));
|
|
22273
22096
|
const names = new Map(roster.members.map((member) => [member.identityId, member.name]));
|
|
22274
22097
|
const requestedBy = requester && !requester.name && names.get(requester.pubkey) ? { ...requester, name: names.get(requester.pubkey) } : requester;
|
|
@@ -22283,6 +22106,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
22283
22106
|
`Corner objective:
|
|
22284
22107
|
${this.options.objective}`,
|
|
22285
22108
|
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):"),
|
|
22109
|
+
roomMentionDirectory(roster, this.agent.publicKey),
|
|
22286
22110
|
[
|
|
22287
22111
|
`Newest trigger:
|
|
22288
22112
|
${trigger}`,
|
|
@@ -22414,9 +22238,7 @@ ${trigger}`,
|
|
|
22414
22238
|
}
|
|
22415
22239
|
}
|
|
22416
22240
|
if (this.stoppedTurns.has(requestId)) {
|
|
22417
|
-
|
|
22418
|
-
await flushToolCalls(result.toolCalls, stoppedText);
|
|
22419
|
-
await stream.settle(stoppedText);
|
|
22241
|
+
stream.close();
|
|
22420
22242
|
throw new TurnStoppedError("turn stopped by the requester");
|
|
22421
22243
|
}
|
|
22422
22244
|
let reply = durableReplyText(result.agentText);
|
|
@@ -22436,12 +22258,11 @@ ${trigger}`,
|
|
|
22436
22258
|
console.warn(`[thin-core] corner ${cornerId} turn ${requestId}: ${explained.reason}`);
|
|
22437
22259
|
}
|
|
22438
22260
|
const durableReply = spoken(reply);
|
|
22439
|
-
|
|
22440
|
-
|
|
22441
|
-
|
|
22442
|
-
|
|
22443
|
-
|
|
22444
|
-
} : void 0));
|
|
22261
|
+
const mentionIds = durableReply ? agentReplyMentionIds(durableReply, roster, this.agent.publicKey) : [];
|
|
22262
|
+
await trace.measure("publish", () => stream.settle(durableReply, durableReply ? {
|
|
22263
|
+
...requestedById ? { triggerMessageId: requestId } : {},
|
|
22264
|
+
mentionIds
|
|
22265
|
+
} : {}));
|
|
22445
22266
|
}, { priority: "interactive", roomKey: cornerId });
|
|
22446
22267
|
}, (error) => console.error(`[thin-core] corner ${cornerId} receipt heartbeat failed:`, error));
|
|
22447
22268
|
await api.execute("postAgentTurnReceipt", {
|
|
@@ -22449,7 +22270,7 @@ ${trigger}`,
|
|
|
22449
22270
|
roomId: cornerId,
|
|
22450
22271
|
requestId,
|
|
22451
22272
|
status: "complete",
|
|
22452
|
-
generationId:
|
|
22273
|
+
generationId: this.commandContext.generationId
|
|
22453
22274
|
});
|
|
22454
22275
|
await trace.finish("complete");
|
|
22455
22276
|
} catch (error) {
|
|
@@ -22464,7 +22285,7 @@ ${trigger}`,
|
|
|
22464
22285
|
roomId: cornerId,
|
|
22465
22286
|
requestId,
|
|
22466
22287
|
status: "failed",
|
|
22467
|
-
generationId:
|
|
22288
|
+
generationId: this.commandContext.generationId,
|
|
22468
22289
|
reason
|
|
22469
22290
|
});
|
|
22470
22291
|
await trace.finish("failed", reason);
|
|
@@ -22474,46 +22295,6 @@ ${trigger}`,
|
|
|
22474
22295
|
this.currentTurn = void 0;
|
|
22475
22296
|
}
|
|
22476
22297
|
}
|
|
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
22298
|
/**
|
|
22518
22299
|
* Bring this worktree onto the corner's branch as GitHub currently has it,
|
|
22519
22300
|
* before any work is done on top of it.
|
|
@@ -22535,197 +22316,42 @@ ${trigger}`,
|
|
|
22535
22316
|
env: { ...process.env, GH_TOKEN: token, GITHUB_TOKEN: token, GIT_TERMINAL_PROMPT: "0" }
|
|
22536
22317
|
});
|
|
22537
22318
|
}
|
|
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
22319
|
async run() {
|
|
22553
22320
|
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
22321
|
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
|
-
}
|
|
22322
|
+
await runServerCommandIntake({
|
|
22323
|
+
api,
|
|
22324
|
+
roomId: cornerId,
|
|
22325
|
+
agentId: this.agent.publicKey,
|
|
22326
|
+
context: this.commandContext,
|
|
22327
|
+
signal,
|
|
22328
|
+
pollMs: this.options.pollMs,
|
|
22329
|
+
presence: {
|
|
22330
|
+
...this.options.config.daemonReleaseVersion ? { releaseVersion: this.options.config.daemonReleaseVersion } : {},
|
|
22331
|
+
...this.options.config.daemonSourceSha ? { sourceSha: this.options.config.daemonSourceSha } : {},
|
|
22332
|
+
available: !this.options.config.modelUnavailable
|
|
22333
|
+
},
|
|
22334
|
+
onWake: (wake) => {
|
|
22335
|
+
this.wakeIntake = wake;
|
|
22336
|
+
},
|
|
22337
|
+
onPoll: () => this.options.onPoll(),
|
|
22338
|
+
onError: (error) => console.error("[thin-core] corner command failed", error),
|
|
22339
|
+
stop: (requestId) => this.stopTurn(requestId),
|
|
22340
|
+
closed: async () => {
|
|
22341
|
+
const state = await api.execute("getCornerRestoreState", { cornerId });
|
|
22342
|
+
if (!state.closeRequested)
|
|
22343
|
+
return false;
|
|
22344
|
+
await this.options.onCloseRequested();
|
|
22345
|
+
return true;
|
|
22346
|
+
},
|
|
22347
|
+
run: (command) => this.prompt(command.turnRequestId, command.source.body, command.source.attachments, command.source.authorId, command.reason === "corner_check" ? [command.source.body] : void 0)
|
|
22348
|
+
});
|
|
22708
22349
|
} finally {
|
|
22709
|
-
stopLive?.();
|
|
22710
|
-
this.wakeIntake = void 0;
|
|
22711
22350
|
this.options.grantRunner?.unregister(cornerId);
|
|
22712
22351
|
await this.options.scheduler.suspend(cornerId);
|
|
22713
22352
|
}
|
|
22714
22353
|
}
|
|
22715
22354
|
};
|
|
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
22355
|
|
|
22730
22356
|
// apps/body/dist/session-scheduler.js
|
|
22731
22357
|
var DEFAULT_PER_ROOM_LIVE_SESSIONS = 10;
|
|
@@ -23145,8 +22771,8 @@ async function materializeCornerWorktree(input) {
|
|
|
23145
22771
|
const repositoryHash = createHash5("sha256").update(remote).digest("hex").slice(0, 24);
|
|
23146
22772
|
const gitCommonDir = resolve19(input.supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
|
|
23147
22773
|
const path = resolve19(input.supervisorRoot, "beeline", "corners", input.cornerId);
|
|
23148
|
-
await
|
|
23149
|
-
await
|
|
22774
|
+
await mkdir12(dirname7(gitCommonDir), { recursive: true, mode: 448 });
|
|
22775
|
+
await mkdir12(dirname7(path), { recursive: true, mode: 448 });
|
|
23150
22776
|
const authEnv = githubGitEnv(input.token);
|
|
23151
22777
|
if (!existsSync4(resolve19(gitCommonDir, "HEAD"))) {
|
|
23152
22778
|
await execFileAsync4("git", ["clone", "--bare", remote, gitCommonDir], {
|
|
@@ -23333,9 +22959,6 @@ var RoomRuntimeCoordinator = class {
|
|
|
23333
22959
|
this.drainDeadlineAt = Math.min(this.drainDeadlineAt ?? Number.POSITIVE_INFINITY, deadlineAt);
|
|
23334
22960
|
}
|
|
23335
22961
|
}
|
|
23336
|
-
async currentPrincipalCanDrive(roomId, workspaceId, principalId) {
|
|
23337
|
-
return this.running.get(roomId)?.body.currentPrincipalCanDrive(workspaceId, principalId);
|
|
23338
|
-
}
|
|
23339
22962
|
async prepareForForcedUpdateRestart() {
|
|
23340
22963
|
const rooms = [...this.running.values()];
|
|
23341
22964
|
await Promise.allSettled(rooms.filter((room) => room.body.isBusy()).map((room) => room.body.prepareForForcedUpdateRestart()));
|
|
@@ -23420,7 +23043,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
23420
23043
|
return this.runtime.rooms.find((room) => room.channelId === roomId);
|
|
23421
23044
|
}
|
|
23422
23045
|
roomRoot(roomId) {
|
|
23423
|
-
return this.roomRecord(roomId)?.root ?? resolve19(
|
|
23046
|
+
return this.roomRecord(roomId)?.root ?? resolve19(dirname7(this.configPath), "rooms", roomId);
|
|
23424
23047
|
}
|
|
23425
23048
|
roomAgentHomeRoot(workspaceRoot, required = false) {
|
|
23426
23049
|
const flag = process.env.BUZZY_BODY_ROOM_HOME;
|
|
@@ -23443,9 +23066,9 @@ var RoomRuntimeCoordinator = class {
|
|
|
23443
23066
|
...this.baseConfig,
|
|
23444
23067
|
workspaceRoot,
|
|
23445
23068
|
agentPrivateRoot: resolve19(workspaceRoot, "agent-private"),
|
|
23446
|
-
agentMemoryRoot: resolve19(
|
|
23447
|
-
openRouterRoutingCacheDir: openRouterRoutingCacheDir(
|
|
23448
|
-
turnTraceDir: turnTraceDirectory(
|
|
23069
|
+
agentMemoryRoot: resolve19(dirname7(this.configPath), "memory"),
|
|
23070
|
+
openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname7(this.configPath)),
|
|
23071
|
+
turnTraceDir: turnTraceDirectory(dirname7(this.configPath)),
|
|
23449
23072
|
...agentHomeRoot ? { agentHomeRoot } : {}
|
|
23450
23073
|
};
|
|
23451
23074
|
}
|
|
@@ -23513,7 +23136,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
23513
23136
|
const targetBranch = repository.targetBranch || "main";
|
|
23514
23137
|
const checkoutId = createHash5("sha256").update(`${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
|
|
23515
23138
|
const path = resolve19(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
|
|
23516
|
-
await
|
|
23139
|
+
await mkdir12(dirname7(path), { recursive: true, mode: 448 });
|
|
23517
23140
|
const token = remote.startsWith("https://github.com/") ? await this.options.daemonApi.execute("getRoomGitHubToken", { roomId }) : void 0;
|
|
23518
23141
|
const env = token ? githubGitEnv(token.token) : process.env;
|
|
23519
23142
|
if (!existsSync4(resolve19(path, ".git"))) {
|
|
@@ -23579,7 +23202,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
23579
23202
|
}) : void 0;
|
|
23580
23203
|
const workspacePath = worktree?.path ?? resolve19(this.roomRoot(corner.cornerId), "scratch");
|
|
23581
23204
|
if (!worktree)
|
|
23582
|
-
await
|
|
23205
|
+
await mkdir12(workspacePath, { recursive: true, mode: 448 });
|
|
23583
23206
|
const isOpener = !corner.openedBy || corner.openedBy === this.agent.publicKey;
|
|
23584
23207
|
if (worktree && shouldPostInitialCornerWorkingState(restore, isOpener)) {
|
|
23585
23208
|
await this.options.daemonApi.execute("postCornerRemoteState", {
|
|
@@ -23878,9 +23501,9 @@ var ThinDaemonCore = class {
|
|
|
23878
23501
|
|
|
23879
23502
|
// apps/body/dist/systemd.js
|
|
23880
23503
|
import { execFile as execFile6 } from "node:child_process";
|
|
23881
|
-
import { mkdir as
|
|
23504
|
+
import { mkdir as mkdir13, readFile as readFile8, writeFile as writeFile9 } from "node:fs/promises";
|
|
23882
23505
|
import { homedir as homedir8 } from "node:os";
|
|
23883
|
-
import { dirname as
|
|
23506
|
+
import { dirname as dirname8, resolve as resolve20 } from "node:path";
|
|
23884
23507
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
23885
23508
|
import { promisify as promisify5 } from "node:util";
|
|
23886
23509
|
var execFileAsync5 = promisify5(execFile6);
|
|
@@ -23951,8 +23574,8 @@ async function installAgentService(publicKey, options = {}) {
|
|
|
23951
23574
|
const content = agentServiceUnit();
|
|
23952
23575
|
const existing = await readFile8(path, "utf8").catch(() => "");
|
|
23953
23576
|
if (existing !== content) {
|
|
23954
|
-
await
|
|
23955
|
-
await
|
|
23577
|
+
await mkdir13(dirname8(path), { recursive: true, mode: 448 });
|
|
23578
|
+
await writeFile9(path, content, { mode: 384 });
|
|
23956
23579
|
}
|
|
23957
23580
|
const run2 = options.run ?? runSystemctl;
|
|
23958
23581
|
await run2(["daemon-reload"]);
|
|
@@ -24032,7 +23655,7 @@ async function retireRemovedAgent(runtime, options = {}) {
|
|
|
24032
23655
|
}
|
|
24033
23656
|
|
|
24034
23657
|
// apps/body/dist/start-command.js
|
|
24035
|
-
import { dirname as
|
|
23658
|
+
import { dirname as dirname9 } from "node:path";
|
|
24036
23659
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
24037
23660
|
var DEFAULT_RESTART_DRAIN_TIMEOUT_MS = 30 * 6e4;
|
|
24038
23661
|
var RESTART_WAIT_REPORT_INTERVAL_MS = 3e4;
|
|
@@ -24107,7 +23730,7 @@ async function runStartCommand(args, interactiveUi) {
|
|
|
24107
23730
|
continue;
|
|
24108
23731
|
}
|
|
24109
23732
|
const spinnerHandle = spinner();
|
|
24110
|
-
spinnerHandle.start(`Starting ${
|
|
23733
|
+
spinnerHandle.start(`Starting ${dirname9(path)}\u2026`);
|
|
24111
23734
|
try {
|
|
24112
23735
|
await startRuntime(path, spinnerHandle);
|
|
24113
23736
|
spinnerHandle.stop(import_picocolors.default.green("Started."));
|
|
@@ -24124,8 +23747,8 @@ async function runStartCommand(args, interactiveUi) {
|
|
|
24124
23747
|
// apps/body/dist/connect-command.js
|
|
24125
23748
|
import { spawn as spawn5 } from "node:child_process";
|
|
24126
23749
|
import { createHash as createHash7 } from "node:crypto";
|
|
24127
|
-
import { chmod as chmod5, mkdir as
|
|
24128
|
-
import { dirname as
|
|
23750
|
+
import { chmod as chmod5, mkdir as mkdir15, readFile as readFile10, unlink as unlink2, writeFile as writeFile11 } from "node:fs/promises";
|
|
23751
|
+
import { dirname as dirname11, resolve as resolve22 } from "node:path";
|
|
24129
23752
|
import { stdin as stdin3, stdout as stdout4 } from "node:process";
|
|
24130
23753
|
|
|
24131
23754
|
// apps/body/dist/clack-support.js
|
|
@@ -24769,8 +24392,8 @@ function providerEnvironment(selection) {
|
|
|
24769
24392
|
};
|
|
24770
24393
|
}
|
|
24771
24394
|
async function writePrivateJson(path, value) {
|
|
24772
|
-
await
|
|
24773
|
-
await
|
|
24395
|
+
await mkdir15(dirname11(path), { recursive: true, mode: 448 });
|
|
24396
|
+
await writeFile11(path, `${JSON.stringify(value, null, 2)}
|
|
24774
24397
|
`, { mode: 384 });
|
|
24775
24398
|
await chmod5(path, 384);
|
|
24776
24399
|
}
|
|
@@ -24779,9 +24402,9 @@ async function writeProviderEnv(selection, agentPubkey) {
|
|
|
24779
24402
|
if (Object.keys(values).length === 0)
|
|
24780
24403
|
return void 0;
|
|
24781
24404
|
const path = resolve22(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
|
|
24782
|
-
await
|
|
24405
|
+
await mkdir15(dirname11(path), { recursive: true, mode: 448 });
|
|
24783
24406
|
const contents = Object.entries(values).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n");
|
|
24784
|
-
await
|
|
24407
|
+
await writeFile11(path, `${contents}
|
|
24785
24408
|
`, { mode: 384 });
|
|
24786
24409
|
await chmod5(path, 384);
|
|
24787
24410
|
return path;
|
|
@@ -24937,7 +24560,7 @@ async function runConnectFinishCommand(path) {
|
|
|
24937
24560
|
if (model) {
|
|
24938
24561
|
const decision2 = await resolveOpenRouterRouting({
|
|
24939
24562
|
model,
|
|
24940
|
-
cacheDir: openRouterRoutingCacheDir(
|
|
24563
|
+
cacheDir: openRouterRoutingCacheDir(dirname11(connected.configPath)),
|
|
24941
24564
|
...apiKey ? { apiKey } : {},
|
|
24942
24565
|
probeTimeoutMs: 1e4
|
|
24943
24566
|
});
|
|
@@ -24959,12 +24582,12 @@ init_self_update_manifest();
|
|
|
24959
24582
|
// apps/body/dist/managed-update.js
|
|
24960
24583
|
init_self_update();
|
|
24961
24584
|
import { spawn as spawn6 } from "node:child_process";
|
|
24962
|
-
import { mkdir as
|
|
24963
|
-
import { dirname as
|
|
24585
|
+
import { mkdir as mkdir17, rm as rm6, stat as stat2, writeFile as writeFile13 } from "node:fs/promises";
|
|
24586
|
+
import { dirname as dirname13, resolve as resolve24 } from "node:path";
|
|
24964
24587
|
|
|
24965
24588
|
// apps/body/dist/update-rollback-alert.js
|
|
24966
|
-
import { mkdir as
|
|
24967
|
-
import { dirname as
|
|
24589
|
+
import { mkdir as mkdir16, readFile as readFile11, rename as rename4, unlink as unlink3, writeFile as writeFile12 } from "node:fs/promises";
|
|
24590
|
+
import { dirname as dirname12, resolve as resolve23 } from "node:path";
|
|
24968
24591
|
var REPORT_INTERVAL_MS = 60 * 60 * 1e3;
|
|
24969
24592
|
var lastLogged = /* @__PURE__ */ new Map();
|
|
24970
24593
|
function updateRollbackAlertPath(runtimeDir) {
|
|
@@ -24973,8 +24596,8 @@ function updateRollbackAlertPath(runtimeDir) {
|
|
|
24973
24596
|
async function writeAlert(runtimeDir, alert) {
|
|
24974
24597
|
const path = updateRollbackAlertPath(runtimeDir);
|
|
24975
24598
|
const staged = `${path}.${process.pid}.tmp`;
|
|
24976
|
-
await
|
|
24977
|
-
await
|
|
24599
|
+
await mkdir16(dirname12(path), { recursive: true });
|
|
24600
|
+
await writeFile12(staged, `${JSON.stringify(alert, null, 2)}
|
|
24978
24601
|
`, { mode: 384 });
|
|
24979
24602
|
await rename4(staged, path);
|
|
24980
24603
|
}
|
|
@@ -25039,11 +24662,11 @@ async function withInstallLock(layout, work, options = {}) {
|
|
|
25039
24662
|
const now2 = options.now ?? Date.now;
|
|
25040
24663
|
const lock = resolve24(layout.releasesRoot, ".state", "install.lock");
|
|
25041
24664
|
const deadline = now2() + (options.waitMs ?? 1e4);
|
|
25042
|
-
await
|
|
24665
|
+
await mkdir17(dirname13(lock), { recursive: true });
|
|
25043
24666
|
for (; ; ) {
|
|
25044
24667
|
try {
|
|
25045
|
-
await
|
|
25046
|
-
await
|
|
24668
|
+
await mkdir17(lock);
|
|
24669
|
+
await writeFile13(resolve24(lock, "owner"), `${process.pid}
|
|
25047
24670
|
${now2()}
|
|
25048
24671
|
`, "utf8");
|
|
25049
24672
|
break;
|
|
@@ -25453,7 +25076,7 @@ async function proveLoadedReleaseReady(layout, runtimeDir, loadedRelease, option
|
|
|
25453
25076
|
});
|
|
25454
25077
|
if (!accepted)
|
|
25455
25078
|
return false;
|
|
25456
|
-
await
|
|
25079
|
+
await writeFile13(resolve24(runtimeDir, "daemon-ready.json"), `${JSON.stringify({
|
|
25457
25080
|
readyAt: (options.now ?? Date.now)(),
|
|
25458
25081
|
loadedRelease,
|
|
25459
25082
|
functionalProof: options.functionalProof
|
|
@@ -25681,8 +25304,8 @@ async function runUpdateCommand(args) {
|
|
|
25681
25304
|
init_self_update();
|
|
25682
25305
|
|
|
25683
25306
|
// apps/body/dist/daemon-failure.js
|
|
25684
|
-
import { mkdir as
|
|
25685
|
-
import { dirname as
|
|
25307
|
+
import { mkdir as mkdir18, readFile as readFile12, rename as rename5, rm as rm7, writeFile as writeFile14 } from "node:fs/promises";
|
|
25308
|
+
import { dirname as dirname14, resolve as resolve25 } from "node:path";
|
|
25686
25309
|
var DAEMON_FAILURE_LIMIT = 3;
|
|
25687
25310
|
var DAEMON_FAILURE_WINDOW_MS = 5 * 6e4;
|
|
25688
25311
|
function daemonFailurePath(runtimeDir) {
|
|
@@ -25702,8 +25325,8 @@ async function readFailureRecord(runtimeDir) {
|
|
|
25702
25325
|
async function writeFailureRecord(runtimeDir, record2) {
|
|
25703
25326
|
const path = daemonFailurePath(runtimeDir);
|
|
25704
25327
|
const staged = `${path}.${process.pid}.tmp`;
|
|
25705
|
-
await
|
|
25706
|
-
await
|
|
25328
|
+
await mkdir18(dirname14(path), { recursive: true, mode: 448 });
|
|
25329
|
+
await writeFile14(staged, `${JSON.stringify(record2, null, 2)}
|
|
25707
25330
|
`, { mode: 384 });
|
|
25708
25331
|
await rename5(staged, path);
|
|
25709
25332
|
}
|
|
@@ -25725,7 +25348,7 @@ async function clearDaemonStartFailures(runtimeDir) {
|
|
|
25725
25348
|
}
|
|
25726
25349
|
|
|
25727
25350
|
// apps/body/dist/update-functional-probe.js
|
|
25728
|
-
import { mkdir as
|
|
25351
|
+
import { mkdir as mkdir19, rm as rm8 } from "node:fs/promises";
|
|
25729
25352
|
import { homedir as homedir10 } from "node:os";
|
|
25730
25353
|
import { resolve as resolve26 } from "node:path";
|
|
25731
25354
|
var UPDATE_PROBE_SESSION_TIMEOUT_MS = 1e4;
|
|
@@ -25771,6 +25394,9 @@ async function probeOutcome(run2) {
|
|
|
25771
25394
|
await run2();
|
|
25772
25395
|
return { kind: "served" };
|
|
25773
25396
|
} catch (error) {
|
|
25397
|
+
if (error instanceof UpdateFunctionalProbeError && error.reason === "sandbox-unavailable") {
|
|
25398
|
+
return { kind: "sandbox-unavailable", reason: error.message };
|
|
25399
|
+
}
|
|
25774
25400
|
if (error instanceof UpdateFunctionalProbeError && error.providerRefusal) {
|
|
25775
25401
|
return { kind: "refused", ...error.providerRefusal };
|
|
25776
25402
|
}
|
|
@@ -25783,6 +25409,8 @@ function describeCurrentReleaseOutcome(outcome) {
|
|
|
25783
25409
|
return "the current release answered";
|
|
25784
25410
|
case "refused":
|
|
25785
25411
|
return `the current release got a different refusal (${outcome.reason})`;
|
|
25412
|
+
case "sandbox-unavailable":
|
|
25413
|
+
return `the current release has the same unavailable sandbox (${outcome.reason})`;
|
|
25786
25414
|
case "unavailable":
|
|
25787
25415
|
return `the current release could not be compared (${outcome.reason})`;
|
|
25788
25416
|
}
|
|
@@ -25794,13 +25422,33 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
25794
25422
|
throw new UpdateFunctionalProbeError("model-unavailable", input.config.modelUnavailable.detail);
|
|
25795
25423
|
}
|
|
25796
25424
|
if (input.sandboxRequired && !input.config.bwrapPath) {
|
|
25797
|
-
|
|
25425
|
+
const detail = input.sandboxUnavailableDetail ?? "the configured bubblewrap boundary did not pass its startup self-test";
|
|
25426
|
+
if (!input.compareWithCurrentRelease) {
|
|
25427
|
+
throw new UpdateFunctionalProbeError("sandbox-unavailable", detail);
|
|
25428
|
+
}
|
|
25429
|
+
const current = await input.compareWithCurrentRelease({
|
|
25430
|
+
kind: "sandbox-unavailable",
|
|
25431
|
+
reason: detail
|
|
25432
|
+
});
|
|
25433
|
+
if (current.kind !== "sandbox-unavailable") {
|
|
25434
|
+
throw new UpdateFunctionalProbeError("sandbox-unavailable", `${detail}; ${describeCurrentReleaseOutcome(current)}`);
|
|
25435
|
+
}
|
|
25436
|
+
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");
|
|
25437
|
+
return {
|
|
25438
|
+
harness,
|
|
25439
|
+
sandboxed: false,
|
|
25440
|
+
sessionStarted: false,
|
|
25441
|
+
turnCompleted: false,
|
|
25442
|
+
nativeTools: [],
|
|
25443
|
+
modelAnswer: "unavailable",
|
|
25444
|
+
modelAnswerReason: `${detail} (the current release has the same host sandbox failure)`
|
|
25445
|
+
};
|
|
25798
25446
|
}
|
|
25799
25447
|
const root = input.probeRoot ?? resolve26(input.runtimeDir, "update-functional-probe");
|
|
25800
25448
|
const cwd = resolve26(root, "checkout");
|
|
25801
25449
|
const homeRoot = resolve26(root, "agent-home");
|
|
25802
25450
|
await rm8(root, { recursive: true, force: true });
|
|
25803
|
-
await
|
|
25451
|
+
await mkdir19(cwd, { recursive: true, mode: 448 });
|
|
25804
25452
|
let client;
|
|
25805
25453
|
try {
|
|
25806
25454
|
const agentEnv = {
|
|
@@ -25830,7 +25478,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
25830
25478
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
25831
25479
|
const operatorHome = input.config.operatorHome ?? homedir10();
|
|
25832
25480
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
25833
|
-
await Promise.all(homeStateDirs.map((dir) =>
|
|
25481
|
+
await Promise.all(homeStateDirs.map((dir) => mkdir19(dir, { recursive: true })));
|
|
25834
25482
|
spawnCommand = wrapAgentCommand({
|
|
25835
25483
|
bwrapPath: input.config.bwrapPath,
|
|
25836
25484
|
spec: {
|
|
@@ -25980,7 +25628,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
25980
25628
|
|
|
25981
25629
|
// apps/body/dist/current-release-probe.js
|
|
25982
25630
|
import { spawn as spawn7 } from "node:child_process";
|
|
25983
|
-
import { dirname as
|
|
25631
|
+
import { dirname as dirname15, join as join9 } from "node:path";
|
|
25984
25632
|
init_self_update();
|
|
25985
25633
|
var CURRENT_RELEASE_PROBE_TIMEOUT_MS = 12e4;
|
|
25986
25634
|
var UPDATE_PROBE_COMMAND = "update-probe";
|
|
@@ -26002,6 +25650,9 @@ function parseReport(line) {
|
|
|
26002
25650
|
if (report.probe === "failed" && typeof report.reason === "string") {
|
|
26003
25651
|
return { probe: "failed", reason: report.reason };
|
|
26004
25652
|
}
|
|
25653
|
+
if (report.probe === "sandbox-unavailable" && typeof report.reason === "string") {
|
|
25654
|
+
return { probe: "sandbox-unavailable", reason: report.reason };
|
|
25655
|
+
}
|
|
26005
25656
|
return void 0;
|
|
26006
25657
|
}
|
|
26007
25658
|
function outcomeFromReport(report) {
|
|
@@ -26010,12 +25661,17 @@ function outcomeFromReport(report) {
|
|
|
26010
25661
|
return { kind: "served" };
|
|
26011
25662
|
case "refused":
|
|
26012
25663
|
return { kind: "refused", status: report.status, reason: report.reason };
|
|
25664
|
+
case "sandbox-unavailable":
|
|
25665
|
+
return { kind: "sandbox-unavailable", reason: report.reason };
|
|
26013
25666
|
case "failed":
|
|
25667
|
+
if (report.reason.startsWith("functional update probe failed (sandbox-unavailable):")) {
|
|
25668
|
+
return { kind: "sandbox-unavailable", reason: report.reason };
|
|
25669
|
+
}
|
|
26014
25670
|
return { kind: "unavailable", reason: report.reason };
|
|
26015
25671
|
}
|
|
26016
25672
|
}
|
|
26017
25673
|
async function probeReleaseInSubprocess(input) {
|
|
26018
|
-
const bundleDir =
|
|
25674
|
+
const bundleDir = join9(input.layout.releasesRoot, input.releaseId);
|
|
26019
25675
|
const entrypoint = await resolveBundleEntrypoint(bundleDir);
|
|
26020
25676
|
if (!entrypoint) {
|
|
26021
25677
|
return { kind: "unavailable", reason: `release ${input.releaseId} has no runnable CLI entrypoint` };
|
|
@@ -26078,7 +25734,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
26078
25734
|
const runtime = await readRuntimeRecord(configPath);
|
|
26079
25735
|
const agent = runtimeAgentCommand(runtime);
|
|
26080
25736
|
const config = loadBodyConfig({
|
|
26081
|
-
workspaceRoot:
|
|
25737
|
+
workspaceRoot: join9(dirname15(configPath), "workspace"),
|
|
26082
25738
|
llmEnvFile: runtime.llmEnvFile,
|
|
26083
25739
|
env: { ...env, BUZZ_AGENT_BIN: agent.command, BUZZ_DEV_MCP_BIN: runtime.mcpBinary },
|
|
26084
25740
|
agent
|
|
@@ -26096,21 +25752,22 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
26096
25752
|
}
|
|
26097
25753
|
const layout = beelineInstallLayout(env);
|
|
26098
25754
|
const releaseId = (layout && await activeReleaseId(layout).catch(() => void 0)) ?? "unknown";
|
|
26099
|
-
const runtimeDir =
|
|
25755
|
+
const runtimeDir = dirname15(configPath);
|
|
26100
25756
|
const outcome = await probeOutcome(() => (options.probe ?? runUpdateFunctionalProbe)({
|
|
26101
25757
|
config,
|
|
26102
25758
|
runtimeDir,
|
|
26103
25759
|
releaseId,
|
|
26104
25760
|
sandboxRequired: runtime.sandbox !== "off",
|
|
25761
|
+
sandboxUnavailableDetail: sandbox.advisory,
|
|
26105
25762
|
// The successor's probe still holds `<runtimeDir>/update-functional-probe`.
|
|
26106
|
-
probeRoot:
|
|
25763
|
+
probeRoot: join9(runtimeDir, "current-release-probe")
|
|
26107
25764
|
}));
|
|
26108
|
-
const report = outcome.kind === "served" ? { probe: "served" } : outcome.kind === "refused" ? { probe: "refused", status: outcome.status, reason: outcome.reason } : { probe: "failed", reason: outcome.reason };
|
|
25765
|
+
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
25766
|
write(JSON.stringify(report));
|
|
26110
25767
|
}
|
|
26111
25768
|
|
|
26112
25769
|
// apps/body/dist/release-status.js
|
|
26113
|
-
import { readFile as readFile13, readdir as readdir5, rename as rename6, writeFile as
|
|
25770
|
+
import { readFile as readFile13, readdir as readdir5, rename as rename6, writeFile as writeFile15 } from "node:fs/promises";
|
|
26114
25771
|
import { resolve as resolve27 } from "node:path";
|
|
26115
25772
|
var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
|
|
26116
25773
|
var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
|
|
@@ -26130,7 +25787,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
|
|
|
26130
25787
|
};
|
|
26131
25788
|
const target = resolve27(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
|
|
26132
25789
|
const temporary = `${target}.${status.pid}.tmp`;
|
|
26133
|
-
await
|
|
25790
|
+
await writeFile15(temporary, `${JSON.stringify(status, null, 2)}
|
|
26134
25791
|
`, { mode: 384 });
|
|
26135
25792
|
await rename6(temporary, target);
|
|
26136
25793
|
return status;
|
|
@@ -26264,7 +25921,7 @@ var DaemonExitError = class extends Error {
|
|
|
26264
25921
|
};
|
|
26265
25922
|
async function runStoredDaemon(pathOrPointer) {
|
|
26266
25923
|
const configPath = await resolveRuntimeConfigPath(pathOrPointer);
|
|
26267
|
-
daemonFailureRuntimeDir =
|
|
25924
|
+
daemonFailureRuntimeDir = dirname16(configPath);
|
|
26268
25925
|
const accessMigration = await migrateRuntimeRecordAccessPolicy(configPath);
|
|
26269
25926
|
let runtime = accessMigration.runtime;
|
|
26270
25927
|
if (!runtime.transport) {
|
|
@@ -26276,7 +25933,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
26276
25933
|
runtime = activated.runtime;
|
|
26277
25934
|
const daemonApi = activated.client;
|
|
26278
25935
|
const agent = runtimeAgentCommand(runtime);
|
|
26279
|
-
await
|
|
25936
|
+
await writeFile16(resolve29(dirname16(configPath), "daemon.pid"), `${process.pid}
|
|
26280
25937
|
`, { mode: 384 });
|
|
26281
25938
|
const env = {
|
|
26282
25939
|
...process.env,
|
|
@@ -26284,7 +25941,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
26284
25941
|
BUZZ_DEV_MCP_BIN: runtime.mcpBinary
|
|
26285
25942
|
};
|
|
26286
25943
|
const config = loadBodyConfig({
|
|
26287
|
-
workspaceRoot: resolve29(
|
|
25944
|
+
workspaceRoot: resolve29(dirname16(configPath), "workspace"),
|
|
26288
25945
|
llmEnvFile: runtime.llmEnvFile,
|
|
26289
25946
|
env,
|
|
26290
25947
|
agent
|
|
@@ -26319,7 +25976,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
26319
25976
|
const stop = () => controller.abort();
|
|
26320
25977
|
process.once("SIGINT", stop);
|
|
26321
25978
|
process.once("SIGTERM", stop);
|
|
26322
|
-
const runtimeDir =
|
|
25979
|
+
const runtimeDir = dirname16(configPath);
|
|
26323
25980
|
const layout = beelineInstallLayout(process.env);
|
|
26324
25981
|
const notifier = new SystemdNotifier();
|
|
26325
25982
|
let rollbackAlertDrain;
|
|
@@ -26401,6 +26058,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
26401
26058
|
runtimeDir,
|
|
26402
26059
|
releaseId: loadedRelease ?? "unknown",
|
|
26403
26060
|
sandboxRequired: runtime.sandbox !== "off",
|
|
26061
|
+
sandboxUnavailableDetail: sandbox.advisory,
|
|
26404
26062
|
...currentReleaseId ? {
|
|
26405
26063
|
compareWithCurrentRelease: async (appeal) => {
|
|
26406
26064
|
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 +26123,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
26465
26123
|
} finally {
|
|
26466
26124
|
clearInterval(scratchSweepTimer);
|
|
26467
26125
|
await notifier.stopping(stoppingStatus).catch(() => void 0);
|
|
26468
|
-
const pidPath = resolve29(
|
|
26126
|
+
const pidPath = resolve29(dirname16(configPath), "daemon.pid");
|
|
26469
26127
|
const recorded = Number((await readFile14(pidPath, "utf8").catch(() => "")).trim());
|
|
26470
26128
|
if (recorded === process.pid) {
|
|
26471
26129
|
await unlink5(pidPath).catch(() => void 0);
|
|
@@ -26542,7 +26200,7 @@ async function main() {
|
|
|
26542
26200
|
const agentPubkey = agentFlag >= 0 ? args[agentFlag + 1] : void 0;
|
|
26543
26201
|
if (!configPath && agentPubkey) {
|
|
26544
26202
|
const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
|
|
26545
|
-
configPath = configs.find((candidate) =>
|
|
26203
|
+
configPath = configs.find((candidate) => dirname16(candidate).endsWith(agentPubkey));
|
|
26546
26204
|
}
|
|
26547
26205
|
if (!configPath && agentPubkey) {
|
|
26548
26206
|
throw new DaemonExitError(`unknown agent ${agentPubkey}: no durable runtime exists; refusing systemd restart loop`, UNKNOWN_AGENT_EXIT_STATUS);
|
|
@@ -26570,7 +26228,7 @@ async function main() {
|
|
|
26570
26228
|
if (!agentPubkey)
|
|
26571
26229
|
throw new Error("stop requires --agent <pubkey>");
|
|
26572
26230
|
const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
|
|
26573
|
-
const configPath = configs.find((candidate) =>
|
|
26231
|
+
const configPath = configs.find((candidate) => dirname16(candidate).endsWith(agentPubkey));
|
|
26574
26232
|
if (!configPath)
|
|
26575
26233
|
throw new Error(`no stored runtime found for agent ${agentPubkey}`);
|
|
26576
26234
|
const runtime = await readRuntimeRecord(configPath);
|