@code-yeongyu/senpi 2026.5.14 → 2026.5.15-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/CHANGELOG.md +1110 -1175
- package/README.md +1 -2
- package/dist/core/agent-session.d.ts +9 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +109 -7
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/dynamic-prompt/verification.d.ts +31 -0
- package/dist/core/dynamic-prompt/verification.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/verification.js +41 -0
- package/dist/core/dynamic-prompt/verification.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/context-reduction.d.ts +97 -0
- package/dist/core/extensions/builtin/compaction/context-reduction.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/context-reduction.js +420 -0
- package/dist/core/extensions/builtin/compaction/context-reduction.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +168 -31
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +197 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.js +690 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/prompts.d.ts +3 -3
- package/dist/core/extensions/builtin/compaction/prompts.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/prompts.js +0 -22
- package/dist/core/extensions/builtin/compaction/prompts.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts +4 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js +48 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +3 -1
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +82 -33
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts +8 -0
- package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/todo-bridge.js +12 -6
- package/dist/core/extensions/builtin/compaction/todo-bridge.js.map +1 -1
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +0 -2
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/core/extensions/builtin/openai-web-search/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/openai-web-search/index.js +26 -1
- package/dist/core/extensions/builtin/openai-web-search/index.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/prompt.js +0 -5
- package/dist/core/extensions/builtin/permission-system/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/system-messages.d.ts +7 -7
- package/dist/core/extensions/builtin/system-messages.d.ts.map +1 -1
- package/dist/core/extensions/builtin/system-messages.js +10 -10
- package/dist/core/extensions/builtin/system-messages.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.js +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.d.ts +1 -1
- package/dist/core/extensions/builtin/todotools/state.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.js +1 -1
- package/dist/core/extensions/builtin/todotools/state.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/system-messages.d.ts +3 -3
- package/dist/core/extensions/builtin/todotools/system-messages.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/system-messages.js +6 -6
- package/dist/core/extensions/builtin/todotools/system-messages.js.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.d.ts +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.js +8 -4
- package/dist/core/extensions/builtin/tool-pair-guard/index.js.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.d.ts +3 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.js +89 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.js.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.d.ts +3 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.js +122 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +2 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +18 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +22 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/messages.d.ts +3 -3
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +5 -10
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +1 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +7 -22
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +1 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +0 -5
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/thinking-levels.d.ts +6 -0
- package/dist/core/thinking-levels.d.ts.map +1 -0
- package/dist/core/thinking-levels.js +36 -0
- package/dist/core/thinking-levels.js.map +1 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +15 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +20 -2
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +3 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +8 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +137 -49
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/working-status.d.ts +15 -0
- package/dist/modes/interactive/working-status.d.ts.map +1 -0
- package/dist/modes/interactive/working-status.js +60 -0
- package/dist/modes/interactive/working-status.js.map +1 -0
- package/docs/extensions.md +0 -1
- package/docs/index.md +0 -1
- package/docs/sdk.md +0 -1
- package/docs/settings.md +1 -29
- package/docs/termux.md +2 -2
- package/docs/usage.md +1 -1
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/overlay-qa-tests.ts +1 -1
- package/package.json +4 -4
- package/dist/core/extensions/builtin/background-task/cancel-tool.d.ts +0 -10
- package/dist/core/extensions/builtin/background-task/cancel-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/cancel-tool.js +0 -109
- package/dist/core/extensions/builtin/background-task/cancel-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/index.d.ts +0 -3
- package/dist/core/extensions/builtin/background-task/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/index.js +0 -207
- package/dist/core/extensions/builtin/background-task/index.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/manager.d.ts +0 -17
- package/dist/core/extensions/builtin/background-task/manager.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/manager.js +0 -114
- package/dist/core/extensions/builtin/background-task/manager.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/notification.d.ts +0 -22
- package/dist/core/extensions/builtin/background-task/notification.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/notification.js +0 -105
- package/dist/core/extensions/builtin/background-task/notification.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/output-tool.d.ts +0 -11
- package/dist/core/extensions/builtin/background-task/output-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/output-tool.js +0 -127
- package/dist/core/extensions/builtin/background-task/output-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/spawner.d.ts +0 -8
- package/dist/core/extensions/builtin/background-task/spawner.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/spawner.js +0 -207
- package/dist/core/extensions/builtin/background-task/spawner.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/task-tool.d.ts +0 -20
- package/dist/core/extensions/builtin/background-task/task-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/task-tool.js +0 -302
- package/dist/core/extensions/builtin/background-task/task-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/types.d.ts +0 -72
- package/dist/core/extensions/builtin/background-task/types.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/types.js +0 -32
- package/dist/core/extensions/builtin/background-task/types.js.map +0 -1
- package/docs/agents.md +0 -348
- package/examples/extensions/subagent/README.md +0 -172
- package/examples/extensions/subagent/agents/planner.md +0 -37
- package/examples/extensions/subagent/agents/reviewer.md +0 -35
- package/examples/extensions/subagent/agents/scout.md +0 -50
- package/examples/extensions/subagent/agents/worker.md +0 -24
- package/examples/extensions/subagent/agents.ts +0 -126
- package/examples/extensions/subagent/index.ts +0 -987
- package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
- package/examples/extensions/subagent/prompts/implement.md +0 -10
- package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type WorkingStatusTextFrameStyle = {
|
|
2
|
+
base: (text: string) => string;
|
|
3
|
+
glow: (text: string) => string;
|
|
4
|
+
highlight: (text: string) => string;
|
|
5
|
+
shimmer?: (text: string, intensity: number) => string;
|
|
6
|
+
};
|
|
7
|
+
type WorkingStatusMessageFrameStyle = WorkingStatusTextFrameStyle & {
|
|
8
|
+
suffix: (text: string) => string;
|
|
9
|
+
};
|
|
10
|
+
export declare function formatWorkingElapsedSeconds(elapsedSeconds: number): string;
|
|
11
|
+
export declare function formatWorkingStatusMessage(message: string, elapsedSeconds: number, interruptKey: string): string;
|
|
12
|
+
export declare function formatWorkingStatusTextFrame(statusMessage: string, animationElapsedMs: number, style: WorkingStatusTextFrameStyle): string;
|
|
13
|
+
export declare function formatWorkingStatusMessageFrame(message: string, elapsedSeconds: number, interruptKey: string, animationElapsedMs: number, style: WorkingStatusMessageFrameStyle): string;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=working-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"working-status.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/working-status.ts"],"names":[],"mappings":"AAIA,KAAK,2BAA2B,GAAG;IAClC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACtD,CAAC;AAEF,KAAK,8BAA8B,GAAG,2BAA2B,GAAG;IACnE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACjC,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAa1E;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhH;AAED,wBAAgB,4BAA4B,CAC3C,aAAa,EAAE,MAAM,EACrB,kBAAkB,EAAE,MAAM,EAC1B,KAAK,EAAE,2BAA2B,GAChC,MAAM,CAsCR;AAED,wBAAgB,+BAA+B,CAC9C,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,kBAAkB,EAAE,MAAM,EAC1B,KAAK,EAAE,8BAA8B,GACnC,MAAM,CAGR","sourcesContent":["const WORKING_STATUS_MESSAGE_SHIMMER_PADDING = 10;\nconst WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH = 5;\nconst WORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS = 2_000;\n\ntype WorkingStatusTextFrameStyle = {\n\tbase: (text: string) => string;\n\tglow: (text: string) => string;\n\thighlight: (text: string) => string;\n\tshimmer?: (text: string, intensity: number) => string;\n};\n\ntype WorkingStatusMessageFrameStyle = WorkingStatusTextFrameStyle & {\n\tsuffix: (text: string) => string;\n};\n\nexport function formatWorkingElapsedSeconds(elapsedSeconds: number): string {\n\tconst totalSeconds = Math.max(0, Math.floor(elapsedSeconds));\n\tconst seconds = totalSeconds % 60;\n\tconst totalMinutes = Math.floor(totalSeconds / 60);\n\tif (totalSeconds < 60) {\n\t\treturn `${totalSeconds}s`;\n\t}\n\tif (totalSeconds < 3600) {\n\t\treturn `${totalMinutes}m ${seconds.toString().padStart(2, \"0\")}s`;\n\t}\n\tconst hours = Math.floor(totalMinutes / 60);\n\tconst minutes = totalMinutes % 60;\n\treturn `${hours}h ${minutes.toString().padStart(2, \"0\")}m ${seconds.toString().padStart(2, \"0\")}s`;\n}\n\nexport function formatWorkingStatusMessage(message: string, elapsedSeconds: number, interruptKey: string): string {\n\treturn `${message} (${formatWorkingElapsedSeconds(elapsedSeconds)} • ${interruptKey} to interrupt)`;\n}\n\nexport function formatWorkingStatusTextFrame(\n\tstatusMessage: string,\n\tanimationElapsedMs: number,\n\tstyle: WorkingStatusTextFrameStyle,\n): string {\n\tconst chars = Array.from(statusMessage);\n\tif (chars.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst period = chars.length + WORKING_STATUS_MESSAGE_SHIMMER_PADDING * 2;\n\tconst sweepProgress =\n\t\t((Math.max(0, animationElapsedMs) % WORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS) /\n\t\t\tWORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS) *\n\t\tperiod;\n\n\treturn chars\n\t\t.map((char, index) => {\n\t\t\tif (char === \" \") {\n\t\t\t\treturn char;\n\t\t\t}\n\t\t\tconst distance = Math.abs(index + WORKING_STATUS_MESSAGE_SHIMMER_PADDING - sweepProgress);\n\t\t\tif (distance > WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH) {\n\t\t\t\tif (style.shimmer) {\n\t\t\t\t\treturn style.shimmer(char, 0);\n\t\t\t\t}\n\t\t\t\treturn style.base(char);\n\t\t\t}\n\n\t\t\tconst intensity = 0.5 * (1 + Math.cos(Math.PI * (distance / WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH)));\n\t\t\tif (style.shimmer) {\n\t\t\t\treturn style.shimmer(char, intensity);\n\t\t\t}\n\t\t\tif (intensity < 0.2) {\n\t\t\t\treturn style.base(char);\n\t\t\t}\n\t\t\tif (intensity < 0.6) {\n\t\t\t\treturn style.glow(char);\n\t\t\t}\n\t\t\treturn style.highlight(char);\n\t\t})\n\t\t.join(\"\");\n}\n\nexport function formatWorkingStatusMessageFrame(\n\tmessage: string,\n\telapsedSeconds: number,\n\tinterruptKey: string,\n\tanimationElapsedMs: number,\n\tstyle: WorkingStatusMessageFrameStyle,\n): string {\n\tconst suffix = ` (${formatWorkingElapsedSeconds(elapsedSeconds)} • ${interruptKey} to interrupt)`;\n\treturn `${formatWorkingStatusTextFrame(message, animationElapsedMs, style)}${style.suffix(suffix)}`;\n}\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const WORKING_STATUS_MESSAGE_SHIMMER_PADDING = 10;
|
|
2
|
+
const WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH = 5;
|
|
3
|
+
const WORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS = 2_000;
|
|
4
|
+
export function formatWorkingElapsedSeconds(elapsedSeconds) {
|
|
5
|
+
const totalSeconds = Math.max(0, Math.floor(elapsedSeconds));
|
|
6
|
+
const seconds = totalSeconds % 60;
|
|
7
|
+
const totalMinutes = Math.floor(totalSeconds / 60);
|
|
8
|
+
if (totalSeconds < 60) {
|
|
9
|
+
return `${totalSeconds}s`;
|
|
10
|
+
}
|
|
11
|
+
if (totalSeconds < 3600) {
|
|
12
|
+
return `${totalMinutes}m ${seconds.toString().padStart(2, "0")}s`;
|
|
13
|
+
}
|
|
14
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
15
|
+
const minutes = totalMinutes % 60;
|
|
16
|
+
return `${hours}h ${minutes.toString().padStart(2, "0")}m ${seconds.toString().padStart(2, "0")}s`;
|
|
17
|
+
}
|
|
18
|
+
export function formatWorkingStatusMessage(message, elapsedSeconds, interruptKey) {
|
|
19
|
+
return `${message} (${formatWorkingElapsedSeconds(elapsedSeconds)} • ${interruptKey} to interrupt)`;
|
|
20
|
+
}
|
|
21
|
+
export function formatWorkingStatusTextFrame(statusMessage, animationElapsedMs, style) {
|
|
22
|
+
const chars = Array.from(statusMessage);
|
|
23
|
+
if (chars.length === 0) {
|
|
24
|
+
return "";
|
|
25
|
+
}
|
|
26
|
+
const period = chars.length + WORKING_STATUS_MESSAGE_SHIMMER_PADDING * 2;
|
|
27
|
+
const sweepProgress = ((Math.max(0, animationElapsedMs) % WORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS) /
|
|
28
|
+
WORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS) *
|
|
29
|
+
period;
|
|
30
|
+
return chars
|
|
31
|
+
.map((char, index) => {
|
|
32
|
+
if (char === " ") {
|
|
33
|
+
return char;
|
|
34
|
+
}
|
|
35
|
+
const distance = Math.abs(index + WORKING_STATUS_MESSAGE_SHIMMER_PADDING - sweepProgress);
|
|
36
|
+
if (distance > WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH) {
|
|
37
|
+
if (style.shimmer) {
|
|
38
|
+
return style.shimmer(char, 0);
|
|
39
|
+
}
|
|
40
|
+
return style.base(char);
|
|
41
|
+
}
|
|
42
|
+
const intensity = 0.5 * (1 + Math.cos(Math.PI * (distance / WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH)));
|
|
43
|
+
if (style.shimmer) {
|
|
44
|
+
return style.shimmer(char, intensity);
|
|
45
|
+
}
|
|
46
|
+
if (intensity < 0.2) {
|
|
47
|
+
return style.base(char);
|
|
48
|
+
}
|
|
49
|
+
if (intensity < 0.6) {
|
|
50
|
+
return style.glow(char);
|
|
51
|
+
}
|
|
52
|
+
return style.highlight(char);
|
|
53
|
+
})
|
|
54
|
+
.join("");
|
|
55
|
+
}
|
|
56
|
+
export function formatWorkingStatusMessageFrame(message, elapsedSeconds, interruptKey, animationElapsedMs, style) {
|
|
57
|
+
const suffix = ` (${formatWorkingElapsedSeconds(elapsedSeconds)} • ${interruptKey} to interrupt)`;
|
|
58
|
+
return `${formatWorkingStatusTextFrame(message, animationElapsedMs, style)}${style.suffix(suffix)}`;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=working-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"working-status.js","sourceRoot":"","sources":["../../../src/modes/interactive/working-status.ts"],"names":[],"mappings":"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","sourcesContent":["const WORKING_STATUS_MESSAGE_SHIMMER_PADDING = 10;\nconst WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH = 5;\nconst WORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS = 2_000;\n\ntype WorkingStatusTextFrameStyle = {\n\tbase: (text: string) => string;\n\tglow: (text: string) => string;\n\thighlight: (text: string) => string;\n\tshimmer?: (text: string, intensity: number) => string;\n};\n\ntype WorkingStatusMessageFrameStyle = WorkingStatusTextFrameStyle & {\n\tsuffix: (text: string) => string;\n};\n\nexport function formatWorkingElapsedSeconds(elapsedSeconds: number): string {\n\tconst totalSeconds = Math.max(0, Math.floor(elapsedSeconds));\n\tconst seconds = totalSeconds % 60;\n\tconst totalMinutes = Math.floor(totalSeconds / 60);\n\tif (totalSeconds < 60) {\n\t\treturn `${totalSeconds}s`;\n\t}\n\tif (totalSeconds < 3600) {\n\t\treturn `${totalMinutes}m ${seconds.toString().padStart(2, \"0\")}s`;\n\t}\n\tconst hours = Math.floor(totalMinutes / 60);\n\tconst minutes = totalMinutes % 60;\n\treturn `${hours}h ${minutes.toString().padStart(2, \"0\")}m ${seconds.toString().padStart(2, \"0\")}s`;\n}\n\nexport function formatWorkingStatusMessage(message: string, elapsedSeconds: number, interruptKey: string): string {\n\treturn `${message} (${formatWorkingElapsedSeconds(elapsedSeconds)} • ${interruptKey} to interrupt)`;\n}\n\nexport function formatWorkingStatusTextFrame(\n\tstatusMessage: string,\n\tanimationElapsedMs: number,\n\tstyle: WorkingStatusTextFrameStyle,\n): string {\n\tconst chars = Array.from(statusMessage);\n\tif (chars.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst period = chars.length + WORKING_STATUS_MESSAGE_SHIMMER_PADDING * 2;\n\tconst sweepProgress =\n\t\t((Math.max(0, animationElapsedMs) % WORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS) /\n\t\t\tWORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS) *\n\t\tperiod;\n\n\treturn chars\n\t\t.map((char, index) => {\n\t\t\tif (char === \" \") {\n\t\t\t\treturn char;\n\t\t\t}\n\t\t\tconst distance = Math.abs(index + WORKING_STATUS_MESSAGE_SHIMMER_PADDING - sweepProgress);\n\t\t\tif (distance > WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH) {\n\t\t\t\tif (style.shimmer) {\n\t\t\t\t\treturn style.shimmer(char, 0);\n\t\t\t\t}\n\t\t\t\treturn style.base(char);\n\t\t\t}\n\n\t\t\tconst intensity = 0.5 * (1 + Math.cos(Math.PI * (distance / WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH)));\n\t\t\tif (style.shimmer) {\n\t\t\t\treturn style.shimmer(char, intensity);\n\t\t\t}\n\t\t\tif (intensity < 0.2) {\n\t\t\t\treturn style.base(char);\n\t\t\t}\n\t\t\tif (intensity < 0.6) {\n\t\t\t\treturn style.glow(char);\n\t\t\t}\n\t\t\treturn style.highlight(char);\n\t\t})\n\t\t.join(\"\");\n}\n\nexport function formatWorkingStatusMessageFrame(\n\tmessage: string,\n\telapsedSeconds: number,\n\tinterruptKey: string,\n\tanimationElapsedMs: number,\n\tstyle: WorkingStatusMessageFrameStyle,\n): string {\n\tconst suffix = ` (${formatWorkingElapsedSeconds(elapsedSeconds)} • ${interruptKey} to interrupt)`;\n\treturn `${formatWorkingStatusTextFrame(message, animationElapsedMs, style)}${style.suffix(suffix)}`;\n}\n"]}
|
package/docs/extensions.md
CHANGED
|
@@ -2576,7 +2576,6 @@ All examples in [examples/extensions/](../examples/extensions/).
|
|
|
2576
2576
|
| `ssh.ts` | SSH remote execution | `registerFlag`, `on("user_bash")`, `on("before_agent_start")`, tool operations |
|
|
2577
2577
|
| `interactive-shell.ts` | Persistent shell session | `on("user_bash")` |
|
|
2578
2578
|
| `sandbox/` | Sandboxed tool execution | Tool operations |
|
|
2579
|
-
| `subagent/` | Spawn sub-agents | `registerTool`, `exec` |
|
|
2580
2579
|
| **Games** |||
|
|
2581
2580
|
| `snake.ts` | Snake game | `registerCommand`, `ui.custom`, keyboard handling |
|
|
2582
2581
|
| `space-invaders.ts` | Space Invaders game | `registerCommand`, `ui.custom` |
|
package/docs/index.md
CHANGED
|
@@ -51,7 +51,6 @@ For the full first-run flow, see [Quickstart](quickstart.md).
|
|
|
51
51
|
## Reference
|
|
52
52
|
|
|
53
53
|
- [Session format](session-format.md) - JSONL session file format, entry types, and SessionManager API.
|
|
54
|
-
- [Agents](agents.md) - subagent profiles, custom agent definitions, and permission rules.
|
|
55
54
|
|
|
56
55
|
## Platform setup
|
|
57
56
|
|
package/docs/sdk.md
CHANGED
|
@@ -8,7 +8,6 @@ The SDK provides programmatic access to pi's agent capabilities. Use it to embed
|
|
|
8
8
|
- Build a custom UI (web, desktop, mobile)
|
|
9
9
|
- Integrate agent capabilities into existing applications
|
|
10
10
|
- Create automated pipelines with agent reasoning
|
|
11
|
-
- Build custom tools that spawn sub-agents
|
|
12
11
|
- Test agent behavior programmatically
|
|
13
12
|
|
|
14
13
|
See [examples/sdk/](../examples/sdk/) for working examples from minimal to full control.
|
package/docs/settings.md
CHANGED
|
@@ -266,28 +266,6 @@ Object form filters which resources to load:
|
|
|
266
266
|
|
|
267
267
|
See [packages.md](packages.md) for package management details.
|
|
268
268
|
|
|
269
|
-
### Agent Defaults
|
|
270
|
-
|
|
271
|
-
| Setting | Type | Default | Description |
|
|
272
|
-
|---------|------|---------|-------------|
|
|
273
|
-
| `agentDefaults.permission` | object | `{}` | Default tool permissions applied to all agents (lowest priority) |
|
|
274
|
-
| `agentDefaults.model` | string | - | Default model ID for agents spawned via `task()` |
|
|
275
|
-
|
|
276
|
-
Permission values: `"allow"`, `"deny"`, `"ask"`. See [agents.md](agents.md) for details.
|
|
277
|
-
|
|
278
|
-
```json
|
|
279
|
-
{
|
|
280
|
-
"agentDefaults": {
|
|
281
|
-
"permission": {
|
|
282
|
-
"edit": "ask",
|
|
283
|
-
"write": "ask",
|
|
284
|
-
"bash": "allow"
|
|
285
|
-
},
|
|
286
|
-
"model": "anthropic/claude-haiku-4-5"
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
```
|
|
290
|
-
|
|
291
269
|
## Example
|
|
292
270
|
|
|
293
271
|
```json
|
|
@@ -310,13 +288,7 @@ Permission values: `"allow"`, `"deny"`, `"ask"`. See [agents.md](agents.md) for
|
|
|
310
288
|
"warnings": {
|
|
311
289
|
"anthropicExtraUsage": true
|
|
312
290
|
},
|
|
313
|
-
"packages": ["pi-skills"]
|
|
314
|
-
"agentDefaults": {
|
|
315
|
-
"permission": {
|
|
316
|
-
"edit": "ask",
|
|
317
|
-
"write": "ask"
|
|
318
|
-
}
|
|
319
|
-
}
|
|
291
|
+
"packages": ["pi-skills"]
|
|
320
292
|
}
|
|
321
293
|
```
|
|
322
294
|
|
package/docs/termux.md
CHANGED
|
@@ -36,7 +36,7 @@ Image clipboard is not supported on Termux (the `ctrl+v` image paste feature wil
|
|
|
36
36
|
|
|
37
37
|
Create `~/.senpi/agent/AGENTS.md` to help the agent understand the Termux environment:
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
````markdown
|
|
40
40
|
# Agent Environment: Termux on Android
|
|
41
41
|
|
|
42
42
|
## Location
|
|
@@ -91,7 +91,7 @@ termux-camera-photo out.jpg # Take photo
|
|
|
91
91
|
- Termux:API app must be installed for `termux-*` commands
|
|
92
92
|
- Use `pkg install termux-api` for the command-line tools
|
|
93
93
|
- Storage permission needed for `/storage/emulated/0` access
|
|
94
|
-
|
|
94
|
+
````
|
|
95
95
|
|
|
96
96
|
## Limitations
|
|
97
97
|
|
package/docs/usage.md
CHANGED
|
@@ -272,6 +272,6 @@ pi --tools read,grep,find,ls -p "Review the code"
|
|
|
272
272
|
|
|
273
273
|
Pi keeps the core small and pushes workflow-specific behavior into extensions, skills, prompt templates, and packages.
|
|
274
274
|
|
|
275
|
-
It intentionally does not include built-in MCP,
|
|
275
|
+
It intentionally does not include built-in MCP, permission popups, plan mode, to-dos, or long-running shell orchestration. You can build or install those workflows as extensions or packages, or use external tools such as containers and tmux.
|
|
276
276
|
|
|
277
277
|
For the full rationale, read the [blog post](https://mariozechner.at/posts/2025-11-30-pi-coding-agent/).
|
package/examples/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Programmatic usage via `createAgentSession()`. Shows how to customize models, pr
|
|
|
10
10
|
### [extensions/](extensions/)
|
|
11
11
|
Example extensions demonstrating:
|
|
12
12
|
- Lifecycle event handlers (tool interception, safety gates, context modifications)
|
|
13
|
-
- Custom tools (todo lists, questions,
|
|
13
|
+
- Custom tools (todo lists, questions, output truncation)
|
|
14
14
|
- Commands and keyboard shortcuts
|
|
15
15
|
- Custom UI (footers, headers, editors, overlays)
|
|
16
16
|
- Git integration (checkpoints, auto-commit)
|
|
@@ -39,7 +39,6 @@ cp permission-gate.ts ~/.senpi/agent/extensions/
|
|
|
39
39
|
| `minimal-mode.ts` | Override built-in tool rendering for minimal display (only tool calls, no output in collapsed mode) |
|
|
40
40
|
| `truncated-tool.ts` | Wraps ripgrep with proper output truncation (50KB/2000 lines) |
|
|
41
41
|
| `ssh.ts` | Delegate all tools to a remote machine via SSH using pluggable operations |
|
|
42
|
-
| `subagent/` | Delegate tasks to specialized subagents with isolated context windows |
|
|
43
42
|
|
|
44
43
|
### Commands & UI
|
|
45
44
|
|
|
@@ -469,7 +469,7 @@ class StreamingOverflowComponent extends BaseOverlay {
|
|
|
469
469
|
"-c",
|
|
470
470
|
`
|
|
471
471
|
echo "Starting streaming overflow test (30+ seconds)..."
|
|
472
|
-
echo "This simulates
|
|
472
|
+
echo "This simulates streaming output with colors, hyperlinks, and long paths"
|
|
473
473
|
echo ""
|
|
474
474
|
for i in $(seq 1 100); do
|
|
475
475
|
# Simulate long file paths with OSC 8 hyperlinks (clickable) - tests width overflow
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/senpi",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.15-3",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piConfig": {
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@anthropic-ai/sdk": "^0.91.1",
|
|
43
|
-
"@earendil-works/pi-agent-core": "^2026.5.
|
|
44
|
-
"@earendil-works/pi-ai": "^2026.5.
|
|
45
|
-
"@earendil-works/pi-tui": "^2026.5.
|
|
43
|
+
"@earendil-works/pi-agent-core": "^2026.5.15-3",
|
|
44
|
+
"@earendil-works/pi-ai": "^2026.5.15-3",
|
|
45
|
+
"@earendil-works/pi-tui": "^2026.5.15-3",
|
|
46
46
|
"@silvia-odwyer/photon-node": "^0.3.4",
|
|
47
47
|
"chalk": "^5.5.0",
|
|
48
48
|
"diff": "^8.0.2",
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Type } from "typebox";
|
|
2
|
-
import type { ToolDefinition } from "../../types.js";
|
|
3
|
-
import type { BackgroundManager } from "./manager.js";
|
|
4
|
-
declare const BackgroundCancelParams: Type.TObject<{
|
|
5
|
-
taskId: Type.TOptional<Type.TString>;
|
|
6
|
-
all: Type.TOptional<Type.TBoolean>;
|
|
7
|
-
}>;
|
|
8
|
-
export declare function createBackgroundCancelTool(manager: BackgroundManager): ToolDefinition<typeof BackgroundCancelParams>;
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=cancel-tool.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cancel-tool.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/background-task/cancel-tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,QAAA,MAAM,sBAAsB;;;EAG1B,CAAC;AAEH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAAC,OAAO,sBAAsB,CAAC,CAmHpH","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport { Type } from \"typebox\";\nimport type { ToolDefinition } from \"../../types.js\";\nimport type { BackgroundManager } from \"./manager.js\";\n\nconst BackgroundCancelParams = Type.Object({\n\ttaskId: Type.Optional(Type.String({ description: \"Task ID to cancel (required if all=false)\" })),\n\tall: Type.Optional(Type.Boolean({ description: \"Cancel all running background tasks (default: false)\" })),\n});\n\nexport function createBackgroundCancelTool(manager: BackgroundManager): ToolDefinition<typeof BackgroundCancelParams> {\n\treturn {\n\t\tname: \"background_cancel\",\n\t\tlabel: \"BackgroundCancel\",\n\t\tdescription: \"Cancel a background task by taskId, or cancel all running tasks with all=true.\",\n\t\tpromptSnippet: \"Cancel background tasks by ID or cancel all running tasks.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use this tool to cancel pending or running background tasks.\",\n\t\t\t\"Provide taskId to cancel a specific task, or set all=true to cancel all active tasks.\",\n\t\t\t\"Cancelled tasks will be marked as 'cancelled' and cannot be resumed.\",\n\t\t],\n\t\tparameters: BackgroundCancelParams,\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate, _ctx) {\n\t\t\tif (!params.taskId && !params.all) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"Error: Provide taskId or set all=true\" }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (params.all) {\n\t\t\t\tconst cancelled = manager.cancelAll();\n\n\t\t\t\tif (cancelled.length === 0) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No active tasks to cancel\" }],\n\t\t\t\t\t\tdetails: { cancelledTasks: [] },\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tfor (const task of cancelled) {\n\t\t\t\t\tif (task.pid !== undefined) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tprocess.kill(task.pid, \"SIGTERM\");\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* process may already be dead */\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst lines: string[] = [`Cancelled ${cancelled.length} task(s):`];\n\t\t\t\tfor (const task of cancelled) {\n\t\t\t\t\tlines.push(`- ${task.id}: ${task.description}`);\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: lines.join(\"\\n\") }],\n\t\t\t\t\tdetails: { cancelledTasks: cancelled },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (params.taskId) {\n\t\t\t\tconst task = manager.getTask(params.taskId);\n\t\t\t\tif (!task) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Error: Task not found: ${params.taskId}` }],\n\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst wasCancelled = manager.cancelTask(params.taskId);\n\n\t\t\t\tif (!wasCancelled) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Task ${params.taskId} is not active (status: ${task.status})` }],\n\t\t\t\t\t\tdetails: { task },\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (task.pid !== undefined) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tprocess.kill(task.pid, \"SIGTERM\");\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t/* process may already be dead */\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst cancelledTask = manager.getTask(params.taskId);\n\t\t\t\tif (!cancelledTask) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Cancelled task ${params.taskId}` }],\n\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Cancelled task ${params.taskId}: ${cancelledTask.description}` }],\n\t\t\t\t\tdetails: { task: cancelledTask },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Error: Provide taskId or set all=true\" }],\n\t\t\t\tdetails: undefined,\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t},\n\t\trenderCall(args, theme) {\n\t\t\tif (args.all) {\n\t\t\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(\"BackgroundCancel \")) + theme.fg(\"accent\", \"[all]\"), 0, 0);\n\t\t\t}\n\t\t\treturn new Text(\n\t\t\t\ttheme.fg(\"toolTitle\", theme.bold(\"BackgroundCancel \")) + theme.fg(\"accent\", args.taskId ?? \"unknown\"),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t},\n\t\trenderResult(result, _options, theme) {\n\t\t\tconst firstContent = result.content[0];\n\t\t\tconst text = firstContent?.type === \"text\" ? firstContent.text : \"(no output)\";\n\t\t\treturn new Text(theme.fg(\"muted\", text), 0, 0);\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { Text } from "@earendil-works/pi-tui";
|
|
2
|
-
import { Type } from "typebox";
|
|
3
|
-
const BackgroundCancelParams = Type.Object({
|
|
4
|
-
taskId: Type.Optional(Type.String({ description: "Task ID to cancel (required if all=false)" })),
|
|
5
|
-
all: Type.Optional(Type.Boolean({ description: "Cancel all running background tasks (default: false)" })),
|
|
6
|
-
});
|
|
7
|
-
export function createBackgroundCancelTool(manager) {
|
|
8
|
-
return {
|
|
9
|
-
name: "background_cancel",
|
|
10
|
-
label: "BackgroundCancel",
|
|
11
|
-
description: "Cancel a background task by taskId, or cancel all running tasks with all=true.",
|
|
12
|
-
promptSnippet: "Cancel background tasks by ID or cancel all running tasks.",
|
|
13
|
-
promptGuidelines: [
|
|
14
|
-
"Use this tool to cancel pending or running background tasks.",
|
|
15
|
-
"Provide taskId to cancel a specific task, or set all=true to cancel all active tasks.",
|
|
16
|
-
"Cancelled tasks will be marked as 'cancelled' and cannot be resumed.",
|
|
17
|
-
],
|
|
18
|
-
parameters: BackgroundCancelParams,
|
|
19
|
-
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
20
|
-
if (!params.taskId && !params.all) {
|
|
21
|
-
return {
|
|
22
|
-
content: [{ type: "text", text: "Error: Provide taskId or set all=true" }],
|
|
23
|
-
details: undefined,
|
|
24
|
-
isError: true,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
if (params.all) {
|
|
28
|
-
const cancelled = manager.cancelAll();
|
|
29
|
-
if (cancelled.length === 0) {
|
|
30
|
-
return {
|
|
31
|
-
content: [{ type: "text", text: "No active tasks to cancel" }],
|
|
32
|
-
details: { cancelledTasks: [] },
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
for (const task of cancelled) {
|
|
36
|
-
if (task.pid !== undefined) {
|
|
37
|
-
try {
|
|
38
|
-
process.kill(task.pid, "SIGTERM");
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
/* process may already be dead */
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const lines = [`Cancelled ${cancelled.length} task(s):`];
|
|
46
|
-
for (const task of cancelled) {
|
|
47
|
-
lines.push(`- ${task.id}: ${task.description}`);
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
content: [{ type: "text", text: lines.join("\n") }],
|
|
51
|
-
details: { cancelledTasks: cancelled },
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
if (params.taskId) {
|
|
55
|
-
const task = manager.getTask(params.taskId);
|
|
56
|
-
if (!task) {
|
|
57
|
-
return {
|
|
58
|
-
content: [{ type: "text", text: `Error: Task not found: ${params.taskId}` }],
|
|
59
|
-
details: undefined,
|
|
60
|
-
isError: true,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
const wasCancelled = manager.cancelTask(params.taskId);
|
|
64
|
-
if (!wasCancelled) {
|
|
65
|
-
return {
|
|
66
|
-
content: [{ type: "text", text: `Task ${params.taskId} is not active (status: ${task.status})` }],
|
|
67
|
-
details: { task },
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
if (task.pid !== undefined) {
|
|
71
|
-
try {
|
|
72
|
-
process.kill(task.pid, "SIGTERM");
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
/* process may already be dead */
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
const cancelledTask = manager.getTask(params.taskId);
|
|
79
|
-
if (!cancelledTask) {
|
|
80
|
-
return {
|
|
81
|
-
content: [{ type: "text", text: `Cancelled task ${params.taskId}` }],
|
|
82
|
-
details: undefined,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
return {
|
|
86
|
-
content: [{ type: "text", text: `Cancelled task ${params.taskId}: ${cancelledTask.description}` }],
|
|
87
|
-
details: { task: cancelledTask },
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
return {
|
|
91
|
-
content: [{ type: "text", text: "Error: Provide taskId or set all=true" }],
|
|
92
|
-
details: undefined,
|
|
93
|
-
isError: true,
|
|
94
|
-
};
|
|
95
|
-
},
|
|
96
|
-
renderCall(args, theme) {
|
|
97
|
-
if (args.all) {
|
|
98
|
-
return new Text(theme.fg("toolTitle", theme.bold("BackgroundCancel ")) + theme.fg("accent", "[all]"), 0, 0);
|
|
99
|
-
}
|
|
100
|
-
return new Text(theme.fg("toolTitle", theme.bold("BackgroundCancel ")) + theme.fg("accent", args.taskId ?? "unknown"), 0, 0);
|
|
101
|
-
},
|
|
102
|
-
renderResult(result, _options, theme) {
|
|
103
|
-
const firstContent = result.content[0];
|
|
104
|
-
const text = firstContent?.type === "text" ? firstContent.text : "(no output)";
|
|
105
|
-
return new Text(theme.fg("muted", text), 0, 0);
|
|
106
|
-
},
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
//# sourceMappingURL=cancel-tool.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cancel-tool.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/background-task/cancel-tool.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport { Type } from \"typebox\";\nimport type { ToolDefinition } from \"../../types.js\";\nimport type { BackgroundManager } from \"./manager.js\";\n\nconst BackgroundCancelParams = Type.Object({\n\ttaskId: Type.Optional(Type.String({ description: \"Task ID to cancel (required if all=false)\" })),\n\tall: Type.Optional(Type.Boolean({ description: \"Cancel all running background tasks (default: false)\" })),\n});\n\nexport function createBackgroundCancelTool(manager: BackgroundManager): ToolDefinition<typeof BackgroundCancelParams> {\n\treturn {\n\t\tname: \"background_cancel\",\n\t\tlabel: \"BackgroundCancel\",\n\t\tdescription: \"Cancel a background task by taskId, or cancel all running tasks with all=true.\",\n\t\tpromptSnippet: \"Cancel background tasks by ID or cancel all running tasks.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use this tool to cancel pending or running background tasks.\",\n\t\t\t\"Provide taskId to cancel a specific task, or set all=true to cancel all active tasks.\",\n\t\t\t\"Cancelled tasks will be marked as 'cancelled' and cannot be resumed.\",\n\t\t],\n\t\tparameters: BackgroundCancelParams,\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate, _ctx) {\n\t\t\tif (!params.taskId && !params.all) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: \"Error: Provide taskId or set all=true\" }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (params.all) {\n\t\t\t\tconst cancelled = manager.cancelAll();\n\n\t\t\t\tif (cancelled.length === 0) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No active tasks to cancel\" }],\n\t\t\t\t\t\tdetails: { cancelledTasks: [] },\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tfor (const task of cancelled) {\n\t\t\t\t\tif (task.pid !== undefined) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tprocess.kill(task.pid, \"SIGTERM\");\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* process may already be dead */\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst lines: string[] = [`Cancelled ${cancelled.length} task(s):`];\n\t\t\t\tfor (const task of cancelled) {\n\t\t\t\t\tlines.push(`- ${task.id}: ${task.description}`);\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: lines.join(\"\\n\") }],\n\t\t\t\t\tdetails: { cancelledTasks: cancelled },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (params.taskId) {\n\t\t\t\tconst task = manager.getTask(params.taskId);\n\t\t\t\tif (!task) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Error: Task not found: ${params.taskId}` }],\n\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst wasCancelled = manager.cancelTask(params.taskId);\n\n\t\t\t\tif (!wasCancelled) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Task ${params.taskId} is not active (status: ${task.status})` }],\n\t\t\t\t\t\tdetails: { task },\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (task.pid !== undefined) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tprocess.kill(task.pid, \"SIGTERM\");\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t/* process may already be dead */\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst cancelledTask = manager.getTask(params.taskId);\n\t\t\t\tif (!cancelledTask) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Cancelled task ${params.taskId}` }],\n\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Cancelled task ${params.taskId}: ${cancelledTask.description}` }],\n\t\t\t\t\tdetails: { task: cancelledTask },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Error: Provide taskId or set all=true\" }],\n\t\t\t\tdetails: undefined,\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t},\n\t\trenderCall(args, theme) {\n\t\t\tif (args.all) {\n\t\t\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(\"BackgroundCancel \")) + theme.fg(\"accent\", \"[all]\"), 0, 0);\n\t\t\t}\n\t\t\treturn new Text(\n\t\t\t\ttheme.fg(\"toolTitle\", theme.bold(\"BackgroundCancel \")) + theme.fg(\"accent\", args.taskId ?? \"unknown\"),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t},\n\t\trenderResult(result, _options, theme) {\n\t\t\tconst firstContent = result.content[0];\n\t\t\tconst text = firstContent?.type === \"text\" ? firstContent.text : \"(no output)\";\n\t\t\treturn new Text(theme.fg(\"muted\", text), 0, 0);\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/background-task/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AA8LrE,MAAM,CAAC,OAAO,UAAU,uBAAuB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAiEtE","sourcesContent":["import type { ExtensionAPI, ExtensionContext } from \"../../types.js\";\nimport { sendBuiltinCustomMessage } from \"../system-messages.js\";\nimport { createBackgroundCancelTool } from \"./cancel-tool.js\";\nimport { BackgroundManager, getWidgetLines } from \"./manager.js\";\nimport { sendCompletionNotification } from \"./notification.js\";\nimport { createBackgroundOutputTool } from \"./output-tool.js\";\nimport { spawnSubagent } from \"./spawner.js\";\nimport { createTaskTool } from \"./task-tool.js\";\nimport { type BackgroundTask, TASK_ENTRY_TYPE } from \"./types.js\";\n\ntype SessionEntry = {\n\ttype: string;\n\tcustomType?: string;\n\tdata?: unknown;\n\tmessage?: unknown;\n};\n\nfunction isTaskStatus(value: unknown): value is BackgroundTask[\"status\"] {\n\treturn (\n\t\tvalue === \"pending\" || value === \"running\" || value === \"completed\" || value === \"error\" || value === \"cancelled\"\n\t);\n}\n\nfunction parseDate(value: unknown): Date | undefined {\n\tif (value === undefined) {\n\t\treturn undefined;\n\t}\n\n\tif (value instanceof Date) {\n\t\treturn Number.isNaN(value.getTime()) ? undefined : value;\n\t}\n\n\tif (typeof value !== \"string\") {\n\t\treturn undefined;\n\t}\n\n\tconst parsedDate = new Date(value);\n\treturn Number.isNaN(parsedDate.getTime()) ? undefined : parsedDate;\n}\n\nfunction parseBackgroundTask(value: unknown): BackgroundTask | undefined {\n\tif (typeof value !== \"object\" || value === null) {\n\t\treturn undefined;\n\t}\n\n\tconst taskRecord = value as Record<string, unknown>;\n\tconst startedAt = parseDate(taskRecord.startedAt);\n\tconst completedAt = parseDate(taskRecord.completedAt);\n\n\tif (\n\t\ttypeof taskRecord.id !== \"string\" ||\n\t\ttypeof taskRecord.description !== \"string\" ||\n\t\ttypeof taskRecord.prompt !== \"string\" ||\n\t\t!isTaskStatus(taskRecord.status) ||\n\t\t(taskRecord.model !== undefined && typeof taskRecord.model !== \"string\") ||\n\t\t(taskRecord.agentType !== undefined && typeof taskRecord.agentType !== \"string\") ||\n\t\t(taskRecord.pid !== undefined && typeof taskRecord.pid !== \"number\") ||\n\t\t(taskRecord.sessionPath !== undefined && typeof taskRecord.sessionPath !== \"string\") ||\n\t\t(taskRecord.activeToolNames !== undefined &&\n\t\t\t(!Array.isArray(taskRecord.activeToolNames) ||\n\t\t\t\ttaskRecord.activeToolNames.some((toolName) => typeof toolName !== \"string\"))) ||\n\t\tstartedAt === undefined ||\n\t\t(taskRecord.completedAt !== undefined && completedAt === undefined) ||\n\t\t(taskRecord.result !== undefined && typeof taskRecord.result !== \"string\") ||\n\t\t(taskRecord.error !== undefined && typeof taskRecord.error !== \"string\") ||\n\t\ttypeof taskRecord.parentSessionId !== \"string\"\n\t) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tid: taskRecord.id,\n\t\tdescription: taskRecord.description,\n\t\tprompt: taskRecord.prompt,\n\t\tmodel: taskRecord.model,\n\t\tagentType: taskRecord.agentType,\n\t\tstatus: taskRecord.status,\n\t\tpid: taskRecord.pid,\n\t\tsessionPath: taskRecord.sessionPath,\n\t\tactiveToolNames: Array.isArray(taskRecord.activeToolNames) ? taskRecord.activeToolNames : [],\n\t\tstartedAt,\n\t\tcompletedAt,\n\t\tresult: taskRecord.result,\n\t\terror: taskRecord.error,\n\t\tparentSessionId: taskRecord.parentSessionId,\n\t};\n}\n\nfunction isTerminalTask(task: BackgroundTask): boolean {\n\treturn task.status === \"completed\" || task.status === \"error\" || task.status === \"cancelled\";\n}\n\nfunction getRestoredTasks(entries: SessionEntry[]): BackgroundTask[] {\n\tconst restoredTasks = new Map<string, BackgroundTask>();\n\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"custom\" || entry.customType !== TASK_ENTRY_TYPE) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst task = parseBackgroundTask(entry.data);\n\t\tif (!task) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isTerminalTask(task)) {\n\t\t\trestoredTasks.set(task.id, task);\n\t\t} else {\n\t\t\trestoredTasks.delete(task.id);\n\t\t}\n\t}\n\n\treturn Array.from(restoredTasks.values());\n}\n\nfunction getCompletionTaskId(message: { content?: unknown }): string | undefined {\n\tif (!Array.isArray(message.content)) {\n\t\treturn undefined;\n\t}\n\n\tfor (const part of message.content) {\n\t\tif (typeof part !== \"object\" || part === null) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst contentPart = part as Record<string, unknown>;\n\t\tif (contentPart.type !== \"text\" || typeof contentPart.text !== \"string\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst match = contentPart.text.match(/\\b(bg_[0-9a-f]{8})\\b/);\n\t\tif (match?.[1]) {\n\t\t\treturn match[1];\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\nclass ObservableBackgroundManager extends BackgroundManager {\n\tconstructor(\n\t\tprivate readonly onChange: () => void,\n\t\tprivate readonly persistTask: (task: BackgroundTask) => void,\n\t) {\n\t\tsuper();\n\t}\n\n\toverride launch(task: Omit<BackgroundTask, \"id\" | \"status\" | \"startedAt\">): BackgroundTask {\n\t\tconst launchedTask = super.launch(task);\n\t\tthis.onChange();\n\t\treturn launchedTask;\n\t}\n\n\toverride updateTask(id: string, updates: Partial<BackgroundTask>): void {\n\t\tsuper.updateTask(id, updates);\n\t\tthis.onChange();\n\t}\n\n\toverride cancelTask(id: string): boolean {\n\t\tconst wasCancelled = super.cancelTask(id);\n\t\tif (wasCancelled) {\n\t\t\tconst cancelledTask = this.getTask(id);\n\t\t\tif (cancelledTask) {\n\t\t\t\tthis.persistTask(cancelledTask);\n\t\t\t}\n\t\t\tthis.onChange();\n\t\t}\n\t\treturn wasCancelled;\n\t}\n\n\toverride cancelAll(): BackgroundTask[] {\n\t\tconst cancelledTasks = super.cancelAll();\n\t\tfor (const task of cancelledTasks) {\n\t\t\tthis.persistTask(task);\n\t\t}\n\t\tif (cancelledTasks.length > 0) {\n\t\t\tthis.onChange();\n\t\t}\n\t\treturn cancelledTasks;\n\t}\n\n\treplaceTasks(tasks: BackgroundTask[]): void {\n\t\tthis.clearTasks();\n\t\tfor (const task of tasks) {\n\t\t\tthis.restoreTask(task);\n\t\t}\n\t\tthis.onChange();\n\t}\n}\n\nexport default function backgroundTaskExtension(pi: ExtensionAPI): void {\n\tlet currentContext: ExtensionContext | undefined;\n\n\tconst syncWidget = (): void => {\n\t\tcurrentContext?.ui.setWidget(\"background-tasks\", getWidgetLines(manager));\n\t};\n\n\tconst manager = new ObservableBackgroundManager(\n\t\t() => {\n\t\t\tsyncWidget();\n\t\t},\n\t\t(task) => {\n\t\t\tpi.appendEntry(TASK_ENTRY_TYPE, task);\n\t\t},\n\t);\n\n\tconst syncFromSession = (ctx: ExtensionContext): void => {\n\t\tcurrentContext = ctx;\n\t\tmanager.replaceTasks(getRestoredTasks(ctx.sessionManager.getBranch() as SessionEntry[]));\n\t};\n\n\tconst notifyingPi = {\n\t\t...pi,\n\t\tsendMessage(message, options) {\n\t\t\tif (message.customType === \"background-task.complete\") {\n\t\t\t\tconst taskId = getCompletionTaskId(message);\n\t\t\t\tif (taskId) {\n\t\t\t\t\tconst task = manager.getTask(taskId);\n\t\t\t\t\tif (task && isTerminalTask(task)) {\n\t\t\t\t\t\tsendCompletionNotification(pi, task, manager);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsendBuiltinCustomMessage(pi, \"background-task.notification\", message, options);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tpi.sendMessage(message, options);\n\t\t},\n\t} satisfies ExtensionAPI;\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tsyncFromSession(ctx);\n\t});\n\n\tpi.on(\"session_tree\", async (_event, ctx) => {\n\t\tsyncFromSession(ctx);\n\t});\n\n\tpi.registerTool(createTaskTool(manager, spawnSubagent, notifyingPi));\n\tpi.registerTool(createBackgroundOutputTool(manager));\n\tpi.registerTool(createBackgroundCancelTool(manager));\n\n\tprocess.on(\"exit\", () => {\n\t\tfor (const task of manager.getActiveTasks()) {\n\t\t\tif (task.pid === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tprocess.kill(task.pid, \"SIGTERM\");\n\t\t\t} catch {}\n\t\t}\n\t});\n}\n"]}
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { sendBuiltinCustomMessage } from "../system-messages.js";
|
|
2
|
-
import { createBackgroundCancelTool } from "./cancel-tool.js";
|
|
3
|
-
import { BackgroundManager, getWidgetLines } from "./manager.js";
|
|
4
|
-
import { sendCompletionNotification } from "./notification.js";
|
|
5
|
-
import { createBackgroundOutputTool } from "./output-tool.js";
|
|
6
|
-
import { spawnSubagent } from "./spawner.js";
|
|
7
|
-
import { createTaskTool } from "./task-tool.js";
|
|
8
|
-
import { TASK_ENTRY_TYPE } from "./types.js";
|
|
9
|
-
function isTaskStatus(value) {
|
|
10
|
-
return (value === "pending" || value === "running" || value === "completed" || value === "error" || value === "cancelled");
|
|
11
|
-
}
|
|
12
|
-
function parseDate(value) {
|
|
13
|
-
if (value === undefined) {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
if (value instanceof Date) {
|
|
17
|
-
return Number.isNaN(value.getTime()) ? undefined : value;
|
|
18
|
-
}
|
|
19
|
-
if (typeof value !== "string") {
|
|
20
|
-
return undefined;
|
|
21
|
-
}
|
|
22
|
-
const parsedDate = new Date(value);
|
|
23
|
-
return Number.isNaN(parsedDate.getTime()) ? undefined : parsedDate;
|
|
24
|
-
}
|
|
25
|
-
function parseBackgroundTask(value) {
|
|
26
|
-
if (typeof value !== "object" || value === null) {
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
29
|
-
const taskRecord = value;
|
|
30
|
-
const startedAt = parseDate(taskRecord.startedAt);
|
|
31
|
-
const completedAt = parseDate(taskRecord.completedAt);
|
|
32
|
-
if (typeof taskRecord.id !== "string" ||
|
|
33
|
-
typeof taskRecord.description !== "string" ||
|
|
34
|
-
typeof taskRecord.prompt !== "string" ||
|
|
35
|
-
!isTaskStatus(taskRecord.status) ||
|
|
36
|
-
(taskRecord.model !== undefined && typeof taskRecord.model !== "string") ||
|
|
37
|
-
(taskRecord.agentType !== undefined && typeof taskRecord.agentType !== "string") ||
|
|
38
|
-
(taskRecord.pid !== undefined && typeof taskRecord.pid !== "number") ||
|
|
39
|
-
(taskRecord.sessionPath !== undefined && typeof taskRecord.sessionPath !== "string") ||
|
|
40
|
-
(taskRecord.activeToolNames !== undefined &&
|
|
41
|
-
(!Array.isArray(taskRecord.activeToolNames) ||
|
|
42
|
-
taskRecord.activeToolNames.some((toolName) => typeof toolName !== "string"))) ||
|
|
43
|
-
startedAt === undefined ||
|
|
44
|
-
(taskRecord.completedAt !== undefined && completedAt === undefined) ||
|
|
45
|
-
(taskRecord.result !== undefined && typeof taskRecord.result !== "string") ||
|
|
46
|
-
(taskRecord.error !== undefined && typeof taskRecord.error !== "string") ||
|
|
47
|
-
typeof taskRecord.parentSessionId !== "string") {
|
|
48
|
-
return undefined;
|
|
49
|
-
}
|
|
50
|
-
return {
|
|
51
|
-
id: taskRecord.id,
|
|
52
|
-
description: taskRecord.description,
|
|
53
|
-
prompt: taskRecord.prompt,
|
|
54
|
-
model: taskRecord.model,
|
|
55
|
-
agentType: taskRecord.agentType,
|
|
56
|
-
status: taskRecord.status,
|
|
57
|
-
pid: taskRecord.pid,
|
|
58
|
-
sessionPath: taskRecord.sessionPath,
|
|
59
|
-
activeToolNames: Array.isArray(taskRecord.activeToolNames) ? taskRecord.activeToolNames : [],
|
|
60
|
-
startedAt,
|
|
61
|
-
completedAt,
|
|
62
|
-
result: taskRecord.result,
|
|
63
|
-
error: taskRecord.error,
|
|
64
|
-
parentSessionId: taskRecord.parentSessionId,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
function isTerminalTask(task) {
|
|
68
|
-
return task.status === "completed" || task.status === "error" || task.status === "cancelled";
|
|
69
|
-
}
|
|
70
|
-
function getRestoredTasks(entries) {
|
|
71
|
-
const restoredTasks = new Map();
|
|
72
|
-
for (const entry of entries) {
|
|
73
|
-
if (entry.type !== "custom" || entry.customType !== TASK_ENTRY_TYPE) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
const task = parseBackgroundTask(entry.data);
|
|
77
|
-
if (!task) {
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
if (isTerminalTask(task)) {
|
|
81
|
-
restoredTasks.set(task.id, task);
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
restoredTasks.delete(task.id);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return Array.from(restoredTasks.values());
|
|
88
|
-
}
|
|
89
|
-
function getCompletionTaskId(message) {
|
|
90
|
-
if (!Array.isArray(message.content)) {
|
|
91
|
-
return undefined;
|
|
92
|
-
}
|
|
93
|
-
for (const part of message.content) {
|
|
94
|
-
if (typeof part !== "object" || part === null) {
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
const contentPart = part;
|
|
98
|
-
if (contentPart.type !== "text" || typeof contentPart.text !== "string") {
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
const match = contentPart.text.match(/\b(bg_[0-9a-f]{8})\b/);
|
|
102
|
-
if (match?.[1]) {
|
|
103
|
-
return match[1];
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return undefined;
|
|
107
|
-
}
|
|
108
|
-
class ObservableBackgroundManager extends BackgroundManager {
|
|
109
|
-
onChange;
|
|
110
|
-
persistTask;
|
|
111
|
-
constructor(onChange, persistTask) {
|
|
112
|
-
super();
|
|
113
|
-
this.onChange = onChange;
|
|
114
|
-
this.persistTask = persistTask;
|
|
115
|
-
}
|
|
116
|
-
launch(task) {
|
|
117
|
-
const launchedTask = super.launch(task);
|
|
118
|
-
this.onChange();
|
|
119
|
-
return launchedTask;
|
|
120
|
-
}
|
|
121
|
-
updateTask(id, updates) {
|
|
122
|
-
super.updateTask(id, updates);
|
|
123
|
-
this.onChange();
|
|
124
|
-
}
|
|
125
|
-
cancelTask(id) {
|
|
126
|
-
const wasCancelled = super.cancelTask(id);
|
|
127
|
-
if (wasCancelled) {
|
|
128
|
-
const cancelledTask = this.getTask(id);
|
|
129
|
-
if (cancelledTask) {
|
|
130
|
-
this.persistTask(cancelledTask);
|
|
131
|
-
}
|
|
132
|
-
this.onChange();
|
|
133
|
-
}
|
|
134
|
-
return wasCancelled;
|
|
135
|
-
}
|
|
136
|
-
cancelAll() {
|
|
137
|
-
const cancelledTasks = super.cancelAll();
|
|
138
|
-
for (const task of cancelledTasks) {
|
|
139
|
-
this.persistTask(task);
|
|
140
|
-
}
|
|
141
|
-
if (cancelledTasks.length > 0) {
|
|
142
|
-
this.onChange();
|
|
143
|
-
}
|
|
144
|
-
return cancelledTasks;
|
|
145
|
-
}
|
|
146
|
-
replaceTasks(tasks) {
|
|
147
|
-
this.clearTasks();
|
|
148
|
-
for (const task of tasks) {
|
|
149
|
-
this.restoreTask(task);
|
|
150
|
-
}
|
|
151
|
-
this.onChange();
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
export default function backgroundTaskExtension(pi) {
|
|
155
|
-
let currentContext;
|
|
156
|
-
const syncWidget = () => {
|
|
157
|
-
currentContext?.ui.setWidget("background-tasks", getWidgetLines(manager));
|
|
158
|
-
};
|
|
159
|
-
const manager = new ObservableBackgroundManager(() => {
|
|
160
|
-
syncWidget();
|
|
161
|
-
}, (task) => {
|
|
162
|
-
pi.appendEntry(TASK_ENTRY_TYPE, task);
|
|
163
|
-
});
|
|
164
|
-
const syncFromSession = (ctx) => {
|
|
165
|
-
currentContext = ctx;
|
|
166
|
-
manager.replaceTasks(getRestoredTasks(ctx.sessionManager.getBranch()));
|
|
167
|
-
};
|
|
168
|
-
const notifyingPi = {
|
|
169
|
-
...pi,
|
|
170
|
-
sendMessage(message, options) {
|
|
171
|
-
if (message.customType === "background-task.complete") {
|
|
172
|
-
const taskId = getCompletionTaskId(message);
|
|
173
|
-
if (taskId) {
|
|
174
|
-
const task = manager.getTask(taskId);
|
|
175
|
-
if (task && isTerminalTask(task)) {
|
|
176
|
-
sendCompletionNotification(pi, task, manager);
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
sendBuiltinCustomMessage(pi, "background-task.notification", message, options);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
pi.sendMessage(message, options);
|
|
184
|
-
},
|
|
185
|
-
};
|
|
186
|
-
pi.on("session_start", async (_event, ctx) => {
|
|
187
|
-
syncFromSession(ctx);
|
|
188
|
-
});
|
|
189
|
-
pi.on("session_tree", async (_event, ctx) => {
|
|
190
|
-
syncFromSession(ctx);
|
|
191
|
-
});
|
|
192
|
-
pi.registerTool(createTaskTool(manager, spawnSubagent, notifyingPi));
|
|
193
|
-
pi.registerTool(createBackgroundOutputTool(manager));
|
|
194
|
-
pi.registerTool(createBackgroundCancelTool(manager));
|
|
195
|
-
process.on("exit", () => {
|
|
196
|
-
for (const task of manager.getActiveTasks()) {
|
|
197
|
-
if (task.pid === undefined) {
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
try {
|
|
201
|
-
process.kill(task.pid, "SIGTERM");
|
|
202
|
-
}
|
|
203
|
-
catch { }
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
//# sourceMappingURL=index.js.map
|