usebeeline 0.0.0 → 0.0.1
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 +797 -253
- package/package.json +2 -2
package/dist/usebeeline.mjs
CHANGED
|
@@ -9515,9 +9515,9 @@ var require_permessage_deflate = __commonJS({
|
|
|
9515
9515
|
* @private
|
|
9516
9516
|
*/
|
|
9517
9517
|
_decompress(data, fin, callback) {
|
|
9518
|
-
const
|
|
9518
|
+
const endpoint2 = this._isServer ? "client" : "server";
|
|
9519
9519
|
if (!this._inflate) {
|
|
9520
|
-
const key = `${
|
|
9520
|
+
const key = `${endpoint2}_max_window_bits`;
|
|
9521
9521
|
const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
|
|
9522
9522
|
this._inflate = zlib.createInflateRaw({
|
|
9523
9523
|
...this._options.zlibInflateOptions,
|
|
@@ -9550,7 +9550,7 @@ var require_permessage_deflate = __commonJS({
|
|
|
9550
9550
|
} else {
|
|
9551
9551
|
this._inflate[kTotalLength] = 0;
|
|
9552
9552
|
this._inflate[kBuffers] = [];
|
|
9553
|
-
if (fin && this.params[`${
|
|
9553
|
+
if (fin && this.params[`${endpoint2}_no_context_takeover`]) {
|
|
9554
9554
|
this._inflate.reset();
|
|
9555
9555
|
}
|
|
9556
9556
|
}
|
|
@@ -9566,9 +9566,9 @@ var require_permessage_deflate = __commonJS({
|
|
|
9566
9566
|
* @private
|
|
9567
9567
|
*/
|
|
9568
9568
|
_compress(data, fin, callback) {
|
|
9569
|
-
const
|
|
9569
|
+
const endpoint2 = this._isServer ? "server" : "client";
|
|
9570
9570
|
if (!this._deflate) {
|
|
9571
|
-
const key = `${
|
|
9571
|
+
const key = `${endpoint2}_max_window_bits`;
|
|
9572
9572
|
const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
|
|
9573
9573
|
this._deflate = zlib.createDeflateRaw({
|
|
9574
9574
|
...this._options.zlibDeflateOptions,
|
|
@@ -9594,7 +9594,7 @@ var require_permessage_deflate = __commonJS({
|
|
|
9594
9594
|
this._deflate[kCallback] = null;
|
|
9595
9595
|
this._deflate[kTotalLength] = 0;
|
|
9596
9596
|
this._deflate[kBuffers] = [];
|
|
9597
|
-
if (fin && this.params[`${
|
|
9597
|
+
if (fin && this.params[`${endpoint2}_no_context_takeover`]) {
|
|
9598
9598
|
this._deflate.reset();
|
|
9599
9599
|
}
|
|
9600
9600
|
callback(null, data2);
|
|
@@ -22145,9 +22145,9 @@ import { constants as fsConstants2 } from "node:fs";
|
|
|
22145
22145
|
import { access as access2, chmod as chmod6, lstat as lstat5, mkdir as mkdir17, open as open2, readFile as readFile12, rename as rename7, rm as rm9, symlink as symlink4, writeFile as writeFile11 } from "node:fs/promises";
|
|
22146
22146
|
import { spawn as spawn11 } from "node:child_process";
|
|
22147
22147
|
import { homedir as homedir10 } from "node:os";
|
|
22148
|
-
import { dirname as dirname15, join as join2, resolve as
|
|
22148
|
+
import { dirname as dirname15, join as join2, resolve as resolve36 } from "node:path";
|
|
22149
22149
|
function anchorLayout(rawLibDir) {
|
|
22150
|
-
const libDir =
|
|
22150
|
+
const libDir = resolve36(rawLibDir);
|
|
22151
22151
|
const segments = libDir.split(/[/\\]/);
|
|
22152
22152
|
const idx = segments.lastIndexOf(RELEASES_SEGMENT);
|
|
22153
22153
|
if (idx >= 2 && segments[idx - 1] === "lib") {
|
|
@@ -22163,9 +22163,9 @@ function anchorLayout(rawLibDir) {
|
|
|
22163
22163
|
// prefix's bin, NOT <prefix>/lib/bin — deriving it one level up was the
|
|
22164
22164
|
// defect that made activateRelease write its stable forwarders where
|
|
22165
22165
|
// nothing executed them, leaving stale raw wrappers in <prefix>/bin.
|
|
22166
|
-
binDir:
|
|
22166
|
+
binDir: resolve36(libDir, "../../bin"),
|
|
22167
22167
|
libDir,
|
|
22168
|
-
releasesRoot:
|
|
22168
|
+
releasesRoot: resolve36(libDir, `../${RELEASES_SEGMENT}`)
|
|
22169
22169
|
};
|
|
22170
22170
|
}
|
|
22171
22171
|
function beelineInstallLayout(env = process.env) {
|
|
@@ -22176,7 +22176,7 @@ function beelineInstallLayout(env = process.env) {
|
|
|
22176
22176
|
}
|
|
22177
22177
|
function defaultBeelineInstallLayout(env = process.env) {
|
|
22178
22178
|
const home = env.HOME?.trim() || homedir10();
|
|
22179
|
-
return anchorLayout(
|
|
22179
|
+
return anchorLayout(resolve36(home, ".local", "lib", "beeline"));
|
|
22180
22180
|
}
|
|
22181
22181
|
function hostPlatformKey() {
|
|
22182
22182
|
const os = process.platform === "linux" ? "linux" : process.platform === "darwin" ? "darwin" : "";
|
|
@@ -22781,7 +22781,7 @@ var init_self_update = __esm({
|
|
|
22781
22781
|
});
|
|
22782
22782
|
|
|
22783
22783
|
// apps/body/dist/cli.js
|
|
22784
|
-
import { dirname as dirname20, resolve as
|
|
22784
|
+
import { dirname as dirname20, resolve as resolve44 } from "node:path";
|
|
22785
22785
|
import { existsSync as existsSync16 } from "node:fs";
|
|
22786
22786
|
import { readdir as readdir9, readFile as readFile17, unlink as unlink6, writeFile as writeFile18 } from "node:fs/promises";
|
|
22787
22787
|
import { stdin as stdin5, stdout as stdout6 } from "node:process";
|
|
@@ -25576,14 +25576,14 @@ function isNonRetryableQueryError(error) {
|
|
|
25576
25576
|
return typeof error === "object" && error !== null && "nonRetryable" in error && error.nonRetryable === true;
|
|
25577
25577
|
}
|
|
25578
25578
|
function withQueryAttemptTimeout(operation, controller) {
|
|
25579
|
-
return new Promise((
|
|
25579
|
+
return new Promise((resolve45, reject) => {
|
|
25580
25580
|
const timer = setTimeout(() => {
|
|
25581
25581
|
controller.abort();
|
|
25582
25582
|
reject(new Error(`queryEvents timed out after ${QUERY_ATTEMPT_TIMEOUT_MS}ms`));
|
|
25583
25583
|
}, QUERY_ATTEMPT_TIMEOUT_MS);
|
|
25584
25584
|
operation.then((value) => {
|
|
25585
25585
|
clearTimeout(timer);
|
|
25586
|
-
|
|
25586
|
+
resolve45(value);
|
|
25587
25587
|
}, (error) => {
|
|
25588
25588
|
clearTimeout(timer);
|
|
25589
25589
|
reject(error);
|
|
@@ -25646,10 +25646,10 @@ async function flushQueryBatch(batchKey, batch) {
|
|
|
25646
25646
|
function enqueueQueryEvents(opts, filters, queryPubkey) {
|
|
25647
25647
|
const scope = `${queryCachePrefix(opts, queryPubkey)}${currentFetchId()}\0${opts.identity ? "auth" : "anon"}`;
|
|
25648
25648
|
const batchKey = filters.every(canPartitionFilter) ? scope : `${scope}\0unpartitioned\0${JSON.stringify(filters)}`;
|
|
25649
|
-
return new Promise((
|
|
25649
|
+
return new Promise((resolve45, reject) => {
|
|
25650
25650
|
const existing = pendingQueryBatches.get(batchKey);
|
|
25651
25651
|
const batch = existing ?? [];
|
|
25652
|
-
batch.push({ opts, filters, queryPubkey, resolve:
|
|
25652
|
+
batch.push({ opts, filters, queryPubkey, resolve: resolve45, reject });
|
|
25653
25653
|
if (existing)
|
|
25654
25654
|
return;
|
|
25655
25655
|
pendingQueryBatches.set(batchKey, batch);
|
|
@@ -25702,7 +25702,7 @@ function publishRetryDelayMs(failedAttempt) {
|
|
|
25702
25702
|
return Math.round(exponential * (1 + Math.random() * 0.25));
|
|
25703
25703
|
}
|
|
25704
25704
|
function sleep(ms) {
|
|
25705
|
-
return new Promise((
|
|
25705
|
+
return new Promise((resolve45) => setTimeout(resolve45, ms));
|
|
25706
25706
|
}
|
|
25707
25707
|
function errorMessage(error) {
|
|
25708
25708
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -25939,7 +25939,7 @@ var RelayWs = class {
|
|
|
25939
25939
|
return pending;
|
|
25940
25940
|
}
|
|
25941
25941
|
doConnect() {
|
|
25942
|
-
return new Promise((
|
|
25942
|
+
return new Promise((resolve45, reject) => {
|
|
25943
25943
|
const WS = this.opts.WebSocketImpl ?? defaultWebSocket();
|
|
25944
25944
|
const timeoutMs = this.opts.connectTimeoutMs ?? 15e3;
|
|
25945
25945
|
let settled = false;
|
|
@@ -25966,7 +25966,7 @@ var RelayWs = class {
|
|
|
25966
25966
|
const reconnected = this.successfulConnections > 0;
|
|
25967
25967
|
this.successfulConnections += 1;
|
|
25968
25968
|
this.startKeepalive();
|
|
25969
|
-
|
|
25969
|
+
resolve45();
|
|
25970
25970
|
if (reconnected)
|
|
25971
25971
|
this.resubscribeLiveRequests();
|
|
25972
25972
|
}
|
|
@@ -26076,14 +26076,14 @@ var RelayWs = class {
|
|
|
26076
26076
|
],
|
|
26077
26077
|
content: ""
|
|
26078
26078
|
}, this.opts.identity.secretKey);
|
|
26079
|
-
return new Promise((
|
|
26080
|
-
this.pendingAuth.set(event.id, { resolve:
|
|
26079
|
+
return new Promise((resolve45, reject) => {
|
|
26080
|
+
this.pendingAuth.set(event.id, { resolve: resolve45, reject });
|
|
26081
26081
|
this.send(["AUTH", event]);
|
|
26082
26082
|
setTimeout(() => {
|
|
26083
26083
|
if (this.pendingAuth.has(event.id)) {
|
|
26084
26084
|
this.pendingAuth.delete(event.id);
|
|
26085
26085
|
if (this.ws && this.ws.readyState === 1)
|
|
26086
|
-
|
|
26086
|
+
resolve45();
|
|
26087
26087
|
else
|
|
26088
26088
|
reject(new Error("NIP-42 AUTH timed out"));
|
|
26089
26089
|
}
|
|
@@ -26108,7 +26108,7 @@ var RelayWs = class {
|
|
|
26108
26108
|
}
|
|
26109
26109
|
/** Publish an event over WS (`["EVENT", event]`). Resolves on OK true. */
|
|
26110
26110
|
publish(event, timeoutMs = 1e4) {
|
|
26111
|
-
return new Promise((
|
|
26111
|
+
return new Promise((resolve45, reject) => {
|
|
26112
26112
|
const timer = setTimeout(() => {
|
|
26113
26113
|
off();
|
|
26114
26114
|
reject(new Error(`WS publish timeout for ${event.id}`));
|
|
@@ -26118,7 +26118,7 @@ var RelayWs = class {
|
|
|
26118
26118
|
clearTimeout(timer);
|
|
26119
26119
|
off();
|
|
26120
26120
|
if (msg[2] === true)
|
|
26121
|
-
|
|
26121
|
+
resolve45();
|
|
26122
26122
|
else
|
|
26123
26123
|
reject(new Error(`WS publish rejected: ${String(msg[3] ?? "")}`));
|
|
26124
26124
|
}
|
|
@@ -26232,7 +26232,7 @@ var RelayWs = class {
|
|
|
26232
26232
|
}
|
|
26233
26233
|
};
|
|
26234
26234
|
function wsQueryEvents(ws, filters, timeoutMs = 1e4) {
|
|
26235
|
-
return new Promise((
|
|
26235
|
+
return new Promise((resolve45, reject) => {
|
|
26236
26236
|
const events = [];
|
|
26237
26237
|
let settled = false;
|
|
26238
26238
|
let unsubscribe;
|
|
@@ -26249,7 +26249,7 @@ function wsQueryEvents(ws, filters, timeoutMs = 1e4) {
|
|
|
26249
26249
|
const timer = setTimeout(() => finish(() => reject(new Error(`wsQueryEvents timeout after ${timeoutMs}ms`))), timeoutMs);
|
|
26250
26250
|
offClose = ws.onClose(() => finish(() => reject(new Error("wsQueryEvents: socket closed"))));
|
|
26251
26251
|
unsubscribe = ws.subscribe(filters, (event) => events.push(event), {
|
|
26252
|
-
onEose: () => finish(() =>
|
|
26252
|
+
onEose: () => finish(() => resolve45(events))
|
|
26253
26253
|
});
|
|
26254
26254
|
});
|
|
26255
26255
|
}
|
|
@@ -26311,13 +26311,13 @@ async function flushWsQueryBatch(batchKey) {
|
|
|
26311
26311
|
}
|
|
26312
26312
|
function enqueueWsQueryEvents(ws, filters, timeoutMs) {
|
|
26313
26313
|
const batchKey = wsBatchKey(ws, filters);
|
|
26314
|
-
return new Promise((
|
|
26314
|
+
return new Promise((resolve45, reject) => {
|
|
26315
26315
|
const existing = pendingWsBatches.get(batchKey);
|
|
26316
26316
|
if (existing) {
|
|
26317
|
-
existing.queries.push({ filters, resolve:
|
|
26317
|
+
existing.queries.push({ filters, resolve: resolve45, reject });
|
|
26318
26318
|
return;
|
|
26319
26319
|
}
|
|
26320
|
-
pendingWsBatches.set(batchKey, { ws, timeoutMs, queries: [{ filters, resolve:
|
|
26320
|
+
pendingWsBatches.set(batchKey, { ws, timeoutMs, queries: [{ filters, resolve: resolve45, reject }] });
|
|
26321
26321
|
queueMicrotask(() => void flushWsQueryBatch(batchKey));
|
|
26322
26322
|
});
|
|
26323
26323
|
}
|
|
@@ -29126,14 +29126,14 @@ async function getGitHubRoomInstallationToken(baseUrl, identity2, roomId) {
|
|
|
29126
29126
|
var HEX_KEY_RE = /^[0-9a-f]{64}$/;
|
|
29127
29127
|
var IDENTITY_PREDECESSORS_TIMEOUT_MS = 5e3;
|
|
29128
29128
|
function withIdentityPredecessorTimeout(operation, controller) {
|
|
29129
|
-
return new Promise((
|
|
29129
|
+
return new Promise((resolve45, reject) => {
|
|
29130
29130
|
const timer = setTimeout(() => {
|
|
29131
29131
|
controller.abort();
|
|
29132
29132
|
reject(new OidcBindError("offline", "identity succession lookup timed out"));
|
|
29133
29133
|
}, IDENTITY_PREDECESSORS_TIMEOUT_MS);
|
|
29134
29134
|
operation.then((value) => {
|
|
29135
29135
|
clearTimeout(timer);
|
|
29136
|
-
|
|
29136
|
+
resolve45(value);
|
|
29137
29137
|
}, (error) => {
|
|
29138
29138
|
clearTimeout(timer);
|
|
29139
29139
|
reject(error);
|
|
@@ -30543,7 +30543,7 @@ var BuzzClient = class {
|
|
|
30543
30543
|
return this.successionPredecessors;
|
|
30544
30544
|
this.successionPredecessors = await Promise.race([
|
|
30545
30545
|
fetchIdentityPredecessors(this.baseUrl, this.identity).catch(() => []),
|
|
30546
|
-
new Promise((
|
|
30546
|
+
new Promise((resolve45) => setTimeout(() => resolve45([]), SUCCESSION_LOAD_TIMEOUT_MS))
|
|
30547
30547
|
]);
|
|
30548
30548
|
return this.successionPredecessors;
|
|
30549
30549
|
}
|
|
@@ -30849,7 +30849,7 @@ var BuzzClient = class {
|
|
|
30849
30849
|
return values.length > 1 ? expanded.flatMap((candidate) => values.map((value) => ({ ...candidate, [tag]: [value] }))) : expanded;
|
|
30850
30850
|
}, [{ ...filter }]));
|
|
30851
30851
|
const seenIds = /* @__PURE__ */ new Set();
|
|
30852
|
-
const unsubscribes = await Promise.all(installedFilters.map((filter) => new Promise((
|
|
30852
|
+
const unsubscribes = await Promise.all(installedFilters.map((filter) => new Promise((resolve45) => {
|
|
30853
30853
|
let settled = false;
|
|
30854
30854
|
let newestCreatedAt = 0;
|
|
30855
30855
|
let unsubscribe = () => void 0;
|
|
@@ -30858,7 +30858,7 @@ var BuzzClient = class {
|
|
|
30858
30858
|
return;
|
|
30859
30859
|
settled = true;
|
|
30860
30860
|
clearTimeout(timer);
|
|
30861
|
-
|
|
30861
|
+
resolve45(unsubscribe);
|
|
30862
30862
|
};
|
|
30863
30863
|
const timer = setTimeout(finish, 3e3);
|
|
30864
30864
|
timer.unref?.();
|
|
@@ -32870,7 +32870,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
32870
32870
|
const current = this.activeRunIds.get(sessionId);
|
|
32871
32871
|
if (current)
|
|
32872
32872
|
return Promise.resolve(current);
|
|
32873
|
-
return new Promise((
|
|
32873
|
+
return new Promise((resolve45, reject) => {
|
|
32874
32874
|
const onUpdate = (update) => {
|
|
32875
32875
|
if (update.sessionId !== sessionId)
|
|
32876
32876
|
return;
|
|
@@ -32878,7 +32878,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
32878
32878
|
if (!runId)
|
|
32879
32879
|
return;
|
|
32880
32880
|
cleanup();
|
|
32881
|
-
|
|
32881
|
+
resolve45(runId);
|
|
32882
32882
|
};
|
|
32883
32883
|
const timer = setTimeout(() => {
|
|
32884
32884
|
cleanup();
|
|
@@ -32955,13 +32955,13 @@ var AcpClient = class extends EventEmitter {
|
|
|
32955
32955
|
}
|
|
32956
32956
|
const id = this.nextId++;
|
|
32957
32957
|
const payload = { jsonrpc: "2.0", id, method, params };
|
|
32958
|
-
return new Promise((
|
|
32958
|
+
return new Promise((resolve45, reject) => {
|
|
32959
32959
|
const timer = setTimeout(() => {
|
|
32960
32960
|
this.pending.delete(id);
|
|
32961
32961
|
reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail, Boolean(onStart)));
|
|
32962
32962
|
}, timeoutMs);
|
|
32963
32963
|
this.pending.set(id, {
|
|
32964
|
-
resolve:
|
|
32964
|
+
resolve: resolve45,
|
|
32965
32965
|
reject,
|
|
32966
32966
|
timer,
|
|
32967
32967
|
method,
|
|
@@ -34610,7 +34610,7 @@ function compactActivityUpdate(update) {
|
|
|
34610
34610
|
const text2 = stripAgentReplyPreamble(compactText(update.content ?? update.message ?? update.output, 2e3) ?? "").trim();
|
|
34611
34611
|
return text2 ? { sessionUpdate: "progress_update", text: text2 } : void 0;
|
|
34612
34612
|
}
|
|
34613
|
-
function projectActivity(client, channelId, channelOwner, sessionId) {
|
|
34613
|
+
function projectActivity(client, channelId, channelOwner, sessionId, publishActivity) {
|
|
34614
34614
|
let pending = [];
|
|
34615
34615
|
let timer;
|
|
34616
34616
|
const toolCallKinds = /* @__PURE__ */ new Map();
|
|
@@ -34620,7 +34620,7 @@ function projectActivity(client, channelId, channelOwner, sessionId) {
|
|
|
34620
34620
|
let publishedPlanKey = "";
|
|
34621
34621
|
let publishTail = Promise.resolve();
|
|
34622
34622
|
const publishBatch = (events) => {
|
|
34623
|
-
const publish = () => emitActivityEvent(channelId, channelOwner, { sessionId, channelId, events });
|
|
34623
|
+
const publish = () => publishActivity ? publishActivity({ sessionId, channelId, events }) : emitActivityEvent(channelId, channelOwner, { sessionId, channelId, events });
|
|
34624
34624
|
publishTail = publishTail.then(publish, publish);
|
|
34625
34625
|
return publishTail;
|
|
34626
34626
|
};
|
|
@@ -34740,7 +34740,13 @@ function projectActivity(client, channelId, channelOwner, sessionId) {
|
|
|
34740
34740
|
currentPlan = compactAuthoredPlan?.items.length ? {
|
|
34741
34741
|
...pinnedObjective ? { objective: pinnedObjective } : compactAuthoredPlan.objective ? { objective: compactAuthoredPlan.objective } : {},
|
|
34742
34742
|
items: compactAuthoredPlan.items
|
|
34743
|
-
} : currentPlan?.items.length ?
|
|
34743
|
+
} : currentPlan?.items.length ? (
|
|
34744
|
+
// A later turn (a follow-up, a nudge, a completion-ladder check) that
|
|
34745
|
+
// brings no fresh plan of its own must not blank a checklist an
|
|
34746
|
+
// earlier turn already published — that is the finished corner
|
|
34747
|
+
// losing its sub-goals, not an honest "no plan yet" state.
|
|
34748
|
+
{ ...currentPlan, ...pinnedObjective ? { objective: pinnedObjective } : {} }
|
|
34749
|
+
) : fallbackPlan(pinnedObjective ?? objective);
|
|
34744
34750
|
await publishPlan(currentPlan);
|
|
34745
34751
|
};
|
|
34746
34752
|
controller.completePlan = async () => {
|
|
@@ -34831,7 +34837,7 @@ function nextMonotonicSecond(lastRef) {
|
|
|
34831
34837
|
lastRef.value = createdAt;
|
|
34832
34838
|
return createdAt;
|
|
34833
34839
|
}
|
|
34834
|
-
function createDraftStreamer(channelId, owner, sessionId, requestId, flushMs = AGENT_DRAFT_FLUSH_MS) {
|
|
34840
|
+
function createDraftStreamer(channelId, owner, sessionId, requestId, flushMs = AGENT_DRAFT_FLUSH_MS, publishLive, retractLive) {
|
|
34835
34841
|
let latest2 = "";
|
|
34836
34842
|
let published = "";
|
|
34837
34843
|
let finished = false;
|
|
@@ -34851,7 +34857,7 @@ function createDraftStreamer(channelId, owner, sessionId, requestId, flushMs = A
|
|
|
34851
34857
|
publishedSnapshots.add(stripped);
|
|
34852
34858
|
const snapshot = stripped;
|
|
34853
34859
|
const createdAt = nextMonotonicSecond(lastCreatedAt);
|
|
34854
|
-
inflight = inflight.then(() => postAgentDraft(channelId, owner, sessionId, requestId, snapshot, createdAt)).catch((error) => console.error("[body] agent draft publish failed:", error));
|
|
34860
|
+
inflight = inflight.then(() => publishLive ? publishLive(snapshot) : postAgentDraft(channelId, owner, sessionId, requestId, snapshot, createdAt)).catch((error) => console.error("[body] agent draft publish failed:", error));
|
|
34855
34861
|
};
|
|
34856
34862
|
return {
|
|
34857
34863
|
onChunk(fullTextSoFar) {
|
|
@@ -34871,13 +34877,13 @@ function createDraftStreamer(channelId, owner, sessionId, requestId, flushMs = A
|
|
|
34871
34877
|
flush();
|
|
34872
34878
|
if (publishedSnapshots.size > 0) {
|
|
34873
34879
|
const createdAt = nextMonotonicSecond(lastCreatedAt);
|
|
34874
|
-
inflight = inflight.then(() => retractAgentDraft(channelId, channelId, owner, createdAt)).catch((error) => console.error("[body] agent draft retract failed:", error));
|
|
34880
|
+
inflight = inflight.then(() => retractLive ? retractLive() : retractAgentDraft(channelId, channelId, owner, createdAt)).catch((error) => console.error("[body] agent draft retract failed:", error));
|
|
34875
34881
|
}
|
|
34876
34882
|
await inflight;
|
|
34877
34883
|
}
|
|
34878
34884
|
};
|
|
34879
34885
|
}
|
|
34880
|
-
function createThoughtStreamer(channelId, owner, sessionId, flushMs = AGENT_DRAFT_FLUSH_MS) {
|
|
34886
|
+
function createThoughtStreamer(channelId, owner, sessionId, flushMs = AGENT_DRAFT_FLUSH_MS, publishLive, retractLive) {
|
|
34881
34887
|
let latest2 = "";
|
|
34882
34888
|
let published = "";
|
|
34883
34889
|
let finished = false;
|
|
@@ -34892,7 +34898,7 @@ function createThoughtStreamer(channelId, owner, sessionId, flushMs = AGENT_DRAF
|
|
|
34892
34898
|
published = text2;
|
|
34893
34899
|
const snapshot = text2;
|
|
34894
34900
|
const createdAt = nextMonotonicSecond(lastCreatedAt);
|
|
34895
|
-
inflight = inflight.then(() => postAgentThought(channelId, owner, sessionId, snapshot, createdAt)).catch((error) => console.error("[body] agent thought publish failed:", error));
|
|
34901
|
+
inflight = inflight.then(() => publishLive ? publishLive(snapshot) : postAgentThought(channelId, owner, sessionId, snapshot, createdAt)).catch((error) => console.error("[body] agent thought publish failed:", error));
|
|
34896
34902
|
};
|
|
34897
34903
|
return {
|
|
34898
34904
|
onChunk(text2) {
|
|
@@ -34910,7 +34916,7 @@ function createThoughtStreamer(channelId, owner, sessionId, flushMs = AGENT_DRAF
|
|
|
34910
34916
|
flush();
|
|
34911
34917
|
if (published) {
|
|
34912
34918
|
const createdAt = nextMonotonicSecond(lastCreatedAt);
|
|
34913
|
-
inflight = inflight.then(() => retractAgentThought(channelId, channelId, owner, sessionId, createdAt)).catch((error) => console.error("[body] agent thought retract failed:", error));
|
|
34919
|
+
inflight = inflight.then(() => retractLive ? retractLive() : retractAgentThought(channelId, channelId, owner, sessionId, createdAt)).catch((error) => console.error("[body] agent thought retract failed:", error));
|
|
34914
34920
|
}
|
|
34915
34921
|
await inflight;
|
|
34916
34922
|
}
|
|
@@ -34984,7 +34990,7 @@ function startAgentPresence(channelId, owner, intervalMs = AGENT_PRESENCE_HEARTB
|
|
|
34984
34990
|
const generationId = randomUUID2();
|
|
34985
34991
|
const backoff = async (delayMs) => {
|
|
34986
34992
|
for (let remaining = delayMs; remaining > 0 && !stopped; remaining -= 250) {
|
|
34987
|
-
await new Promise((
|
|
34993
|
+
await new Promise((resolve45) => setTimeout(resolve45, Math.min(250, remaining)));
|
|
34988
34994
|
}
|
|
34989
34995
|
};
|
|
34990
34996
|
const publishWithRetry = async (nextStatus) => {
|
|
@@ -35132,7 +35138,7 @@ function delayWithJitter(attempt) {
|
|
|
35132
35138
|
const spread = exponential * 0.25;
|
|
35133
35139
|
return Math.max(250, Math.round(exponential - spread + Math.random() * spread * 2));
|
|
35134
35140
|
}
|
|
35135
|
-
var sleep2 = (ms) => new Promise((
|
|
35141
|
+
var sleep2 = (ms) => new Promise((resolve45) => setTimeout(resolve45, ms));
|
|
35136
35142
|
async function publishCritical(publish, options) {
|
|
35137
35143
|
const maxAttempts = options.maxAttempts ?? CRITICAL_PUBLISH_MAX_ATTEMPTS;
|
|
35138
35144
|
let lastError;
|
|
@@ -35179,6 +35185,7 @@ function migrateDurableBodyData(candidate, path) {
|
|
|
35179
35185
|
modelTurns: legacy.modelTurns,
|
|
35180
35186
|
sessionReprimes: legacy.sessionReprimes,
|
|
35181
35187
|
githubEventCursors: legacy.githubEventCursors,
|
|
35188
|
+
daemonInboxCursors: legacy.daemonInboxCursors,
|
|
35182
35189
|
factory: legacy.factory
|
|
35183
35190
|
};
|
|
35184
35191
|
}
|
|
@@ -35220,6 +35227,7 @@ var DurableBodyState = class {
|
|
|
35220
35227
|
this.data.modelTurns ??= [];
|
|
35221
35228
|
this.data.sessionReprimes ??= [];
|
|
35222
35229
|
this.data.githubEventCursors ??= {};
|
|
35230
|
+
this.data.daemonInboxCursors ??= {};
|
|
35223
35231
|
} catch (error) {
|
|
35224
35232
|
if (error.code !== "ENOENT")
|
|
35225
35233
|
throw error;
|
|
@@ -35288,6 +35296,18 @@ var DurableBodyState = class {
|
|
|
35288
35296
|
await this.load();
|
|
35289
35297
|
return { ...this.inbox(channelId).cursor };
|
|
35290
35298
|
}
|
|
35299
|
+
async daemonInboxCursor(channelId) {
|
|
35300
|
+
await this.load();
|
|
35301
|
+
return this.data.daemonInboxCursors?.[channelId];
|
|
35302
|
+
}
|
|
35303
|
+
async setDaemonInboxCursor(channelId, cursor3) {
|
|
35304
|
+
await this.load();
|
|
35305
|
+
const cursors = this.data.daemonInboxCursors ??= {};
|
|
35306
|
+
if (cursors[channelId] === cursor3)
|
|
35307
|
+
return;
|
|
35308
|
+
cursors[channelId] = cursor3;
|
|
35309
|
+
await this.save();
|
|
35310
|
+
}
|
|
35291
35311
|
/** Persist one inspectable model invocation, including the human event that authorized it. */
|
|
35292
35312
|
async recordModelTurn(turn) {
|
|
35293
35313
|
await this.load();
|
|
@@ -37683,7 +37703,7 @@ var WorkCalendar = class {
|
|
|
37683
37703
|
if (!found) {
|
|
37684
37704
|
const delay = this.dependencies.runNowVisibilityRetryMs ?? RUN_NOW_VISIBILITY_RETRY_MS;
|
|
37685
37705
|
if (delay > 0)
|
|
37686
|
-
await new Promise((
|
|
37706
|
+
await new Promise((resolve45) => setTimeout(resolve45, delay));
|
|
37687
37707
|
await this.refresh();
|
|
37688
37708
|
found = this.scheduleById(scheduleId);
|
|
37689
37709
|
}
|
|
@@ -38577,8 +38597,8 @@ function trustySquireIpcPaths(env = process.env) {
|
|
|
38577
38597
|
for (const address of [env.DBUS_SESSION_BUS_ADDRESS, env.DBUS_STARTER_ADDRESS]) {
|
|
38578
38598
|
if (!address?.trim())
|
|
38579
38599
|
continue;
|
|
38580
|
-
for (const
|
|
38581
|
-
const match = /(?:^unix:|,)path=([^,]+)/.exec(
|
|
38600
|
+
for (const endpoint2 of address.split(";")) {
|
|
38601
|
+
const match = /(?:^unix:|,)path=([^,]+)/.exec(endpoint2);
|
|
38582
38602
|
if (match?.[1] && isAbsolute5(match[1]))
|
|
38583
38603
|
paths.add(resolve13(match[1]));
|
|
38584
38604
|
}
|
|
@@ -38592,8 +38612,8 @@ function trustySquireIpcPaths(env = process.env) {
|
|
|
38592
38612
|
return [...paths];
|
|
38593
38613
|
}
|
|
38594
38614
|
function hasUnmaskableTrustySquireIpc(env = process.env) {
|
|
38595
|
-
return [env.DBUS_SESSION_BUS_ADDRESS, env.DBUS_STARTER_ADDRESS].some((address) => address?.split(";").filter(Boolean).some((
|
|
38596
|
-
const match = /(?:^unix:|,)path=([^,]+)/.exec(
|
|
38615
|
+
return [env.DBUS_SESSION_BUS_ADDRESS, env.DBUS_STARTER_ADDRESS].some((address) => address?.split(";").filter(Boolean).some((endpoint2) => {
|
|
38616
|
+
const match = /(?:^unix:|,)path=([^,]+)/.exec(endpoint2);
|
|
38597
38617
|
return !match?.[1] || !isAbsolute5(match[1]);
|
|
38598
38618
|
}));
|
|
38599
38619
|
}
|
|
@@ -39972,15 +39992,15 @@ var SquireHostBroker = class {
|
|
|
39972
39992
|
allowedTools: new Set(allowedTools)
|
|
39973
39993
|
};
|
|
39974
39994
|
channel.allowedTools = new Set(allowedTools);
|
|
39975
|
-
const
|
|
39995
|
+
const endpoint2 = {
|
|
39976
39996
|
name: "squire",
|
|
39977
39997
|
command: process.execPath,
|
|
39978
39998
|
args: [this.proxyEntrypoint, "127.0.0.1", String(address.port), channel.token],
|
|
39979
39999
|
env: []
|
|
39980
40000
|
};
|
|
39981
|
-
channel.endpoint =
|
|
40001
|
+
channel.endpoint = endpoint2;
|
|
39982
40002
|
this.channels.set(channelId, channel);
|
|
39983
|
-
return
|
|
40003
|
+
return endpoint2;
|
|
39984
40004
|
}
|
|
39985
40005
|
accept(socket) {
|
|
39986
40006
|
socket.setEncoding("utf8");
|
|
@@ -40205,14 +40225,14 @@ var AgentToolHostBroker = class {
|
|
|
40205
40225
|
previous?.connection?.destroy();
|
|
40206
40226
|
const token2 = randomBytes6(32).toString("hex");
|
|
40207
40227
|
const proxyArgs = [this.proxyEntrypoint, "127.0.0.1", String(address.port), token2];
|
|
40208
|
-
const
|
|
40228
|
+
const endpoint2 = {
|
|
40209
40229
|
name: BEELINE_AGENT_TOOL_SERVER_NAME,
|
|
40210
40230
|
command: process.execPath,
|
|
40211
40231
|
args: this.proxyEntrypoint.endsWith(".ts") ? ["--import", "tsx", ...proxyArgs] : proxyArgs,
|
|
40212
40232
|
env: []
|
|
40213
40233
|
};
|
|
40214
|
-
this.sessions.set(binding.channelId, { token: token2, binding, endpoint });
|
|
40215
|
-
return
|
|
40234
|
+
this.sessions.set(binding.channelId, { token: token2, binding, endpoint: endpoint2 });
|
|
40235
|
+
return endpoint2;
|
|
40216
40236
|
}
|
|
40217
40237
|
revoke(channelId) {
|
|
40218
40238
|
const session = this.sessions.get(channelId);
|
|
@@ -40537,8 +40557,8 @@ async function inspectMcpServer(spec, timeoutMs = 15e3) {
|
|
|
40537
40557
|
const request = (method, params) => {
|
|
40538
40558
|
const id = nextId++;
|
|
40539
40559
|
const payload = JSON.stringify({ jsonrpc: "2.0", id, method, params });
|
|
40540
|
-
return new Promise((
|
|
40541
|
-
pending.set(id, { resolve:
|
|
40560
|
+
return new Promise((resolve45, reject) => {
|
|
40561
|
+
pending.set(id, { resolve: resolve45, reject });
|
|
40542
40562
|
child.stdin.write(payload + "\n");
|
|
40543
40563
|
});
|
|
40544
40564
|
};
|
|
@@ -41760,8 +41780,8 @@ var AgentMentionTurnQueue = class {
|
|
|
41760
41780
|
run(cornerId, task) {
|
|
41761
41781
|
const prior = this.tails.get(cornerId) ?? Promise.resolve();
|
|
41762
41782
|
let release;
|
|
41763
|
-
const gate = new Promise((
|
|
41764
|
-
release =
|
|
41783
|
+
const gate = new Promise((resolve45) => {
|
|
41784
|
+
release = resolve45;
|
|
41765
41785
|
});
|
|
41766
41786
|
const tail = prior.catch(() => void 0).then(() => gate);
|
|
41767
41787
|
this.tails.set(cornerId, tail);
|
|
@@ -43628,6 +43648,10 @@ function isChannelAddressedMessage(event, agentPubkey, roomParticipants = [], in
|
|
|
43628
43648
|
return false;
|
|
43629
43649
|
if (event.tags.some((tag) => tag[0] === "p" && tag[1] === agentPubkey))
|
|
43630
43650
|
return true;
|
|
43651
|
+
const replyParentId = event.tags.find((tag) => tag[0] === "e" && tag[1] && tag[3] === "reply")?.[1];
|
|
43652
|
+
const replyParent = replyParentId ? indexedMessages.find((message2) => message2.id === replyParentId) : void 0;
|
|
43653
|
+
if (replyParent?.author.kind === "agent" && replyParent.author.pubkey === agentPubkey)
|
|
43654
|
+
return true;
|
|
43631
43655
|
if (event.tags.some((tag) => tag[0] === "p" && tag[1] && roomParticipants.includes(tag[1]))) {
|
|
43632
43656
|
return false;
|
|
43633
43657
|
}
|
|
@@ -43635,21 +43659,7 @@ function isChannelAddressedMessage(event, agentPubkey, roomParticipants = [], in
|
|
|
43635
43659
|
participants.delete(agentPubkey);
|
|
43636
43660
|
if (participants.size === 1 && participants.has(event.pubkey))
|
|
43637
43661
|
return true;
|
|
43638
|
-
|
|
43639
|
-
if (indexedCurrent && indexedCurrent.presentation !== "message")
|
|
43640
|
-
return false;
|
|
43641
|
-
const conversation = indexedMessages.filter((message2) => message2.presentation === "message");
|
|
43642
|
-
const currentIndex = conversation.findIndex((message2) => message2.id === event.id);
|
|
43643
|
-
const latestIndexed = conversation.at(-1);
|
|
43644
|
-
const followsIndexedTail = latestIndexed && (latestIndexed.createdAt < event.created_at || latestIndexed.createdAt === event.created_at && latestIndexed.id.localeCompare(event.id) < 0);
|
|
43645
|
-
const preceding = currentIndex >= 0 ? conversation[currentIndex - 1] : followsIndexedTail ? latestIndexed : void 0;
|
|
43646
|
-
if (preceding?.author.kind !== "agent" || preceding.author.pubkey !== agentPubkey)
|
|
43647
|
-
return false;
|
|
43648
|
-
const repliedTo = preceding.reply?.eventId;
|
|
43649
|
-
if (!repliedTo)
|
|
43650
|
-
return false;
|
|
43651
|
-
const triggeringMessage = conversation.find((message2) => message2.id === repliedTo);
|
|
43652
|
-
return triggeringMessage?.author.kind === "human" && triggeringMessage.author.pubkey === event.pubkey;
|
|
43662
|
+
return false;
|
|
43653
43663
|
}
|
|
43654
43664
|
function isChannelWorkIntent(event, agentPubkey, roomParticipants = [], indexedMessages = []) {
|
|
43655
43665
|
if (!isChannelAddressedMessage(event, agentPubkey, roomParticipants, indexedMessages))
|
|
@@ -43821,6 +43831,8 @@ var Body = class {
|
|
|
43821
43831
|
* disposes its own sockets exactly as before.
|
|
43822
43832
|
*/
|
|
43823
43833
|
sharedSocket;
|
|
43834
|
+
/** Present only after the one-way monolith transport switch is activated. */
|
|
43835
|
+
daemonApi;
|
|
43824
43836
|
disposed = false;
|
|
43825
43837
|
/**
|
|
43826
43838
|
* Set only after the managed update's absolute drain deadline expires.
|
|
@@ -43888,6 +43900,7 @@ var Body = class {
|
|
|
43888
43900
|
this.onRoomPresence = services.onRoomPresence;
|
|
43889
43901
|
this.runScheduleNow = services.runScheduleNow;
|
|
43890
43902
|
this.sharedSocket = services.relaySocket;
|
|
43903
|
+
this.daemonApi = services.daemonApi;
|
|
43891
43904
|
this.durableState = new DurableBodyState(services.statePath ?? resolve27(config.workspaceRoot, ".beeline-body-state.json"));
|
|
43892
43905
|
this.permissionReader = {
|
|
43893
43906
|
readEvent: async (eventId) => {
|
|
@@ -44639,7 +44652,8 @@ var Body = class {
|
|
|
44639
44652
|
this.agentIdentity,
|
|
44640
44653
|
// Transcript correlation follows the durable logical turn, not a
|
|
44641
44654
|
// physical ACP process id that changes after suspension/restart.
|
|
44642
|
-
session.logicalSessionId ?? opened.sessionId
|
|
44655
|
+
session.logicalSessionId ?? opened.sessionId,
|
|
44656
|
+
this.daemonApi ? (batch) => this.publishMonolithActivity(input.channelId, batch) : void 0
|
|
44643
44657
|
);
|
|
44644
44658
|
session.activityProjection = activityProjection;
|
|
44645
44659
|
session.unsubscribeActivity = activityProjection;
|
|
@@ -44681,7 +44695,16 @@ var Body = class {
|
|
|
44681
44695
|
async applyModelConfigForSession(client, sessionId, communityId, sessionNewRaw, session) {
|
|
44682
44696
|
let selection = null;
|
|
44683
44697
|
try {
|
|
44684
|
-
|
|
44698
|
+
if (this.daemonApi) {
|
|
44699
|
+
const configured = await this.daemonApi.execute("getAgentConfiguration", {
|
|
44700
|
+
agentId: this.agentIdentity.publicKey,
|
|
44701
|
+
roomId: session.channelId
|
|
44702
|
+
});
|
|
44703
|
+
selection = configured.model || configured.effort ? { model: configured.model, effort: configured.effort } : null;
|
|
44704
|
+
} else {
|
|
44705
|
+
const persisted = await getAgentModelConfig(this.agentClientContext(), communityId, this.agentIdentity.publicKey);
|
|
44706
|
+
selection = persisted ? { model: persisted.model, effort: persisted.effort } : null;
|
|
44707
|
+
}
|
|
44685
44708
|
} catch (error) {
|
|
44686
44709
|
console.error("[body] failed to read persisted agent model config:", error);
|
|
44687
44710
|
}
|
|
@@ -44695,7 +44718,21 @@ var Body = class {
|
|
|
44695
44718
|
session.modelConfigOptions = catalogOptions;
|
|
44696
44719
|
if (catalogOptions.length) {
|
|
44697
44720
|
try {
|
|
44698
|
-
|
|
44721
|
+
if (this.daemonApi) {
|
|
44722
|
+
await this.daemonApi.execute("postAgentModelCatalog", {
|
|
44723
|
+
agentId: this.agentIdentity.publicKey,
|
|
44724
|
+
workspaceId: communityId,
|
|
44725
|
+
options: withEffectiveCurrentValues(catalogOptions, applied).flatMap((option) => ["model", "thought_level", "effort", "reasoning_effort"].includes(option.category) ? [
|
|
44726
|
+
{
|
|
44727
|
+
...option,
|
|
44728
|
+
category: option.category
|
|
44729
|
+
}
|
|
44730
|
+
] : []),
|
|
44731
|
+
...applied ? { selection: applied } : {}
|
|
44732
|
+
});
|
|
44733
|
+
} else {
|
|
44734
|
+
await publishAgentModelCatalog(this.agentClientContext(), communityId, withEffectiveCurrentValues(catalogOptions, applied), applied ?? void 0);
|
|
44735
|
+
}
|
|
44699
44736
|
} catch (error) {
|
|
44700
44737
|
console.error("[body] failed to publish agent model catalog:", error);
|
|
44701
44738
|
}
|
|
@@ -44726,7 +44763,15 @@ var Body = class {
|
|
|
44726
44763
|
attachAgentCommandPublisher(client, communityId, sessionId) {
|
|
44727
44764
|
const publisher = createAgentCommandPublisher({
|
|
44728
44765
|
publish: async (commands) => {
|
|
44729
|
-
|
|
44766
|
+
if (this.daemonApi) {
|
|
44767
|
+
await this.daemonApi.execute("postAgentCommands", {
|
|
44768
|
+
agentId: this.agentIdentity.publicKey,
|
|
44769
|
+
workspaceId: communityId,
|
|
44770
|
+
commands
|
|
44771
|
+
});
|
|
44772
|
+
} else {
|
|
44773
|
+
await publishAgentCommands(this.agentClientContext(), communityId, commands);
|
|
44774
|
+
}
|
|
44730
44775
|
},
|
|
44731
44776
|
publishedSignatures: PUBLISHED_COMMAND_SIGNATURES,
|
|
44732
44777
|
dedupeKeyPrefix: communityId
|
|
@@ -44930,6 +44975,43 @@ var Body = class {
|
|
|
44930
44975
|
console.error("[body] failed to publish queued-steer acknowledgement:", error);
|
|
44931
44976
|
});
|
|
44932
44977
|
}
|
|
44978
|
+
async publishMonolithActivity(channelId, batch) {
|
|
44979
|
+
if (!this.daemonApi)
|
|
44980
|
+
return;
|
|
44981
|
+
const activity2 = batch.events.map((event) => {
|
|
44982
|
+
const plan = event.plan && typeof event.plan === "object" ? event.plan : void 0;
|
|
44983
|
+
return {
|
|
44984
|
+
kind: event.sessionUpdate === "tool_activity" ? "tool" : "summary",
|
|
44985
|
+
title: typeof event.title === "string" ? event.title : typeof event.text === "string" ? event.text : "Agent activity",
|
|
44986
|
+
...typeof event.command === "string" ? { operation: event.command } : {},
|
|
44987
|
+
...typeof event.status === "string" ? { status: event.status } : {},
|
|
44988
|
+
...plan?.items ? {
|
|
44989
|
+
plan: {
|
|
44990
|
+
...plan.objective ? { objective: plan.objective } : {},
|
|
44991
|
+
items: plan.items
|
|
44992
|
+
}
|
|
44993
|
+
} : {}
|
|
44994
|
+
};
|
|
44995
|
+
});
|
|
44996
|
+
await this.daemonApi.execute("postAgentActivity", {
|
|
44997
|
+
agentId: this.agentIdentity.publicKey,
|
|
44998
|
+
roomId: channelId,
|
|
44999
|
+
requestId: batch.sessionId,
|
|
45000
|
+
activity: activity2
|
|
45001
|
+
});
|
|
45002
|
+
}
|
|
45003
|
+
postTurnStatus(roomId, requestId, sessionId, status) {
|
|
45004
|
+
if (!this.daemonApi) {
|
|
45005
|
+
return postAgentTurnStatus(roomId, this.agentIdentity, requestId, sessionId, status, this.presenceGenerations.get(roomId));
|
|
45006
|
+
}
|
|
45007
|
+
return this.daemonApi.execute("postAgentTurnReceipt", {
|
|
45008
|
+
agentId: this.agentIdentity.publicKey,
|
|
45009
|
+
roomId,
|
|
45010
|
+
requestId,
|
|
45011
|
+
status,
|
|
45012
|
+
generationId: sessionId
|
|
45013
|
+
}).then(() => void 0);
|
|
45014
|
+
}
|
|
44933
45015
|
/**
|
|
44934
45016
|
* Prompt deadlines are process-health boundaries, not merely UI timeouts.
|
|
44935
45017
|
* Retire a non-returning ACP generation so the next Room turn gets a fresh
|
|
@@ -44943,8 +45025,28 @@ var Body = class {
|
|
|
44943
45025
|
* the caller publishes exactly one final agent message after this resolves.
|
|
44944
45026
|
*/
|
|
44945
45027
|
async promptAgent(session, prompt, turn, activeRoomTurn) {
|
|
44946
|
-
const draft = !turn.silent ? createDraftStreamer(turn.channelId, this.agentIdentity, session.logicalSessionId ?? session.sessionId, turn.requestId)
|
|
44947
|
-
|
|
45028
|
+
const draft = !turn.silent ? createDraftStreamer(turn.channelId, this.agentIdentity, session.logicalSessionId ?? session.sessionId, turn.requestId, void 0, this.daemonApi ? (text2) => this.daemonApi.execute("postAgentDraft", {
|
|
45029
|
+
agentId: this.agentIdentity.publicKey,
|
|
45030
|
+
roomId: turn.channelId,
|
|
45031
|
+
turnId: session.logicalSessionId ?? session.sessionId,
|
|
45032
|
+
text: text2
|
|
45033
|
+
}).then(() => void 0) : void 0, this.daemonApi ? () => this.daemonApi.execute("retractAgentLiveOutput", {
|
|
45034
|
+
agentId: this.agentIdentity.publicKey,
|
|
45035
|
+
roomId: turn.channelId,
|
|
45036
|
+
turnId: session.logicalSessionId ?? session.sessionId,
|
|
45037
|
+
kind: "draft"
|
|
45038
|
+
}).then(() => void 0) : void 0) : void 0;
|
|
45039
|
+
const thought = !turn.silent ? createThoughtStreamer(turn.channelId, this.agentIdentity, session.logicalSessionId ?? session.sessionId, void 0, this.daemonApi ? (text2) => this.daemonApi.execute("postAgentThought", {
|
|
45040
|
+
agentId: this.agentIdentity.publicKey,
|
|
45041
|
+
roomId: turn.channelId,
|
|
45042
|
+
turnId: session.logicalSessionId ?? session.sessionId,
|
|
45043
|
+
text: text2
|
|
45044
|
+
}).then(() => void 0) : void 0, this.daemonApi ? () => this.daemonApi.execute("retractAgentLiveOutput", {
|
|
45045
|
+
agentId: this.agentIdentity.publicKey,
|
|
45046
|
+
roomId: turn.channelId,
|
|
45047
|
+
turnId: session.logicalSessionId ?? session.sessionId,
|
|
45048
|
+
kind: "thought"
|
|
45049
|
+
}).then(() => void 0) : void 0) : void 0;
|
|
44948
45050
|
const permissionTurn = {
|
|
44949
45051
|
requestId: turn.requestId,
|
|
44950
45052
|
...turn.originalRequestId ? { originalRequestId: turn.originalRequestId } : {},
|
|
@@ -45200,7 +45302,7 @@ var Body = class {
|
|
|
45200
45302
|
return { attachments, failed };
|
|
45201
45303
|
}
|
|
45202
45304
|
async publishAgentResult(channelId, session, result, fallback = "", options = {}) {
|
|
45203
|
-
const uploaded = await this.uploadAgentOutputs(session, result);
|
|
45305
|
+
const uploaded = this.daemonApi ? { attachments: [], failed: false } : await this.uploadAgentOutputs(session, result);
|
|
45204
45306
|
let reply = stripAttachmentDirectives(stripAgentReplyPreamble(result.agentText)).trim();
|
|
45205
45307
|
if (reply && isPureRetryNarration(reply)) {
|
|
45206
45308
|
console.log(`[body] discarded harness retry narration instead of publishing it as a reply`);
|
|
@@ -45219,6 +45321,16 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
|
|
|
45219
45321
|
return "";
|
|
45220
45322
|
}
|
|
45221
45323
|
const extraTags = options.prepareTags ? await options.prepareTags(reply) : options.extraTags ?? [];
|
|
45324
|
+
if (this.daemonApi) {
|
|
45325
|
+
await this.daemonApi.execute("postRoomMessage", {
|
|
45326
|
+
roomId: channelId,
|
|
45327
|
+
...options.replyTo ? { requestId: options.replyTo } : {},
|
|
45328
|
+
text: reply,
|
|
45329
|
+
presentation: "message",
|
|
45330
|
+
...extraTags.length ? { tags: Object.fromEntries(extraTags.filter((tag) => tag[0] && tag[1])) } : {}
|
|
45331
|
+
});
|
|
45332
|
+
return reply;
|
|
45333
|
+
}
|
|
45222
45334
|
let event;
|
|
45223
45335
|
if (options.replyTo) {
|
|
45224
45336
|
event = await this.durableState.reserveReply(channelId, options.replyTo, buildAgentMessage(channelId, this.agentIdentity, reply, options.replyTo, uploaded.attachments, [["request", options.replyTo], ...extraTags], options.replyRootId));
|
|
@@ -45534,8 +45646,10 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
|
|
|
45534
45646
|
console.warn(`[body] ${scopeWarning}`);
|
|
45535
45647
|
const readonlyServerWithoutMemory = readOnlyMcpServer(this.config, readonlyCwd);
|
|
45536
45648
|
const agentId = this.agentIdentity;
|
|
45537
|
-
|
|
45538
|
-
|
|
45649
|
+
if (!this.daemonApi) {
|
|
45650
|
+
await this.ensureAgentInChannel(tlcChannelId, agentId);
|
|
45651
|
+
await this.ensureAgentEntity(tlcChannelId);
|
|
45652
|
+
}
|
|
45539
45653
|
const communityId = await this.channelCommunityId(tlcChannelId);
|
|
45540
45654
|
const workspaceId = communityId ?? tlcChannelId;
|
|
45541
45655
|
const roomMemory = await this.sessionMemory(communityId);
|
|
@@ -45591,6 +45705,16 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
|
|
|
45591
45705
|
if (boundRepo)
|
|
45592
45706
|
this.agentToolRoomRepositories.set(tlcChannelId, boundRepo);
|
|
45593
45707
|
const mandateGeneration2 = Date.now();
|
|
45708
|
+
if (this.daemonApi) {
|
|
45709
|
+
this.agentTools.bindMandate(tlcChannelId, {
|
|
45710
|
+
schema_version: BEELINE_AGENT_TOOL_SCHEMA_VERSION,
|
|
45711
|
+
generation: { event_id: `monolith:${mandateGeneration2}`, generation: mandateGeneration2 },
|
|
45712
|
+
grants: [],
|
|
45713
|
+
defaults: BEELINE_MANDATE_DEFAULTS.map((entry) => ({ ...entry })),
|
|
45714
|
+
blockers: []
|
|
45715
|
+
});
|
|
45716
|
+
return session;
|
|
45717
|
+
}
|
|
45594
45718
|
const started = buildControlMessage("permission-status", tlcChannelId, agentId, `\u{1F916} Agent session started (read-only) \u2014 session=${session.logicalSessionId}`, [
|
|
45595
45719
|
["session", session.logicalSessionId],
|
|
45596
45720
|
["mode", "readonly"],
|
|
@@ -45660,7 +45784,11 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
|
|
|
45660
45784
|
}
|
|
45661
45785
|
}).catch(async (error) => {
|
|
45662
45786
|
if (attempt.cornerId && !this.subchannels.has(attempt.cornerId)) {
|
|
45663
|
-
|
|
45787
|
+
if (this.daemonApi) {
|
|
45788
|
+
await this.daemonApi.execute("archiveCorner", { cornerId: attempt.cornerId }).catch(() => void 0);
|
|
45789
|
+
} else {
|
|
45790
|
+
await archiveChannel(this.agentIdentity, attempt.cornerId).catch(() => void 0);
|
|
45791
|
+
}
|
|
45664
45792
|
await this.postFailureFactOnce(tlcChannelId, `Corner for ${attempt.objective || "the requested task"} could not start and was closed.`, [
|
|
45665
45793
|
["subchannel", attempt.cornerId],
|
|
45666
45794
|
["request", request.eventId],
|
|
@@ -45689,7 +45817,8 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
|
|
|
45689
45817
|
const freshRoomRepo = roomRepo && this.refreshRepositoryTruth ? await this.refreshRepositoryTruth(roomRepo, "corner-open") : roomRepo;
|
|
45690
45818
|
const boundRepo = freshRoomRepo ? await this.cornerBoundRepo(tlcChannelId, freshRoomRepo) : void 0;
|
|
45691
45819
|
const agentId = this.agentIdentity;
|
|
45692
|
-
|
|
45820
|
+
if (!this.daemonApi)
|
|
45821
|
+
await this.ensureAgentInChannel(tlcChannelId, agentId);
|
|
45693
45822
|
const communityId = await this.channelCommunityId(tlcChannelId);
|
|
45694
45823
|
const conversation = await this.agentHistory(tlcChannelId);
|
|
45695
45824
|
const statedTask = intent ? taskDescriptionFromCornerRequest(intent).slice(0, 320) : "";
|
|
@@ -45699,7 +45828,14 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
|
|
|
45699
45828
|
const cornerName = cornerTitleFromTask(taskDescription);
|
|
45700
45829
|
const taskSlug = slugifyCornerTask(cornerName);
|
|
45701
45830
|
const openingHumanPubkey = request?.authorPubkey ?? this.bodyIdentity.publicKey;
|
|
45702
|
-
const subchannelId = await
|
|
45831
|
+
const subchannelId = this.daemonApi ? (await this.daemonApi.execute("createCorner", {
|
|
45832
|
+
roomId: tlcChannelId,
|
|
45833
|
+
requestId: request?.eventId ?? randomUUID5().replaceAll("-", ""),
|
|
45834
|
+
name: cornerName,
|
|
45835
|
+
task: taskDescription,
|
|
45836
|
+
...boundRepo ? { repository: this.repoId(boundRepo) } : {},
|
|
45837
|
+
...boundRepo?.targetBranch ? { targetBranch: shortBranchName(boundRepo.targetBranch) } : {}
|
|
45838
|
+
})).cornerId : await createAgentSubchannel(agentId, tlcChannelId, cornerName, openingHumanPubkey, communityId ?? void 0, taskDescription || void 0, [
|
|
45703
45839
|
...request ? [
|
|
45704
45840
|
["request", request.eventId],
|
|
45705
45841
|
["requester", request.authorPubkey]
|
|
@@ -45720,30 +45856,50 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
|
|
|
45720
45856
|
if (request) {
|
|
45721
45857
|
const requesterAttribution = request.delegation ? (await this.roomAuthorAttributions(tlcChannelId, [request.authorPubkey])).get(request.authorPubkey) : request.authorAttribution;
|
|
45722
45858
|
const requester = requesterAttribution?.handle ?? fallbackPersonName(request.authorPubkey);
|
|
45723
|
-
|
|
45724
|
-
|
|
45725
|
-
|
|
45726
|
-
|
|
45727
|
-
|
|
45728
|
-
|
|
45729
|
-
|
|
45730
|
-
|
|
45731
|
-
|
|
45732
|
-
|
|
45733
|
-
|
|
45859
|
+
const createdText = `Corner requested by @${requester.replace(/^@/, "")}: ${taskDescription || request.content.trim() || "untitled task"}`;
|
|
45860
|
+
if (this.daemonApi) {
|
|
45861
|
+
await this.daemonApi.execute("postRoomMessage", {
|
|
45862
|
+
roomId: tlcChannelId,
|
|
45863
|
+
requestId: request.eventId,
|
|
45864
|
+
text: createdText,
|
|
45865
|
+
presentation: "card",
|
|
45866
|
+
tags: { type: "corner-created", subchannel: subchannelId, status: "open" }
|
|
45867
|
+
});
|
|
45868
|
+
} else
|
|
45869
|
+
await postControlMessage("corner-created", tlcChannelId, agentId, createdText, [
|
|
45734
45870
|
["subchannel", subchannelId],
|
|
45735
|
-
["
|
|
45736
|
-
["
|
|
45871
|
+
["request", request.eventId],
|
|
45872
|
+
["requester", request.authorPubkey],
|
|
45873
|
+
["status", "open"],
|
|
45874
|
+
["display-status", "starting"],
|
|
45875
|
+
["task", taskDescription]
|
|
45737
45876
|
]);
|
|
45877
|
+
if (!options?.suppressOpenCard) {
|
|
45878
|
+
if (this.daemonApi) {
|
|
45879
|
+
await this.daemonApi.execute("postRoomMessage", {
|
|
45880
|
+
roomId: tlcChannelId,
|
|
45881
|
+
requestId: request.eventId,
|
|
45882
|
+
text: `Corner opened: ${cornerName}`,
|
|
45883
|
+
presentation: "card",
|
|
45884
|
+
tags: { type: "corner-open", subchannel: subchannelId, objective: taskDescription }
|
|
45885
|
+
});
|
|
45886
|
+
} else
|
|
45887
|
+
await postControlMessage("corner-open-fact", tlcChannelId, agentId, `Corner opened: ${cornerName}`, [
|
|
45888
|
+
["t", "corner-open"],
|
|
45889
|
+
["subchannel", subchannelId],
|
|
45890
|
+
["objective", taskDescription || request.content.trim() || cornerName],
|
|
45891
|
+
["name", cornerName]
|
|
45892
|
+
]);
|
|
45738
45893
|
}
|
|
45739
45894
|
}
|
|
45740
|
-
|
|
45741
|
-
|
|
45742
|
-
|
|
45743
|
-
|
|
45744
|
-
|
|
45745
|
-
|
|
45746
|
-
|
|
45895
|
+
if (!this.daemonApi)
|
|
45896
|
+
try {
|
|
45897
|
+
await waitUntilMember(this.agentClientContext(), subchannelId, openingHumanPubkey);
|
|
45898
|
+
} catch (error) {
|
|
45899
|
+
await archiveChannel(agentId, subchannelId).catch((archiveError) => console.error(`[body] failed to archive corner ${subchannelId} after its opening human was not projected:`, archiveError));
|
|
45900
|
+
throw error;
|
|
45901
|
+
}
|
|
45902
|
+
const mirroredParticipantPubkeys = this.daemonApi ? [agentId.publicKey, openingHumanPubkey] : await this.mirrorMembers(tlcChannelId, subchannelId);
|
|
45747
45903
|
const participantPubkeys = [.../* @__PURE__ */ new Set([...mirroredParticipantPubkeys, openingHumanPubkey])];
|
|
45748
45904
|
const worktreePath = boundRepo ? this.cornerWorktreePath(boundRepo, subchannelId) : resolve27(this.config.workspaceRoot, "repoless-corners", subchannelId);
|
|
45749
45905
|
const featureBranch = taskSlug ? `feature/${taskSlug}-${subchannelId.slice(0, 8)}` : `feature/${subchannelId.slice(0, 8)}`;
|
|
@@ -45770,7 +45926,8 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
|
|
|
45770
45926
|
if (cornerMemory) {
|
|
45771
45927
|
mcpServers.push(readOnlyMcpServer(this.config, worktreePath, cornerMemory.dir));
|
|
45772
45928
|
}
|
|
45773
|
-
|
|
45929
|
+
if (!this.daemonApi)
|
|
45930
|
+
mcpServers.push(...await this.authorizedExternalServers(subchannelId));
|
|
45774
45931
|
mcpServers.push(...operatorMcpServersForCorners(this.config.accessPolicy, this.config.operatorMcpServers));
|
|
45775
45932
|
if (boundRepo) {
|
|
45776
45933
|
const codegraphServer = codegraphMcpServer(this.config);
|
|
@@ -45859,32 +46016,42 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
|
|
|
45859
46016
|
["request", request.eventId],
|
|
45860
46017
|
["requester", request.authorPubkey]
|
|
45861
46018
|
] : [];
|
|
45862
|
-
|
|
46019
|
+
const liveText = boundRepo ? `\u{1F916} Agent edit session started \u2014 members mirrored from parent TLC.
|
|
45863
46020
|
Worktree: ${worktreePath}
|
|
45864
46021
|
Branch: ${featureBranch}` : `\u{1F916} Agent repo-less corner started \u2014 members mirrored from parent TLC.
|
|
45865
46022
|
Workspace: ${worktreePath}
|
|
45866
|
-
Deliver artifacts from this corner; there is no branch to land
|
|
45867
|
-
|
|
45868
|
-
|
|
45869
|
-
|
|
45870
|
-
|
|
45871
|
-
|
|
45872
|
-
|
|
45873
|
-
|
|
45874
|
-
|
|
45875
|
-
|
|
45876
|
-
|
|
45877
|
-
["
|
|
45878
|
-
["
|
|
45879
|
-
["
|
|
45880
|
-
["
|
|
45881
|
-
["
|
|
45882
|
-
["
|
|
45883
|
-
["
|
|
45884
|
-
["
|
|
45885
|
-
|
|
45886
|
-
|
|
45887
|
-
|
|
46023
|
+
Deliver artifacts from this corner; there is no branch to land.`;
|
|
46024
|
+
if (this.daemonApi) {
|
|
46025
|
+
await this.daemonApi.execute("postRoomMessage", {
|
|
46026
|
+
roomId: subchannelId,
|
|
46027
|
+
...request ? { requestId: request.eventId } : {},
|
|
46028
|
+
text: liveText,
|
|
46029
|
+
presentation: "system",
|
|
46030
|
+
tags: { type: "corner-session-live", parent: tlcChannelId, status: "live" }
|
|
46031
|
+
});
|
|
46032
|
+
} else
|
|
46033
|
+
await postControlMessage("corner-session-live", subchannelId, agentId, liveText, [
|
|
46034
|
+
["session", session.logicalSessionId],
|
|
46035
|
+
["parent", tlcChannelId],
|
|
46036
|
+
["mode", "edit"],
|
|
46037
|
+
["agent", agentId.publicKey],
|
|
46038
|
+
...repoId ? [["repo", repoId]] : [],
|
|
46039
|
+
...boundRepo ? [["feature", featureBranch]] : [],
|
|
46040
|
+
...boundRepo ? [["branch", targetBranch2]] : [],
|
|
46041
|
+
["status", "live"],
|
|
46042
|
+
...options?.mission ? [
|
|
46043
|
+
["mission", options.mission.missionId],
|
|
46044
|
+
["grant", options.mission.grantEventId],
|
|
46045
|
+
["controller-agent", options.mission.controllerAgentPubkey],
|
|
46046
|
+
["principal", options.mission.principalPubkey],
|
|
46047
|
+
["target-agent", options.mission.targetAgentPubkey],
|
|
46048
|
+
["mission-workspace", options.mission.workspaceId],
|
|
46049
|
+
["mission-room", options.mission.roomId],
|
|
46050
|
+
["mission-repo", options.mission.repository.key],
|
|
46051
|
+
["mission-ref", options.mission.repository.targetBranch]
|
|
46052
|
+
] : [],
|
|
46053
|
+
...requestTags
|
|
46054
|
+
]);
|
|
45888
46055
|
return info;
|
|
45889
46056
|
}
|
|
45890
46057
|
/** Resolve display-only Room speaker labels. These labels never grant authority. */
|
|
@@ -45963,6 +46130,32 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
45963
46130
|
}).room(channelId)).messages;
|
|
45964
46131
|
}
|
|
45965
46132
|
async agentHistory(channelId) {
|
|
46133
|
+
if (this.daemonApi) {
|
|
46134
|
+
const history = await this.daemonApi.execute("getRoomConversation", {
|
|
46135
|
+
roomId: channelId,
|
|
46136
|
+
limit: 200
|
|
46137
|
+
});
|
|
46138
|
+
return history.items.filter((item) => item.type === "message").map((item) => ({
|
|
46139
|
+
type: item.authorId === this.agentIdentity.publicKey ? "agent-message" : "human-message",
|
|
46140
|
+
eventId: item.id,
|
|
46141
|
+
channelId,
|
|
46142
|
+
author: {
|
|
46143
|
+
pubkey: item.authorId,
|
|
46144
|
+
kind: item.authorId === this.agentIdentity.publicKey ? "agent" : "human",
|
|
46145
|
+
label: item.authorId === this.agentIdentity.publicKey ? this.agentIdentity.name : fallbackPersonName(item.authorId)
|
|
46146
|
+
},
|
|
46147
|
+
body: item.body,
|
|
46148
|
+
attachments: item.attachments.map((attachment2) => ({
|
|
46149
|
+
url: attachment2.url,
|
|
46150
|
+
name: attachment2.name ?? "attachment",
|
|
46151
|
+
mimeType: attachment2.mimeType ?? "application/octet-stream",
|
|
46152
|
+
size: attachment2.size ?? 0,
|
|
46153
|
+
...attachment2.thumbnailUrl ? { thumbnailUrl: attachment2.thumbnailUrl } : {}
|
|
46154
|
+
})),
|
|
46155
|
+
createdAt: item.createdAt,
|
|
46156
|
+
provenance: "monolith-verified"
|
|
46157
|
+
}));
|
|
46158
|
+
}
|
|
45966
46159
|
return roomViewConversationHistory(channelId, await this.indexedRoomMessages(channelId));
|
|
45967
46160
|
}
|
|
45968
46161
|
ensureChannelPresenceCache(channelId) {
|
|
@@ -46586,7 +46779,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
46586
46779
|
let addressed = isChannelAddressedMessage(event, this.agentIdentity.publicKey, roomParticipants);
|
|
46587
46780
|
const otherParticipants = new Set(roomParticipants);
|
|
46588
46781
|
otherParticipants.delete(this.agentIdentity.publicKey);
|
|
46589
|
-
if (!addressed && event.kind === 9 && event.pubkey !== this.agentIdentity.publicKey && otherParticipants.size > 1) {
|
|
46782
|
+
if (!addressed && event.kind === 9 && event.pubkey !== this.agentIdentity.publicKey && otherParticipants.size > 1 && event.tags.some((tag) => tag[0] === "e" && tag[1] && tag[3] === "reply")) {
|
|
46590
46783
|
if (!indexedMessagesLoaded) {
|
|
46591
46784
|
indexedMessages = await this.indexedRoomMessages(tlcChannelId);
|
|
46592
46785
|
indexedMessagesLoaded = true;
|
|
@@ -47008,20 +47201,24 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
47008
47201
|
const delegatedReplyTags = this.delegatedReplyTags(request);
|
|
47009
47202
|
if (this.config.modelUnavailable) {
|
|
47010
47203
|
const receiptSessionId = this.sessions.get(tlcChannelId)?.logicalSessionId ?? `${this.agentIdentity.publicKey}:${tlcChannelId}`;
|
|
47011
|
-
|
|
47012
|
-
|
|
47013
|
-
|
|
47014
|
-
|
|
47015
|
-
|
|
47016
|
-
|
|
47017
|
-
|
|
47018
|
-
|
|
47019
|
-
|
|
47204
|
+
if (this.daemonApi) {
|
|
47205
|
+
await this.postTurnStatus(tlcChannelId, request.eventId, receiptSessionId, "failed");
|
|
47206
|
+
} else {
|
|
47207
|
+
await postControlMessage("turn-receipt", tlcChannelId, this.agentIdentity, "", [
|
|
47208
|
+
["t", "agent-turn"],
|
|
47209
|
+
["request", request.eventId],
|
|
47210
|
+
["session", receiptSessionId],
|
|
47211
|
+
["agent", this.agentIdentity.publicKey],
|
|
47212
|
+
["mode", "readonly"],
|
|
47213
|
+
["status", "failed"],
|
|
47214
|
+
...this.presenceGenerations.get(tlcChannelId) ? [["generation", this.presenceGenerations.get(tlcChannelId)]] : []
|
|
47215
|
+
]);
|
|
47216
|
+
}
|
|
47020
47217
|
return { status: "handled", outcome: { openedCorner: false, producedReply: true } };
|
|
47021
47218
|
}
|
|
47022
|
-
if (!scheduled)
|
|
47219
|
+
if (!scheduled && !this.daemonApi)
|
|
47023
47220
|
await this.markSlashCommandVocabulary(tlcChannelId, request.content);
|
|
47024
|
-
const releaseIntent = boundRepo && editPolicy === "repository" && !explicitCornerWork && !scheduled && releaseRoomIntent(request.content);
|
|
47221
|
+
const releaseIntent = !this.daemonApi && boundRepo && editPolicy === "repository" && !explicitCornerWork && !scheduled && releaseRoomIntent(request.content);
|
|
47025
47222
|
const informationOnly = scheduled !== void 0 || agentExchange !== void 0 || releaseIntent !== void 0 || isReadOnlyInformationRequest(request.content);
|
|
47026
47223
|
const requestAuthor = request.authorAttribution ?? (() => {
|
|
47027
47224
|
const name = fallbackPersonName(request.authorPubkey);
|
|
@@ -47093,7 +47290,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
47093
47290
|
async acquireRoomReplySession(tlcChannelId, turn) {
|
|
47094
47291
|
const { request, boundRepo, editPolicy } = turn;
|
|
47095
47292
|
const receiptSessionId = this.sessions.get(tlcChannelId)?.logicalSessionId ?? `${this.agentIdentity.publicKey}:${tlcChannelId}`;
|
|
47096
|
-
await
|
|
47293
|
+
await this.postTurnStatus(tlcChannelId, request.eventId, receiptSessionId, "working");
|
|
47097
47294
|
try {
|
|
47098
47295
|
const session = this.sessions.get(tlcChannelId) ?? await this.provision(tlcChannelId, boundRepo, editPolicy);
|
|
47099
47296
|
if (session.mode !== "readonly") {
|
|
@@ -47101,7 +47298,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
47101
47298
|
}
|
|
47102
47299
|
return { status: "ready", receiptSessionId, session };
|
|
47103
47300
|
} catch (error) {
|
|
47104
|
-
await
|
|
47301
|
+
await this.postTurnStatus(tlcChannelId, request.eventId, receiptSessionId, "failed").catch((statusError) => console.error("[body] failed to replace Room receipt after session start failure:", statusError));
|
|
47105
47302
|
if (!(error instanceof ReadOnlyToolsUnavailableError))
|
|
47106
47303
|
throw error;
|
|
47107
47304
|
console.error(`[body] read-only tools unavailable for Room ${tlcChannelId}:`, error);
|
|
@@ -47197,7 +47394,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
47197
47394
|
} catch (publishError) {
|
|
47198
47395
|
console.error("[body] failed to publish Room reply after corner transition:", publishError);
|
|
47199
47396
|
}
|
|
47200
|
-
await
|
|
47397
|
+
await this.postTurnStatus(tlcChannelId, request.eventId, session.logicalSessionId ?? session.sessionId, "complete");
|
|
47201
47398
|
return { openedCorner: true, producedReply: true };
|
|
47202
47399
|
}
|
|
47203
47400
|
if (!scheduled && !agentExchange && usesTextTargetBranchFallback(this.config.agentCommand ?? this.config.agentBinary)) {
|
|
@@ -47207,7 +47404,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
47207
47404
|
}
|
|
47208
47405
|
if (turn.targetBranchProposalFailed) {
|
|
47209
47406
|
console.log(`[body] room ${tlcChannelId} request ${request.eventId}: target-branch proposal publication failed; leaving the request retryable`);
|
|
47210
|
-
await
|
|
47407
|
+
await this.postTurnStatus(tlcChannelId, request.eventId, session.logicalSessionId ?? session.sessionId, "failed").catch((statusError) => console.error("[body] failed to publish Room turn failure status:", statusError));
|
|
47211
47408
|
return { openedCorner: false, producedReply: false };
|
|
47212
47409
|
}
|
|
47213
47410
|
}
|
|
@@ -47233,17 +47430,17 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
47233
47430
|
}
|
|
47234
47431
|
this.processedRequestIds.add(request.eventId);
|
|
47235
47432
|
await this.durableState.delivered(tlcChannelId, request.eventId);
|
|
47236
|
-
await
|
|
47433
|
+
await this.postTurnStatus(tlcChannelId, request.eventId, session.logicalSessionId ?? session.sessionId, "complete").catch((statusError) => console.error("[body] failed to publish Room turn completion status:", statusError));
|
|
47237
47434
|
return { openedCorner: false, producedReply: Boolean(reply) };
|
|
47238
47435
|
} catch (error) {
|
|
47239
47436
|
if (this.forcedUpdateRestart && promptAttempted && !scheduled) {
|
|
47240
47437
|
return { openedCorner: false, producedReply: false };
|
|
47241
47438
|
}
|
|
47242
47439
|
if (scheduled && error instanceof ScheduleActivationRefusedError) {
|
|
47243
|
-
await
|
|
47440
|
+
await this.postTurnStatus(tlcChannelId, request.eventId, session.logicalSessionId ?? session.sessionId, "failed").catch(() => void 0);
|
|
47244
47441
|
throw error;
|
|
47245
47442
|
}
|
|
47246
|
-
await
|
|
47443
|
+
await this.postTurnStatus(tlcChannelId, request.eventId, session.logicalSessionId ?? session.sessionId, "failed").catch((statusError) => console.error("[body] failed to publish Room turn failure status:", statusError));
|
|
47247
47444
|
if (promptAttempted) {
|
|
47248
47445
|
console.error(`[body] Room turn ${request.eventId} failed:`, error);
|
|
47249
47446
|
this.processedRequestIds.add(request.eventId);
|
|
@@ -47530,6 +47727,13 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
47530
47727
|
return [...new Set(checked.filter((item) => item.human).map((item) => item.pubkey))];
|
|
47531
47728
|
}
|
|
47532
47729
|
async requesterCanOpenCornerDirectly(roomId, requesterPubkey) {
|
|
47730
|
+
if (this.daemonApi) {
|
|
47731
|
+
const authority = await this.daemonApi.execute("getRoomAuthority", {
|
|
47732
|
+
roomId,
|
|
47733
|
+
principalId: requesterPubkey
|
|
47734
|
+
});
|
|
47735
|
+
return authority.member && authority.principalKind === "human" && (authority.role === "owner" || authority.role === "admin");
|
|
47736
|
+
}
|
|
47533
47737
|
const member2 = (await listMembers(this.agentClientContext(), roomId)).find((candidate) => candidate.pubkey === requesterPubkey);
|
|
47534
47738
|
return Boolean(member2 && (member2.role === "owner" || member2.role === "admin") && !await isRegisteredAgentIdentity2(requesterPubkey, this.agentRelay));
|
|
47535
47739
|
}
|
|
@@ -48179,7 +48383,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
48179
48383
|
let preparedMention;
|
|
48180
48384
|
let publishedMentionEvent;
|
|
48181
48385
|
const parentRoomId = info.session.parentChannelId;
|
|
48182
|
-
await this.finishCornerTurn(info, result, "", parentRoomId ? {
|
|
48386
|
+
await this.finishCornerTurn(info, result, "", parentRoomId && !this.daemonApi ? {
|
|
48183
48387
|
extraTagsForText: async (text2) => {
|
|
48184
48388
|
preparedMention = await this.prepareCornerAgentMention({
|
|
48185
48389
|
roomId: parentRoomId,
|
|
@@ -48195,14 +48399,14 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
48195
48399
|
}
|
|
48196
48400
|
} : {});
|
|
48197
48401
|
await this.completeCornerPlan(info.session);
|
|
48198
|
-
await
|
|
48402
|
+
await this.postTurnStatus(info.subchannelId, requestId, sessionId, "complete");
|
|
48199
48403
|
if (preparedMention && publishedMentionEvent) {
|
|
48200
48404
|
await this.finishCornerAgentMention(preparedMention, publishedMentionEvent);
|
|
48201
48405
|
}
|
|
48202
48406
|
} catch (error) {
|
|
48203
48407
|
if (info.archived)
|
|
48204
48408
|
return;
|
|
48205
|
-
await
|
|
48409
|
+
await this.postTurnStatus(info.subchannelId, requestId, sessionId, "failed").catch(() => void 0);
|
|
48206
48410
|
} finally {
|
|
48207
48411
|
this.runningAgentTasks.delete(info.subchannelId);
|
|
48208
48412
|
await this.observeOneCornerRemote(info).catch((error) => console.error(`[body] corner ${info.subchannelId} completion observation failed:`, error));
|
|
@@ -48219,6 +48423,15 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
48219
48423
|
return false;
|
|
48220
48424
|
this.publishingFailureFacts.add(coordinate);
|
|
48221
48425
|
try {
|
|
48426
|
+
if (this.daemonApi) {
|
|
48427
|
+
await this.daemonApi.execute("postRoomMessage", {
|
|
48428
|
+
roomId: channelId,
|
|
48429
|
+
text: content,
|
|
48430
|
+
presentation: "system",
|
|
48431
|
+
tags: Object.fromEntries(tags.filter((tag) => tag[0] && tag[1]))
|
|
48432
|
+
});
|
|
48433
|
+
return true;
|
|
48434
|
+
}
|
|
48222
48435
|
const existing = await this.agentRelay.queryEvents([
|
|
48223
48436
|
{
|
|
48224
48437
|
kinds: [9],
|
|
@@ -48521,8 +48734,8 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
48521
48734
|
release = lease.release;
|
|
48522
48735
|
this.roomSockets.set(channelId, client);
|
|
48523
48736
|
let finishWait = () => void 0;
|
|
48524
|
-
const socketClosed = new Promise((
|
|
48525
|
-
finishWait =
|
|
48737
|
+
const socketClosed = new Promise((resolve45) => {
|
|
48738
|
+
finishWait = resolve45;
|
|
48526
48739
|
});
|
|
48527
48740
|
offClose = client.onSocketClose(finishWait);
|
|
48528
48741
|
const onAbort = () => finishWait();
|
|
@@ -48603,6 +48816,77 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
48603
48816
|
}
|
|
48604
48817
|
}
|
|
48605
48818
|
}
|
|
48819
|
+
async runMonolithRoomLoop(channelId, boundRepo, editPolicy, opts) {
|
|
48820
|
+
const api = this.daemonApi;
|
|
48821
|
+
let cursor3 = await this.durableState.daemonInboxCursor(channelId);
|
|
48822
|
+
await api.execute("postAgentPresence", {
|
|
48823
|
+
agentId: this.agentIdentity.publicKey,
|
|
48824
|
+
roomId: channelId,
|
|
48825
|
+
status: this.config.modelUnavailable ? "offline" : "online"
|
|
48826
|
+
});
|
|
48827
|
+
if (!cursor3) {
|
|
48828
|
+
const activation = await api.execute("getRoomInbox", {
|
|
48829
|
+
roomId: channelId,
|
|
48830
|
+
startAtLatest: true
|
|
48831
|
+
});
|
|
48832
|
+
if (activation.cursor) {
|
|
48833
|
+
cursor3 = activation.cursor;
|
|
48834
|
+
await this.durableState.setDaemonInboxCursor(channelId, cursor3);
|
|
48835
|
+
}
|
|
48836
|
+
}
|
|
48837
|
+
while (!opts.signal?.aborted && !this.disposed) {
|
|
48838
|
+
try {
|
|
48839
|
+
const inbox = await api.execute("getRoomInbox", {
|
|
48840
|
+
roomId: channelId,
|
|
48841
|
+
...cursor3 ? { after: cursor3 } : {},
|
|
48842
|
+
limit: 200
|
|
48843
|
+
});
|
|
48844
|
+
for (const item of inbox.items) {
|
|
48845
|
+
if (item.authorId === this.agentIdentity.publicKey || item.type !== "message" || item.mentionIds.length > 0 && !item.mentionIds.includes(this.agentIdentity.publicKey) || this.processedRequestIds.has(item.id))
|
|
48846
|
+
continue;
|
|
48847
|
+
const authority = await api.execute("getRoomAuthority", {
|
|
48848
|
+
roomId: channelId,
|
|
48849
|
+
principalId: item.authorId
|
|
48850
|
+
});
|
|
48851
|
+
if (!authority.member || authority.principalKind !== "human")
|
|
48852
|
+
continue;
|
|
48853
|
+
if (!this.senderAccessAllowed(item.authorId))
|
|
48854
|
+
continue;
|
|
48855
|
+
const attachments = item.attachments.map((attachment2) => ({
|
|
48856
|
+
url: attachment2.url,
|
|
48857
|
+
name: attachment2.name ?? "attachment",
|
|
48858
|
+
mimeType: attachment2.mimeType ?? "application/octet-stream",
|
|
48859
|
+
size: attachment2.size ?? 0,
|
|
48860
|
+
...attachment2.thumbnailUrl ? { thumbnailUrl: attachment2.thumbnailUrl } : {}
|
|
48861
|
+
}));
|
|
48862
|
+
const request = {
|
|
48863
|
+
eventId: item.id,
|
|
48864
|
+
authorPubkey: item.authorId,
|
|
48865
|
+
content: item.body.trim(),
|
|
48866
|
+
attachments,
|
|
48867
|
+
createdAt: item.createdAt,
|
|
48868
|
+
...item.rootMessageId ? { replyRootId: item.rootMessageId } : {}
|
|
48869
|
+
};
|
|
48870
|
+
const workIntent = !isReadOnlyInformationRequest(item.body);
|
|
48871
|
+
const outcome = await this.replyInRoom(channelId, boundRepo, request, editPolicy === "repository" && workIntent, editPolicy, void 0, workIntent);
|
|
48872
|
+
if (outcome.producedReply)
|
|
48873
|
+
this.processedRequestIds.add(item.id);
|
|
48874
|
+
}
|
|
48875
|
+
if (inbox.cursor) {
|
|
48876
|
+
cursor3 = inbox.cursor;
|
|
48877
|
+
await this.durableState.setDaemonInboxCursor(channelId, cursor3);
|
|
48878
|
+
}
|
|
48879
|
+
this.onRoomPollSuccess?.(channelId);
|
|
48880
|
+
await this.waitForPoll(opts.pollMs ?? 1e3, opts.signal);
|
|
48881
|
+
} catch (error) {
|
|
48882
|
+
if (opts.signal?.aborted || this.disposed)
|
|
48883
|
+
break;
|
|
48884
|
+
this.onRoomPollFailure?.(channelId, 1e3);
|
|
48885
|
+
console.error(`[body] monolith Room ${channelId} poll failed:`, error);
|
|
48886
|
+
await this.waitForPoll(1e3, opts.signal);
|
|
48887
|
+
}
|
|
48888
|
+
}
|
|
48889
|
+
}
|
|
48606
48890
|
/** One long-running body loop owns request discovery, steering, and merge closure. */
|
|
48607
48891
|
async runChannelLoop(tlcChannelId, boundRepo, opts = {}) {
|
|
48608
48892
|
await this.channelCommunityId(tlcChannelId).then((communityId) => communityId ? this.syncModelSelectionToRelay(communityId) : void 0).catch((error) => console.error("[body] model catalog sync failed:", error));
|
|
@@ -48628,6 +48912,10 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
48628
48912
|
}
|
|
48629
48913
|
/** Durable loop for DMs and ordinary Rooms that have no repository binding. */
|
|
48630
48914
|
async runConversationRoomLoop(channelId, editPolicy, opts = {}) {
|
|
48915
|
+
if (this.daemonApi) {
|
|
48916
|
+
await this.runMonolithRoomLoop(channelId, void 0, editPolicy, opts);
|
|
48917
|
+
return;
|
|
48918
|
+
}
|
|
48631
48919
|
await this.channelCommunityId(channelId).then((communityId) => communityId ? this.syncModelSelectionToRelay(communityId) : void 0).catch((error) => console.error("[body] model selection sync failed:", error));
|
|
48632
48920
|
const stopPresence = startAgentPresence(channelId, this.agentIdentity, void 0, (status) => this.onRoomPresence?.(channelId, status), this.config.modelUnavailable ? "offline" : "online", {
|
|
48633
48921
|
policy: this.config.accessPolicy ?? LEGACY_ACCESS_POLICY,
|
|
@@ -48649,6 +48937,11 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
48649
48937
|
}
|
|
48650
48938
|
/** Durable paired-agent loop for the repository's single Workspace Room. */
|
|
48651
48939
|
async runRepositoryRoomLoop(communityId, channelId, boundRepo, opts = {}) {
|
|
48940
|
+
if (this.daemonApi) {
|
|
48941
|
+
await this.assertRepositorySafety(channelId, boundRepo);
|
|
48942
|
+
await this.runMonolithRoomLoop(channelId, boundRepo, "repository", opts);
|
|
48943
|
+
return;
|
|
48944
|
+
}
|
|
48652
48945
|
if (!boundRepo.repositoryKey)
|
|
48653
48946
|
throw new Error("paired Room is missing its repository key");
|
|
48654
48947
|
await this.syncModelSelectionToRelay(communityId).catch((error) => console.error("[body] model selection sync failed:", error));
|
|
@@ -49035,6 +49328,8 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
49035
49328
|
}
|
|
49036
49329
|
}
|
|
49037
49330
|
async observeOneCornerRemote(info, githubEventId) {
|
|
49331
|
+
if (this.daemonApi)
|
|
49332
|
+
return;
|
|
49038
49333
|
if (info.archived || !info.boundRepo || !info.featureBranch || !info.boundRepo.truth?.binding.remote?.startsWith("git://github.com/"))
|
|
49039
49334
|
return;
|
|
49040
49335
|
if (this.observingCornerRemotes.has(info.subchannelId))
|
|
@@ -49805,6 +50100,14 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
49805
50100
|
const fallback = shortBranchName(boundRepo.targetBranch);
|
|
49806
50101
|
const confirmed = this.confirmedRoomTargetBranches.get(channelId);
|
|
49807
50102
|
try {
|
|
50103
|
+
if (this.daemonApi) {
|
|
50104
|
+
const config2 = await this.daemonApi.execute("getRoomTargetBranch", {
|
|
50105
|
+
roomId: channelId
|
|
50106
|
+
});
|
|
50107
|
+
const branch2 = shortBranchName(config2.targetBranch);
|
|
50108
|
+
this.confirmedRoomTargetBranches.set(channelId, branch2);
|
|
50109
|
+
return branch2;
|
|
50110
|
+
}
|
|
49808
50111
|
const config = await getRoomRepository(this.agentClientContext(), channelId);
|
|
49809
50112
|
if (!config?.targetBranch)
|
|
49810
50113
|
return confirmed ?? fallback;
|
|
@@ -49845,15 +50148,24 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
49845
50148
|
void announceNoop;
|
|
49846
50149
|
return false;
|
|
49847
50150
|
}
|
|
49848
|
-
|
|
49849
|
-
|
|
49850
|
-
|
|
49851
|
-
|
|
49852
|
-
|
|
49853
|
-
|
|
49854
|
-
|
|
49855
|
-
|
|
49856
|
-
|
|
50151
|
+
if (this.daemonApi) {
|
|
50152
|
+
await this.daemonApi.execute("postTargetBranchProposal", {
|
|
50153
|
+
roomId: tlcChannelId,
|
|
50154
|
+
requestId: request.eventId,
|
|
50155
|
+
from,
|
|
50156
|
+
to: branch,
|
|
50157
|
+
repository: this.repoId(boundRepo)
|
|
50158
|
+
});
|
|
50159
|
+
} else
|
|
50160
|
+
await postControlMessage("target-branch-proposal", tlcChannelId, this.agentIdentity, targetBranchProposalText(from, branch), [
|
|
50161
|
+
["t", TARGET_BRANCH_PROPOSAL_TAG],
|
|
50162
|
+
["from", from],
|
|
50163
|
+
["to", branch],
|
|
50164
|
+
["repo", this.repoId(boundRepo)],
|
|
50165
|
+
["agent", this.agentIdentity.publicKey],
|
|
50166
|
+
["request", request.eventId],
|
|
50167
|
+
["requester", request.authorPubkey]
|
|
50168
|
+
]);
|
|
49857
50169
|
return true;
|
|
49858
50170
|
}
|
|
49859
50171
|
agentClientContext() {
|
|
@@ -49868,6 +50180,13 @@ Deliver artifacts from this corner; there is no branch to land.`, [
|
|
|
49868
50180
|
}
|
|
49869
50181
|
/** Resolve the parent channel's optional community linkage. */
|
|
49870
50182
|
async channelCommunityId(channelId) {
|
|
50183
|
+
if (this.daemonApi) {
|
|
50184
|
+
const authority = await this.daemonApi.execute("getRoomAuthority", {
|
|
50185
|
+
roomId: channelId,
|
|
50186
|
+
principalId: this.agentIdentity.publicKey
|
|
50187
|
+
});
|
|
50188
|
+
return authority.member ? authority.workspaceId : null;
|
|
50189
|
+
}
|
|
49871
50190
|
const creates = await this.agentRelay.queryEvents([
|
|
49872
50191
|
{ kinds: [9007], "#h": [channelId], limit: 5 }
|
|
49873
50192
|
]);
|
|
@@ -50571,6 +50890,24 @@ import { basename as basename9, dirname as dirname11, isAbsolute as isAbsolute10
|
|
|
50571
50890
|
import { spawn as spawn8, spawnSync as spawnSync2, execFile } from "node:child_process";
|
|
50572
50891
|
import { promisify } from "node:util";
|
|
50573
50892
|
var execFileAsync = promisify(execFile);
|
|
50893
|
+
function isMonolithTransport(value) {
|
|
50894
|
+
if (typeof value !== "object" || value === null)
|
|
50895
|
+
return false;
|
|
50896
|
+
const candidate = value;
|
|
50897
|
+
if (candidate.kind !== "monolith" || typeof candidate.baseUrl !== "string")
|
|
50898
|
+
return false;
|
|
50899
|
+
let origin;
|
|
50900
|
+
try {
|
|
50901
|
+
origin = new URL(candidate.baseUrl);
|
|
50902
|
+
} catch {
|
|
50903
|
+
return false;
|
|
50904
|
+
}
|
|
50905
|
+
if (origin.protocol !== "https:" && origin.protocol !== "http:" || origin.username || origin.password || origin.pathname && origin.pathname !== "/" || origin.search || origin.hash || origin.origin !== candidate.baseUrl)
|
|
50906
|
+
return false;
|
|
50907
|
+
const exchange = candidate.exchangeToken;
|
|
50908
|
+
const daemon = candidate.daemonToken;
|
|
50909
|
+
return typeof exchange === "string" && /^bde_[A-Za-z0-9_-]{43}$/.test(exchange) && daemon === void 0 || typeof daemon === "string" && /^bdt_[A-Za-z0-9_-]{43}$/.test(daemon) && exchange === void 0;
|
|
50910
|
+
}
|
|
50574
50911
|
function runtimeAgentCommand(runtime) {
|
|
50575
50912
|
const command = runtime.agentCommand ?? runtime.agentBinary;
|
|
50576
50913
|
const inferredKind = command.endsWith("/buzz-agent") || command === "buzz-agent" ? "reference" : "custom";
|
|
@@ -50906,7 +51243,7 @@ async function readRuntimeRecord(path) {
|
|
|
50906
51243
|
createdAt: parsed.createdAt
|
|
50907
51244
|
};
|
|
50908
51245
|
}
|
|
50909
|
-
if (parsed.version !== 2 || !parsed.communityId || !parsed.supervisorRoot || !Array.isArray(parsed.rooms) || parsed.rooms.some((room) => !room.channelId || !room.repo?.root || room.root !== void 0 && (typeof room.root !== "string" || !room.root)) || parsed.agentKind !== void 0 && !AGENT_KINDS.includes(parsed.agentKind) || parsed.accessPolicy !== void 0 && !isAgentAccessPolicy(parsed.accessPolicy) || parsed.accessAllowlist !== void 0 && !isAgentAccessAllowlist(parsed.accessAllowlist) || parsed.accessPolicy === "allowlist" && !isAgentAccessAllowlist(parsed.accessAllowlist) || parsed.accessPolicy !== "allowlist" && parsed.accessAllowlist !== void 0 || parsed.accessAutoResponse !== void 0 && typeof parsed.accessAutoResponse !== "string" || parsed.externalMcpCapabilities !== void 0 && (!Array.isArray(parsed.externalMcpCapabilities) || parsed.externalMcpCapabilities.some((capability) => !isExternalMcpCapability(capability)) || parsed.accessPolicy !== "creator") || parsed.sandbox !== void 0 && !isSandboxPolicy(parsed.sandbox) || parsed.sandboxMaskPaths !== void 0 && (!Array.isArray(parsed.sandboxMaskPaths) || parsed.sandboxMaskPaths.some((path2) => typeof path2 !== "string" || !path2.trim())) || parsed.sharedSkills !== void 0 && (!Array.isArray(parsed.sharedSkills) || parsed.sharedSkills.some((name) => !isSharedSkillName(name)) || new Set(parsed.sharedSkills).size !== parsed.sharedSkills.length) || parsed.modelSelection !== void 0 && (typeof parsed.modelSelection !== "object" || parsed.modelSelection === null || parsed.modelSelection.model !== void 0 && typeof parsed.modelSelection.model !== "string" || parsed.modelSelection.effort !== void 0 && typeof parsed.modelSelection.effort !== "string") || parsed.agentCommand !== void 0 && !parsed.agentCommand || parsed.agentArgs !== void 0 && (!Array.isArray(parsed.agentArgs) || parsed.agentArgs.some((argument) => typeof argument !== "string"))) {
|
|
51246
|
+
if (parsed.version !== 2 || !parsed.communityId || !parsed.supervisorRoot || !Array.isArray(parsed.rooms) || parsed.rooms.some((room) => !room.channelId || !room.repo?.root || room.root !== void 0 && (typeof room.root !== "string" || !room.root)) || parsed.agentKind !== void 0 && !AGENT_KINDS.includes(parsed.agentKind) || parsed.accessPolicy !== void 0 && !isAgentAccessPolicy(parsed.accessPolicy) || parsed.accessAllowlist !== void 0 && !isAgentAccessAllowlist(parsed.accessAllowlist) || parsed.accessPolicy === "allowlist" && !isAgentAccessAllowlist(parsed.accessAllowlist) || parsed.accessPolicy !== "allowlist" && parsed.accessAllowlist !== void 0 || parsed.accessAutoResponse !== void 0 && typeof parsed.accessAutoResponse !== "string" || parsed.externalMcpCapabilities !== void 0 && (!Array.isArray(parsed.externalMcpCapabilities) || parsed.externalMcpCapabilities.some((capability) => !isExternalMcpCapability(capability)) || parsed.accessPolicy !== "creator") || parsed.sandbox !== void 0 && !isSandboxPolicy(parsed.sandbox) || parsed.sandboxMaskPaths !== void 0 && (!Array.isArray(parsed.sandboxMaskPaths) || parsed.sandboxMaskPaths.some((path2) => typeof path2 !== "string" || !path2.trim())) || parsed.sharedSkills !== void 0 && (!Array.isArray(parsed.sharedSkills) || parsed.sharedSkills.some((name) => !isSharedSkillName(name)) || new Set(parsed.sharedSkills).size !== parsed.sharedSkills.length) || parsed.modelSelection !== void 0 && (typeof parsed.modelSelection !== "object" || parsed.modelSelection === null || parsed.modelSelection.model !== void 0 && typeof parsed.modelSelection.model !== "string" || parsed.modelSelection.effort !== void 0 && typeof parsed.modelSelection.effort !== "string") || parsed.transport !== void 0 && !isMonolithTransport(parsed.transport) || parsed.agentCommand !== void 0 && !parsed.agentCommand || parsed.agentArgs !== void 0 && (!Array.isArray(parsed.agentArgs) || parsed.agentArgs.some((argument) => typeof argument !== "string"))) {
|
|
50910
51247
|
throw new Error(`invalid agent runtime config: ${configPath}`);
|
|
50911
51248
|
}
|
|
50912
51249
|
runtimeIdentity(parsed.agent);
|
|
@@ -52832,6 +53169,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
52832
53169
|
* NIP-01 subId onto it, instead of opening ~N+1 sockets on one agent pubkey.
|
|
52833
53170
|
*/
|
|
52834
53171
|
relaySocket;
|
|
53172
|
+
daemonApi;
|
|
52835
53173
|
repositoryTruth;
|
|
52836
53174
|
githubApp;
|
|
52837
53175
|
namedRepositoryResolutions = /* @__PURE__ */ new Map();
|
|
@@ -52878,13 +53216,16 @@ var RoomRuntimeCoordinator = class {
|
|
|
52878
53216
|
idleMs: Number(process.env.BUZZY_BODY_SESSION_IDLE_MS ?? String(5 * 6e4)),
|
|
52879
53217
|
reserveInteractiveSlot: true
|
|
52880
53218
|
});
|
|
52881
|
-
this.
|
|
52882
|
-
|
|
52883
|
-
|
|
52884
|
-
|
|
52885
|
-
|
|
52886
|
-
|
|
52887
|
-
|
|
53219
|
+
this.daemonApi = options.daemonApi;
|
|
53220
|
+
if (!this.daemonApi) {
|
|
53221
|
+
this.relaySocket = options.relaySocket ?? new SharedRelaySocket({
|
|
53222
|
+
baseUrl: runtime.relayBaseUrl,
|
|
53223
|
+
...runtime.relayHost ? { host: runtime.relayHost } : {},
|
|
53224
|
+
...baseConfig.relayWsUrl ? { wsUrl: baseConfig.relayWsUrl } : {},
|
|
53225
|
+
identity: this.agent,
|
|
53226
|
+
WebSocketImpl: wrapper_default
|
|
53227
|
+
});
|
|
53228
|
+
}
|
|
52888
53229
|
this.githubApp = GitHubAppRuntime.fromEnvironment(process.env, {
|
|
52889
53230
|
baseUrl: runtime.relayBaseUrl,
|
|
52890
53231
|
identity: this.agent
|
|
@@ -53046,6 +53387,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
53046
53387
|
await client.syncAgentDeclaration(this.runtime.communityId, { displayName });
|
|
53047
53388
|
}
|
|
53048
53389
|
async reconcile() {
|
|
53390
|
+
if (this.daemonApi)
|
|
53391
|
+
return this.reconcileMonolith();
|
|
53049
53392
|
const client = createBuzzClient({
|
|
53050
53393
|
baseUrl: this.runtime.relayBaseUrl,
|
|
53051
53394
|
...this.runtime.relayHost ? { host: this.runtime.relayHost } : {},
|
|
@@ -53227,6 +53570,45 @@ var RoomRuntimeCoordinator = class {
|
|
|
53227
53570
|
client.disconnect();
|
|
53228
53571
|
}
|
|
53229
53572
|
}
|
|
53573
|
+
async reconcileMonolith() {
|
|
53574
|
+
const bootstrap = await this.daemonApi.execute("getDaemonBootstrap", {
|
|
53575
|
+
agentId: this.agent.publicKey
|
|
53576
|
+
});
|
|
53577
|
+
if (!bootstrap.workspaceIds.includes(this.runtime.communityId)) {
|
|
53578
|
+
this.workspaceRemovalConfirmations += 1;
|
|
53579
|
+
if (this.workspaceRemovalConfirmations < REMOVAL_CONFIRMATION_READS) {
|
|
53580
|
+
this.confirmationPending = true;
|
|
53581
|
+
return "unknown";
|
|
53582
|
+
}
|
|
53583
|
+
return "not-member";
|
|
53584
|
+
}
|
|
53585
|
+
this.workspaceRemovalConfirmations = 0;
|
|
53586
|
+
const desired = new Map(bootstrap.rooms.filter((room) => !room.archived).map((room) => [room.roomId, room]));
|
|
53587
|
+
for (const channelId of desired.keys())
|
|
53588
|
+
this.roomRemovalConfirmations.delete(channelId);
|
|
53589
|
+
for (const [channelId, running] of [...this.running]) {
|
|
53590
|
+
if (desired.has(channelId))
|
|
53591
|
+
continue;
|
|
53592
|
+
const confirmations = (this.roomRemovalConfirmations.get(channelId) ?? 0) + 1;
|
|
53593
|
+
this.roomRemovalConfirmations.set(channelId, confirmations);
|
|
53594
|
+
if (confirmations < REMOVAL_CONFIRMATION_READS) {
|
|
53595
|
+
this.confirmationPending = true;
|
|
53596
|
+
continue;
|
|
53597
|
+
}
|
|
53598
|
+
running.controller.abort();
|
|
53599
|
+
await running.promise.catch(() => void 0);
|
|
53600
|
+
}
|
|
53601
|
+
await mapWithConcurrency([...desired.keys()], ROOM_JOIN_CONCURRENCY, async (channelId) => {
|
|
53602
|
+
if (this.running.has(channelId))
|
|
53603
|
+
return;
|
|
53604
|
+
const known = this.runtime.rooms.find((room) => room.channelId === channelId);
|
|
53605
|
+
if (known)
|
|
53606
|
+
await this.startRepositoryRoom(known, channelId);
|
|
53607
|
+
else
|
|
53608
|
+
this.startConversationRoom(channelId, "named-repository");
|
|
53609
|
+
});
|
|
53610
|
+
return "member";
|
|
53611
|
+
}
|
|
53230
53612
|
/**
|
|
53231
53613
|
* Record the relay's terminal `channel is archived` verdict for one Room:
|
|
53232
53614
|
* logged once, then the Room is held inert — dropped from serving for the
|
|
@@ -53333,7 +53715,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
53333
53715
|
};
|
|
53334
53716
|
const body = new Body(config, runtimeIdentity(this.runtime.body), this.agent, {
|
|
53335
53717
|
scheduler: this.scheduler,
|
|
53336
|
-
relaySocket: this.relaySocket,
|
|
53718
|
+
...this.relaySocket ? { relaySocket: this.relaySocket } : {},
|
|
53719
|
+
...this.daemonApi ? { daemonApi: this.daemonApi } : {},
|
|
53337
53720
|
statePath: resolve30(workspaceRoot, "body-state.json"),
|
|
53338
53721
|
resolveNamedRepository: (target) => this.resolveNamedRepository(channelId, target),
|
|
53339
53722
|
refreshRepositoryTruth: (repo, checkpoint) => this.refreshBoundRepo(repo, checkpoint),
|
|
@@ -53379,7 +53762,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
53379
53762
|
const startedAt = this.now();
|
|
53380
53763
|
const body = new Body(config, runtimeIdentity(this.runtime.body), this.agent, {
|
|
53381
53764
|
scheduler: this.scheduler,
|
|
53382
|
-
relaySocket: this.relaySocket,
|
|
53765
|
+
...this.relaySocket ? { relaySocket: this.relaySocket } : {},
|
|
53766
|
+
...this.daemonApi ? { daemonApi: this.daemonApi } : {},
|
|
53383
53767
|
statePath: resolve30(workspaceRoot, "body-state.json"),
|
|
53384
53768
|
resolveNamedRepository: (target) => this.resolveNamedRepository(channelId, target),
|
|
53385
53769
|
onRoomPollSuccess: () => this.notePoll(channelId),
|
|
@@ -54156,29 +54540,41 @@ async function waitForNextTick(ms, signal) {
|
|
|
54156
54540
|
var ThinDaemonCore = class {
|
|
54157
54541
|
agent;
|
|
54158
54542
|
relaySocket;
|
|
54543
|
+
daemonApi;
|
|
54159
54544
|
roomRuntime;
|
|
54160
54545
|
workCalendar;
|
|
54161
54546
|
now;
|
|
54162
54547
|
constructor(runtime, configPath, baseConfig, options = {}) {
|
|
54163
54548
|
this.agent = runtimeIdentity(runtime.agent);
|
|
54164
54549
|
this.now = options.now ?? Date.now;
|
|
54165
|
-
this.
|
|
54166
|
-
|
|
54167
|
-
|
|
54168
|
-
|
|
54169
|
-
|
|
54170
|
-
|
|
54171
|
-
|
|
54550
|
+
this.daemonApi = options.daemonApi;
|
|
54551
|
+
if (runtime.transport && !this.daemonApi) {
|
|
54552
|
+
throw new Error("monolith runtime requires an activated daemon API client");
|
|
54553
|
+
}
|
|
54554
|
+
if (!runtime.transport) {
|
|
54555
|
+
this.relaySocket = new SharedRelaySocket({
|
|
54556
|
+
baseUrl: runtime.relayBaseUrl,
|
|
54557
|
+
...runtime.relayHost ? { host: runtime.relayHost } : {},
|
|
54558
|
+
...baseConfig.relayWsUrl ? { wsUrl: baseConfig.relayWsUrl } : {},
|
|
54559
|
+
identity: this.agent,
|
|
54560
|
+
WebSocketImpl: wrapper_default
|
|
54561
|
+
});
|
|
54562
|
+
}
|
|
54172
54563
|
this.roomRuntime = new RoomRuntimeCoordinator(runtime, configPath, baseConfig, {
|
|
54173
54564
|
...options,
|
|
54174
|
-
relaySocket: this.relaySocket
|
|
54565
|
+
...this.relaySocket ? { relaySocket: this.relaySocket } : {},
|
|
54566
|
+
...this.daemonApi ? { daemonApi: this.daemonApi } : {}
|
|
54175
54567
|
});
|
|
54176
|
-
this.workCalendar = options.workCalendar ??
|
|
54568
|
+
this.workCalendar = options.workCalendar ?? (this.daemonApi ? {
|
|
54569
|
+
start: async () => void 0,
|
|
54570
|
+
dispose: async () => void 0,
|
|
54571
|
+
refreshNow: async () => void 0
|
|
54572
|
+
} : createDaemonWorkCalendar({
|
|
54177
54573
|
runtime,
|
|
54178
54574
|
configPath,
|
|
54179
54575
|
roomRuntime: this.roomRuntime,
|
|
54180
54576
|
nowMs: this.now
|
|
54181
|
-
});
|
|
54577
|
+
}));
|
|
54182
54578
|
if (this.workCalendar.runNow) {
|
|
54183
54579
|
this.roomRuntime.setScheduleRunNow((scheduleId) => this.workCalendar.runNow(scheduleId));
|
|
54184
54580
|
}
|
|
@@ -54215,20 +54611,24 @@ var ThinDaemonCore = class {
|
|
|
54215
54611
|
let calendarState = "idle";
|
|
54216
54612
|
await opts.onEstablished?.();
|
|
54217
54613
|
try {
|
|
54218
|
-
|
|
54219
|
-
|
|
54220
|
-
|
|
54221
|
-
|
|
54222
|
-
|
|
54223
|
-
|
|
54224
|
-
|
|
54225
|
-
|
|
54226
|
-
|
|
54227
|
-
|
|
54228
|
-
|
|
54229
|
-
|
|
54230
|
-
|
|
54231
|
-
|
|
54614
|
+
if (!this.relaySocket) {
|
|
54615
|
+
degraded = "";
|
|
54616
|
+
} else {
|
|
54617
|
+
const client = await this.relaySocket.connected();
|
|
54618
|
+
const socket = client.socket;
|
|
54619
|
+
if (!socket)
|
|
54620
|
+
throw new Error("control-plane WS connected but exposed no socket");
|
|
54621
|
+
unsubscribeControl = socket.subscribe([
|
|
54622
|
+
{
|
|
54623
|
+
kinds: [KIND_PUT_USER, KIND_REMOVE_USER],
|
|
54624
|
+
"#p": [this.agent.publicKey],
|
|
54625
|
+
since: Math.floor(this.now() / 1e3)
|
|
54626
|
+
}
|
|
54627
|
+
], () => {
|
|
54628
|
+
wake = true;
|
|
54629
|
+
});
|
|
54630
|
+
degraded = "";
|
|
54631
|
+
}
|
|
54232
54632
|
} catch (error) {
|
|
54233
54633
|
degraded = `relay control socket degraded: ${error instanceof Error ? error.message : String(error)}`;
|
|
54234
54634
|
console.error(`[thin-core] control-plane WS unavailable; relying on the ${this.roomRuntime.reconcileHeartbeatIntervalMs()}ms heartbeat poll:`, error);
|
|
@@ -54271,11 +54671,106 @@ var ThinDaemonCore = class {
|
|
|
54271
54671
|
unsubscribeControl?.();
|
|
54272
54672
|
await this.workCalendar.dispose();
|
|
54273
54673
|
await this.roomRuntime.shutdown();
|
|
54274
|
-
this.relaySocket
|
|
54674
|
+
this.relaySocket?.disconnect();
|
|
54275
54675
|
}
|
|
54276
54676
|
}
|
|
54277
54677
|
};
|
|
54278
54678
|
|
|
54679
|
+
// apps/body/dist/daemon-api-client.js
|
|
54680
|
+
import { resolve as resolve32 } from "node:path";
|
|
54681
|
+
var DaemonApiError = class extends Error {
|
|
54682
|
+
status;
|
|
54683
|
+
retryable;
|
|
54684
|
+
constructor(message2, status, retryable) {
|
|
54685
|
+
super(message2);
|
|
54686
|
+
this.status = status;
|
|
54687
|
+
this.retryable = retryable;
|
|
54688
|
+
this.name = "DaemonApiError";
|
|
54689
|
+
}
|
|
54690
|
+
};
|
|
54691
|
+
function endpoint(origin, path) {
|
|
54692
|
+
return new URL(path, `${origin}/`).toString();
|
|
54693
|
+
}
|
|
54694
|
+
async function responseError(response) {
|
|
54695
|
+
let code = "request_failed";
|
|
54696
|
+
try {
|
|
54697
|
+
const value = await response.json();
|
|
54698
|
+
if (typeof value.error === "string" && value.error)
|
|
54699
|
+
code = value.error;
|
|
54700
|
+
} catch {
|
|
54701
|
+
}
|
|
54702
|
+
return new DaemonApiError(`monolith daemon request failed (${response.status}: ${code})`, response.status, response.status === 408 || response.status === 429 || response.status >= 500);
|
|
54703
|
+
}
|
|
54704
|
+
var DaemonApiClient = class {
|
|
54705
|
+
baseUrl;
|
|
54706
|
+
daemonToken;
|
|
54707
|
+
agentId;
|
|
54708
|
+
fetchImpl;
|
|
54709
|
+
constructor(baseUrl, daemonToken, agentId, fetchImpl = fetch) {
|
|
54710
|
+
this.baseUrl = baseUrl;
|
|
54711
|
+
this.daemonToken = daemonToken;
|
|
54712
|
+
this.agentId = agentId;
|
|
54713
|
+
this.fetchImpl = fetchImpl;
|
|
54714
|
+
}
|
|
54715
|
+
async execute(name, input) {
|
|
54716
|
+
const candidate = input;
|
|
54717
|
+
if (typeof candidate.agentId === "string" && candidate.agentId !== this.agentId) {
|
|
54718
|
+
throw new Error("daemon operation agentId does not match the runtime identity");
|
|
54719
|
+
}
|
|
54720
|
+
const response = await this.fetchImpl(endpoint(this.baseUrl, `/v1/daemon/operations/${String(name)}`), {
|
|
54721
|
+
method: "POST",
|
|
54722
|
+
headers: {
|
|
54723
|
+
authorization: `Bearer ${this.daemonToken}`,
|
|
54724
|
+
"content-type": "application/json"
|
|
54725
|
+
},
|
|
54726
|
+
body: JSON.stringify(input)
|
|
54727
|
+
});
|
|
54728
|
+
if (!response.ok)
|
|
54729
|
+
throw await responseError(response);
|
|
54730
|
+
return await response.json();
|
|
54731
|
+
}
|
|
54732
|
+
};
|
|
54733
|
+
async function activateDaemonTransport(path, fetchImpl = fetch) {
|
|
54734
|
+
const runtime = await readRuntimeRecord(path);
|
|
54735
|
+
const expectedPath = resolve32(runtimeDirectory(runtime.supervisorRoot, runtime.agent.publicKey), "runtime.json");
|
|
54736
|
+
if (resolve32(path) !== expectedPath) {
|
|
54737
|
+
throw new Error(`refusing daemon token exchange outside canonical runtime path: ${path}`);
|
|
54738
|
+
}
|
|
54739
|
+
const transport = runtime.transport;
|
|
54740
|
+
if (!transport)
|
|
54741
|
+
return void 0;
|
|
54742
|
+
if ("daemonToken" in transport && transport.daemonToken) {
|
|
54743
|
+
return {
|
|
54744
|
+
runtime,
|
|
54745
|
+
client: new DaemonApiClient(transport.baseUrl, transport.daemonToken, runtime.agent.publicKey, fetchImpl)
|
|
54746
|
+
};
|
|
54747
|
+
}
|
|
54748
|
+
const response = await fetchImpl(endpoint(transport.baseUrl, "/v1/auth/daemon/exchange"), {
|
|
54749
|
+
method: "POST",
|
|
54750
|
+
headers: { "content-type": "application/json" },
|
|
54751
|
+
body: JSON.stringify({ exchangeToken: transport.exchangeToken })
|
|
54752
|
+
});
|
|
54753
|
+
if (!response.ok)
|
|
54754
|
+
throw await responseError(response);
|
|
54755
|
+
const result = await response.json();
|
|
54756
|
+
if (typeof result.daemonToken !== "string" || !/^bdt_[A-Za-z0-9_-]{43}$/.test(result.daemonToken) || result.agentId !== runtime.agent.publicKey) {
|
|
54757
|
+
throw new Error("daemon token exchange returned an invalid runtime identity");
|
|
54758
|
+
}
|
|
54759
|
+
const promoted = {
|
|
54760
|
+
...runtime,
|
|
54761
|
+
transport: {
|
|
54762
|
+
kind: "monolith",
|
|
54763
|
+
baseUrl: transport.baseUrl,
|
|
54764
|
+
daemonToken: result.daemonToken
|
|
54765
|
+
}
|
|
54766
|
+
};
|
|
54767
|
+
await writeRuntimeRecord(promoted);
|
|
54768
|
+
return {
|
|
54769
|
+
runtime: promoted,
|
|
54770
|
+
client: new DaemonApiClient(transport.baseUrl, result.daemonToken, runtime.agent.publicKey, fetchImpl)
|
|
54771
|
+
};
|
|
54772
|
+
}
|
|
54773
|
+
|
|
54279
54774
|
// apps/body/dist/relay-command.js
|
|
54280
54775
|
var defaults = {
|
|
54281
54776
|
cwd: () => process.cwd(),
|
|
@@ -54356,7 +54851,7 @@ var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
|
54356
54851
|
import { execFile as execFile2 } from "node:child_process";
|
|
54357
54852
|
import { mkdir as mkdir15, readFile as readFile11, writeFile as writeFile9 } from "node:fs/promises";
|
|
54358
54853
|
import { homedir as homedir7 } from "node:os";
|
|
54359
|
-
import { dirname as dirname13, resolve as
|
|
54854
|
+
import { dirname as dirname13, resolve as resolve33 } from "node:path";
|
|
54360
54855
|
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
54361
54856
|
import { promisify as promisify3 } from "node:util";
|
|
54362
54857
|
var execFileAsync2 = promisify3(execFile2);
|
|
@@ -54398,9 +54893,9 @@ WantedBy=default.target
|
|
|
54398
54893
|
}
|
|
54399
54894
|
function isCanonicalInstalledLauncher(env = process.env, invocationPath = process.argv[1]) {
|
|
54400
54895
|
const home = env.HOME?.trim() || homedir7();
|
|
54401
|
-
const expectedLibDir =
|
|
54896
|
+
const expectedLibDir = resolve33(home, ".local", "lib", "beeline");
|
|
54402
54897
|
const expectedPrefix = `${expectedLibDir}/`;
|
|
54403
|
-
return
|
|
54898
|
+
return resolve33(env.BEELINE_LIB_DIR?.trim() || "/") === expectedLibDir && Boolean(invocationPath) && resolve33(invocationPath).startsWith(expectedPrefix);
|
|
54404
54899
|
}
|
|
54405
54900
|
function assertCanonicalInstalledLauncher(env, invocationPath) {
|
|
54406
54901
|
if (isCanonicalInstalledLauncher(env, invocationPath))
|
|
@@ -54408,8 +54903,8 @@ function assertCanonicalInstalledLauncher(env, invocationPath) {
|
|
|
54408
54903
|
throw new Error("refusing to modify the shared Beeline systemd unit outside the canonical ~/.local/bin/beeline launcher");
|
|
54409
54904
|
}
|
|
54410
54905
|
function systemdUserUnitPath(env = process.env) {
|
|
54411
|
-
const configRoot = env.XDG_CONFIG_HOME?.trim() ||
|
|
54412
|
-
return
|
|
54906
|
+
const configRoot = env.XDG_CONFIG_HOME?.trim() || resolve33(homedir7(), ".config");
|
|
54907
|
+
return resolve33(configRoot, "systemd", "user", SYSTEMD_UNIT_NAME);
|
|
54413
54908
|
}
|
|
54414
54909
|
var runSystemctl = async (args) => {
|
|
54415
54910
|
const result = await execFileAsync2("systemctl", ["--user", ...args], {
|
|
@@ -54583,7 +55078,7 @@ async function runStartCommand(args, interactiveUi) {
|
|
|
54583
55078
|
// apps/body/dist/pair-command.js
|
|
54584
55079
|
import { existsSync as existsSync15 } from "node:fs";
|
|
54585
55080
|
import { homedir as homedir9 } from "node:os";
|
|
54586
|
-
import { resolve as
|
|
55081
|
+
import { resolve as resolve35 } from "node:path";
|
|
54587
55082
|
import { stdin as stdin3, stdout as stdout4 } from "node:process";
|
|
54588
55083
|
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
54589
55084
|
|
|
@@ -54856,7 +55351,7 @@ import { spawn as spawn10 } from "node:child_process";
|
|
|
54856
55351
|
import { constants as constants4 } from "node:fs";
|
|
54857
55352
|
import { access, chmod as chmod5, mkdir as mkdir16, writeFile as writeFile10 } from "node:fs/promises";
|
|
54858
55353
|
import { homedir as homedir8 } from "node:os";
|
|
54859
|
-
import { resolve as
|
|
55354
|
+
import { resolve as resolve34 } from "node:path";
|
|
54860
55355
|
var CONNECT_TIMEOUT_MS = 30 * 6e4;
|
|
54861
55356
|
var TRUSTY_SQUIRE_SKILL = `---
|
|
54862
55357
|
name: trusty-squire
|
|
@@ -54932,7 +55427,7 @@ async function ensureSkillAt(path) {
|
|
|
54932
55427
|
return path;
|
|
54933
55428
|
} catch {
|
|
54934
55429
|
}
|
|
54935
|
-
await mkdir16(
|
|
55430
|
+
await mkdir16(resolve34(path, ".."), { recursive: true, mode: 448 });
|
|
54936
55431
|
try {
|
|
54937
55432
|
await writeFile10(path, TRUSTY_SQUIRE_SKILL, { mode: 384, flag: "wx" });
|
|
54938
55433
|
} catch (error) {
|
|
@@ -54943,11 +55438,11 @@ async function ensureSkillAt(path) {
|
|
|
54943
55438
|
return path;
|
|
54944
55439
|
}
|
|
54945
55440
|
async function ensureTrustySquireSkill(operatorHome = homedir8()) {
|
|
54946
|
-
return ensureSkillAt(
|
|
55441
|
+
return ensureSkillAt(resolve34(operatorHome, ".agents", "skills", "trusty-squire", "SKILL.md"));
|
|
54947
55442
|
}
|
|
54948
55443
|
async function ensureHarnessSkill(kind, operatorHome) {
|
|
54949
55444
|
const harnessDir = kind === "codex" ? ".codex" : ".claude";
|
|
54950
|
-
return ensureSkillAt(
|
|
55445
|
+
return ensureSkillAt(resolve34(operatorHome, harnessDir, "skills", "trusty-squire", "SKILL.md"));
|
|
54951
55446
|
}
|
|
54952
55447
|
async function connectTrustySquireForPair(input) {
|
|
54953
55448
|
const target = assertTrustySquireConnectSupported(input.agentKind);
|
|
@@ -55102,7 +55597,7 @@ function resolvePairRepository(repoFlag) {
|
|
|
55102
55597
|
if (!repoFlag) {
|
|
55103
55598
|
return { cwd: process.cwd(), repo: null };
|
|
55104
55599
|
}
|
|
55105
|
-
const resolved =
|
|
55600
|
+
const resolved = resolve35(repoFlag);
|
|
55106
55601
|
if (!existsSync15(resolved)) {
|
|
55107
55602
|
throw new Error(`--repo path does not exist: ${resolved}`);
|
|
55108
55603
|
}
|
|
@@ -55364,7 +55859,7 @@ async function runPairCommand(args, llmEnvFile, agentPrivateKey) {
|
|
|
55364
55859
|
import { spawn as spawn12 } from "node:child_process";
|
|
55365
55860
|
import { createHash as createHash15, randomBytes as randomBytes7 } from "node:crypto";
|
|
55366
55861
|
import { chmod as chmod7, mkdir as mkdir18, readFile as readFile13, unlink as unlink5, writeFile as writeFile12 } from "node:fs/promises";
|
|
55367
|
-
import { dirname as dirname16, resolve as
|
|
55862
|
+
import { dirname as dirname16, resolve as resolve37 } from "node:path";
|
|
55368
55863
|
import { stdin as stdin4, stdout as stdout5 } from "node:process";
|
|
55369
55864
|
init_self_update();
|
|
55370
55865
|
init_self_update_manifest();
|
|
@@ -55409,6 +55904,10 @@ var clackPrompts = {
|
|
|
55409
55904
|
clackPromptOutput();
|
|
55410
55905
|
return unwrapPrompt(await select(input), "Connection cancelled.");
|
|
55411
55906
|
},
|
|
55907
|
+
async autocomplete(input) {
|
|
55908
|
+
clackPromptOutput();
|
|
55909
|
+
return unwrapPrompt(await autocomplete({ ...input, output: clackPromptOutput() }), "Connection cancelled.");
|
|
55910
|
+
},
|
|
55412
55911
|
async text(input) {
|
|
55413
55912
|
clackPromptOutput();
|
|
55414
55913
|
return unwrapPrompt(await text({
|
|
@@ -55424,7 +55923,21 @@ var clackPrompts = {
|
|
|
55424
55923
|
}), "Connection cancelled.");
|
|
55425
55924
|
}
|
|
55426
55925
|
};
|
|
55427
|
-
async function
|
|
55926
|
+
async function loadConnectModelCatalog(input) {
|
|
55927
|
+
const agent = resolveAgentCommand({ kind: input.harness });
|
|
55928
|
+
const catalog = await fetchAgentModelCatalog(agent, providerEnvironment({
|
|
55929
|
+
harness: input.harness,
|
|
55930
|
+
...input.provider ? { provider: input.provider } : {},
|
|
55931
|
+
...input.apiKey ? { apiKey: input.apiKey } : {},
|
|
55932
|
+
model: defaultConnectModel(input.harness, input.provider)
|
|
55933
|
+
}));
|
|
55934
|
+
const modelAxis = catalog.catalog.find((axis) => axis.category === "model");
|
|
55935
|
+
if (!modelAxis?.options.length) {
|
|
55936
|
+
throw new Error(`${input.harness} did not advertise any available models`);
|
|
55937
|
+
}
|
|
55938
|
+
return { currentValue: modelAxis.currentValue, options: modelAxis.options };
|
|
55939
|
+
}
|
|
55940
|
+
async function collectConnectWizard(prompts = clackPrompts, loadModels = loadConnectModelCatalog) {
|
|
55428
55941
|
const harness = await prompts.select({
|
|
55429
55942
|
message: brass("Choose harness"),
|
|
55430
55943
|
options: CONNECT_HARNESSES.map((value) => ({
|
|
@@ -55449,16 +55962,36 @@ async function collectConnectWizard(prompts = clackPrompts) {
|
|
|
55449
55962
|
validate: (value) => value.trim() ? void 0 : "API key is required"
|
|
55450
55963
|
});
|
|
55451
55964
|
}
|
|
55452
|
-
const
|
|
55965
|
+
const catalog = await loadModels({
|
|
55966
|
+
harness,
|
|
55967
|
+
...provider ? { provider } : {},
|
|
55968
|
+
...apiKey ? { apiKey: apiKey.trim() } : {}
|
|
55969
|
+
});
|
|
55970
|
+
const initialModel = catalog.currentValue ?? defaultConnectModel(harness, provider);
|
|
55971
|
+
const model = await prompts.autocomplete({
|
|
55453
55972
|
message: brass("Choose model"),
|
|
55454
|
-
|
|
55455
|
-
|
|
55973
|
+
options: catalog.options.map((choice) => ({
|
|
55974
|
+
value: choice.id,
|
|
55975
|
+
label: choice.name ? `${choice.name} (${choice.id})` : choice.id
|
|
55976
|
+
})),
|
|
55977
|
+
...catalog.options.some((choice) => choice.id === initialModel) ? { initialValue: initialModel } : {},
|
|
55978
|
+
placeholder: "Type to filter available models\u2026",
|
|
55979
|
+
maxItems: 12
|
|
55980
|
+
});
|
|
55981
|
+
const name = await prompts.text({
|
|
55982
|
+
message: brass("Agent name"),
|
|
55983
|
+
validate: (value) => {
|
|
55984
|
+
if (!value.trim())
|
|
55985
|
+
return "Agent name is required";
|
|
55986
|
+
return isReasonableAgentName(value) ? void 0 : `Use letters, spaces, hyphens, or apostrophes (${AGENT_NAME_MAX_LENGTH} characters max)`;
|
|
55987
|
+
}
|
|
55456
55988
|
});
|
|
55457
55989
|
const soul = await prompts.text({
|
|
55458
55990
|
message: brass("Input soul"),
|
|
55459
55991
|
validate: (value) => value.trim() ? void 0 : "Soul is required"
|
|
55460
55992
|
});
|
|
55461
55993
|
return {
|
|
55994
|
+
name: name.trim().replace(/\s+/g, " "),
|
|
55462
55995
|
harness,
|
|
55463
55996
|
...provider ? { provider } : {},
|
|
55464
55997
|
...apiKey ? { apiKey: apiKey.trim() } : {},
|
|
@@ -55531,7 +56064,7 @@ async function installCurrentRelease(fetchImpl) {
|
|
|
55531
56064
|
}
|
|
55532
56065
|
});
|
|
55533
56066
|
await activateRelease(layout, releaseId);
|
|
55534
|
-
return
|
|
56067
|
+
return resolve37(layout.binDir, "beeline");
|
|
55535
56068
|
}
|
|
55536
56069
|
function providerEnvironment(selection) {
|
|
55537
56070
|
if (!selection.provider || !selection.apiKey)
|
|
@@ -55561,7 +56094,7 @@ async function writeProviderEnv(selection, agentPubkey) {
|
|
|
55561
56094
|
const values = providerEnvironment(selection);
|
|
55562
56095
|
if (Object.keys(values).length === 0)
|
|
55563
56096
|
return void 0;
|
|
55564
|
-
const path =
|
|
56097
|
+
const path = resolve37(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
|
|
55565
56098
|
await mkdir18(dirname16(path), { recursive: true, mode: 448 });
|
|
55566
56099
|
const contents = Object.entries(values).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n");
|
|
55567
56100
|
await writeFile12(path, `${contents}
|
|
@@ -55610,13 +56143,14 @@ async function runConnectCommand(options = {}) {
|
|
|
55610
56143
|
intro(brass("Beeline connect"));
|
|
55611
56144
|
const selection = await collectConnectWizard();
|
|
55612
56145
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
55613
|
-
const baseUrl = (process.env.BEELINE_AUTH_URL ?? "https://usebeeline.app").replace(/\/$/, "");
|
|
56146
|
+
const baseUrl = (process.env.BEELINE_AUTH_URL ?? "https://server.usebeeline.app").replace(/\/$/, "");
|
|
55614
56147
|
const verifier = randomBytes7(32).toString("base64url");
|
|
55615
|
-
const start = await brassSpinner("Preparing secure
|
|
56148
|
+
const start = await brassSpinner("Preparing secure sign-in\u2026", () => jsonRequest(`${baseUrl}/auth/device/connect`, {
|
|
55616
56149
|
harness: selection.harness,
|
|
55617
56150
|
...selection.provider ? { provider: selection.provider } : {},
|
|
55618
56151
|
model: selection.model,
|
|
55619
56152
|
soul: selection.soul,
|
|
56153
|
+
agent_name: selection.name,
|
|
55620
56154
|
code_challenge: sha2564(verifier)
|
|
55621
56155
|
}, fetchImpl));
|
|
55622
56156
|
try {
|
|
@@ -55624,10 +56158,10 @@ async function runConnectCommand(options = {}) {
|
|
|
55624
56158
|
} catch {
|
|
55625
56159
|
console.log(`Open this link to connect: ${start.verification_uri_complete}`);
|
|
55626
56160
|
}
|
|
55627
|
-
const grant = await brassSpinner("
|
|
56161
|
+
const grant = await brassSpinner("Connecting to your Beeline Workspace\u2026", () => pollDeviceGrant({ baseUrl, start, verifier, fetchImpl }));
|
|
55628
56162
|
const installedBinary = await brassSpinner("Installing the Beeline daemon\u2026", () => installCurrentRelease(fetchImpl));
|
|
55629
56163
|
const llmEnvFile = await writeProviderEnv(selection, grant.agent_pubkey);
|
|
55630
|
-
const grantPath =
|
|
56164
|
+
const grantPath = resolve37(defaultSupervisorRoot(process.env), "beeline", "connect", `grant-${process.pid}-${Date.now()}.json`);
|
|
55631
56165
|
await writePrivateJson(grantPath, {
|
|
55632
56166
|
pairingCode: grant.pairing_code,
|
|
55633
56167
|
agentSecretKey: grant.agent_secret_key,
|
|
@@ -55658,11 +56192,11 @@ async function runConnectFinishCommand(path) {
|
|
|
55658
56192
|
if (!isCanonicalInstalledLauncher(process.env, process.argv[1])) {
|
|
55659
56193
|
throw new Error("connect-finish may run only from the canonical installed Beeline launcher");
|
|
55660
56194
|
}
|
|
55661
|
-
const grant = JSON.parse(await readFile13(
|
|
56195
|
+
const grant = JSON.parse(await readFile13(resolve37(path), "utf8"));
|
|
55662
56196
|
if (!isDevicePairingGrant(grant))
|
|
55663
56197
|
throw new Error("device connection grant is invalid");
|
|
55664
56198
|
await completeDevicePairing(grant);
|
|
55665
|
-
await unlink5(
|
|
56199
|
+
await unlink5(resolve37(path));
|
|
55666
56200
|
}
|
|
55667
56201
|
|
|
55668
56202
|
// apps/body/dist/mission-scaffold-command.js
|
|
@@ -55670,7 +56204,7 @@ var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
|
55670
56204
|
|
|
55671
56205
|
// apps/body/dist/mission-scaffold.js
|
|
55672
56206
|
import { readdir as readdir7, writeFile as writeFile13 } from "node:fs/promises";
|
|
55673
|
-
import { isAbsolute as isAbsolute11, join as join3, relative as relative8, resolve as
|
|
56207
|
+
import { isAbsolute as isAbsolute11, join as join3, relative as relative8, resolve as resolve38 } from "node:path";
|
|
55674
56208
|
var DEFAULT_MISSION_NAME = "Mission";
|
|
55675
56209
|
var UNKNOWN = "(capture during the bootstrap interview)";
|
|
55676
56210
|
function line(value, fallback = UNKNOWN) {
|
|
@@ -55787,7 +56321,7 @@ function orgChartMarkdown(input) {
|
|
|
55787
56321
|
`;
|
|
55788
56322
|
}
|
|
55789
56323
|
async function planMissionScaffold(dir, input = {}) {
|
|
55790
|
-
const root =
|
|
56324
|
+
const root = resolve38(dir);
|
|
55791
56325
|
let existing;
|
|
55792
56326
|
try {
|
|
55793
56327
|
existing = new Set(await readdir7(root));
|
|
@@ -55884,13 +56418,13 @@ init_self_update_manifest();
|
|
|
55884
56418
|
init_self_update();
|
|
55885
56419
|
import { spawn as spawn13 } from "node:child_process";
|
|
55886
56420
|
import { mkdir as mkdir20, rm as rm10, stat as stat4, writeFile as writeFile15 } from "node:fs/promises";
|
|
55887
|
-
import { dirname as dirname18, resolve as
|
|
56421
|
+
import { dirname as dirname18, resolve as resolve40 } from "node:path";
|
|
55888
56422
|
|
|
55889
56423
|
// apps/body/dist/update-rollback-alert.js
|
|
55890
56424
|
import { mkdir as mkdir19, readFile as readFile14, rename as rename8, writeFile as writeFile14 } from "node:fs/promises";
|
|
55891
|
-
import { dirname as dirname17, resolve as
|
|
56425
|
+
import { dirname as dirname17, resolve as resolve39 } from "node:path";
|
|
55892
56426
|
function updateRollbackAlertPath(runtimeDir) {
|
|
55893
|
-
return
|
|
56427
|
+
return resolve39(runtimeDir, "update-rollback-alert.json");
|
|
55894
56428
|
}
|
|
55895
56429
|
async function writeAlert(runtimeDir, alert) {
|
|
55896
56430
|
const path = updateRollbackAlertPath(runtimeDir);
|
|
@@ -55933,13 +56467,13 @@ var LOCK_STALE_MS = UPDATE_WORKER_DEADLINE_MS + 5 * 6e4;
|
|
|
55933
56467
|
var DEFAULT_UPDATE_INITIAL_DELAY_MS = 0;
|
|
55934
56468
|
async function withInstallLock(layout, work, options = {}) {
|
|
55935
56469
|
const now7 = options.now ?? Date.now;
|
|
55936
|
-
const lock =
|
|
56470
|
+
const lock = resolve40(layout.releasesRoot, ".state", "install.lock");
|
|
55937
56471
|
const deadline = now7() + (options.waitMs ?? 1e4);
|
|
55938
56472
|
await mkdir20(dirname18(lock), { recursive: true });
|
|
55939
56473
|
for (; ; ) {
|
|
55940
56474
|
try {
|
|
55941
56475
|
await mkdir20(lock);
|
|
55942
|
-
await writeFile15(
|
|
56476
|
+
await writeFile15(resolve40(lock, "owner"), `${process.pid}
|
|
55943
56477
|
${now7()}
|
|
55944
56478
|
`, "utf8");
|
|
55945
56479
|
break;
|
|
@@ -56047,7 +56581,7 @@ var ManagedUpdateHandoff = class _ManagedUpdateHandoff {
|
|
|
56047
56581
|
if (!attempt || attempt.releaseId !== desiredRelease || attempt.status !== "pending") {
|
|
56048
56582
|
const from = await readInstalledBundleIdentity({
|
|
56049
56583
|
...this.#layout,
|
|
56050
|
-
libDir:
|
|
56584
|
+
libDir: resolve40(this.#layout.releasesRoot, this.#loadedRelease)
|
|
56051
56585
|
}).catch(() => void 0) ?? {};
|
|
56052
56586
|
const to = await readInstalledBundleIdentity(this.#layout).catch(() => void 0) ?? {};
|
|
56053
56587
|
const record2 = {
|
|
@@ -56231,7 +56765,7 @@ async function proveLoadedReleaseReady(layout, runtimeDir, loadedRelease, option
|
|
|
56231
56765
|
});
|
|
56232
56766
|
if (!accepted)
|
|
56233
56767
|
return false;
|
|
56234
|
-
await writeFile15(
|
|
56768
|
+
await writeFile15(resolve40(runtimeDir, "daemon-ready.json"), `${JSON.stringify({
|
|
56235
56769
|
readyAt: (options.now ?? Date.now)(),
|
|
56236
56770
|
loadedRelease,
|
|
56237
56771
|
functionalProof: options.functionalProof
|
|
@@ -56437,11 +56971,11 @@ init_self_update();
|
|
|
56437
56971
|
|
|
56438
56972
|
// apps/body/dist/daemon-failure.js
|
|
56439
56973
|
import { mkdir as mkdir21, readFile as readFile15, rename as rename9, rm as rm11, writeFile as writeFile16 } from "node:fs/promises";
|
|
56440
|
-
import { dirname as dirname19, resolve as
|
|
56974
|
+
import { dirname as dirname19, resolve as resolve41 } from "node:path";
|
|
56441
56975
|
var DAEMON_FAILURE_LIMIT = 3;
|
|
56442
56976
|
var DAEMON_FAILURE_WINDOW_MS = 5 * 6e4;
|
|
56443
56977
|
function daemonFailurePath(runtimeDir) {
|
|
56444
|
-
return
|
|
56978
|
+
return resolve41(runtimeDir, "daemon-distress.json");
|
|
56445
56979
|
}
|
|
56446
56980
|
async function readFailureRecord(runtimeDir) {
|
|
56447
56981
|
try {
|
|
@@ -56482,7 +57016,7 @@ async function clearDaemonStartFailures(runtimeDir) {
|
|
|
56482
57016
|
// apps/body/dist/update-functional-probe.js
|
|
56483
57017
|
import { mkdir as mkdir22, rm as rm12 } from "node:fs/promises";
|
|
56484
57018
|
import { homedir as homedir11 } from "node:os";
|
|
56485
|
-
import { resolve as
|
|
57019
|
+
import { resolve as resolve42 } from "node:path";
|
|
56486
57020
|
var UPDATE_PROBE_SESSION_TIMEOUT_MS = 1e4;
|
|
56487
57021
|
var UPDATE_PROBE_SESSION_OPEN_TIMEOUT_MS = 2e4;
|
|
56488
57022
|
var UPDATE_PROBE_TURN_TIMEOUT_MS = 45e3;
|
|
@@ -56504,9 +57038,9 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
56504
57038
|
if (input.sandboxRequired && !input.config.bwrapPath) {
|
|
56505
57039
|
throw new UpdateFunctionalProbeError("sandbox-unavailable", "the configured bubblewrap boundary did not pass its startup self-test");
|
|
56506
57040
|
}
|
|
56507
|
-
const root =
|
|
56508
|
-
const cwd =
|
|
56509
|
-
const homeRoot =
|
|
57041
|
+
const root = resolve42(input.runtimeDir, "update-functional-probe");
|
|
57042
|
+
const cwd = resolve42(root, "checkout");
|
|
57043
|
+
const homeRoot = resolve42(root, "agent-home");
|
|
56510
57044
|
await rm12(root, { recursive: true, force: true });
|
|
56511
57045
|
await mkdir22(cwd, { recursive: true, mode: 448 });
|
|
56512
57046
|
const calls = [];
|
|
@@ -56629,7 +57163,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
56629
57163
|
|
|
56630
57164
|
// apps/body/dist/release-status.js
|
|
56631
57165
|
import { readFile as readFile16, readdir as readdir8, rename as rename10, writeFile as writeFile17 } from "node:fs/promises";
|
|
56632
|
-
import { resolve as
|
|
57166
|
+
import { resolve as resolve43 } from "node:path";
|
|
56633
57167
|
var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
|
|
56634
57168
|
var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
|
|
56635
57169
|
var SOURCE_SHA = /^[0-9a-f]{7,64}$/;
|
|
@@ -56646,7 +57180,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity2, opti
|
|
|
56646
57180
|
pid: options.pid ?? process.pid,
|
|
56647
57181
|
readyAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString()
|
|
56648
57182
|
};
|
|
56649
|
-
const target =
|
|
57183
|
+
const target = resolve43(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
|
|
56650
57184
|
const temporary = `${target}.${status.pid}.tmp`;
|
|
56651
57185
|
await writeFile17(temporary, `${JSON.stringify(status, null, 2)}
|
|
56652
57186
|
`, { mode: 384 });
|
|
@@ -56808,11 +57342,19 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
56808
57342
|
const configPath = await resolveRuntimeConfigPath(pathOrPointer);
|
|
56809
57343
|
daemonFailureRuntimeDir = dirname20(configPath);
|
|
56810
57344
|
const accessMigration = await migrateRuntimeRecordAccessPolicy(configPath);
|
|
56811
|
-
|
|
57345
|
+
let { runtime } = await migrateLegacyRepositoryPaths(accessMigration.runtime, {
|
|
56812
57346
|
log: console.log
|
|
56813
57347
|
});
|
|
57348
|
+
let daemonApi;
|
|
57349
|
+
if (runtime.transport) {
|
|
57350
|
+
const activated = await activateDaemonTransport(configPath);
|
|
57351
|
+
if (!activated)
|
|
57352
|
+
throw new Error("monolith daemon transport activation failed");
|
|
57353
|
+
runtime = activated.runtime;
|
|
57354
|
+
daemonApi = activated.client;
|
|
57355
|
+
}
|
|
56814
57356
|
const agent = runtimeAgentCommand(runtime);
|
|
56815
|
-
await writeFile18(
|
|
57357
|
+
await writeFile18(resolve44(dirname20(configPath), "daemon.pid"), `${process.pid}
|
|
56816
57358
|
`, { mode: 384 });
|
|
56817
57359
|
const env = {
|
|
56818
57360
|
...process.env,
|
|
@@ -56822,7 +57364,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
56822
57364
|
...runtime.relayHost ? { BUZZY_RELAY_HOST: runtime.relayHost } : {}
|
|
56823
57365
|
};
|
|
56824
57366
|
const config = loadBodyConfig({
|
|
56825
|
-
workspaceRoot:
|
|
57367
|
+
workspaceRoot: resolve44(dirname20(configPath), "workspace"),
|
|
56826
57368
|
llmEnvFile: runtime.llmEnvFile,
|
|
56827
57369
|
env,
|
|
56828
57370
|
agent
|
|
@@ -56902,7 +57444,9 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
56902
57444
|
let ready = false;
|
|
56903
57445
|
let stoppingStatus = "daemon stopped";
|
|
56904
57446
|
try {
|
|
56905
|
-
const core = new ThinDaemonCore(runtime, configPath, config
|
|
57447
|
+
const core = new ThinDaemonCore(runtime, configPath, config, {
|
|
57448
|
+
...daemonApi ? { daemonApi } : {}
|
|
57449
|
+
});
|
|
56906
57450
|
const result = await core.run({
|
|
56907
57451
|
signal: controller.signal,
|
|
56908
57452
|
onEstablished: async () => {
|
|
@@ -56969,7 +57513,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
56969
57513
|
throw error;
|
|
56970
57514
|
} finally {
|
|
56971
57515
|
await notifier.stopping(stoppingStatus).catch(() => void 0);
|
|
56972
|
-
const pidPath =
|
|
57516
|
+
const pidPath = resolve44(dirname20(configPath), "daemon.pid");
|
|
56973
57517
|
const recorded = Number((await readFile17(pidPath, "utf8").catch(() => "")).trim());
|
|
56974
57518
|
if (recorded === process.pid) {
|
|
56975
57519
|
await unlink6(pidPath).catch(() => void 0);
|
|
@@ -56980,13 +57524,13 @@ async function runtimeSpendStatePaths(configPath, runtime) {
|
|
|
56980
57524
|
const paths = /* @__PURE__ */ new Set();
|
|
56981
57525
|
const runtimeRoot = dirname20(configPath);
|
|
56982
57526
|
for (const room of runtime.rooms) {
|
|
56983
|
-
paths.add(
|
|
57527
|
+
paths.add(resolve44(room.root ?? resolve44(runtimeRoot, "rooms", room.channelId), "body-state.json"));
|
|
56984
57528
|
}
|
|
56985
|
-
const roomsRoot =
|
|
57529
|
+
const roomsRoot = resolve44(runtimeRoot, "rooms");
|
|
56986
57530
|
const entries = await readdir9(roomsRoot, { withFileTypes: true }).catch(() => []);
|
|
56987
57531
|
for (const entry of entries) {
|
|
56988
57532
|
if (entry.isDirectory())
|
|
56989
|
-
paths.add(
|
|
57533
|
+
paths.add(resolve44(roomsRoot, entry.name, "body-state.json"));
|
|
56990
57534
|
}
|
|
56991
57535
|
return [...paths];
|
|
56992
57536
|
}
|
|
@@ -57089,7 +57633,7 @@ async function main2() {
|
|
|
57089
57633
|
}
|
|
57090
57634
|
if (!configPath)
|
|
57091
57635
|
throw new Error("daemon requires --config <runtime.json> or --agent <pubkey>");
|
|
57092
|
-
await runStoredDaemon(
|
|
57636
|
+
await runStoredDaemon(resolve44(configPath));
|
|
57093
57637
|
return;
|
|
57094
57638
|
}
|
|
57095
57639
|
if (command === "update") {
|