usebeeline 0.0.47 → 0.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/usebeeline.mjs +402 -113
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -309,12 +309,12 @@ __export(self_update_exports, {
|
|
|
309
309
|
});
|
|
310
310
|
import { createHash as createHash5 } from "node:crypto";
|
|
311
311
|
import { constants as fsConstants } from "node:fs";
|
|
312
|
-
import { access, chmod as chmod3, lstat as lstat2, mkdir as
|
|
312
|
+
import { access, chmod as chmod3, lstat as lstat2, mkdir as mkdir12, open, readFile as readFile9, rename as rename3, rm as rm5, symlink as symlink2, writeFile as writeFile8 } from "node:fs/promises";
|
|
313
313
|
import { spawn as spawn4 } from "node:child_process";
|
|
314
314
|
import { homedir as homedir9 } from "node:os";
|
|
315
|
-
import { dirname as dirname9, join as join7, resolve as
|
|
315
|
+
import { dirname as dirname9, join as join7, resolve as resolve20 } from "node:path";
|
|
316
316
|
function anchorLayout(rawLibDir) {
|
|
317
|
-
const libDir =
|
|
317
|
+
const libDir = resolve20(rawLibDir);
|
|
318
318
|
const segments = libDir.split(/[/\\]/);
|
|
319
319
|
const idx = segments.lastIndexOf(RELEASES_SEGMENT);
|
|
320
320
|
if (idx >= 2 && segments[idx - 1] === "lib") {
|
|
@@ -330,9 +330,9 @@ function anchorLayout(rawLibDir) {
|
|
|
330
330
|
// prefix's bin, NOT <prefix>/lib/bin — deriving it one level up was the
|
|
331
331
|
// defect that made activateRelease write its stable forwarders where
|
|
332
332
|
// nothing executed them, leaving stale raw wrappers in <prefix>/bin.
|
|
333
|
-
binDir:
|
|
333
|
+
binDir: resolve20(libDir, "../../bin"),
|
|
334
334
|
libDir,
|
|
335
|
-
releasesRoot:
|
|
335
|
+
releasesRoot: resolve20(libDir, `../${RELEASES_SEGMENT}`)
|
|
336
336
|
};
|
|
337
337
|
}
|
|
338
338
|
function beelineInstallLayout(env = process.env) {
|
|
@@ -343,7 +343,7 @@ function beelineInstallLayout(env = process.env) {
|
|
|
343
343
|
}
|
|
344
344
|
function defaultBeelineInstallLayout(env = process.env) {
|
|
345
345
|
const home = env.HOME?.trim() || homedir9();
|
|
346
|
-
return anchorLayout(
|
|
346
|
+
return anchorLayout(resolve20(home, ".local", "lib", "beeline"));
|
|
347
347
|
}
|
|
348
348
|
function hostPlatformKey() {
|
|
349
349
|
const os = process.platform === "linux" ? "linux" : process.platform === "darwin" ? "darwin" : "";
|
|
@@ -387,7 +387,7 @@ async function readUpdateState(layout) {
|
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
389
|
async function writeUpdateState(layout, state) {
|
|
390
|
-
await
|
|
390
|
+
await mkdir12(join7(layout.releasesRoot, ".state"), { recursive: true });
|
|
391
391
|
await writeFile8(updateStatePath(layout), `${JSON.stringify(state, null, 2)}
|
|
392
392
|
`, "utf8");
|
|
393
393
|
}
|
|
@@ -501,7 +501,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
501
501
|
previouslyVerified = true;
|
|
502
502
|
} catch {
|
|
503
503
|
}
|
|
504
|
-
await
|
|
504
|
+
await mkdir12(releaseDir, { recursive: true });
|
|
505
505
|
const tempArchive = join7(layout.releasesRoot, `.download-${releaseId}-${process.pid}.tar.gz`);
|
|
506
506
|
try {
|
|
507
507
|
log2(`downloading ${published.file}`);
|
|
@@ -588,8 +588,8 @@ async function replaceFile(path, contents, mode) {
|
|
|
588
588
|
async function activateRelease(layout, releaseId) {
|
|
589
589
|
const releaseDir = join7(layout.releasesRoot, releaseId);
|
|
590
590
|
await access(join7(releaseDir, BUNDLE_ENTRYPOINT), fsConstants.F_OK);
|
|
591
|
-
await
|
|
592
|
-
await
|
|
591
|
+
await mkdir12(layout.releasesRoot, { recursive: true });
|
|
592
|
+
await mkdir12(layout.binDir, { recursive: true });
|
|
593
593
|
let previousReleaseId = await activeReleaseId(layout);
|
|
594
594
|
const kind = await pathKind(layout.libDir);
|
|
595
595
|
if (kind === "directory") {
|
|
@@ -628,7 +628,7 @@ async function normalizeLegacyBundleShape(bundleDir) {
|
|
|
628
628
|
}
|
|
629
629
|
if (!anyFlat)
|
|
630
630
|
return;
|
|
631
|
-
await
|
|
631
|
+
await mkdir12(innerLib, { recursive: true });
|
|
632
632
|
for (const name of LEGACY_FLAT_BUNDLE_FILES) {
|
|
633
633
|
try {
|
|
634
634
|
await access(join7(innerLib, name), fsConstants.F_OK);
|
|
@@ -661,7 +661,7 @@ async function repairInstallForwarders(layout, opts = {}) {
|
|
|
661
661
|
}
|
|
662
662
|
if (current === forwarderScript("beeline"))
|
|
663
663
|
return false;
|
|
664
|
-
await
|
|
664
|
+
await mkdir12(layout.binDir, { recursive: true });
|
|
665
665
|
await writeBinForwarders(layout, layout.libDir);
|
|
666
666
|
opts.logger?.(`[body] self-update: repaired <prefix>/bin forwarders to follow the active-bundle anchor (${layout.libDir})`);
|
|
667
667
|
return true;
|
|
@@ -693,7 +693,7 @@ async function readUpdateAttempt(layout) {
|
|
|
693
693
|
}
|
|
694
694
|
}
|
|
695
695
|
async function writeUpdateAttempt(layout, record2) {
|
|
696
|
-
await
|
|
696
|
+
await mkdir12(join7(layout.releasesRoot, ".state"), { recursive: true });
|
|
697
697
|
const path = updateAttemptPath(layout);
|
|
698
698
|
const staged = `${path}.${process.pid}.tmp`;
|
|
699
699
|
await writeFile8(staged, `${JSON.stringify(record2, null, 2)}
|
|
@@ -955,7 +955,7 @@ var init_self_update = __esm({
|
|
|
955
955
|
});
|
|
956
956
|
|
|
957
957
|
// apps/body/dist/cli.js
|
|
958
|
-
import { dirname as dirname15, resolve as
|
|
958
|
+
import { dirname as dirname15, resolve as resolve27 } from "node:path";
|
|
959
959
|
import { readFile as readFile14, unlink as unlink3, writeFile as writeFile14 } from "node:fs/promises";
|
|
960
960
|
import { stdin as stdin4, stdout as stdout5 } from "node:process";
|
|
961
961
|
|
|
@@ -2952,8 +2952,12 @@ function parseSandboxMaskEnv(env) {
|
|
|
2952
2952
|
}
|
|
2953
2953
|
|
|
2954
2954
|
// apps/body/dist/access-policy.js
|
|
2955
|
+
var AGENT_ACCESS_POLICIES = ["everyone", "creator", "allowlist"];
|
|
2955
2956
|
var DEFAULT_ACCESS_POLICY = "creator";
|
|
2956
2957
|
var LEGACY_ACCESS_POLICY = "everyone";
|
|
2958
|
+
function isAgentAccessPolicy(value) {
|
|
2959
|
+
return AGENT_ACCESS_POLICIES.includes(value);
|
|
2960
|
+
}
|
|
2957
2961
|
var ACCESS_REFUSAL_WINDOW_MS = 60 * 60 * 1e3;
|
|
2958
2962
|
function isSenderPermitted(policy, senderPubkey, ownerPubkey, allowlist = void 0) {
|
|
2959
2963
|
if (!senderPubkey)
|
|
@@ -3828,7 +3832,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
3828
3832
|
const current = this.activeRunIds.get(sessionId);
|
|
3829
3833
|
if (current)
|
|
3830
3834
|
return Promise.resolve(current);
|
|
3831
|
-
return new Promise((
|
|
3835
|
+
return new Promise((resolve28, reject) => {
|
|
3832
3836
|
const onUpdate = (update) => {
|
|
3833
3837
|
if (update.sessionId !== sessionId)
|
|
3834
3838
|
return;
|
|
@@ -3836,7 +3840,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
3836
3840
|
if (!runId)
|
|
3837
3841
|
return;
|
|
3838
3842
|
cleanup();
|
|
3839
|
-
|
|
3843
|
+
resolve28(runId);
|
|
3840
3844
|
};
|
|
3841
3845
|
const timer = setTimeout(() => {
|
|
3842
3846
|
cleanup();
|
|
@@ -3920,13 +3924,13 @@ var AcpClient = class extends EventEmitter {
|
|
|
3920
3924
|
}
|
|
3921
3925
|
const id = this.nextId++;
|
|
3922
3926
|
const payload = { jsonrpc: "2.0", id, method, params };
|
|
3923
|
-
return new Promise((
|
|
3927
|
+
return new Promise((resolve28, reject) => {
|
|
3924
3928
|
const timer = setTimeout(() => {
|
|
3925
3929
|
this.pending.delete(id);
|
|
3926
3930
|
reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail, Boolean(onStart), detail));
|
|
3927
3931
|
}, timeoutMs);
|
|
3928
3932
|
this.pending.set(id, {
|
|
3929
|
-
resolve:
|
|
3933
|
+
resolve: resolve28,
|
|
3930
3934
|
reject,
|
|
3931
3935
|
timer,
|
|
3932
3936
|
method,
|
|
@@ -13059,7 +13063,7 @@ async function stageMonolithAgentRuntime(input) {
|
|
|
13059
13063
|
supervisorRoot,
|
|
13060
13064
|
transport: { kind: "monolith", baseUrl, exchangeToken: input.daemonExchangeToken },
|
|
13061
13065
|
...input.llmEnvFile ? { llmEnvFile: input.llmEnvFile } : {},
|
|
13062
|
-
accessPolicy: DEFAULT_ACCESS_POLICY,
|
|
13066
|
+
accessPolicy: input.accessPolicy ?? DEFAULT_ACCESS_POLICY,
|
|
13063
13067
|
agentBinary: input.agentBinary,
|
|
13064
13068
|
agentKind: input.agentKind,
|
|
13065
13069
|
agentCommand: input.agentCommand,
|
|
@@ -13279,8 +13283,8 @@ async function activateDaemonTransport(path, fetchImpl = fetch) {
|
|
|
13279
13283
|
import { execFile as execFile4 } from "node:child_process";
|
|
13280
13284
|
import { createHash as createHash4 } from "node:crypto";
|
|
13281
13285
|
import { existsSync as existsSync4, mkdirSync } from "node:fs";
|
|
13282
|
-
import { mkdir as
|
|
13283
|
-
import { dirname as dirname6, resolve as
|
|
13286
|
+
import { mkdir as mkdir10, rm as rm4 } from "node:fs/promises";
|
|
13287
|
+
import { dirname as dirname6, resolve as resolve18 } from "node:path";
|
|
13284
13288
|
import { promisify as promisify3 } from "node:util";
|
|
13285
13289
|
|
|
13286
13290
|
// apps/body/dist/grant-runner.js
|
|
@@ -14122,7 +14126,7 @@ var GrantRunnerServer = class {
|
|
|
14122
14126
|
|
|
14123
14127
|
// apps/body/dist/monolith-corner-turn.js
|
|
14124
14128
|
import { execFile as execFile3 } from "node:child_process";
|
|
14125
|
-
import { mkdir as
|
|
14129
|
+
import { mkdir as mkdir8 } from "node:fs/promises";
|
|
14126
14130
|
import { homedir as homedir6 } from "node:os";
|
|
14127
14131
|
import { join as join5 } from "node:path";
|
|
14128
14132
|
import { promisify as promisify2 } from "node:util";
|
|
@@ -14147,6 +14151,8 @@ var BEELINE_ROOM_CAPABILITIES = [
|
|
|
14147
14151
|
"Files and photos people share are downloaded for you: read them at the local path named in the prompt (photos may also arrive inline); never fetch the reference URL.",
|
|
14148
14152
|
"To create a file (this Room has no other way to write one), call beeline-agent write_scratch_file with a relative path and content - text by default, or base64 for bytes you computed; it returns a path in your writable session home. To send a file, call beeline-agent attach_file with a path inside your checkout or anywhere in your writable session home (wherever a file you or your harness generated actually landed, including one you just wrote); it is attached to your reply. write_scratch_file produces the file, not a picture - turning it into a raster image needs a converter, which needs shell, which this Room does not have.",
|
|
14149
14153
|
"To run something later or repeatedly, call beeline-agent create_schedule (interval in minutes or a 5-field cron, optional maxRuns); list_schedules / delete_schedule manage them.",
|
|
14154
|
+
"To react to things that HAPPEN in this Room rather than only to what is said to you, call beeline-agent subscribe_events with the kinds you want (joined, schedule-ran, corner-opened, check-passed, check-failed, merged); each one then wakes you for a turn. It replaces your list, so send every kind you want - list_event_subscriptions shows the current one. You do this yourself: nobody has to configure it for you.",
|
|
14155
|
+
"To state something that happened so the Room and other agents can act on it, call beeline-agent emit_event with your own agent:<slug> kind, one sentence, and optionally the agent members to wake. Chains of events are bounded and a refused emit posts nothing.",
|
|
14150
14156
|
"When repository work is needed, you MUST call beeline-agent open_corner with a name of at most three words - it titles the corner everywhere - and a complete objective of no more than 24 words. The host-governed call is the only way to start write work.",
|
|
14151
14157
|
"When open_corner succeeds, the server posts the corner card: do not announce or restate the opening. End the turn with nothing more unless the person asked something else.",
|
|
14152
14158
|
"Never claim an action or reply happened unless the prompt or a tool result proves it."
|
|
@@ -15664,8 +15670,191 @@ function sessionConfigFingerprint(input) {
|
|
|
15664
15670
|
]);
|
|
15665
15671
|
}
|
|
15666
15672
|
|
|
15667
|
-
// apps/body/dist/
|
|
15673
|
+
// apps/body/dist/pi-mcp-bridge.js
|
|
15674
|
+
import { mkdir as mkdir6 } from "node:fs/promises";
|
|
15668
15675
|
import { resolve as resolve14 } from "node:path";
|
|
15676
|
+
var PI_MCP_BRIDGE_FILENAME = "beeline-mcp-bridge.js";
|
|
15677
|
+
function harnessMountsSessionMcpServers(agentCommand) {
|
|
15678
|
+
return !(agentCommand && /(^|[/\\])pi-acp(\.[a-z]+)?$/i.test(agentCommand));
|
|
15679
|
+
}
|
|
15680
|
+
function piMcpBridgeSource(servers) {
|
|
15681
|
+
const manifest = servers.map((server) => ({
|
|
15682
|
+
name: server.name,
|
|
15683
|
+
command: server.command,
|
|
15684
|
+
args: server.args ?? [],
|
|
15685
|
+
env: Object.fromEntries((server.env ?? []).map((entry) => [entry.name, entry.value]))
|
|
15686
|
+
}));
|
|
15687
|
+
return `${BRIDGE_PREAMBLE}const SERVERS = ${JSON.stringify(manifest, null, 2)};
|
|
15688
|
+
${BRIDGE_BODY}`;
|
|
15689
|
+
}
|
|
15690
|
+
async function installPiMcpBridge(input) {
|
|
15691
|
+
if (harnessMountsSessionMcpServers(input.agentCommand))
|
|
15692
|
+
return void 0;
|
|
15693
|
+
if (!input.piHome || !input.servers.length)
|
|
15694
|
+
return void 0;
|
|
15695
|
+
const directory = resolve14(input.piHome, "extensions");
|
|
15696
|
+
const path = resolve14(directory, PI_MCP_BRIDGE_FILENAME);
|
|
15697
|
+
try {
|
|
15698
|
+
await mkdir6(directory, { recursive: true, mode: 448 });
|
|
15699
|
+
await writeIsolatedHarnessFile(path, piMcpBridgeSource(input.servers));
|
|
15700
|
+
return path;
|
|
15701
|
+
} catch (error) {
|
|
15702
|
+
console.error("[body] pi MCP bridge could not be written", path, error);
|
|
15703
|
+
return void 0;
|
|
15704
|
+
}
|
|
15705
|
+
}
|
|
15706
|
+
var BRIDGE_PREAMBLE = `// Generated by Beeline for one Room session. Do not edit: it is rewritten on
|
|
15707
|
+
// every activation. It republishes this session's MCP servers as pi tools,
|
|
15708
|
+
// because pi has no MCP client of its own (apps/body/src/pi-mcp-bridge.ts).
|
|
15709
|
+
import { spawn } from 'node:child_process';
|
|
15710
|
+
|
|
15711
|
+
`;
|
|
15712
|
+
var BRIDGE_BODY = `const LIST_TIMEOUT_MS = 20000;
|
|
15713
|
+
|
|
15714
|
+
/**
|
|
15715
|
+
* One request/response against one MCP server over a short-lived process.
|
|
15716
|
+
*
|
|
15717
|
+
* A fresh process per call keeps nothing alive between turns: these servers
|
|
15718
|
+
* hold no session state - each tool call is a bounded daemon HTTP request - so
|
|
15719
|
+
* a pool would buy latency at the cost of processes outliving the session that
|
|
15720
|
+
* spawned them.
|
|
15721
|
+
*/
|
|
15722
|
+
function callServer(server, request, signal, timeoutMs) {
|
|
15723
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
15724
|
+
const child = spawn(server.command, server.args, {
|
|
15725
|
+
env: { ...process.env, ...server.env },
|
|
15726
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
15727
|
+
});
|
|
15728
|
+
let settled = false;
|
|
15729
|
+
let buffer = '';
|
|
15730
|
+
let timer;
|
|
15731
|
+
const finish = (error, value) => {
|
|
15732
|
+
if (settled) return;
|
|
15733
|
+
settled = true;
|
|
15734
|
+
if (timer) clearTimeout(timer);
|
|
15735
|
+
signal?.removeEventListener?.('abort', onAbort);
|
|
15736
|
+
child.kill('SIGKILL');
|
|
15737
|
+
if (error) rejectPromise(error); else resolvePromise(value);
|
|
15738
|
+
};
|
|
15739
|
+
const onAbort = () => finish(new Error(server.name + ' call cancelled'));
|
|
15740
|
+
if (timeoutMs) {
|
|
15741
|
+
timer = setTimeout(
|
|
15742
|
+
() => finish(new Error(server.name + ' did not answer in ' + timeoutMs + 'ms')),
|
|
15743
|
+
timeoutMs,
|
|
15744
|
+
);
|
|
15745
|
+
}
|
|
15746
|
+
if (signal) {
|
|
15747
|
+
if (signal.aborted) { onAbort(); return; }
|
|
15748
|
+
signal.addEventListener?.('abort', onAbort, { once: true });
|
|
15749
|
+
}
|
|
15750
|
+
child.on('error', (error) => finish(error));
|
|
15751
|
+
child.on('exit', () => finish(new Error(server.name + ' exited before answering')));
|
|
15752
|
+
child.stdout.setEncoding('utf8');
|
|
15753
|
+
child.stdout.on('data', (chunk) => {
|
|
15754
|
+
buffer += chunk;
|
|
15755
|
+
let newline = buffer.indexOf('\\n');
|
|
15756
|
+
while (newline >= 0) {
|
|
15757
|
+
const line = buffer.slice(0, newline).trim();
|
|
15758
|
+
buffer = buffer.slice(newline + 1);
|
|
15759
|
+
if (line) {
|
|
15760
|
+
let message;
|
|
15761
|
+
try { message = JSON.parse(line); } catch { message = undefined; }
|
|
15762
|
+
// Only the answer to OUR id: the initialize reply and any
|
|
15763
|
+
// notification the server writes share this stream.
|
|
15764
|
+
if (message && message.id === request.id) {
|
|
15765
|
+
if (message.error) {
|
|
15766
|
+
finish(new Error(message.error.message || 'MCP error'));
|
|
15767
|
+
} else {
|
|
15768
|
+
finish(undefined, message.result ?? {});
|
|
15769
|
+
}
|
|
15770
|
+
return;
|
|
15771
|
+
}
|
|
15772
|
+
}
|
|
15773
|
+
newline = buffer.indexOf('\\n');
|
|
15774
|
+
}
|
|
15775
|
+
});
|
|
15776
|
+
child.stdin.write(
|
|
15777
|
+
JSON.stringify({
|
|
15778
|
+
jsonrpc: '2.0',
|
|
15779
|
+
id: 0,
|
|
15780
|
+
method: 'initialize',
|
|
15781
|
+
params: {
|
|
15782
|
+
protocolVersion: '2024-11-05',
|
|
15783
|
+
capabilities: {},
|
|
15784
|
+
clientInfo: { name: 'beeline-pi-bridge', version: '1.0.0' },
|
|
15785
|
+
},
|
|
15786
|
+
}) + '\\n',
|
|
15787
|
+
);
|
|
15788
|
+
child.stdin.write(JSON.stringify(request) + '\\n');
|
|
15789
|
+
});
|
|
15790
|
+
}
|
|
15791
|
+
|
|
15792
|
+
function textOf(result) {
|
|
15793
|
+
const content = Array.isArray(result?.content) ? result.content : [];
|
|
15794
|
+
const text = content
|
|
15795
|
+
.filter((part) => part && part.type === 'text' && typeof part.text === 'string')
|
|
15796
|
+
.map((part) => part.text)
|
|
15797
|
+
.join('\\n');
|
|
15798
|
+
return text || 'The tool returned no text.';
|
|
15799
|
+
}
|
|
15800
|
+
|
|
15801
|
+
function labelOf(name) {
|
|
15802
|
+
return name.replace(/_/g, ' ').replace(/^./, (first) => first.toUpperCase());
|
|
15803
|
+
}
|
|
15804
|
+
|
|
15805
|
+
export default async function (pi) {
|
|
15806
|
+
for (const server of SERVERS) {
|
|
15807
|
+
let tools = [];
|
|
15808
|
+
try {
|
|
15809
|
+
const listed = await callServer(
|
|
15810
|
+
server,
|
|
15811
|
+
{ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {} },
|
|
15812
|
+
undefined,
|
|
15813
|
+
LIST_TIMEOUT_MS,
|
|
15814
|
+
);
|
|
15815
|
+
tools = Array.isArray(listed?.tools) ? listed.tools : [];
|
|
15816
|
+
} catch (error) {
|
|
15817
|
+
// A server that will not list is a server whose tools this session does
|
|
15818
|
+
// not have. Say so once; never fail the session over it.
|
|
15819
|
+
console.error('[beeline] MCP server ' + server.name + ' did not list its tools:', error);
|
|
15820
|
+
continue;
|
|
15821
|
+
}
|
|
15822
|
+
for (const tool of tools) {
|
|
15823
|
+
if (!tool || typeof tool.name !== 'string') continue;
|
|
15824
|
+
const schema =
|
|
15825
|
+
tool.inputSchema && typeof tool.inputSchema === 'object'
|
|
15826
|
+
? tool.inputSchema
|
|
15827
|
+
: { type: 'object', properties: {} };
|
|
15828
|
+
pi.registerTool({
|
|
15829
|
+
name: server.name + '__' + tool.name,
|
|
15830
|
+
label: labelOf(tool.name),
|
|
15831
|
+
description: typeof tool.description === 'string' ? tool.description : tool.name,
|
|
15832
|
+
parameters: schema,
|
|
15833
|
+
async execute(_toolCallId, params, signal) {
|
|
15834
|
+
const result = await callServer(
|
|
15835
|
+
server,
|
|
15836
|
+
{
|
|
15837
|
+
jsonrpc: '2.0',
|
|
15838
|
+
id: 1,
|
|
15839
|
+
method: 'tools/call',
|
|
15840
|
+
params: { name: tool.name, arguments: params ?? {} },
|
|
15841
|
+
},
|
|
15842
|
+
signal,
|
|
15843
|
+
);
|
|
15844
|
+
// An MCP refusal is a RESULT carrying isError. Throwing is how a pi
|
|
15845
|
+
// tool reports failure, so the sentence explaining the refusal is
|
|
15846
|
+
// what the model reads.
|
|
15847
|
+
if (result?.isError) throw new Error(textOf(result));
|
|
15848
|
+
return { content: [{ type: 'text', text: textOf(result) }], details: {} };
|
|
15849
|
+
},
|
|
15850
|
+
});
|
|
15851
|
+
}
|
|
15852
|
+
}
|
|
15853
|
+
}
|
|
15854
|
+
`;
|
|
15855
|
+
|
|
15856
|
+
// apps/body/dist/room-session.js
|
|
15857
|
+
import { resolve as resolve15 } from "node:path";
|
|
15669
15858
|
|
|
15670
15859
|
// apps/body/dist/read-only-policy.js
|
|
15671
15860
|
var READ_ONLY_MCP_SERVER_NAME = "beeline-readonly-mcp";
|
|
@@ -15888,21 +16077,21 @@ function readOnlyMcpServer(config, cwd, agentMemoryDir) {
|
|
|
15888
16077
|
command: config.readonlyMcpCommand,
|
|
15889
16078
|
args: [...config.readonlyMcpArgs ?? []],
|
|
15890
16079
|
env: [
|
|
15891
|
-
{ name: "BEELINE_READONLY_ROOT", value:
|
|
16080
|
+
{ name: "BEELINE_READONLY_ROOT", value: resolve15(cwd) },
|
|
15892
16081
|
...config.agentHomeRoot ? [
|
|
15893
16082
|
{
|
|
15894
16083
|
name: "BEELINE_READONLY_AGENT_SKILLS_ROOT",
|
|
15895
|
-
value:
|
|
16084
|
+
value: resolve15(config.agentHomeRoot, skillDir, "skills")
|
|
15896
16085
|
}
|
|
15897
16086
|
] : [],
|
|
15898
|
-
...agentMemoryDir ? [{ name: "BEELINE_READONLY_AGENT_MEMORY_ROOT", value:
|
|
16087
|
+
...agentMemoryDir ? [{ name: "BEELINE_READONLY_AGENT_MEMORY_ROOT", value: resolve15(agentMemoryDir) }] : []
|
|
15899
16088
|
]
|
|
15900
16089
|
};
|
|
15901
16090
|
}
|
|
15902
16091
|
|
|
15903
16092
|
// apps/body/dist/pi-turn-record.js
|
|
15904
16093
|
import { readdir as readdir3, readFile as readFile7 } from "node:fs/promises";
|
|
15905
|
-
import { resolve as
|
|
16094
|
+
import { resolve as resolve16 } from "node:path";
|
|
15906
16095
|
function summarizeProviderError(errorMessage2) {
|
|
15907
16096
|
const trimmed = errorMessage2.trim();
|
|
15908
16097
|
const statusMatch = /^(\d{3}):\s*([\s\S]*)$/.exec(trimmed);
|
|
@@ -15923,7 +16112,7 @@ function summarizeProviderError(errorMessage2) {
|
|
|
15923
16112
|
}
|
|
15924
16113
|
async function sessionFileFromMap(home, sessionId) {
|
|
15925
16114
|
try {
|
|
15926
|
-
const raw = await readFile7(
|
|
16115
|
+
const raw = await readFile7(resolve16(home, ".pi", "pi-acp", "session-map.json"), "utf8");
|
|
15927
16116
|
const map = JSON.parse(raw);
|
|
15928
16117
|
const file = map.sessions?.[sessionId]?.sessionFile;
|
|
15929
16118
|
return typeof file === "string" && file ? file : void 0;
|
|
@@ -15932,7 +16121,7 @@ async function sessionFileFromMap(home, sessionId) {
|
|
|
15932
16121
|
}
|
|
15933
16122
|
}
|
|
15934
16123
|
async function sessionFileFromLayout(piDir, sessionId) {
|
|
15935
|
-
const sessionsRoot =
|
|
16124
|
+
const sessionsRoot = resolve16(piDir, "sessions");
|
|
15936
16125
|
const suffix = `_${sessionId}.jsonl`;
|
|
15937
16126
|
let projects;
|
|
15938
16127
|
try {
|
|
@@ -15941,7 +16130,7 @@ async function sessionFileFromLayout(piDir, sessionId) {
|
|
|
15941
16130
|
return void 0;
|
|
15942
16131
|
}
|
|
15943
16132
|
for (const project of projects) {
|
|
15944
|
-
const dir =
|
|
16133
|
+
const dir = resolve16(sessionsRoot, project);
|
|
15945
16134
|
let files;
|
|
15946
16135
|
try {
|
|
15947
16136
|
files = await readdir3(dir);
|
|
@@ -15950,7 +16139,7 @@ async function sessionFileFromLayout(piDir, sessionId) {
|
|
|
15950
16139
|
}
|
|
15951
16140
|
const match = files.find((file) => file.endsWith(suffix));
|
|
15952
16141
|
if (match)
|
|
15953
|
-
return
|
|
16142
|
+
return resolve16(dir, match);
|
|
15954
16143
|
}
|
|
15955
16144
|
return void 0;
|
|
15956
16145
|
}
|
|
@@ -16145,8 +16334,8 @@ async function withTurnReceiptHeartbeat(api, receipt, task, onHeartbeatError) {
|
|
|
16145
16334
|
}
|
|
16146
16335
|
|
|
16147
16336
|
// apps/body/dist/turn-trace.js
|
|
16148
|
-
import { appendFile, mkdir as
|
|
16149
|
-
import { resolve as
|
|
16337
|
+
import { appendFile, mkdir as mkdir7, readdir as readdir4, rm as rm3 } from "node:fs/promises";
|
|
16338
|
+
import { resolve as resolve17 } from "node:path";
|
|
16150
16339
|
import { performance as performance2 } from "node:perf_hooks";
|
|
16151
16340
|
var TURN_PHASES = [
|
|
16152
16341
|
/** Enqueued on `SessionScheduler` until this turn holds a slot. A capacity wait lives here. */
|
|
@@ -16376,7 +16565,7 @@ function formatTurnTraceLine(record2) {
|
|
|
16376
16565
|
return [head, ...record2.attempts.map((attempt) => formatTurnAttempt(attempt))].join("\n ");
|
|
16377
16566
|
}
|
|
16378
16567
|
function turnTraceDirectory(runtimeDir) {
|
|
16379
|
-
return
|
|
16568
|
+
return resolve17(runtimeDir, "turn-traces");
|
|
16380
16569
|
}
|
|
16381
16570
|
var TURN_TRACE_RETENTION_DAYS = 7;
|
|
16382
16571
|
function traceFileName(date) {
|
|
@@ -16393,13 +16582,13 @@ var TurnTraceFile = class {
|
|
|
16393
16582
|
this.options = options;
|
|
16394
16583
|
}
|
|
16395
16584
|
path(now2 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))()) {
|
|
16396
|
-
return
|
|
16585
|
+
return resolve17(this.directory, traceFileName(now2));
|
|
16397
16586
|
}
|
|
16398
16587
|
write(record2) {
|
|
16399
16588
|
this.tail = this.tail.catch(() => void 0).then(async () => {
|
|
16400
16589
|
const now2 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))();
|
|
16401
16590
|
const path = this.path(now2);
|
|
16402
|
-
await
|
|
16591
|
+
await mkdir7(this.directory, { recursive: true, mode: 448 });
|
|
16403
16592
|
await appendFile(path, `${JSON.stringify(record2)}
|
|
16404
16593
|
`, { mode: 384 });
|
|
16405
16594
|
await this.prune(now2);
|
|
@@ -16417,7 +16606,7 @@ var TurnTraceFile = class {
|
|
|
16417
16606
|
this.prunedDay = day;
|
|
16418
16607
|
const cutoff = traceFileName(new Date(now2.getTime() - TURN_TRACE_RETENTION_DAYS * 864e5));
|
|
16419
16608
|
const names = await readdir4(this.directory).catch(() => []);
|
|
16420
|
-
await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm3(
|
|
16609
|
+
await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm3(resolve17(this.directory, name), { force: true })));
|
|
16421
16610
|
}
|
|
16422
16611
|
};
|
|
16423
16612
|
|
|
@@ -16677,7 +16866,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
16677
16866
|
soul: configuration.soul ?? self?.soul,
|
|
16678
16867
|
agentName: self?.name ?? this.agent.name
|
|
16679
16868
|
});
|
|
16680
|
-
await
|
|
16869
|
+
await mkdir8(this.options.worktreePath, { recursive: true });
|
|
16681
16870
|
const selection = configuration.model || configuration.effort ? { model: configuration.model, effort: configuration.effort } : this.options.config.modelSelection;
|
|
16682
16871
|
const homeOverlay = this.options.config.agentHomeRoot ? await prepareRoomAgentHome({
|
|
16683
16872
|
root: this.options.config.agentHomeRoot,
|
|
@@ -16711,7 +16900,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
16711
16900
|
this.attachmentDir = tmpDir ? join5(tmpDir, "beeline-attachments") : void 0;
|
|
16712
16901
|
this.sessionScratchDir = tmpDir;
|
|
16713
16902
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
16714
|
-
await Promise.all(homeStateDirs.map((dir) =>
|
|
16903
|
+
await Promise.all(homeStateDirs.map((dir) => mkdir8(dir, { recursive: true })));
|
|
16715
16904
|
const spawnCommand = wrapAgentCommand({
|
|
16716
16905
|
bwrapPath: this.options.config.bwrapPath,
|
|
16717
16906
|
spec: {
|
|
@@ -16764,6 +16953,11 @@ var MonolithCornerTurnLoop = class {
|
|
|
16764
16953
|
...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
|
|
16765
16954
|
})
|
|
16766
16955
|
];
|
|
16956
|
+
await installPiMcpBridge({
|
|
16957
|
+
agentCommand: command,
|
|
16958
|
+
piHome: agentEnv.PI_CODING_AGENT_DIR,
|
|
16959
|
+
servers
|
|
16960
|
+
});
|
|
16767
16961
|
const persona = configuration.soul ?? self?.soul;
|
|
16768
16962
|
const identityInstructions = `Your Beeline identity is ${self?.name ?? this.agent.name}.`;
|
|
16769
16963
|
const personaInstructions = [
|
|
@@ -17117,8 +17311,16 @@ async function waitForWake(api, cornerId, signal) {
|
|
|
17117
17311
|
try {
|
|
17118
17312
|
await api.execute("waitForCornerWake", { cornerId });
|
|
17119
17313
|
} catch {
|
|
17314
|
+
await never(signal);
|
|
17120
17315
|
}
|
|
17121
17316
|
}
|
|
17317
|
+
async function never(signal) {
|
|
17318
|
+
if (signal?.aborted)
|
|
17319
|
+
return;
|
|
17320
|
+
await new Promise((resolveNever) => {
|
|
17321
|
+
signal?.addEventListener("abort", () => resolveNever(), { once: true });
|
|
17322
|
+
});
|
|
17323
|
+
}
|
|
17122
17324
|
async function wait(ms, signal) {
|
|
17123
17325
|
if (signal?.aborted)
|
|
17124
17326
|
return;
|
|
@@ -17134,7 +17336,7 @@ async function wait(ms, signal) {
|
|
|
17134
17336
|
}
|
|
17135
17337
|
|
|
17136
17338
|
// apps/body/dist/monolith-room-turn.js
|
|
17137
|
-
import { mkdir as
|
|
17339
|
+
import { mkdir as mkdir9 } from "node:fs/promises";
|
|
17138
17340
|
import { homedir as homedir7 } from "node:os";
|
|
17139
17341
|
import { join as join6 } from "node:path";
|
|
17140
17342
|
|
|
@@ -17142,6 +17344,24 @@ import { join as join6 } from "node:path";
|
|
|
17142
17344
|
var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
|
|
17143
17345
|
var SCHEDULE_RAN_VERB = "ran a schedule for";
|
|
17144
17346
|
|
|
17347
|
+
// packages/api-contract/dist/system-events.js
|
|
17348
|
+
var SERVER_EVENT_KINDS = [
|
|
17349
|
+
"joined",
|
|
17350
|
+
"schedule-ran",
|
|
17351
|
+
"corner-opened",
|
|
17352
|
+
"check-passed",
|
|
17353
|
+
"check-failed",
|
|
17354
|
+
"merged",
|
|
17355
|
+
"grant-decided"
|
|
17356
|
+
];
|
|
17357
|
+
function isServerEventKind(value) {
|
|
17358
|
+
return SERVER_EVENT_KINDS.includes(value);
|
|
17359
|
+
}
|
|
17360
|
+
var RESUME_KINDS = ["grant-decided"];
|
|
17361
|
+
function isResumeKind(value) {
|
|
17362
|
+
return RESUME_KINDS.includes(value);
|
|
17363
|
+
}
|
|
17364
|
+
|
|
17145
17365
|
// apps/body/dist/monolith-room-turn.js
|
|
17146
17366
|
function isRoomMcpPermissionRequest(request, mountedServers = ROOM_MOUNTED_MCP_SERVERS) {
|
|
17147
17367
|
if (isSquireMcpPermissionRequest(request))
|
|
@@ -17152,11 +17372,35 @@ function roomPrincipalMayAddressAgent(authority, humanPermitted) {
|
|
|
17152
17372
|
return authority.member && (authority.principalKind === "agent" || authority.principalKind === "human" && humanPermitted);
|
|
17153
17373
|
}
|
|
17154
17374
|
function isScheduledPrompt(item, agentId) {
|
|
17155
|
-
|
|
17375
|
+
if (item.type !== "system" || !item.mentionIds.includes(agentId))
|
|
17376
|
+
return false;
|
|
17377
|
+
if (item.systemEvent?.kind)
|
|
17378
|
+
return item.systemEvent.kind === "schedule-ran";
|
|
17379
|
+
return item.systemEvent?.verb === SCHEDULE_RAN_VERB;
|
|
17380
|
+
}
|
|
17381
|
+
function inboxItemAuthorName(item, agentId, names) {
|
|
17382
|
+
if (isScheduledPrompt(item, agentId))
|
|
17383
|
+
return SCHEDULE_SCHEDULER_NAME;
|
|
17384
|
+
const subject = item.systemEvent?.subject;
|
|
17385
|
+
if (item.type === "system" && subject?.name)
|
|
17386
|
+
return subject.name;
|
|
17387
|
+
return names.get(item.authorId) ?? item.authorId.slice(0, 12);
|
|
17156
17388
|
}
|
|
17157
17389
|
function inboxItemPromptBody(item, agentId) {
|
|
17158
17390
|
return isScheduledPrompt(item, agentId) ? item.systemEvent?.consequence ?? item.body : item.body;
|
|
17159
17391
|
}
|
|
17392
|
+
function isSubscribedEvent(item, agentId) {
|
|
17393
|
+
const kind = item.systemEvent?.kind;
|
|
17394
|
+
return item.type === "system" && kind !== void 0 && !isResumeKind(kind) && item.mentionIds.includes(agentId);
|
|
17395
|
+
}
|
|
17396
|
+
function inboxItemSkipsSenderPolicy(item, agentId) {
|
|
17397
|
+
if (isGrantDecisionLine(item, agentId))
|
|
17398
|
+
return true;
|
|
17399
|
+
if (item.type !== "system" || !item.mentionIds.includes(agentId))
|
|
17400
|
+
return false;
|
|
17401
|
+
const kind = item.systemEvent?.kind;
|
|
17402
|
+
return kind === void 0 ? isScheduledPrompt(item, agentId) : isServerEventKind(kind);
|
|
17403
|
+
}
|
|
17160
17404
|
function isGrantDecisionLine(item, agentId) {
|
|
17161
17405
|
return item.type === "system" && item.mentionIds.includes(agentId) && parseGrantDecisionLine(item.body) !== void 0;
|
|
17162
17406
|
}
|
|
@@ -17165,7 +17409,7 @@ function inboxItemTriggersTurn(item, agentId) {
|
|
|
17165
17409
|
return false;
|
|
17166
17410
|
if (!item.mentionIds.includes(agentId))
|
|
17167
17411
|
return false;
|
|
17168
|
-
return item.type === "message" || isScheduledPrompt(item, agentId) || isGrantDecisionLine(item, agentId);
|
|
17412
|
+
return item.type === "message" || isSubscribedEvent(item, agentId) || isScheduledPrompt(item, agentId) || isGrantDecisionLine(item, agentId);
|
|
17169
17413
|
}
|
|
17170
17414
|
function pendingGrantToolCall(call) {
|
|
17171
17415
|
if (!/(?:^|[._:/-])request_grant$/i.test(call.title ?? ""))
|
|
@@ -17407,7 +17651,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
17407
17651
|
agentName: self?.name ?? this.agent.name
|
|
17408
17652
|
});
|
|
17409
17653
|
const directMessage = Array.isArray(repositoryState.directParticipants) && repositoryState.directParticipants.length === 2;
|
|
17410
|
-
await
|
|
17654
|
+
await mkdir9(this.options.cwd, { recursive: true });
|
|
17411
17655
|
const selection = configuration.model || configuration.effort ? { model: configuration.model, effort: configuration.effort } : this.options.config.modelSelection;
|
|
17412
17656
|
const homeOverlay = this.options.config.agentHomeRoot ? await prepareRoomAgentHome({
|
|
17413
17657
|
root: this.options.config.agentHomeRoot,
|
|
@@ -17437,7 +17681,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
17437
17681
|
this.sessionScratchDir = tmpDir;
|
|
17438
17682
|
this.sessionStateDirs = stateDirs;
|
|
17439
17683
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
17440
|
-
await Promise.all(homeStateDirs.map((dir) =>
|
|
17684
|
+
await Promise.all(homeStateDirs.map((dir) => mkdir9(dir, { recursive: true })));
|
|
17441
17685
|
const spawnCommand = wrapAgentCommand({
|
|
17442
17686
|
bwrapPath: this.options.config.bwrapPath,
|
|
17443
17687
|
spec: {
|
|
@@ -17466,6 +17710,11 @@ var MonolithRoomTurnLoop = class {
|
|
|
17466
17710
|
...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
|
|
17467
17711
|
})
|
|
17468
17712
|
];
|
|
17713
|
+
await installPiMcpBridge({
|
|
17714
|
+
agentCommand: command,
|
|
17715
|
+
piHome: agentEnv.PI_CODING_AGENT_DIR,
|
|
17716
|
+
servers
|
|
17717
|
+
});
|
|
17469
17718
|
const mountedServers = servers.map((server) => server.name);
|
|
17470
17719
|
const clientOptions = {
|
|
17471
17720
|
agentCommand: spawnCommand.command,
|
|
@@ -17657,7 +17906,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
17657
17906
|
const buildPrompt = () => [
|
|
17658
17907
|
this.turnInstructionPrefix,
|
|
17659
17908
|
WarmTranscript.render(this.warmTranscript.select(this.sessionId, transcriptRows), "Room conversation so far:", "New in the Room since your last turn (the earlier conversation is already in this session):"),
|
|
17660
|
-
`Newest message from ${
|
|
17909
|
+
`Newest message from ${inboxItemAuthorName(item, this.agent.publicKey, names)}:`,
|
|
17661
17910
|
roomMessagePrompt("", inboxItemPromptBody(item, this.agent.publicKey), item.attachments, delivered, this.acceptsImages()),
|
|
17662
17911
|
grantDecision ? [
|
|
17663
17912
|
"This is the answer to your grant request; your paused work resumes now.",
|
|
@@ -17819,7 +18068,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
17819
18068
|
for (const item of inbox.items) {
|
|
17820
18069
|
if (!inboxItemTriggersTurn(item, this.agent.publicKey))
|
|
17821
18070
|
continue;
|
|
17822
|
-
if (!
|
|
18071
|
+
if (!inboxItemSkipsSenderPolicy(item, this.agent.publicKey)) {
|
|
17823
18072
|
const authority = await api.execute("getRoomAuthority", {
|
|
17824
18073
|
roomId,
|
|
17825
18074
|
principalId: item.authorId
|
|
@@ -18481,13 +18730,13 @@ var RoomRuntimeCoordinator = class {
|
|
|
18481
18730
|
return this.runtime.rooms.find((room) => room.channelId === roomId);
|
|
18482
18731
|
}
|
|
18483
18732
|
roomRoot(roomId) {
|
|
18484
|
-
return this.roomRecord(roomId)?.root ??
|
|
18733
|
+
return this.roomRecord(roomId)?.root ?? resolve18(dirname6(this.configPath), "rooms", roomId);
|
|
18485
18734
|
}
|
|
18486
18735
|
roomAgentHomeRoot(workspaceRoot, required = false) {
|
|
18487
18736
|
const flag = process.env.BUZZY_BODY_ROOM_HOME;
|
|
18488
18737
|
if (!required && flag === "0")
|
|
18489
18738
|
return void 0;
|
|
18490
|
-
const home =
|
|
18739
|
+
const home = resolve18(workspaceRoot, "agent-home");
|
|
18491
18740
|
if (!required && flag !== "1" && !existsSync4(home) && existsSync4(workspaceRoot))
|
|
18492
18741
|
return void 0;
|
|
18493
18742
|
try {
|
|
@@ -18504,8 +18753,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
18504
18753
|
return {
|
|
18505
18754
|
...this.baseConfig,
|
|
18506
18755
|
workspaceRoot,
|
|
18507
|
-
agentPrivateRoot:
|
|
18508
|
-
agentMemoryRoot:
|
|
18756
|
+
agentPrivateRoot: resolve18(workspaceRoot, "agent-private"),
|
|
18757
|
+
agentMemoryRoot: resolve18(dirname6(this.configPath), "memory"),
|
|
18509
18758
|
openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname6(this.configPath)),
|
|
18510
18759
|
turnTraceDir: turnTraceDirectory(dirname6(this.configPath)),
|
|
18511
18760
|
...agentHomeRoot ? { agentHomeRoot } : {}
|
|
@@ -18574,11 +18823,11 @@ var RoomRuntimeCoordinator = class {
|
|
|
18574
18823
|
const remote = roomCheckoutRemote(repository.remote);
|
|
18575
18824
|
const targetBranch = repository.targetBranch || "main";
|
|
18576
18825
|
const checkoutId = createHash4("sha256").update(`${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
|
|
18577
|
-
const path =
|
|
18578
|
-
await
|
|
18826
|
+
const path = resolve18(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
|
|
18827
|
+
await mkdir10(dirname6(path), { recursive: true, mode: 448 });
|
|
18579
18828
|
const token = remote.startsWith("https://github.com/") ? await this.options.daemonApi.execute("getRoomGitHubToken", { roomId }) : void 0;
|
|
18580
18829
|
const env = token ? githubGitEnv(token.token) : process.env;
|
|
18581
|
-
if (!existsSync4(
|
|
18830
|
+
if (!existsSync4(resolve18(path, ".git"))) {
|
|
18582
18831
|
await execFileAsync3("git", ["clone", "--no-checkout", remote, path], {
|
|
18583
18832
|
env,
|
|
18584
18833
|
maxBuffer: 4 * 1024 * 1024
|
|
@@ -18703,12 +18952,12 @@ var RoomRuntimeCoordinator = class {
|
|
|
18703
18952
|
async materializeCornerWorktree(input) {
|
|
18704
18953
|
const remote = githubHttpsRemote(input.remote);
|
|
18705
18954
|
const repositoryHash = createHash4("sha256").update(remote).digest("hex").slice(0, 24);
|
|
18706
|
-
const gitCommonDir =
|
|
18707
|
-
const path =
|
|
18708
|
-
await
|
|
18709
|
-
await
|
|
18955
|
+
const gitCommonDir = resolve18(this.runtime.supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
|
|
18956
|
+
const path = resolve18(this.runtime.supervisorRoot, "beeline", "corners", input.cornerId);
|
|
18957
|
+
await mkdir10(dirname6(gitCommonDir), { recursive: true, mode: 448 });
|
|
18958
|
+
await mkdir10(dirname6(path), { recursive: true, mode: 448 });
|
|
18710
18959
|
const authEnv = githubGitEnv(input.token);
|
|
18711
|
-
if (!existsSync4(
|
|
18960
|
+
if (!existsSync4(resolve18(gitCommonDir, "HEAD"))) {
|
|
18712
18961
|
await execFileAsync3("git", ["clone", "--bare", remote, gitCommonDir], {
|
|
18713
18962
|
env: authEnv,
|
|
18714
18963
|
maxBuffer: 4 * 1024 * 1024
|
|
@@ -18721,7 +18970,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
18721
18970
|
"origin",
|
|
18722
18971
|
`+refs/heads/${input.targetBranch}:refs/remotes/origin/${input.targetBranch}`
|
|
18723
18972
|
], { env: authEnv, maxBuffer: 4 * 1024 * 1024 });
|
|
18724
|
-
if (!existsSync4(
|
|
18973
|
+
if (!existsSync4(resolve18(path, ".git"))) {
|
|
18725
18974
|
await rm4(path, { recursive: true, force: true });
|
|
18726
18975
|
await execFileAsync3("git", [
|
|
18727
18976
|
`--git-dir=${gitCommonDir}`,
|
|
@@ -18758,7 +19007,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
18758
19007
|
`${this.agent.publicKey.slice(0, 16)}@users.noreply.github.com`
|
|
18759
19008
|
]);
|
|
18760
19009
|
const top = await execFileAsync3("git", ["-C", path, "rev-parse", "--show-toplevel"]);
|
|
18761
|
-
if (
|
|
19010
|
+
if (resolve18(top.stdout.trim()) !== resolve18(path)) {
|
|
18762
19011
|
throw new Error(`corner worktree escaped its isolated root: ${top.stdout.trim()}`);
|
|
18763
19012
|
}
|
|
18764
19013
|
return { path, gitCommonDir };
|
|
@@ -18936,9 +19185,9 @@ var ThinDaemonCore = class {
|
|
|
18936
19185
|
|
|
18937
19186
|
// apps/body/dist/systemd.js
|
|
18938
19187
|
import { execFile as execFile5 } from "node:child_process";
|
|
18939
|
-
import { mkdir as
|
|
19188
|
+
import { mkdir as mkdir11, readFile as readFile8, writeFile as writeFile7 } from "node:fs/promises";
|
|
18940
19189
|
import { homedir as homedir8 } from "node:os";
|
|
18941
|
-
import { dirname as dirname7, resolve as
|
|
19190
|
+
import { dirname as dirname7, resolve as resolve19 } from "node:path";
|
|
18942
19191
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
18943
19192
|
import { promisify as promisify4 } from "node:util";
|
|
18944
19193
|
var execFileAsync4 = promisify4(execFile5);
|
|
@@ -18980,9 +19229,9 @@ WantedBy=default.target
|
|
|
18980
19229
|
}
|
|
18981
19230
|
function isCanonicalInstalledLauncher(env = process.env, invocationPath = process.argv[1]) {
|
|
18982
19231
|
const home = env.HOME?.trim() || homedir8();
|
|
18983
|
-
const expectedLibDir =
|
|
19232
|
+
const expectedLibDir = resolve19(home, ".local", "lib", "beeline");
|
|
18984
19233
|
const expectedPrefix = `${expectedLibDir}/`;
|
|
18985
|
-
return
|
|
19234
|
+
return resolve19(env.BEELINE_LIB_DIR?.trim() || "/") === expectedLibDir && Boolean(invocationPath) && resolve19(invocationPath).startsWith(expectedPrefix);
|
|
18986
19235
|
}
|
|
18987
19236
|
function assertCanonicalInstalledLauncher(env, invocationPath) {
|
|
18988
19237
|
if (isCanonicalInstalledLauncher(env, invocationPath))
|
|
@@ -18990,8 +19239,8 @@ function assertCanonicalInstalledLauncher(env, invocationPath) {
|
|
|
18990
19239
|
throw new Error("refusing to modify the shared Beeline systemd unit outside the canonical ~/.local/bin/beeline launcher");
|
|
18991
19240
|
}
|
|
18992
19241
|
function systemdUserUnitPath(env = process.env) {
|
|
18993
|
-
const configRoot = env.XDG_CONFIG_HOME?.trim() ||
|
|
18994
|
-
return
|
|
19242
|
+
const configRoot = env.XDG_CONFIG_HOME?.trim() || resolve19(homedir8(), ".config");
|
|
19243
|
+
return resolve19(configRoot, "systemd", "user", SYSTEMD_UNIT_NAME);
|
|
18995
19244
|
}
|
|
18996
19245
|
var runSystemctl = async (args) => {
|
|
18997
19246
|
const result = await execFileAsync4("systemctl", ["--user", ...args], {
|
|
@@ -19009,7 +19258,7 @@ async function installAgentService(publicKey, options = {}) {
|
|
|
19009
19258
|
const content = agentServiceUnit();
|
|
19010
19259
|
const existing = await readFile8(path, "utf8").catch(() => "");
|
|
19011
19260
|
if (existing !== content) {
|
|
19012
|
-
await
|
|
19261
|
+
await mkdir11(dirname7(path), { recursive: true, mode: 448 });
|
|
19013
19262
|
await writeFile7(path, content, { mode: 384 });
|
|
19014
19263
|
}
|
|
19015
19264
|
const run2 = options.run ?? runSystemctl;
|
|
@@ -19182,8 +19431,8 @@ async function runStartCommand(args, interactiveUi) {
|
|
|
19182
19431
|
// apps/body/dist/connect-command.js
|
|
19183
19432
|
import { spawn as spawn5 } from "node:child_process";
|
|
19184
19433
|
import { createHash as createHash6 } from "node:crypto";
|
|
19185
|
-
import { chmod as chmod4, mkdir as
|
|
19186
|
-
import { dirname as dirname10, resolve as
|
|
19434
|
+
import { chmod as chmod4, mkdir as mkdir13, readFile as readFile10, unlink as unlink2, writeFile as writeFile9 } from "node:fs/promises";
|
|
19435
|
+
import { dirname as dirname10, resolve as resolve21 } from "node:path";
|
|
19187
19436
|
import { stdin as stdin3, stdout as stdout4 } from "node:process";
|
|
19188
19437
|
|
|
19189
19438
|
// packages/api-contract/dist/agent-pairing-code.js
|
|
@@ -19476,6 +19725,7 @@ async function pairDevice(grant, options = {}) {
|
|
|
19476
19725
|
agentCommand: selectedAgent.command,
|
|
19477
19726
|
agentArgs: selectedAgent.args,
|
|
19478
19727
|
modelSelection: { model: grant.model },
|
|
19728
|
+
...grant.accessPolicy ? { accessPolicy: grant.accessPolicy } : {},
|
|
19479
19729
|
mcpBinary: localConfig.mcpBinary,
|
|
19480
19730
|
agentIdentity,
|
|
19481
19731
|
bodyIdentity: identityFromKey(grant.bodySecretKey, DEFAULT_BODY_IDENTITY_NAME2),
|
|
@@ -19760,6 +20010,11 @@ async function jsonRequest(url, body, fetchImpl) {
|
|
|
19760
20010
|
}
|
|
19761
20011
|
return response.json();
|
|
19762
20012
|
}
|
|
20013
|
+
function parseConnectSubscriptions(value) {
|
|
20014
|
+
return [
|
|
20015
|
+
...new Set((value ?? "").split(",").map((entry) => entry.trim().toLowerCase()).filter(Boolean))
|
|
20016
|
+
];
|
|
20017
|
+
}
|
|
19763
20018
|
function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl) {
|
|
19764
20019
|
const normalizedPairingCode = normalizeAgentPairingCode(pairingCode);
|
|
19765
20020
|
if (!normalizedPairingCode)
|
|
@@ -19770,7 +20025,11 @@ function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl) {
|
|
|
19770
20025
|
harness: selection.harness,
|
|
19771
20026
|
...selection.provider ? { provider: selection.provider } : {},
|
|
19772
20027
|
model: selection.model,
|
|
19773
|
-
avatar_seed: avatarSeed
|
|
20028
|
+
avatar_seed: avatarSeed,
|
|
20029
|
+
// This wizard always finishes the join itself (`finishConnectedAgentPairing`,
|
|
20030
|
+
// called once the rename prompt below settles), so the claim must not
|
|
20031
|
+
// join Rooms or announce yet.
|
|
20032
|
+
defer_join: true
|
|
19774
20033
|
}, fetchImpl);
|
|
19775
20034
|
}
|
|
19776
20035
|
async function renameConnectedAgent(baseUrl, pairingCode, name, fetchImpl) {
|
|
@@ -19780,6 +20039,16 @@ async function renameConnectedAgent(baseUrl, pairingCode, name, fetchImpl) {
|
|
|
19780
20039
|
const renamed = await jsonRequest(`${baseUrl}/auth/agent/connect/name`, { pairing_code: normalizedPairingCode, agent_name: name.trim().replace(/\s+/g, " ") }, fetchImpl);
|
|
19781
20040
|
return renamed.agent_name;
|
|
19782
20041
|
}
|
|
20042
|
+
async function finishConnectedAgentPairing(baseUrl, pairingCode, workspaceJoined, eventSubscriptions, fetchImpl) {
|
|
20043
|
+
const normalizedPairingCode = normalizeAgentPairingCode(pairingCode);
|
|
20044
|
+
if (!normalizedPairingCode)
|
|
20045
|
+
throw new Error("invalid pairing code");
|
|
20046
|
+
await jsonRequest(`${baseUrl}/auth/agent/connect/finish`, {
|
|
20047
|
+
pairing_code: normalizedPairingCode,
|
|
20048
|
+
workspace_joined: workspaceJoined,
|
|
20049
|
+
...eventSubscriptions.length ? { event_subscriptions: [...eventSubscriptions] } : {}
|
|
20050
|
+
}, fetchImpl);
|
|
20051
|
+
}
|
|
19783
20052
|
function seededIdentityLine(grant) {
|
|
19784
20053
|
return grant.agent_face ? `${grant.agent_name} the ${grant.agent_face}` : grant.agent_name;
|
|
19785
20054
|
}
|
|
@@ -19797,7 +20066,7 @@ async function installCurrentRelease(fetchImpl) {
|
|
|
19797
20066
|
});
|
|
19798
20067
|
await activateRelease(layout, releaseId);
|
|
19799
20068
|
return {
|
|
19800
|
-
binary:
|
|
20069
|
+
binary: resolve21(layout.binDir, "beeline"),
|
|
19801
20070
|
version: published.version ?? releaseId
|
|
19802
20071
|
};
|
|
19803
20072
|
}
|
|
@@ -19820,7 +20089,7 @@ function providerEnvironment(selection) {
|
|
|
19820
20089
|
};
|
|
19821
20090
|
}
|
|
19822
20091
|
async function writePrivateJson(path, value) {
|
|
19823
|
-
await
|
|
20092
|
+
await mkdir13(dirname10(path), { recursive: true, mode: 448 });
|
|
19824
20093
|
await writeFile9(path, `${JSON.stringify(value, null, 2)}
|
|
19825
20094
|
`, { mode: 384 });
|
|
19826
20095
|
await chmod4(path, 384);
|
|
@@ -19829,8 +20098,8 @@ async function writeProviderEnv(selection, agentPubkey) {
|
|
|
19829
20098
|
const values = providerEnvironment(selection);
|
|
19830
20099
|
if (Object.keys(values).length === 0)
|
|
19831
20100
|
return void 0;
|
|
19832
|
-
const path =
|
|
19833
|
-
await
|
|
20101
|
+
const path = resolve21(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
|
|
20102
|
+
await mkdir13(dirname10(path), { recursive: true, mode: 448 });
|
|
19834
20103
|
const contents = Object.entries(values).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n");
|
|
19835
20104
|
await writeFile9(path, `${contents}
|
|
19836
20105
|
`, { mode: 384 });
|
|
@@ -19877,12 +20146,12 @@ async function runConnectCommand(code, options = {}) {
|
|
|
19877
20146
|
}
|
|
19878
20147
|
const restoreRails = paintWizardBrass();
|
|
19879
20148
|
try {
|
|
19880
|
-
await runConnectWizard(code, options.fetchImpl ?? fetch);
|
|
20149
|
+
await runConnectWizard(code, options.fetchImpl ?? fetch, options.subscribe ?? [], options.accessPolicy);
|
|
19881
20150
|
} finally {
|
|
19882
20151
|
restoreRails();
|
|
19883
20152
|
}
|
|
19884
20153
|
}
|
|
19885
|
-
async function runConnectWizard(code, fetchImpl) {
|
|
20154
|
+
async function runConnectWizard(code, fetchImpl, eventSubscriptions, accessPolicy) {
|
|
19886
20155
|
intro(brass("Beeline connect"));
|
|
19887
20156
|
const pairingCode = code?.trim() || await clackPrompts.text({
|
|
19888
20157
|
message: brass("Pairing code from the app"),
|
|
@@ -19892,9 +20161,10 @@ async function runConnectWizard(code, fetchImpl) {
|
|
|
19892
20161
|
const baseUrl = (process.env.BEELINE_AUTH_URL ?? "https://server.usebeeline.app").replace(/\/$/, "");
|
|
19893
20162
|
const claimed = await brassSpinner("Connecting to your Beeline Workspace\u2026", () => requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl), (connectedGrant) => `Connected to ${connectedGrant.workspace_name}`);
|
|
19894
20163
|
const grant = { ...claimed, agent_name: await confirmSeededName(baseUrl, pairingCode, claimed, fetchImpl) };
|
|
20164
|
+
await finishConnectedAgentPairing(baseUrl, pairingCode, grant.workspace_joined, eventSubscriptions, fetchImpl);
|
|
19895
20165
|
const installedRelease = await brassSpinner("Installing the Beeline daemon\u2026", () => installCurrentRelease(fetchImpl), (release) => `Installed Beeline helper ${release.version}`);
|
|
19896
20166
|
const llmEnvFile = await writeProviderEnv(selection, grant.agent_pubkey);
|
|
19897
|
-
const grantPath =
|
|
20167
|
+
const grantPath = resolve21(defaultSupervisorRoot(process.env), "beeline", "connect", `grant-${process.pid}-${Date.now()}.json`);
|
|
19898
20168
|
await writePrivateJson(grantPath, {
|
|
19899
20169
|
agentSecretKey: grant.agent_secret_key,
|
|
19900
20170
|
bodySecretKey: grant.body_secret_key,
|
|
@@ -19907,7 +20177,8 @@ async function runConnectWizard(code, fetchImpl) {
|
|
|
19907
20177
|
pairedBy: grant.paired_by,
|
|
19908
20178
|
monolithBaseUrl: baseUrl,
|
|
19909
20179
|
daemonExchangeToken: grant.daemon_exchange_token,
|
|
19910
|
-
...llmEnvFile ? { llmEnvFile } : {}
|
|
20180
|
+
...llmEnvFile ? { llmEnvFile } : {},
|
|
20181
|
+
...accessPolicy ? { accessPolicy } : {}
|
|
19911
20182
|
});
|
|
19912
20183
|
await brassSpinner("Starting your agent\u2026", () => runInstalledFinish(installedRelease.binary, grantPath), () => `Started ${grant.agent_name}`);
|
|
19913
20184
|
console.log("");
|
|
@@ -19947,6 +20218,8 @@ function isDevicePairingGrant(value) {
|
|
|
19947
20218
|
if (!value || typeof value !== "object")
|
|
19948
20219
|
return false;
|
|
19949
20220
|
const grant = value;
|
|
20221
|
+
if (grant.accessPolicy !== void 0 && !isAgentAccessPolicy(grant.accessPolicy))
|
|
20222
|
+
return false;
|
|
19950
20223
|
let monolithOrigin = "";
|
|
19951
20224
|
try {
|
|
19952
20225
|
monolithOrigin = new URL(grant.monolithBaseUrl ?? "").origin;
|
|
@@ -19973,11 +20246,11 @@ async function runConnectFinishCommand(path) {
|
|
|
19973
20246
|
throw new Error("connect-finish may run only from the canonical installed Beeline launcher");
|
|
19974
20247
|
}
|
|
19975
20248
|
try {
|
|
19976
|
-
const grant = JSON.parse(await readFile10(
|
|
20249
|
+
const grant = JSON.parse(await readFile10(resolve21(path), "utf8"));
|
|
19977
20250
|
if (!isDevicePairingGrant(grant))
|
|
19978
20251
|
throw new Error("device connection grant is invalid");
|
|
19979
20252
|
const connected = await completeDevicePairing(grant);
|
|
19980
|
-
await unlink2(
|
|
20253
|
+
await unlink2(resolve21(path));
|
|
19981
20254
|
const providerEnv = grant.llmEnvFile ? await readFile10(grant.llmEnvFile, "utf8").catch(() => "") : "";
|
|
19982
20255
|
const apiKey = (/^OPENROUTER_API_KEY=(\S+)/m.exec(providerEnv)?.[1] ?? "").replace(/^["']|["']$/g, "");
|
|
19983
20256
|
const model = openRouterModelId(grant.model, { OPENROUTER_API_KEY: apiKey });
|
|
@@ -20006,19 +20279,19 @@ init_self_update_manifest();
|
|
|
20006
20279
|
// apps/body/dist/managed-update.js
|
|
20007
20280
|
init_self_update();
|
|
20008
20281
|
import { spawn as spawn6 } from "node:child_process";
|
|
20009
|
-
import { mkdir as
|
|
20010
|
-
import { dirname as dirname12, resolve as
|
|
20282
|
+
import { mkdir as mkdir15, rm as rm6, stat as stat2, writeFile as writeFile11 } from "node:fs/promises";
|
|
20283
|
+
import { dirname as dirname12, resolve as resolve23 } from "node:path";
|
|
20011
20284
|
|
|
20012
20285
|
// apps/body/dist/update-rollback-alert.js
|
|
20013
|
-
import { mkdir as
|
|
20014
|
-
import { dirname as dirname11, resolve as
|
|
20286
|
+
import { mkdir as mkdir14, readFile as readFile11, rename as rename4, writeFile as writeFile10 } from "node:fs/promises";
|
|
20287
|
+
import { dirname as dirname11, resolve as resolve22 } from "node:path";
|
|
20015
20288
|
function updateRollbackAlertPath(runtimeDir) {
|
|
20016
|
-
return
|
|
20289
|
+
return resolve22(runtimeDir, "update-rollback-alert.json");
|
|
20017
20290
|
}
|
|
20018
20291
|
async function writeAlert(runtimeDir, alert) {
|
|
20019
20292
|
const path = updateRollbackAlertPath(runtimeDir);
|
|
20020
20293
|
const staged = `${path}.${process.pid}.tmp`;
|
|
20021
|
-
await
|
|
20294
|
+
await mkdir14(dirname11(path), { recursive: true });
|
|
20022
20295
|
await writeFile10(staged, `${JSON.stringify(alert, null, 2)}
|
|
20023
20296
|
`, { mode: 384 });
|
|
20024
20297
|
await rename4(staged, path);
|
|
@@ -20056,13 +20329,13 @@ var LOCK_STALE_MS = UPDATE_WORKER_DEADLINE_MS + 5 * 6e4;
|
|
|
20056
20329
|
var DEFAULT_UPDATE_INITIAL_DELAY_MS = 0;
|
|
20057
20330
|
async function withInstallLock(layout, work, options = {}) {
|
|
20058
20331
|
const now2 = options.now ?? Date.now;
|
|
20059
|
-
const lock =
|
|
20332
|
+
const lock = resolve23(layout.releasesRoot, ".state", "install.lock");
|
|
20060
20333
|
const deadline = now2() + (options.waitMs ?? 1e4);
|
|
20061
|
-
await
|
|
20334
|
+
await mkdir15(dirname12(lock), { recursive: true });
|
|
20062
20335
|
for (; ; ) {
|
|
20063
20336
|
try {
|
|
20064
|
-
await
|
|
20065
|
-
await writeFile11(
|
|
20337
|
+
await mkdir15(lock);
|
|
20338
|
+
await writeFile11(resolve23(lock, "owner"), `${process.pid}
|
|
20066
20339
|
${now2()}
|
|
20067
20340
|
`, "utf8");
|
|
20068
20341
|
break;
|
|
@@ -20185,7 +20458,7 @@ var ManagedUpdateHandoff = class _ManagedUpdateHandoff {
|
|
|
20185
20458
|
if (!attempt || attempt.releaseId !== desiredRelease || attempt.status !== "pending") {
|
|
20186
20459
|
const from = await readInstalledBundleIdentity({
|
|
20187
20460
|
...this.#layout,
|
|
20188
|
-
libDir:
|
|
20461
|
+
libDir: resolve23(this.#layout.releasesRoot, this.#loadedRelease)
|
|
20189
20462
|
}).catch(() => void 0) ?? {};
|
|
20190
20463
|
const to = await readInstalledBundleIdentity(this.#layout).catch(() => void 0) ?? {};
|
|
20191
20464
|
const record2 = {
|
|
@@ -20472,7 +20745,7 @@ async function proveLoadedReleaseReady(layout, runtimeDir, loadedRelease, option
|
|
|
20472
20745
|
});
|
|
20473
20746
|
if (!accepted)
|
|
20474
20747
|
return false;
|
|
20475
|
-
await writeFile11(
|
|
20748
|
+
await writeFile11(resolve23(runtimeDir, "daemon-ready.json"), `${JSON.stringify({
|
|
20476
20749
|
readyAt: (options.now ?? Date.now)(),
|
|
20477
20750
|
loadedRelease,
|
|
20478
20751
|
functionalProof: options.functionalProof
|
|
@@ -20677,12 +20950,12 @@ async function runUpdateCommand(args) {
|
|
|
20677
20950
|
init_self_update();
|
|
20678
20951
|
|
|
20679
20952
|
// apps/body/dist/daemon-failure.js
|
|
20680
|
-
import { mkdir as
|
|
20681
|
-
import { dirname as dirname13, resolve as
|
|
20953
|
+
import { mkdir as mkdir16, readFile as readFile12, rename as rename5, rm as rm7, writeFile as writeFile12 } from "node:fs/promises";
|
|
20954
|
+
import { dirname as dirname13, resolve as resolve24 } from "node:path";
|
|
20682
20955
|
var DAEMON_FAILURE_LIMIT = 3;
|
|
20683
20956
|
var DAEMON_FAILURE_WINDOW_MS = 5 * 6e4;
|
|
20684
20957
|
function daemonFailurePath(runtimeDir) {
|
|
20685
|
-
return
|
|
20958
|
+
return resolve24(runtimeDir, "daemon-distress.json");
|
|
20686
20959
|
}
|
|
20687
20960
|
async function readFailureRecord(runtimeDir) {
|
|
20688
20961
|
try {
|
|
@@ -20698,7 +20971,7 @@ async function readFailureRecord(runtimeDir) {
|
|
|
20698
20971
|
async function writeFailureRecord(runtimeDir, record2) {
|
|
20699
20972
|
const path = daemonFailurePath(runtimeDir);
|
|
20700
20973
|
const staged = `${path}.${process.pid}.tmp`;
|
|
20701
|
-
await
|
|
20974
|
+
await mkdir16(dirname13(path), { recursive: true, mode: 448 });
|
|
20702
20975
|
await writeFile12(staged, `${JSON.stringify(record2, null, 2)}
|
|
20703
20976
|
`, { mode: 384 });
|
|
20704
20977
|
await rename5(staged, path);
|
|
@@ -20721,9 +20994,9 @@ async function clearDaemonStartFailures(runtimeDir) {
|
|
|
20721
20994
|
}
|
|
20722
20995
|
|
|
20723
20996
|
// apps/body/dist/update-functional-probe.js
|
|
20724
|
-
import { mkdir as
|
|
20997
|
+
import { mkdir as mkdir17, rm as rm8 } from "node:fs/promises";
|
|
20725
20998
|
import { homedir as homedir10 } from "node:os";
|
|
20726
|
-
import { resolve as
|
|
20999
|
+
import { resolve as resolve25 } from "node:path";
|
|
20727
21000
|
var UPDATE_PROBE_SESSION_TIMEOUT_MS = 1e4;
|
|
20728
21001
|
var UPDATE_PROBE_SESSION_OPEN_TIMEOUT_MS = 2e4;
|
|
20729
21002
|
var UPDATE_PROBE_TURN_TIMEOUT_MS = 45e3;
|
|
@@ -20769,11 +21042,11 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
20769
21042
|
if (input.sandboxRequired && !input.config.bwrapPath) {
|
|
20770
21043
|
throw new UpdateFunctionalProbeError("sandbox-unavailable", "the configured bubblewrap boundary did not pass its startup self-test");
|
|
20771
21044
|
}
|
|
20772
|
-
const root = input.probeRoot ??
|
|
20773
|
-
const cwd =
|
|
20774
|
-
const homeRoot =
|
|
21045
|
+
const root = input.probeRoot ?? resolve25(input.runtimeDir, "update-functional-probe");
|
|
21046
|
+
const cwd = resolve25(root, "checkout");
|
|
21047
|
+
const homeRoot = resolve25(root, "agent-home");
|
|
20775
21048
|
await rm8(root, { recursive: true, force: true });
|
|
20776
|
-
await
|
|
21049
|
+
await mkdir17(cwd, { recursive: true, mode: 448 });
|
|
20777
21050
|
let client;
|
|
20778
21051
|
try {
|
|
20779
21052
|
const agentEnv = {
|
|
@@ -20802,7 +21075,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
20802
21075
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
20803
21076
|
const operatorHome = input.config.operatorHome ?? homedir10();
|
|
20804
21077
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
20805
|
-
await Promise.all(homeStateDirs.map((dir) =>
|
|
21078
|
+
await Promise.all(homeStateDirs.map((dir) => mkdir17(dir, { recursive: true })));
|
|
20806
21079
|
spawnCommand = wrapAgentCommand({
|
|
20807
21080
|
bwrapPath: input.config.bwrapPath,
|
|
20808
21081
|
spec: {
|
|
@@ -20938,7 +21211,7 @@ async function probeReleaseInSubprocess(input) {
|
|
|
20938
21211
|
return { kind: "unavailable", reason: `release ${input.releaseId} has no runnable CLI entrypoint` };
|
|
20939
21212
|
}
|
|
20940
21213
|
const timeoutMs = input.timeoutMs ?? CURRENT_RELEASE_PROBE_TIMEOUT_MS;
|
|
20941
|
-
return new Promise((
|
|
21214
|
+
return new Promise((resolve28) => {
|
|
20942
21215
|
const child = spawn7(input.execPath ?? process.execPath, [entrypoint, UPDATE_PROBE_COMMAND, "--config", input.runtimeConfigPath], { env: input.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] });
|
|
20943
21216
|
let stdout6 = "";
|
|
20944
21217
|
let stderr = "";
|
|
@@ -20948,7 +21221,7 @@ async function probeReleaseInSubprocess(input) {
|
|
|
20948
21221
|
return;
|
|
20949
21222
|
settled = true;
|
|
20950
21223
|
clearTimeout(timer);
|
|
20951
|
-
|
|
21224
|
+
resolve28(outcome);
|
|
20952
21225
|
};
|
|
20953
21226
|
const timer = setTimeout(() => {
|
|
20954
21227
|
child.kill("SIGKILL");
|
|
@@ -21028,7 +21301,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
21028
21301
|
|
|
21029
21302
|
// apps/body/dist/release-status.js
|
|
21030
21303
|
import { readFile as readFile13, readdir as readdir5, rename as rename6, writeFile as writeFile13 } from "node:fs/promises";
|
|
21031
|
-
import { resolve as
|
|
21304
|
+
import { resolve as resolve26 } from "node:path";
|
|
21032
21305
|
var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
|
|
21033
21306
|
var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
|
|
21034
21307
|
var SOURCE_SHA = /^[0-9a-f]{7,64}$/;
|
|
@@ -21045,7 +21318,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
|
|
|
21045
21318
|
pid: options.pid ?? process.pid,
|
|
21046
21319
|
readyAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString()
|
|
21047
21320
|
};
|
|
21048
|
-
const target =
|
|
21321
|
+
const target = resolve26(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
|
|
21049
21322
|
const temporary = `${target}.${status.pid}.tmp`;
|
|
21050
21323
|
await writeFile13(temporary, `${JSON.stringify(status, null, 2)}
|
|
21051
21324
|
`, { mode: 384 });
|
|
@@ -21059,7 +21332,12 @@ function usage(exitCode = 1) {
|
|
|
21059
21332
|
${import_picocolors3.default.bold("Beeline \u2014 thin Room agent.")}
|
|
21060
21333
|
|
|
21061
21334
|
${import_picocolors3.default.dim("Usage:")}
|
|
21062
|
-
beeline connect [XXXXXXXX-XXXXXXXX]
|
|
21335
|
+
beeline connect [XXXXXXXX-XXXXXXXX] [--subscribe <kinds>] [--access <policy>]
|
|
21336
|
+
Install and connect an app-authorized agent;
|
|
21337
|
+
--subscribe takes a comma-separated list of
|
|
21338
|
+
event kinds it reacts to (e.g. joined);
|
|
21339
|
+
--access is everyone|creator|allowlist
|
|
21340
|
+
(default creator)
|
|
21063
21341
|
beeline start [agent-pubkey] Start \u2014 or RESTART when already running,
|
|
21064
21342
|
stopping cleanly after in-flight work \u2014
|
|
21065
21343
|
this repo's (or, outside a repo, this
|
|
@@ -21100,7 +21378,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
21100
21378
|
runtime = activated.runtime;
|
|
21101
21379
|
const daemonApi = activated.client;
|
|
21102
21380
|
const agent = runtimeAgentCommand(runtime);
|
|
21103
|
-
await writeFile14(
|
|
21381
|
+
await writeFile14(resolve27(dirname15(configPath), "daemon.pid"), `${process.pid}
|
|
21104
21382
|
`, { mode: 384 });
|
|
21105
21383
|
const env = {
|
|
21106
21384
|
...process.env,
|
|
@@ -21108,7 +21386,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
21108
21386
|
BUZZ_DEV_MCP_BIN: runtime.mcpBinary
|
|
21109
21387
|
};
|
|
21110
21388
|
const config = loadBodyConfig({
|
|
21111
|
-
workspaceRoot:
|
|
21389
|
+
workspaceRoot: resolve27(dirname15(configPath), "workspace"),
|
|
21112
21390
|
llmEnvFile: runtime.llmEnvFile,
|
|
21113
21391
|
env,
|
|
21114
21392
|
agent
|
|
@@ -21278,7 +21556,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
21278
21556
|
throw error;
|
|
21279
21557
|
} finally {
|
|
21280
21558
|
await notifier.stopping(stoppingStatus).catch(() => void 0);
|
|
21281
|
-
const pidPath =
|
|
21559
|
+
const pidPath = resolve27(dirname15(configPath), "daemon.pid");
|
|
21282
21560
|
const recorded = Number((await readFile14(pidPath, "utf8").catch(() => "")).trim());
|
|
21283
21561
|
if (recorded === process.pid) {
|
|
21284
21562
|
await unlink3(pidPath).catch(() => void 0);
|
|
@@ -21300,7 +21578,18 @@ async function main() {
|
|
|
21300
21578
|
return;
|
|
21301
21579
|
}
|
|
21302
21580
|
if (command === "connect") {
|
|
21303
|
-
|
|
21581
|
+
const subscribeFlag = args.indexOf("--subscribe");
|
|
21582
|
+
const subscribe = subscribeFlag >= 0 ? parseConnectSubscriptions(args[subscribeFlag + 1]) : [];
|
|
21583
|
+
const accessFlag = args.indexOf("--access");
|
|
21584
|
+
const accessPolicy = accessFlag >= 0 ? args[accessFlag + 1] : void 0;
|
|
21585
|
+
if (accessFlag >= 0 && !isAgentAccessPolicy(accessPolicy)) {
|
|
21586
|
+
throw new Error(`--access must be one of ${AGENT_ACCESS_POLICIES.join(", ")}`);
|
|
21587
|
+
}
|
|
21588
|
+
const code = args[1] && !args[1].startsWith("--") ? args[1] : void 0;
|
|
21589
|
+
await runConnectCommand(code, {
|
|
21590
|
+
...subscribe.length ? { subscribe } : {},
|
|
21591
|
+
...isAgentAccessPolicy(accessPolicy) ? { accessPolicy } : {}
|
|
21592
|
+
});
|
|
21304
21593
|
return;
|
|
21305
21594
|
}
|
|
21306
21595
|
if (command === "connect-finish") {
|
|
@@ -21342,7 +21631,7 @@ async function main() {
|
|
|
21342
21631
|
}
|
|
21343
21632
|
if (!configPath)
|
|
21344
21633
|
throw new Error("daemon requires --config <runtime.json> or --agent <pubkey>");
|
|
21345
|
-
await runStoredDaemon(
|
|
21634
|
+
await runStoredDaemon(resolve27(configPath));
|
|
21346
21635
|
return;
|
|
21347
21636
|
}
|
|
21348
21637
|
if (command === "update") {
|