usebeeline 0.1.20 → 0.1.22
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 +1012 -429
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -212,8 +212,8 @@ async function runSquireBrokerLink(options) {
|
|
|
212
212
|
const pending = /* @__PURE__ */ new Map();
|
|
213
213
|
const queued = [];
|
|
214
214
|
let resolveDone;
|
|
215
|
-
const done = new Promise((
|
|
216
|
-
resolveDone =
|
|
215
|
+
const done = new Promise((resolve49) => {
|
|
216
|
+
resolveDone = resolve49;
|
|
217
217
|
});
|
|
218
218
|
const failResponse = (id) => `${JSON.stringify({
|
|
219
219
|
jsonrpc: "2.0",
|
|
@@ -480,8 +480,8 @@ function socketHolders(inodes, profileDir, procRoot = "/proc") {
|
|
|
480
480
|
}
|
|
481
481
|
function alive(pid, procRoot) {
|
|
482
482
|
try {
|
|
483
|
-
const
|
|
484
|
-
return
|
|
483
|
+
const stat11 = readFileSync(join(procRoot, String(pid), "stat"), "utf8");
|
|
484
|
+
return stat11.slice(stat11.lastIndexOf(")") + 2, stat11.lastIndexOf(")") + 3) !== "Z";
|
|
485
485
|
} catch {
|
|
486
486
|
return false;
|
|
487
487
|
}
|
|
@@ -5680,11 +5680,11 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
5680
5680
|
const extract2 = await run("tar", ["-xzf", tempArchive, "-C", releaseDir], 5 * 6e4);
|
|
5681
5681
|
if (extract2.status !== 0)
|
|
5682
5682
|
throw new Error(`extracting bundle failed: ${extract2.stderr}`);
|
|
5683
|
-
for (const
|
|
5683
|
+
for (const relative5 of requiredBundlePaths()) {
|
|
5684
5684
|
try {
|
|
5685
|
-
await access(join8(releaseDir,
|
|
5685
|
+
await access(join8(releaseDir, relative5), fsConstants2.F_OK);
|
|
5686
5686
|
} catch {
|
|
5687
|
-
throw new Error(`staged bundle is missing ${
|
|
5687
|
+
throw new Error(`staged bundle is missing ${relative5}`);
|
|
5688
5688
|
}
|
|
5689
5689
|
}
|
|
5690
5690
|
const engineMinimum = await readBundleEngineMinimum(releaseDir);
|
|
@@ -10099,10 +10099,10 @@ var require_resolve_block_map = __commonJS({
|
|
|
10099
10099
|
let offset = bm.offset;
|
|
10100
10100
|
let commentEnd = null;
|
|
10101
10101
|
for (const collItem of bm.items) {
|
|
10102
|
-
const { start, key, sep:
|
|
10102
|
+
const { start, key, sep: sep4, value } = collItem;
|
|
10103
10103
|
const keyProps = resolveProps.resolveProps(start, {
|
|
10104
10104
|
indicator: "explicit-key-ind",
|
|
10105
|
-
next: key ??
|
|
10105
|
+
next: key ?? sep4?.[0],
|
|
10106
10106
|
offset,
|
|
10107
10107
|
onError,
|
|
10108
10108
|
parentIndent: bm.indent,
|
|
@@ -10116,7 +10116,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
10116
10116
|
else if ("indent" in key && key.indent !== bm.indent)
|
|
10117
10117
|
onError(offset, "BAD_INDENT", startColMsg);
|
|
10118
10118
|
}
|
|
10119
|
-
if (!keyProps.anchor && !keyProps.tag && !
|
|
10119
|
+
if (!keyProps.anchor && !keyProps.tag && !sep4) {
|
|
10120
10120
|
commentEnd = keyProps.end;
|
|
10121
10121
|
if (keyProps.comment) {
|
|
10122
10122
|
if (map.comment)
|
|
@@ -10140,7 +10140,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
10140
10140
|
ctx.atKey = false;
|
|
10141
10141
|
if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
|
|
10142
10142
|
onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
|
|
10143
|
-
const valueProps = resolveProps.resolveProps(
|
|
10143
|
+
const valueProps = resolveProps.resolveProps(sep4 ?? [], {
|
|
10144
10144
|
indicator: "map-value-ind",
|
|
10145
10145
|
next: value,
|
|
10146
10146
|
offset: keyNode.range[2],
|
|
@@ -10156,7 +10156,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
10156
10156
|
if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
|
|
10157
10157
|
onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
|
|
10158
10158
|
}
|
|
10159
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset,
|
|
10159
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep4, null, valueProps, onError);
|
|
10160
10160
|
if (ctx.schema.compat)
|
|
10161
10161
|
utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
|
|
10162
10162
|
offset = valueNode.range[2];
|
|
@@ -10247,7 +10247,7 @@ var require_resolve_end = __commonJS({
|
|
|
10247
10247
|
let comment = "";
|
|
10248
10248
|
if (end) {
|
|
10249
10249
|
let hasSpace = false;
|
|
10250
|
-
let
|
|
10250
|
+
let sep4 = "";
|
|
10251
10251
|
for (const token of end) {
|
|
10252
10252
|
const { source, type } = token;
|
|
10253
10253
|
switch (type) {
|
|
@@ -10261,13 +10261,13 @@ var require_resolve_end = __commonJS({
|
|
|
10261
10261
|
if (!comment)
|
|
10262
10262
|
comment = cb;
|
|
10263
10263
|
else
|
|
10264
|
-
comment +=
|
|
10265
|
-
|
|
10264
|
+
comment += sep4 + cb;
|
|
10265
|
+
sep4 = "";
|
|
10266
10266
|
break;
|
|
10267
10267
|
}
|
|
10268
10268
|
case "newline":
|
|
10269
10269
|
if (comment)
|
|
10270
|
-
|
|
10270
|
+
sep4 += source;
|
|
10271
10271
|
hasSpace = true;
|
|
10272
10272
|
break;
|
|
10273
10273
|
default:
|
|
@@ -10310,18 +10310,18 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
10310
10310
|
let offset = fc.offset + fc.start.source.length;
|
|
10311
10311
|
for (let i3 = 0; i3 < fc.items.length; ++i3) {
|
|
10312
10312
|
const collItem = fc.items[i3];
|
|
10313
|
-
const { start, key, sep:
|
|
10313
|
+
const { start, key, sep: sep4, value } = collItem;
|
|
10314
10314
|
const props = resolveProps.resolveProps(start, {
|
|
10315
10315
|
flow: fcName,
|
|
10316
10316
|
indicator: "explicit-key-ind",
|
|
10317
|
-
next: key ??
|
|
10317
|
+
next: key ?? sep4?.[0],
|
|
10318
10318
|
offset,
|
|
10319
10319
|
onError,
|
|
10320
10320
|
parentIndent: fc.indent,
|
|
10321
10321
|
startOnNewline: false
|
|
10322
10322
|
});
|
|
10323
10323
|
if (!props.found) {
|
|
10324
|
-
if (!props.anchor && !props.tag && !
|
|
10324
|
+
if (!props.anchor && !props.tag && !sep4 && !value) {
|
|
10325
10325
|
if (i3 === 0 && props.comma)
|
|
10326
10326
|
onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
|
|
10327
10327
|
else if (i3 < fc.items.length - 1)
|
|
@@ -10375,8 +10375,8 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
10375
10375
|
}
|
|
10376
10376
|
}
|
|
10377
10377
|
}
|
|
10378
|
-
if (!isMap && !
|
|
10379
|
-
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end,
|
|
10378
|
+
if (!isMap && !sep4 && !props.found) {
|
|
10379
|
+
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep4, null, props, onError);
|
|
10380
10380
|
coll.items.push(valueNode);
|
|
10381
10381
|
offset = valueNode.range[2];
|
|
10382
10382
|
if (isBlock(value))
|
|
@@ -10388,7 +10388,7 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
10388
10388
|
if (isBlock(key))
|
|
10389
10389
|
onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
10390
10390
|
ctx.atKey = false;
|
|
10391
|
-
const valueProps = resolveProps.resolveProps(
|
|
10391
|
+
const valueProps = resolveProps.resolveProps(sep4 ?? [], {
|
|
10392
10392
|
flow: fcName,
|
|
10393
10393
|
indicator: "map-value-ind",
|
|
10394
10394
|
next: value,
|
|
@@ -10399,8 +10399,8 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
10399
10399
|
});
|
|
10400
10400
|
if (valueProps.found) {
|
|
10401
10401
|
if (!isMap && !props.found && ctx.options.strict) {
|
|
10402
|
-
if (
|
|
10403
|
-
for (const st of
|
|
10402
|
+
if (sep4)
|
|
10403
|
+
for (const st of sep4) {
|
|
10404
10404
|
if (st === valueProps.found)
|
|
10405
10405
|
break;
|
|
10406
10406
|
if (st.type === "newline") {
|
|
@@ -10417,7 +10417,7 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
10417
10417
|
else
|
|
10418
10418
|
onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
|
|
10419
10419
|
}
|
|
10420
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end,
|
|
10420
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep4, null, valueProps, onError) : null;
|
|
10421
10421
|
if (valueNode) {
|
|
10422
10422
|
if (isBlock(value))
|
|
10423
10423
|
onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
@@ -10597,7 +10597,7 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
10597
10597
|
chompStart = i3 + 1;
|
|
10598
10598
|
}
|
|
10599
10599
|
let value = "";
|
|
10600
|
-
let
|
|
10600
|
+
let sep4 = "";
|
|
10601
10601
|
let prevMoreIndented = false;
|
|
10602
10602
|
for (let i3 = 0; i3 < contentStart; ++i3)
|
|
10603
10603
|
value += lines[i3][0].slice(trimIndent) + "\n";
|
|
@@ -10614,24 +10614,24 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
10614
10614
|
indent = "";
|
|
10615
10615
|
}
|
|
10616
10616
|
if (type === Scalar.Scalar.BLOCK_LITERAL) {
|
|
10617
|
-
value +=
|
|
10618
|
-
|
|
10617
|
+
value += sep4 + indent.slice(trimIndent) + content;
|
|
10618
|
+
sep4 = "\n";
|
|
10619
10619
|
} else if (indent.length > trimIndent || content[0] === " ") {
|
|
10620
|
-
if (
|
|
10621
|
-
|
|
10622
|
-
else if (!prevMoreIndented &&
|
|
10623
|
-
|
|
10624
|
-
value +=
|
|
10625
|
-
|
|
10620
|
+
if (sep4 === " ")
|
|
10621
|
+
sep4 = "\n";
|
|
10622
|
+
else if (!prevMoreIndented && sep4 === "\n")
|
|
10623
|
+
sep4 = "\n\n";
|
|
10624
|
+
value += sep4 + indent.slice(trimIndent) + content;
|
|
10625
|
+
sep4 = "\n";
|
|
10626
10626
|
prevMoreIndented = true;
|
|
10627
10627
|
} else if (content === "") {
|
|
10628
|
-
if (
|
|
10628
|
+
if (sep4 === "\n")
|
|
10629
10629
|
value += "\n";
|
|
10630
10630
|
else
|
|
10631
|
-
|
|
10631
|
+
sep4 = "\n";
|
|
10632
10632
|
} else {
|
|
10633
|
-
value +=
|
|
10634
|
-
|
|
10633
|
+
value += sep4 + content;
|
|
10634
|
+
sep4 = " ";
|
|
10635
10635
|
prevMoreIndented = false;
|
|
10636
10636
|
}
|
|
10637
10637
|
}
|
|
@@ -10813,25 +10813,25 @@ var require_resolve_flow_scalar = __commonJS({
|
|
|
10813
10813
|
if (!match)
|
|
10814
10814
|
return source;
|
|
10815
10815
|
let res = match[1];
|
|
10816
|
-
let
|
|
10816
|
+
let sep4 = " ";
|
|
10817
10817
|
let pos = first.lastIndex;
|
|
10818
10818
|
line.lastIndex = pos;
|
|
10819
10819
|
while (match = line.exec(source)) {
|
|
10820
10820
|
if (match[1] === "") {
|
|
10821
|
-
if (
|
|
10822
|
-
res +=
|
|
10821
|
+
if (sep4 === "\n")
|
|
10822
|
+
res += sep4;
|
|
10823
10823
|
else
|
|
10824
|
-
|
|
10824
|
+
sep4 = "\n";
|
|
10825
10825
|
} else {
|
|
10826
|
-
res +=
|
|
10827
|
-
|
|
10826
|
+
res += sep4 + match[1];
|
|
10827
|
+
sep4 = " ";
|
|
10828
10828
|
}
|
|
10829
10829
|
pos = line.lastIndex;
|
|
10830
10830
|
}
|
|
10831
10831
|
const last = /[ \t]*(.*)/sy;
|
|
10832
10832
|
last.lastIndex = pos;
|
|
10833
10833
|
match = last.exec(source);
|
|
10834
|
-
return res +
|
|
10834
|
+
return res + sep4 + (match?.[1] ?? "");
|
|
10835
10835
|
}
|
|
10836
10836
|
function doubleQuotedValue(source, onError) {
|
|
10837
10837
|
let res = "";
|
|
@@ -11641,14 +11641,14 @@ var require_cst_stringify = __commonJS({
|
|
|
11641
11641
|
}
|
|
11642
11642
|
}
|
|
11643
11643
|
}
|
|
11644
|
-
function stringifyItem({ start, key, sep:
|
|
11644
|
+
function stringifyItem({ start, key, sep: sep4, value }) {
|
|
11645
11645
|
let res = "";
|
|
11646
11646
|
for (const st of start)
|
|
11647
11647
|
res += st.source;
|
|
11648
11648
|
if (key)
|
|
11649
11649
|
res += stringifyToken(key);
|
|
11650
|
-
if (
|
|
11651
|
-
for (const st of
|
|
11650
|
+
if (sep4)
|
|
11651
|
+
for (const st of sep4)
|
|
11652
11652
|
res += st.source;
|
|
11653
11653
|
if (value)
|
|
11654
11654
|
res += stringifyToken(value);
|
|
@@ -12815,18 +12815,18 @@ var require_parser = __commonJS({
|
|
|
12815
12815
|
if (this.type === "map-value-ind") {
|
|
12816
12816
|
const prev = getPrevProps(this.peek(2));
|
|
12817
12817
|
const start = getFirstKeyStartProps(prev);
|
|
12818
|
-
let
|
|
12818
|
+
let sep4;
|
|
12819
12819
|
if (scalar.end) {
|
|
12820
|
-
|
|
12821
|
-
|
|
12820
|
+
sep4 = scalar.end;
|
|
12821
|
+
sep4.push(this.sourceToken);
|
|
12822
12822
|
delete scalar.end;
|
|
12823
12823
|
} else
|
|
12824
|
-
|
|
12824
|
+
sep4 = [this.sourceToken];
|
|
12825
12825
|
const map = {
|
|
12826
12826
|
type: "block-map",
|
|
12827
12827
|
offset: scalar.offset,
|
|
12828
12828
|
indent: scalar.indent,
|
|
12829
|
-
items: [{ start, key: scalar, sep:
|
|
12829
|
+
items: [{ start, key: scalar, sep: sep4 }]
|
|
12830
12830
|
};
|
|
12831
12831
|
this.onKeyLine = true;
|
|
12832
12832
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -12979,15 +12979,15 @@ var require_parser = __commonJS({
|
|
|
12979
12979
|
} else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
|
|
12980
12980
|
const start2 = getFirstKeyStartProps(it.start);
|
|
12981
12981
|
const key = it.key;
|
|
12982
|
-
const
|
|
12983
|
-
|
|
12982
|
+
const sep4 = it.sep;
|
|
12983
|
+
sep4.push(this.sourceToken);
|
|
12984
12984
|
delete it.key;
|
|
12985
12985
|
delete it.sep;
|
|
12986
12986
|
this.stack.push({
|
|
12987
12987
|
type: "block-map",
|
|
12988
12988
|
offset: this.offset,
|
|
12989
12989
|
indent: this.indent,
|
|
12990
|
-
items: [{ start: start2, key, sep:
|
|
12990
|
+
items: [{ start: start2, key, sep: sep4 }]
|
|
12991
12991
|
});
|
|
12992
12992
|
} else if (start.length > 0) {
|
|
12993
12993
|
it.sep = it.sep.concat(start, this.sourceToken);
|
|
@@ -13181,13 +13181,13 @@ var require_parser = __commonJS({
|
|
|
13181
13181
|
const prev = getPrevProps(parent);
|
|
13182
13182
|
const start = getFirstKeyStartProps(prev);
|
|
13183
13183
|
fixFlowSeqItems(fc);
|
|
13184
|
-
const
|
|
13185
|
-
|
|
13184
|
+
const sep4 = fc.end.splice(1, fc.end.length);
|
|
13185
|
+
sep4.push(this.sourceToken);
|
|
13186
13186
|
const map = {
|
|
13187
13187
|
type: "block-map",
|
|
13188
13188
|
offset: fc.offset,
|
|
13189
13189
|
indent: fc.indent,
|
|
13190
|
-
items: [{ start, key: fc, sep:
|
|
13190
|
+
items: [{ start, key: fc, sep: sep4 }]
|
|
13191
13191
|
};
|
|
13192
13192
|
this.onKeyLine = true;
|
|
13193
13193
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -13722,7 +13722,38 @@ function squireApprovalFromMcp(request, response) {
|
|
|
13722
13722
|
if (!link2)
|
|
13723
13723
|
return void 0;
|
|
13724
13724
|
const args = record(params?.arguments) ?? {};
|
|
13725
|
-
|
|
13725
|
+
const expiresAt = approvalExpiryIn(response.result);
|
|
13726
|
+
return {
|
|
13727
|
+
tool,
|
|
13728
|
+
...squireApprovalCopy(tool, args),
|
|
13729
|
+
...link2,
|
|
13730
|
+
...expiresAt !== void 0 ? { expiresAt } : {}
|
|
13731
|
+
};
|
|
13732
|
+
}
|
|
13733
|
+
function approvalExpiryIn(value, depth = 0) {
|
|
13734
|
+
if (depth > 6)
|
|
13735
|
+
return void 0;
|
|
13736
|
+
if (typeof value === "string") {
|
|
13737
|
+
if (value.length > 2e4 || !/^[{[]/.test(value.trim()))
|
|
13738
|
+
return void 0;
|
|
13739
|
+
try {
|
|
13740
|
+
return approvalExpiryIn(JSON.parse(value), depth + 1);
|
|
13741
|
+
} catch {
|
|
13742
|
+
return void 0;
|
|
13743
|
+
}
|
|
13744
|
+
}
|
|
13745
|
+
if (Array.isArray(value))
|
|
13746
|
+
return value.map((entry) => approvalExpiryIn(entry, depth + 1)).find((expiry) => expiry !== void 0);
|
|
13747
|
+
const item = record(value);
|
|
13748
|
+
if (!item)
|
|
13749
|
+
return void 0;
|
|
13750
|
+
const raw = item.expires_at ?? item.expiresAt;
|
|
13751
|
+
if (typeof raw === "string") {
|
|
13752
|
+
const parsed = Date.parse(raw);
|
|
13753
|
+
if (Number.isFinite(parsed) && parsed > 0)
|
|
13754
|
+
return parsed;
|
|
13755
|
+
}
|
|
13756
|
+
return Object.values(item).map((entry) => approvalExpiryIn(entry, depth + 1)).find((expiry) => expiry !== void 0);
|
|
13726
13757
|
}
|
|
13727
13758
|
function squireLoginWallIn(value, depth = 0) {
|
|
13728
13759
|
if (depth > 6)
|
|
@@ -14036,7 +14067,7 @@ function configureNetworkFamilyDefaults(network = net) {
|
|
|
14036
14067
|
configureNetworkFamilyDefaults();
|
|
14037
14068
|
|
|
14038
14069
|
// apps/body/dist/cli.js
|
|
14039
|
-
import { dirname as
|
|
14070
|
+
import { dirname as dirname32, resolve as resolve48 } from "node:path";
|
|
14040
14071
|
import { stdin as stdin4, stdout as stdout5 } from "node:process";
|
|
14041
14072
|
|
|
14042
14073
|
// node_modules/@clack/core/dist/index.mjs
|
|
@@ -15476,7 +15507,7 @@ function parseCursorModelsOutput(output) {
|
|
|
15476
15507
|
};
|
|
15477
15508
|
}
|
|
15478
15509
|
async function enumerateCursorModels(env = process.env) {
|
|
15479
|
-
return new Promise((
|
|
15510
|
+
return new Promise((resolve49) => {
|
|
15480
15511
|
const child = spawn2("cursor-agent", ["models"], {
|
|
15481
15512
|
env,
|
|
15482
15513
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -15490,11 +15521,11 @@ async function enumerateCursorModels(env = process.env) {
|
|
|
15490
15521
|
});
|
|
15491
15522
|
child.on("error", () => {
|
|
15492
15523
|
clearTimeout(timer);
|
|
15493
|
-
|
|
15524
|
+
resolve49(void 0);
|
|
15494
15525
|
});
|
|
15495
15526
|
child.on("close", (code) => {
|
|
15496
15527
|
clearTimeout(timer);
|
|
15497
|
-
|
|
15528
|
+
resolve49(code === 0 ? parseCursorModelsOutput(output) : void 0);
|
|
15498
15529
|
});
|
|
15499
15530
|
});
|
|
15500
15531
|
}
|
|
@@ -15921,13 +15952,13 @@ var CursorAcpServer = class {
|
|
|
15921
15952
|
consumeLine(line);
|
|
15922
15953
|
});
|
|
15923
15954
|
try {
|
|
15924
|
-
const { code, signal } = await new Promise((
|
|
15955
|
+
const { code, signal } = await new Promise((resolve49) => {
|
|
15925
15956
|
let settled = false;
|
|
15926
15957
|
const finish = (exitCode, exitSignal) => {
|
|
15927
15958
|
if (settled)
|
|
15928
15959
|
return;
|
|
15929
15960
|
settled = true;
|
|
15930
|
-
|
|
15961
|
+
resolve49({ code: exitCode, signal: exitSignal });
|
|
15931
15962
|
};
|
|
15932
15963
|
child.once("error", (error) => {
|
|
15933
15964
|
spawnError = error instanceof Error ? error.message : String(error);
|
|
@@ -16072,10 +16103,10 @@ function releaseSquireConnectSession(log2, owner = "") {
|
|
|
16072
16103
|
function squireChromeProfileDir() {
|
|
16073
16104
|
return process.env.TRUSTY_SQUIRE_PROFILE_DIR ?? squireHostPaths(homedir2()).profileDir;
|
|
16074
16105
|
}
|
|
16075
|
-
var defaultShellRunner = (command, args) => new Promise((
|
|
16106
|
+
var defaultShellRunner = (command, args) => new Promise((resolve49) => {
|
|
16076
16107
|
execFile(command, [...args], { timeout: 12e4, maxBuffer: 4 * 1024 * 1024, encoding: "utf8" }, (error, stdout6, stderr) => {
|
|
16077
16108
|
const code = error?.code;
|
|
16078
|
-
|
|
16109
|
+
resolve49({
|
|
16079
16110
|
code: typeof code === "number" ? code : error ? 1 : 0,
|
|
16080
16111
|
stdout: String(stdout6 ?? ""),
|
|
16081
16112
|
stderr: String(stderr ?? "")
|
|
@@ -16100,7 +16131,7 @@ function killConnectTree(child) {
|
|
|
16100
16131
|
}
|
|
16101
16132
|
child.kill();
|
|
16102
16133
|
}
|
|
16103
|
-
var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((
|
|
16134
|
+
var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((resolve49) => {
|
|
16104
16135
|
const child = spawn5(command, args, {
|
|
16105
16136
|
stdio: ["ignore", "pipe", "pipe"],
|
|
16106
16137
|
env: env ?? squireConnectProcessEnv(),
|
|
@@ -16114,7 +16145,7 @@ var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((res
|
|
|
16114
16145
|
const safetyTimer = setTimeout(() => {
|
|
16115
16146
|
if (!resolved) {
|
|
16116
16147
|
resolved = true;
|
|
16117
|
-
|
|
16148
|
+
resolve49({ stdout: stdout6, stderr, pid: child.pid ?? void 0, report, abort: () => {
|
|
16118
16149
|
} });
|
|
16119
16150
|
}
|
|
16120
16151
|
killConnectTree(child);
|
|
@@ -16149,7 +16180,7 @@ var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((res
|
|
|
16149
16180
|
const finish = (result) => {
|
|
16150
16181
|
if (!resolved) {
|
|
16151
16182
|
resolved = true;
|
|
16152
|
-
|
|
16183
|
+
resolve49(result);
|
|
16153
16184
|
}
|
|
16154
16185
|
};
|
|
16155
16186
|
const settle = (result) => {
|
|
@@ -16641,13 +16672,13 @@ var StdioSquireMcpClient = class {
|
|
|
16641
16672
|
const child = this.child;
|
|
16642
16673
|
if (!child)
|
|
16643
16674
|
return Promise.reject(new Error("Squire MCP session is not running"));
|
|
16644
|
-
return new Promise((
|
|
16675
|
+
return new Promise((resolve49, reject) => {
|
|
16645
16676
|
const timeoutMs = method === "initialize" ? INITIALIZE_TIMEOUT_MS : CALL_TIMEOUT_MS;
|
|
16646
16677
|
const timer = setTimeout(() => {
|
|
16647
16678
|
this.pending.delete(id);
|
|
16648
16679
|
reject(new Error(`${toolName2 ?? method} timed out after ${timeoutMs}ms`));
|
|
16649
16680
|
}, timeoutMs);
|
|
16650
|
-
this.pending.set(id, { resolve:
|
|
16681
|
+
this.pending.set(id, { resolve: resolve49, reject, timer });
|
|
16651
16682
|
child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}
|
|
16652
16683
|
`);
|
|
16653
16684
|
});
|
|
@@ -16809,9 +16840,9 @@ var SquireTaskRelay = class {
|
|
|
16809
16840
|
response.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ error: error instanceof Error ? error.message : "Squire relay failed" }));
|
|
16810
16841
|
}
|
|
16811
16842
|
});
|
|
16812
|
-
await new Promise((
|
|
16843
|
+
await new Promise((resolve49, reject) => {
|
|
16813
16844
|
server.once("error", reject);
|
|
16814
|
-
server.listen(0, "127.0.0.1",
|
|
16845
|
+
server.listen(0, "127.0.0.1", resolve49);
|
|
16815
16846
|
});
|
|
16816
16847
|
this.server = server;
|
|
16817
16848
|
const address = server.address();
|
|
@@ -17850,11 +17881,11 @@ var RegistryMcpHostBroker = class {
|
|
|
17850
17881
|
})();
|
|
17851
17882
|
});
|
|
17852
17883
|
});
|
|
17853
|
-
await new Promise((
|
|
17884
|
+
await new Promise((resolve49, reject) => {
|
|
17854
17885
|
this.server.once("error", reject);
|
|
17855
17886
|
this.server.listen(this.socketPath, () => {
|
|
17856
17887
|
this.server.off("error", reject);
|
|
17857
|
-
|
|
17888
|
+
resolve49();
|
|
17858
17889
|
});
|
|
17859
17890
|
});
|
|
17860
17891
|
chmodSync(this.socketPath, 384);
|
|
@@ -17863,12 +17894,12 @@ var RegistryMcpHostBroker = class {
|
|
|
17863
17894
|
const server = this.server;
|
|
17864
17895
|
this.server = void 0;
|
|
17865
17896
|
if (server)
|
|
17866
|
-
await new Promise((
|
|
17897
|
+
await new Promise((resolve49) => server.close(() => resolve49()));
|
|
17867
17898
|
rmSync(this.socketPath, { force: true });
|
|
17868
17899
|
}
|
|
17869
17900
|
};
|
|
17870
17901
|
async function brokerRequest(socketPath, request) {
|
|
17871
|
-
return new Promise((
|
|
17902
|
+
return new Promise((resolve49, reject) => {
|
|
17872
17903
|
const socket = createConnection3(socketPath);
|
|
17873
17904
|
let output = "";
|
|
17874
17905
|
socket.setEncoding("utf8");
|
|
@@ -17885,7 +17916,7 @@ async function brokerRequest(socketPath, request) {
|
|
|
17885
17916
|
throw new Error(parsed.error);
|
|
17886
17917
|
if (!Array.isArray(parsed.messages) || !parsed.messages.every((entry) => typeof entry === "string"))
|
|
17887
17918
|
throw new Error("Registry MCP broker returned an invalid response");
|
|
17888
|
-
|
|
17919
|
+
resolve49(parsed.messages);
|
|
17889
17920
|
} catch (error) {
|
|
17890
17921
|
reject(error);
|
|
17891
17922
|
}
|
|
@@ -18099,7 +18130,8 @@ var TURN_SILENCE_KINDS = [
|
|
|
18099
18130
|
"helper-out-of-date",
|
|
18100
18131
|
"update-interrupted",
|
|
18101
18132
|
"offline",
|
|
18102
|
-
"context-overflow"
|
|
18133
|
+
"context-overflow",
|
|
18134
|
+
"resource-limit"
|
|
18103
18135
|
];
|
|
18104
18136
|
var TURN_RECEIPT_REASON_KINDS = [
|
|
18105
18137
|
"hiccup",
|
|
@@ -18111,6 +18143,7 @@ var TURN_RECEIPT_REASON_KINDS = [
|
|
|
18111
18143
|
"update-interrupted",
|
|
18112
18144
|
"offline",
|
|
18113
18145
|
"context-overflow",
|
|
18146
|
+
"resource-limit",
|
|
18114
18147
|
"model-selection-unavailable"
|
|
18115
18148
|
];
|
|
18116
18149
|
function isTurnReceiptReasonKind(value) {
|
|
@@ -18158,6 +18191,9 @@ function classifyTurnSilence(reason, reasonKind) {
|
|
|
18158
18191
|
if (isContextOverflowFault(text2)) {
|
|
18159
18192
|
return { kind: "context-overflow" };
|
|
18160
18193
|
}
|
|
18194
|
+
if (/\bresource_limit: ACP session exceeded its \d+ MiB memory limit\b/i.test(text2)) {
|
|
18195
|
+
return { kind: "resource-limit" };
|
|
18196
|
+
}
|
|
18161
18197
|
if (/\b402\b/.test(text2) || /usage limit/i.test(text2) || /more credits/i.test(text2) || /quota/i.test(text2) || /allowance is spent/i.test(text2)) {
|
|
18162
18198
|
return {
|
|
18163
18199
|
kind: "allowance-spent",
|
|
@@ -19354,7 +19390,7 @@ var AgentSignIn = class {
|
|
|
19354
19390
|
};
|
|
19355
19391
|
for (const name of ISOLATION_VARIABLES)
|
|
19356
19392
|
delete env[name];
|
|
19357
|
-
return new Promise((
|
|
19393
|
+
return new Promise((resolve49, reject) => {
|
|
19358
19394
|
let output = "";
|
|
19359
19395
|
let answered = false;
|
|
19360
19396
|
let child;
|
|
@@ -19395,7 +19431,7 @@ var AgentSignIn = class {
|
|
|
19395
19431
|
return;
|
|
19396
19432
|
answered = true;
|
|
19397
19433
|
clearTimeout(linkTimer);
|
|
19398
|
-
|
|
19434
|
+
resolve49(link2);
|
|
19399
19435
|
};
|
|
19400
19436
|
child.stdout?.on("data", read2);
|
|
19401
19437
|
child.stderr?.on("data", read2);
|
|
@@ -29228,13 +29264,13 @@ var RoomSupervisor = class {
|
|
|
29228
29264
|
*/
|
|
29229
29265
|
retryDelay(failures, signal, since = this.#wakes) {
|
|
29230
29266
|
const delay = this.delaysMs[failures - 1];
|
|
29231
|
-
return new Promise((
|
|
29267
|
+
return new Promise((resolve49) => {
|
|
29232
29268
|
let timer;
|
|
29233
29269
|
const done = () => {
|
|
29234
29270
|
clearTimeout(timer);
|
|
29235
29271
|
this.#parked.delete(done);
|
|
29236
29272
|
signal?.removeEventListener("abort", done);
|
|
29237
|
-
|
|
29273
|
+
resolve49();
|
|
29238
29274
|
};
|
|
29239
29275
|
this.#parked.add(done);
|
|
29240
29276
|
signal?.addEventListener("abort", done, { once: true });
|
|
@@ -29426,12 +29462,12 @@ async function retryBeforeReady(work, options) {
|
|
|
29426
29462
|
if (wait2 <= 0)
|
|
29427
29463
|
break;
|
|
29428
29464
|
await options.extendStartTimeout(wait2 + 15e3);
|
|
29429
|
-
await new Promise((
|
|
29465
|
+
await new Promise((resolve49) => {
|
|
29430
29466
|
const timer = setTimeout(done, wait2);
|
|
29431
29467
|
function done() {
|
|
29432
29468
|
clearTimeout(timer);
|
|
29433
29469
|
options.signal?.removeEventListener("abort", done);
|
|
29434
|
-
|
|
29470
|
+
resolve49();
|
|
29435
29471
|
}
|
|
29436
29472
|
wake = done;
|
|
29437
29473
|
options.signal?.addEventListener("abort", done, { once: true });
|
|
@@ -29599,6 +29635,94 @@ import { resolve as resolve20 } from "node:path";
|
|
|
29599
29635
|
import { spawn as spawn11 } from "node:child_process";
|
|
29600
29636
|
import { EventEmitter } from "node:events";
|
|
29601
29637
|
|
|
29638
|
+
// apps/body/dist/acp-resource-scope.js
|
|
29639
|
+
import { execFile as execFile6 } from "node:child_process";
|
|
29640
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
29641
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
29642
|
+
import { totalmem } from "node:os";
|
|
29643
|
+
import { promisify as promisify5 } from "node:util";
|
|
29644
|
+
var execFileAsync5 = promisify5(execFile6);
|
|
29645
|
+
function acpSessionMemoryMaxBytes(hostMemoryBytes = totalmem()) {
|
|
29646
|
+
return Math.max(8 * 1024 ** 3, Math.floor(hostMemoryBytes / 4));
|
|
29647
|
+
}
|
|
29648
|
+
var ACP_SESSION_MEMORY_MAX_BYTES = acpSessionMemoryMaxBytes();
|
|
29649
|
+
var AcpResourceScope = class {
|
|
29650
|
+
memoryMaxBytes;
|
|
29651
|
+
unit = `beeline-acp-${randomUUID6()}.scope`;
|
|
29652
|
+
#stop;
|
|
29653
|
+
constructor(memoryMaxBytes = ACP_SESSION_MEMORY_MAX_BYTES) {
|
|
29654
|
+
this.memoryMaxBytes = memoryMaxBytes;
|
|
29655
|
+
}
|
|
29656
|
+
launch(command, args, agentEnv) {
|
|
29657
|
+
const env = { ...agentEnv };
|
|
29658
|
+
const stripBus = !Object.hasOwn(agentEnv, "DBUS_SESSION_BUS_ADDRESS");
|
|
29659
|
+
if (stripBus && process.env.DBUS_SESSION_BUS_ADDRESS)
|
|
29660
|
+
env.DBUS_SESSION_BUS_ADDRESS = process.env.DBUS_SESSION_BUS_ADDRESS;
|
|
29661
|
+
if (!env.XDG_RUNTIME_DIR && process.env.XDG_RUNTIME_DIR)
|
|
29662
|
+
env.XDG_RUNTIME_DIR = process.env.XDG_RUNTIME_DIR;
|
|
29663
|
+
const stripRuntime = !Object.hasOwn(agentEnv, "XDG_RUNTIME_DIR");
|
|
29664
|
+
const owner = managedServiceUnit();
|
|
29665
|
+
return {
|
|
29666
|
+
command: "systemd-run",
|
|
29667
|
+
args: [
|
|
29668
|
+
"--user",
|
|
29669
|
+
"--scope",
|
|
29670
|
+
"--quiet",
|
|
29671
|
+
"--same-dir",
|
|
29672
|
+
`--unit=${this.unit}`,
|
|
29673
|
+
`--property=MemoryMax=${this.memoryMaxBytes}`,
|
|
29674
|
+
"--property=MemorySwapMax=0",
|
|
29675
|
+
"--property=OOMPolicy=kill",
|
|
29676
|
+
"--property=KillMode=control-group",
|
|
29677
|
+
"--property=TimeoutStopSec=1s",
|
|
29678
|
+
...owner ? [`--property=BindsTo=${owner}`, `--property=After=${owner}`] : [],
|
|
29679
|
+
"/usr/bin/env",
|
|
29680
|
+
...stripBus ? ["-u", "DBUS_SESSION_BUS_ADDRESS"] : [],
|
|
29681
|
+
...stripRuntime ? ["-u", "XDG_RUNTIME_DIR"] : [],
|
|
29682
|
+
command,
|
|
29683
|
+
...args
|
|
29684
|
+
],
|
|
29685
|
+
env
|
|
29686
|
+
};
|
|
29687
|
+
}
|
|
29688
|
+
/** An OOM result survives process exit until reset-failed unloads the unit. */
|
|
29689
|
+
async exceededMemoryLimit() {
|
|
29690
|
+
try {
|
|
29691
|
+
const { stdout: stdout6 } = await execFileAsync5("systemctl", ["--user", "show", this.unit, "--property=Result", "--value"], { timeout: 5e3 });
|
|
29692
|
+
return stdout6.trim() === "oom-kill";
|
|
29693
|
+
} catch {
|
|
29694
|
+
return false;
|
|
29695
|
+
}
|
|
29696
|
+
}
|
|
29697
|
+
async stop() {
|
|
29698
|
+
return this.#stop ??= (async () => {
|
|
29699
|
+
try {
|
|
29700
|
+
await execFileAsync5("systemctl", ["--user", "stop", this.unit], { timeout: 5e3 });
|
|
29701
|
+
} catch (error) {
|
|
29702
|
+
const { stdout: stdout6 } = await execFileAsync5("systemctl", ["--user", "show", this.unit, "--property=LoadState", "--value"], { timeout: 5e3 });
|
|
29703
|
+
if (stdout6.trim() !== "not-found")
|
|
29704
|
+
throw error;
|
|
29705
|
+
} finally {
|
|
29706
|
+
await execFileAsync5("systemctl", ["--user", "reset-failed", this.unit], { timeout: 5e3 }).catch(() => void 0);
|
|
29707
|
+
}
|
|
29708
|
+
})().catch((error) => {
|
|
29709
|
+
this.#stop = void 0;
|
|
29710
|
+
throw error;
|
|
29711
|
+
});
|
|
29712
|
+
}
|
|
29713
|
+
};
|
|
29714
|
+
function managedServiceUnit() {
|
|
29715
|
+
if (process.env.BEELINE_MANAGED_BY_SYSTEMD !== "1")
|
|
29716
|
+
return void 0;
|
|
29717
|
+
try {
|
|
29718
|
+
const cgroup = readFileSync4("/proc/self/cgroup", "utf8");
|
|
29719
|
+
const path = cgroup.split("\n").find((line) => line.startsWith("0::"))?.slice(3);
|
|
29720
|
+
return path?.split("/").find((part) => /^beeline-(?:helper|agent@.+)\.service$/.test(part));
|
|
29721
|
+
} catch {
|
|
29722
|
+
return void 0;
|
|
29723
|
+
}
|
|
29724
|
+
}
|
|
29725
|
+
|
|
29602
29726
|
// apps/body/dist/harness-capabilities.js
|
|
29603
29727
|
var PROFILES = [
|
|
29604
29728
|
{
|
|
@@ -29912,6 +30036,13 @@ var AcpRuntimeExitedError = class extends Error {
|
|
|
29912
30036
|
this.name = "AcpRuntimeExitedError";
|
|
29913
30037
|
}
|
|
29914
30038
|
};
|
|
30039
|
+
var AcpResourceLimitError = class extends Error {
|
|
30040
|
+
cause = "resource_limit";
|
|
30041
|
+
constructor(memoryMaxBytes) {
|
|
30042
|
+
super(`resource_limit: ACP session exceeded its ${Math.floor(memoryMaxBytes / 1024 / 1024)} MiB memory limit`);
|
|
30043
|
+
this.name = "AcpResourceLimitError";
|
|
30044
|
+
}
|
|
30045
|
+
};
|
|
29915
30046
|
function killChildProcessGroup(child, signal) {
|
|
29916
30047
|
if (!child.pid)
|
|
29917
30048
|
return;
|
|
@@ -30196,6 +30327,10 @@ var AcpClient = class extends EventEmitter {
|
|
|
30196
30327
|
permissionAllowlist;
|
|
30197
30328
|
commandsHandler;
|
|
30198
30329
|
oomKills;
|
|
30330
|
+
useResourceScope;
|
|
30331
|
+
resourceScopeMemoryMaxBytes;
|
|
30332
|
+
resourceScope;
|
|
30333
|
+
resourceScopeUnavailable = false;
|
|
30199
30334
|
/** A deliberate stop owns its SIGKILL; that exit is never labelled OOM. */
|
|
30200
30335
|
stopping = false;
|
|
30201
30336
|
constructor(opts) {
|
|
@@ -30216,21 +30351,25 @@ var AcpClient = class extends EventEmitter {
|
|
|
30216
30351
|
this.permissionAllowlist = opts.permissionAllowlist;
|
|
30217
30352
|
this.commandsHandler = opts.onCommands;
|
|
30218
30353
|
this.oomKills = opts.oomKills ?? new OomKillTracker(cgroupOomKillProbe());
|
|
30354
|
+
this.useResourceScope = opts.resourceScope === "systemd" || opts.resourceScope === void 0 && process.platform === "linux" && process.env.BEELINE_MANAGED_BY_SYSTEMD === "1";
|
|
30355
|
+
this.resourceScopeMemoryMaxBytes = opts.resourceScopeMemoryMaxBytes;
|
|
30219
30356
|
}
|
|
30220
30357
|
async start(timeoutMs = 6e4) {
|
|
30221
30358
|
if (this.alive)
|
|
30222
30359
|
return;
|
|
30223
30360
|
await this.oomKills.prime().catch(() => void 0);
|
|
30224
30361
|
this.stopping = false;
|
|
30225
|
-
|
|
30362
|
+
const childEnv = this.inheritProcessEnv ? { ...process.env, ...this.agentEnv } : this.agentEnv;
|
|
30363
|
+
this.resourceScope = this.useResourceScope && !this.resourceScopeUnavailable ? new AcpResourceScope(this.resourceScopeMemoryMaxBytes) : void 0;
|
|
30364
|
+
const launch = this.resourceScope?.launch(this.agentCommand, this.agentArgs, childEnv);
|
|
30365
|
+
this.child = await withAdapterInstallLock(() => spawn11(launch?.command ?? this.agentCommand, launch?.args ?? this.agentArgs, {
|
|
30226
30366
|
// agentEnv is the child's whole environment: buildAgentEnv's allowlist is
|
|
30227
30367
|
// a real boundary, not a decorative one layered over a full inherit.
|
|
30228
|
-
env:
|
|
30368
|
+
env: launch?.env ?? childEnv,
|
|
30229
30369
|
...this.agentCwd ? { cwd: this.agentCwd } : {},
|
|
30230
|
-
//
|
|
30231
|
-
//
|
|
30232
|
-
|
|
30233
|
-
detached: process.platform !== "win32",
|
|
30370
|
+
// Managed Linux sessions use a cgroup scope. The process-group fallback
|
|
30371
|
+
// covers helpers without a user systemd manager.
|
|
30372
|
+
detached: !launch && process.platform !== "win32",
|
|
30234
30373
|
stdio: ["pipe", "pipe", "pipe"]
|
|
30235
30374
|
}));
|
|
30236
30375
|
this.alive = true;
|
|
@@ -30265,10 +30404,35 @@ var AcpClient = class extends EventEmitter {
|
|
|
30265
30404
|
if (this.listenerCount("error") > 0)
|
|
30266
30405
|
this.emit("error", err);
|
|
30267
30406
|
});
|
|
30268
|
-
|
|
30269
|
-
|
|
30270
|
-
|
|
30271
|
-
|
|
30407
|
+
let initResult;
|
|
30408
|
+
try {
|
|
30409
|
+
initResult = await this.request("initialize", {
|
|
30410
|
+
protocolVersion: 1,
|
|
30411
|
+
clientCapabilities: {}
|
|
30412
|
+
}, timeoutMs);
|
|
30413
|
+
} catch (error) {
|
|
30414
|
+
if (launch && /EPIPE/.test(String(error)) && this.child?.exitCode === null) {
|
|
30415
|
+
await new Promise((resolve49) => {
|
|
30416
|
+
const timer = setTimeout(resolve49, 250);
|
|
30417
|
+
this.child?.once("close", () => {
|
|
30418
|
+
clearTimeout(timer);
|
|
30419
|
+
resolve49();
|
|
30420
|
+
});
|
|
30421
|
+
});
|
|
30422
|
+
}
|
|
30423
|
+
const scopeUnavailable = launch && !this.resourceScopeUnavailable && /(?:Failed to connect to bus|Failed to create bus connection|spawn systemd-run ENOENT)/i.test(`${this.stderrTail}
|
|
30424
|
+
${String(error)}`);
|
|
30425
|
+
await this.stop().catch(() => void 0);
|
|
30426
|
+
if (scopeUnavailable) {
|
|
30427
|
+
this.resourceScopeUnavailable = true;
|
|
30428
|
+
this.resourceScope = void 0;
|
|
30429
|
+
this.child = null;
|
|
30430
|
+
this.alive = false;
|
|
30431
|
+
console.warn("[acp] systemd user scope unavailable; starting ACP session in a process group");
|
|
30432
|
+
return this.start(timeoutMs);
|
|
30433
|
+
}
|
|
30434
|
+
throw error;
|
|
30435
|
+
}
|
|
30272
30436
|
const initMeta = initResult._meta;
|
|
30273
30437
|
const steering = initMeta?.steering;
|
|
30274
30438
|
this.supportsStandardSteering = steering?.supported === true;
|
|
@@ -30281,22 +30445,25 @@ var AcpClient = class extends EventEmitter {
|
|
|
30281
30445
|
}
|
|
30282
30446
|
/**
|
|
30283
30447
|
* One child exit: reject every in-flight request so the turn fails and is
|
|
30284
|
-
* reported instead of hanging, then publish the exit. A
|
|
30285
|
-
*
|
|
30286
|
-
* cause instead of a bare signal.
|
|
30448
|
+
* reported instead of hanging, then publish the exit. A scoped exit reads
|
|
30449
|
+
* that scope's result; an unscoped SIGKILL uses the daemon cgroup's OOM
|
|
30450
|
+
* counter so the rejection can name the cause instead of a bare signal.
|
|
30287
30451
|
*/
|
|
30288
30452
|
async handleChildExit(code, signal) {
|
|
30453
|
+
const child = this.child;
|
|
30289
30454
|
this.alive = false;
|
|
30290
30455
|
for (const p of this.pending.values())
|
|
30291
30456
|
this.clearTimer(p);
|
|
30457
|
+
const scope = this.resourceScope;
|
|
30458
|
+
const memoryLimited = scope && !this.stopping ? await scope.exceededMemoryLimit() : false;
|
|
30292
30459
|
let oomKilled = false;
|
|
30293
|
-
if (signal === "SIGKILL" && !this.stopping) {
|
|
30460
|
+
if (!memoryLimited && signal === "SIGKILL" && !this.stopping) {
|
|
30294
30461
|
let diagnosticTimer;
|
|
30295
30462
|
try {
|
|
30296
30463
|
oomKilled = await Promise.race([
|
|
30297
30464
|
this.oomKills.consume().catch(() => false),
|
|
30298
|
-
new Promise((
|
|
30299
|
-
diagnosticTimer = setTimeout(() =>
|
|
30465
|
+
new Promise((resolve49) => {
|
|
30466
|
+
diagnosticTimer = setTimeout(() => resolve49(false), 100);
|
|
30300
30467
|
})
|
|
30301
30468
|
]);
|
|
30302
30469
|
} finally {
|
|
@@ -30308,13 +30475,21 @@ var AcpClient = class extends EventEmitter {
|
|
|
30308
30475
|
const stderrSuffix = meaningful ? `: ${meaningful}` : "";
|
|
30309
30476
|
for (const [, p] of this.pending) {
|
|
30310
30477
|
this.clearTimer(p);
|
|
30311
|
-
p.reject(new AcpRuntimeExitedError(`${exitText}${stderrSuffix}`));
|
|
30478
|
+
p.reject(memoryLimited ? new AcpResourceLimitError(scope.memoryMaxBytes) : new AcpRuntimeExitedError(`${exitText}${stderrSuffix}`));
|
|
30312
30479
|
}
|
|
30313
30480
|
this.pending.clear();
|
|
30314
30481
|
this.activeRunIds.clear();
|
|
30315
30482
|
this.activePromptSessions.clear();
|
|
30316
30483
|
this.toolCallMetadata.clear();
|
|
30317
30484
|
this.sessionCommands.clear();
|
|
30485
|
+
if (scope) {
|
|
30486
|
+
await scope.stop().then(() => {
|
|
30487
|
+
if (this.resourceScope === scope)
|
|
30488
|
+
this.resourceScope = void 0;
|
|
30489
|
+
if (this.child === child)
|
|
30490
|
+
this.child = null;
|
|
30491
|
+
}).catch((error) => console.error("[acp] resource scope cleanup failed:", error));
|
|
30492
|
+
}
|
|
30318
30493
|
this.emit("exit", { code, signal });
|
|
30319
30494
|
}
|
|
30320
30495
|
failRuntime(detail) {
|
|
@@ -30324,27 +30499,36 @@ var AcpClient = class extends EventEmitter {
|
|
|
30324
30499
|
p.reject(new AcpRuntimeExitedError(detail));
|
|
30325
30500
|
}
|
|
30326
30501
|
this.pending.clear();
|
|
30502
|
+
if (this.resourceScope)
|
|
30503
|
+
void this.resourceScope.stop().catch((error) => console.error("[acp] resource scope cleanup failed:", error));
|
|
30327
30504
|
}
|
|
30328
30505
|
async stop() {
|
|
30329
30506
|
const child = this.child;
|
|
30330
|
-
|
|
30507
|
+
const scope = this.resourceScope;
|
|
30508
|
+
if (!child && !scope)
|
|
30331
30509
|
return;
|
|
30332
30510
|
this.stopping = true;
|
|
30333
30511
|
try {
|
|
30334
|
-
if (
|
|
30512
|
+
if (child?.stdin.writable) {
|
|
30335
30513
|
this.notify("shutdown", {});
|
|
30336
30514
|
}
|
|
30337
30515
|
} catch {
|
|
30338
30516
|
}
|
|
30339
|
-
|
|
30340
|
-
|
|
30341
|
-
|
|
30342
|
-
|
|
30343
|
-
}
|
|
30344
|
-
|
|
30345
|
-
|
|
30346
|
-
|
|
30347
|
-
|
|
30517
|
+
if (scope) {
|
|
30518
|
+
await scope.stop();
|
|
30519
|
+
if (this.resourceScope === scope)
|
|
30520
|
+
this.resourceScope = void 0;
|
|
30521
|
+
} else if (child) {
|
|
30522
|
+
await new Promise((r2) => setTimeout(r2, 300));
|
|
30523
|
+
try {
|
|
30524
|
+
killChildProcessGroup(child, "SIGTERM");
|
|
30525
|
+
} catch {
|
|
30526
|
+
}
|
|
30527
|
+
await new Promise((r2) => setTimeout(r2, 500));
|
|
30528
|
+
try {
|
|
30529
|
+
killChildProcessGroup(child, "SIGKILL");
|
|
30530
|
+
} catch {
|
|
30531
|
+
}
|
|
30348
30532
|
}
|
|
30349
30533
|
this.child = null;
|
|
30350
30534
|
this.alive = false;
|
|
@@ -30720,7 +30904,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
30720
30904
|
const current = this.activeRunIds.get(sessionId);
|
|
30721
30905
|
if (current)
|
|
30722
30906
|
return Promise.resolve(current);
|
|
30723
|
-
return new Promise((
|
|
30907
|
+
return new Promise((resolve49, reject) => {
|
|
30724
30908
|
const onUpdate = (update) => {
|
|
30725
30909
|
if (update.sessionId !== sessionId)
|
|
30726
30910
|
return;
|
|
@@ -30728,7 +30912,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
30728
30912
|
if (!runId)
|
|
30729
30913
|
return;
|
|
30730
30914
|
cleanup();
|
|
30731
|
-
|
|
30915
|
+
resolve49(runId);
|
|
30732
30916
|
};
|
|
30733
30917
|
const timer = setTimeout(() => {
|
|
30734
30918
|
cleanup();
|
|
@@ -30807,14 +30991,14 @@ var AcpClient = class extends EventEmitter {
|
|
|
30807
30991
|
}
|
|
30808
30992
|
const id = this.nextId++;
|
|
30809
30993
|
const payload = { jsonrpc: "2.0", id, method, params };
|
|
30810
|
-
return new Promise((
|
|
30994
|
+
return new Promise((resolve49, reject) => {
|
|
30811
30995
|
const timer = backstop ? void 0 : setTimeout(() => {
|
|
30812
30996
|
this.pending.delete(id);
|
|
30813
30997
|
reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail, false, detail));
|
|
30814
30998
|
}, timeoutMs);
|
|
30815
30999
|
const sessionId = params?.sessionId;
|
|
30816
31000
|
this.pending.set(id, {
|
|
30817
|
-
resolve:
|
|
31001
|
+
resolve: resolve49,
|
|
30818
31002
|
reject,
|
|
30819
31003
|
timer,
|
|
30820
31004
|
method,
|
|
@@ -30845,7 +31029,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
30845
31029
|
|
|
30846
31030
|
// apps/body/dist/agent-home.js
|
|
30847
31031
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
30848
|
-
import { existsSync as existsSync7, readFileSync as
|
|
31032
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, watch } from "node:fs";
|
|
30849
31033
|
|
|
30850
31034
|
// node_modules/smol-toml/dist/date.js
|
|
30851
31035
|
var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
|
|
@@ -31013,7 +31197,7 @@ function skipVoid(ctx, banNewLines, banComments) {
|
|
|
31013
31197
|
skipComment(ctx);
|
|
31014
31198
|
}
|
|
31015
31199
|
}
|
|
31016
|
-
function skipUntil(ctx,
|
|
31200
|
+
function skipUntil(ctx, sep4, end) {
|
|
31017
31201
|
let ptr = ctx.p;
|
|
31018
31202
|
if (!end) {
|
|
31019
31203
|
ptr = indexOfNewline(ctx.s, ptr);
|
|
@@ -31024,7 +31208,7 @@ function skipUntil(ctx, sep3, end) {
|
|
|
31024
31208
|
let c2 = ctx.s.charCodeAt(ctx.p);
|
|
31025
31209
|
if (c2 === 35) {
|
|
31026
31210
|
skipComment(ctx);
|
|
31027
|
-
} else if (c2 === end || c2 ===
|
|
31211
|
+
} else if (c2 === end || c2 === sep4) {
|
|
31028
31212
|
return;
|
|
31029
31213
|
}
|
|
31030
31214
|
}
|
|
@@ -31642,7 +31826,7 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
|
|
|
31642
31826
|
}
|
|
31643
31827
|
|
|
31644
31828
|
// apps/body/dist/agent-home.js
|
|
31645
|
-
import { createHash as createHash7, randomUUID as
|
|
31829
|
+
import { createHash as createHash7, randomUUID as randomUUID7 } from "node:crypto";
|
|
31646
31830
|
import { chmod as chmod5, copyFile, lstat as lstat3, mkdir as mkdir11, readFile as readFile16, readlink, readdir as readdir4, realpath, rename as rename7, rm as rm6, symlink as symlink2, unlink as unlink5, writeFile as writeFile9 } from "node:fs/promises";
|
|
31647
31831
|
import { homedir as homedir11 } from "node:os";
|
|
31648
31832
|
import { basename as basename3, dirname as dirname12, join as join12, relative, resolve as resolve16, sep } from "node:path";
|
|
@@ -31768,7 +31952,7 @@ function androidAgentEnv(input) {
|
|
|
31768
31952
|
}
|
|
31769
31953
|
|
|
31770
31954
|
// apps/body/dist/beeline-skill.js
|
|
31771
|
-
import { readFileSync as
|
|
31955
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
31772
31956
|
import { resolve as resolve13 } from "node:path";
|
|
31773
31957
|
|
|
31774
31958
|
// packages/api-contract/dist/phone-types.js
|
|
@@ -32275,7 +32459,7 @@ var BEELINE_ROOM_MECHANICS = [
|
|
|
32275
32459
|
"If you need reach outside the sandbox, call beeline-agent request_grant. If you already know discrete options, call beeline-agent ask_choice (one human, optional) or open_poll (every human in this Room, required deadline). A poll is refused below two electors and above fifty, and in a DM. A plurality is a fact, never permission to deploy, delete, merge, or spend. Open-ended asks stay tagged prose. Never put Always / Once / No on a preference.",
|
|
32276
32460
|
"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."
|
|
32277
32461
|
].join(" ");
|
|
32278
|
-
function runningBeelineReleaseId(env = process.env, read2 = (path) =>
|
|
32462
|
+
function runningBeelineReleaseId(env = process.env, read2 = (path) => readFileSync5(path, "utf8")) {
|
|
32279
32463
|
try {
|
|
32280
32464
|
const lib = env.BEELINE_LIB_DIR;
|
|
32281
32465
|
if (!lib)
|
|
@@ -32312,7 +32496,7 @@ The tools this build knows, what each is for, and which the owner of this machin
|
|
|
32312
32496
|
|
|
32313
32497
|
**Use available tools before asking the person.** Before asking a person for a code, a status or a file, call workbench_status and check whether a tool or connected app you already have can get it, then use it. This includes an emailed verification code in an already-connected inbox. Ask only when none can, and say why. The key-ownership and grant rules still apply.
|
|
32314
32498
|
|
|
32315
|
-
**Offer the tool at the moment you need it.** When the work in front of you needs a tool the person does not have, do not send them to a settings page and do not stop at naming it. Call workbench_status first - a tool they already have is used, not offered. In a Room or DM, call offer_connector with the connectorType and one short reason: a card appears there, spoken by you, addressed to the person you are answering, with one action. Connector offers are unavailable in corners; use a Room or DM for those. Your turn pauses on the card - say in prose what you are waiting for and end the turn; you are woken when it is added, and then you carry on.
|
|
32499
|
+
**Offer the tool at the moment you need it.** When the work in front of you needs a tool the person does not have, do not send them to a settings page and do not stop at naming it. Call workbench_status first - a tool they already have is used, not offered. In a Room or DM, call offer_connector with the connectorType and one short reason: a card appears there, spoken by you, addressed to the person you are answering, with one action. Connector offers are unavailable in corners; use a Room or DM for those. When the person wants Squire on a different Google account (or its signed-in account is the wrong one), call offer_connector with connectorType trusty-squire and intent "switch" - a plain connect keeps the account it already has. Your turn pauses on the card - say in prose what you are waiting for and end the turn; you are woken when it is added, and then you carry on.
|
|
32316
32500
|
|
|
32317
32501
|
**Research before you offer, and say so.** Never offer a tool you cannot describe. If someone asks you to install or add something you do not already know - by name, by purpose, or by what it will hold - say plainly that you are looking it up first, find out what it is and what it does with credentials, and state what you learned in your reply BEFORE the card appears. A person reading "Add X?" must already have read, in your own words, what X is. Refusing to act blind is part of being trusted with keys.
|
|
32318
32502
|
|
|
@@ -33579,7 +33763,7 @@ async function writeBackDetachedClaudeLogin(target, source) {
|
|
|
33579
33763
|
const written = await withSharedClaudeLoginLock(shared, async () => {
|
|
33580
33764
|
if (!await isNewer())
|
|
33581
33765
|
return false;
|
|
33582
|
-
const temp = `${shared}.beeline-${
|
|
33766
|
+
const temp = `${shared}.beeline-${randomUUID7()}`;
|
|
33583
33767
|
try {
|
|
33584
33768
|
await writeFile9(temp, detached, { flag: "wx", mode: 384 });
|
|
33585
33769
|
await chmod5(temp, 384);
|
|
@@ -33596,7 +33780,7 @@ async function writeBackDetachedClaudeLogin(target, source) {
|
|
|
33596
33780
|
return "not-newer";
|
|
33597
33781
|
if (await readFile16(target, "utf8") !== detached)
|
|
33598
33782
|
return "busy";
|
|
33599
|
-
const link2 = `${target}.beeline-link-${
|
|
33783
|
+
const link2 = `${target}.beeline-link-${randomUUID7()}`;
|
|
33600
33784
|
await symlink2(source, link2);
|
|
33601
33785
|
await rename7(link2, target);
|
|
33602
33786
|
return "linked";
|
|
@@ -33626,7 +33810,7 @@ async function repairRoomAgentCredentialLinks(input) {
|
|
|
33626
33810
|
if (outcome !== "not-newer")
|
|
33627
33811
|
continue;
|
|
33628
33812
|
}
|
|
33629
|
-
const quarantine = `${target}.beeline-quarantine-${Date.now()}-${
|
|
33813
|
+
const quarantine = `${target}.beeline-quarantine-${Date.now()}-${randomUUID7()}`;
|
|
33630
33814
|
await rename7(target, quarantine);
|
|
33631
33815
|
}
|
|
33632
33816
|
await symlink2(source, target);
|
|
@@ -33745,7 +33929,7 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
|
|
|
33745
33929
|
try {
|
|
33746
33930
|
const source = resolve16(operatorHome, config.toml);
|
|
33747
33931
|
const target = resolve16(root, config.dir, "config.toml");
|
|
33748
|
-
const mcpSection = existsSync7(source) ? localHarnessMcpToml(
|
|
33932
|
+
const mcpSection = existsSync7(source) ? localHarnessMcpToml(readFileSync6(source, "utf8")) : void 0;
|
|
33749
33933
|
const section = config.dir === "codex" ? [CODEX_ROOM_AGENT_LOCKDOWN_TOML, CODEX_ROOM_WEB_SEARCH_TOML, mcpSection].filter(Boolean).join("\n") : mcpSection;
|
|
33750
33934
|
if (!section) {
|
|
33751
33935
|
await unlink5(target).catch(() => void 0);
|
|
@@ -33765,7 +33949,7 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
|
|
|
33765
33949
|
const source = resolve16(operatorHome, ".config", "goose", name);
|
|
33766
33950
|
const target = resolve16(gooseConfigDir, name);
|
|
33767
33951
|
if (existsSync7(source)) {
|
|
33768
|
-
const body =
|
|
33952
|
+
const body = readFileSync6(source, "utf8");
|
|
33769
33953
|
await writeIsolatedHarnessFile(target, name === "config.yaml" ? localGooseConfig(body) : body);
|
|
33770
33954
|
} else {
|
|
33771
33955
|
await unlink5(target).catch(() => void 0);
|
|
@@ -33843,7 +34027,7 @@ async function applyGrantedHostRoutes(root, operatorHome, granted, agentKind, fa
|
|
|
33843
34027
|
if (Object.keys(routes).length === 0)
|
|
33844
34028
|
continue;
|
|
33845
34029
|
const target = resolve16(root, config.dir, "config.toml");
|
|
33846
|
-
const existing = existsSync7(target) ?
|
|
34030
|
+
const existing = existsSync7(target) ? readFileSync6(target, "utf8") : void 0;
|
|
33847
34031
|
const merged = mergeTomlHostRoutes(existing, routes);
|
|
33848
34032
|
if (merged)
|
|
33849
34033
|
await writeIsolatedHarnessFile(target, merged);
|
|
@@ -33854,7 +34038,7 @@ async function applyGrantedHostRoutes(root, operatorHome, granted, agentKind, fa
|
|
|
33854
34038
|
const gooseConfigDir = resolve16(root, "goose", "config");
|
|
33855
34039
|
await mkdir11(gooseConfigDir, { recursive: true, mode: 448 });
|
|
33856
34040
|
const target = resolve16(gooseConfigDir, "config.yaml");
|
|
33857
|
-
const existing = existsSync7(target) ?
|
|
34041
|
+
const existing = existsSync7(target) ? readFileSync6(target, "utf8") : void 0;
|
|
33858
34042
|
const merged = mergeGooseHostRoutes(existing, routes);
|
|
33859
34043
|
if (merged)
|
|
33860
34044
|
await writeIsolatedHarnessFile(target, merged);
|
|
@@ -33929,7 +34113,7 @@ async function provisionPiCustomModelConfig(root, operatorHome, failClosed, open
|
|
|
33929
34113
|
if (resolvedSource !== source) {
|
|
33930
34114
|
throw new AgentHomeSecurityError(`Pi custom model config resolves through a link: ${source}`);
|
|
33931
34115
|
}
|
|
33932
|
-
const sourceValue = JSON.parse(
|
|
34116
|
+
const sourceValue = JSON.parse(readFileSync6(resolvedSource, "utf8"));
|
|
33933
34117
|
await writeIsolatedHarnessFile(target, `${JSON.stringify(withOpenRouterModelRouting(sourceValue, pin), null, 2)}
|
|
33934
34118
|
`);
|
|
33935
34119
|
} catch (error) {
|
|
@@ -33941,7 +34125,7 @@ async function provisionPiCustomModelConfig(root, operatorHome, failClosed, open
|
|
|
33941
34125
|
}
|
|
33942
34126
|
function readClaudeUserScopeMcpServers(path) {
|
|
33943
34127
|
try {
|
|
33944
|
-
const parsed = JSON.parse(
|
|
34128
|
+
const parsed = JSON.parse(readFileSync6(path, "utf8"));
|
|
33945
34129
|
const servers = recordValue2(parsed.mcpServers);
|
|
33946
34130
|
if (servers)
|
|
33947
34131
|
return localMcpServers(servers);
|
|
@@ -34142,7 +34326,7 @@ function readExistingText(path) {
|
|
|
34142
34326
|
if (!existsSync7(path))
|
|
34143
34327
|
return void 0;
|
|
34144
34328
|
try {
|
|
34145
|
-
return
|
|
34329
|
+
return readFileSync6(path, "utf8");
|
|
34146
34330
|
} catch {
|
|
34147
34331
|
return void 0;
|
|
34148
34332
|
}
|
|
@@ -34164,7 +34348,7 @@ async function provisionManagedSkillsDir(target, managedSkills, sharedSkills, op
|
|
|
34164
34348
|
const plan = await planManagedSkills(managedSkills, sharedSkills, optionalShares);
|
|
34165
34349
|
if (await materializedSkillManifest(target) === plan.manifest)
|
|
34166
34350
|
return;
|
|
34167
|
-
const staged = resolve16(parent, `.skills.${process.pid}.${
|
|
34351
|
+
const staged = resolve16(parent, `.skills.${process.pid}.${randomUUID7()}.tmp`);
|
|
34168
34352
|
await mkdir11(staged, { mode: 448 });
|
|
34169
34353
|
try {
|
|
34170
34354
|
for (const entry of plan.entries) {
|
|
@@ -34416,7 +34600,7 @@ async function writeIsolatedHarnessFile(path, content) {
|
|
|
34416
34600
|
if (!parentStats.isDirectory() || parentStats.isSymbolicLink()) {
|
|
34417
34601
|
throw new Error(`isolated harness parent is not a real directory: ${parent}`);
|
|
34418
34602
|
}
|
|
34419
|
-
const temporary = resolve16(parent, `.${basename3(path)}.${process.pid}.${
|
|
34603
|
+
const temporary = resolve16(parent, `.${basename3(path)}.${process.pid}.${randomUUID7()}.tmp`);
|
|
34420
34604
|
try {
|
|
34421
34605
|
await writeFile9(temporary, content, { mode: 384, flag: "wx" });
|
|
34422
34606
|
await chmod5(temporary, 384);
|
|
@@ -34473,8 +34657,8 @@ function harnessStateDirsFromEnv(env) {
|
|
|
34473
34657
|
}
|
|
34474
34658
|
|
|
34475
34659
|
// apps/body/dist/bwrap-sandbox.js
|
|
34476
|
-
import { execFile as
|
|
34477
|
-
import { lstatSync, readdirSync as readdirSync3, readFileSync as
|
|
34660
|
+
import { execFile as execFile7, spawnSync } from "node:child_process";
|
|
34661
|
+
import { lstatSync, readdirSync as readdirSync3, readFileSync as readFileSync7, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
34478
34662
|
import { homedir as homedir12 } from "node:os";
|
|
34479
34663
|
import { basename as basename4, dirname as dirname13, isAbsolute as isAbsolute2, relative as relative2, resolve as resolve17 } from "node:path";
|
|
34480
34664
|
var DEFAULT_SANDBOX_POLICY = "bwrap";
|
|
@@ -34533,7 +34717,7 @@ var KNOWN_CREDENTIAL_MASK_PATHS = [
|
|
|
34533
34717
|
".secrets.env",
|
|
34534
34718
|
".beeline/registry-mcp"
|
|
34535
34719
|
];
|
|
34536
|
-
function credentialMaskPaths(extraPaths, home = homedir12(),
|
|
34720
|
+
function credentialMaskPaths(extraPaths, home = homedir12(), stat11 = (path) => {
|
|
34537
34721
|
try {
|
|
34538
34722
|
const info = lstatSync(path);
|
|
34539
34723
|
return { isDirectory: info.isDirectory() };
|
|
@@ -34552,7 +34736,7 @@ function credentialMaskPaths(extraPaths, home = homedir12(), stat10 = (path) =>
|
|
|
34552
34736
|
if (seen.has(path))
|
|
34553
34737
|
continue;
|
|
34554
34738
|
seen.add(path);
|
|
34555
|
-
const info =
|
|
34739
|
+
const info = stat11(path);
|
|
34556
34740
|
if (!info) {
|
|
34557
34741
|
if (required.has(path))
|
|
34558
34742
|
masks.push({ path, kind: "dir", create: true });
|
|
@@ -34787,7 +34971,7 @@ function readInstallFailure(stateDir) {
|
|
|
34787
34971
|
if (!stateDir)
|
|
34788
34972
|
return void 0;
|
|
34789
34973
|
try {
|
|
34790
|
-
const at = Number.parseInt(
|
|
34974
|
+
const at = Number.parseInt(readFileSync7(installFailureMarker(stateDir), "utf8").trim(), 10);
|
|
34791
34975
|
return Number.isFinite(at) ? at : void 0;
|
|
34792
34976
|
} catch {
|
|
34793
34977
|
return void 0;
|
|
@@ -34810,8 +34994,8 @@ function clearInstallFailure(stateDir) {
|
|
|
34810
34994
|
} catch {
|
|
34811
34995
|
}
|
|
34812
34996
|
}
|
|
34813
|
-
var runSandboxInstallCommand = (command, args) => new Promise((
|
|
34814
|
-
|
|
34997
|
+
var runSandboxInstallCommand = (command, args) => new Promise((resolve49) => {
|
|
34998
|
+
execFile7(command, [...args], {
|
|
34815
34999
|
timeout: INSTALL_TIMEOUT_MS,
|
|
34816
35000
|
maxBuffer: INSTALL_OUTPUT_LIMIT * 2,
|
|
34817
35001
|
// A dpkg prompt on a host with a held conffile would otherwise sit on
|
|
@@ -34820,7 +35004,7 @@ var runSandboxInstallCommand = (command, args) => new Promise((resolve45) => {
|
|
|
34820
35004
|
}, (error, stdout6, stderr) => {
|
|
34821
35005
|
const code = error && "code" in error && typeof error.code === "number" ? error.code : error ? null : 0;
|
|
34822
35006
|
const output = [stdout6, stderr].join("").trim();
|
|
34823
|
-
|
|
35007
|
+
resolve49({ code, output: output || (error ? error.message : "") });
|
|
34824
35008
|
});
|
|
34825
35009
|
});
|
|
34826
35010
|
function lastLine2(output, fallback) {
|
|
@@ -35105,7 +35289,7 @@ function isAllowedAgentModelConfigCategory(category, id) {
|
|
|
35105
35289
|
}
|
|
35106
35290
|
|
|
35107
35291
|
// apps/body/dist/model-config.js
|
|
35108
|
-
import { lstatSync as lstatSync2, readFileSync as
|
|
35292
|
+
import { lstatSync as lstatSync2, readFileSync as readFileSync8 } from "node:fs";
|
|
35109
35293
|
import { basename as basename5, resolve as resolve19 } from "node:path";
|
|
35110
35294
|
|
|
35111
35295
|
// apps/body/dist/transient-provider-error.js
|
|
@@ -35331,7 +35515,7 @@ function credentialedPiCustomProviders(env) {
|
|
|
35331
35515
|
if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1 || stats.size > 1048576) {
|
|
35332
35516
|
return held;
|
|
35333
35517
|
}
|
|
35334
|
-
const parsed = JSON.parse(
|
|
35518
|
+
const parsed = JSON.parse(readFileSync8(path, "utf8"));
|
|
35335
35519
|
const providers = parsed.providers;
|
|
35336
35520
|
const remember = (name, config) => {
|
|
35337
35521
|
if (typeof name !== "string" || !name.trim() || !config || typeof config !== "object")
|
|
@@ -35564,7 +35748,7 @@ function describeCurrentReleaseOutcome(outcome) {
|
|
|
35564
35748
|
async function retryWhileAdapterReinstalls(run2, options = {}) {
|
|
35565
35749
|
const attempts = options.attempts ?? 12;
|
|
35566
35750
|
const delayMs = options.delayMs ?? 5e3;
|
|
35567
|
-
const sleep4 = options.sleep ?? ((ms) => new Promise((
|
|
35751
|
+
const sleep4 = options.sleep ?? ((ms) => new Promise((resolve49) => setTimeout(resolve49, ms)));
|
|
35568
35752
|
for (let attempt = 1; ; attempt += 1) {
|
|
35569
35753
|
try {
|
|
35570
35754
|
return await run2();
|
|
@@ -36792,7 +36976,7 @@ async function runStartCommand(args, interactiveUi, dependencyOverrides = {}) {
|
|
|
36792
36976
|
|
|
36793
36977
|
// apps/body/dist/connect-command.js
|
|
36794
36978
|
import { spawn as spawn13 } from "node:child_process";
|
|
36795
|
-
import { createHash as createHash9, randomUUID as
|
|
36979
|
+
import { createHash as createHash9, randomUUID as randomUUID8 } from "node:crypto";
|
|
36796
36980
|
import { chmod as chmod7, mkdir as mkdir16, readFile as readFile20, unlink as unlink7, writeFile as writeFile13 } from "node:fs/promises";
|
|
36797
36981
|
import { homedir as homedir15, hostname } from "node:os";
|
|
36798
36982
|
import { dirname as dirname19, resolve as resolve26 } from "node:path";
|
|
@@ -36912,7 +37096,7 @@ async function validateAgentModelSelection(agent, agentEnv, selection) {
|
|
|
36912
37096
|
}
|
|
36913
37097
|
|
|
36914
37098
|
// apps/body/dist/config.js
|
|
36915
|
-
import { accessSync as accessSync3, constants as constants2, existsSync as existsSync8, readFileSync as
|
|
37099
|
+
import { accessSync as accessSync3, constants as constants2, existsSync as existsSync8, readFileSync as readFileSync9 } from "node:fs";
|
|
36916
37100
|
import { basename as basename7, dirname as dirname17, resolve as resolve24 } from "node:path";
|
|
36917
37101
|
function firstExisting2(paths) {
|
|
36918
37102
|
for (const p of paths) {
|
|
@@ -37009,7 +37193,7 @@ function parseEnvFile(path) {
|
|
|
37009
37193
|
const out = {};
|
|
37010
37194
|
if (!existsSync8(path))
|
|
37011
37195
|
return out;
|
|
37012
|
-
const text2 =
|
|
37196
|
+
const text2 = readFileSync9(path, "utf8");
|
|
37013
37197
|
for (const raw of text2.split("\n")) {
|
|
37014
37198
|
const line = raw.trim();
|
|
37015
37199
|
if (!line || line.startsWith("#"))
|
|
@@ -37856,7 +38040,7 @@ async function readMachineId(env = process.env) {
|
|
|
37856
38040
|
if (!/^[0-9a-f-]{32,}$/.test(machineId))
|
|
37857
38041
|
throw new Error("invalid persisted machine id");
|
|
37858
38042
|
} catch {
|
|
37859
|
-
machineId =
|
|
38043
|
+
machineId = randomUUID8();
|
|
37860
38044
|
try {
|
|
37861
38045
|
await mkdir16(configDir, { recursive: true, mode: 448 });
|
|
37862
38046
|
await writeFile13(machineIdPath, `${machineId}
|
|
@@ -38186,7 +38370,7 @@ async function probeReleaseInSubprocess(input) {
|
|
|
38186
38370
|
return { kind: "unavailable", reason: `release ${input.releaseId} has no runnable CLI entrypoint` };
|
|
38187
38371
|
}
|
|
38188
38372
|
const timeoutMs = input.timeoutMs ?? CURRENT_RELEASE_PROBE_TIMEOUT_MS;
|
|
38189
|
-
return new Promise((
|
|
38373
|
+
return new Promise((resolve49) => {
|
|
38190
38374
|
const child = spawn14(input.execPath ?? process.execPath, [entrypoint, UPDATE_PROBE_COMMAND, "--config", input.runtimeConfigPath], { env: input.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] });
|
|
38191
38375
|
let stdout6 = "";
|
|
38192
38376
|
let stderr = "";
|
|
@@ -38196,7 +38380,7 @@ async function probeReleaseInSubprocess(input) {
|
|
|
38196
38380
|
return;
|
|
38197
38381
|
settled = true;
|
|
38198
38382
|
clearTimeout(timer);
|
|
38199
|
-
|
|
38383
|
+
resolve49(outcome);
|
|
38200
38384
|
};
|
|
38201
38385
|
const timer = setTimeout(() => {
|
|
38202
38386
|
child.kill("SIGKILL");
|
|
@@ -38276,12 +38460,12 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
38276
38460
|
}
|
|
38277
38461
|
|
|
38278
38462
|
// apps/body/dist/machine-helper.js
|
|
38279
|
-
import { mkdir as mkdir29, rename as rename13, stat as
|
|
38280
|
-
import { dirname as
|
|
38463
|
+
import { mkdir as mkdir29, rename as rename13, stat as stat10, writeFile as writeFile22 } from "node:fs/promises";
|
|
38464
|
+
import { dirname as dirname31, resolve as resolve47 } from "node:path";
|
|
38281
38465
|
|
|
38282
38466
|
// apps/body/dist/agent-runtime.js
|
|
38283
38467
|
import { homedir as homedir19 } from "node:os";
|
|
38284
|
-
import { dirname as
|
|
38468
|
+
import { dirname as dirname30, join as join23, resolve as resolve45 } from "node:path";
|
|
38285
38469
|
|
|
38286
38470
|
// apps/body/dist/model-availability.js
|
|
38287
38471
|
var SECRET_VALUE = /(?:token|key|secret|password)=?[^\s,;]*/gi;
|
|
@@ -38404,8 +38588,8 @@ async function syncAgentModelCatalog(input) {
|
|
|
38404
38588
|
}
|
|
38405
38589
|
|
|
38406
38590
|
// apps/body/dist/connector-tailscale.js
|
|
38407
|
-
import { execFile as
|
|
38408
|
-
import { randomUUID as
|
|
38591
|
+
import { execFile as execFile8 } from "node:child_process";
|
|
38592
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
38409
38593
|
import { rm as rm10 } from "node:fs/promises";
|
|
38410
38594
|
import { tmpdir as tmpdir3, userInfo } from "node:os";
|
|
38411
38595
|
import { join as join14 } from "node:path";
|
|
@@ -38415,10 +38599,10 @@ var LOGIN_URL = /https:\/\/login\.tailscale\.com\/[A-Za-z0-9_/-]+/u;
|
|
|
38415
38599
|
function clipped(value) {
|
|
38416
38600
|
return value.length <= OUTPUT_LIMIT ? value : value.slice(value.length - OUTPUT_LIMIT);
|
|
38417
38601
|
}
|
|
38418
|
-
var runTailscaleCommand = (command, args) => new Promise((
|
|
38419
|
-
|
|
38602
|
+
var runTailscaleCommand = (command, args) => new Promise((resolve49) => {
|
|
38603
|
+
execFile8(command, [...args], { timeout: COMMAND_TIMEOUT_MS, maxBuffer: OUTPUT_LIMIT * 2 }, (error, stdout6, stderr) => {
|
|
38420
38604
|
const code = error && "code" in error && typeof error.code === "number" ? error.code : error ? null : 0;
|
|
38421
|
-
|
|
38605
|
+
resolve49({ code, stdout: clipped(stdout6), stderr: clipped(stderr) });
|
|
38422
38606
|
});
|
|
38423
38607
|
});
|
|
38424
38608
|
function loginUrlFrom(status, output) {
|
|
@@ -38495,7 +38679,7 @@ async function ensureInstalled(run2, onProgress, platform) {
|
|
|
38495
38679
|
}
|
|
38496
38680
|
};
|
|
38497
38681
|
}
|
|
38498
|
-
const script = join14(tmpdir3(), `beeline-tailscale-install-${process.pid}-${
|
|
38682
|
+
const script = join14(tmpdir3(), `beeline-tailscale-install-${process.pid}-${randomUUID9()}.sh`);
|
|
38499
38683
|
const steps2 = [
|
|
38500
38684
|
step2("Tailscale installed", "running", {
|
|
38501
38685
|
command: "curl -fsSL https://tailscale.com/install.sh"
|
|
@@ -38978,16 +39162,16 @@ function describe2(error) {
|
|
|
38978
39162
|
}
|
|
38979
39163
|
|
|
38980
39164
|
// apps/body/dist/room-runtime.js
|
|
38981
|
-
import { execFile as
|
|
39165
|
+
import { execFile as execFile16 } from "node:child_process";
|
|
38982
39166
|
import { createHash as createHash14 } from "node:crypto";
|
|
38983
39167
|
import { existsSync as existsSync10, mkdirSync as mkdirSync3 } from "node:fs";
|
|
38984
|
-
import { mkdir as mkdir27, readdir as
|
|
38985
|
-
import { dirname as
|
|
38986
|
-
import { promisify as
|
|
39168
|
+
import { lstat as lstat7, mkdir as mkdir27, readdir as readdir11, realpath as realpath3, rm as rm17 } from "node:fs/promises";
|
|
39169
|
+
import { dirname as dirname28, relative as relative4, resolve as resolve40, sep as sep3 } from "node:path";
|
|
39170
|
+
import { promisify as promisify11 } from "node:util";
|
|
38987
39171
|
|
|
38988
39172
|
// apps/body/dist/grant-runner.js
|
|
38989
|
-
import { execFile as
|
|
38990
|
-
import { createHash as createHash11, randomBytes as randomBytes9, randomUUID as
|
|
39173
|
+
import { execFile as execFile9 } from "node:child_process";
|
|
39174
|
+
import { createHash as createHash11, randomBytes as randomBytes9, randomUUID as randomUUID10 } from "node:crypto";
|
|
38991
39175
|
import { chmod as chmod8, mkdir as mkdir17, readFile as readFile22, readdir as readdir6, rename as rename9, rm as rm11, rmdir, stat as stat7, writeFile as writeFile15 } from "node:fs/promises";
|
|
38992
39176
|
import { createServer as createServer3 } from "node:http";
|
|
38993
39177
|
import { dirname as dirname21, resolve as resolve28 } from "node:path";
|
|
@@ -39168,7 +39352,7 @@ var GrantCommandRunner = class {
|
|
|
39168
39352
|
const sandboxMarker = runsOnHost ? void 0 : `[beeline-sandbox-started:${randomBytes9(16).toString("hex")}]`;
|
|
39169
39353
|
const spawn15 = runsOnHost ? { command: argv[0], args: argv.slice(1) } : roomSandboxCommand(policy, room.cwd, argv, sandboxMarker);
|
|
39170
39354
|
const outcome = await new Promise((resolveRun) => {
|
|
39171
|
-
const child =
|
|
39355
|
+
const child = execFile9(spawn15.command, spawn15.args, {
|
|
39172
39356
|
cwd: room.cwd,
|
|
39173
39357
|
env,
|
|
39174
39358
|
timeout: this.options.timeoutMs ?? GRANT_COMMAND_TIMEOUT_MS,
|
|
@@ -39538,13 +39722,13 @@ var TurnUsageAccumulator = class {
|
|
|
39538
39722
|
};
|
|
39539
39723
|
|
|
39540
39724
|
// apps/body/dist/server-command-intake.js
|
|
39541
|
-
import { randomUUID as
|
|
39725
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
39542
39726
|
import { mkdir as mkdir18, writeFile as writeFile16 } from "node:fs/promises";
|
|
39543
39727
|
import { writeFileSync as writeFileSync4 } from "node:fs";
|
|
39544
39728
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
39545
39729
|
import { dirname as dirname22, join as join16 } from "node:path";
|
|
39546
39730
|
var CommandExecutionContext = class {
|
|
39547
|
-
generationId =
|
|
39731
|
+
generationId = randomUUID11();
|
|
39548
39732
|
path;
|
|
39549
39733
|
current;
|
|
39550
39734
|
constructor(root) {
|
|
@@ -39702,11 +39886,11 @@ async function runServerCommandIntake(options) {
|
|
|
39702
39886
|
if (attempt === 3)
|
|
39703
39887
|
throw error;
|
|
39704
39888
|
const waitMs = Math.max(250 * 2 ** attempt, error instanceof DaemonApiError ? error.retryAfterMs ?? 0 : 0);
|
|
39705
|
-
await new Promise((
|
|
39889
|
+
await new Promise((resolve49) => {
|
|
39706
39890
|
const done = () => {
|
|
39707
39891
|
clearTimeout(timer);
|
|
39708
39892
|
signal?.removeEventListener("abort", done);
|
|
39709
|
-
|
|
39893
|
+
resolve49();
|
|
39710
39894
|
};
|
|
39711
39895
|
const timer = setTimeout(done, waitMs);
|
|
39712
39896
|
signal?.addEventListener("abort", done, { once: true });
|
|
@@ -39797,11 +39981,11 @@ async function runServerCommandIntake(options) {
|
|
|
39797
39981
|
}
|
|
39798
39982
|
}
|
|
39799
39983
|
options.onPoll?.();
|
|
39800
|
-
const reconcile = await new Promise((
|
|
39984
|
+
const reconcile = await new Promise((resolve49) => {
|
|
39801
39985
|
const done = (needed) => {
|
|
39802
39986
|
signal?.removeEventListener("abort", aborted);
|
|
39803
39987
|
wake = void 0;
|
|
39804
|
-
|
|
39988
|
+
resolve49(needed);
|
|
39805
39989
|
};
|
|
39806
39990
|
const aborted = () => done(false);
|
|
39807
39991
|
wake = done;
|
|
@@ -39841,13 +40025,13 @@ async function runServerCommandIntake(options) {
|
|
|
39841
40025
|
}
|
|
39842
40026
|
|
|
39843
40027
|
// apps/body/dist/monolith-corner-turn.js
|
|
39844
|
-
import { execFile as
|
|
40028
|
+
import { execFile as execFile14 } from "node:child_process";
|
|
39845
40029
|
import { createHash as createHash13 } from "node:crypto";
|
|
39846
40030
|
import { existsSync as existsSync9 } from "node:fs";
|
|
39847
40031
|
import { mkdir as mkdir26, readFile as readFile30, writeFile as writeFile20 } from "node:fs/promises";
|
|
39848
40032
|
import { homedir as homedir18, hostname as hostname3 } from "node:os";
|
|
39849
|
-
import { dirname as dirname26, join as
|
|
39850
|
-
import { promisify as
|
|
40033
|
+
import { dirname as dirname26, join as join21, resolve as resolve38 } from "node:path";
|
|
40034
|
+
import { promisify as promisify9 } from "node:util";
|
|
39851
40035
|
|
|
39852
40036
|
// apps/body/dist/agent-command-catalog.js
|
|
39853
40037
|
function agentCommandCatalogPublisher(input) {
|
|
@@ -40497,13 +40681,13 @@ async function hasCornerPrepareScript(worktreePath) {
|
|
|
40497
40681
|
}
|
|
40498
40682
|
|
|
40499
40683
|
// apps/body/dist/pi-mcp-bridge.js
|
|
40500
|
-
import { execFile as
|
|
40684
|
+
import { execFile as execFile10 } from "node:child_process";
|
|
40501
40685
|
import { mkdtemp as mkdtemp2, mkdir as mkdir20, readFile as readFile26, rm as rm12, unlink as unlink8 } from "node:fs/promises";
|
|
40502
40686
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
40503
40687
|
import { resolve as resolve30 } from "node:path";
|
|
40504
|
-
import { promisify as
|
|
40688
|
+
import { promisify as promisify6 } from "node:util";
|
|
40505
40689
|
var PI_MCP_BRIDGE_FILENAME = "beeline-mcp-bridge.js";
|
|
40506
|
-
var
|
|
40690
|
+
var execFileAsync6 = promisify6(execFile10);
|
|
40507
40691
|
var nativeMcpProbes = /* @__PURE__ */ new Map();
|
|
40508
40692
|
async function piHasNativeMcp(command, env) {
|
|
40509
40693
|
const path = env?.PATH ?? process.env.PATH ?? "";
|
|
@@ -40513,7 +40697,7 @@ async function piHasNativeMcp(command, env) {
|
|
|
40513
40697
|
probe = (async () => {
|
|
40514
40698
|
const home = await mkdtemp2(resolve30(tmpdir5(), "beeline-pi-mcp-probe-"));
|
|
40515
40699
|
try {
|
|
40516
|
-
const { stdout: stdout6 } = await
|
|
40700
|
+
const { stdout: stdout6 } = await execFileAsync6(command, ["mcp", "list", "--json"], {
|
|
40517
40701
|
cwd: home,
|
|
40518
40702
|
timeout: 1200,
|
|
40519
40703
|
env: { PATH: path, HOME: home, PI_CODING_AGENT_DIR: home, PI_OFFLINE: "1" }
|
|
@@ -40810,7 +40994,7 @@ export default async function (pi) {
|
|
|
40810
40994
|
`;
|
|
40811
40995
|
|
|
40812
40996
|
// apps/body/dist/corner-branch-sync.js
|
|
40813
|
-
import { execFile as
|
|
40997
|
+
import { execFile as execFile11 } from "node:child_process";
|
|
40814
40998
|
import { access as access2, readFile as readFile27 } from "node:fs/promises";
|
|
40815
40999
|
import { resolve as resolve31 } from "node:path";
|
|
40816
41000
|
var CORNER_GIT_SYNC_TIMEOUT_MS = 12e4;
|
|
@@ -40818,7 +41002,7 @@ var CORNER_GIT_SYNC_KILL_GRACE_MS = 1e3;
|
|
|
40818
41002
|
var CornerGitSyncInterruptedError = class extends Error {
|
|
40819
41003
|
};
|
|
40820
41004
|
async function syncCornerBranch(input) {
|
|
40821
|
-
const
|
|
41005
|
+
const git2 = async (args, cleanup = false) => {
|
|
40822
41006
|
const controller = new AbortController();
|
|
40823
41007
|
const signal = input.signal && !cleanup ? AbortSignal.any([input.signal, controller.signal]) : controller.signal;
|
|
40824
41008
|
const timer = setTimeout(() => controller.abort(), CORNER_GIT_SYNC_TIMEOUT_MS);
|
|
@@ -40826,11 +41010,11 @@ async function syncCornerBranch(input) {
|
|
|
40826
41010
|
try {
|
|
40827
41011
|
if (signal.aborted)
|
|
40828
41012
|
throw interrupted();
|
|
40829
|
-
return await new Promise((
|
|
41013
|
+
return await new Promise((resolve49, reject) => {
|
|
40830
41014
|
let killTimer;
|
|
40831
41015
|
let stdout6 = "";
|
|
40832
41016
|
let failure = null;
|
|
40833
|
-
const child = input.git ? void 0 :
|
|
41017
|
+
const child = input.git ? void 0 : execFile11("git", ["-C", input.worktreePath, ...args], {
|
|
40834
41018
|
...input.env ? { env: input.env } : {},
|
|
40835
41019
|
signal,
|
|
40836
41020
|
maxBuffer: 4 * 1024 * 1024
|
|
@@ -40860,10 +41044,10 @@ async function syncCornerBranch(input) {
|
|
|
40860
41044
|
else if (failure)
|
|
40861
41045
|
reject(failure);
|
|
40862
41046
|
else
|
|
40863
|
-
|
|
41047
|
+
resolve49(stdout6);
|
|
40864
41048
|
});
|
|
40865
41049
|
else
|
|
40866
|
-
input.git(args).then(
|
|
41050
|
+
input.git(args).then(resolve49, reject).finally(cleanup2);
|
|
40867
41051
|
});
|
|
40868
41052
|
} finally {
|
|
40869
41053
|
clearTimeout(timer);
|
|
@@ -40873,10 +41057,10 @@ async function syncCornerBranch(input) {
|
|
|
40873
41057
|
const gitDir = resolve31(input.worktreePath, marker.startsWith("gitdir: ") ? marker.slice(8).trim() : ".git");
|
|
40874
41058
|
for (const directory of ["rebase-merge", "rebase-apply"]) {
|
|
40875
41059
|
if (await access2(resolve31(gitDir, directory)).then(() => true, () => false))
|
|
40876
|
-
await
|
|
41060
|
+
await git2(["rebase", "--abort"], true);
|
|
40877
41061
|
}
|
|
40878
41062
|
const remoteRef = `refs/remotes/origin/${input.featureBranch}`;
|
|
40879
|
-
const fetched = await
|
|
41063
|
+
const fetched = await git2([
|
|
40880
41064
|
"fetch",
|
|
40881
41065
|
"origin",
|
|
40882
41066
|
`+refs/heads/${input.featureBranch}:${remoteRef}`
|
|
@@ -40888,31 +41072,31 @@ async function syncCornerBranch(input) {
|
|
|
40888
41072
|
});
|
|
40889
41073
|
if (!fetched)
|
|
40890
41074
|
return "unchanged";
|
|
40891
|
-
const remote = (await
|
|
41075
|
+
const remote = (await git2(["rev-parse", remoteRef])).trim();
|
|
40892
41076
|
if (!remote)
|
|
40893
41077
|
throw new Error(`fetched corner branch has no remote ref: ${remoteRef}`);
|
|
40894
|
-
const local = (await
|
|
41078
|
+
const local = (await git2(["rev-parse", "HEAD"])).trim();
|
|
40895
41079
|
if (local === remote)
|
|
40896
41080
|
return "unchanged";
|
|
40897
|
-
if (await contains(
|
|
41081
|
+
if (await contains(git2, local, remote))
|
|
40898
41082
|
return "unchanged";
|
|
40899
|
-
const behind = await contains(
|
|
41083
|
+
const behind = await contains(git2, remote, local);
|
|
40900
41084
|
try {
|
|
40901
|
-
await
|
|
41085
|
+
await git2(behind ? ["merge", "--ff-only", remote] : ["rebase", remote]);
|
|
40902
41086
|
return behind ? "fast-forwarded" : "rebased";
|
|
40903
41087
|
} catch (error) {
|
|
40904
|
-
await
|
|
41088
|
+
await git2(["rebase", "--abort"], true).catch((error2) => {
|
|
40905
41089
|
if (error2 instanceof CornerGitSyncInterruptedError)
|
|
40906
41090
|
throw error2;
|
|
40907
41091
|
});
|
|
40908
41092
|
if (error instanceof CornerGitSyncInterruptedError)
|
|
40909
41093
|
throw error;
|
|
40910
|
-
await
|
|
41094
|
+
await git2(["reset", "--hard", remote]);
|
|
40911
41095
|
return "realigned";
|
|
40912
41096
|
}
|
|
40913
41097
|
}
|
|
40914
|
-
async function contains(
|
|
40915
|
-
return
|
|
41098
|
+
async function contains(git2, head, ancestor) {
|
|
41099
|
+
return git2(["merge-base", "--is-ancestor", ancestor, head]).then(() => true, (error) => {
|
|
40916
41100
|
if (error instanceof CornerGitSyncInterruptedError)
|
|
40917
41101
|
throw error;
|
|
40918
41102
|
return false;
|
|
@@ -41066,6 +41250,7 @@ var AGENT_SURFACE_TOOL_NAMES = [
|
|
|
41066
41250
|
"pr_checks_status",
|
|
41067
41251
|
"post_artifact",
|
|
41068
41252
|
"write_scratch_file",
|
|
41253
|
+
"scratch_status",
|
|
41069
41254
|
"fetch_image",
|
|
41070
41255
|
"connect_app"
|
|
41071
41256
|
];
|
|
@@ -41138,11 +41323,11 @@ function beelineAgentMcpServer(config, api, context) {
|
|
|
41138
41323
|
{ name: "BEELINE_DAEMON_ROOM_ID", value: context.roomId },
|
|
41139
41324
|
{ name: "BEELINE_DAEMON_WORKSPACE_ID", value: context.workspaceId },
|
|
41140
41325
|
...context.cornerId ? [{ name: "BEELINE_DAEMON_CORNER_ID", value: context.cornerId }] : [],
|
|
41141
|
-
...context.agentMayCloseCorner ? [{ name: "BEELINE_CORNER_AGENT_CLOSE", value: "1" }] : [],
|
|
41142
41326
|
...context.reviewer ? [{ name: "BEELINE_CORNER_REVIEWER", value: "1" }] : [],
|
|
41143
41327
|
...context.cornerId && context.repositoryBacked ? [{ name: "BEELINE_CORNER_REPOSITORY", value: "1" }] : [],
|
|
41144
41328
|
...context.attachRoot ? [{ name: "BEELINE_ATTACH_ROOT", value: context.attachRoot }] : [],
|
|
41145
41329
|
...context.attachScratchRoot ? [{ name: "BEELINE_ATTACH_SCRATCH_ROOT", value: context.attachScratchRoot }] : [],
|
|
41330
|
+
...context.cornerScratchRoot ? [{ name: "BEELINE_CORNER_SCRATCH_ROOT", value: context.cornerScratchRoot }] : [],
|
|
41146
41331
|
...context.grantRunner ? [
|
|
41147
41332
|
{ name: "BEELINE_GRANT_RUNNER_URL", value: context.grantRunner.url },
|
|
41148
41333
|
{ name: "BEELINE_GRANT_RUNNER_TOKEN", value: context.grantRunner.token }
|
|
@@ -41172,6 +41357,90 @@ function readOnlyMcpServer(config, cwd, agentMemoryDir) {
|
|
|
41172
41357
|
};
|
|
41173
41358
|
}
|
|
41174
41359
|
|
|
41360
|
+
// apps/body/dist/scratch-lifecycle.js
|
|
41361
|
+
import { execFile as execFile12 } from "node:child_process";
|
|
41362
|
+
import { lstat as lstat4, readdir as readdir7, rmdir as rmdir2, rm as rm13, stat as stat8, unlink as unlink9 } from "node:fs/promises";
|
|
41363
|
+
import { join as join18, resolve as resolve33 } from "node:path";
|
|
41364
|
+
import { promisify as promisify7 } from "node:util";
|
|
41365
|
+
var execFileAsync7 = promisify7(execFile12);
|
|
41366
|
+
var CORNER_SCRATCH_BUDGET_BYTES = 5 * 1024 ** 3;
|
|
41367
|
+
var CORNER_SCRATCH_TTL_MS = 14 * 24 * 60 * 6e4;
|
|
41368
|
+
var SHARED_MODEL_CACHE_BUDGET_BYTES = 32 * 1024 ** 3;
|
|
41369
|
+
var MODEL_CACHE_IDLE_MS = 24 * 60 * 6e4;
|
|
41370
|
+
async function allocatedDirectoryBytes(path) {
|
|
41371
|
+
if (!await lstat4(path).catch(() => void 0))
|
|
41372
|
+
return 0;
|
|
41373
|
+
const output = await execFileAsync7("du", ["-s", "-B1", "--", path], {
|
|
41374
|
+
maxBuffer: 1024 * 1024
|
|
41375
|
+
}).then((result) => result.stdout);
|
|
41376
|
+
const bytes = Number(output.split(/\s+/)[0]);
|
|
41377
|
+
if (!Number.isSafeInteger(bytes) || bytes < 0)
|
|
41378
|
+
throw new Error("scratch usage could not be measured");
|
|
41379
|
+
return bytes;
|
|
41380
|
+
}
|
|
41381
|
+
function scratchBudgetMessage(usage2, budget = CORNER_SCRATCH_BUDGET_BYTES) {
|
|
41382
|
+
const mib = (bytes) => Math.ceil(bytes / 1024 ** 2);
|
|
41383
|
+
return `Scratch ${mib(usage2)} / ${mib(budget)} MiB; files idle for 14 days expire. Use scratch_status and your shell to inspect, update or delete files. ${usage2 > budget ? "OVER BUDGET: remove files before writing more." : ""}`.trim();
|
|
41384
|
+
}
|
|
41385
|
+
function scratchGrowthExceedsBudget(usage2, atTurnStart, budget = CORNER_SCRATCH_BUDGET_BYTES) {
|
|
41386
|
+
return usage2 > budget && usage2 > atTurnStart;
|
|
41387
|
+
}
|
|
41388
|
+
async function sweepStaleCornerScratch(root, now2 = Date.now(), ttlMs = CORNER_SCRATCH_TTL_MS) {
|
|
41389
|
+
const cutoff = now2 - ttlMs;
|
|
41390
|
+
let files = 0;
|
|
41391
|
+
let bytes = 0;
|
|
41392
|
+
const visit = async (dir, top) => {
|
|
41393
|
+
for (const entry of await readdir7(dir, { withFileTypes: true }).catch(() => [])) {
|
|
41394
|
+
if (top && (entry.name === "agent-home" || entry.name === ".git"))
|
|
41395
|
+
continue;
|
|
41396
|
+
const path = join18(dir, entry.name);
|
|
41397
|
+
const info = await lstat4(path).catch(() => void 0);
|
|
41398
|
+
if (!info || info.isSymbolicLink())
|
|
41399
|
+
continue;
|
|
41400
|
+
if (info.isDirectory()) {
|
|
41401
|
+
await visit(path, false);
|
|
41402
|
+
if (!top)
|
|
41403
|
+
await rmdir2(path).catch(() => void 0);
|
|
41404
|
+
} else if (info.isFile() && info.mtimeMs < cutoff) {
|
|
41405
|
+
await unlink9(path);
|
|
41406
|
+
files++;
|
|
41407
|
+
bytes += info.size;
|
|
41408
|
+
}
|
|
41409
|
+
}
|
|
41410
|
+
};
|
|
41411
|
+
if ((await lstat4(root).catch(() => void 0))?.isDirectory())
|
|
41412
|
+
await visit(resolve33(root), true);
|
|
41413
|
+
return { files, bytes };
|
|
41414
|
+
}
|
|
41415
|
+
async function pruneSharedModelCache(root, now2 = Date.now(), budget = SHARED_MODEL_CACHE_BUDGET_BYTES) {
|
|
41416
|
+
let usage2 = await allocatedDirectoryBytes(root);
|
|
41417
|
+
if (usage2 <= budget)
|
|
41418
|
+
return [];
|
|
41419
|
+
const candidates = [];
|
|
41420
|
+
for (const parent of [join18(root, "hub"), root]) {
|
|
41421
|
+
for (const entry of await readdir7(parent, { withFileTypes: true }).catch(() => [])) {
|
|
41422
|
+
const eligible = parent === root ? entry.name === "xet" : /^(?:models|datasets|spaces)--/.test(entry.name);
|
|
41423
|
+
if (!eligible || !entry.isDirectory())
|
|
41424
|
+
continue;
|
|
41425
|
+
const path = join18(parent, entry.name);
|
|
41426
|
+
const info = await stat8(path);
|
|
41427
|
+
if (info.mtimeMs > now2 - MODEL_CACHE_IDLE_MS)
|
|
41428
|
+
continue;
|
|
41429
|
+
candidates.push({ path, usedAt: info.mtimeMs });
|
|
41430
|
+
}
|
|
41431
|
+
}
|
|
41432
|
+
candidates.sort((a2, b) => a2.usedAt - b.usedAt || a2.path.localeCompare(b.path));
|
|
41433
|
+
const removed = [];
|
|
41434
|
+
for (const item of candidates) {
|
|
41435
|
+
if (usage2 <= budget)
|
|
41436
|
+
break;
|
|
41437
|
+
await rm13(item.path, { recursive: true, force: true });
|
|
41438
|
+
usage2 = await allocatedDirectoryBytes(root);
|
|
41439
|
+
removed.push(item.path);
|
|
41440
|
+
}
|
|
41441
|
+
return removed;
|
|
41442
|
+
}
|
|
41443
|
+
|
|
41175
41444
|
// apps/body/dist/institutional-context.js
|
|
41176
41445
|
import { performance as performance2 } from "node:perf_hooks";
|
|
41177
41446
|
var INSTITUTIONAL_CONTEXT_TIMEOUT_MS = 500;
|
|
@@ -41220,16 +41489,16 @@ async function awaitInstitutionalContext(fetch2, log2 = console.warn, budgetMs =
|
|
|
41220
41489
|
}
|
|
41221
41490
|
|
|
41222
41491
|
// apps/body/dist/codegraph.js
|
|
41223
|
-
import { execFile as
|
|
41492
|
+
import { execFile as execFile13 } from "node:child_process";
|
|
41224
41493
|
import { access as access3, appendFile, mkdir as mkdir21, readFile as readFile28 } from "node:fs/promises";
|
|
41225
|
-
import { dirname as dirname23, isAbsolute as isAbsolute3, resolve as
|
|
41226
|
-
import { promisify as
|
|
41227
|
-
var
|
|
41494
|
+
import { dirname as dirname23, isAbsolute as isAbsolute3, resolve as resolve34 } from "node:path";
|
|
41495
|
+
import { promisify as promisify8 } from "node:util";
|
|
41496
|
+
var execFileAsync8 = promisify8(execFile13);
|
|
41228
41497
|
var CODEGRAPH_MCP_SERVER_NAME = "codegraph";
|
|
41229
41498
|
var CODEGRAPH_INDEX_PATH = ".codegraph/codegraph.db";
|
|
41230
41499
|
var CODEGRAPH_PREPARE_TIMEOUT_MS = 12e4;
|
|
41231
41500
|
function codegraphIndexDirectory(cwd) {
|
|
41232
|
-
return
|
|
41501
|
+
return resolve34(cwd, dirname23(CODEGRAPH_INDEX_PATH));
|
|
41233
41502
|
}
|
|
41234
41503
|
function codegraphMcpServer(config, cwd, options) {
|
|
41235
41504
|
if (!config.codegraphCommand)
|
|
@@ -41237,7 +41506,7 @@ function codegraphMcpServer(config, cwd, options) {
|
|
|
41237
41506
|
return {
|
|
41238
41507
|
name: CODEGRAPH_MCP_SERVER_NAME,
|
|
41239
41508
|
command: config.codegraphCommand,
|
|
41240
|
-
args: ["serve", "--mcp", "--path",
|
|
41509
|
+
args: ["serve", "--mcp", "--path", resolve34(cwd), ...options.readonly ? ["--no-watch"] : []],
|
|
41241
41510
|
env: [
|
|
41242
41511
|
{ name: "CODEGRAPH_TELEMETRY", value: "0" },
|
|
41243
41512
|
// One MCP child per harness session is easier to contain than a daemon
|
|
@@ -41251,25 +41520,25 @@ function codegraphFingerprintServers(config, servers, mounted = Boolean(config.c
|
|
|
41251
41520
|
}
|
|
41252
41521
|
async function isGitWorktree(cwd) {
|
|
41253
41522
|
try {
|
|
41254
|
-
const { stdout: stdout6 } = await
|
|
41523
|
+
const { stdout: stdout6 } = await execFileAsync8("git", ["rev-parse", "--show-toplevel"], {
|
|
41255
41524
|
cwd,
|
|
41256
41525
|
timeout: 1e4
|
|
41257
41526
|
});
|
|
41258
|
-
return
|
|
41527
|
+
return resolve34(stdout6.trim()) === resolve34(cwd);
|
|
41259
41528
|
} catch {
|
|
41260
41529
|
return false;
|
|
41261
41530
|
}
|
|
41262
41531
|
}
|
|
41263
41532
|
async function excludeIndexFromGitStatus(cwd) {
|
|
41264
41533
|
try {
|
|
41265
|
-
const { stdout: stdout6 } = await
|
|
41534
|
+
const { stdout: stdout6 } = await execFileAsync8("git", ["rev-parse", "--git-path", "info/exclude"], {
|
|
41266
41535
|
cwd,
|
|
41267
41536
|
timeout: 1e4
|
|
41268
41537
|
});
|
|
41269
41538
|
const gitPath = stdout6.trim();
|
|
41270
41539
|
if (!gitPath)
|
|
41271
41540
|
return;
|
|
41272
|
-
const path = isAbsolute3(gitPath) ? gitPath :
|
|
41541
|
+
const path = isAbsolute3(gitPath) ? gitPath : resolve34(cwd, gitPath);
|
|
41273
41542
|
await mkdir21(dirname23(path), { recursive: true });
|
|
41274
41543
|
const existing = await readFile28(path, "utf8").catch(() => "");
|
|
41275
41544
|
if (existing.split("\n").includes(".codegraph/"))
|
|
@@ -41284,11 +41553,11 @@ async function prepareCodegraphIndex(config, cwd) {
|
|
|
41284
41553
|
if (!command || !await isGitWorktree(cwd))
|
|
41285
41554
|
return false;
|
|
41286
41555
|
await excludeIndexFromGitStatus(cwd);
|
|
41287
|
-
const indexPath =
|
|
41556
|
+
const indexPath = resolve34(cwd, CODEGRAPH_INDEX_PATH);
|
|
41288
41557
|
const indexed = await access3(indexPath).then(() => true, () => false);
|
|
41289
41558
|
const args = indexed ? ["sync", "--quiet", cwd] : ["init", "--yes", cwd];
|
|
41290
41559
|
try {
|
|
41291
|
-
await
|
|
41560
|
+
await execFileAsync8(command, args, {
|
|
41292
41561
|
cwd,
|
|
41293
41562
|
env: { ...process.env, CODEGRAPH_TELEMETRY: "0", CODEGRAPH_NO_DAEMON: "1" },
|
|
41294
41563
|
timeout: CODEGRAPH_PREPARE_TIMEOUT_MS,
|
|
@@ -41304,7 +41573,7 @@ async function prepareCodegraphIndex(config, cwd) {
|
|
|
41304
41573
|
// apps/body/dist/monolith-room-turn.js
|
|
41305
41574
|
import { mkdir as mkdir23, writeFile as writeFile18 } from "node:fs/promises";
|
|
41306
41575
|
import { homedir as homedir17, hostname as hostname2 } from "node:os";
|
|
41307
|
-
import { dirname as dirname24, join as
|
|
41576
|
+
import { dirname as dirname24, join as join19 } from "node:path";
|
|
41308
41577
|
|
|
41309
41578
|
// packages/api-contract/dist/scheduled-prompts.js
|
|
41310
41579
|
var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
|
|
@@ -41408,6 +41677,7 @@ function cornerHasRepositoryWork(brief) {
|
|
|
41408
41677
|
var CORNER_RUNTIME_AUTHOR_CONTRACT = `The current brief's spec \u2014 stories, criteria, non-goals, risks \u2014 defines scope and done. The human approval quote wins any conflict. The short objective is navigation-only, never scope.
|
|
41409
41678
|
Meet every story; respect every non-goal and risk.
|
|
41410
41679
|
Before any code or build action, the brief must hold this ask's outline; opening and prompting inside it is not that outline. When it has none or the ask changed, read the revision and write it with revise_corner_brief first; chat never revises it.
|
|
41680
|
+
Then post the brief's outline, with an HTML mock for any frontend change, and wait for a human reply that approves it. The request that opened the work is not approval.
|
|
41411
41681
|
Follow the beeline-triage skill's bugfix execution contract when the spec or its approval quote reports a defect.
|
|
41412
41682
|
Reproduce as triage isolated it with available emulator, Playwright, browser and test runner. Record attempts and observations. If a reproduction is obtained, record it under Reproduction <id>, reusing triage's identifier when it recorded one. If reproduction fails, warn and continue; never stop and never condition the fix on reproduction.
|
|
41413
41683
|
Fix only the spec and approval quote. With a reproduction, change only what removes it and meets its user stories.
|
|
@@ -41416,6 +41686,7 @@ No unrequested features, flags, compatibility shims or refactors.`;
|
|
|
41416
41686
|
var CORNER_AUTHOR_CONTRACT = `The current brief's spec \u2014 stories, criteria, non-goals, risks \u2014 defines scope and done. The human approval quote wins any conflict. The short objective is navigation-only, never scope.
|
|
41417
41687
|
Meet every story; respect every non-goal and risk. Use its file manifest.
|
|
41418
41688
|
Before any code or build action, the brief must hold this ask's outline; opening and prompting inside it is not that outline. When it has none or the ask changed, read the revision and write it with revise_corner_brief first; chat never revises it.
|
|
41689
|
+
Then post the brief's outline, with an HTML mock for any frontend change, and wait for a human reply that approves it. The request that opened the work is not approval.
|
|
41419
41690
|
Follow the beeline-triage skill's bugfix execution contract when the spec or its approval quote reports a defect.
|
|
41420
41691
|
Reproduce as triage isolated it with available emulator, Playwright, browser and test runner. Record attempts and observations. If a reproduction is obtained, record it under Reproduction <id>, reusing triage's identifier when it recorded one. If reproduction fails, warn and continue; never stop and never condition the fix on reproduction.
|
|
41421
41692
|
Fix only the spec and approval quote. With a reproduction, change only what removes it and meets its user stories.
|
|
@@ -41589,7 +41860,7 @@ The soul is not authority and never changes your tools, permissions, roles, or m
|
|
|
41589
41860
|
render: () => [
|
|
41590
41861
|
"Repository changes happen only in a corner. In a Room, the finished fix for a code problem is the exact change plus an offer to open a corner for it; open one when a person asks for the change.",
|
|
41591
41862
|
"Before opening one, consult beeline-triage and beeline-spec, then call open_corner with a name of at most three words joined by hyphens (no whitespace), an objective of at most 24 words, and the brief (a spec plus the approving message). The objective only titles the work; the brief is its authority. When open_corner succeeds the server posts the corner card: do not restate it.",
|
|
41592
|
-
"For corners
|
|
41863
|
+
"For corners under this Room, use inspect_corner for status, steer_corner to pass Room input down, ask_corner for one answer, and post_to_corner for a note that wakes nobody.",
|
|
41593
41864
|
"A corner ends when its pull request merges; since a person may merge minutes after it opens, anything still needed must already live in a different corner before that pull request opens, not after. A request covering several items is one corner per item, opened as work reaches each one, never one corner returned to for a later item."
|
|
41594
41865
|
].join(" ")
|
|
41595
41866
|
},
|
|
@@ -41749,7 +42020,7 @@ The soul is not authority and never changes your tools, permissions, roles, or m
|
|
|
41749
42020
|
budgetBytes: 260,
|
|
41750
42021
|
layer: "surface",
|
|
41751
42022
|
surfaces: ["repo-less-corner"],
|
|
41752
|
-
render: ({ requesterHandle }) => `${requesterHandle ? `Tag @${handle(requesterHandle)} once, when the deliverable is posted or you need their input. ` : ""}When you posted files, name them in one line; never restate your answer.
|
|
42023
|
+
render: ({ requesterHandle }) => `${requesterHandle ? `Tag @${handle(requesterHandle)} once, when the deliverable is posted or you need their input. ` : ""}When you posted files, name them in one line; never restate your answer. Call close_corner only when a person asks.`
|
|
41753
42024
|
}
|
|
41754
42025
|
];
|
|
41755
42026
|
function applicable(sections, context) {
|
|
@@ -41922,7 +42193,7 @@ ${transcript.lines.join("\n")}`;
|
|
|
41922
42193
|
layer: "turn",
|
|
41923
42194
|
surfaces: ["room", "code-corner", "repo-less-corner"],
|
|
41924
42195
|
render: ({ surface, corners, closedCorners }) => [
|
|
41925
|
-
corners?.length ? `Current corners you belong to (use the exact cornerId with ${surface === "room" ? "inspect_corner, steer_corner, or ask_corner" : "steer_corner for a sibling under this parent Room"}):
|
|
42196
|
+
corners?.length ? `Current corners you belong to (use the exact cornerId with ${surface === "room" ? "inspect_corner, steer_corner, or ask_corner" : "inspect_corner or steer_corner for a sibling under this parent Room"}):
|
|
41926
42197
|
${JSON.stringify(corners)}` : "",
|
|
41927
42198
|
surface === "room" && closedCorners?.length ? `Corners you belong to closed in the last 24 hours (merge commit is unavailable when absent):
|
|
41928
42199
|
${closedCorners.map((corner) => `- ${corner.name ?? corner.cornerId} (${corner.cornerId}): PR ${corner.pullRequestNumber ? `#${corner.pullRequestNumber}` : "unavailable"}, merge commit ${corner.mergeCommitSha ?? "unavailable"}`).join("\n")}` : ""
|
|
@@ -41989,8 +42260,8 @@ function assembleTurnPrompt(context) {
|
|
|
41989
42260
|
}
|
|
41990
42261
|
|
|
41991
42262
|
// apps/body/dist/turn-trace.js
|
|
41992
|
-
import { appendFile as appendFile2, mkdir as mkdir22, readdir as
|
|
41993
|
-
import { resolve as
|
|
42263
|
+
import { appendFile as appendFile2, mkdir as mkdir22, readdir as readdir8, rm as rm14 } from "node:fs/promises";
|
|
42264
|
+
import { resolve as resolve35 } from "node:path";
|
|
41994
42265
|
import { performance as performance3 } from "node:perf_hooks";
|
|
41995
42266
|
var TURN_PHASES = [
|
|
41996
42267
|
/** Enqueued on `SessionScheduler` until this turn holds a slot. A capacity wait lives here. */
|
|
@@ -42276,7 +42547,7 @@ function formatTurnTraceLine(record5) {
|
|
|
42276
42547
|
return [head, ...record5.attempts.map((attempt) => formatTurnAttempt(attempt))].join("\n ");
|
|
42277
42548
|
}
|
|
42278
42549
|
function turnTraceDirectory(runtimeDir) {
|
|
42279
|
-
return
|
|
42550
|
+
return resolve35(runtimeDir, "turn-traces");
|
|
42280
42551
|
}
|
|
42281
42552
|
var TURN_TRACE_RETENTION_DAYS = 7;
|
|
42282
42553
|
function traceFileName(date) {
|
|
@@ -42293,7 +42564,7 @@ var TurnTraceFile = class {
|
|
|
42293
42564
|
this.options = options;
|
|
42294
42565
|
}
|
|
42295
42566
|
path(now2 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))()) {
|
|
42296
|
-
return
|
|
42567
|
+
return resolve35(this.directory, traceFileName(now2));
|
|
42297
42568
|
}
|
|
42298
42569
|
write(record5) {
|
|
42299
42570
|
this.tail = this.tail.catch(() => void 0).then(async () => {
|
|
@@ -42316,8 +42587,8 @@ var TurnTraceFile = class {
|
|
|
42316
42587
|
return;
|
|
42317
42588
|
this.prunedDay = day;
|
|
42318
42589
|
const cutoff = traceFileName(new Date(now2.getTime() - TURN_TRACE_RETENTION_DAYS * 864e5));
|
|
42319
|
-
const names = await
|
|
42320
|
-
await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) =>
|
|
42590
|
+
const names = await readdir8(this.directory).catch(() => []);
|
|
42591
|
+
await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm14(resolve35(this.directory, name), { force: true })));
|
|
42321
42592
|
}
|
|
42322
42593
|
};
|
|
42323
42594
|
|
|
@@ -42669,7 +42940,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
42669
42940
|
const cached = this.deliveredAttachments.get(item.id);
|
|
42670
42941
|
if (cached?.length === item.attachments.length)
|
|
42671
42942
|
return cached;
|
|
42672
|
-
const delivered = await deliverAttachments(item.attachments,
|
|
42943
|
+
const delivered = await deliverAttachments(item.attachments, join19(this.attachmentDir, item.id.replace(/[^\w-]/g, "_")), this.options.fetchImpl, cached);
|
|
42673
42944
|
this.deliveredAttachments.set(item.id, withoutImageData(delivered.filter((entry) => entry.path)));
|
|
42674
42945
|
return delivered;
|
|
42675
42946
|
}
|
|
@@ -42739,7 +43010,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
42739
43010
|
this.sessionFingerprint = void 0;
|
|
42740
43011
|
this.sessionCodegraphReady = false;
|
|
42741
43012
|
this.pinnedProviderOverride = void 0;
|
|
42742
|
-
if (client
|
|
43013
|
+
if (client)
|
|
42743
43014
|
await client.stop();
|
|
42744
43015
|
}
|
|
42745
43016
|
/**
|
|
@@ -42919,7 +43190,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
42919
43190
|
args: this.options.config.agentArgs ?? []
|
|
42920
43191
|
}, selection);
|
|
42921
43192
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
42922
|
-
this.attachmentDir = tmpDir ?
|
|
43193
|
+
this.attachmentDir = tmpDir ? join19(tmpDir, "beeline-attachments") : void 0;
|
|
42923
43194
|
this.sessionScratchDir = tmpDir;
|
|
42924
43195
|
this.sessionStateDirs = stateDirs;
|
|
42925
43196
|
const homeStateDirs = harnessHomeStateDirs(harnessLabel, agentEnv.HOME ?? operatorHome);
|
|
@@ -43160,7 +43431,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
43160
43431
|
this.sessionId = void 0;
|
|
43161
43432
|
this.sessionFingerprint = void 0;
|
|
43162
43433
|
this.sessionCodegraphReady = false;
|
|
43163
|
-
if (client
|
|
43434
|
+
if (client)
|
|
43164
43435
|
await client.stop();
|
|
43165
43436
|
this.pinnedProviderOverride = next;
|
|
43166
43437
|
await (trace ? trace.measure("activation", () => this.activate(trace)) : this.activate());
|
|
@@ -43239,8 +43510,8 @@ var MonolithRoomTurnLoop = class {
|
|
|
43239
43510
|
let timer;
|
|
43240
43511
|
const stats = statsPromise && remaining > 0 ? await Promise.race([
|
|
43241
43512
|
statsPromise,
|
|
43242
|
-
new Promise((
|
|
43243
|
-
timer = setTimeout(() =>
|
|
43513
|
+
new Promise((resolve49) => {
|
|
43514
|
+
timer = setTimeout(() => resolve49(void 0), remaining);
|
|
43244
43515
|
})
|
|
43245
43516
|
]).finally(() => {
|
|
43246
43517
|
if (timer)
|
|
@@ -43624,6 +43895,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
43624
43895
|
this.squireRelay.close();
|
|
43625
43896
|
this.options.grantRunner?.unregister(roomId);
|
|
43626
43897
|
await this.options.scheduler.suspend(roomId);
|
|
43898
|
+
this.options.scheduler.forget(roomId);
|
|
43627
43899
|
}
|
|
43628
43900
|
}
|
|
43629
43901
|
};
|
|
@@ -43654,9 +43926,9 @@ function roomMessagePrompt(author, body, attachments, delivered, harnessAcceptsI
|
|
|
43654
43926
|
|
|
43655
43927
|
// apps/body/dist/corner-github-auth.js
|
|
43656
43928
|
import { chmod as chmod9, mkdir as mkdir24, writeFile as writeFile19 } from "node:fs/promises";
|
|
43657
|
-
import { delimiter as delimiter3, resolve as
|
|
43929
|
+
import { delimiter as delimiter3, resolve as resolve36 } from "node:path";
|
|
43658
43930
|
async function installCornerGitHubWrappers(input) {
|
|
43659
|
-
const bin =
|
|
43931
|
+
const bin = resolve36(input.root, "beeline-github-bin");
|
|
43660
43932
|
await mkdir24(bin, { recursive: true, mode: 448 });
|
|
43661
43933
|
const common = {
|
|
43662
43934
|
node: process.execPath,
|
|
@@ -43668,13 +43940,13 @@ async function installCornerGitHubWrappers(input) {
|
|
|
43668
43940
|
gitCommand: input.gitBinary,
|
|
43669
43941
|
originUrl: input.originUrl ?? ""
|
|
43670
43942
|
};
|
|
43671
|
-
await writeLauncher(
|
|
43943
|
+
await writeLauncher(resolve36(bin, "git"), {
|
|
43672
43944
|
...common,
|
|
43673
43945
|
command: input.gitBinary,
|
|
43674
43946
|
launcher: "git",
|
|
43675
43947
|
restFallback: false
|
|
43676
43948
|
});
|
|
43677
|
-
await writeLauncher(
|
|
43949
|
+
await writeLauncher(resolve36(bin, "gh"), {
|
|
43678
43950
|
...common,
|
|
43679
43951
|
command: input.ghBinary ?? "",
|
|
43680
43952
|
launcher: "gh",
|
|
@@ -44109,37 +44381,37 @@ if (!refusal) {
|
|
|
44109
44381
|
}
|
|
44110
44382
|
|
|
44111
44383
|
// apps/body/dist/warm-node-modules.js
|
|
44112
|
-
import { createHash as createHash12, randomUUID as
|
|
44384
|
+
import { createHash as createHash12, randomUUID as randomUUID12 } from "node:crypto";
|
|
44113
44385
|
import { constants as fsConstants3 } from "node:fs";
|
|
44114
|
-
import { chmod as chmod10, copyFile as copyFile2, link, lstat as
|
|
44115
|
-
import { dirname as dirname25, join as
|
|
44386
|
+
import { chmod as chmod10, copyFile as copyFile2, link, lstat as lstat5, mkdir as mkdir25, readdir as readdir9, readFile as readFile29, readlink as readlink2, rename as rename10, rm as rm15, stat as stat9, symlink as symlink3, utimes } from "node:fs/promises";
|
|
44387
|
+
import { dirname as dirname25, join as join20, resolve as resolve37 } from "node:path";
|
|
44116
44388
|
var STORE_FORMAT = "v1";
|
|
44117
44389
|
var STAGING_PREFIX = ".beeline-warm-";
|
|
44118
44390
|
var STAGING_SWEEP_MS = 24 * 60 * 60 * 1e3;
|
|
44119
44391
|
var WARM_STORE_MAX_ENTRIES = 3;
|
|
44120
44392
|
function sharedNpmCacheDir(supervisorRoot) {
|
|
44121
|
-
return
|
|
44393
|
+
return resolve37(supervisorRoot, "beeline", "npm-cache");
|
|
44122
44394
|
}
|
|
44123
44395
|
function sharedPnpmStoreDir(supervisorRoot) {
|
|
44124
|
-
return
|
|
44396
|
+
return resolve37(supervisorRoot, "beeline", "pnpm-store");
|
|
44125
44397
|
}
|
|
44126
44398
|
function sharedCargoTargetDir(supervisorRoot) {
|
|
44127
|
-
return
|
|
44399
|
+
return resolve37(supervisorRoot, "beeline", "cargo-target");
|
|
44128
44400
|
}
|
|
44129
44401
|
function sharedTurboCacheDir(supervisorRoot) {
|
|
44130
|
-
return
|
|
44402
|
+
return resolve37(supervisorRoot, "beeline", "turbo-cache");
|
|
44131
44403
|
}
|
|
44132
44404
|
function warmNodeModulesStoreDir(supervisorRoot) {
|
|
44133
|
-
return
|
|
44405
|
+
return resolve37(supervisorRoot, "beeline", "node-modules");
|
|
44134
44406
|
}
|
|
44135
44407
|
function mobileNodeModulesStoreDir(supervisorRoot) {
|
|
44136
|
-
return
|
|
44408
|
+
return resolve37(supervisorRoot, "beeline", "node-modules-mobile");
|
|
44137
44409
|
}
|
|
44138
44410
|
function isPlanRefusal(value) {
|
|
44139
44411
|
return "failure" in value;
|
|
44140
44412
|
}
|
|
44141
44413
|
async function readWarmPlan(worktreePath) {
|
|
44142
|
-
const lockfile = await readFile29(
|
|
44414
|
+
const lockfile = await readFile29(resolve37(worktreePath, "package-lock.json")).catch(() => void 0);
|
|
44143
44415
|
if (!lockfile)
|
|
44144
44416
|
return { failure: "no-lockfile" };
|
|
44145
44417
|
const packages = parseLockfilePackages(lockfile);
|
|
@@ -44178,11 +44450,11 @@ async function seedWarmNodeModules(input) {
|
|
|
44178
44450
|
return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
|
|
44179
44451
|
}
|
|
44180
44452
|
for (const tree of plan.trees) {
|
|
44181
|
-
if (await pathExists(
|
|
44453
|
+
if (await pathExists(resolve37(input.worktreePath, tree))) {
|
|
44182
44454
|
return { reason: "present", key: plan.key };
|
|
44183
44455
|
}
|
|
44184
44456
|
}
|
|
44185
|
-
const entry =
|
|
44457
|
+
const entry = resolve37(input.storeRoot, plan.key);
|
|
44186
44458
|
if (!await isDirectory(entry))
|
|
44187
44459
|
return { reason: "cold", key: plan.key };
|
|
44188
44460
|
const [storeDevice, checkoutDevice] = await Promise.all([
|
|
@@ -44192,29 +44464,29 @@ async function seedWarmNodeModules(input) {
|
|
|
44192
44464
|
if (storeDevice === void 0 || storeDevice !== checkoutDevice) {
|
|
44193
44465
|
return { reason: "cross-device", key: plan.key };
|
|
44194
44466
|
}
|
|
44195
|
-
const staging =
|
|
44467
|
+
const staging = resolve37(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID12()}`);
|
|
44196
44468
|
const placed = [];
|
|
44197
44469
|
const now2 = (input.now ?? Date.now)();
|
|
44198
44470
|
try {
|
|
44199
44471
|
await sweepStaleStaging(input.storeRoot, now2);
|
|
44200
44472
|
await utimes(entry, now2 / 1e3, now2 / 1e3).catch(() => void 0);
|
|
44201
44473
|
for (const tree of plan.trees) {
|
|
44202
|
-
await cloneTree(
|
|
44474
|
+
await cloneTree(resolve37(entry, tree), resolve37(staging, tree), seedFile);
|
|
44203
44475
|
}
|
|
44204
44476
|
for (const tree of plan.trees) {
|
|
44205
|
-
const target =
|
|
44477
|
+
const target = resolve37(input.worktreePath, tree);
|
|
44206
44478
|
await mkdir25(dirname25(target), { recursive: true });
|
|
44207
|
-
await rename10(
|
|
44479
|
+
await rename10(resolve37(staging, tree), target);
|
|
44208
44480
|
placed.push(target);
|
|
44209
44481
|
}
|
|
44210
44482
|
return { reason: "seeded", key: plan.key };
|
|
44211
44483
|
} catch (error) {
|
|
44212
44484
|
for (const target of placed) {
|
|
44213
|
-
await
|
|
44485
|
+
await rm15(target, { recursive: true, force: true }).catch(() => void 0);
|
|
44214
44486
|
}
|
|
44215
44487
|
return { reason: "failed", key: plan.key, detail: describe3(error) };
|
|
44216
44488
|
} finally {
|
|
44217
|
-
await
|
|
44489
|
+
await rm15(staging, { recursive: true, force: true }).catch(() => void 0);
|
|
44218
44490
|
}
|
|
44219
44491
|
}
|
|
44220
44492
|
async function harvestWarmNodeModules(input) {
|
|
@@ -44222,11 +44494,11 @@ async function harvestWarmNodeModules(input) {
|
|
|
44222
44494
|
if (isPlanRefusal(plan)) {
|
|
44223
44495
|
return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
|
|
44224
44496
|
}
|
|
44225
|
-
const entry =
|
|
44497
|
+
const entry = resolve37(input.storeRoot, plan.key);
|
|
44226
44498
|
if (await pathExists(entry))
|
|
44227
44499
|
return { reason: "already-warm", key: plan.key };
|
|
44228
44500
|
for (const tree of plan.trees) {
|
|
44229
|
-
if (!await isDirectory(
|
|
44501
|
+
if (!await isDirectory(resolve37(input.worktreePath, tree))) {
|
|
44230
44502
|
return { reason: "no-node-modules", key: plan.key, detail: tree };
|
|
44231
44503
|
}
|
|
44232
44504
|
}
|
|
@@ -44238,12 +44510,12 @@ async function harvestWarmNodeModules(input) {
|
|
|
44238
44510
|
detail: `${missing.length} absent, e.g. ${missing.slice(0, 3).join(", ")}`
|
|
44239
44511
|
};
|
|
44240
44512
|
}
|
|
44241
|
-
const staging =
|
|
44513
|
+
const staging = resolve37(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID12()}`);
|
|
44242
44514
|
try {
|
|
44243
44515
|
await mkdir25(input.storeRoot, { recursive: true, mode: 493 });
|
|
44244
44516
|
await sweepStaleStaging(input.storeRoot, (input.now ?? Date.now)());
|
|
44245
44517
|
for (const tree of plan.trees) {
|
|
44246
|
-
await cloneTree(
|
|
44518
|
+
await cloneTree(resolve37(input.worktreePath, tree), resolve37(staging, tree), harvestFile);
|
|
44247
44519
|
}
|
|
44248
44520
|
await input.onCopied?.();
|
|
44249
44521
|
if (!await stagedTreeIsPublishable(input.worktreePath, staging, plan.key)) {
|
|
@@ -44257,25 +44529,25 @@ async function harvestWarmNodeModules(input) {
|
|
|
44257
44529
|
return { reason: "already-warm", key: plan.key };
|
|
44258
44530
|
return { reason: "failed", key: plan.key, detail: describe3(error) };
|
|
44259
44531
|
} finally {
|
|
44260
|
-
await
|
|
44532
|
+
await rm15(staging, { recursive: true, force: true }).catch(() => void 0);
|
|
44261
44533
|
}
|
|
44262
44534
|
}
|
|
44263
44535
|
async function stagedTreeIsPublishable(worktreePath, staging, key) {
|
|
44264
44536
|
const settled = await readWarmPlan(worktreePath);
|
|
44265
44537
|
if (isPlanRefusal(settled) || settled.key !== key)
|
|
44266
44538
|
return false;
|
|
44267
|
-
const hidden =
|
|
44539
|
+
const hidden = join20("node_modules", ".package-lock.json");
|
|
44268
44540
|
const [copied, current] = await Promise.all([
|
|
44269
|
-
readFile29(
|
|
44270
|
-
readFile29(
|
|
44541
|
+
readFile29(resolve37(staging, hidden)).catch(() => void 0),
|
|
44542
|
+
readFile29(resolve37(worktreePath, hidden)).catch(() => void 0)
|
|
44271
44543
|
]);
|
|
44272
44544
|
if (!copied || !current || !copied.equals(current))
|
|
44273
44545
|
return false;
|
|
44274
44546
|
return (await missingInstalledPackages(worktreePath, staging)).length === 0;
|
|
44275
44547
|
}
|
|
44276
44548
|
async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
|
|
44277
|
-
const wanted = parseLockfilePackages(await readFile29(
|
|
44278
|
-
const installed = parseLockfilePackages(await readFile29(
|
|
44549
|
+
const wanted = parseLockfilePackages(await readFile29(resolve37(worktreePath, "package-lock.json")).catch(() => void 0));
|
|
44550
|
+
const installed = parseLockfilePackages(await readFile29(resolve37(treeRoot, "node_modules", ".package-lock.json")).catch(() => void 0));
|
|
44279
44551
|
if (!wanted)
|
|
44280
44552
|
return ["package-lock.json is unreadable"];
|
|
44281
44553
|
if (!installed)
|
|
@@ -44295,14 +44567,14 @@ async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
|
|
|
44295
44567
|
required.push(path);
|
|
44296
44568
|
}
|
|
44297
44569
|
await mapWithLimit(required, INTEGRITY_READ_CONCURRENCY, async (path) => {
|
|
44298
|
-
if (!(path in installed) || !await isInstalledPackage(
|
|
44570
|
+
if (!(path in installed) || !await isInstalledPackage(resolve37(treeRoot, path))) {
|
|
44299
44571
|
missing.push(path);
|
|
44300
44572
|
}
|
|
44301
44573
|
});
|
|
44302
44574
|
return missing.sort();
|
|
44303
44575
|
}
|
|
44304
44576
|
async function isInstalledPackage(path) {
|
|
44305
|
-
return
|
|
44577
|
+
return stat9(join20(path, "package.json")).then((info) => info.isFile(), () => false);
|
|
44306
44578
|
}
|
|
44307
44579
|
var INTEGRITY_READ_CONCURRENCY = 64;
|
|
44308
44580
|
async function mapWithLimit(values, limit, visit) {
|
|
@@ -44335,9 +44607,9 @@ function isContainedTreePath(value) {
|
|
|
44335
44607
|
}
|
|
44336
44608
|
async function cloneTree(source, target, file, topLevel = true) {
|
|
44337
44609
|
await mkdir25(target, { recursive: true, mode: 493 });
|
|
44338
|
-
for (const entry of await
|
|
44339
|
-
const from =
|
|
44340
|
-
const to =
|
|
44610
|
+
for (const entry of await readdir9(source, { withFileTypes: true })) {
|
|
44611
|
+
const from = join20(source, entry.name);
|
|
44612
|
+
const to = join20(target, entry.name);
|
|
44341
44613
|
if (entry.isSymbolicLink()) {
|
|
44342
44614
|
await symlink3(await readlink2(from), to);
|
|
44343
44615
|
continue;
|
|
@@ -44352,7 +44624,7 @@ async function cloneTree(source, target, file, topLevel = true) {
|
|
|
44352
44624
|
}
|
|
44353
44625
|
var harvestFile = async (source, target) => {
|
|
44354
44626
|
await copyFile2(source, target, fsConstants3.COPYFILE_FICLONE);
|
|
44355
|
-
const info = await
|
|
44627
|
+
const info = await stat9(source);
|
|
44356
44628
|
await chmod10(target, info.mode & 4095 & ~146);
|
|
44357
44629
|
};
|
|
44358
44630
|
var seedFile = async (source, target, topLevel) => {
|
|
@@ -44364,46 +44636,46 @@ var seedFile = async (source, target, topLevel) => {
|
|
|
44364
44636
|
await chmod10(target, 420);
|
|
44365
44637
|
};
|
|
44366
44638
|
async function pruneWarmStore(storeRoot, keep) {
|
|
44367
|
-
const names = (await
|
|
44639
|
+
const names = (await readdir9(storeRoot).catch(() => [])).filter((name) => !name.startsWith(STAGING_PREFIX));
|
|
44368
44640
|
const entries = [];
|
|
44369
44641
|
for (const name of names) {
|
|
44370
|
-
const info = await
|
|
44642
|
+
const info = await lstat5(join20(storeRoot, name)).catch(() => void 0);
|
|
44371
44643
|
if (info?.isDirectory())
|
|
44372
44644
|
entries.push({ name, usedAt: info.mtimeMs });
|
|
44373
44645
|
}
|
|
44374
44646
|
const dropped = entries.sort((a2, b) => b.usedAt - a2.usedAt || a2.name.localeCompare(b.name)).slice(keep);
|
|
44375
44647
|
for (const entry of dropped) {
|
|
44376
|
-
await
|
|
44648
|
+
await rm15(join20(storeRoot, entry.name), { recursive: true, force: true }).catch(() => void 0);
|
|
44377
44649
|
}
|
|
44378
44650
|
return dropped.map((entry) => entry.name);
|
|
44379
44651
|
}
|
|
44380
44652
|
async function sweepStaleStaging(storeRoot, now2) {
|
|
44381
|
-
const entries = await
|
|
44653
|
+
const entries = await readdir9(storeRoot).catch(() => []);
|
|
44382
44654
|
for (const name of entries) {
|
|
44383
44655
|
if (!name.startsWith(STAGING_PREFIX))
|
|
44384
44656
|
continue;
|
|
44385
|
-
const path =
|
|
44386
|
-
const info = await
|
|
44657
|
+
const path = join20(storeRoot, name);
|
|
44658
|
+
const info = await lstat5(path).catch(() => void 0);
|
|
44387
44659
|
if (!info || now2 - info.mtimeMs < STAGING_SWEEP_MS)
|
|
44388
44660
|
continue;
|
|
44389
|
-
await
|
|
44661
|
+
await rm15(path, { recursive: true, force: true }).catch(() => void 0);
|
|
44390
44662
|
}
|
|
44391
44663
|
}
|
|
44392
44664
|
async function pathExists(path) {
|
|
44393
|
-
return
|
|
44665
|
+
return lstat5(path).then(() => true, () => false);
|
|
44394
44666
|
}
|
|
44395
44667
|
async function deviceOf(path) {
|
|
44396
|
-
return
|
|
44668
|
+
return stat9(path).then((info) => info.dev, () => void 0);
|
|
44397
44669
|
}
|
|
44398
44670
|
async function isDirectory(path) {
|
|
44399
|
-
return
|
|
44671
|
+
return stat9(path).then((info) => info.isDirectory(), () => false);
|
|
44400
44672
|
}
|
|
44401
44673
|
function describe3(error) {
|
|
44402
44674
|
return error instanceof Error ? error.message : String(error);
|
|
44403
44675
|
}
|
|
44404
44676
|
|
|
44405
44677
|
// apps/body/dist/monolith-corner-turn.js
|
|
44406
|
-
var
|
|
44678
|
+
var execFileAsync9 = promisify9(execFile14);
|
|
44407
44679
|
var TOOL_ARGUMENT_MAX_BYTES = 1200;
|
|
44408
44680
|
var TOOL_OUTPUT_MAX_BYTES = 3200;
|
|
44409
44681
|
var TOOL_PATH_LIMIT = 12;
|
|
@@ -44417,8 +44689,8 @@ function isCornerReviewTurn(reviewer, trigger) {
|
|
|
44417
44689
|
async function cornerUndeliveredRepositoryState(worktreePath, featureBranch, targetBranch) {
|
|
44418
44690
|
try {
|
|
44419
44691
|
const [{ stdout: status }, ahead] = await Promise.all([
|
|
44420
|
-
|
|
44421
|
-
featureBranch ? firstResolvedRemoteRef(worktreePath, [featureBranch, targetBranch]).then((remoteRef) => remoteRef ?
|
|
44692
|
+
execFileAsync9("git", ["-C", worktreePath, "status", "--porcelain=v1"]),
|
|
44693
|
+
featureBranch ? firstResolvedRemoteRef(worktreePath, [featureBranch, targetBranch]).then((remoteRef) => remoteRef ? execFileAsync9("git", [
|
|
44422
44694
|
"-C",
|
|
44423
44695
|
worktreePath,
|
|
44424
44696
|
"rev-list",
|
|
@@ -44438,7 +44710,7 @@ async function firstResolvedRemoteRef(worktreePath, branches) {
|
|
|
44438
44710
|
if (!branch)
|
|
44439
44711
|
continue;
|
|
44440
44712
|
const ref = `refs/remotes/origin/${branch}`;
|
|
44441
|
-
const resolved = await
|
|
44713
|
+
const resolved = await execFileAsync9("git", ["-C", worktreePath, "rev-parse", "--verify", ref]).then(() => true).catch(() => false);
|
|
44442
44714
|
if (resolved)
|
|
44443
44715
|
return ref;
|
|
44444
44716
|
}
|
|
@@ -44590,7 +44862,7 @@ async function cornerToolActivity(call, worktreePath, requestedBy) {
|
|
|
44590
44862
|
let title = oneLine(redactToolDetail(call.title ?? "")) || `${operation} tool`;
|
|
44591
44863
|
if (isSuccessfulCommit(call)) {
|
|
44592
44864
|
try {
|
|
44593
|
-
const shown = await
|
|
44865
|
+
const shown = await execFileAsync9("git", ["-C", worktreePath, "show", "--format=%s", "--name-only", "--no-renames", "HEAD"], { maxBuffer: 1024 * 1024 });
|
|
44594
44866
|
const lines = shown.stdout.split(/\r?\n/);
|
|
44595
44867
|
const subject = oneLine(lines.shift() ?? "commit");
|
|
44596
44868
|
const files = new Set(lines.map(oneLine).filter(Boolean));
|
|
@@ -44851,7 +45123,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
44851
45123
|
this.sessionCodegraphReady = false;
|
|
44852
45124
|
this.pinnedProviderOverride = void 0;
|
|
44853
45125
|
this.sessionModel = null;
|
|
44854
|
-
if (client
|
|
45126
|
+
if (client)
|
|
44855
45127
|
await client.stop();
|
|
44856
45128
|
}
|
|
44857
45129
|
/** See `MonolithRoomTurnLoop.sessionIsCurrent`: retention never keeps a
|
|
@@ -45012,9 +45284,9 @@ var MonolithCornerTurnLoop = class {
|
|
|
45012
45284
|
const repository = this.options.repository;
|
|
45013
45285
|
let githubEnv = repository ? { GH_TOKEN: repository.githubToken, GITHUB_TOKEN: repository.githubToken } : {};
|
|
45014
45286
|
if (repository && this.options.config.runtimeConfigPath && this.options.config.agentHomeRoot) {
|
|
45015
|
-
const gitBinary = (await
|
|
45016
|
-
const ghBinary = await
|
|
45017
|
-
const originUrl = await
|
|
45287
|
+
const gitBinary = (await execFileAsync9("which", ["git"])).stdout.trim();
|
|
45288
|
+
const ghBinary = await execFileAsync9("which", ["gh"]).then((result) => result.stdout.trim()).catch(() => void 0);
|
|
45289
|
+
const originUrl = await execFileAsync9(gitBinary, [
|
|
45018
45290
|
"-C",
|
|
45019
45291
|
this.options.worktreePath,
|
|
45020
45292
|
"remote",
|
|
@@ -45040,7 +45312,8 @@ var MonolithCornerTurnLoop = class {
|
|
|
45040
45312
|
const pnpmStoreDir = sharedPnpmStoreDir(this.options.runtime.supervisorRoot);
|
|
45041
45313
|
const cargoTargetDir = sharedCargoTargetDir(this.options.runtime.supervisorRoot);
|
|
45042
45314
|
const turboCacheDir = sharedTurboCacheDir(this.options.runtime.supervisorRoot);
|
|
45043
|
-
|
|
45315
|
+
const modelCacheDir = resolve38(this.options.runtime.supervisorRoot, "beeline", "model-cache");
|
|
45316
|
+
await Promise.all([npmCacheDir, pnpmStoreDir, cargoTargetDir, turboCacheDir, modelCacheDir].map((path) => mkdir26(path, { recursive: true, mode: 448 })));
|
|
45044
45317
|
const agentEnv = {
|
|
45045
45318
|
...this.options.config.agentEnv,
|
|
45046
45319
|
...homeOverlay,
|
|
@@ -45050,7 +45323,9 @@ var MonolithCornerTurnLoop = class {
|
|
|
45050
45323
|
// hardlinks packages out of this content-addressable store.
|
|
45051
45324
|
PNPM_CONFIG_STORE_DIR: pnpmStoreDir,
|
|
45052
45325
|
CARGO_TARGET_DIR: cargoTargetDir,
|
|
45053
|
-
TURBO_CACHE_DIR: turboCacheDir
|
|
45326
|
+
TURBO_CACHE_DIR: turboCacheDir,
|
|
45327
|
+
HF_HOME: modelCacheDir,
|
|
45328
|
+
HUGGINGFACE_HUB_CACHE: join21(modelCacheDir, "hub")
|
|
45054
45329
|
};
|
|
45055
45330
|
this.agentEnv = agentEnv;
|
|
45056
45331
|
this.modelContextTokens = await modelContextWindowTokens(selection.model, agentEnv.PI_CODING_AGENT_DIR);
|
|
@@ -45060,7 +45335,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
45060
45335
|
args: this.options.config.agentArgs ?? []
|
|
45061
45336
|
}, selection);
|
|
45062
45337
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
45063
|
-
this.attachmentDir = tmpDir ?
|
|
45338
|
+
this.attachmentDir = tmpDir ? join21(tmpDir, "beeline-attachments") : void 0;
|
|
45064
45339
|
this.sessionScratchDir = tmpDir;
|
|
45065
45340
|
const homeStateDirs = harnessHomeStateDirs(harnessLabel, agentEnv.HOME ?? operatorHome);
|
|
45066
45341
|
await Promise.all(homeStateDirs.map((dir) => mkdir26(dir, { recursive: true })));
|
|
@@ -45087,6 +45362,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
45087
45362
|
pnpmStoreDir,
|
|
45088
45363
|
cargoTargetDir,
|
|
45089
45364
|
turboCacheDir,
|
|
45365
|
+
modelCacheDir,
|
|
45090
45366
|
...registryMcpHostBindPaths(configuration.registryMcpRoutes, this.options.config.registryMcpBrokerSocket),
|
|
45091
45367
|
...grantedSquireHostBindPaths({
|
|
45092
45368
|
operatorHome,
|
|
@@ -45165,7 +45441,9 @@ var MonolithCornerTurnLoop = class {
|
|
|
45165
45441
|
// per-corner cache.
|
|
45166
45442
|
{ name: "npm_config_cache", value: npmCacheDir },
|
|
45167
45443
|
{ name: "PNPM_CONFIG_STORE_DIR", value: pnpmStoreDir },
|
|
45168
|
-
{ name: "CARGO_TARGET_DIR", value: cargoTargetDir }
|
|
45444
|
+
{ name: "CARGO_TARGET_DIR", value: cargoTargetDir },
|
|
45445
|
+
{ name: "HF_HOME", value: modelCacheDir },
|
|
45446
|
+
{ name: "HUGGINGFACE_HUB_CACHE", value: join21(modelCacheDir, "hub") }
|
|
45169
45447
|
]
|
|
45170
45448
|
}
|
|
45171
45449
|
] : [],
|
|
@@ -45173,13 +45451,13 @@ var MonolithCornerTurnLoop = class {
|
|
|
45173
45451
|
roomId: this.options.parentRoomId,
|
|
45174
45452
|
workspaceId: this.options.workspaceId,
|
|
45175
45453
|
cornerId: this.options.cornerId,
|
|
45176
|
-
agentMayCloseCorner: Boolean(repository),
|
|
45177
45454
|
reviewer,
|
|
45178
45455
|
repositoryBacked: Boolean(repository),
|
|
45179
45456
|
attachRoot: this.options.worktreePath,
|
|
45180
45457
|
// The whole per-session overlay, not an enumerated subset: see
|
|
45181
45458
|
// `monolith-room-turn.ts`'s matching comment.
|
|
45182
45459
|
attachScratchRoot,
|
|
45460
|
+
...!repository ? { cornerScratchRoot: this.options.worktreePath } : {},
|
|
45183
45461
|
turnContextPath: this.commandContext.path,
|
|
45184
45462
|
squireRelay: squireScope.relay,
|
|
45185
45463
|
...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
|
|
@@ -45273,7 +45551,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
45273
45551
|
this.options.api.execute("getCornerRestoreState", {
|
|
45274
45552
|
cornerId: this.options.cornerId
|
|
45275
45553
|
}),
|
|
45276
|
-
|
|
45554
|
+
execFileAsync9("git", ["-C", this.options.worktreePath, "rev-parse", "HEAD"]).then(({ stdout: stdout6 }) => stdout6.trim())
|
|
45277
45555
|
]);
|
|
45278
45556
|
const pr = restore.lifecycle?.pr;
|
|
45279
45557
|
if (restore.lifecycle?.checks !== "passing" || !pr?.number || !pr.headSha || pr.headSha !== localHead)
|
|
@@ -45287,7 +45565,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
45287
45565
|
briefRevision: restore.brief?.revision
|
|
45288
45566
|
}),
|
|
45289
45567
|
...this.options.config.agentHomeRoot && this.options.config.agentKind && !AGENT_SKILL_DIRS.includes(this.options.config.agentKind) ? [
|
|
45290
|
-
`This harness has no verified native skill discovery. Read the release-managed review procedure at ${
|
|
45568
|
+
`This harness has no verified native skill discovery. Read the release-managed review procedure at ${resolve38(this.options.config.agentHomeRoot, "codex", "skills", "beeline-review", "SKILL.md")} before the verdict.`
|
|
45291
45569
|
] : []
|
|
45292
45570
|
].join("\n");
|
|
45293
45571
|
} catch {
|
|
@@ -45353,7 +45631,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
45353
45631
|
this.sessionId = void 0;
|
|
45354
45632
|
this.sessionFingerprint = void 0;
|
|
45355
45633
|
this.sessionCodegraphReady = false;
|
|
45356
|
-
if (client
|
|
45634
|
+
if (client)
|
|
45357
45635
|
await client.stop();
|
|
45358
45636
|
this.pinnedProviderOverride = next;
|
|
45359
45637
|
await (trace ? trace.measure("activation", () => this.activate(trace)) : this.activate());
|
|
@@ -45402,8 +45680,8 @@ var MonolithCornerTurnLoop = class {
|
|
|
45402
45680
|
let timer;
|
|
45403
45681
|
const stats = statsPromise && remaining > 0 ? await Promise.race([
|
|
45404
45682
|
statsPromise,
|
|
45405
|
-
new Promise((
|
|
45406
|
-
timer = setTimeout(() =>
|
|
45683
|
+
new Promise((resolve49) => {
|
|
45684
|
+
timer = setTimeout(() => resolve49(void 0), remaining);
|
|
45407
45685
|
})
|
|
45408
45686
|
]).finally(() => {
|
|
45409
45687
|
if (timer)
|
|
@@ -45454,7 +45732,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
45454
45732
|
let repositoryWork = cornerHasRepositoryWork(restored.brief);
|
|
45455
45733
|
let repositoryHeld = restored.held === true;
|
|
45456
45734
|
let assignedBrief = restored.brief;
|
|
45457
|
-
const taskDelivered = this.attachmentDir && attachments.length ? await deliverAttachments(attachments,
|
|
45735
|
+
const taskDelivered = this.attachmentDir && attachments.length ? await deliverAttachments(attachments, join21(this.attachmentDir, requestId.replace(/[^\w-]/g, "_")), this.options.fetchImpl) : [];
|
|
45458
45736
|
let delivered = taskDelivered;
|
|
45459
45737
|
let briefFileLines = [];
|
|
45460
45738
|
let missingRequiredBriefFile = false;
|
|
@@ -45465,7 +45743,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
45465
45743
|
mimeType: file.mime,
|
|
45466
45744
|
size: file.size
|
|
45467
45745
|
}));
|
|
45468
|
-
const briefDelivered = this.attachmentDir && briefAttachments.length ? await deliverAttachments(briefAttachments,
|
|
45746
|
+
const briefDelivered = this.attachmentDir && briefAttachments.length ? await deliverAttachments(briefAttachments, join21(this.attachmentDir, requestId.replace(/[^\w-]/g, "_"), "brief", String(assignedBrief.revision)), this.options.fetchImpl) : [];
|
|
45469
45747
|
briefFileLines = await Promise.all((assignedBrief?.attachments ?? []).map(async (file, index) => {
|
|
45470
45748
|
const entry = briefDelivered.find((item) => item.attachment === briefAttachments[index]);
|
|
45471
45749
|
const verified = entry?.path && createHash13("sha256").update(await readFile30(entry.path)).digest("hex") === file.sha256;
|
|
@@ -45551,11 +45829,19 @@ var MonolithCornerTurnLoop = class {
|
|
|
45551
45829
|
}
|
|
45552
45830
|
});
|
|
45553
45831
|
trace.notePromptSections(assembled.report);
|
|
45554
|
-
trace.notePromptWindow(assembled.text, this.modelContextTokens);
|
|
45555
45832
|
this.commandContext.notePromptSections([
|
|
45556
45833
|
...this.sessionPromptSectionIds,
|
|
45557
45834
|
...assembled.report.map((section) => section.id)
|
|
45558
45835
|
]);
|
|
45836
|
+
if (!repositoryWork) {
|
|
45837
|
+
const usage2 = await allocatedDirectoryBytes(this.options.worktreePath);
|
|
45838
|
+
const text2 = `${assembled.text}
|
|
45839
|
+
|
|
45840
|
+
${scratchBudgetMessage(usage2)}`;
|
|
45841
|
+
trace.notePromptWindow(text2, this.modelContextTokens);
|
|
45842
|
+
return text2;
|
|
45843
|
+
}
|
|
45844
|
+
trace.notePromptWindow(assembled.text, this.modelContextTokens);
|
|
45559
45845
|
return assembled.text;
|
|
45560
45846
|
};
|
|
45561
45847
|
const stream = new AgentTurnStream({
|
|
@@ -45664,24 +45950,34 @@ var MonolithCornerTurnLoop = class {
|
|
|
45664
45950
|
narrationRunBoundary = 0;
|
|
45665
45951
|
currentNarrationRun = "";
|
|
45666
45952
|
trace.promptSent();
|
|
45667
|
-
|
|
45668
|
-
|
|
45669
|
-
|
|
45670
|
-
|
|
45671
|
-
|
|
45672
|
-
|
|
45673
|
-
|
|
45674
|
-
|
|
45675
|
-
if (
|
|
45676
|
-
|
|
45677
|
-
|
|
45953
|
+
const scratchRoot = this.repositoryWork ? void 0 : this.options.worktreePath;
|
|
45954
|
+
const scratchAtStart = scratchRoot ? await allocatedDirectoryBytes(scratchRoot) : 0;
|
|
45955
|
+
try {
|
|
45956
|
+
return await this.turnUsage.measure({ agentEnv: this.agentEnv, sessionId: this.sessionId }, () => this.client.sessionPrompt(this.sessionId, promptWithImages(prompt, attachmentImageBlocks(delivered, this.acceptsImages())), ROOM_PROMPT_BACKSTOP_MS, (delta, full, currentRun, runs) => {
|
|
45957
|
+
trace.firstModelOutput();
|
|
45958
|
+
if (runs) {
|
|
45959
|
+
completedNarrationRuns = runs.slice(narrationRunBoundary);
|
|
45960
|
+
currentNarrationRun = "";
|
|
45961
|
+
} else if (currentRun === void 0)
|
|
45962
|
+
currentNarrationRun += delta;
|
|
45963
|
+
else {
|
|
45964
|
+
if (currentNarrationRun && currentNarrationRun !== currentRun && !currentRun.startsWith(currentNarrationRun))
|
|
45965
|
+
completedNarrationRuns.push(currentNarrationRun);
|
|
45966
|
+
currentNarrationRun = currentRun;
|
|
45967
|
+
}
|
|
45968
|
+
stream.onChunk(delta, full, currentRun);
|
|
45969
|
+
}, void 0, (calls) => {
|
|
45970
|
+
trace.toolCalls(calls);
|
|
45971
|
+
publishToolCalls(calls, true);
|
|
45972
|
+
publishToolCalls(calls, false, lastNarratedToolCall);
|
|
45973
|
+
}));
|
|
45974
|
+
} finally {
|
|
45975
|
+
if (scratchRoot) {
|
|
45976
|
+
const usage2 = await allocatedDirectoryBytes(scratchRoot);
|
|
45977
|
+
if (scratchGrowthExceedsBudget(usage2, scratchAtStart))
|
|
45978
|
+
throw new Error(`Scratch budget exceeded. ${scratchBudgetMessage(usage2)}`);
|
|
45678
45979
|
}
|
|
45679
|
-
|
|
45680
|
-
}, void 0, (calls) => {
|
|
45681
|
-
trace.toolCalls(calls);
|
|
45682
|
-
publishToolCalls(calls, true);
|
|
45683
|
-
publishToolCalls(calls, false, lastNarratedToolCall);
|
|
45684
|
-
}));
|
|
45980
|
+
}
|
|
45685
45981
|
};
|
|
45686
45982
|
let loginRetryUsed = false;
|
|
45687
45983
|
const runPrompt = async (prompt, continuation) => {
|
|
@@ -45886,13 +46182,13 @@ ${continuation}` : assembled;
|
|
|
45886
46182
|
if (this.harvest || !this.options.repository)
|
|
45887
46183
|
return;
|
|
45888
46184
|
const { cornerId, worktreePath, runtime } = this.options;
|
|
45889
|
-
const mobilePath =
|
|
46185
|
+
const mobilePath = resolve38(worktreePath, "apps/mobile");
|
|
45890
46186
|
const jobs = [
|
|
45891
46187
|
harvestWarmNodeModules({
|
|
45892
46188
|
worktreePath,
|
|
45893
46189
|
storeRoot: warmNodeModulesStoreDir(runtime.supervisorRoot)
|
|
45894
46190
|
}),
|
|
45895
|
-
...existsSync9(
|
|
46191
|
+
...existsSync9(resolve38(mobilePath, "package-lock.json")) ? [
|
|
45896
46192
|
harvestWarmNodeModules({
|
|
45897
46193
|
worktreePath: mobilePath,
|
|
45898
46194
|
storeRoot: mobileNodeModulesStoreDir(runtime.supervisorRoot)
|
|
@@ -45940,7 +46236,7 @@ ${continuation}` : assembled;
|
|
|
45940
46236
|
const delay = outage ? Math.min(2e3 * 2 ** attempt, 3e4) : 250 * (attempt + 1);
|
|
45941
46237
|
if ((outage ? Date.now() + delay > outageDeadline : attempt === 2) || this.forcedStop || this.currentTurn && this.stoppedTurns.has(this.currentTurn.requestId))
|
|
45942
46238
|
throw error;
|
|
45943
|
-
await new Promise((
|
|
46239
|
+
await new Promise((resolve49) => setTimeout(resolve49, delay));
|
|
45944
46240
|
}
|
|
45945
46241
|
}
|
|
45946
46242
|
if (!token)
|
|
@@ -46032,11 +46328,95 @@ ${continuation}` : assembled;
|
|
|
46032
46328
|
this.squireRelay.close();
|
|
46033
46329
|
this.options.grantRunner?.unregister(cornerId);
|
|
46034
46330
|
await this.options.scheduler.suspend(cornerId);
|
|
46331
|
+
this.options.scheduler.forget(cornerId);
|
|
46035
46332
|
await this.harvest;
|
|
46036
46333
|
}
|
|
46037
46334
|
}
|
|
46038
46335
|
};
|
|
46039
46336
|
|
|
46337
|
+
// apps/body/dist/corner-disk-recovery.js
|
|
46338
|
+
import { execFile as execFile15 } from "node:child_process";
|
|
46339
|
+
import { lstat as lstat6, readdir as readdir10, realpath as realpath2, rm as rm16 } from "node:fs/promises";
|
|
46340
|
+
import { basename as basename9, dirname as dirname27, join as join22, relative as relative3, resolve as resolve39, sep as sep2 } from "node:path";
|
|
46341
|
+
import { promisify as promisify10 } from "node:util";
|
|
46342
|
+
var execFileAsync10 = promisify10(execFile15);
|
|
46343
|
+
var GENERATED_DIRS = /* @__PURE__ */ new Set([
|
|
46344
|
+
"node_modules",
|
|
46345
|
+
"target",
|
|
46346
|
+
"build",
|
|
46347
|
+
"dist",
|
|
46348
|
+
".next",
|
|
46349
|
+
".turbo",
|
|
46350
|
+
".expo"
|
|
46351
|
+
]);
|
|
46352
|
+
var MAX_DIRECTORY_DEPTH = 4;
|
|
46353
|
+
var MAX_VISITED_DIRECTORIES = 5e3;
|
|
46354
|
+
function cornerRecoveryPointerPath(worktree) {
|
|
46355
|
+
const checkout = resolve39(worktree.path);
|
|
46356
|
+
if (basename9(checkout) !== worktree.cornerId || basename9(dirname27(checkout)) !== "corners" || basename9(dirname27(dirname27(checkout))) !== "beeline" || !/^[a-zA-Z0-9-]{1,80}$/.test(worktree.cornerId)) {
|
|
46357
|
+
throw new Error("refusing recovery pointer outside a Beeline corner checkout");
|
|
46358
|
+
}
|
|
46359
|
+
return resolve39(dirname27(dirname27(checkout)), "recovery", "corners", `${worktree.cornerId}.json`);
|
|
46360
|
+
}
|
|
46361
|
+
async function git(checkout, args) {
|
|
46362
|
+
const result = await execFileAsync10("git", ["-C", checkout, ...args], {
|
|
46363
|
+
maxBuffer: 4 * 1024 * 1024
|
|
46364
|
+
});
|
|
46365
|
+
return result.stdout;
|
|
46366
|
+
}
|
|
46367
|
+
async function ignoredAndUntracked(checkout, path) {
|
|
46368
|
+
const rel = relative3(checkout, path);
|
|
46369
|
+
if (!rel || rel === ".." || rel.startsWith(`..${sep2}`))
|
|
46370
|
+
return false;
|
|
46371
|
+
const ignored = await git(checkout, ["check-ignore", "-q", "--", `${rel}/`]).then(() => true, () => false);
|
|
46372
|
+
if (!ignored)
|
|
46373
|
+
return false;
|
|
46374
|
+
return !(await git(checkout, ["ls-files", "--", rel])).trim();
|
|
46375
|
+
}
|
|
46376
|
+
async function preserveUnpublishedCornerWorktree(worktree, reason) {
|
|
46377
|
+
const checkout = resolve39(worktree.path);
|
|
46378
|
+
const pointer = cornerRecoveryPointerPath(worktree);
|
|
46379
|
+
const info = await lstat6(checkout);
|
|
46380
|
+
if (!info.isDirectory() || await realpath2(checkout) !== checkout) {
|
|
46381
|
+
throw new Error("refusing to prune a non-canonical corner checkout");
|
|
46382
|
+
}
|
|
46383
|
+
const head = (await git(checkout, ["rev-parse", "--verify", "HEAD"])).trim();
|
|
46384
|
+
const record5 = {
|
|
46385
|
+
cornerId: worktree.cornerId,
|
|
46386
|
+
checkout,
|
|
46387
|
+
branch: worktree.branch,
|
|
46388
|
+
head,
|
|
46389
|
+
reason,
|
|
46390
|
+
recordedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
46391
|
+
};
|
|
46392
|
+
await writePrivateFileAtomically(pointer, `${JSON.stringify(record5, null, 2)}
|
|
46393
|
+
`);
|
|
46394
|
+
const pruned = [];
|
|
46395
|
+
const pending = [{ path: checkout, depth: 0 }];
|
|
46396
|
+
let visited = 0;
|
|
46397
|
+
while (pending.length) {
|
|
46398
|
+
const current = pending.shift();
|
|
46399
|
+
if (++visited > MAX_VISITED_DIRECTORIES)
|
|
46400
|
+
break;
|
|
46401
|
+
if (current.depth >= MAX_DIRECTORY_DEPTH)
|
|
46402
|
+
continue;
|
|
46403
|
+
for (const entry of await readdir10(current.path, { withFileTypes: true })) {
|
|
46404
|
+
if (!entry.isDirectory() || entry.name === ".git")
|
|
46405
|
+
continue;
|
|
46406
|
+
const path = join22(current.path, entry.name);
|
|
46407
|
+
if (GENERATED_DIRS.has(entry.name)) {
|
|
46408
|
+
if (await ignoredAndUntracked(checkout, path)) {
|
|
46409
|
+
await rm16(path, { recursive: true, force: true });
|
|
46410
|
+
pruned.push(relative3(checkout, path));
|
|
46411
|
+
}
|
|
46412
|
+
continue;
|
|
46413
|
+
}
|
|
46414
|
+
pending.push({ path, depth: current.depth + 1 });
|
|
46415
|
+
}
|
|
46416
|
+
}
|
|
46417
|
+
return { pointer, pruned };
|
|
46418
|
+
}
|
|
46419
|
+
|
|
46040
46420
|
// apps/body/dist/surface-health.js
|
|
46041
46421
|
var SurfaceHealth = class {
|
|
46042
46422
|
surfaces = /* @__PURE__ */ new Map();
|
|
@@ -46125,7 +46505,7 @@ function resolveSessionIdleMs(env = process.env) {
|
|
|
46125
46505
|
return Number.isSafeInteger(value) && value > 0 ? value : DEFAULT_SESSION_IDLE_MS;
|
|
46126
46506
|
}
|
|
46127
46507
|
var DEFAULT_WORKSPACE_LIVE_SESSIONS_FLOOR = 4;
|
|
46128
|
-
var SessionScheduler = class {
|
|
46508
|
+
var SessionScheduler = class _SessionScheduler {
|
|
46129
46509
|
/** Fixed ceiling when explicitly configured; undefined selects the dynamic one. */
|
|
46130
46510
|
fixedMaxLiveSessions;
|
|
46131
46511
|
perRoomLiveSessions;
|
|
@@ -46140,6 +46520,7 @@ var SessionScheduler = class {
|
|
|
46140
46520
|
queues = /* @__PURE__ */ new Map();
|
|
46141
46521
|
drainingKeys = /* @__PURE__ */ new Set();
|
|
46142
46522
|
physicalHistory = /* @__PURE__ */ new Map();
|
|
46523
|
+
static MAX_GENERATIONS_PER_KEY = 4;
|
|
46143
46524
|
/**
|
|
46144
46525
|
* Sessions already removed from `live` whose process is still being torn
|
|
46145
46526
|
* down. They keep occupying capacity until `suspend()` resolves, so an
|
|
@@ -46263,6 +46644,10 @@ var SessionScheduler = class {
|
|
|
46263
46644
|
generations(key) {
|
|
46264
46645
|
return this.physicalHistory.get(key) ?? [];
|
|
46265
46646
|
}
|
|
46647
|
+
/** A Room/corner loop ended; its diagnostic IDs no longer have a reader. */
|
|
46648
|
+
forget(key) {
|
|
46649
|
+
this.physicalHistory.delete(key);
|
|
46650
|
+
}
|
|
46266
46651
|
/**
|
|
46267
46652
|
* Read-only capacity diagnostic, exported beside the turn trace
|
|
46268
46653
|
* (`turn-trace.ts`) so a stalled turn can be attributed to a capacity wait
|
|
@@ -46336,6 +46721,7 @@ var SessionScheduler = class {
|
|
|
46336
46721
|
this.sweepTimer = void 0;
|
|
46337
46722
|
const sessions = [...this.live.values()];
|
|
46338
46723
|
this.live.clear();
|
|
46724
|
+
this.physicalHistory.clear();
|
|
46339
46725
|
await Promise.all(sessions.map((session) => this.retire(session)));
|
|
46340
46726
|
this.wakeCapacityWaiters();
|
|
46341
46727
|
}
|
|
@@ -46449,6 +46835,8 @@ var SessionScheduler = class {
|
|
|
46449
46835
|
await this.notifyState(lifecycle, "live");
|
|
46450
46836
|
const generations = this.physicalHistory.get(key) ?? [];
|
|
46451
46837
|
generations.push(physicalSessionId);
|
|
46838
|
+
if (generations.length > _SessionScheduler.MAX_GENERATIONS_PER_KEY)
|
|
46839
|
+
generations.shift();
|
|
46452
46840
|
this.physicalHistory.set(key, generations);
|
|
46453
46841
|
return true;
|
|
46454
46842
|
} catch (error) {
|
|
@@ -46548,7 +46936,7 @@ function cornerStartConfigKey(repository, objective) {
|
|
|
46548
46936
|
function cornerRepositoryCacheDir(supervisorRoot, remote) {
|
|
46549
46937
|
const normalizedRemote = roomCheckoutRemote(remote);
|
|
46550
46938
|
const repositoryHash = createHash14("sha256").update(normalizedRemote).digest("hex").slice(0, 24);
|
|
46551
|
-
return
|
|
46939
|
+
return resolve40(supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
|
|
46552
46940
|
}
|
|
46553
46941
|
function isStandingCornerStartFault(error) {
|
|
46554
46942
|
const text2 = error instanceof Error ? error.message : String(error);
|
|
@@ -46557,24 +46945,24 @@ function isStandingCornerStartFault(error) {
|
|
|
46557
46945
|
async function materializeCornerWorktree(input) {
|
|
46558
46946
|
const remote = roomCheckoutRemote(input.remote);
|
|
46559
46947
|
const gitCommonDir = cornerRepositoryCacheDir(input.supervisorRoot, remote);
|
|
46560
|
-
const path =
|
|
46561
|
-
await mkdir27(
|
|
46562
|
-
await mkdir27(
|
|
46948
|
+
const path = resolve40(input.supervisorRoot, "beeline", "corners", input.cornerId);
|
|
46949
|
+
await mkdir27(dirname28(gitCommonDir), { recursive: true, mode: 448 });
|
|
46950
|
+
await mkdir27(dirname28(path), { recursive: true, mode: 448 });
|
|
46563
46951
|
const authEnv = githubGitEnv(input.token);
|
|
46564
|
-
if (!existsSync10(
|
|
46565
|
-
await
|
|
46952
|
+
if (!existsSync10(resolve40(gitCommonDir, "HEAD"))) {
|
|
46953
|
+
await execFileAsync11("git", ["clone", "--bare", remote, gitCommonDir], {
|
|
46566
46954
|
env: authEnv,
|
|
46567
46955
|
maxBuffer: 4 * 1024 * 1024
|
|
46568
46956
|
});
|
|
46569
46957
|
}
|
|
46570
|
-
await
|
|
46958
|
+
await execFileAsync11("git", [
|
|
46571
46959
|
`--git-dir=${gitCommonDir}`,
|
|
46572
46960
|
"fetch",
|
|
46573
46961
|
"--prune",
|
|
46574
46962
|
"origin",
|
|
46575
46963
|
`+refs/heads/${input.targetBranch}:refs/remotes/origin/${input.targetBranch}`
|
|
46576
46964
|
], { env: authEnv, maxBuffer: 4 * 1024 * 1024 });
|
|
46577
|
-
const restored = await
|
|
46965
|
+
const restored = await execFileAsync11("git", [
|
|
46578
46966
|
`--git-dir=${gitCommonDir}`,
|
|
46579
46967
|
"fetch",
|
|
46580
46968
|
"origin",
|
|
@@ -46584,9 +46972,9 @@ async function materializeCornerWorktree(input) {
|
|
|
46584
46972
|
return false;
|
|
46585
46973
|
throw error;
|
|
46586
46974
|
});
|
|
46587
|
-
if (!existsSync10(
|
|
46588
|
-
await
|
|
46589
|
-
await
|
|
46975
|
+
if (!existsSync10(resolve40(path, ".git"))) {
|
|
46976
|
+
await rm17(path, { recursive: true, force: true });
|
|
46977
|
+
await execFileAsync11("git", [
|
|
46590
46978
|
`--git-dir=${gitCommonDir}`,
|
|
46591
46979
|
"worktree",
|
|
46592
46980
|
"add",
|
|
@@ -46602,8 +46990,8 @@ async function materializeCornerWorktree(input) {
|
|
|
46602
46990
|
if (seed.reason !== "no-lockfile") {
|
|
46603
46991
|
console.log(`[thin-core] corner ${input.cornerId} warm node_modules: ${seed.reason}${seed.detail ? ` (${seed.detail})` : ""}`);
|
|
46604
46992
|
}
|
|
46605
|
-
const mobilePath =
|
|
46606
|
-
if (existsSync10(
|
|
46993
|
+
const mobilePath = resolve40(path, "apps/mobile");
|
|
46994
|
+
if (existsSync10(resolve40(mobilePath, "package-lock.json"))) {
|
|
46607
46995
|
const mobileSeed = await seedWarmNodeModules({
|
|
46608
46996
|
worktreePath: mobilePath,
|
|
46609
46997
|
storeRoot: mobileNodeModulesStoreDir(input.supervisorRoot)
|
|
@@ -46613,14 +47001,14 @@ async function materializeCornerWorktree(input) {
|
|
|
46613
47001
|
}
|
|
46614
47002
|
}
|
|
46615
47003
|
}
|
|
46616
|
-
await
|
|
47004
|
+
await execFileAsync11("git", [
|
|
46617
47005
|
`--git-dir=${gitCommonDir}`,
|
|
46618
47006
|
"config",
|
|
46619
47007
|
"extensions.worktreeConfig",
|
|
46620
47008
|
"true"
|
|
46621
47009
|
]);
|
|
46622
|
-
await
|
|
46623
|
-
await
|
|
47010
|
+
await execFileAsync11("git", ["-C", path, "config", "--worktree", "core.bare", "false"]);
|
|
47011
|
+
await execFileAsync11("git", [
|
|
46624
47012
|
"-C",
|
|
46625
47013
|
path,
|
|
46626
47014
|
"config",
|
|
@@ -46628,7 +47016,7 @@ async function materializeCornerWorktree(input) {
|
|
|
46628
47016
|
"credential.https://github.com.helper",
|
|
46629
47017
|
"!f() { echo username=x-access-token; echo password=$GH_TOKEN; }; f"
|
|
46630
47018
|
]);
|
|
46631
|
-
await
|
|
47019
|
+
await execFileAsync11("git", [
|
|
46632
47020
|
"-C",
|
|
46633
47021
|
path,
|
|
46634
47022
|
"config",
|
|
@@ -46636,7 +47024,7 @@ async function materializeCornerWorktree(input) {
|
|
|
46636
47024
|
"user.name",
|
|
46637
47025
|
input.committer.name
|
|
46638
47026
|
]);
|
|
46639
|
-
await
|
|
47027
|
+
await execFileAsync11("git", [
|
|
46640
47028
|
"-C",
|
|
46641
47029
|
path,
|
|
46642
47030
|
"config",
|
|
@@ -46644,8 +47032,8 @@ async function materializeCornerWorktree(input) {
|
|
|
46644
47032
|
"user.email",
|
|
46645
47033
|
`${input.committer.publicKey.slice(0, 16)}@users.noreply.github.com`
|
|
46646
47034
|
]);
|
|
46647
|
-
const top = (await
|
|
46648
|
-
if (await
|
|
47035
|
+
const top = (await execFileAsync11("git", ["-C", path, "rev-parse", "--show-toplevel"])).stdout.trim();
|
|
47036
|
+
if (await realpath3(top) !== await realpath3(path)) {
|
|
46649
47037
|
throw new Error(`corner worktree escaped its isolated root: ${top}`);
|
|
46650
47038
|
}
|
|
46651
47039
|
return { path, gitCommonDir };
|
|
@@ -46660,31 +47048,31 @@ async function mapWithConcurrency(values, limit, visit) {
|
|
|
46660
47048
|
}));
|
|
46661
47049
|
}
|
|
46662
47050
|
async function discoverCornerWorktree(supervisorRoot, cornerId) {
|
|
46663
|
-
const cornersRoot =
|
|
46664
|
-
const path =
|
|
46665
|
-
if (
|
|
47051
|
+
const cornersRoot = resolve40(supervisorRoot, "beeline", "corners");
|
|
47052
|
+
const path = resolve40(cornersRoot, cornerId);
|
|
47053
|
+
if (dirname28(path) !== cornersRoot || !existsSync10(resolve40(path, ".git")))
|
|
46666
47054
|
return void 0;
|
|
46667
47055
|
const [canonicalRoot, canonicalPath] = await Promise.all([
|
|
46668
|
-
|
|
46669
|
-
|
|
47056
|
+
realpath3(cornersRoot),
|
|
47057
|
+
realpath3(path).catch(() => void 0)
|
|
46670
47058
|
]);
|
|
46671
|
-
if (!canonicalPath ||
|
|
47059
|
+
if (!canonicalPath || relative4(canonicalRoot, canonicalPath) !== cornerId) {
|
|
46672
47060
|
throw new Error(`refusing corner ${cornerId} whose checkout path is not canonical`);
|
|
46673
47061
|
}
|
|
46674
|
-
const common = await
|
|
47062
|
+
const common = await execFileAsync11("git", ["-C", path, "rev-parse", "--git-common-dir"]).catch(() => void 0);
|
|
46675
47063
|
if (!common)
|
|
46676
47064
|
return void 0;
|
|
46677
|
-
const gitCommonDir =
|
|
46678
|
-
const repositoriesRoot =
|
|
46679
|
-
const commonRelative =
|
|
46680
|
-
if (!commonRelative || commonRelative === ".." || commonRelative.startsWith(`..${
|
|
47065
|
+
const gitCommonDir = resolve40(path, common.stdout.trim());
|
|
47066
|
+
const repositoriesRoot = resolve40(supervisorRoot, "beeline", "repositories");
|
|
47067
|
+
const commonRelative = relative4(repositoriesRoot, gitCommonDir);
|
|
47068
|
+
if (!commonRelative || commonRelative === ".." || commonRelative.startsWith(`..${sep3}`) || commonRelative.startsWith(sep3)) {
|
|
46681
47069
|
throw new Error(`refusing corner ${cornerId} with git directory outside repository cache`);
|
|
46682
47070
|
}
|
|
46683
47071
|
return { path, gitCommonDir };
|
|
46684
47072
|
}
|
|
46685
47073
|
async function localCornerWorktreeIds(supervisorRoot) {
|
|
46686
|
-
const root =
|
|
46687
|
-
const entries = await
|
|
47074
|
+
const root = resolve40(supervisorRoot, "beeline", "corners");
|
|
47075
|
+
const entries = await readdir11(root, { withFileTypes: true }).catch((error) => {
|
|
46688
47076
|
if (error.code === "ENOENT")
|
|
46689
47077
|
return [];
|
|
46690
47078
|
throw error;
|
|
@@ -46698,12 +47086,12 @@ async function removeCornerWorktreeAndBranches(worktree, options = {}) {
|
|
|
46698
47086
|
const worktreeExists = existsSync10(worktree.path);
|
|
46699
47087
|
const localExists = await gitRefExists(worktree.gitCommonDir, localRef);
|
|
46700
47088
|
if (worktreeExists) {
|
|
46701
|
-
const checkedOut = await
|
|
47089
|
+
const checkedOut = await execFileAsync11("git", ["-C", worktree.path, "symbolic-ref", "--quiet", "HEAD"], { maxBuffer: 4 * 1024 * 1024 }).then((result) => result.stdout.trim(), () => void 0);
|
|
46702
47090
|
if (!worktree.recovered && checkedOut !== localRef) {
|
|
46703
47091
|
throw new Error(`corner worktree branch mismatch: expected ${localRef}`);
|
|
46704
47092
|
}
|
|
46705
47093
|
await assertCornerWorktreePublished(worktree);
|
|
46706
|
-
await
|
|
47094
|
+
await execFileAsync11("git", [
|
|
46707
47095
|
`--git-dir=${worktree.gitCommonDir}`,
|
|
46708
47096
|
"worktree",
|
|
46709
47097
|
"remove",
|
|
@@ -46728,7 +47116,7 @@ async function removeCornerWorktreeAndBranches(worktree, options = {}) {
|
|
|
46728
47116
|
await deleteExactRemoteBranch(worktree.gitCommonDir, remoteRef, worktree.token);
|
|
46729
47117
|
}
|
|
46730
47118
|
if (await gitRefExists(worktree.gitCommonDir, localRef)) {
|
|
46731
|
-
await
|
|
47119
|
+
await execFileAsync11("git", [
|
|
46732
47120
|
`--git-dir=${worktree.gitCommonDir}`,
|
|
46733
47121
|
"branch",
|
|
46734
47122
|
"--delete",
|
|
@@ -46739,18 +47127,18 @@ async function removeCornerWorktreeAndBranches(worktree, options = {}) {
|
|
|
46739
47127
|
}
|
|
46740
47128
|
}
|
|
46741
47129
|
async function assertCornerWorktreePublished(worktree) {
|
|
46742
|
-
const status = async () => (await
|
|
46743
|
-
const originalHead = (await
|
|
47130
|
+
const status = async () => (await execFileAsync11("git", ["-C", worktree.path, "status", "--porcelain=v1", "--untracked-files=all"], { maxBuffer: 4 * 1024 * 1024 })).stdout.trim();
|
|
47131
|
+
const originalHead = (await execFileAsync11("git", ["-C", worktree.path, "rev-parse", "--verify", "HEAD"])).stdout.trim();
|
|
46744
47132
|
if (await status())
|
|
46745
47133
|
throw new Error(`corner ${worktree.cornerId} has unpushed working-tree work`);
|
|
46746
47134
|
await assertPublishedOnOrigin(worktree.gitCommonDir, originalHead, worktree.cornerId, worktree.token);
|
|
46747
|
-
const settledHead = (await
|
|
47135
|
+
const settledHead = (await execFileAsync11("git", ["-C", worktree.path, "rev-parse", "--verify", "HEAD"])).stdout.trim();
|
|
46748
47136
|
if (settledHead !== originalHead || await status()) {
|
|
46749
47137
|
throw new Error(`corner ${worktree.cornerId} changed during cleanup`);
|
|
46750
47138
|
}
|
|
46751
47139
|
}
|
|
46752
47140
|
async function assertLocalBranchPublished(worktree) {
|
|
46753
|
-
const head = (await
|
|
47141
|
+
const head = (await execFileAsync11("git", [
|
|
46754
47142
|
`--git-dir=${worktree.gitCommonDir}`,
|
|
46755
47143
|
"rev-parse",
|
|
46756
47144
|
"--verify",
|
|
@@ -46761,7 +47149,7 @@ async function assertLocalBranchPublished(worktree) {
|
|
|
46761
47149
|
async function assertPublishedOnOrigin(gitCommonDir, head, cornerId, token) {
|
|
46762
47150
|
let published = await originContains(gitCommonDir, head);
|
|
46763
47151
|
if (!published) {
|
|
46764
|
-
await
|
|
47152
|
+
await execFileAsync11("git", [
|
|
46765
47153
|
`--git-dir=${gitCommonDir}`,
|
|
46766
47154
|
"fetch",
|
|
46767
47155
|
"--prune",
|
|
@@ -46777,7 +47165,7 @@ function hasUnpublishedWork(error) {
|
|
|
46777
47165
|
return error instanceof Error && / has unpushed (?:commits|working-tree work)$/.test(error.message);
|
|
46778
47166
|
}
|
|
46779
47167
|
async function originContains(gitCommonDir, head) {
|
|
46780
|
-
const result = await
|
|
47168
|
+
const result = await execFileAsync11("git", [
|
|
46781
47169
|
`--git-dir=${gitCommonDir}`,
|
|
46782
47170
|
"for-each-ref",
|
|
46783
47171
|
"--format=%(refname)",
|
|
@@ -46787,13 +47175,13 @@ async function originContains(gitCommonDir, head) {
|
|
|
46787
47175
|
]);
|
|
46788
47176
|
return Boolean(result.stdout.trim());
|
|
46789
47177
|
}
|
|
46790
|
-
var
|
|
47178
|
+
var execFileAsync11 = promisify11(execFile16);
|
|
46791
47179
|
async function removeCornerScratchWorkspace(input) {
|
|
46792
|
-
const expected =
|
|
46793
|
-
if (
|
|
47180
|
+
const expected = resolve40(input.roomRoot, "scratch");
|
|
47181
|
+
if (resolve40(input.scratchPath) !== expected) {
|
|
46794
47182
|
throw new Error(`refusing to remove scratch outside corner ${input.cornerId}`);
|
|
46795
47183
|
}
|
|
46796
|
-
await
|
|
47184
|
+
await rm17(expected, { recursive: true, force: true });
|
|
46797
47185
|
}
|
|
46798
47186
|
var RoomRuntimeCoordinator = class {
|
|
46799
47187
|
configPath;
|
|
@@ -46820,6 +47208,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
46820
47208
|
* then left alone; the checkout and its commits are kept, never deleted.
|
|
46821
47209
|
*/
|
|
46822
47210
|
archiveCleanupAbandoned = /* @__PURE__ */ new Set();
|
|
47211
|
+
lastCornerScratchSweepAt = 0;
|
|
46823
47212
|
startingCorners = /* @__PURE__ */ new Set();
|
|
46824
47213
|
/**
|
|
46825
47214
|
* Rooms whose start is in flight. `running` is not set until the checkout
|
|
@@ -47060,7 +47449,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
47060
47449
|
return;
|
|
47061
47450
|
try {
|
|
47062
47451
|
const result = await this.options.daemonApi.execute("listRoomCorners", {
|
|
47063
|
-
roomId: room.roomId
|
|
47452
|
+
roomId: room.roomId,
|
|
47453
|
+
activeOnly: true
|
|
47064
47454
|
});
|
|
47065
47455
|
for (const corner of result.corners) {
|
|
47066
47456
|
this.monolithCornerParents.set(corner.cornerId, room.roomId);
|
|
@@ -47100,6 +47490,9 @@ var RoomRuntimeCoordinator = class {
|
|
|
47100
47490
|
if (this.stopped)
|
|
47101
47491
|
return "member";
|
|
47102
47492
|
await this.sweepArchivedCornerWorktrees(archivedCorners, desired);
|
|
47493
|
+
if (this.stopped)
|
|
47494
|
+
return "member";
|
|
47495
|
+
await this.sweepCornerLocalState(archivedCorners, desired);
|
|
47103
47496
|
if (this.stopped)
|
|
47104
47497
|
return "member";
|
|
47105
47498
|
for (const cornerId of this.idleCornerSubscriptions.keys()) {
|
|
@@ -47117,6 +47510,10 @@ var RoomRuntimeCoordinator = class {
|
|
|
47117
47510
|
await this.stopRunning(channelId, running);
|
|
47118
47511
|
this.roomRemovalConfirmations.delete(channelId);
|
|
47119
47512
|
}
|
|
47513
|
+
for (const cornerId of this.monolithCornerParents.keys()) {
|
|
47514
|
+
if (!desired.has(cornerId) && !this.running.has(cornerId) && !this.startingCorners.has(cornerId))
|
|
47515
|
+
this.monolithCornerParents.delete(cornerId);
|
|
47516
|
+
}
|
|
47120
47517
|
this.surfaceHealth.retain(/* @__PURE__ */ new Set([...desired, ...this.running.keys()]));
|
|
47121
47518
|
await mapWithConcurrency(desiredTopRooms, ROOM_JOIN_CONCURRENCY, async (roomId) => {
|
|
47122
47519
|
if (this.stopped)
|
|
@@ -47191,6 +47588,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
47191
47588
|
if (event.archived === true) {
|
|
47192
47589
|
this.unwatchCorner(roomId);
|
|
47193
47590
|
this.surfaceHealth.remove(roomId);
|
|
47591
|
+
if (!this.running.has(roomId))
|
|
47592
|
+
this.monolithCornerParents.delete(roomId);
|
|
47194
47593
|
return;
|
|
47195
47594
|
}
|
|
47196
47595
|
this.roomRemovalConfirmations.delete(roomId);
|
|
@@ -47228,18 +47627,20 @@ var RoomRuntimeCoordinator = class {
|
|
|
47228
47627
|
} catch (error) {
|
|
47229
47628
|
console.error(`[thin-core] corner ${channelId} cleanup failed; will retry:`, error);
|
|
47230
47629
|
}
|
|
47630
|
+
if (running.worktree || running.scratch)
|
|
47631
|
+
await this.cleanupArchivedCornerLocalState(channelId);
|
|
47231
47632
|
}
|
|
47232
47633
|
roomRecord(roomId) {
|
|
47233
47634
|
return this.runtime.rooms.find((room) => room.channelId === roomId);
|
|
47234
47635
|
}
|
|
47235
47636
|
roomRoot(roomId) {
|
|
47236
|
-
return this.roomRecord(roomId)?.root ??
|
|
47637
|
+
return this.roomRecord(roomId)?.root ?? resolve40(dirname28(this.configPath), "rooms", roomId);
|
|
47237
47638
|
}
|
|
47238
47639
|
roomAgentHomeRoot(workspaceRoot, required = false) {
|
|
47239
47640
|
const flag = process.env.BUZZY_BODY_ROOM_HOME;
|
|
47240
47641
|
if (!required && flag === "0")
|
|
47241
47642
|
return void 0;
|
|
47242
|
-
const home =
|
|
47643
|
+
const home = resolve40(workspaceRoot, "agent-home");
|
|
47243
47644
|
if (!required && flag !== "1" && !existsSync10(home) && existsSync10(workspaceRoot))
|
|
47244
47645
|
return void 0;
|
|
47245
47646
|
try {
|
|
@@ -47255,10 +47656,10 @@ var RoomRuntimeCoordinator = class {
|
|
|
47255
47656
|
return {
|
|
47256
47657
|
...this.baseConfig,
|
|
47257
47658
|
workspaceRoot,
|
|
47258
|
-
agentPrivateRoot:
|
|
47259
|
-
agentMemoryRoot:
|
|
47260
|
-
openRouterRoutingCacheDir: openRouterRoutingCacheDir(
|
|
47261
|
-
turnTraceDir: turnTraceDirectory(
|
|
47659
|
+
agentPrivateRoot: resolve40(workspaceRoot, "agent-private"),
|
|
47660
|
+
agentMemoryRoot: resolve40(dirname28(this.configPath), "memory"),
|
|
47661
|
+
openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname28(this.configPath)),
|
|
47662
|
+
turnTraceDir: turnTraceDirectory(dirname28(this.configPath)),
|
|
47262
47663
|
...agentHomeRoot ? { agentHomeRoot } : {}
|
|
47263
47664
|
};
|
|
47264
47665
|
}
|
|
@@ -47339,17 +47740,17 @@ var RoomRuntimeCoordinator = class {
|
|
|
47339
47740
|
const remote = roomCheckoutRemote(repository.remote);
|
|
47340
47741
|
const targetBranch = repository.targetBranch || "main";
|
|
47341
47742
|
const checkoutId = createHash14("sha256").update(`${roomId}\0${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
|
|
47342
|
-
const path =
|
|
47343
|
-
await mkdir27(
|
|
47743
|
+
const path = resolve40(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
|
|
47744
|
+
await mkdir27(dirname28(path), { recursive: true, mode: 448 });
|
|
47344
47745
|
const token = remote.startsWith("https://github.com/") ? await this.parentRepositoryToken(roomId) : void 0;
|
|
47345
47746
|
const env = token ? githubGitEnv(token.token) : process.env;
|
|
47346
|
-
if (!existsSync10(
|
|
47347
|
-
await
|
|
47747
|
+
if (!existsSync10(resolve40(path, ".git"))) {
|
|
47748
|
+
await execFileAsync11("git", ["clone", "--no-checkout", remote, path], {
|
|
47348
47749
|
env,
|
|
47349
47750
|
maxBuffer: 4 * 1024 * 1024
|
|
47350
47751
|
});
|
|
47351
47752
|
}
|
|
47352
|
-
const fetched = await
|
|
47753
|
+
const fetched = await execFileAsync11("git", [
|
|
47353
47754
|
"-C",
|
|
47354
47755
|
path,
|
|
47355
47756
|
"fetch",
|
|
@@ -47365,7 +47766,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
47365
47766
|
void this.options.daemonApi.execute("noteEmptyRoomRepository", { roomId }).catch((error) => console.warn(`[thin-core] Room ${roomId} empty-repository notice failed:`, error));
|
|
47366
47767
|
return this.roomRoot(roomId);
|
|
47367
47768
|
}
|
|
47368
|
-
await
|
|
47769
|
+
await execFileAsync11("git", ["-C", path, "checkout", "--detach", "--force", `origin/${targetBranch}`], {
|
|
47369
47770
|
env,
|
|
47370
47771
|
maxBuffer: 4 * 1024 * 1024
|
|
47371
47772
|
});
|
|
@@ -47380,7 +47781,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
47380
47781
|
const cwd = await this.materializeRoomCheckout(roomId, repository);
|
|
47381
47782
|
if (cwd === this.roomRoot(roomId))
|
|
47382
47783
|
return { cwd };
|
|
47383
|
-
const { stdout: stdout6 } = await
|
|
47784
|
+
const { stdout: stdout6 } = await execFileAsync11("git", ["-C", cwd, "rev-parse", "--verify", "HEAD"]);
|
|
47384
47785
|
return { cwd, branch, commit: stdout6.trim() };
|
|
47385
47786
|
} catch (error) {
|
|
47386
47787
|
console.warn(`[thin-core] Room ${roomId} checkout refresh unavailable:`, error);
|
|
@@ -47430,9 +47831,11 @@ var RoomRuntimeCoordinator = class {
|
|
|
47430
47831
|
featureBranch,
|
|
47431
47832
|
token: granted.token
|
|
47432
47833
|
}) : void 0;
|
|
47433
|
-
const workspacePath = worktree?.path ??
|
|
47834
|
+
const workspacePath = worktree?.path ?? resolve40(this.roomRoot(corner.cornerId), "scratch");
|
|
47434
47835
|
if (!worktree)
|
|
47435
47836
|
await mkdir27(workspacePath, { recursive: true, mode: 448 });
|
|
47837
|
+
await writePrivateFileAtomically(resolve40(this.roomRoot(corner.cornerId), ".beeline-corner.json"), `${JSON.stringify({ cornerId: corner.cornerId, parentRoomId: corner.parentRoomId })}
|
|
47838
|
+
`);
|
|
47436
47839
|
if (worktree && shouldPostInitialCornerWorkingState(restore)) {
|
|
47437
47840
|
await this.options.daemonApi.execute("postCornerRemoteState", {
|
|
47438
47841
|
cornerId: corner.cornerId,
|
|
@@ -47486,10 +47889,11 @@ var RoomRuntimeCoordinator = class {
|
|
|
47486
47889
|
this.surfaceHealth.degraded(corner.cornerId, "corner command loop exited");
|
|
47487
47890
|
console.error(`[thin-core] corner ${corner.cornerId} failed:`, error);
|
|
47488
47891
|
}
|
|
47489
|
-
}).finally(() => {
|
|
47892
|
+
}).finally(async () => {
|
|
47490
47893
|
if (this.running.get(corner.cornerId)?.body === loop) {
|
|
47491
47894
|
this.running.delete(corner.cornerId);
|
|
47492
47895
|
}
|
|
47896
|
+
await this.cleanupArchivedCornerLocalState(corner.cornerId).catch((error) => console.error(`[thin-core] corner ${corner.cornerId} local cleanup deferred:`, error));
|
|
47493
47897
|
});
|
|
47494
47898
|
if (this.stopped) {
|
|
47495
47899
|
controller.abort();
|
|
@@ -47606,7 +48010,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
47606
48010
|
await this.restartRunningRoomForRepositoryChange(roomId);
|
|
47607
48011
|
if (this.stopped)
|
|
47608
48012
|
return;
|
|
47609
|
-
const result = await this.options.daemonApi.execute("listRoomCorners", { roomId });
|
|
48013
|
+
const result = await this.options.daemonApi.execute("listRoomCorners", { roomId, activeOnly: true });
|
|
47610
48014
|
for (const corner of result.corners) {
|
|
47611
48015
|
this.monolithCornerParents.set(corner.cornerId, roomId);
|
|
47612
48016
|
if (corner.archived)
|
|
@@ -47763,6 +48167,12 @@ var RoomRuntimeCoordinator = class {
|
|
|
47763
48167
|
} catch (error) {
|
|
47764
48168
|
if (hasUnpublishedWork(error)) {
|
|
47765
48169
|
this.archiveCleanupAbandoned.add(cornerId);
|
|
48170
|
+
try {
|
|
48171
|
+
const saved = await preserveUnpublishedCornerWorktree(worktree, "archived with unpublished local work");
|
|
48172
|
+
console.warn(`[thin-core] corner ${cornerId} recoverable at ${saved.pointer}; pruned ${saved.pruned.join(", ") || "no generated directories"}`);
|
|
48173
|
+
} catch (preserveError) {
|
|
48174
|
+
console.error(`[thin-core] corner ${cornerId} recovery preservation failed:`, preserveError);
|
|
48175
|
+
}
|
|
47766
48176
|
console.error(`[thin-core] corner ${cornerId} branch cleanup abandoned; unpublished work kept:`, error);
|
|
47767
48177
|
continue;
|
|
47768
48178
|
}
|
|
@@ -47783,11 +48193,14 @@ var RoomRuntimeCoordinator = class {
|
|
|
47783
48193
|
continue;
|
|
47784
48194
|
if (!this.archiveCleanupDue(cornerId))
|
|
47785
48195
|
continue;
|
|
48196
|
+
if (this.archiveCleanupAbandoned.has(cornerId))
|
|
48197
|
+
continue;
|
|
47786
48198
|
if (this.archiveCleanupAccessDenied.has(cornerId) && !corners.has(cornerId))
|
|
47787
48199
|
continue;
|
|
47788
48200
|
this.archiveCleanupAccessDenied.delete(cornerId);
|
|
47789
48201
|
let corner = corners.get(cornerId);
|
|
47790
48202
|
let discovered;
|
|
48203
|
+
let candidate;
|
|
47791
48204
|
try {
|
|
47792
48205
|
discovered = await discoverCornerWorktree(this.runtime.supervisorRoot, cornerId);
|
|
47793
48206
|
if (!discovered) {
|
|
@@ -47813,22 +48226,33 @@ var RoomRuntimeCoordinator = class {
|
|
|
47813
48226
|
throw new Error(`archived corner ${corner.cornerId} has no authoritative repository`);
|
|
47814
48227
|
}
|
|
47815
48228
|
const expectedCommonDir = cornerRepositoryCacheDir(this.runtime.supervisorRoot, repository.remote);
|
|
47816
|
-
if (
|
|
48229
|
+
if (resolve40(discovered.gitCommonDir) !== expectedCommonDir) {
|
|
47817
48230
|
throw new Error(`archived corner ${corner.cornerId} repository cache does not match`);
|
|
47818
48231
|
}
|
|
47819
48232
|
if (!restore.featureBranch) {
|
|
47820
48233
|
throw new Error(`archived corner ${corner.cornerId} has no authoritative feature branch`);
|
|
47821
48234
|
}
|
|
47822
|
-
|
|
48235
|
+
candidate = {
|
|
47823
48236
|
...discovered,
|
|
47824
48237
|
cornerId: corner.cornerId,
|
|
47825
48238
|
branch: restore.featureBranch,
|
|
47826
48239
|
parentRoomId: corner.parentRoomId,
|
|
47827
48240
|
token: "",
|
|
47828
48241
|
recovered: true
|
|
47829
|
-
}
|
|
48242
|
+
};
|
|
48243
|
+
await this.reapCornerWorktree(candidate);
|
|
47830
48244
|
console.log(`[thin-core] swept archived corner worktree ${cornerId}`);
|
|
47831
48245
|
} catch (error) {
|
|
48246
|
+
if (candidate && hasUnpublishedWork(error)) {
|
|
48247
|
+
this.archiveCleanupAbandoned.add(cornerId);
|
|
48248
|
+
try {
|
|
48249
|
+
const saved = await preserveUnpublishedCornerWorktree(candidate, "archived with unpublished local work");
|
|
48250
|
+
console.warn(`[thin-core] archived corner ${cornerId} recoverable at ${saved.pointer}; pruned ${saved.pruned.join(", ") || "no generated directories"}`);
|
|
48251
|
+
} catch (preserveError) {
|
|
48252
|
+
console.error(`[thin-core] archived corner ${cornerId} recovery preservation failed:`, preserveError);
|
|
48253
|
+
}
|
|
48254
|
+
continue;
|
|
48255
|
+
}
|
|
47832
48256
|
if (error instanceof DaemonApiError && error.status === 403)
|
|
47833
48257
|
this.archiveCleanupAccessDenied.add(cornerId);
|
|
47834
48258
|
else
|
|
@@ -47885,6 +48309,64 @@ var RoomRuntimeCoordinator = class {
|
|
|
47885
48309
|
scratchPath: scratch.path
|
|
47886
48310
|
});
|
|
47887
48311
|
}
|
|
48312
|
+
/** Reap a corner's private state only after the server confirms archive and
|
|
48313
|
+
* its ACP session has suspended. A missing/failed read is never authority. */
|
|
48314
|
+
async cleanupArchivedCornerLocalState(cornerId, knownArchive) {
|
|
48315
|
+
if (this.running.has(cornerId) || this.startingCorners.has(cornerId))
|
|
48316
|
+
return false;
|
|
48317
|
+
const root = resolve40(dirname28(this.configPath), "rooms", cornerId);
|
|
48318
|
+
if (this.roomRoot(cornerId) !== root || !/^[a-zA-Z0-9-]{1,80}$/.test(cornerId))
|
|
48319
|
+
return false;
|
|
48320
|
+
const info = await lstat7(root).catch(() => void 0);
|
|
48321
|
+
if (!info?.isDirectory() || await realpath3(root) !== root)
|
|
48322
|
+
return false;
|
|
48323
|
+
let archived = knownArchive?.has(cornerId) ?? false;
|
|
48324
|
+
if (!archived) {
|
|
48325
|
+
try {
|
|
48326
|
+
const restore = await this.options.daemonApi.execute("getCornerRestoreState", { cornerId });
|
|
48327
|
+
archived = restore.archived === true;
|
|
48328
|
+
} catch {
|
|
48329
|
+
return false;
|
|
48330
|
+
}
|
|
48331
|
+
}
|
|
48332
|
+
if (!archived)
|
|
48333
|
+
return false;
|
|
48334
|
+
await this.scheduler.suspend(cornerId);
|
|
48335
|
+
await rm17(resolve40(root, "scratch"), { recursive: true, force: true });
|
|
48336
|
+
await rm17(resolve40(root, "agent-home"), { recursive: true, force: true });
|
|
48337
|
+
await rm17(resolve40(root, ".beeline-corner.json"), { force: true });
|
|
48338
|
+
return true;
|
|
48339
|
+
}
|
|
48340
|
+
/** Recover chat-only scratch and per-member homes after missed close events
|
|
48341
|
+
* or a helper restart. A marker identifies new code corners after their
|
|
48342
|
+
* checkout has already gone; a scratch directory identifies legacy chat
|
|
48343
|
+
* corners. Active scratch gets a 14-day file TTL, never a wholesale reap. */
|
|
48344
|
+
async sweepCornerLocalState(archived, desired) {
|
|
48345
|
+
const root = resolve40(dirname28(this.configPath), "rooms");
|
|
48346
|
+
const due = this.now() - this.lastCornerScratchSweepAt >= 6 * 60 * 6e4;
|
|
48347
|
+
if (due)
|
|
48348
|
+
this.lastCornerScratchSweepAt = this.now();
|
|
48349
|
+
for (const entry of await readdir11(root, { withFileTypes: true }).catch(() => [])) {
|
|
48350
|
+
if (!entry.isDirectory() || !/^[a-zA-Z0-9-]{1,80}$/.test(entry.name))
|
|
48351
|
+
continue;
|
|
48352
|
+
const roomRoot = resolve40(root, entry.name);
|
|
48353
|
+
const scratch = resolve40(roomRoot, "scratch");
|
|
48354
|
+
const marker = resolve40(roomRoot, ".beeline-corner.json");
|
|
48355
|
+
const hasScratch = (await lstat7(scratch).catch(() => void 0))?.isDirectory() ?? false;
|
|
48356
|
+
const hasMarker = (await lstat7(marker).catch(() => void 0))?.isFile() ?? false;
|
|
48357
|
+
if (!hasScratch && !hasMarker)
|
|
48358
|
+
continue;
|
|
48359
|
+
if (desired.has(entry.name)) {
|
|
48360
|
+
if (due && hasScratch && !this.startingCorners.has(entry.name) && !this.running.get(entry.name)?.body.isBusy()) {
|
|
48361
|
+
await sweepStaleCornerScratch(scratch, this.now(), CORNER_SCRATCH_TTL_MS).catch((error) => console.error(`[thin-core] corner ${entry.name} scratch TTL sweep failed:`, error));
|
|
48362
|
+
}
|
|
48363
|
+
continue;
|
|
48364
|
+
}
|
|
48365
|
+
if (this.running.has(entry.name) || this.startingCorners.has(entry.name))
|
|
48366
|
+
continue;
|
|
48367
|
+
await this.cleanupArchivedCornerLocalState(entry.name, archived).catch((error) => console.error(`[thin-core] corner ${entry.name} local cleanup deferred:`, error));
|
|
48368
|
+
}
|
|
48369
|
+
}
|
|
47888
48370
|
notePoll(roomId) {
|
|
47889
48371
|
this.surfaceHealth.intakeReady(roomId);
|
|
47890
48372
|
const room = this.running.get(roomId);
|
|
@@ -47969,7 +48451,7 @@ function githubGitEnv(token) {
|
|
|
47969
48451
|
}
|
|
47970
48452
|
async function gitRefExists(gitCommonDir, ref) {
|
|
47971
48453
|
try {
|
|
47972
|
-
await
|
|
48454
|
+
await execFileAsync11("git", [
|
|
47973
48455
|
`--git-dir=${gitCommonDir}`,
|
|
47974
48456
|
"show-ref",
|
|
47975
48457
|
"--verify",
|
|
@@ -47985,7 +48467,7 @@ async function gitRefExists(gitCommonDir, ref) {
|
|
|
47985
48467
|
}
|
|
47986
48468
|
async function repositoryHeadRef(gitCommonDir) {
|
|
47987
48469
|
try {
|
|
47988
|
-
const head = await
|
|
48470
|
+
const head = await execFileAsync11("git", [
|
|
47989
48471
|
`--git-dir=${gitCommonDir}`,
|
|
47990
48472
|
"symbolic-ref",
|
|
47991
48473
|
"--quiet",
|
|
@@ -48005,7 +48487,7 @@ ${gitStderr(error)}`);
|
|
|
48005
48487
|
}
|
|
48006
48488
|
async function deleteExactRemoteBranch(gitCommonDir, remoteRef, token, options = {}) {
|
|
48007
48489
|
const authEnv = githubGitEnv(token);
|
|
48008
|
-
const listRemote = () =>
|
|
48490
|
+
const listRemote = () => execFileAsync11("git", [`--git-dir=${gitCommonDir}`, "ls-remote", "--heads", "origin", remoteRef], {
|
|
48009
48491
|
env: authEnv,
|
|
48010
48492
|
maxBuffer: 4 * 1024 * 1024
|
|
48011
48493
|
});
|
|
@@ -48021,7 +48503,7 @@ async function deleteExactRemoteBranch(gitCommonDir, remoteRef, token, options =
|
|
|
48021
48503
|
try {
|
|
48022
48504
|
const remote = await listRemote();
|
|
48023
48505
|
if (remote.stdout.trim()) {
|
|
48024
|
-
await
|
|
48506
|
+
await execFileAsync11("git", [`--git-dir=${gitCommonDir}`, "push", "origin", `:${remoteRef}`], {
|
|
48025
48507
|
env: authEnv,
|
|
48026
48508
|
maxBuffer: 4 * 1024 * 1024
|
|
48027
48509
|
});
|
|
@@ -48163,15 +48645,15 @@ var ThinDaemonCore = class {
|
|
|
48163
48645
|
};
|
|
48164
48646
|
|
|
48165
48647
|
// apps/body/dist/force-update-journal.js
|
|
48166
|
-
import { mkdirSync as mkdirSync4, readFileSync as
|
|
48167
|
-
import { resolve as
|
|
48648
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync10, renameSync, writeFileSync as writeFileSync5 } from "node:fs";
|
|
48649
|
+
import { resolve as resolve41 } from "node:path";
|
|
48168
48650
|
var NAME = "force-update-interruptions.json";
|
|
48169
48651
|
function pathFor(runtimeDir) {
|
|
48170
|
-
return
|
|
48652
|
+
return resolve41(runtimeDir, NAME);
|
|
48171
48653
|
}
|
|
48172
48654
|
function read(runtimeDir) {
|
|
48173
48655
|
try {
|
|
48174
|
-
const rows = JSON.parse(
|
|
48656
|
+
const rows = JSON.parse(readFileSync10(pathFor(runtimeDir), "utf8"));
|
|
48175
48657
|
if (!Array.isArray(rows))
|
|
48176
48658
|
throw new Error("invalid force-update interruption journal");
|
|
48177
48659
|
return rows.map((row) => {
|
|
@@ -48245,17 +48727,17 @@ function staleGeneration(error) {
|
|
|
48245
48727
|
init_launchd();
|
|
48246
48728
|
init_systemd();
|
|
48247
48729
|
import { mkdir as mkdir28, rename as rename11 } from "node:fs/promises";
|
|
48248
|
-
import { dirname as
|
|
48730
|
+
import { dirname as dirname29, resolve as resolve42 } from "node:path";
|
|
48249
48731
|
async function retireRemovedAgent(runtime, options = {}) {
|
|
48250
|
-
const deletedRoot =
|
|
48251
|
-
const target =
|
|
48732
|
+
const deletedRoot = resolve42(runtime.supervisorRoot, "beeline", "deleted-runtimes");
|
|
48733
|
+
const target = resolve42(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
|
|
48252
48734
|
return relocateAgentRuntime(runtime, target, {
|
|
48253
48735
|
...options.run ? { run: options.run } : {}
|
|
48254
48736
|
});
|
|
48255
48737
|
}
|
|
48256
48738
|
async function relocateAgentRuntime(runtime, target, options = {}) {
|
|
48257
48739
|
const source = runtimeDirectory(runtime.supervisorRoot, runtime.agent.publicKey);
|
|
48258
|
-
const destination =
|
|
48740
|
+
const destination = resolve42(target);
|
|
48259
48741
|
if (destination === source || destination.startsWith(`${source}/`)) {
|
|
48260
48742
|
throw new Error("agent runtime destination must be outside the live runtime");
|
|
48261
48743
|
}
|
|
@@ -48268,7 +48750,7 @@ async function relocateAgentRuntime(runtime, target, options = {}) {
|
|
|
48268
48750
|
...options.run ? { run: options.run } : {}
|
|
48269
48751
|
});
|
|
48270
48752
|
}
|
|
48271
|
-
await mkdir28(
|
|
48753
|
+
await mkdir28(dirname29(destination), { recursive: true, mode: 448 });
|
|
48272
48754
|
await rename11(source, destination);
|
|
48273
48755
|
return destination;
|
|
48274
48756
|
}
|
|
@@ -48278,8 +48760,8 @@ init_self_update();
|
|
|
48278
48760
|
init_systemd();
|
|
48279
48761
|
|
|
48280
48762
|
// apps/body/dist/release-status.js
|
|
48281
|
-
import { readFile as readFile31, readdir as
|
|
48282
|
-
import { resolve as
|
|
48763
|
+
import { readFile as readFile31, readdir as readdir12, rename as rename12, writeFile as writeFile21 } from "node:fs/promises";
|
|
48764
|
+
import { resolve as resolve43 } from "node:path";
|
|
48283
48765
|
var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
|
|
48284
48766
|
var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
|
|
48285
48767
|
var SOURCE_SHA = /^[0-9a-f]{7,64}$/;
|
|
@@ -48296,7 +48778,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
|
|
|
48296
48778
|
pid: options.pid ?? process.pid,
|
|
48297
48779
|
readyAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString()
|
|
48298
48780
|
};
|
|
48299
|
-
const target =
|
|
48781
|
+
const target = resolve43(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
|
|
48300
48782
|
const temporary = `${target}.${status.pid}.tmp`;
|
|
48301
48783
|
await writeFile21(temporary, `${JSON.stringify(status, null, 2)}
|
|
48302
48784
|
`, { mode: 384 });
|
|
@@ -48305,8 +48787,8 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
|
|
|
48305
48787
|
}
|
|
48306
48788
|
|
|
48307
48789
|
// apps/body/dist/scratch-sweep.js
|
|
48308
|
-
import { lstat as
|
|
48309
|
-
import { resolve as
|
|
48790
|
+
import { lstat as lstat8, readdir as readdir13, rmdir as rmdir3, unlink as unlink10 } from "node:fs/promises";
|
|
48791
|
+
import { resolve as resolve44 } from "node:path";
|
|
48310
48792
|
var DEFAULT_SCRATCH_TTL_HOURS = 72;
|
|
48311
48793
|
var NEVER_SWEEP_SUBDIR_NAMES = new Set(HOME_SUBDIRS.filter((name) => name !== "tmp"));
|
|
48312
48794
|
function scratchTtlMs(env = process.env) {
|
|
@@ -48315,10 +48797,10 @@ function scratchTtlMs(env = process.env) {
|
|
|
48315
48797
|
return (Number.isFinite(hours) && hours > 0 ? hours : DEFAULT_SCRATCH_TTL_HOURS) * 60 * 60 * 1e3;
|
|
48316
48798
|
}
|
|
48317
48799
|
async function discoverAttachScratchRoots(runtimeDir) {
|
|
48318
|
-
const roomsDir =
|
|
48800
|
+
const roomsDir = resolve44(runtimeDir, "rooms");
|
|
48319
48801
|
let entries;
|
|
48320
48802
|
try {
|
|
48321
|
-
entries = await
|
|
48803
|
+
entries = await readdir13(roomsDir, { withFileTypes: true });
|
|
48322
48804
|
} catch {
|
|
48323
48805
|
return [];
|
|
48324
48806
|
}
|
|
@@ -48326,8 +48808,8 @@ async function discoverAttachScratchRoots(runtimeDir) {
|
|
|
48326
48808
|
for (const entry of entries) {
|
|
48327
48809
|
if (!entry.isDirectory())
|
|
48328
48810
|
continue;
|
|
48329
|
-
const home =
|
|
48330
|
-
const stats = await
|
|
48811
|
+
const home = resolve44(roomsDir, entry.name, "agent-home");
|
|
48812
|
+
const stats = await lstat8(home).catch(() => void 0);
|
|
48331
48813
|
if (stats?.isDirectory())
|
|
48332
48814
|
roots.push(home);
|
|
48333
48815
|
}
|
|
@@ -48336,7 +48818,7 @@ async function discoverAttachScratchRoots(runtimeDir) {
|
|
|
48336
48818
|
async function removeStaleFiles(dir, cutoffMs, protectNamesHere) {
|
|
48337
48819
|
let entries;
|
|
48338
48820
|
try {
|
|
48339
|
-
entries = await
|
|
48821
|
+
entries = await readdir13(dir, { withFileTypes: true });
|
|
48340
48822
|
} catch {
|
|
48341
48823
|
return { removedFiles: 0, removedBytes: 0 };
|
|
48342
48824
|
}
|
|
@@ -48345,22 +48827,22 @@ async function removeStaleFiles(dir, cutoffMs, protectNamesHere) {
|
|
|
48345
48827
|
for (const entry of entries) {
|
|
48346
48828
|
if (protectNamesHere && NEVER_SWEEP_SUBDIR_NAMES.has(entry.name))
|
|
48347
48829
|
continue;
|
|
48348
|
-
const path =
|
|
48349
|
-
const stats = await
|
|
48830
|
+
const path = resolve44(dir, entry.name);
|
|
48831
|
+
const stats = await lstat8(path).catch(() => void 0);
|
|
48350
48832
|
if (!stats || stats.isSymbolicLink())
|
|
48351
48833
|
continue;
|
|
48352
48834
|
if (stats.isDirectory()) {
|
|
48353
48835
|
const nested = await removeStaleFiles(path, cutoffMs, false);
|
|
48354
48836
|
removedFiles += nested.removedFiles;
|
|
48355
48837
|
removedBytes += nested.removedBytes;
|
|
48356
|
-
const remaining = await
|
|
48838
|
+
const remaining = await readdir13(path).catch(() => void 0);
|
|
48357
48839
|
if (remaining && remaining.length === 0)
|
|
48358
|
-
await
|
|
48840
|
+
await rmdir3(path).catch(() => void 0);
|
|
48359
48841
|
continue;
|
|
48360
48842
|
}
|
|
48361
48843
|
if (!stats.isFile() || stats.mtimeMs >= cutoffMs)
|
|
48362
48844
|
continue;
|
|
48363
|
-
await
|
|
48845
|
+
await unlink10(path).catch(() => void 0);
|
|
48364
48846
|
removedFiles += 1;
|
|
48365
48847
|
removedBytes += stats.size;
|
|
48366
48848
|
}
|
|
@@ -48371,7 +48853,7 @@ async function sweepAttachScratchRoots(roots, ttlMs, now2 = Date.now()) {
|
|
|
48371
48853
|
let removedFiles = 0;
|
|
48372
48854
|
let removedBytes = 0;
|
|
48373
48855
|
for (const root of roots) {
|
|
48374
|
-
const stats = await
|
|
48856
|
+
const stats = await lstat8(root).catch(() => void 0);
|
|
48375
48857
|
if (!stats?.isDirectory())
|
|
48376
48858
|
continue;
|
|
48377
48859
|
const result = await removeStaleFiles(root, cutoffMs, true);
|
|
@@ -48394,7 +48876,7 @@ function runScratchSweepLogged(runtimeDir) {
|
|
|
48394
48876
|
void runScratchSweep(runtimeDir).catch((error) => console.error("[body] scratch sweep failed:", error));
|
|
48395
48877
|
}
|
|
48396
48878
|
async function runAgentRuntime(configPath, host, signal) {
|
|
48397
|
-
const runtimeDir =
|
|
48879
|
+
const runtimeDir = dirname30(configPath);
|
|
48398
48880
|
await convergeRuntimeRecordFileModes(configPath);
|
|
48399
48881
|
const accessMigration = await migrateRuntimeRecordAccessPolicy(configPath);
|
|
48400
48882
|
let runtime = accessMigration.runtime;
|
|
@@ -48430,7 +48912,7 @@ async function runAgentRuntime(configPath, host, signal) {
|
|
|
48430
48912
|
BUZZ_DEV_MCP_BIN: runtime.mcpBinary
|
|
48431
48913
|
};
|
|
48432
48914
|
const config = loadBodyConfig({
|
|
48433
|
-
workspaceRoot:
|
|
48915
|
+
workspaceRoot: resolve45(runtimeDir, "workspace"),
|
|
48434
48916
|
llmEnvFile: runtime.llmEnvFile,
|
|
48435
48917
|
env,
|
|
48436
48918
|
agent
|
|
@@ -48740,7 +49222,7 @@ async function runAgentRuntime(configPath, host, signal) {
|
|
|
48740
49222
|
return exitReason ?? lifecycle.stopReason ?? "stopped";
|
|
48741
49223
|
}
|
|
48742
49224
|
function registryBrokerSocketPath(home, agentId) {
|
|
48743
|
-
return
|
|
49225
|
+
return join23(home ?? homedir19(), ".beeline", "registry-mcp-broker", `${process.pid}-${agentId.slice(0, 8)}.sock`);
|
|
48744
49226
|
}
|
|
48745
49227
|
function interruptHostedAgent(agent) {
|
|
48746
49228
|
agent.lifecycle.quiesce("force-update");
|
|
@@ -48781,6 +49263,78 @@ var ForceUpdateCoordinator = class {
|
|
|
48781
49263
|
init_launchd();
|
|
48782
49264
|
init_self_update();
|
|
48783
49265
|
init_systemd();
|
|
49266
|
+
|
|
49267
|
+
// apps/body/dist/host-disk-retention.js
|
|
49268
|
+
import { execFile as execFile17 } from "node:child_process";
|
|
49269
|
+
import { lstat as lstat9, readdir as readdir14, rm as rm18 } from "node:fs/promises";
|
|
49270
|
+
import { join as join24, resolve as resolve46 } from "node:path";
|
|
49271
|
+
import { promisify as promisify12 } from "node:util";
|
|
49272
|
+
var execFileAsync12 = promisify12(execFile17);
|
|
49273
|
+
var DELETED_RUNTIME_TTL_MS = 30 * 24 * 60 * 6e4;
|
|
49274
|
+
var REPOSITORY_CACHE_TTL_MS = 30 * 24 * 60 * 6e4;
|
|
49275
|
+
async function pruneDeletedRuntimes(supervisorRoot, now2 = Date.now()) {
|
|
49276
|
+
const root = resolve46(supervisorRoot, "beeline", "deleted-runtimes");
|
|
49277
|
+
const removed = [];
|
|
49278
|
+
for (const entry of await readdir14(root, { withFileTypes: true }).catch(() => [])) {
|
|
49279
|
+
const match = /^([a-f0-9]{64})-(\d{13})$/.exec(entry.name);
|
|
49280
|
+
if (!entry.isDirectory() || !match || now2 - Number(match[2]) < DELETED_RUNTIME_TTL_MS)
|
|
49281
|
+
continue;
|
|
49282
|
+
const path = join24(root, entry.name);
|
|
49283
|
+
if (!(await lstat9(path)).isDirectory())
|
|
49284
|
+
continue;
|
|
49285
|
+
await rm18(path, { recursive: true, force: true });
|
|
49286
|
+
removed.push(path);
|
|
49287
|
+
}
|
|
49288
|
+
return removed;
|
|
49289
|
+
}
|
|
49290
|
+
async function pruneRepositoryCaches(supervisorRoot, now2 = Date.now()) {
|
|
49291
|
+
const root = resolve46(supervisorRoot, "beeline", "repositories");
|
|
49292
|
+
const removed = [];
|
|
49293
|
+
for (const entry of await readdir14(root, { withFileTypes: true }).catch(() => [])) {
|
|
49294
|
+
if (!entry.isDirectory() || !/^[a-f0-9]{24}\.git$/.test(entry.name))
|
|
49295
|
+
continue;
|
|
49296
|
+
const path = join24(root, entry.name);
|
|
49297
|
+
const info = await lstat9(path);
|
|
49298
|
+
if (!info.isDirectory() || now2 - info.mtimeMs < REPOSITORY_CACHE_TTL_MS)
|
|
49299
|
+
continue;
|
|
49300
|
+
const listing = await execFileAsync12("git", [`--git-dir=${path}`, "worktree", "list", "--porcelain"]).then((result) => result.stdout, () => void 0);
|
|
49301
|
+
if (listing === void 0)
|
|
49302
|
+
continue;
|
|
49303
|
+
const attached = listing.split("\n").some((line) => line.startsWith("worktree ") && resolve46(line.slice("worktree ".length)) !== path);
|
|
49304
|
+
if (attached)
|
|
49305
|
+
continue;
|
|
49306
|
+
const refs = await execFileAsync12("git", [
|
|
49307
|
+
`--git-dir=${path}`,
|
|
49308
|
+
"for-each-ref",
|
|
49309
|
+
"--format=%(refname) %(objectname)"
|
|
49310
|
+
]).then((result) => result.stdout, () => void 0);
|
|
49311
|
+
if (refs === void 0)
|
|
49312
|
+
continue;
|
|
49313
|
+
const byName = /* @__PURE__ */ new Map();
|
|
49314
|
+
for (const line of refs.trim().split("\n")) {
|
|
49315
|
+
const match = /^(refs\/\S+) ([a-f0-9]{40,64})$/.exec(line);
|
|
49316
|
+
if (match)
|
|
49317
|
+
byName.set(match[1], match[2]);
|
|
49318
|
+
}
|
|
49319
|
+
const unpublishedHead = [...byName].some(([name, oid]) => name.startsWith("refs/heads/") && byName.get(name.replace("refs/heads/", "refs/remotes/origin/")) !== oid);
|
|
49320
|
+
if (unpublishedHead)
|
|
49321
|
+
continue;
|
|
49322
|
+
const unreachable = await execFileAsync12("git", [
|
|
49323
|
+
`--git-dir=${path}`,
|
|
49324
|
+
"fsck",
|
|
49325
|
+
"--unreachable",
|
|
49326
|
+
"--no-reflogs",
|
|
49327
|
+
"--no-progress"
|
|
49328
|
+
]).then((result) => result.stdout, () => void 0);
|
|
49329
|
+
if (unreachable === void 0 || /unreachable commit /.test(unreachable))
|
|
49330
|
+
continue;
|
|
49331
|
+
await rm18(path, { recursive: true, force: true });
|
|
49332
|
+
removed.push(path);
|
|
49333
|
+
}
|
|
49334
|
+
return removed;
|
|
49335
|
+
}
|
|
49336
|
+
|
|
49337
|
+
// apps/body/dist/machine-helper.js
|
|
48784
49338
|
var AGENT_RESTART_BASE_MS = 5e3;
|
|
48785
49339
|
var AGENT_RESTART_MAX_MS = 6e4;
|
|
48786
49340
|
var PREVIOUS_HOLDER_WAIT_MS = 12e4;
|
|
@@ -48801,6 +49355,32 @@ async function runMachineHelper(options = {}) {
|
|
|
48801
49355
|
const slots = /* @__PURE__ */ new Map();
|
|
48802
49356
|
const hosted = /* @__PURE__ */ new Map();
|
|
48803
49357
|
const links = /* @__PURE__ */ new Map();
|
|
49358
|
+
let diskSweepRunning = false;
|
|
49359
|
+
let lastModelSweepAt = 0;
|
|
49360
|
+
let lastRetentionSweepAt = 0;
|
|
49361
|
+
const sweepHostDisk = async () => {
|
|
49362
|
+
const now2 = Date.now();
|
|
49363
|
+
if (controller.signal.aborted || diskSweepRunning || [...slots.values()].some((slot) => slot.state === "starting" || slot.state === "restarting") || [...hosted.values()].some((agent) => !agent.core.isWorkspaceIdle()) || now2 - lastModelSweepAt < 60 * 6e4 && now2 - lastRetentionSweepAt < 24 * 60 * 6e4)
|
|
49364
|
+
return;
|
|
49365
|
+
diskSweepRunning = true;
|
|
49366
|
+
try {
|
|
49367
|
+
const modelDue = now2 - lastModelSweepAt >= 60 * 6e4;
|
|
49368
|
+
const removed = modelDue ? await pruneSharedModelCache(resolve47(supervisorRoot, "beeline", "model-cache")) : [];
|
|
49369
|
+
if (modelDue)
|
|
49370
|
+
lastModelSweepAt = now2;
|
|
49371
|
+
if (now2 - lastRetentionSweepAt >= 24 * 60 * 6e4) {
|
|
49372
|
+
removed.push(...await pruneDeletedRuntimes(supervisorRoot));
|
|
49373
|
+
removed.push(...await pruneRepositoryCaches(supervisorRoot));
|
|
49374
|
+
lastRetentionSweepAt = now2;
|
|
49375
|
+
}
|
|
49376
|
+
if (removed.length)
|
|
49377
|
+
console.log(`[helper] idle disk sweep removed ${removed.length} expired cache/runtime directories`);
|
|
49378
|
+
} catch (error) {
|
|
49379
|
+
console.warn("[helper] idle disk sweep failed:", error);
|
|
49380
|
+
} finally {
|
|
49381
|
+
diskSweepRunning = false;
|
|
49382
|
+
}
|
|
49383
|
+
};
|
|
48804
49384
|
if (!options.configPaths)
|
|
48805
49385
|
await writeHelperPidRecord(supervisorRoot, process.pid);
|
|
48806
49386
|
const layout = beelineInstallLayout(env);
|
|
@@ -48812,7 +49392,7 @@ async function runMachineHelper(options = {}) {
|
|
|
48812
49392
|
const paths = options.configPaths ?? await findAgentRuntimeConfigPaths(env);
|
|
48813
49393
|
const live = [];
|
|
48814
49394
|
for (const path of paths) {
|
|
48815
|
-
if (!await
|
|
49395
|
+
if (!await stat10(path).then(() => true, () => false))
|
|
48816
49396
|
continue;
|
|
48817
49397
|
if (await isAgentStopped(path))
|
|
48818
49398
|
continue;
|
|
@@ -48832,7 +49412,7 @@ async function runMachineHelper(options = {}) {
|
|
|
48832
49412
|
const settle = await settleUpdateAttemptOnStart(layout);
|
|
48833
49413
|
if (settle.kind === "rolled-back") {
|
|
48834
49414
|
for (const path of await hostedRuntimes())
|
|
48835
|
-
await queueUpdateRollbackAlert(
|
|
49415
|
+
await queueUpdateRollbackAlert(dirname31(path), settle.record.releaseId);
|
|
48836
49416
|
console.error(`[helper] self-update ROLLED BACK: bundle ${describeIdentity(settle.record.to)} never confirmed healthy; restored ${settle.record.previousReleaseId ?? "previous release"}`);
|
|
48837
49417
|
return finish(await standDownForRollback());
|
|
48838
49418
|
}
|
|
@@ -48873,7 +49453,7 @@ async function runMachineHelper(options = {}) {
|
|
|
48873
49453
|
since: new Date(slot.since).toISOString()
|
|
48874
49454
|
}]))
|
|
48875
49455
|
};
|
|
48876
|
-
await mkdir29(
|
|
49456
|
+
await mkdir29(dirname31(path), { recursive: true, mode: 448 });
|
|
48877
49457
|
const staged = `${path}.${process.pid}.tmp`;
|
|
48878
49458
|
await writeFile22(staged, `${JSON.stringify(body, null, 2)}
|
|
48879
49459
|
`, { mode: 384 });
|
|
@@ -48966,6 +49546,7 @@ async function runMachineHelper(options = {}) {
|
|
|
48966
49546
|
for (const agent of hosted.values())
|
|
48967
49547
|
agent.lifecycle.resumeAfterFailedUpdate(() => agent.core.resumeServing());
|
|
48968
49548
|
}
|
|
49549
|
+
void sweepHostDisk();
|
|
48969
49550
|
};
|
|
48970
49551
|
let readyResolve;
|
|
48971
49552
|
const allEstablished = new Promise((resolveReady) => {
|
|
@@ -49020,7 +49601,7 @@ async function runMachineHelper(options = {}) {
|
|
|
49020
49601
|
const supervise = async (slot) => {
|
|
49021
49602
|
let failures = 0;
|
|
49022
49603
|
while (!controller.signal.aborted && !slot.controller.signal.aborted) {
|
|
49023
|
-
if (!await
|
|
49604
|
+
if (!await stat10(slot.configPath).then(() => true, () => false)) {
|
|
49024
49605
|
setState(slot, "removed", "runtime no longer on this machine");
|
|
49025
49606
|
break;
|
|
49026
49607
|
}
|
|
@@ -49030,7 +49611,7 @@ async function runMachineHelper(options = {}) {
|
|
|
49030
49611
|
reason = await runAgent(slot.configPath, host, slot.controller.signal);
|
|
49031
49612
|
} catch (error) {
|
|
49032
49613
|
console.error(`[helper] agent ${slot.agentId} failed:`, error);
|
|
49033
|
-
const failure = await settleDaemonStartFailure(
|
|
49614
|
+
const failure = await settleDaemonStartFailure(dirname31(slot.configPath), error).catch(() => ({ distressed: false }));
|
|
49034
49615
|
if (failure.distressed) {
|
|
49035
49616
|
console.error(`[helper] agent ${slot.agentId} failed to start ${failure.count} times; it stays stopped. operator record: ${failure.path}`);
|
|
49036
49617
|
reason = "distress";
|
|
@@ -49079,7 +49660,7 @@ async function runMachineHelper(options = {}) {
|
|
|
49079
49660
|
const runtime = await readRuntimeRecord(configPath).catch(() => void 0);
|
|
49080
49661
|
const slot = existing ?? {
|
|
49081
49662
|
configPath,
|
|
49082
|
-
agentId: runtime?.agent.publicKey ??
|
|
49663
|
+
agentId: runtime?.agent.publicKey ?? dirname31(configPath).split("/").at(-1),
|
|
49083
49664
|
controller: new AbortController(),
|
|
49084
49665
|
state: "starting",
|
|
49085
49666
|
status: "",
|
|
@@ -49119,6 +49700,8 @@ async function runMachineHelper(options = {}) {
|
|
|
49119
49700
|
allEstablished,
|
|
49120
49701
|
new Promise((resolveAbort) => controller.signal.addEventListener("abort", () => resolveAbort(), { once: true }))
|
|
49121
49702
|
]);
|
|
49703
|
+
if (!controller.signal.aborted)
|
|
49704
|
+
void sweepHostDisk();
|
|
49122
49705
|
if (!controller.signal.aborted)
|
|
49123
49706
|
await notifier.ready(`ready; ${statusLine()}`).catch((error) => console.error("[helper] ready notification failed:", error));
|
|
49124
49707
|
if (!controller.signal.aborted)
|
|
@@ -49185,7 +49768,7 @@ async function waitForPreviousHolder(configPath, signal) {
|
|
|
49185
49768
|
return;
|
|
49186
49769
|
if (!announced) {
|
|
49187
49770
|
announced = true;
|
|
49188
|
-
console.log(`[helper] waiting for process ${pid} to let go of ${
|
|
49771
|
+
console.log(`[helper] waiting for process ${pid} to let go of ${dirname31(configPath)}`);
|
|
49189
49772
|
}
|
|
49190
49773
|
const waited = Date.now() - startedAt;
|
|
49191
49774
|
if (waited >= PREVIOUS_HOLDER_WAIT_MS && !asked) {
|
|
@@ -49310,7 +49893,7 @@ async function main() {
|
|
|
49310
49893
|
const roomId = roomFlag >= 0 ? args[roomFlag + 1] : void 0;
|
|
49311
49894
|
if (!configPath || !roomId)
|
|
49312
49895
|
throw new Error("corner-read-token requires --config and --room");
|
|
49313
|
-
const activated = await activateDaemonTransport(
|
|
49896
|
+
const activated = await activateDaemonTransport(resolve48(configPath));
|
|
49314
49897
|
if (!activated)
|
|
49315
49898
|
throw new Error("corner-read-token requires monolith transport");
|
|
49316
49899
|
const credential = await activated.client.execute("getRoomGitHubToken", { roomId });
|
|
@@ -49365,7 +49948,7 @@ async function main() {
|
|
|
49365
49948
|
}
|
|
49366
49949
|
if (!configPath && !args.includes("--machine"))
|
|
49367
49950
|
throw new Error("daemon requires --machine, or --config <runtime.json> for one agent");
|
|
49368
|
-
const { reason, lifecycle } = await runMachineHelper(configPath ? { configPaths: [
|
|
49951
|
+
const { reason, lifecycle } = await runMachineHelper(configPath ? { configPaths: [resolve48(configPath)] } : {});
|
|
49369
49952
|
daemonLifecycle = lifecycle;
|
|
49370
49953
|
lifecycle.exit(reason);
|
|
49371
49954
|
return;
|
|
@@ -49388,7 +49971,7 @@ async function main() {
|
|
|
49388
49971
|
if (!agentPubkey)
|
|
49389
49972
|
throw new Error("stop requires --agent <pubkey>");
|
|
49390
49973
|
const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
|
|
49391
|
-
const configPath = configs.find((candidate) =>
|
|
49974
|
+
const configPath = configs.find((candidate) => dirname32(candidate).endsWith(agentPubkey));
|
|
49392
49975
|
if (!configPath)
|
|
49393
49976
|
throw new Error(`no stored runtime found for agent ${agentPubkey}`);
|
|
49394
49977
|
const runtime = await readRuntimeRecord(configPath);
|