usebeeline 0.0.50 → 0.0.53
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 +180 -50
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -14141,6 +14141,39 @@ import { basename as basename3, dirname as dirname5, join as join3, relative as
|
|
|
14141
14141
|
// apps/body/dist/beeline-skill.js
|
|
14142
14142
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
14143
14143
|
import { resolve as resolve11 } from "node:path";
|
|
14144
|
+
|
|
14145
|
+
// packages/api-contract/dist/system-events.js
|
|
14146
|
+
var SERVER_EVENT_KINDS = [
|
|
14147
|
+
"joined",
|
|
14148
|
+
"schedule-ran",
|
|
14149
|
+
"corner-opened",
|
|
14150
|
+
"check-passed",
|
|
14151
|
+
"check-failed",
|
|
14152
|
+
"merged",
|
|
14153
|
+
"grant-decided"
|
|
14154
|
+
];
|
|
14155
|
+
function isServerEventKind(value) {
|
|
14156
|
+
return SERVER_EVENT_KINDS.includes(value);
|
|
14157
|
+
}
|
|
14158
|
+
var RESUME_KINDS = ["grant-decided"];
|
|
14159
|
+
function isResumeKind(value) {
|
|
14160
|
+
return RESUME_KINDS.includes(value);
|
|
14161
|
+
}
|
|
14162
|
+
|
|
14163
|
+
// packages/api-contract/dist/agent-pairing-code.js
|
|
14164
|
+
var CURRENT_AGENT_PAIRING_CODE = /^[0-9A-F]{8}-[0-9A-F]{8}$/;
|
|
14165
|
+
var LEGACY_AGENT_PAIRING_CODE = /^BUZZ-(?:[0-9A-F]{8}-[0-9A-F]{8}|[A-HJ-NP-Z2-9]{4}-[A-HJ-NP-Z2-9]{4})$/;
|
|
14166
|
+
function normalizeAgentPairingCode(value) {
|
|
14167
|
+
if (typeof value !== "string")
|
|
14168
|
+
return void 0;
|
|
14169
|
+
const normalized = value.trim().toUpperCase();
|
|
14170
|
+
return isAgentPairingCode(normalized) ? normalized : void 0;
|
|
14171
|
+
}
|
|
14172
|
+
function isAgentPairingCode(value) {
|
|
14173
|
+
return typeof value === "string" && (CURRENT_AGENT_PAIRING_CODE.test(value) || LEGACY_AGENT_PAIRING_CODE.test(value));
|
|
14174
|
+
}
|
|
14175
|
+
|
|
14176
|
+
// apps/body/dist/beeline-skill.js
|
|
14144
14177
|
var USING_BEELINE_SKILL_NAME = "using-beeline";
|
|
14145
14178
|
var BEELINE_ROOM_CAPABILITIES = [
|
|
14146
14179
|
"The repository filesystem is read-only in this Room session.",
|
|
@@ -14151,7 +14184,7 @@ var BEELINE_ROOM_CAPABILITIES = [
|
|
|
14151
14184
|
"Files and photos people share are downloaded for you: read them at the local path named in the prompt (photos may also arrive inline); never fetch the reference URL.",
|
|
14152
14185
|
"To create a file (this Room has no other way to write one), call beeline-agent write_scratch_file with a relative path and content - text by default, or base64 for bytes you computed; it returns a path in your writable session home. To send a file, call beeline-agent attach_file with a path inside your checkout or anywhere in your writable session home (wherever a file you or your harness generated actually landed, including one you just wrote); it is attached to your reply. write_scratch_file produces the file, not a picture - turning it into a raster image needs a converter, which needs shell, which this Room does not have.",
|
|
14153
14186
|
"To run something later or repeatedly, call beeline-agent create_schedule (interval in minutes or a 5-field cron, optional maxRuns); list_schedules / delete_schedule manage them.",
|
|
14154
|
-
|
|
14187
|
+
`To react to things that HAPPEN in this Room rather than only to what is said to you, call beeline-agent subscribe_events with the kinds you want (${SERVER_EVENT_KINDS.join(", ")}); each one then wakes you for a turn. It replaces your list, so send every kind you want - list_event_subscriptions shows the current one. You do this yourself: nobody has to configure it for you. grant-decided carries the grant id and status and resumes the turn that asked for the grant.`,
|
|
14155
14188
|
"To state something that happened so the Room and other agents can act on it, call beeline-agent emit_event with your own agent:<slug> kind, one sentence, and optionally the agent members to wake. Chains of events are bounded and a refused emit posts nothing.",
|
|
14156
14189
|
"When repository work is needed, you MUST call beeline-agent open_corner with a name of at most three words - it titles the corner everywhere - and a complete objective of no more than 24 words. The host-governed call is the only way to start write work.",
|
|
14157
14190
|
"When open_corner succeeds, the server posts the corner card: do not announce or restate the opening. End the turn with nothing more unless the person asked something else.",
|
|
@@ -15111,6 +15144,7 @@ async function resolveSharedSkillSources(operatorHome, names) {
|
|
|
15111
15144
|
return resolveExplicitSkillSources(operatorHome, names);
|
|
15112
15145
|
const seen = /* @__PURE__ */ new Set();
|
|
15113
15146
|
const resolved = [];
|
|
15147
|
+
const skipped = [];
|
|
15114
15148
|
for (const relativeRoot of OPERATOR_SKILL_SOURCE_DIRS) {
|
|
15115
15149
|
const sourceRoot = resolve13(operatorHome, relativeRoot);
|
|
15116
15150
|
const rootStats = await lstat(sourceRoot).catch(() => void 0);
|
|
@@ -15122,23 +15156,61 @@ async function resolveSharedSkillSources(operatorHome, names) {
|
|
|
15122
15156
|
const candidate = resolve13(sourceRoot, entry);
|
|
15123
15157
|
try {
|
|
15124
15158
|
const candidateStats = await lstat(candidate);
|
|
15125
|
-
if (
|
|
15159
|
+
if (candidateStats.isSymbolicLink()) {
|
|
15160
|
+
const reason = await realpath(candidate).then(() => "symlinked directory", (error) => isMissingPathError(error) ? "dangling symlink" : "symlinked directory");
|
|
15161
|
+
skipped.push({
|
|
15162
|
+
path: candidate,
|
|
15163
|
+
reason
|
|
15164
|
+
});
|
|
15165
|
+
continue;
|
|
15166
|
+
}
|
|
15167
|
+
if (!candidateStats.isDirectory()) {
|
|
15168
|
+
skipped.push({ path: candidate, reason: "not an ordinary directory" });
|
|
15126
15169
|
continue;
|
|
15170
|
+
}
|
|
15127
15171
|
assertContained(sourceRoot, candidate);
|
|
15128
15172
|
const skillMd = resolve13(candidate, "SKILL.md");
|
|
15129
|
-
const skillStats = await lstat(skillMd)
|
|
15173
|
+
const skillStats = await lstat(skillMd).catch((error) => {
|
|
15174
|
+
if (isMissingPathError(error)) {
|
|
15175
|
+
skipped.push({ path: candidate, reason: "missing SKILL.md" });
|
|
15176
|
+
return void 0;
|
|
15177
|
+
}
|
|
15178
|
+
throw error;
|
|
15179
|
+
});
|
|
15180
|
+
if (!skillStats)
|
|
15181
|
+
continue;
|
|
15130
15182
|
if (!skillStats.isFile() || skillStats.isSymbolicLink() || skillStats.nlink !== 1) {
|
|
15131
|
-
|
|
15183
|
+
skipped.push({ path: candidate, reason: "SKILL.md is not an ordinary file" });
|
|
15184
|
+
continue;
|
|
15132
15185
|
}
|
|
15133
15186
|
seen.add(entry);
|
|
15134
15187
|
resolved.push({ name: entry, source: candidate });
|
|
15135
15188
|
} catch (error) {
|
|
15189
|
+
if (isMissingPathError(error)) {
|
|
15190
|
+
skipped.push({ path: candidate, reason: "missing during discovery" });
|
|
15191
|
+
continue;
|
|
15192
|
+
}
|
|
15136
15193
|
console.warn(`[body] skipping operator skill ${entry}:`, error);
|
|
15137
15194
|
}
|
|
15138
15195
|
}
|
|
15139
15196
|
}
|
|
15197
|
+
logSkippedOperatorSkills(skipped);
|
|
15140
15198
|
return resolved;
|
|
15141
15199
|
}
|
|
15200
|
+
function isMissingPathError(error) {
|
|
15201
|
+
return typeof error === "object" && error !== null && error.code === "ENOENT";
|
|
15202
|
+
}
|
|
15203
|
+
function logSkippedOperatorSkills(skipped) {
|
|
15204
|
+
const totals = /* @__PURE__ */ new Map();
|
|
15205
|
+
for (const { path, reason } of skipped) {
|
|
15206
|
+
console.warn(`[body] skipping operator skill ${path}: ${reason}`);
|
|
15207
|
+
totals.set(reason, (totals.get(reason) ?? 0) + 1);
|
|
15208
|
+
}
|
|
15209
|
+
for (const [reason, count] of totals) {
|
|
15210
|
+
if (count > 1)
|
|
15211
|
+
console.warn(`[body] ${count} skill entries skipped: ${reason}`);
|
|
15212
|
+
}
|
|
15213
|
+
}
|
|
15142
15214
|
async function resolveExplicitSkillSources(operatorHome, names) {
|
|
15143
15215
|
const unique = [...new Set(names)];
|
|
15144
15216
|
for (const name of unique) {
|
|
@@ -16968,6 +17040,9 @@ var MonolithCornerTurnLoop = class {
|
|
|
16968
17040
|
this.sessionScratchDir = tmpDir;
|
|
16969
17041
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
16970
17042
|
await Promise.all(homeStateDirs.map((dir) => mkdir9(dir, { recursive: true })));
|
|
17043
|
+
const attachScratchRoot = this.options.config.agentHomeRoot ?? tmpDir;
|
|
17044
|
+
if (attachScratchRoot)
|
|
17045
|
+
await mkdir9(attachScratchRoot, { recursive: true });
|
|
16971
17046
|
const spawnCommand = wrapAgentCommand({
|
|
16972
17047
|
bwrapPath: this.options.config.bwrapPath,
|
|
16973
17048
|
spec: {
|
|
@@ -16979,6 +17054,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
16979
17054
|
harnessStateDirs: stateDirs,
|
|
16980
17055
|
harnessHomeStateDirs: homeStateDirs,
|
|
16981
17056
|
...tmpDir ? { tmpDir } : {},
|
|
17057
|
+
...attachScratchRoot ? { additionalWritablePaths: [attachScratchRoot] } : {},
|
|
16982
17058
|
maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome)
|
|
16983
17059
|
},
|
|
16984
17060
|
command,
|
|
@@ -17016,7 +17092,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
17016
17092
|
attachRoot: this.options.worktreePath,
|
|
17017
17093
|
// The whole per-session overlay, not an enumerated subset: see
|
|
17018
17094
|
// `monolith-room-turn.ts`'s matching comment.
|
|
17019
|
-
attachScratchRoot
|
|
17095
|
+
attachScratchRoot,
|
|
17020
17096
|
...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
|
|
17021
17097
|
})
|
|
17022
17098
|
];
|
|
@@ -17411,24 +17487,6 @@ import { join as join6 } from "node:path";
|
|
|
17411
17487
|
var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
|
|
17412
17488
|
var SCHEDULE_RAN_VERB = "ran a schedule for";
|
|
17413
17489
|
|
|
17414
|
-
// packages/api-contract/dist/system-events.js
|
|
17415
|
-
var SERVER_EVENT_KINDS = [
|
|
17416
|
-
"joined",
|
|
17417
|
-
"schedule-ran",
|
|
17418
|
-
"corner-opened",
|
|
17419
|
-
"check-passed",
|
|
17420
|
-
"check-failed",
|
|
17421
|
-
"merged",
|
|
17422
|
-
"grant-decided"
|
|
17423
|
-
];
|
|
17424
|
-
function isServerEventKind(value) {
|
|
17425
|
-
return SERVER_EVENT_KINDS.includes(value);
|
|
17426
|
-
}
|
|
17427
|
-
var RESUME_KINDS = ["grant-decided"];
|
|
17428
|
-
function isResumeKind(value) {
|
|
17429
|
-
return RESUME_KINDS.includes(value);
|
|
17430
|
-
}
|
|
17431
|
-
|
|
17432
17490
|
// apps/body/dist/monolith-room-turn.js
|
|
17433
17491
|
function isRoomMcpPermissionRequest(request, mountedServers = ROOM_MOUNTED_MCP_SERVERS) {
|
|
17434
17492
|
if (isSquireMcpPermissionRequest(request))
|
|
@@ -17501,6 +17559,15 @@ function agentReplyMentionIds(text2, roster, authorId) {
|
|
|
17501
17559
|
aliases.set(key, entry);
|
|
17502
17560
|
}
|
|
17503
17561
|
}
|
|
17562
|
+
for (const member of roster.members) {
|
|
17563
|
+
if (member.identityId === authorId || !member.handle)
|
|
17564
|
+
continue;
|
|
17565
|
+
const handle = member.handle.trim().replace(/^@/, "").toLocaleLowerCase();
|
|
17566
|
+
const canonical = aliases.get(handle);
|
|
17567
|
+
const legacy = `a_${handle}`;
|
|
17568
|
+
if (canonical && !aliases.has(legacy))
|
|
17569
|
+
aliases.set(legacy, { ...canonical, display: legacy });
|
|
17570
|
+
}
|
|
17504
17571
|
const mentioned = [];
|
|
17505
17572
|
for (const { display, ids } of [...aliases.values()].sort((left, right) => right.display.length - left.display.length)) {
|
|
17506
17573
|
if (ids.size !== 1)
|
|
@@ -17749,6 +17816,9 @@ var MonolithRoomTurnLoop = class {
|
|
|
17749
17816
|
this.sessionStateDirs = stateDirs;
|
|
17750
17817
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
17751
17818
|
await Promise.all(homeStateDirs.map((dir) => mkdir10(dir, { recursive: true })));
|
|
17819
|
+
const attachScratchRoot = this.options.config.agentHomeRoot ?? tmpDir;
|
|
17820
|
+
if (attachScratchRoot)
|
|
17821
|
+
await mkdir10(attachScratchRoot, { recursive: true });
|
|
17752
17822
|
const spawnCommand = wrapAgentCommand({
|
|
17753
17823
|
bwrapPath: this.options.config.bwrapPath,
|
|
17754
17824
|
spec: {
|
|
@@ -17757,6 +17827,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
17757
17827
|
harnessStateDirs: stateDirs,
|
|
17758
17828
|
harnessHomeStateDirs: homeStateDirs,
|
|
17759
17829
|
...tmpDir ? { tmpDir } : {},
|
|
17830
|
+
...attachScratchRoot ? { additionalWritablePaths: [attachScratchRoot] } : {},
|
|
17760
17831
|
maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome)
|
|
17761
17832
|
},
|
|
17762
17833
|
command,
|
|
@@ -17772,7 +17843,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
17772
17843
|
// never picks where a harness writes a file it generates (grok's own
|
|
17773
17844
|
// images dir, say), so anything inside the overlay it could possibly
|
|
17774
17845
|
// have written must be attachable, whatever subdirectory that is.
|
|
17775
|
-
attachScratchRoot
|
|
17846
|
+
attachScratchRoot,
|
|
17776
17847
|
directMessage,
|
|
17777
17848
|
...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
|
|
17778
17849
|
})
|
|
@@ -19502,19 +19573,6 @@ import { chmod as chmod5, mkdir as mkdir14, readFile as readFile10, unlink as un
|
|
|
19502
19573
|
import { dirname as dirname10, resolve as resolve22 } from "node:path";
|
|
19503
19574
|
import { stdin as stdin3, stdout as stdout4 } from "node:process";
|
|
19504
19575
|
|
|
19505
|
-
// packages/api-contract/dist/agent-pairing-code.js
|
|
19506
|
-
var CURRENT_AGENT_PAIRING_CODE = /^[0-9A-F]{8}-[0-9A-F]{8}$/;
|
|
19507
|
-
var LEGACY_AGENT_PAIRING_CODE = /^BUZZ-(?:[0-9A-F]{8}-[0-9A-F]{8}|[A-HJ-NP-Z2-9]{4}-[A-HJ-NP-Z2-9]{4})$/;
|
|
19508
|
-
function normalizeAgentPairingCode(value) {
|
|
19509
|
-
if (typeof value !== "string")
|
|
19510
|
-
return void 0;
|
|
19511
|
-
const normalized = value.trim().toUpperCase();
|
|
19512
|
-
return isAgentPairingCode(normalized) ? normalized : void 0;
|
|
19513
|
-
}
|
|
19514
|
-
function isAgentPairingCode(value) {
|
|
19515
|
-
return typeof value === "string" && (CURRENT_AGENT_PAIRING_CODE.test(value) || LEGACY_AGENT_PAIRING_CODE.test(value));
|
|
19516
|
-
}
|
|
19517
|
-
|
|
19518
19576
|
// apps/body/dist/clack-support.js
|
|
19519
19577
|
import { stdout as stdout2 } from "node:process";
|
|
19520
19578
|
var FALLBACK_TERMINAL_COLUMNS = 80;
|
|
@@ -20820,39 +20878,59 @@ async function proveLoadedReleaseReady(layout, runtimeDir, loadedRelease, option
|
|
|
20820
20878
|
`, { mode: 384 });
|
|
20821
20879
|
return true;
|
|
20822
20880
|
}
|
|
20881
|
+
function siblingRevertNote(attempt, loadedRelease) {
|
|
20882
|
+
if (!loadedRelease || attempt?.releaseId !== loadedRelease || attempt.status !== "reverted") {
|
|
20883
|
+
return void 0;
|
|
20884
|
+
}
|
|
20885
|
+
return `shared update attempt reverted by sibling ${attempt.revertedBy ?? "unknown"}: ${attempt.failure ?? "no failure recorded"}`;
|
|
20886
|
+
}
|
|
20887
|
+
function describeOwnProof(proof) {
|
|
20888
|
+
return proof.modelAnswer === "unavailable" ? `this daemon's own probe reached the model boundary without an answer (${proof.modelAnswerReason ?? "no reason recorded"})` : "this daemon's own probe passed";
|
|
20889
|
+
}
|
|
20890
|
+
function attemptFailureText(error) {
|
|
20891
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
20892
|
+
return message.replace(/\s+/g, " ").trim().slice(0, 300);
|
|
20893
|
+
}
|
|
20823
20894
|
async function gateManagedSuccessor(input) {
|
|
20824
20895
|
try {
|
|
20825
20896
|
const attempt = await readUpdateAttempt(input.layout);
|
|
20826
20897
|
const desiredRelease = attempt?.status === "pending" ? attempt.releaseId : void 0;
|
|
20827
20898
|
if (!desiredRelease || !input.loadedRelease || desiredRelease !== input.loadedRelease) {
|
|
20828
|
-
|
|
20899
|
+
const reverted = siblingRevertNote(attempt, input.loadedRelease);
|
|
20900
|
+
throw new Error(reverted ? `successor release ${input.loadedRelease} was reverted before this daemon probed it: ${reverted}` : `successor loaded release ${input.loadedRelease ?? "unknown"}, not the pending desired release`);
|
|
20829
20901
|
}
|
|
20830
20902
|
const proof = await input.probe();
|
|
20831
20903
|
if (!await proveLoadedReleaseReady(input.layout, input.runtimeDir, input.loadedRelease, {
|
|
20832
20904
|
probeId: input.probeId,
|
|
20833
20905
|
functionalProof: proof
|
|
20834
20906
|
})) {
|
|
20835
|
-
|
|
20907
|
+
const reverted = siblingRevertNote(await readUpdateAttempt(input.layout), input.loadedRelease);
|
|
20908
|
+
throw new Error(reverted ? `successor release ${input.loadedRelease} lost its attempt while this daemon proved it: ${describeOwnProof(proof)}; ${reverted}` : `successor release ${input.loadedRelease} did not produce functional proof`);
|
|
20836
20909
|
}
|
|
20837
20910
|
return { kind: "passed", proof };
|
|
20838
20911
|
} catch (error) {
|
|
20839
20912
|
return {
|
|
20840
20913
|
kind: "failed",
|
|
20841
20914
|
error,
|
|
20842
|
-
rolledBack: await rollbackFailedSuccessor(input.layout, input.runtimeDir
|
|
20915
|
+
rolledBack: await rollbackFailedSuccessor(input.layout, input.runtimeDir, {
|
|
20916
|
+
probeId: input.probeId,
|
|
20917
|
+
failure: attemptFailureText(error)
|
|
20918
|
+
})
|
|
20843
20919
|
};
|
|
20844
20920
|
}
|
|
20845
20921
|
}
|
|
20846
|
-
async function rollbackFailedSuccessor(layout, runtimeDir) {
|
|
20922
|
+
async function rollbackFailedSuccessor(layout, runtimeDir, cause = {}) {
|
|
20847
20923
|
return withInstallLock(layout, async () => {
|
|
20848
20924
|
const attempt = await readUpdateAttempt(layout);
|
|
20849
20925
|
if (!attempt || attempt.status !== "pending")
|
|
20850
20926
|
return false;
|
|
20927
|
+
const attribution = cause.probeId ? { revertedBy: cause.probeId } : {};
|
|
20851
20928
|
if (!attempt.previousReleaseId) {
|
|
20852
20929
|
await replaceUpdateAttempt(layout, {
|
|
20853
20930
|
...attempt,
|
|
20854
20931
|
status: "reverted",
|
|
20855
|
-
failure: "functional served-turn proof failed, but no previous release exists"
|
|
20932
|
+
failure: cause.failure ?? "functional served-turn proof failed, but no previous release exists",
|
|
20933
|
+
...attribution
|
|
20856
20934
|
});
|
|
20857
20935
|
return false;
|
|
20858
20936
|
}
|
|
@@ -20860,7 +20938,8 @@ async function rollbackFailedSuccessor(layout, runtimeDir) {
|
|
|
20860
20938
|
await replaceUpdateAttempt(layout, {
|
|
20861
20939
|
...attempt,
|
|
20862
20940
|
status: "reverted",
|
|
20863
|
-
failure: "functional served-turn proof failed before confirmation"
|
|
20941
|
+
failure: cause.failure ?? "functional served-turn proof failed before confirmation",
|
|
20942
|
+
...attribution
|
|
20864
20943
|
});
|
|
20865
20944
|
if (runtimeDir)
|
|
20866
20945
|
await queueUpdateRollbackAlert(runtimeDir, attempt.releaseId);
|
|
@@ -21067,6 +21146,28 @@ import { resolve as resolve26 } from "node:path";
|
|
|
21067
21146
|
var UPDATE_PROBE_SESSION_TIMEOUT_MS = 1e4;
|
|
21068
21147
|
var UPDATE_PROBE_SESSION_OPEN_TIMEOUT_MS = 2e4;
|
|
21069
21148
|
var UPDATE_PROBE_TURN_TIMEOUT_MS = 45e3;
|
|
21149
|
+
var ACP_ERROR_CODE = /\bACP error (-\d+):/;
|
|
21150
|
+
var ACP_PROMPT_INACTIVITY = /\bACP session\/prompt timed out after \d+ms of inactivity\b/;
|
|
21151
|
+
function isServerInternalCode(code) {
|
|
21152
|
+
return code === -32603 || code <= -32e3 && code >= -32099;
|
|
21153
|
+
}
|
|
21154
|
+
function classifyAcpTurnFailure(error) {
|
|
21155
|
+
const message = error instanceof Error ? error.message : typeof error === "string" ? error : void 0;
|
|
21156
|
+
if (!message)
|
|
21157
|
+
return void 0;
|
|
21158
|
+
if (ACP_PROMPT_INACTIVITY.test(message))
|
|
21159
|
+
return { kind: "prompt-inactivity" };
|
|
21160
|
+
const code = Number(ACP_ERROR_CODE.exec(message)?.[1]);
|
|
21161
|
+
if (Number.isFinite(code) && isServerInternalCode(code))
|
|
21162
|
+
return { kind: "server-internal", code };
|
|
21163
|
+
return void 0;
|
|
21164
|
+
}
|
|
21165
|
+
function sameAcpTurnFailure(one, other) {
|
|
21166
|
+
if (one.kind === "server-internal") {
|
|
21167
|
+
return other.kind === "server-internal" && one.code === other.code;
|
|
21168
|
+
}
|
|
21169
|
+
return other.kind === one.kind;
|
|
21170
|
+
}
|
|
21070
21171
|
var UpdateFunctionalProbeError = class extends Error {
|
|
21071
21172
|
reason;
|
|
21072
21173
|
code = "BEELINE_UPDATE_FUNCTIONAL_PROBE_FAILED";
|
|
@@ -21138,6 +21239,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
21138
21239
|
args: agentArgsWithModelSelection(selectedAgent, input.config.modelSelection)
|
|
21139
21240
|
};
|
|
21140
21241
|
let modelAnswer = {};
|
|
21242
|
+
let turnCompleted = true;
|
|
21141
21243
|
if (input.config.bwrapPath) {
|
|
21142
21244
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
21143
21245
|
const operatorHome = input.config.operatorHome ?? homedir10();
|
|
@@ -21199,7 +21301,11 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
21199
21301
|
...refusal ? { providerRefusal: refusal } : {}
|
|
21200
21302
|
});
|
|
21201
21303
|
}
|
|
21202
|
-
const current = await input.compareWithCurrentRelease(
|
|
21304
|
+
const current = await input.compareWithCurrentRelease({
|
|
21305
|
+
kind: "provider-refusal",
|
|
21306
|
+
reason: refusal.reason,
|
|
21307
|
+
refusal
|
|
21308
|
+
});
|
|
21203
21309
|
if (current.kind !== "refused" || current.status !== refusal.status) {
|
|
21204
21310
|
throw new UpdateFunctionalProbeError("turn-failed", `${detail}; ${describeCurrentReleaseOutcome(current)}`, { providerRefusal: refusal });
|
|
21205
21311
|
}
|
|
@@ -21214,7 +21320,26 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
21214
21320
|
} catch (error) {
|
|
21215
21321
|
if (error instanceof UpdateFunctionalProbeError)
|
|
21216
21322
|
throw error;
|
|
21217
|
-
|
|
21323
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
21324
|
+
const failure = classifyAcpTurnFailure(error);
|
|
21325
|
+
if (!failure || !input.compareWithCurrentRelease) {
|
|
21326
|
+
throw new UpdateFunctionalProbeError("turn-failed", detail, { cause: error });
|
|
21327
|
+
}
|
|
21328
|
+
const current = await input.compareWithCurrentRelease({
|
|
21329
|
+
kind: "acp-turn-failure",
|
|
21330
|
+
reason: detail,
|
|
21331
|
+
failure
|
|
21332
|
+
});
|
|
21333
|
+
const currentFailure = current.kind === "unavailable" ? classifyAcpTurnFailure(current.reason) : void 0;
|
|
21334
|
+
if (!currentFailure || !sameAcpTurnFailure(failure, currentFailure)) {
|
|
21335
|
+
throw new UpdateFunctionalProbeError("turn-failed", `${detail}; ${describeCurrentReleaseOutcome(current)}`, { cause: error });
|
|
21336
|
+
}
|
|
21337
|
+
console.warn(`[body] update probe: the probe turn failed the same way on this release and the current release (${detail}); that failure is not this bundle's doing, so the probe passes as inconclusive`);
|
|
21338
|
+
turnCompleted = false;
|
|
21339
|
+
modelAnswer = {
|
|
21340
|
+
modelAnswer: "unavailable",
|
|
21341
|
+
modelAnswerReason: `${detail} (the current release fails the same way)`
|
|
21342
|
+
};
|
|
21218
21343
|
}
|
|
21219
21344
|
} catch (error) {
|
|
21220
21345
|
if (error instanceof UpdateFunctionalProbeError)
|
|
@@ -21225,7 +21350,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
21225
21350
|
harness,
|
|
21226
21351
|
sandboxed: Boolean(input.config.bwrapPath),
|
|
21227
21352
|
sessionStarted: true,
|
|
21228
|
-
turnCompleted
|
|
21353
|
+
turnCompleted,
|
|
21229
21354
|
nativeTools: [],
|
|
21230
21355
|
...modelAnswer
|
|
21231
21356
|
};
|
|
@@ -21239,7 +21364,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
21239
21364
|
import { spawn as spawn7 } from "node:child_process";
|
|
21240
21365
|
import { dirname as dirname14, join as join8 } from "node:path";
|
|
21241
21366
|
init_self_update();
|
|
21242
|
-
var CURRENT_RELEASE_PROBE_TIMEOUT_MS =
|
|
21367
|
+
var CURRENT_RELEASE_PROBE_TIMEOUT_MS = 12e4;
|
|
21243
21368
|
var UPDATE_PROBE_COMMAND = "update-probe";
|
|
21244
21369
|
function parseReport(line) {
|
|
21245
21370
|
let parsed;
|
|
@@ -21567,8 +21692,8 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
21567
21692
|
releaseId: loadedRelease ?? "unknown",
|
|
21568
21693
|
sandboxRequired: runtime.sandbox !== "off",
|
|
21569
21694
|
...currentReleaseId ? {
|
|
21570
|
-
compareWithCurrentRelease: async (
|
|
21571
|
-
console.warn(`[thin-core] successor probe
|
|
21695
|
+
compareWithCurrentRelease: async (appeal) => {
|
|
21696
|
+
console.warn(`[thin-core] successor probe got no answer from the provider (${appeal.reason}); probing the current release ${currentReleaseId} for the same outcome`);
|
|
21572
21697
|
await extendSystemdStartTimeout(CURRENT_RELEASE_PROBE_TIMEOUT_MS + 15e3);
|
|
21573
21698
|
return probeReleaseInSubprocess({
|
|
21574
21699
|
layout,
|
|
@@ -21614,7 +21739,12 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
21614
21739
|
console.log(`[beeline] agent ${runtime.agent.publicKey} removed; runtime archived at ${archivedRuntime}`);
|
|
21615
21740
|
}
|
|
21616
21741
|
} catch (error) {
|
|
21617
|
-
const rolledBack = successorRolledBack || layout && pendingSuccessor && !ready &&
|
|
21742
|
+
const rolledBack = successorRolledBack || layout && pendingSuccessor && !ready && // Named, so a sibling daemon's journal can say whose failure reverted
|
|
21743
|
+
// the attempt it shares with this one.
|
|
21744
|
+
await rollbackFailedSuccessor(layout, runtimeDir, {
|
|
21745
|
+
probeId: runtime.agent.publicKey,
|
|
21746
|
+
failure: attemptFailureText(error)
|
|
21747
|
+
});
|
|
21618
21748
|
if (rolledBack) {
|
|
21619
21749
|
console.error("[thin-core] successor failed before READY; previous release restored once");
|
|
21620
21750
|
const alertRoom = runtime.rooms[0]?.channelId;
|