@astralyn/pi 0.84.11 → 0.84.13
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/CHANGELOG.md +31 -0
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +2 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/core/agent-session.d.ts +62 -8
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +395 -78
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +4 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +5 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +19 -5
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +44 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +18 -10
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +4 -2
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +8 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +17 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +5 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/extensions/background/actions.d.ts +21 -0
- package/dist/extensions/background/actions.d.ts.map +1 -0
- package/dist/extensions/background/actions.js +264 -0
- package/dist/extensions/background/actions.js.map +1 -0
- package/dist/extensions/background/constants.d.ts +24 -0
- package/dist/extensions/background/constants.d.ts.map +1 -0
- package/dist/extensions/background/constants.js +24 -0
- package/dist/extensions/background/constants.js.map +1 -0
- package/dist/extensions/background/index.d.ts +6 -115
- package/dist/extensions/background/index.d.ts.map +1 -1
- package/dist/extensions/background/index.js +38 -509
- package/dist/extensions/background/index.js.map +1 -1
- package/dist/extensions/background/manager.d.ts +2 -1
- package/dist/extensions/background/manager.d.ts.map +1 -1
- package/dist/extensions/background/manager.js +8 -10
- package/dist/extensions/background/manager.js.map +1 -1
- package/dist/extensions/background/notify.d.ts +16 -0
- package/dist/extensions/background/notify.d.ts.map +1 -0
- package/dist/extensions/background/notify.js +114 -0
- package/dist/extensions/background/notify.js.map +1 -0
- package/dist/extensions/background/output-file.d.ts +58 -0
- package/dist/extensions/background/output-file.d.ts.map +1 -0
- package/dist/extensions/background/output-file.js +122 -0
- package/dist/extensions/background/output-file.js.map +1 -0
- package/dist/extensions/background/registry.d.ts +40 -72
- package/dist/extensions/background/registry.d.ts.map +1 -1
- package/dist/extensions/background/registry.js +71 -184
- package/dist/extensions/background/registry.js.map +1 -1
- package/dist/extensions/background/render.d.ts +3 -10
- package/dist/extensions/background/render.d.ts.map +1 -1
- package/dist/extensions/background/render.js +20 -60
- package/dist/extensions/background/render.js.map +1 -1
- package/dist/extensions/background/schema.d.ts +34 -0
- package/dist/extensions/background/schema.d.ts.map +1 -0
- package/dist/extensions/background/schema.js +89 -0
- package/dist/extensions/background/schema.js.map +1 -0
- package/dist/extensions/background/task-view.d.ts +48 -0
- package/dist/extensions/background/task-view.d.ts.map +1 -0
- package/dist/extensions/background/task-view.js +90 -0
- package/dist/extensions/background/task-view.js.map +1 -0
- package/dist/extensions/background/text.d.ts +15 -0
- package/dist/extensions/background/text.d.ts.map +1 -0
- package/dist/extensions/background/text.js +31 -0
- package/dist/extensions/background/text.js.map +1 -0
- package/dist/extensions/background/types.d.ts +74 -0
- package/dist/extensions/background/types.d.ts.map +1 -0
- package/dist/extensions/background/types.js +17 -0
- package/dist/extensions/background/types.js.map +1 -0
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +2 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/llama/client.d.ts +6 -0
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +7 -0
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts +3 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +27 -6
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/subagent/activity.d.ts +5 -0
- package/dist/extensions/subagent/activity.d.ts.map +1 -1
- package/dist/extensions/subagent/activity.js +5 -0
- package/dist/extensions/subagent/activity.js.map +1 -1
- package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
- package/dist/extensions/subagent/agents-command.js +6 -391
- package/dist/extensions/subagent/agents-command.js.map +1 -1
- package/dist/extensions/subagent/constants.d.ts.map +1 -1
- package/dist/extensions/subagent/constants.js +1 -0
- package/dist/extensions/subagent/constants.js.map +1 -1
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +15 -1
- package/dist/extensions/subagent/render.js.map +1 -1
- package/dist/extensions/subagent/resolve.d.ts.map +1 -1
- package/dist/extensions/subagent/resolve.js +2 -4
- package/dist/extensions/subagent/resolve.js.map +1 -1
- package/dist/extensions/subagent/runner.d.ts +1 -1
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +8 -8
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/sdk-runner.d.ts +11 -0
- package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
- package/dist/extensions/subagent/sdk-runner.js +90 -79
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/state.d.ts.map +1 -1
- package/dist/extensions/subagent/state.js +145 -126
- package/dist/extensions/subagent/state.js.map +1 -1
- package/dist/extensions/subagent/text.d.ts.map +1 -1
- package/dist/extensions/subagent/text.js +4 -0
- package/dist/extensions/subagent/text.js.map +1 -1
- package/dist/extensions/subagent/ui/agents-dialog.d.ts +4 -0
- package/dist/extensions/subagent/ui/agents-dialog.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/agents-dialog.js +84 -0
- package/dist/extensions/subagent/ui/agents-dialog.js.map +1 -0
- package/dist/extensions/subagent/ui/choice-menu.d.ts +39 -0
- package/dist/extensions/subagent/ui/choice-menu.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/choice-menu.js +93 -0
- package/dist/extensions/subagent/ui/choice-menu.js.map +1 -0
- package/dist/extensions/subagent/ui/model-picker.d.ts +47 -0
- package/dist/extensions/subagent/ui/model-picker.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/model-picker.js +142 -0
- package/dist/extensions/subagent/ui/model-picker.js.map +1 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.d.ts +41 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.js +98 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.js.map +1 -0
- package/dist/extensions/web-search/auth.d.ts +12 -0
- package/dist/extensions/web-search/auth.d.ts.map +1 -0
- package/dist/extensions/web-search/auth.js +90 -0
- package/dist/extensions/web-search/auth.js.map +1 -0
- package/dist/extensions/web-search/constants.d.ts +13 -0
- package/dist/extensions/web-search/constants.d.ts.map +1 -0
- package/dist/extensions/web-search/constants.js +27 -0
- package/dist/extensions/web-search/constants.js.map +1 -0
- package/dist/extensions/web-search/fusion.d.ts +36 -0
- package/dist/extensions/web-search/fusion.d.ts.map +1 -0
- package/dist/extensions/web-search/fusion.js +272 -0
- package/dist/extensions/web-search/fusion.js.map +1 -0
- package/dist/extensions/web-search/index.d.ts +6 -0
- package/dist/extensions/web-search/index.d.ts.map +1 -0
- package/dist/extensions/web-search/index.js +70 -0
- package/dist/extensions/web-search/index.js.map +1 -0
- package/dist/extensions/web-search/providers/deepseek.d.ts +15 -0
- package/dist/extensions/web-search/providers/deepseek.d.ts.map +1 -0
- package/dist/extensions/web-search/providers/deepseek.js +63 -0
- package/dist/extensions/web-search/providers/deepseek.js.map +1 -0
- package/dist/extensions/web-search/providers/http.d.ts +9 -0
- package/dist/extensions/web-search/providers/http.d.ts.map +1 -0
- package/dist/extensions/web-search/providers/http.js +25 -0
- package/dist/extensions/web-search/providers/http.js.map +1 -0
- package/dist/extensions/web-search/providers/minimax.d.ts +14 -0
- package/dist/extensions/web-search/providers/minimax.d.ts.map +1 -0
- package/dist/extensions/web-search/providers/minimax.js +69 -0
- package/dist/extensions/web-search/providers/minimax.js.map +1 -0
- package/dist/extensions/web-search/render.d.ts +11 -0
- package/dist/extensions/web-search/render.d.ts.map +1 -0
- package/dist/extensions/web-search/render.js +109 -0
- package/dist/extensions/web-search/render.js.map +1 -0
- package/dist/extensions/web-search/schema.d.ts +12 -0
- package/dist/extensions/web-search/schema.d.ts.map +1 -0
- package/dist/extensions/web-search/schema.js +57 -0
- package/dist/extensions/web-search/schema.js.map +1 -0
- package/dist/extensions/web-search/types.d.ts +111 -0
- package/dist/extensions/web-search/types.d.ts.map +1 -0
- package/dist/extensions/web-search/types.js +5 -0
- package/dist/extensions/web-search/types.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +10 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +71 -58
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +7 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +3 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +12 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +6 -4
- package/dist/utils/shell.js.map +1 -1
- package/docs/bundled/README.md +1 -0
- package/docs/bundled/extensions/web-search.md +50 -0
- package/docs/compaction.md +5 -12
- package/docs/environment-variables.md +3 -0
- package/docs/extensions.md +21 -5
- package/docs/keybindings.md +1 -1
- package/docs/quickstart.md +1 -1
- package/docs/rpc.md +23 -0
- package/docs/settings.md +7 -0
- package/docs/terminal-setup.md +12 -0
- package/docs/usage.md +4 -3
- package/npm-shrinkwrap.json +29 -29
- package/package.json +6 -6
- package/dist/core/compaction-controller.d.ts +0 -90
- package/dist/core/compaction-controller.d.ts.map +0 -1
- package/dist/core/compaction-controller.js +0 -471
- package/dist/core/compaction-controller.js.map +0 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* background — bounded reads of a task's output file.
|
|
3
|
+
*
|
|
4
|
+
* Output files grow without limit, so nothing here ever reads a whole file:
|
|
5
|
+
* every read is a positioned slice, aligned so it starts on a UTF-8 codepoint
|
|
6
|
+
* boundary. Split out from registry.ts because process lifecycle and file
|
|
7
|
+
* access are independent concerns — and because the tests already treat them
|
|
8
|
+
* that way.
|
|
9
|
+
*/
|
|
10
|
+
export interface OutputSlice {
|
|
11
|
+
text: string;
|
|
12
|
+
sliceBytes: number;
|
|
13
|
+
totalBytes: number;
|
|
14
|
+
/** True when the file holds more bytes than the slice. */
|
|
15
|
+
truncated: boolean;
|
|
16
|
+
/** True in tail mode when the slice starts mid-line. */
|
|
17
|
+
startsMidLine: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Read a bounded slice from the head or tail of a file via positioned reads —
|
|
21
|
+
* never the whole file.
|
|
22
|
+
*/
|
|
23
|
+
export declare function readOutputSlice(filePath: string, options: {
|
|
24
|
+
mode: "head" | "tail";
|
|
25
|
+
maxBytes: number;
|
|
26
|
+
}): Promise<OutputSlice>;
|
|
27
|
+
/**
|
|
28
|
+
* Read the last `maxBytes` of a file starting no earlier than `fromByte` — the
|
|
29
|
+
* bounded delta since an offset, tail-aligned so the outcome (at the end of
|
|
30
|
+
* the output) is always included. The returned `fromByte` is where the slice
|
|
31
|
+
* actually starts.
|
|
32
|
+
*
|
|
33
|
+
* An offset past EOF is not an error — the output may have been truncated at
|
|
34
|
+
* the cap, or the caller may be reusing an id from an earlier read. Such a read
|
|
35
|
+
* falls back to the tail and reports `offsetPastEof` so the caller can say so.
|
|
36
|
+
*/
|
|
37
|
+
export declare function readOutputSince(filePath: string, fromByte: number, maxBytes: number): Promise<OutputSlice & {
|
|
38
|
+
fromByte: number;
|
|
39
|
+
offsetPastEof: boolean;
|
|
40
|
+
}>;
|
|
41
|
+
/** A tail read that reports failure instead of throwing; `slice` is absent when `error` is set. */
|
|
42
|
+
export interface TailRead {
|
|
43
|
+
slice?: OutputSlice;
|
|
44
|
+
error?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Tail read for notifications and the stall probe — the one place that decides
|
|
48
|
+
* what "the output could not be read" looks like, so neither caller has to
|
|
49
|
+
* accumulate the same six fields by hand. Text is returned raw; callers
|
|
50
|
+
* sanitize at the point they render it.
|
|
51
|
+
*/
|
|
52
|
+
export declare function readTail(filePath: string, maxBytes: number): Promise<TailRead>;
|
|
53
|
+
/**
|
|
54
|
+
* Create an empty output file exclusively ('wx'): fails on any existing path,
|
|
55
|
+
* including a symlink, so creation can never truncate what the path points at.
|
|
56
|
+
*/
|
|
57
|
+
export declare function createOutputFileExclusively(path: string): void;
|
|
58
|
+
//# sourceMappingURL=output-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-file.d.ts","sourceRoot":"","sources":["../../../src/extensions/background/output-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,wDAAwD;IACxD,aAAa,EAAE,OAAO,CAAC;CACvB;AAqCD;;;GAGG;AACH,wBAAsB,eAAe,CACpC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClD,OAAO,CAAC,WAAW,CAAC,CAiBtB;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACpC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAAC,CAwBrE;AAED,mGAAmG;AACnG,MAAM,WAAW,QAAQ;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAMpF;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAG9D"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* background — bounded reads of a task's output file.
|
|
3
|
+
*
|
|
4
|
+
* Output files grow without limit, so nothing here ever reads a whole file:
|
|
5
|
+
* every read is a positioned slice, aligned so it starts on a UTF-8 codepoint
|
|
6
|
+
* boundary. Split out from registry.ts because process lifecycle and file
|
|
7
|
+
* access are independent concerns — and because the tests already treat them
|
|
8
|
+
* that way.
|
|
9
|
+
*/
|
|
10
|
+
import { closeSync, openSync } from "node:fs";
|
|
11
|
+
import { open } from "node:fs/promises";
|
|
12
|
+
/**
|
|
13
|
+
* Read `length` bytes at `start`, first nudging the start past any UTF-8
|
|
14
|
+
* continuation bytes so the text begins on a codepoint boundary. The same probe
|
|
15
|
+
* reveals whether the slice starts mid-line. A `start` of 0 is used as-is —
|
|
16
|
+
* there is nothing before it to align against.
|
|
17
|
+
*/
|
|
18
|
+
async function readAligned(file, size, start, length) {
|
|
19
|
+
let position = start;
|
|
20
|
+
let remaining = length;
|
|
21
|
+
let startsMidLine = false;
|
|
22
|
+
if (position > 0 && remaining > 0) {
|
|
23
|
+
// Probe from one byte before the slice: probe[0] tells whether the slice
|
|
24
|
+
// starts at a line boundary, the rest lets us skip UTF-8 continuation
|
|
25
|
+
// bytes (0b10xxxxxx) so we never split a codepoint.
|
|
26
|
+
const probeStart = position - 1;
|
|
27
|
+
const probe = Buffer.alloc(Math.min(5, size - probeStart));
|
|
28
|
+
await file.read(probe, 0, probe.length, probeStart);
|
|
29
|
+
let skip = 0;
|
|
30
|
+
while (1 + skip < probe.length && ((probe[1 + skip] ?? 0) & 0b1100_0000) === 0b1000_0000) {
|
|
31
|
+
skip++;
|
|
32
|
+
}
|
|
33
|
+
position += skip;
|
|
34
|
+
remaining -= skip;
|
|
35
|
+
startsMidLine = probe[skip] !== 0x0a;
|
|
36
|
+
}
|
|
37
|
+
const buffer = Buffer.alloc(Math.max(0, remaining));
|
|
38
|
+
const bytesRead = buffer.length > 0 ? (await file.read(buffer, 0, buffer.length, position)).bytesRead : 0;
|
|
39
|
+
return { text: buffer.subarray(0, bytesRead).toString("utf8"), sliceBytes: bytesRead, startsMidLine, position };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Read a bounded slice from the head or tail of a file via positioned reads —
|
|
43
|
+
* never the whole file.
|
|
44
|
+
*/
|
|
45
|
+
export async function readOutputSlice(filePath, options) {
|
|
46
|
+
const file = await open(filePath, "r");
|
|
47
|
+
try {
|
|
48
|
+
const { size } = await file.stat();
|
|
49
|
+
const length = Math.min(size, Math.max(0, Math.floor(options.maxBytes)));
|
|
50
|
+
const start = options.mode === "tail" ? size - length : 0;
|
|
51
|
+
const slice = await readAligned(file, size, start, length);
|
|
52
|
+
return {
|
|
53
|
+
text: slice.text,
|
|
54
|
+
sliceBytes: slice.sliceBytes,
|
|
55
|
+
totalBytes: size,
|
|
56
|
+
truncated: size > slice.sliceBytes,
|
|
57
|
+
startsMidLine: slice.startsMidLine,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
await file.close();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Read the last `maxBytes` of a file starting no earlier than `fromByte` — the
|
|
66
|
+
* bounded delta since an offset, tail-aligned so the outcome (at the end of
|
|
67
|
+
* the output) is always included. The returned `fromByte` is where the slice
|
|
68
|
+
* actually starts.
|
|
69
|
+
*
|
|
70
|
+
* An offset past EOF is not an error — the output may have been truncated at
|
|
71
|
+
* the cap, or the caller may be reusing an id from an earlier read. Such a read
|
|
72
|
+
* falls back to the tail and reports `offsetPastEof` so the caller can say so.
|
|
73
|
+
*/
|
|
74
|
+
export async function readOutputSince(filePath, fromByte, maxBytes) {
|
|
75
|
+
const file = await open(filePath, "r");
|
|
76
|
+
try {
|
|
77
|
+
const { size } = await file.stat();
|
|
78
|
+
const offsetPastEof = Math.floor(fromByte) > size;
|
|
79
|
+
const floor = offsetPastEof ? 0 : Math.min(Math.max(0, Math.floor(fromByte)), size);
|
|
80
|
+
const length = Math.min(size - floor, Math.max(0, Math.floor(maxBytes)));
|
|
81
|
+
const start = size - length;
|
|
82
|
+
// Decided before alignment: nudging the start past continuation bytes is
|
|
83
|
+
// not the same as dropping output the caller asked for.
|
|
84
|
+
const truncated = start > floor;
|
|
85
|
+
const slice = await readAligned(file, size, start, length);
|
|
86
|
+
return {
|
|
87
|
+
text: slice.text,
|
|
88
|
+
sliceBytes: slice.sliceBytes,
|
|
89
|
+
totalBytes: size,
|
|
90
|
+
truncated,
|
|
91
|
+
startsMidLine: slice.startsMidLine,
|
|
92
|
+
fromByte: slice.position,
|
|
93
|
+
offsetPastEof,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
await file.close();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Tail read for notifications and the stall probe — the one place that decides
|
|
102
|
+
* what "the output could not be read" looks like, so neither caller has to
|
|
103
|
+
* accumulate the same six fields by hand. Text is returned raw; callers
|
|
104
|
+
* sanitize at the point they render it.
|
|
105
|
+
*/
|
|
106
|
+
export async function readTail(filePath, maxBytes) {
|
|
107
|
+
try {
|
|
108
|
+
return { slice: await readOutputSlice(filePath, { mode: "tail", maxBytes }) };
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Create an empty output file exclusively ('wx'): fails on any existing path,
|
|
116
|
+
* including a symlink, so creation can never truncate what the path points at.
|
|
117
|
+
*/
|
|
118
|
+
export function createOutputFileExclusively(path) {
|
|
119
|
+
const handle = openSync(path, "wx");
|
|
120
|
+
closeSync(handle);
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=output-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-file.js","sourceRoot":"","sources":["../../../src/extensions/background/output-file.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * background — bounded reads of a task's output file.\n *\n * Output files grow without limit, so nothing here ever reads a whole file:\n * every read is a positioned slice, aligned so it starts on a UTF-8 codepoint\n * boundary. Split out from registry.ts because process lifecycle and file\n * access are independent concerns — and because the tests already treat them\n * that way.\n */\n\nimport { closeSync, openSync } from \"node:fs\";\nimport { type FileHandle, open } from \"node:fs/promises\";\n\nexport interface OutputSlice {\n\ttext: string;\n\tsliceBytes: number;\n\ttotalBytes: number;\n\t/** True when the file holds more bytes than the slice. */\n\ttruncated: boolean;\n\t/** True in tail mode when the slice starts mid-line. */\n\tstartsMidLine: boolean;\n}\n\n/**\n * Read `length` bytes at `start`, first nudging the start past any UTF-8\n * continuation bytes so the text begins on a codepoint boundary. The same probe\n * reveals whether the slice starts mid-line. A `start` of 0 is used as-is —\n * there is nothing before it to align against.\n */\nasync function readAligned(\n\tfile: FileHandle,\n\tsize: number,\n\tstart: number,\n\tlength: number,\n): Promise<{ text: string; sliceBytes: number; startsMidLine: boolean; position: number }> {\n\tlet position = start;\n\tlet remaining = length;\n\tlet startsMidLine = false;\n\tif (position > 0 && remaining > 0) {\n\t\t// Probe from one byte before the slice: probe[0] tells whether the slice\n\t\t// starts at a line boundary, the rest lets us skip UTF-8 continuation\n\t\t// bytes (0b10xxxxxx) so we never split a codepoint.\n\t\tconst probeStart = position - 1;\n\t\tconst probe = Buffer.alloc(Math.min(5, size - probeStart));\n\t\tawait file.read(probe, 0, probe.length, probeStart);\n\t\tlet skip = 0;\n\t\twhile (1 + skip < probe.length && ((probe[1 + skip] ?? 0) & 0b1100_0000) === 0b1000_0000) {\n\t\t\tskip++;\n\t\t}\n\t\tposition += skip;\n\t\tremaining -= skip;\n\t\tstartsMidLine = probe[skip] !== 0x0a;\n\t}\n\tconst buffer = Buffer.alloc(Math.max(0, remaining));\n\tconst bytesRead = buffer.length > 0 ? (await file.read(buffer, 0, buffer.length, position)).bytesRead : 0;\n\treturn { text: buffer.subarray(0, bytesRead).toString(\"utf8\"), sliceBytes: bytesRead, startsMidLine, position };\n}\n\n/**\n * Read a bounded slice from the head or tail of a file via positioned reads —\n * never the whole file.\n */\nexport async function readOutputSlice(\n\tfilePath: string,\n\toptions: { mode: \"head\" | \"tail\"; maxBytes: number },\n): Promise<OutputSlice> {\n\tconst file = await open(filePath, \"r\");\n\ttry {\n\t\tconst { size } = await file.stat();\n\t\tconst length = Math.min(size, Math.max(0, Math.floor(options.maxBytes)));\n\t\tconst start = options.mode === \"tail\" ? size - length : 0;\n\t\tconst slice = await readAligned(file, size, start, length);\n\t\treturn {\n\t\t\ttext: slice.text,\n\t\t\tsliceBytes: slice.sliceBytes,\n\t\t\ttotalBytes: size,\n\t\t\ttruncated: size > slice.sliceBytes,\n\t\t\tstartsMidLine: slice.startsMidLine,\n\t\t};\n\t} finally {\n\t\tawait file.close();\n\t}\n}\n\n/**\n * Read the last `maxBytes` of a file starting no earlier than `fromByte` — the\n * bounded delta since an offset, tail-aligned so the outcome (at the end of\n * the output) is always included. The returned `fromByte` is where the slice\n * actually starts.\n *\n * An offset past EOF is not an error — the output may have been truncated at\n * the cap, or the caller may be reusing an id from an earlier read. Such a read\n * falls back to the tail and reports `offsetPastEof` so the caller can say so.\n */\nexport async function readOutputSince(\n\tfilePath: string,\n\tfromByte: number,\n\tmaxBytes: number,\n): Promise<OutputSlice & { fromByte: number; offsetPastEof: boolean }> {\n\tconst file = await open(filePath, \"r\");\n\ttry {\n\t\tconst { size } = await file.stat();\n\t\tconst offsetPastEof = Math.floor(fromByte) > size;\n\t\tconst floor = offsetPastEof ? 0 : Math.min(Math.max(0, Math.floor(fromByte)), size);\n\t\tconst length = Math.min(size - floor, Math.max(0, Math.floor(maxBytes)));\n\t\tconst start = size - length;\n\t\t// Decided before alignment: nudging the start past continuation bytes is\n\t\t// not the same as dropping output the caller asked for.\n\t\tconst truncated = start > floor;\n\t\tconst slice = await readAligned(file, size, start, length);\n\t\treturn {\n\t\t\ttext: slice.text,\n\t\t\tsliceBytes: slice.sliceBytes,\n\t\t\ttotalBytes: size,\n\t\t\ttruncated,\n\t\t\tstartsMidLine: slice.startsMidLine,\n\t\t\tfromByte: slice.position,\n\t\t\toffsetPastEof,\n\t\t};\n\t} finally {\n\t\tawait file.close();\n\t}\n}\n\n/** A tail read that reports failure instead of throwing; `slice` is absent when `error` is set. */\nexport interface TailRead {\n\tslice?: OutputSlice;\n\terror?: string;\n}\n\n/**\n * Tail read for notifications and the stall probe — the one place that decides\n * what \"the output could not be read\" looks like, so neither caller has to\n * accumulate the same six fields by hand. Text is returned raw; callers\n * sanitize at the point they render it.\n */\nexport async function readTail(filePath: string, maxBytes: number): Promise<TailRead> {\n\ttry {\n\t\treturn { slice: await readOutputSlice(filePath, { mode: \"tail\", maxBytes }) };\n\t} catch (error) {\n\t\treturn { error: error instanceof Error ? error.message : String(error) };\n\t}\n}\n\n/**\n * Create an empty output file exclusively ('wx'): fails on any existing path,\n * including a symlink, so creation can never truncate what the path points at.\n */\nexport function createOutputFileExclusively(path: string): void {\n\tconst handle = openSync(path, \"wx\");\n\tcloseSync(handle);\n}\n"]}
|
|
@@ -11,13 +11,10 @@
|
|
|
11
11
|
* whole process tree cross-platform.
|
|
12
12
|
*/
|
|
13
13
|
import type { BashOperations } from "../../core/tools/bash.ts";
|
|
14
|
+
import { type OutputSlice } from "./output-file.ts";
|
|
14
15
|
export declare const DEFAULT_MAX_OUTPUT_BYTES: number;
|
|
15
16
|
export declare const DEFAULT_MAX_RUNNING_TASKS = 8;
|
|
16
17
|
export declare const DEFAULT_NOTIFY_TAIL_BYTES: number;
|
|
17
|
-
/** Wait-window bounds shared by execution and the pending-call renderer. */
|
|
18
|
-
export declare const BG_WAIT_DEFAULT_MS = 20000;
|
|
19
|
-
export declare const BG_WAIT_MIN_MS = 1000;
|
|
20
|
-
export declare const BG_WAIT_MAX_MS = 60000;
|
|
21
18
|
/** Stall watchdog defaults, matching Claude Code's CC-1175 tuning. */
|
|
22
19
|
export declare const STALL_POLL_INTERVAL_MS = 5000;
|
|
23
20
|
export declare const STALL_THRESHOLD_MS = 45000;
|
|
@@ -47,31 +44,25 @@ export interface BgTask {
|
|
|
47
44
|
outputTruncated: boolean;
|
|
48
45
|
error?: string;
|
|
49
46
|
timeoutSeconds?: number;
|
|
50
|
-
/** Delivery
|
|
47
|
+
/** Delivery happened: a notification was sent, or a waiter returned this task inline. */
|
|
51
48
|
notified: boolean;
|
|
52
49
|
}
|
|
53
|
-
|
|
50
|
+
/**
|
|
51
|
+
* What a settled or stalled task hands to the extension for delivery.
|
|
52
|
+
*
|
|
53
|
+
* One shape with one discriminant, because both are delivered the same way and
|
|
54
|
+
* carry the same payload; only the registry cares about the difference (a
|
|
55
|
+
* completion participates in the delivery claim, a stall is informational and
|
|
56
|
+
* bypasses it).
|
|
57
|
+
*/
|
|
58
|
+
export interface BgNotification {
|
|
59
|
+
kind: "completion" | "stall";
|
|
54
60
|
task: BgTask;
|
|
55
|
-
/** Sanitized tail of the output file;
|
|
56
|
-
|
|
57
|
-
tailBytes: number;
|
|
58
|
-
totalBytes: number;
|
|
59
|
-
tailTruncated: boolean;
|
|
60
|
-
tailStartsMidLine: boolean;
|
|
61
|
+
/** Sanitized tail of the output file; absent when it could not be read. */
|
|
62
|
+
tail: OutputSlice | undefined;
|
|
61
63
|
/** Set when the output file could not be read; the notification still fires. */
|
|
62
64
|
tailError?: string;
|
|
63
65
|
}
|
|
64
|
-
/** One-shot signal that a running task appears blocked on interactive input. */
|
|
65
|
-
export type BgStallNotification = BgTaskNotification;
|
|
66
|
-
export interface OutputSlice {
|
|
67
|
-
text: string;
|
|
68
|
-
sliceBytes: number;
|
|
69
|
-
totalBytes: number;
|
|
70
|
-
/** True when the file holds more bytes than the slice. */
|
|
71
|
-
truncated: boolean;
|
|
72
|
-
/** True in tail mode when the slice starts mid-line. */
|
|
73
|
-
startsMidLine: boolean;
|
|
74
|
-
}
|
|
75
66
|
/** Outcome of a bounded wait: terminal delivery, or the wait window expiring. */
|
|
76
67
|
export type WaitOutcome = {
|
|
77
68
|
outcome: "terminal";
|
|
@@ -80,23 +71,6 @@ export type WaitOutcome = {
|
|
|
80
71
|
outcome: "timeout";
|
|
81
72
|
task: BgTask;
|
|
82
73
|
};
|
|
83
|
-
/**
|
|
84
|
-
* Read a bounded slice from the head or tail of a file via positioned reads —
|
|
85
|
-
* never the whole file.
|
|
86
|
-
*/
|
|
87
|
-
export declare function readOutputSlice(filePath: string, options: {
|
|
88
|
-
mode: "head" | "tail";
|
|
89
|
-
maxBytes: number;
|
|
90
|
-
}): Promise<OutputSlice>;
|
|
91
|
-
/**
|
|
92
|
-
* Read the last `maxBytes` of a file starting no earlier than `fromByte` — the
|
|
93
|
-
* bounded delta since an offset, tail-aligned so the outcome (at the end of
|
|
94
|
-
* the output) is always included. `fromByte` is clamped into the file; the
|
|
95
|
-
* returned `fromByte` is where the slice actually starts.
|
|
96
|
-
*/
|
|
97
|
-
export declare function readOutputSince(filePath: string, fromByte: number, maxBytes: number): Promise<OutputSlice & {
|
|
98
|
-
fromByte: number;
|
|
99
|
-
}>;
|
|
100
74
|
export interface BackgroundRegistryOptions {
|
|
101
75
|
operations: BashOperations;
|
|
102
76
|
/** Directory for task output files. Defaults to the system temp directory. */
|
|
@@ -104,16 +78,17 @@ export interface BackgroundRegistryOptions {
|
|
|
104
78
|
maxOutputBytes?: number;
|
|
105
79
|
maxRunningTasks?: number;
|
|
106
80
|
notifyTailBytes?: number;
|
|
107
|
-
/** Called at most once
|
|
108
|
-
onNotify: (notification:
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
-
|
|
81
|
+
/** Called at most once per task per kind; synchronous throws do not prevent settlement. */
|
|
82
|
+
onNotify: (notification: BgNotification) => void;
|
|
83
|
+
/**
|
|
84
|
+
* Stall watchdog tuning; `false` disables the watchdog outright. Defaults
|
|
85
|
+
* follow Claude Code's CC-1175 (5s/45s/1KB).
|
|
86
|
+
*/
|
|
112
87
|
stall?: {
|
|
113
88
|
pollIntervalMs?: number;
|
|
114
89
|
thresholdMs?: number;
|
|
115
90
|
tailBytes?: number;
|
|
116
|
-
};
|
|
91
|
+
} | false;
|
|
117
92
|
/** Called whenever a task starts or reaches a terminal state. */
|
|
118
93
|
onChange: () => void;
|
|
119
94
|
now?: () => number;
|
|
@@ -133,7 +108,7 @@ export declare class BackgroundTaskRegistry {
|
|
|
133
108
|
private readonly maxRunningTasks;
|
|
134
109
|
private readonly notifyTailBytes;
|
|
135
110
|
private readonly onNotify;
|
|
136
|
-
private readonly
|
|
111
|
+
private readonly stallEnabled;
|
|
137
112
|
private readonly stallPollIntervalMs;
|
|
138
113
|
private readonly stallThresholdMs;
|
|
139
114
|
private readonly stallTailBytes;
|
|
@@ -155,11 +130,13 @@ export declare class BackgroundTaskRegistry {
|
|
|
155
130
|
listTasks(): BgTask[];
|
|
156
131
|
/** Resolve a task by id or unique id prefix; the "bg-" prefix may be omitted. */
|
|
157
132
|
resolveTask(idPrefix: string): ResolveTaskResult;
|
|
133
|
+
/**
|
|
134
|
+
* Request a kill. Reports only whether one was issued: why it was not is
|
|
135
|
+
* already on the task (an unknown id cannot reach here through the tool,
|
|
136
|
+
* which resolves first, and a settled task carries its own status).
|
|
137
|
+
*/
|
|
158
138
|
killTask(id: string): {
|
|
159
|
-
killed:
|
|
160
|
-
} | {
|
|
161
|
-
killed: false;
|
|
162
|
-
reason: "not-found" | "not-running";
|
|
139
|
+
killed: boolean;
|
|
163
140
|
};
|
|
164
141
|
counts(): Record<BgTaskStatus, number> & {
|
|
165
142
|
total: number;
|
|
@@ -168,19 +145,17 @@ export declare class BackgroundTaskRegistry {
|
|
|
168
145
|
/** Resolves once the task has finalized, including its notification attempt. */
|
|
169
146
|
waitForTask(id: string): Promise<BgTask>;
|
|
170
147
|
/**
|
|
171
|
-
* Bounded model-facing wait
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* notification is left untouched and fires as usual.
|
|
176
|
-
*
|
|
177
|
-
* All interleavings are deterministic on JS's single thread: a waiter that
|
|
178
|
-
* registers before finalize's synchronous claim check claims delivery; one
|
|
179
|
-
* that arrives after sees a terminal status and returns it immediately
|
|
180
|
-
* (the followUp may also arrive — an idempotent repeat, not a lie).
|
|
148
|
+
* Bounded model-facing wait. Delivery is claimed by whoever actually
|
|
149
|
+
* delivers: a waiter that returns a terminal task marks it notified, so
|
|
150
|
+
* finalize's followUp is skipped and the completion is delivered exactly
|
|
151
|
+
* once, inline here.
|
|
181
152
|
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
153
|
+
* Nothing claims on behalf of anyone else, which is what makes an
|
|
154
|
+
* interrupted wait safe: an aborted waiter never marks the task notified,
|
|
155
|
+
* and the last waiter to leave without delivering sends the followUp itself.
|
|
156
|
+
* A waiter that arrives after the task already settled returns immediately
|
|
157
|
+
* without registering — the followUp may also arrive, an idempotent repeat
|
|
158
|
+
* rather than a lie.
|
|
184
159
|
*/
|
|
185
160
|
waitForResult(id: string, timeoutMs: number, signal?: AbortSignal): Promise<WaitOutcome>;
|
|
186
161
|
/**
|
|
@@ -198,6 +173,8 @@ export declare class BackgroundTaskRegistry {
|
|
|
198
173
|
private clearStallWatchdog;
|
|
199
174
|
private checkStall;
|
|
200
175
|
private probeStallTail;
|
|
176
|
+
/** The one place a notification payload is shaped, for either kind. */
|
|
177
|
+
private emit;
|
|
201
178
|
private newTaskId;
|
|
202
179
|
private run;
|
|
203
180
|
private handleData;
|
|
@@ -205,13 +182,4 @@ export declare class BackgroundTaskRegistry {
|
|
|
205
182
|
private classifyOutcome;
|
|
206
183
|
private notifyCompletion;
|
|
207
184
|
}
|
|
208
|
-
/**
|
|
209
|
-
* Create an empty output file exclusively ('wx'): fails on any existing path,
|
|
210
|
-
* including a symlink, so creation can never truncate what the path points at.
|
|
211
|
-
*/
|
|
212
|
-
export declare function createOutputFileExclusively(path: string): void;
|
|
213
|
-
/** First non-empty line of a command, trimmed — for one-line task labels. */
|
|
214
|
-
export declare function firstCommandLine(command: string): string;
|
|
215
|
-
/** Compact duration like Pi's own timers: 12s, 3m05s, 1h02m. */
|
|
216
|
-
export declare function formatDuration(ms: number): string;
|
|
217
185
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/extensions/background/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/extensions/background/registry.ts"],"names":[],"mappings":"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"}
|