pi-fabric 0.104.1 → 0.104.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/agents/manager.d.ts.map +1 -1
- package/dist/chunks/chunk-2Y24ML7H.js +115 -0
- package/dist/chunks/chunk-2Y24ML7H.js.map +7 -0
- package/dist/chunks/chunk-B2Y4364O.js +78 -0
- package/dist/chunks/chunk-B2Y4364O.js.map +7 -0
- package/dist/chunks/{chunk-PQW2ISQ3.js → chunk-Y5HBN75E.js} +27 -11
- package/dist/chunks/chunk-Y5HBN75E.js.map +7 -0
- package/dist/chunks/{chunk-TTNR3ULB.js → chunk-ZLWJ3T75.js} +2 -2
- package/dist/fabric-runtime-state.js +1 -1
- package/dist/index.js +7 -6
- package/dist/index.js.map +2 -2
- package/dist/jev-fabric/client.js +1 -1
- package/dist/jev-fabric/client.js.map +2 -2
- package/dist/jev-fabric/resolve.js +1 -1
- package/dist/jev-fabric/resolve.js.map +2 -2
- package/dist/residency/host.js +2 -2
- package/dist/residency/pi-entry.js +2 -2
- package/dist/ui/conversation-render.d.ts +2 -1
- package/dist/ui/conversation-render.d.ts.map +1 -1
- package/dist/ui/conversation-scrollbar.d.ts +1 -1
- package/dist/ui/conversation-scrollbar.d.ts.map +1 -1
- package/dist/ui/conversation-selection.d.ts +2 -2
- package/dist/ui/conversation-selection.d.ts.map +1 -1
- package/dist/ui/conversation.d.ts +1 -0
- package/dist/ui/conversation.d.ts.map +1 -1
- package/dist/ui/conversation.js +28 -14
- package/dist/ui/conversation.js.map +2 -2
- package/dist/ui/image-overlays.d.ts +16 -0
- package/dist/ui/image-overlays.d.ts.map +1 -0
- package/dist/ui/image-overlays.js +10 -0
- package/dist/ui/image-overlays.js.map +7 -0
- package/dist/ui/kitty-viewport.d.ts +24 -0
- package/dist/ui/kitty-viewport.d.ts.map +1 -0
- package/dist/ui/settings.d.ts.map +1 -1
- package/dist/ui/settings.js +7 -4
- package/dist/ui/settings.js.map +2 -2
- package/docs/agents.md +1 -1
- package/docs/background-tasks.md +1 -1
- package/docs/configuration.md +1 -1
- package/docs/kitty-images.md +89 -0
- package/docs/shell-composition.md +1 -1
- package/package.json +6 -5
- package/dist/chunks/chunk-PQW2ISQ3.js.map +0 -7
- /package/dist/chunks/{chunk-TTNR3ULB.js.map → chunk-ZLWJ3T75.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
3
|
<p>
|
|
4
|
-
<img src="https://raw.githubusercontent.com/
|
|
4
|
+
<img src="https://raw.githubusercontent.com/fabric-runtime/pi-fabric/main/media/opencollective/fabric-runtime/fa-avatar.png" alt="Pi Fabric logo" width="96" height="96">
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
7
|
# pi-fabric
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
_One program for tools, MCP, agents, workflows, actors, mesh, councils, and recursion._
|
|
12
12
|
|
|
13
13
|
<p>
|
|
14
|
-
<img src="https://raw.githubusercontent.com/
|
|
14
|
+
<img src="https://raw.githubusercontent.com/fabric-runtime/pi-fabric/main/media/banner.svg" alt="Animated banner: one checked TypeScript program weaving pi core tools, MCP servers, agents, and mesh into a single result" width="100%">
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
17
|
[](https://www.npmjs.com/package/pi-fabric)
|
|
18
18
|
[](https://arcprize.org/scorecards/d4c56c67-136b-4643-b648-62ae28fe2a54)
|
|
19
|
-
[](https://github.com/fabric-runtime/pi-fabric/actions/workflows/test.yml)
|
|
20
20
|
[](https://github.com/earendil-works/pi-coding-agent)
|
|
21
21
|
[](LICENSE)
|
|
22
22
|
[](https://opencollective.com/pi-fabric)
|
|
@@ -96,7 +96,7 @@ pi install npm:pi-fabric
|
|
|
96
96
|
From GitHub:
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
|
-
pi install git:github.com/
|
|
99
|
+
pi install git:github.com/fabric-runtime/pi-fabric
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
From a local checkout:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/agents/manager.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOzD,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EAEtB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,iBAAiB,CAAC;AAkBzB,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,mBAAmB,CAAC;AAU3B,OAAO,KAAK,EACV,yBAAyB,EACzB,0BAA0B,EAE1B,kBAAkB,EAClB,cAAc,EACd,eAAe,EAEf,cAAc,EACd,eAAe,EACf,cAAc,EAEd,gBAAgB,EAKjB,MAAM,YAAY,CAAC;AAapB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAqBpE,OAAO,EAGL,KAAK,6BAA6B,EACnC,MAAM,uBAAuB,CAAC;AAsB/B,eAAO,MAAM,uBAAuB,GAClC,qBAAqB,MAAM,EAC3B,qBAAqB,MAAM,KAC1B,MAYF,CAAC;AAEF,UAAU,+BAA+B;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,KAAK,gCAAgC,GAAG,CACtC,OAAO,EAAE,+BAA+B,KACrC,MAAM,GAAG,SAAS,CAAC;AAExB,8EAA8E;AAC9E,eAAO,MAAM,eAAe,GAAI,WAAW,MAAM,EAAE,eAAe,MAAM,KAAG,MAoB1E,CAAC;
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/agents/manager.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOzD,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EAEtB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,iBAAiB,CAAC;AAkBzB,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,mBAAmB,CAAC;AAU3B,OAAO,KAAK,EACV,yBAAyB,EACzB,0BAA0B,EAE1B,kBAAkB,EAClB,cAAc,EACd,eAAe,EAEf,cAAc,EACd,eAAe,EACf,cAAc,EAEd,gBAAgB,EAKjB,MAAM,YAAY,CAAC;AAapB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAqBpE,OAAO,EAGL,KAAK,6BAA6B,EACnC,MAAM,uBAAuB,CAAC;AAsB/B,eAAO,MAAM,uBAAuB,GAClC,qBAAqB,MAAM,EAC3B,qBAAqB,MAAM,KAC1B,MAYF,CAAC;AAEF,UAAU,+BAA+B;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,KAAK,gCAAgC,GAAG,CACtC,OAAO,EAAE,+BAA+B,KACrC,MAAM,GAAG,SAAS,CAAC;AAExB,8EAA8E;AAC9E,eAAO,MAAM,eAAe,GAAI,WAAW,MAAM,EAAE,eAAe,MAAM,KAAG,MAoB1E,CAAC;AA4SF,qBAAa,YAAY;;IAiErB,QAAQ,CAAC,GAAG,EAAE,MAAM;IACpB,QAAQ,CAAC,MAAM,EAAE,iBAAiB;gBADzB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,iBAAiB,EAClC,OAAO,GAAE;QACP,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,MAAM,CAAC,EAAE,MAAM,YAAY,CAAC;QAC5B,aAAa,CAAC,EAAE,MAAM,mBAAmB,CAAC;QAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,qBAAqB,CAAC;QAClC,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;QACxD,gBAAgB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;QACxC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,IAAI,CAAC;QAC7D,wFAAwF;QACxF,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC;QAC9F,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACvE,8BAA8B,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;QAC7G,0BAA0B,CAAC,EAAE,gCAAgC,CAAC;QAC9D,2BAA2B,CAAC,EAAE,MAAM,mBAAmB,EAAE,GAAG,SAAS,CAAC;QACtE,6EAA6E;QAC7E,cAAc,CAAC,EAAE,MAAM,oBAAoB,CAAC;QAC5C,gEAAgE;QAChE,SAAS,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;QACrC,oFAAoF;QACpF,eAAe,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;KACvC;IAsFR,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAK7C,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM;IAgBzC,yFAAyF;IACzF,aAAa,CACX,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,QAAQ,GAAG,YAAY,CAAC,GACjE,YAAY,GAAG,SAAS;IAuB3B,6FAA6F;IAC7F,oBAAoB,CAAC,SAAS,CAAC,EAAE,mBAAmB,GAAG,mBAAmB;IAQ1E,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC;IAsB/E,iFAAiF;IACjF,mBAAmB,CAAC,SAAS,CAAC,EAAE,oBAAoB,GAAG,oBAAoB;IAgmB3E;;;;OAIG;IACG,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAqE5C,iEAAiE;IAC3D,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU/B,GAAG,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IAK5E,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAiB/C,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAKhC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IA+D9B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,eAAe;IAgBpD,IAAI,IAAI,KAAK,CAAC,cAAc,GAAG,eAAe,CAAC;IAI/C,SAAS,IAAI,KAAK,CAAC,cAAc,GAAG,eAAe,CAAC;IA8BpD,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI5C,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIzC,YAAY,CAAC,OAAO,UAAQ,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAUzD,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA4BzC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,UAAQ,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAc9E,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,cAAc;IAkBnF,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,gBAAgB;IAIpE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,gBAAgB;IAyBvE,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,gBAAgB;IAKvE,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,gBAAgB;IAkBvE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,gBAAgB;IA8B5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAqyBvB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// src/ui/kitty-viewport.ts
|
|
2
|
+
import { getPngDimensions } from "@earendil-works/pi-tui";
|
|
3
|
+
var isKittyImageLine = (line) => line.includes("\x1B_G");
|
|
4
|
+
var EMPTY_IMAGE_ROWS = /* @__PURE__ */ new Set();
|
|
5
|
+
var MAX_CROP_CACHE_BYTES = 16 * 1024 * 1024;
|
|
6
|
+
var MAX_CACHED_CROPS = 2;
|
|
7
|
+
function header(line) {
|
|
8
|
+
const start = line.indexOf("\x1B_G");
|
|
9
|
+
if (start < 0) return void 0;
|
|
10
|
+
const end = line.indexOf(";", start);
|
|
11
|
+
if (end < 0) return void 0;
|
|
12
|
+
const controls = line.slice(start + 3, end).split(",");
|
|
13
|
+
const rows = Number(controls.find((control) => control.startsWith("r="))?.slice(2));
|
|
14
|
+
if (!Number.isSafeInteger(rows) || rows <= 0) return void 0;
|
|
15
|
+
return { start, end, controls, rows };
|
|
16
|
+
}
|
|
17
|
+
var KittyViewport = class {
|
|
18
|
+
source;
|
|
19
|
+
images = [];
|
|
20
|
+
crops = /* @__PURE__ */ new Map();
|
|
21
|
+
cropBytes = 0;
|
|
22
|
+
clear() {
|
|
23
|
+
this.source = void 0;
|
|
24
|
+
this.images = [];
|
|
25
|
+
this.crops.clear();
|
|
26
|
+
this.cropBytes = 0;
|
|
27
|
+
}
|
|
28
|
+
slice(source, start, end) {
|
|
29
|
+
if (source !== this.source) {
|
|
30
|
+
this.clear();
|
|
31
|
+
this.source = source;
|
|
32
|
+
for (let row = 0; row < source.length; row++) {
|
|
33
|
+
const image = header(source[row]);
|
|
34
|
+
if (!image) continue;
|
|
35
|
+
this.images.push({ ...image, row, line: source[row] });
|
|
36
|
+
row += image.rows - 1;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const lines = source.slice(start, end);
|
|
40
|
+
if (!lines.length || !this.images.length) return { lines, imageRows: EMPTY_IMAGE_ROWS };
|
|
41
|
+
let low = 0;
|
|
42
|
+
let high = this.images.length;
|
|
43
|
+
while (low < high) {
|
|
44
|
+
const middle = low + high >>> 1;
|
|
45
|
+
const image = this.images[middle];
|
|
46
|
+
if (image.row + image.rows <= start) low = middle + 1;
|
|
47
|
+
else high = middle;
|
|
48
|
+
}
|
|
49
|
+
let imageRows;
|
|
50
|
+
for (let index = low; index < this.images.length; index++) {
|
|
51
|
+
const image = this.images[index];
|
|
52
|
+
if (image.row >= start + lines.length) break;
|
|
53
|
+
const row = Math.max(0, image.row - start);
|
|
54
|
+
const hidden = Math.max(0, start - image.row);
|
|
55
|
+
const visible = Math.min(image.rows - hidden, lines.length - row);
|
|
56
|
+
const line = this.crop(image, hidden, visible);
|
|
57
|
+
lines[row] = line;
|
|
58
|
+
if (!line) continue;
|
|
59
|
+
imageRows ??= /* @__PURE__ */ new Set();
|
|
60
|
+
for (let i = row; i < row + visible; i++) imageRows.add(i);
|
|
61
|
+
}
|
|
62
|
+
return { lines, imageRows: imageRows ?? EMPTY_IMAGE_ROWS };
|
|
63
|
+
}
|
|
64
|
+
crop(image, hidden, visible) {
|
|
65
|
+
if (hidden === 0 && visible === image.rows) return image.line;
|
|
66
|
+
const cached = this.crops.get(image);
|
|
67
|
+
if (cached?.hidden === hidden && cached.visible === visible) return cached.line;
|
|
68
|
+
if (image.heightPx === void 0) image.heightPx = getPngDimensions(image.line.slice(image.end + 1, image.end + 33))?.heightPx ?? null;
|
|
69
|
+
if (!image.heightPx || !image.controls.includes("f=100") || !image.controls.includes("a=T")) return "";
|
|
70
|
+
const sourceY = Math.floor(image.heightPx * hidden / image.rows);
|
|
71
|
+
const sourceEnd = Math.ceil(image.heightPx * (hidden + visible) / image.rows);
|
|
72
|
+
const controls = image.controls.filter((control) => !/^[yhr]=/.test(control));
|
|
73
|
+
controls.push(`y=${sourceY}`, `h=${Math.max(1, sourceEnd - sourceY)}`, `r=${visible}`);
|
|
74
|
+
const line = `${image.line.slice(0, image.start)}\x1B_G${controls.join(",")};${image.line.slice(image.end + 1)}`;
|
|
75
|
+
if (cached) {
|
|
76
|
+
this.cropBytes -= cached.bytes;
|
|
77
|
+
this.crops.delete(image);
|
|
78
|
+
}
|
|
79
|
+
const bytes = line.length * 2;
|
|
80
|
+
if (bytes <= MAX_CROP_CACHE_BYTES) {
|
|
81
|
+
while (this.crops.size >= MAX_CACHED_CROPS || this.cropBytes + bytes > MAX_CROP_CACHE_BYTES) {
|
|
82
|
+
const oldest = this.crops.keys().next().value;
|
|
83
|
+
this.cropBytes -= this.crops.get(oldest).bytes;
|
|
84
|
+
this.crops.delete(oldest);
|
|
85
|
+
}
|
|
86
|
+
this.crops.set(image, { hidden, visible, line, bytes });
|
|
87
|
+
this.cropBytes += bytes;
|
|
88
|
+
}
|
|
89
|
+
return line;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
function hideKittyImages(lines, viewportHeight = lines.length) {
|
|
93
|
+
const start = Math.max(0, lines.length - viewportHeight);
|
|
94
|
+
let result;
|
|
95
|
+
const hide = (row) => {
|
|
96
|
+
result ??= lines.slice();
|
|
97
|
+
result[row] = "";
|
|
98
|
+
};
|
|
99
|
+
for (let row = start; row < lines.length; row++) if (isKittyImageLine(lines[row])) hide(row);
|
|
100
|
+
for (let row = start - 1; row >= 0; row--) {
|
|
101
|
+
const line = lines[row];
|
|
102
|
+
if (line === "") continue;
|
|
103
|
+
const image = header(line);
|
|
104
|
+
if (image && row + image.rows > start) hide(row);
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
return result ?? lines;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export {
|
|
111
|
+
isKittyImageLine,
|
|
112
|
+
KittyViewport,
|
|
113
|
+
hideKittyImages
|
|
114
|
+
};
|
|
115
|
+
//# sourceMappingURL=chunk-2Y24ML7H.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/ui/kitty-viewport.ts"],
|
|
4
|
+
"sourcesContent": ["import { getPngDimensions } from \"@earendil-works/pi-tui\";\n\nexport const isKittyImageLine = (line: string): boolean => line.includes(\"\\x1b_G\");\nconst EMPTY_IMAGE_ROWS: ReadonlySet<number> = new Set<number>();\nconst MAX_CROP_CACHE_BYTES = 16 * 1024 * 1024;\nconst MAX_CACHED_CROPS = 2; // Only the top and bottom image can need cropping.\n\nfunction header(line: string) {\n const start = line.indexOf(\"\\x1b_G\");\n if (start < 0) return undefined;\n const end = line.indexOf(\";\", start);\n if (end < 0) return undefined;\n const controls = line.slice(start + 3, end).split(\",\");\n const rows = Number(controls.find((control) => control.startsWith(\"r=\"))?.slice(2));\n if (!Number.isSafeInteger(rows) || rows <= 0) return undefined;\n return { start, end, controls, rows };\n}\n\ntype ImageBlock = NonNullable<ReturnType<typeof header>> & { row: number; line: string; heightPx?: number | null };\ntype CachedCrop = { hidden: number; visible: number; line: string; bytes: number };\nexport interface KittyViewportFrame {\n lines: string[];\n /** Reserved rows must stay empty so Pi pre-clears them before placing pixels. */\n imageRows: ReadonlySet<number>;\n}\n\n/** Index immutable retained frames once. Scrolling then touches only the viewport\n * and its intersecting images, never a long run of offscreen blank reservations.\n * The two-entry, byte-bounded crop cache avoids rebuilding megabyte transmissions\n * on unchanged frames. No image data is decoded, uploaded or deleted here. */\nexport class KittyViewport {\n private source: readonly string[] | undefined;\n private images: ImageBlock[] = [];\n private readonly crops = new Map<ImageBlock, CachedCrop>();\n private cropBytes = 0;\n\n clear(): void {\n this.source = undefined;\n this.images = [];\n this.crops.clear();\n this.cropBytes = 0;\n }\n\n slice(source: readonly string[], start: number, end: number): KittyViewportFrame {\n if (source !== this.source) {\n this.clear();\n this.source = source;\n for (let row = 0; row < source.length; row++) {\n const image = header(source[row]!);\n if (!image) continue;\n this.images.push({ ...image, row, line: source[row]! });\n row += image.rows - 1;\n }\n }\n const lines = source.slice(start, end);\n if (!lines.length || !this.images.length) return { lines, imageRows: EMPTY_IMAGE_ROWS };\n let low = 0;\n let high = this.images.length;\n while (low < high) {\n const middle = (low + high) >>> 1;\n const image = this.images[middle]!;\n if (image.row + image.rows <= start) low = middle + 1;\n else high = middle;\n }\n let imageRows: Set<number> | undefined;\n for (let index = low; index < this.images.length; index++) {\n const image = this.images[index]!;\n if (image.row >= start + lines.length) break;\n const row = Math.max(0, image.row - start);\n const hidden = Math.max(0, start - image.row);\n const visible = Math.min(image.rows - hidden, lines.length - row);\n const line = this.crop(image, hidden, visible);\n lines[row] = line;\n if (!line) continue;\n imageRows ??= new Set<number>();\n for (let i = row; i < row + visible; i++) imageRows.add(i);\n }\n return { lines, imageRows: imageRows ?? EMPTY_IMAGE_ROWS };\n }\n\n private crop(image: ImageBlock, hidden: number, visible: number): string {\n if (hidden === 0 && visible === image.rows) return image.line;\n const cached = this.crops.get(image);\n if (cached?.hidden === hidden && cached.visible === visible) return cached.line;\n // Pi's f=100 transmission starts with a PNG header. Read only its first 32\n // base64 characters, not a second Pi installation's image metadata registry.\n if (image.heightPx === undefined) image.heightPx = getPngDimensions(image.line.slice(image.end + 1, image.end + 33))?.heightPx ?? null;\n if (!image.heightPx || !image.controls.includes(\"f=100\") || !image.controls.includes(\"a=T\")) return \"\";\n const sourceY = Math.floor(image.heightPx * hidden / image.rows);\n const sourceEnd = Math.ceil(image.heightPx * (hidden + visible) / image.rows);\n const controls = image.controls.filter((control) => !/^[yhr]=/.test(control));\n controls.push(`y=${sourceY}`, `h=${Math.max(1, sourceEnd - sourceY)}`, `r=${visible}`);\n const line = `${image.line.slice(0, image.start)}\\x1b_G${controls.join(\",\")};${image.line.slice(image.end + 1)}`;\n if (cached) {\n this.cropBytes -= cached.bytes;\n this.crops.delete(image);\n }\n const bytes = line.length * 2; // conservative UTF-16 storage budget\n if (bytes <= MAX_CROP_CACHE_BYTES) {\n while (this.crops.size >= MAX_CACHED_CROPS || this.cropBytes + bytes > MAX_CROP_CACHE_BYTES) {\n const oldest = this.crops.keys().next().value!;\n this.cropBytes -= this.crops.get(oldest)!.bytes;\n this.crops.delete(oldest);\n }\n this.crops.set(image, { hidden, visible, line, bytes });\n this.cropBytes += bytes;\n }\n return line;\n }\n}\n\n/** Hide only background placements that can reach the visible terminal. Leave\n * offscreen scrollback intact; removing it would force unnecessary reuploads on\n * close. Return text-only frames unchanged instead of copying retained history. */\nexport function hideKittyImages(lines: string[], viewportHeight = lines.length): string[] {\n const start = Math.max(0, lines.length - viewportHeight);\n let result: string[] | undefined;\n const hide = (row: number): void => { result ??= lines.slice(); result[row] = \"\"; };\n for (let row = start; row < lines.length; row++) if (isKittyImageLine(lines[row]!)) hide(row);\n // An image anchored above the viewport may extend into it through empty rows.\n for (let row = start - 1; row >= 0; row--) {\n const line = lines[row]!;\n if (line === \"\") continue;\n const image = header(line);\n if (image && row + image.rows > start) hide(row);\n break;\n }\n return result ?? lines;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hideKittyImages
|
|
3
|
+
} from "./chunk-2Y24ML7H.js";
|
|
4
|
+
|
|
5
|
+
// src/ui/image-overlays.ts
|
|
6
|
+
var leases = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
function retainImageSafeOverlays(tui) {
|
|
8
|
+
let prototype = Object.getPrototypeOf(tui);
|
|
9
|
+
while (prototype && !Object.hasOwn(prototype, "compositeOverlays")) prototype = Object.getPrototypeOf(prototype);
|
|
10
|
+
if (!prototype) return () => {
|
|
11
|
+
};
|
|
12
|
+
const host = prototype;
|
|
13
|
+
if (typeof host.compositeOverlays !== "function" || typeof host.compositeLineAt !== "function" || typeof host.isOverlayVisible !== "function") return () => {
|
|
14
|
+
};
|
|
15
|
+
let lease = leases.get(prototype);
|
|
16
|
+
if (!lease) {
|
|
17
|
+
const original = host.compositeOverlays;
|
|
18
|
+
const originalLine = host.compositeLineAt;
|
|
19
|
+
const composite = function(lines, width, height) {
|
|
20
|
+
const visible = this.overlayStack.filter((entry) => this.isOverlayVisible(entry)).sort((a, b) => a.focusOrder - b.focusOrder);
|
|
21
|
+
if (!visible.length) return original.call(this, lines, width, height);
|
|
22
|
+
const restore = [];
|
|
23
|
+
try {
|
|
24
|
+
for (const entry of visible.slice(0, -1)) {
|
|
25
|
+
const component = entry.component;
|
|
26
|
+
entry.component = {
|
|
27
|
+
render: (columns) => hideKittyImages(component.render(columns)),
|
|
28
|
+
invalidate: () => component.invalidate()
|
|
29
|
+
};
|
|
30
|
+
restore.push(() => {
|
|
31
|
+
entry.component = component;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return original.call(this, hideKittyImages(lines, height), width, height);
|
|
35
|
+
} finally {
|
|
36
|
+
for (const undo of restore.reverse()) undo();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const compositeLine = function(base, overlay, column, width, totalWidth) {
|
|
40
|
+
if (column === 0 && width === totalWidth) return overlay;
|
|
41
|
+
return originalLine.call(this, base, overlay, column, width, totalWidth);
|
|
42
|
+
};
|
|
43
|
+
host.compositeOverlays = composite;
|
|
44
|
+
host.compositeLineAt = compositeLine;
|
|
45
|
+
lease = { count: 0, restore: () => {
|
|
46
|
+
if (host.compositeOverlays === composite) host.compositeOverlays = original;
|
|
47
|
+
if (host.compositeLineAt === compositeLine) host.compositeLineAt = originalLine;
|
|
48
|
+
} };
|
|
49
|
+
leases.set(prototype, lease);
|
|
50
|
+
}
|
|
51
|
+
lease.count++;
|
|
52
|
+
let released = false;
|
|
53
|
+
return () => {
|
|
54
|
+
if (released) return;
|
|
55
|
+
released = true;
|
|
56
|
+
if (--lease.count === 0) {
|
|
57
|
+
lease.restore();
|
|
58
|
+
leases.delete(prototype);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async function imageSafeCustom(ui, factory, options) {
|
|
63
|
+
let release;
|
|
64
|
+
try {
|
|
65
|
+
return await ui.custom((tui, theme, keys, done) => {
|
|
66
|
+
release = retainImageSafeOverlays(tui);
|
|
67
|
+
return factory(tui, theme, keys, done);
|
|
68
|
+
}, options);
|
|
69
|
+
} finally {
|
|
70
|
+
release?.();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export {
|
|
75
|
+
retainImageSafeOverlays,
|
|
76
|
+
imageSafeCustom
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=chunk-B2Y4364O.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/ui/image-overlays.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ExtensionContext, KeybindingsManager, Theme } from \"@earendil-works/pi-coding-agent\";\nimport type { Component, TUI } from \"@earendil-works/pi-tui\";\nimport { hideKittyImages } from \"./kitty-viewport.js\";\n\ntype OverlayEntry = { component: Component; focusOrder: number };\ntype Compositor = {\n overlayStack: OverlayEntry[];\n isOverlayVisible(entry: OverlayEntry): boolean;\n compositeOverlays(lines: string[], width: number, height: number): string[];\n compositeLineAt(base: string, overlay: string, column: number, width: number, totalWidth: number): string;\n};\nconst leases = new WeakMap<object, { count: number; restore(): void }>();\n\n/** Pi 1.0's compositor returns a base image instead of the overlay, and pads\n * full-width image reservations into text. There is no public compositor hook.\n * Lease only these two host prototype methods while a Fabric overlay is open;\n * native layout, focus, visibility, image deletion and upload caches still own\n * the frame. Resolve through the supplied live proxy, never import another TUI.\n * Background layers deliberately hide images rather than trying to z-order\n * terminal graphics against text. The native diff restores them on close. */\nexport function retainImageSafeOverlays(tui: TUI): () => void {\n let prototype = Object.getPrototypeOf(tui) as object | null;\n while (prototype && !Object.hasOwn(prototype, \"compositeOverlays\")) prototype = Object.getPrototypeOf(prototype) as object | null;\n if (!prototype) return () => {};\n const host = prototype as Compositor;\n if (typeof host.compositeOverlays !== \"function\" || typeof host.compositeLineAt !== \"function\" ||\n typeof host.isOverlayVisible !== \"function\") return () => {};\n let lease = leases.get(prototype);\n if (!lease) {\n const original = host.compositeOverlays;\n const originalLine = host.compositeLineAt;\n const composite: Compositor[\"compositeOverlays\"] = function (this: Compositor, lines, width, height) {\n const visible = this.overlayStack.filter((entry) => this.isOverlayVisible(entry))\n .sort((a, b) => a.focusOrder - b.focusOrder);\n if (!visible.length) return original.call(this, lines, width, height);\n const restore: (() => void)[] = [];\n try {\n for (const entry of visible.slice(0, -1)) {\n const component = entry.component;\n // Wrap the stack slot, not the component: third-party components may\n // be frozen or use private fields, and must keep their render receiver.\n entry.component = {\n render: (columns) => hideKittyImages(component.render(columns)),\n invalidate: () => component.invalidate(),\n };\n restore.push(() => { entry.component = component; });\n }\n return original.call(this, hideKittyImages(lines, height), width, height);\n } finally {\n for (const undo of restore.reverse()) undo();\n }\n };\n const compositeLine: Compositor[\"compositeLineAt\"] = function (this: Compositor, base, overlay, column, width, totalWidth) {\n // Avoid padding image reservations or passing control payloads through\n // text slicing. A full-width overlay replaces the entire terminal row.\n if (column === 0 && width === totalWidth) return overlay;\n return originalLine.call(this, base, overlay, column, width, totalWidth);\n };\n host.compositeOverlays = composite;\n host.compositeLineAt = compositeLine;\n lease = { count: 0, restore: () => {\n if (host.compositeOverlays === composite) host.compositeOverlays = original;\n if (host.compositeLineAt === compositeLine) host.compositeLineAt = originalLine;\n } };\n leases.set(prototype, lease);\n }\n lease.count++;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n if (--lease.count === 0) {\n lease.restore();\n leases.delete(prototype);\n }\n };\n}\n\ntype CustomComponent = Component & { dispose?(): void };\nexport async function imageSafeCustom<T>(\n ui: ExtensionContext[\"ui\"],\n factory: (tui: TUI, theme: Theme, keys: KeybindingsManager, done: (result: T) => void) => CustomComponent | Promise<CustomComponent>,\n options?: Parameters<ExtensionContext[\"ui\"][\"custom\"]>[1],\n): Promise<T> {\n let release: (() => void) | undefined;\n try {\n return await ui.custom<T>((tui, theme, keys, done) => {\n release = retainImageSafeOverlays(tui);\n return factory(tui, theme, keys, done);\n }, options);\n } finally {\n release?.();\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AAWA,IAAM,SAAS,oBAAI,QAAoD;AAShE,SAAS,wBAAwB,KAAsB;AAC5D,MAAI,YAAY,OAAO,eAAe,GAAG;AACzC,SAAO,aAAa,CAAC,OAAO,OAAO,WAAW,mBAAmB,EAAG,aAAY,OAAO,eAAe,SAAS;AAC/G,MAAI,CAAC,UAAW,QAAO,MAAM;AAAA,EAAC;AAC9B,QAAM,OAAO;AACb,MAAI,OAAO,KAAK,sBAAsB,cAAc,OAAO,KAAK,oBAAoB,cAClF,OAAO,KAAK,qBAAqB,WAAY,QAAO,MAAM;AAAA,EAAC;AAC7D,MAAI,QAAQ,OAAO,IAAI,SAAS;AAChC,MAAI,CAAC,OAAO;AACV,UAAM,WAAW,KAAK;AACtB,UAAM,eAAe,KAAK;AAC1B,UAAM,YAA6C,SAA4B,OAAO,OAAO,QAAQ;AACnG,YAAM,UAAU,KAAK,aAAa,OAAO,CAAC,UAAU,KAAK,iBAAiB,KAAK,CAAC,EAC7E,KAAK,CAAC,GAAG,MAAM,EAAE,aAAa,EAAE,UAAU;AAC7C,UAAI,CAAC,QAAQ,OAAQ,QAAO,SAAS,KAAK,MAAM,OAAO,OAAO,MAAM;AACpE,YAAM,UAA0B,CAAC;AACjC,UAAI;AACF,mBAAW,SAAS,QAAQ,MAAM,GAAG,EAAE,GAAG;AACxC,gBAAM,YAAY,MAAM;AAGxB,gBAAM,YAAY;AAAA,YAChB,QAAQ,CAAC,YAAY,gBAAgB,UAAU,OAAO,OAAO,CAAC;AAAA,YAC9D,YAAY,MAAM,UAAU,WAAW;AAAA,UACzC;AACA,kBAAQ,KAAK,MAAM;AAAE,kBAAM,YAAY;AAAA,UAAW,CAAC;AAAA,QACrD;AACA,eAAO,SAAS,KAAK,MAAM,gBAAgB,OAAO,MAAM,GAAG,OAAO,MAAM;AAAA,MAC1E,UAAE;AACA,mBAAW,QAAQ,QAAQ,QAAQ,EAAG,MAAK;AAAA,MAC7C;AAAA,IACF;AACA,UAAM,gBAA+C,SAA4B,MAAM,SAAS,QAAQ,OAAO,YAAY;AAGzH,UAAI,WAAW,KAAK,UAAU,WAAY,QAAO;AACjD,aAAO,aAAa,KAAK,MAAM,MAAM,SAAS,QAAQ,OAAO,UAAU;AAAA,IACzE;AACA,SAAK,oBAAoB;AACzB,SAAK,kBAAkB;AACvB,YAAQ,EAAE,OAAO,GAAG,SAAS,MAAM;AACjC,UAAI,KAAK,sBAAsB,UAAW,MAAK,oBAAoB;AACnE,UAAI,KAAK,oBAAoB,cAAe,MAAK,kBAAkB;AAAA,IACrE,EAAE;AACF,WAAO,IAAI,WAAW,KAAK;AAAA,EAC7B;AACA,QAAM;AACN,MAAI,WAAW;AACf,SAAO,MAAM;AACX,QAAI,SAAU;AACd,eAAW;AACX,QAAI,EAAE,MAAM,UAAU,GAAG;AACvB,YAAM,QAAQ;AACd,aAAO,OAAO,SAAS;AAAA,IACzB;AAAA,EACF;AACF;AAGA,eAAsB,gBACpB,IACA,SACA,SACY;AACZ,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,GAAG,OAAU,CAAC,KAAK,OAAO,MAAM,SAAS;AACpD,gBAAU,wBAAwB,GAAG;AACrC,aAAO,QAAQ,KAAK,OAAO,MAAM,IAAI;AAAA,IACvC,GAAG,OAAO;AAAA,EACZ,UAAE;AACA,cAAU;AAAA,EACZ;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -2006,6 +2006,21 @@ var compactUiRecord = (record) => {
|
|
|
2006
2006
|
...nestedAgents && nestedAgents.length > 0 ? { nestedAgents: nestedAgents.map((nested) => compactUiRecord(nested)) } : {}
|
|
2007
2007
|
};
|
|
2008
2008
|
};
|
|
2009
|
+
var reconcileNestedAgents = (records, owner) => records.map((record) => {
|
|
2010
|
+
let next = record;
|
|
2011
|
+
if (terminalStatuses.has(owner.status) && !terminalStatuses.has(record.status) && record.residency !== "durable") {
|
|
2012
|
+
const { currentTool: _currentTool, blockedOn: _blockedOn, ...rest } = record;
|
|
2013
|
+
const finishedAt = owner.finishedAt ?? owner.updatedAt;
|
|
2014
|
+
next = {
|
|
2015
|
+
...rest,
|
|
2016
|
+
status: "failed",
|
|
2017
|
+
error: `Nested agent owner ${owner.id} finished (${owner.status}) before a terminal result was retained`,
|
|
2018
|
+
finishedAt,
|
|
2019
|
+
updatedAt: Math.max(record.updatedAt, finishedAt)
|
|
2020
|
+
};
|
|
2021
|
+
}
|
|
2022
|
+
return next.nestedAgents ? { ...next, nestedAgents: reconcileNestedAgents(next.nestedAgents, next) } : next;
|
|
2023
|
+
});
|
|
2009
2024
|
var readNestedAgents = (runDirectory, depth = 0) => {
|
|
2010
2025
|
if (depth >= 8) return [];
|
|
2011
2026
|
const nestedRoot = path12.join(runDirectory, "nested");
|
|
@@ -2087,6 +2102,7 @@ var AgentManager = class {
|
|
|
2087
2102
|
this.#semaphore = new AgentAdmission(config.maxConcurrent, Infinity, config.maxDepth);
|
|
2088
2103
|
this.#managedTempRoot = options.runRoot === void 0 && process.env.PI_FABRIC_RUN_ROOT === void 0;
|
|
2089
2104
|
this.#runRoot = options.runRoot ?? process.env.PI_FABRIC_RUN_ROOT ?? fs11.mkdtempSync(path12.join(os3.tmpdir(), "pi-fabric-runs-"));
|
|
2105
|
+
this.#parentOwnedRunRoot = options.runRoot === void 0 && this.#parentLineage?.worker === true && this.#parentLineage.depth > 0 && path12.basename(this.#runRoot) === "nested" && path12.basename(path12.dirname(this.#runRoot)) === this.#parentLineage.runId;
|
|
2090
2106
|
this.#retention = options.retention ?? DEFAULT_FABRIC_CONFIG.retention;
|
|
2091
2107
|
this.#workerPath = options.workerPath ?? fileURLToPath(new URL("../worker.js", import.meta.url));
|
|
2092
2108
|
this.#fabricExtensionPath = options.fabricExtensionPath ?? fileURLToPath(new URL("../index.js", import.meta.url));
|
|
@@ -2134,6 +2150,7 @@ var AgentManager = class {
|
|
|
2134
2150
|
#worktrees = new WorktreeManager();
|
|
2135
2151
|
#runRoot;
|
|
2136
2152
|
#managedTempRoot;
|
|
2153
|
+
#parentOwnedRunRoot;
|
|
2137
2154
|
#retention;
|
|
2138
2155
|
#workerPath;
|
|
2139
2156
|
#fabricExtensionPath;
|
|
@@ -3132,7 +3149,7 @@ var AgentManager = class {
|
|
|
3132
3149
|
this.#unregisteredTransports.clear();
|
|
3133
3150
|
const storageSafe = !this.#managedTempRoot || canRemoveManagedRunRoot(this.#runRoot);
|
|
3134
3151
|
if (!this.config.retainRuns) {
|
|
3135
|
-
if (storageSafe) {
|
|
3152
|
+
if (storageSafe && !this.#parentOwnedRunRoot) {
|
|
3136
3153
|
await removeTree(this.#runRoot).catch(() => void 0);
|
|
3137
3154
|
}
|
|
3138
3155
|
} else if (this.#managedTempRoot) {
|
|
@@ -3431,6 +3448,8 @@ var AgentManager = class {
|
|
|
3431
3448
|
#settle(managed, result) {
|
|
3432
3449
|
if (managed.settled) return;
|
|
3433
3450
|
if (managed.worktreeResult) result.worktreeResult = managed.worktreeResult;
|
|
3451
|
+
const nested = this.#nestedAgents(managed, true);
|
|
3452
|
+
if (nested.length > 0) result.nestedAgents = reconcileNestedAgents(nested, result);
|
|
3434
3453
|
this.#drainLifecycle(managed);
|
|
3435
3454
|
if (!beginAgentSettlement(managed)) return;
|
|
3436
3455
|
managed.questions?.abort(new Error("Agent run settled"));
|
|
@@ -3447,10 +3466,8 @@ var AgentManager = class {
|
|
|
3447
3466
|
const compactResult = compactUiRecord(result);
|
|
3448
3467
|
managed.latestRecord = compactResult;
|
|
3449
3468
|
managed.latestUiRecord = compactResult;
|
|
3450
|
-
if (
|
|
3451
|
-
managed.nestedSnapshot =
|
|
3452
|
-
(record) => compactUiRecord(record)
|
|
3453
|
-
);
|
|
3469
|
+
if (result.nestedAgents) {
|
|
3470
|
+
managed.nestedSnapshot = result.nestedAgents.map((record) => compactUiRecord(record));
|
|
3454
3471
|
}
|
|
3455
3472
|
this.#pruneRetainedUiRecords();
|
|
3456
3473
|
this.#invalidateUiList();
|
|
@@ -3712,9 +3729,8 @@ var AgentManager = class {
|
|
|
3712
3729
|
...managed.worktree ? { worktree: managed.worktree } : {}
|
|
3713
3730
|
};
|
|
3714
3731
|
}
|
|
3715
|
-
//
|
|
3716
|
-
//
|
|
3717
|
-
// in the parent run until that parent is explicitly cleaned up.
|
|
3732
|
+
// Retain a bounded tree even when legacy workers removed their nested run
|
|
3733
|
+
// directories. Terminal-owner reconciliation prevents cached active ghosts.
|
|
3718
3734
|
#nestedAgents(managed, force = false) {
|
|
3719
3735
|
const now = Date.now();
|
|
3720
3736
|
const needsInitialDiscovery = managed.nestedSnapshot === void 0 && fs11.existsSync(path12.join(managed.runDirectory, "nested"));
|
|
@@ -3730,10 +3746,10 @@ var AgentManager = class {
|
|
|
3730
3746
|
return managed.nestedSnapshot ? structuredClone(managed.nestedSnapshot) : [];
|
|
3731
3747
|
}
|
|
3732
3748
|
#withTransportMetadata(record, managed) {
|
|
3733
|
-
const nestedAgents = this.#nestedAgents(
|
|
3749
|
+
const nestedAgents = reconcileNestedAgents(this.#nestedAgents(
|
|
3734
3750
|
managed,
|
|
3735
3751
|
terminalStatuses.has(record.status) && !managed.settled
|
|
3736
|
-
);
|
|
3752
|
+
), record);
|
|
3737
3753
|
const budget = this.#budgetSummary();
|
|
3738
3754
|
const { logFile: _logFile, nestedAgents: _nestedAgents, ...safeRecord } = record;
|
|
3739
3755
|
const model = record.model ?? managed.model;
|
|
@@ -7747,4 +7763,4 @@ export {
|
|
|
7747
7763
|
agentParticipantRecords,
|
|
7748
7764
|
actorParticipantRecord
|
|
7749
7765
|
};
|
|
7750
|
-
//# sourceMappingURL=chunk-
|
|
7766
|
+
//# sourceMappingURL=chunk-Y5HBN75E.js.map
|