@astralyn/pi 0.82.4 → 0.82.6
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 +52 -0
- package/dist/cli/project-trust.d.ts.map +1 -1
- package/dist/cli/project-trust.js +4 -1
- package/dist/cli/project-trust.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +4 -22
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +2 -3
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +37 -5
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +11 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +3 -13
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +6 -36
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/extensions/plan/constants.d.ts +11 -2
- package/dist/extensions/plan/constants.d.ts.map +1 -1
- package/dist/extensions/plan/constants.js +14 -2
- package/dist/extensions/plan/constants.js.map +1 -1
- package/dist/extensions/plan/index.d.ts +0 -18
- package/dist/extensions/plan/index.d.ts.map +1 -1
- package/dist/extensions/plan/index.js +35 -3
- package/dist/extensions/plan/index.js.map +1 -1
- package/dist/extensions/plan/view.d.ts +36 -0
- package/dist/extensions/plan/view.d.ts.map +1 -0
- package/dist/extensions/plan/view.js +74 -0
- package/dist/extensions/plan/view.js.map +1 -0
- package/dist/extensions/question/dialog.d.ts +3 -1
- package/dist/extensions/question/dialog.d.ts.map +1 -1
- package/dist/extensions/question/dialog.js +106 -52
- package/dist/extensions/question/dialog.js.map +1 -1
- package/dist/extensions/question/index.d.ts.map +1 -1
- package/dist/extensions/question/index.js +2 -2
- package/dist/extensions/question/index.js.map +1 -1
- package/dist/extensions/question/render-cache.d.ts +9 -0
- package/dist/extensions/question/render-cache.d.ts.map +1 -1
- package/dist/extensions/question/render-cache.js +22 -0
- package/dist/extensions/question/render-cache.js.map +1 -1
- package/dist/extensions/question/results.d.ts.map +1 -1
- package/dist/extensions/question/results.js +6 -1
- package/dist/extensions/question/results.js.map +1 -1
- package/dist/extensions/question/schema.d.ts +4 -0
- package/dist/extensions/question/schema.d.ts.map +1 -1
- package/dist/extensions/question/schema.js +19 -28
- package/dist/extensions/question/schema.js.map +1 -1
- package/dist/extensions/question/types.d.ts +1 -1
- package/dist/extensions/question/types.d.ts.map +1 -1
- package/dist/extensions/question/types.js.map +1 -1
- package/dist/extensions/router/stream.d.ts.map +1 -1
- package/dist/extensions/router/stream.js +44 -0
- package/dist/extensions/router/stream.js.map +1 -1
- package/dist/extensions/subagent/activity.d.ts.map +1 -1
- package/dist/extensions/subagent/activity.js +25 -4
- package/dist/extensions/subagent/activity.js.map +1 -1
- package/dist/extensions/subagent/agents.d.ts.map +1 -1
- package/dist/extensions/subagent/agents.js +12 -6
- package/dist/extensions/subagent/agents.js.map +1 -1
- package/dist/extensions/subagent/constants.d.ts +1 -1
- package/dist/extensions/subagent/constants.d.ts.map +1 -1
- package/dist/extensions/subagent/constants.js +3 -2
- package/dist/extensions/subagent/constants.js.map +1 -1
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +14 -0
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +243 -116
- 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 +13 -9
- 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 +9 -3
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/schema.d.ts.map +1 -1
- package/dist/extensions/subagent/schema.js +4 -4
- package/dist/extensions/subagent/schema.js.map +1 -1
- package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
- package/dist/extensions/subagent/sdk-runner.js +5 -0
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/types.d.ts +7 -0
- package/dist/extensions/subagent/types.d.ts.map +1 -1
- package/dist/extensions/subagent/types.js.map +1 -1
- package/dist/extensions/todo/constants.d.ts +17 -6
- package/dist/extensions/todo/constants.d.ts.map +1 -1
- package/dist/extensions/todo/constants.js +47 -9
- package/dist/extensions/todo/constants.js.map +1 -1
- package/dist/extensions/todo/index.d.ts +1 -15
- package/dist/extensions/todo/index.d.ts.map +1 -1
- package/dist/extensions/todo/index.js +35 -4
- package/dist/extensions/todo/index.js.map +1 -1
- package/dist/extensions/todo/schema.d.ts +59 -7
- package/dist/extensions/todo/schema.d.ts.map +1 -1
- package/dist/extensions/todo/schema.js +72 -12
- package/dist/extensions/todo/schema.js.map +1 -1
- package/dist/extensions/todo/state.d.ts +20 -5
- package/dist/extensions/todo/state.d.ts.map +1 -1
- package/dist/extensions/todo/state.js +1016 -134
- package/dist/extensions/todo/state.js.map +1 -1
- package/dist/extensions/todo/view.d.ts +16 -1
- package/dist/extensions/todo/view.d.ts.map +1 -1
- package/dist/extensions/todo/view.js +293 -7
- package/dist/extensions/todo/view.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +6 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +14 -6
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +6 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +41 -2
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +8 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/coalescing-terminal.d.ts +71 -17
- package/dist/utils/coalescing-terminal.d.ts.map +1 -1
- package/dist/utils/coalescing-terminal.js +136 -31
- package/dist/utils/coalescing-terminal.js.map +1 -1
- package/docs/bundled/extensions/plan.md +6 -4
- package/docs/bundled/extensions/question.md +9 -7
- package/docs/bundled/extensions/subagent.md +4 -4
- package/docs/bundled/extensions/todo.md +9 -5
- package/docs/bundled/tool-presentation.md +1 -1
- package/docs/extensions.md +14 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/utils/output-decoder.d.ts +0 -52
- package/dist/utils/output-decoder.d.ts.map +0 -1
- package/dist/utils/output-decoder.js +0 -134
- package/dist/utils/output-decoder.js.map +0 -1
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { isUtf8 } from "node:buffer";
|
|
2
|
-
import { spawnSync } from "child_process";
|
|
3
|
-
/**
|
|
4
|
-
* Windows OEM code pages mapped to WHATWG TextDecoder labels. Console
|
|
5
|
-
* programs emit piped output in the OEM code page, so only code pages that
|
|
6
|
-
* TextDecoder can represent are listed; others keep UTF-8 decoding.
|
|
7
|
-
*/
|
|
8
|
-
const OEM_CODE_PAGE_ENCODINGS = {
|
|
9
|
-
"866": "ibm866",
|
|
10
|
-
"874": "windows-874",
|
|
11
|
-
"932": "shift_jis",
|
|
12
|
-
"936": "gbk",
|
|
13
|
-
"949": "euc-kr",
|
|
14
|
-
"950": "big5",
|
|
15
|
-
"1251": "windows-1251",
|
|
16
|
-
"1252": "windows-1252",
|
|
17
|
-
};
|
|
18
|
-
let cachedConsoleFallbackEncoding;
|
|
19
|
-
/**
|
|
20
|
-
* Resolve the fallback encoding for console output on this system.
|
|
21
|
-
*
|
|
22
|
-
* On Windows, cmd.exe builtins, Windows PowerShell, and classic console tools
|
|
23
|
-
* such as ipconfig emit piped output in the legacy OEM code page (GBK on
|
|
24
|
-
* Simplified Chinese systems, Shift_JIS on Japanese systems, and so on)
|
|
25
|
-
* rather than UTF-8. Returns the TextDecoder label for that code page, or
|
|
26
|
-
* null when output should stay UTF-8: non-Windows platforms, UTF-8 systems
|
|
27
|
-
* (code page 65001), and code pages TextDecoder cannot represent.
|
|
28
|
-
*/
|
|
29
|
-
export function getConsoleFallbackEncoding() {
|
|
30
|
-
if (cachedConsoleFallbackEncoding === undefined) {
|
|
31
|
-
cachedConsoleFallbackEncoding = detectConsoleFallbackEncoding();
|
|
32
|
-
}
|
|
33
|
-
return cachedConsoleFallbackEncoding;
|
|
34
|
-
}
|
|
35
|
-
function detectConsoleFallbackEncoding() {
|
|
36
|
-
if (process.platform !== "win32") {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
try {
|
|
40
|
-
const result = spawnSync("reg", ["query", "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage", "/v", "OEMCP"], { encoding: "utf-8", timeout: 5000, windowsHide: true });
|
|
41
|
-
if (result.status !== 0 || !result.stdout) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
const match = result.stdout.match(/OEMCP\s+REG_SZ\s+(\d+)/);
|
|
45
|
-
const encoding = match ? OEM_CODE_PAGE_ENCODINGS[match[1]] : undefined;
|
|
46
|
-
if (!encoding) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
// Node builds with small-icu lack these decoders; verify availability.
|
|
50
|
-
new TextDecoder(encoding);
|
|
51
|
-
return encoding;
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
const DEFAULT_DETECTION_LIMIT_BYTES = 256 * 1024;
|
|
58
|
-
/**
|
|
59
|
-
* Streaming decoder that assumes UTF-8 and falls back to the system console
|
|
60
|
-
* encoding when the stream turns out not to be UTF-8.
|
|
61
|
-
*
|
|
62
|
-
* Decoding starts as plain streaming UTF-8 — the fast path for virtually all
|
|
63
|
-
* output. When a replacement character appears, the bytes seen so far are
|
|
64
|
-
* checked with isUtf8: if they are genuinely invalid UTF-8, everything is
|
|
65
|
-
* re-decoded with the fallback encoding and the result is reported with
|
|
66
|
-
* `rewound: true` so the caller can rebuild its derived state. If the bytes
|
|
67
|
-
* are valid UTF-8 (the source itself contained replacement characters),
|
|
68
|
-
* detection stops and UTF-8 decoding continues.
|
|
69
|
-
*
|
|
70
|
-
* Raw bytes are retained only while detection is active and only up to
|
|
71
|
-
* `detectionLimitBytes`; larger streams lock to UTF-8 and memory stays flat.
|
|
72
|
-
*/
|
|
73
|
-
export class OutputDecoder {
|
|
74
|
-
decoder = new TextDecoder();
|
|
75
|
-
fallbackEncoding;
|
|
76
|
-
detectionLimitBytes;
|
|
77
|
-
pending = [];
|
|
78
|
-
pendingBytes = 0;
|
|
79
|
-
detecting;
|
|
80
|
-
constructor(options = {}) {
|
|
81
|
-
this.fallbackEncoding =
|
|
82
|
-
options.fallbackEncoding === undefined ? getConsoleFallbackEncoding() : options.fallbackEncoding;
|
|
83
|
-
this.detectionLimitBytes = options.detectionLimitBytes ?? DEFAULT_DETECTION_LIMIT_BYTES;
|
|
84
|
-
this.detecting = this.fallbackEncoding !== null;
|
|
85
|
-
}
|
|
86
|
-
push(data) {
|
|
87
|
-
const text = this.decoder.decode(data, { stream: true });
|
|
88
|
-
if (!this.detecting) {
|
|
89
|
-
return { text, rewound: false };
|
|
90
|
-
}
|
|
91
|
-
this.pending.push(data);
|
|
92
|
-
this.pendingBytes += data.length;
|
|
93
|
-
if (text.includes("�")) {
|
|
94
|
-
return this.tryRewind(text);
|
|
95
|
-
}
|
|
96
|
-
if (this.pendingBytes > this.detectionLimitBytes) {
|
|
97
|
-
this.stopDetecting();
|
|
98
|
-
}
|
|
99
|
-
return { text, rewound: false };
|
|
100
|
-
}
|
|
101
|
-
flush() {
|
|
102
|
-
const text = this.decoder.decode();
|
|
103
|
-
if (this.detecting && text.includes("�")) {
|
|
104
|
-
return this.tryRewind(text);
|
|
105
|
-
}
|
|
106
|
-
this.stopDetecting();
|
|
107
|
-
return { text, rewound: false };
|
|
108
|
-
}
|
|
109
|
-
tryRewind(utf8Text) {
|
|
110
|
-
const raw = Buffer.concat(this.pending);
|
|
111
|
-
if (isUtf8(raw)) {
|
|
112
|
-
// The replacement characters exist in the source bytes themselves;
|
|
113
|
-
// the stream is valid UTF-8, so stop watching and keep it.
|
|
114
|
-
this.stopDetecting();
|
|
115
|
-
return { text: utf8Text, rewound: false };
|
|
116
|
-
}
|
|
117
|
-
try {
|
|
118
|
-
this.decoder = new TextDecoder(this.fallbackEncoding);
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
this.stopDetecting();
|
|
122
|
-
return { text: utf8Text, rewound: false };
|
|
123
|
-
}
|
|
124
|
-
const text = this.decoder.decode(raw, { stream: true });
|
|
125
|
-
this.stopDetecting();
|
|
126
|
-
return { text, rewound: true };
|
|
127
|
-
}
|
|
128
|
-
stopDetecting() {
|
|
129
|
-
this.detecting = false;
|
|
130
|
-
this.pending = [];
|
|
131
|
-
this.pendingBytes = 0;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
//# sourceMappingURL=output-decoder.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"output-decoder.js","sourceRoot":"","sources":["../../src/utils/output-decoder.ts"],"names":[],"mappings":"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","sourcesContent":["import { isUtf8 } from \"node:buffer\";\nimport { spawnSync } from \"child_process\";\n\n/**\n * Windows OEM code pages mapped to WHATWG TextDecoder labels. Console\n * programs emit piped output in the OEM code page, so only code pages that\n * TextDecoder can represent are listed; others keep UTF-8 decoding.\n */\nconst OEM_CODE_PAGE_ENCODINGS: Record<string, string> = {\n\t\"866\": \"ibm866\",\n\t\"874\": \"windows-874\",\n\t\"932\": \"shift_jis\",\n\t\"936\": \"gbk\",\n\t\"949\": \"euc-kr\",\n\t\"950\": \"big5\",\n\t\"1251\": \"windows-1251\",\n\t\"1252\": \"windows-1252\",\n};\n\nlet cachedConsoleFallbackEncoding: string | null | undefined;\n\n/**\n * Resolve the fallback encoding for console output on this system.\n *\n * On Windows, cmd.exe builtins, Windows PowerShell, and classic console tools\n * such as ipconfig emit piped output in the legacy OEM code page (GBK on\n * Simplified Chinese systems, Shift_JIS on Japanese systems, and so on)\n * rather than UTF-8. Returns the TextDecoder label for that code page, or\n * null when output should stay UTF-8: non-Windows platforms, UTF-8 systems\n * (code page 65001), and code pages TextDecoder cannot represent.\n */\nexport function getConsoleFallbackEncoding(): string | null {\n\tif (cachedConsoleFallbackEncoding === undefined) {\n\t\tcachedConsoleFallbackEncoding = detectConsoleFallbackEncoding();\n\t}\n\treturn cachedConsoleFallbackEncoding;\n}\n\nfunction detectConsoleFallbackEncoding(): string | null {\n\tif (process.platform !== \"win32\") {\n\t\treturn null;\n\t}\n\ttry {\n\t\tconst result = spawnSync(\n\t\t\t\"reg\",\n\t\t\t[\"query\", \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Nls\\\\CodePage\", \"/v\", \"OEMCP\"],\n\t\t\t{ encoding: \"utf-8\", timeout: 5000, windowsHide: true },\n\t\t);\n\t\tif (result.status !== 0 || !result.stdout) {\n\t\t\treturn null;\n\t\t}\n\t\tconst match = result.stdout.match(/OEMCP\\s+REG_SZ\\s+(\\d+)/);\n\t\tconst encoding = match ? OEM_CODE_PAGE_ENCODINGS[match[1]] : undefined;\n\t\tif (!encoding) {\n\t\t\treturn null;\n\t\t}\n\t\t// Node builds with small-icu lack these decoders; verify availability.\n\t\tnew TextDecoder(encoding);\n\t\treturn encoding;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport interface DecodedChunk {\n\t/** Decoded text for this push, or the full re-decoded transcript when rewound. */\n\ttext: string;\n\t/**\n\t * True when the decoder switched to the fallback encoding. All previously\n\t * returned text is invalid; `text` replaces the entire transcript.\n\t */\n\trewound: boolean;\n}\n\nconst DEFAULT_DETECTION_LIMIT_BYTES = 256 * 1024;\n\n/**\n * Streaming decoder that assumes UTF-8 and falls back to the system console\n * encoding when the stream turns out not to be UTF-8.\n *\n * Decoding starts as plain streaming UTF-8 — the fast path for virtually all\n * output. When a replacement character appears, the bytes seen so far are\n * checked with isUtf8: if they are genuinely invalid UTF-8, everything is\n * re-decoded with the fallback encoding and the result is reported with\n * `rewound: true` so the caller can rebuild its derived state. If the bytes\n * are valid UTF-8 (the source itself contained replacement characters),\n * detection stops and UTF-8 decoding continues.\n *\n * Raw bytes are retained only while detection is active and only up to\n * `detectionLimitBytes`; larger streams lock to UTF-8 and memory stays flat.\n */\nexport class OutputDecoder {\n\tprivate decoder = new TextDecoder();\n\tprivate readonly fallbackEncoding: string | null;\n\tprivate readonly detectionLimitBytes: number;\n\tprivate pending: Buffer[] = [];\n\tprivate pendingBytes = 0;\n\tprivate detecting: boolean;\n\n\tconstructor(options: { fallbackEncoding?: string | null; detectionLimitBytes?: number } = {}) {\n\t\tthis.fallbackEncoding =\n\t\t\toptions.fallbackEncoding === undefined ? getConsoleFallbackEncoding() : options.fallbackEncoding;\n\t\tthis.detectionLimitBytes = options.detectionLimitBytes ?? DEFAULT_DETECTION_LIMIT_BYTES;\n\t\tthis.detecting = this.fallbackEncoding !== null;\n\t}\n\n\tpush(data: Buffer): DecodedChunk {\n\t\tconst text = this.decoder.decode(data, { stream: true });\n\t\tif (!this.detecting) {\n\t\t\treturn { text, rewound: false };\n\t\t}\n\t\tthis.pending.push(data);\n\t\tthis.pendingBytes += data.length;\n\t\tif (text.includes(\"�\")) {\n\t\t\treturn this.tryRewind(text);\n\t\t}\n\t\tif (this.pendingBytes > this.detectionLimitBytes) {\n\t\t\tthis.stopDetecting();\n\t\t}\n\t\treturn { text, rewound: false };\n\t}\n\n\tflush(): DecodedChunk {\n\t\tconst text = this.decoder.decode();\n\t\tif (this.detecting && text.includes(\"�\")) {\n\t\t\treturn this.tryRewind(text);\n\t\t}\n\t\tthis.stopDetecting();\n\t\treturn { text, rewound: false };\n\t}\n\n\tprivate tryRewind(utf8Text: string): DecodedChunk {\n\t\tconst raw = Buffer.concat(this.pending);\n\t\tif (isUtf8(raw)) {\n\t\t\t// The replacement characters exist in the source bytes themselves;\n\t\t\t// the stream is valid UTF-8, so stop watching and keep it.\n\t\t\tthis.stopDetecting();\n\t\t\treturn { text: utf8Text, rewound: false };\n\t\t}\n\t\ttry {\n\t\t\tthis.decoder = new TextDecoder(this.fallbackEncoding as string);\n\t\t} catch {\n\t\t\tthis.stopDetecting();\n\t\t\treturn { text: utf8Text, rewound: false };\n\t\t}\n\t\tconst text = this.decoder.decode(raw, { stream: true });\n\t\tthis.stopDetecting();\n\t\treturn { text, rewound: true };\n\t}\n\n\tprivate stopDetecting(): void {\n\t\tthis.detecting = false;\n\t\tthis.pending = [];\n\t\tthis.pendingBytes = 0;\n\t}\n}\n"]}
|