@astralyn/pi 0.84.3 → 0.84.5
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 +54 -0
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +11 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-command.d.ts.map +1 -1
- package/dist/cli/auth-command.js +5 -4
- package/dist/cli/auth-command.js.map +1 -1
- package/dist/cli/project-trust.d.ts.map +1 -1
- package/dist/cli/project-trust.js +1 -4
- package/dist/cli/project-trust.js.map +1 -1
- package/dist/core/agent-session.d.ts +6 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +7 -6
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/experimental.d.ts +4 -0
- package/dist/core/experimental.d.ts.map +1 -1
- package/dist/core/experimental.js +4 -0
- package/dist/core/experimental.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.map +1 -1
- package/dist/core/extensions/runner.js +4 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +10 -14
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +29 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +4 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-config.d.ts +5 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +1 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts +2 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +4 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/project-trust.js +2 -2
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/sdk.d.ts +5 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +2 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.js +2 -2
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +6 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +12 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +3 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +2 -0
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +2 -0
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +2 -0
- package/dist/core/tools/write.js.map +1 -1
- package/dist/extensions/background/index.d.ts +74 -0
- package/dist/extensions/background/index.d.ts.map +1 -0
- package/dist/extensions/background/index.js +332 -0
- package/dist/extensions/background/index.js.map +1 -0
- package/dist/extensions/background/manager.d.ts +81 -0
- package/dist/extensions/background/manager.d.ts.map +1 -0
- package/dist/extensions/background/manager.js +320 -0
- package/dist/extensions/background/manager.js.map +1 -0
- package/dist/extensions/background/registry.d.ts +138 -0
- package/dist/extensions/background/registry.d.ts.map +1 -0
- package/dist/extensions/background/registry.js +358 -0
- package/dist/extensions/background/registry.js.map +1 -0
- package/dist/extensions/background/render.d.ts +26 -0
- package/dist/extensions/background/render.d.ts.map +1 -0
- package/dist/extensions/background/render.js +118 -0
- package/dist/extensions/background/render.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/subagent/activity.d.ts +0 -1
- package/dist/extensions/subagent/activity.d.ts.map +1 -1
- package/dist/extensions/subagent/activity.js +2 -5
- package/dist/extensions/subagent/activity.js.map +1 -1
- package/dist/extensions/subagent/agents-command.d.ts +4 -0
- package/dist/extensions/subagent/agents-command.d.ts.map +1 -0
- package/dist/extensions/subagent/agents-command.js +385 -0
- package/dist/extensions/subagent/agents-command.js.map +1 -0
- package/dist/extensions/subagent/agents.d.ts +3 -6
- package/dist/extensions/subagent/agents.d.ts.map +1 -1
- package/dist/extensions/subagent/agents.js +22 -190
- package/dist/extensions/subagent/agents.js.map +1 -1
- package/dist/extensions/subagent/constants.d.ts +4 -5
- package/dist/extensions/subagent/constants.d.ts.map +1 -1
- package/dist/extensions/subagent/constants.js +11 -7
- package/dist/extensions/subagent/constants.js.map +1 -1
- package/dist/extensions/subagent/index.d.ts +0 -3
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +58 -315
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent/render.d.ts +1 -1
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +208 -585
- package/dist/extensions/subagent/render.js.map +1 -1
- package/dist/extensions/subagent/resolve.d.ts +2 -2
- package/dist/extensions/subagent/resolve.d.ts.map +1 -1
- package/dist/extensions/subagent/resolve.js +23 -15
- package/dist/extensions/subagent/resolve.js.map +1 -1
- package/dist/extensions/subagent/runner.d.ts +1 -2
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +109 -131
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/schema.d.ts +4 -10
- package/dist/extensions/subagent/schema.d.ts.map +1 -1
- package/dist/extensions/subagent/schema.js +8 -13
- 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 +9 -20
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/settings.d.ts +2 -3
- package/dist/extensions/subagent/settings.d.ts.map +1 -1
- package/dist/extensions/subagent/settings.js +30 -21
- package/dist/extensions/subagent/settings.js.map +1 -1
- package/dist/extensions/subagent/text.d.ts +3 -0
- package/dist/extensions/subagent/text.d.ts.map +1 -0
- package/dist/extensions/subagent/text.js +16 -0
- package/dist/extensions/subagent/text.js.map +1 -0
- package/dist/extensions/subagent/types.d.ts +13 -33
- package/dist/extensions/subagent/types.d.ts.map +1 -1
- package/dist/extensions/subagent/types.js.map +1 -1
- package/dist/extensions/subagent/ui/model-list.d.ts +68 -0
- package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/model-list.js +248 -0
- package/dist/extensions/subagent/ui/model-list.js.map +1 -0
- package/dist/extensions/todo/constants.d.ts +6 -17
- package/dist/extensions/todo/constants.d.ts.map +1 -1
- package/dist/extensions/todo/constants.js +20 -31
- package/dist/extensions/todo/constants.js.map +1 -1
- package/dist/extensions/todo/index.d.ts.map +1 -1
- package/dist/extensions/todo/index.js +36 -57
- package/dist/extensions/todo/index.js.map +1 -1
- package/dist/extensions/todo/schema.d.ts +20 -59
- package/dist/extensions/todo/schema.d.ts.map +1 -1
- package/dist/extensions/todo/schema.js +23 -69
- package/dist/extensions/todo/schema.js.map +1 -1
- package/dist/extensions/todo/state.d.ts +23 -65
- package/dist/extensions/todo/state.d.ts.map +1 -1
- package/dist/extensions/todo/state.js +238 -1262
- package/dist/extensions/todo/state.js.map +1 -1
- package/dist/extensions/todo/view.d.ts +19 -10
- package/dist/extensions/todo/view.d.ts.map +1 -1
- package/dist/extensions/todo/view.js +411 -463
- package/dist/extensions/todo/view.js.map +1 -1
- package/dist/extensions/todo/widget.d.ts +15 -0
- package/dist/extensions/todo/widget.d.ts.map +1 -0
- package/dist/extensions/todo/widget.js +50 -0
- package/dist/extensions/todo/widget.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +5 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +1 -2
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +5 -11
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +2 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- 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 +8 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +77 -25
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
- package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
- package/dist/modes/interactive/model-catalog-refresh.js +36 -0
- package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
- package/dist/modes/interactive/theme/dark.json +2 -0
- package/dist/modes/interactive/theme/light.json +2 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +23 -10
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +9 -1
- package/dist/modes/interactive/theme/theme.d.ts +5 -3
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +12 -2
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +4 -1
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +5 -2
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +1 -8
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/package-manager-cli.js +1 -1
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/server/create-harness.d.ts.map +1 -1
- package/dist/server/create-harness.js +2 -0
- package/dist/server/create-harness.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +10 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +14 -19
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/bundled/README.md +2 -1
- package/docs/bundled/extensions/background.md +64 -0
- package/docs/bundled/extensions/subagent.md +84 -57
- package/docs/bundled/extensions/todo.md +84 -24
- package/docs/bundled/tool-presentation.md +1 -1
- package/docs/compaction.md +6 -6
- package/docs/custom-provider.md +1 -1
- package/docs/docs.json +4 -0
- package/docs/environment-variables.md +8 -2
- package/docs/extensions.md +6 -2
- package/docs/json.md +6 -4
- package/docs/keybindings.md +9 -2
- package/docs/rpc.md +15 -4
- package/docs/sdk.md +9 -0
- package/docs/settings.md +31 -0
- package/docs/terminal-setup.md +23 -2
- package/docs/themes.md +24 -3
- package/docs/tui.md +2 -2
- package/docs/usage.md +4 -3
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +170 -221
- package/package.json +6 -6
- package/dist/extensions/subagent/picker.d.ts +0 -31
- package/dist/extensions/subagent/picker.d.ts.map +0 -1
- package/dist/extensions/subagent/picker.js +0 -109
- package/dist/extensions/subagent/picker.js.map +0 -1
- package/dist/extensions/todo/overlay.d.ts +0 -24
- package/dist/extensions/todo/overlay.d.ts.map +0 -1
- package/dist/extensions/todo/overlay.js +0 -135
- package/dist/extensions/todo/overlay.js.map +0 -1
- package/examples/extensions/subagent/README.md +0 -175
- 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 -1009
- 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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astralyn/pi",
|
|
3
|
-
"version": "0.84.
|
|
3
|
+
"version": "0.84.5",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piConfig": {
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
"prepublishOnly": "npm run clean && npm run build"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@earendil-works/pi-agent-core": "0.84.
|
|
56
|
-
"@earendil-works/pi-ai": "0.84.
|
|
57
|
-
"@earendil-works/pi-client": "0.84.
|
|
58
|
-
"@earendil-works/pi-protocol": "0.84.
|
|
59
|
-
"@earendil-works/pi-tui": "0.84.
|
|
55
|
+
"@earendil-works/pi-agent-core": "0.84.2",
|
|
56
|
+
"@earendil-works/pi-ai": "0.84.2",
|
|
57
|
+
"@earendil-works/pi-client": "0.84.2",
|
|
58
|
+
"@earendil-works/pi-protocol": "0.84.2",
|
|
59
|
+
"@earendil-works/pi-tui": "0.84.2",
|
|
60
60
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
61
61
|
"chalk": "5.6.2",
|
|
62
62
|
"cross-spawn": "7.0.6",
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Container, type Focusable } from "@earendil-works/pi-tui";
|
|
2
|
-
import type { Theme } from "../../modes/interactive/theme/theme.ts";
|
|
3
|
-
export interface PickerItem<T> {
|
|
4
|
-
value: T;
|
|
5
|
-
label: string;
|
|
6
|
-
detail?: string;
|
|
7
|
-
current?: boolean;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Searchable selector matching the native /model experience: type to
|
|
11
|
-
* fuzzy-filter, arrows wrap around the list, enter confirms, escape
|
|
12
|
-
* cancels (resolves undefined). Mounted via ctx.ui.custom().
|
|
13
|
-
*/
|
|
14
|
-
export declare class SearchPickerComponent<T> extends Container implements Focusable {
|
|
15
|
-
private readonly theme;
|
|
16
|
-
private readonly items;
|
|
17
|
-
private readonly onDone;
|
|
18
|
-
private readonly searchInput;
|
|
19
|
-
private readonly listContainer;
|
|
20
|
-
private filtered;
|
|
21
|
-
private selectedIndex;
|
|
22
|
-
private _focused;
|
|
23
|
-
get focused(): boolean;
|
|
24
|
-
set focused(value: boolean);
|
|
25
|
-
constructor(theme: Theme, title: string, items: PickerItem<T>[], onDone: (value: T | undefined) => void);
|
|
26
|
-
private filter;
|
|
27
|
-
private confirm;
|
|
28
|
-
private updateList;
|
|
29
|
-
handleInput(keyData: string): void;
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=picker.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"picker.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/picker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAoD,MAAM,wBAAwB,CAAC;AAGrH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAEpE,MAAM,WAAW,UAAU,CAAC,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAID;;;;GAIG;AACH,qBAAa,qBAAqB,CAAC,CAAC,CAAE,SAAQ,SAAU,YAAW,SAAS;IAC3E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;IACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAY;IAC1C,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,aAAa,CAAK;IAE1B,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;gBAEW,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI;IA8BvG,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,UAAU;IAiClB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAmBlC"}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { Container, fuzzyFilter, getKeybindings, Input, Spacer, Text } from "@earendil-works/pi-tui";
|
|
2
|
-
import { DynamicBorder } from "../../modes/interactive/components/dynamic-border.js";
|
|
3
|
-
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
4
|
-
const MAX_VISIBLE = 10;
|
|
5
|
-
/**
|
|
6
|
-
* Searchable selector matching the native /model experience: type to
|
|
7
|
-
* fuzzy-filter, arrows wrap around the list, enter confirms, escape
|
|
8
|
-
* cancels (resolves undefined). Mounted via ctx.ui.custom().
|
|
9
|
-
*/
|
|
10
|
-
export class SearchPickerComponent extends Container {
|
|
11
|
-
get focused() {
|
|
12
|
-
return this._focused;
|
|
13
|
-
}
|
|
14
|
-
set focused(value) {
|
|
15
|
-
this._focused = value;
|
|
16
|
-
this.searchInput.focused = value;
|
|
17
|
-
}
|
|
18
|
-
constructor(theme, title, items, onDone) {
|
|
19
|
-
super();
|
|
20
|
-
this.selectedIndex = 0;
|
|
21
|
-
this._focused = false;
|
|
22
|
-
this.theme = theme;
|
|
23
|
-
this.items = items;
|
|
24
|
-
this.onDone = onDone;
|
|
25
|
-
this.filtered = items;
|
|
26
|
-
const currentIndex = items.findIndex((item) => item.current);
|
|
27
|
-
if (currentIndex >= 0)
|
|
28
|
-
this.selectedIndex = currentIndex;
|
|
29
|
-
this.addChild(new DynamicBorder());
|
|
30
|
-
this.addChild(new Spacer(1));
|
|
31
|
-
this.addChild(new Text(theme.fg("toolTitle", theme.bold(title)), 0, 0));
|
|
32
|
-
this.addChild(new Spacer(1));
|
|
33
|
-
this.searchInput = new Input();
|
|
34
|
-
this.addChild(this.searchInput);
|
|
35
|
-
this.addChild(new Spacer(1));
|
|
36
|
-
this.listContainer = new Container();
|
|
37
|
-
this.addChild(this.listContainer);
|
|
38
|
-
this.addChild(new Spacer(1));
|
|
39
|
-
this.addChild(new Text(`${theme.fg("muted", "↑↓")} ${theme.fg("dim", "navigate")} ${keyHint("tui.select.confirm", "select")} ${keyHint("tui.select.cancel", "cancel")}`, 0, 0));
|
|
40
|
-
this.addChild(new DynamicBorder());
|
|
41
|
-
this.updateList();
|
|
42
|
-
}
|
|
43
|
-
filter(query) {
|
|
44
|
-
this.filtered = query
|
|
45
|
-
? fuzzyFilter(this.items, query, (item) => `${item.label} ${item.detail ?? ""}`)
|
|
46
|
-
: this.items;
|
|
47
|
-
this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filtered.length - 1));
|
|
48
|
-
this.updateList();
|
|
49
|
-
}
|
|
50
|
-
confirm() {
|
|
51
|
-
const selected = this.filtered[this.selectedIndex];
|
|
52
|
-
if (selected)
|
|
53
|
-
this.onDone(selected.value);
|
|
54
|
-
}
|
|
55
|
-
updateList() {
|
|
56
|
-
this.listContainer.clear();
|
|
57
|
-
const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(MAX_VISIBLE / 2), this.filtered.length - MAX_VISIBLE));
|
|
58
|
-
const endIndex = Math.min(startIndex + MAX_VISIBLE, this.filtered.length);
|
|
59
|
-
for (let index = startIndex; index < endIndex; index++) {
|
|
60
|
-
const item = this.filtered[index];
|
|
61
|
-
if (!item)
|
|
62
|
-
continue;
|
|
63
|
-
const isSelected = index === this.selectedIndex;
|
|
64
|
-
const marker = item.current ? this.theme.fg("success", " ✓") : "";
|
|
65
|
-
const line = isSelected
|
|
66
|
-
? `${this.theme.fg("accent", "→ ")}${this.theme.fg("accent", item.label)}${marker}`
|
|
67
|
-
: ` ${item.label}${marker}`;
|
|
68
|
-
this.listContainer.addChild(new Text(line, 0, 0));
|
|
69
|
-
}
|
|
70
|
-
if (startIndex > 0 || endIndex < this.filtered.length) {
|
|
71
|
-
this.listContainer.addChild(new Text(this.theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filtered.length})`), 0, 0));
|
|
72
|
-
}
|
|
73
|
-
if (this.filtered.length === 0) {
|
|
74
|
-
this.listContainer.addChild(new Text(this.theme.fg("muted", " No matches"), 0, 0));
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const detail = this.filtered[this.selectedIndex]?.detail;
|
|
78
|
-
if (detail) {
|
|
79
|
-
this.listContainer.addChild(new Spacer(1));
|
|
80
|
-
this.listContainer.addChild(new Text(this.theme.fg("muted", ` ${detail}`), 0, 0));
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
handleInput(keyData) {
|
|
84
|
-
const kb = getKeybindings();
|
|
85
|
-
if (kb.matches(keyData, "tui.select.up")) {
|
|
86
|
-
if (this.filtered.length === 0)
|
|
87
|
-
return;
|
|
88
|
-
this.selectedIndex = this.selectedIndex === 0 ? this.filtered.length - 1 : this.selectedIndex - 1;
|
|
89
|
-
this.updateList();
|
|
90
|
-
}
|
|
91
|
-
else if (kb.matches(keyData, "tui.select.down")) {
|
|
92
|
-
if (this.filtered.length === 0)
|
|
93
|
-
return;
|
|
94
|
-
this.selectedIndex = this.selectedIndex === this.filtered.length - 1 ? 0 : this.selectedIndex + 1;
|
|
95
|
-
this.updateList();
|
|
96
|
-
}
|
|
97
|
-
else if (kb.matches(keyData, "tui.select.confirm")) {
|
|
98
|
-
this.confirm();
|
|
99
|
-
}
|
|
100
|
-
else if (kb.matches(keyData, "tui.select.cancel")) {
|
|
101
|
-
this.onDone(undefined);
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
this.searchInput.handleInput(keyData);
|
|
105
|
-
this.filter(this.searchInput.getValue());
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
//# sourceMappingURL=picker.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"picker.js","sourceRoot":"","sources":["../../../src/extensions/subagent/picker.ts"],"names":[],"mappings":"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","sourcesContent":["import { Container, type Focusable, fuzzyFilter, getKeybindings, Input, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport { DynamicBorder } from \"../../modes/interactive/components/dynamic-border.ts\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\n\nexport interface PickerItem<T> {\n\tvalue: T;\n\tlabel: string;\n\tdetail?: string;\n\tcurrent?: boolean;\n}\n\nconst MAX_VISIBLE = 10;\n\n/**\n * Searchable selector matching the native /model experience: type to\n * fuzzy-filter, arrows wrap around the list, enter confirms, escape\n * cancels (resolves undefined). Mounted via ctx.ui.custom().\n */\nexport class SearchPickerComponent<T> extends Container implements Focusable {\n\tprivate readonly theme: Theme;\n\tprivate readonly items: PickerItem<T>[];\n\tprivate readonly onDone: (value: T | undefined) => void;\n\tprivate readonly searchInput: Input;\n\tprivate readonly listContainer: Container;\n\tprivate filtered: PickerItem<T>[];\n\tprivate selectedIndex = 0;\n\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tconstructor(theme: Theme, title: string, items: PickerItem<T>[], onDone: (value: T | undefined) => void) {\n\t\tsuper();\n\t\tthis.theme = theme;\n\t\tthis.items = items;\n\t\tthis.onDone = onDone;\n\t\tthis.filtered = items;\n\t\tconst currentIndex = items.findIndex((item) => item.current);\n\t\tif (currentIndex >= 0) this.selectedIndex = currentIndex;\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.fg(\"toolTitle\", theme.bold(title)), 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.searchInput = new Input();\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(\n\t\t\tnew Text(\n\t\t\t\t`${theme.fg(\"muted\", \"↑↓\")} ${theme.fg(\"dim\", \"navigate\")} ${keyHint(\"tui.select.confirm\", \"select\")} ${keyHint(\"tui.select.cancel\", \"cancel\")}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.updateList();\n\t}\n\n\tprivate filter(query: string): void {\n\t\tthis.filtered = query\n\t\t\t? fuzzyFilter(this.items, query, (item) => `${item.label} ${item.detail ?? \"\"}`)\n\t\t\t: this.items;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filtered.length - 1));\n\t\tthis.updateList();\n\t}\n\n\tprivate confirm(): void {\n\t\tconst selected = this.filtered[this.selectedIndex];\n\t\tif (selected) this.onDone(selected.value);\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(MAX_VISIBLE / 2), this.filtered.length - MAX_VISIBLE),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + MAX_VISIBLE, this.filtered.length);\n\t\tfor (let index = startIndex; index < endIndex; index++) {\n\t\t\tconst item = this.filtered[index];\n\t\t\tif (!item) continue;\n\t\t\tconst isSelected = index === this.selectedIndex;\n\t\t\tconst marker = item.current ? this.theme.fg(\"success\", \" ✓\") : \"\";\n\t\t\tconst line = isSelected\n\t\t\t\t? `${this.theme.fg(\"accent\", \"→ \")}${this.theme.fg(\"accent\", item.label)}${marker}`\n\t\t\t\t: ` ${item.label}${marker}`;\n\t\t\tthis.listContainer.addChild(new Text(line, 0, 0));\n\t\t}\n\t\tif (startIndex > 0 || endIndex < this.filtered.length) {\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(this.theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filtered.length})`), 0, 0),\n\t\t\t);\n\t\t}\n\t\tif (this.filtered.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(this.theme.fg(\"muted\", \" No matches\"), 0, 0));\n\t\t\treturn;\n\t\t}\n\t\tconst detail = this.filtered[this.selectedIndex]?.detail;\n\t\tif (detail) {\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(this.theme.fg(\"muted\", ` ${detail}`), 0, 0));\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.filtered.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.filtered.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t} else if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.filtered.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.filtered.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t} else if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tthis.confirm();\n\t\t} else if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onDone(undefined);\n\t\t} else {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filter(this.searchInput.getValue());\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { ExtensionUIContext } from "../../core/extensions/types.ts";
|
|
2
|
-
export declare class TodoOverlay {
|
|
3
|
-
private ui;
|
|
4
|
-
private tui;
|
|
5
|
-
private registered;
|
|
6
|
-
private knownStatuses;
|
|
7
|
-
private completedAt;
|
|
8
|
-
private hiddenCompleted;
|
|
9
|
-
private completionHideTimer;
|
|
10
|
-
/** Pure render cache: same width + visibility state → skip rebuild. */
|
|
11
|
-
private cachedWidth;
|
|
12
|
-
private cachedLines;
|
|
13
|
-
setUI(ui: ExtensionUIContext): void;
|
|
14
|
-
resetVisibility(): void;
|
|
15
|
-
update(): void;
|
|
16
|
-
/** Track new completions for a short confirmation window; hide historical ones. */
|
|
17
|
-
private syncVisibilityFromState;
|
|
18
|
-
private scheduleCompletionHide;
|
|
19
|
-
private clearCompletionHideTimer;
|
|
20
|
-
private invalidateRenderCache;
|
|
21
|
-
private render;
|
|
22
|
-
dispose(): void;
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=overlay.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/overlay.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAUzE,qBAAa,WAAW;IACvB,OAAO,CAAC,EAAE,CAAiC;IAC3C,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,mBAAmB,CAA4C;IACvE,uEAAuE;IACvE,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,WAAW,CAAuB;IAE1C,KAAK,CAAC,EAAE,EAAE,kBAAkB,GAAG,IAAI;IAMnC,eAAe,IAAI,IAAI;IAQvB,MAAM,IAAI,IAAI;IAoCd,mFAAmF;IACnF,OAAO,CAAC,uBAAuB;IAyC/B,OAAO,CAAC,sBAAsB;IAiB9B,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,MAAM;IAUd,OAAO,IAAI,IAAI;CAOf"}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { getTodoState } from "./state.js";
|
|
2
|
-
import { hasVisibleOverlayItems, renderOverlayLines } from "./view.js";
|
|
3
|
-
const WIDGET_KEY = "todos";
|
|
4
|
-
const RECENT_COMPLETION_MS = 30_000;
|
|
5
|
-
export class TodoOverlay {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.registered = false;
|
|
8
|
-
this.knownStatuses = new Map();
|
|
9
|
-
this.completedAt = new Map();
|
|
10
|
-
this.hiddenCompleted = new Set();
|
|
11
|
-
}
|
|
12
|
-
setUI(ui) {
|
|
13
|
-
if (this.ui === ui)
|
|
14
|
-
return;
|
|
15
|
-
this.dispose();
|
|
16
|
-
this.ui = ui;
|
|
17
|
-
}
|
|
18
|
-
resetVisibility() {
|
|
19
|
-
this.clearCompletionHideTimer();
|
|
20
|
-
this.knownStatuses.clear();
|
|
21
|
-
this.completedAt.clear();
|
|
22
|
-
this.hiddenCompleted.clear();
|
|
23
|
-
this.invalidateRenderCache();
|
|
24
|
-
}
|
|
25
|
-
update() {
|
|
26
|
-
if (!this.ui)
|
|
27
|
-
return;
|
|
28
|
-
const state = getTodoState();
|
|
29
|
-
this.syncVisibilityFromState(state);
|
|
30
|
-
this.invalidateRenderCache();
|
|
31
|
-
// Register/unregister based on state, never as a render side effect.
|
|
32
|
-
if (!hasVisibleOverlayItems(state, this.hiddenCompleted)) {
|
|
33
|
-
if (this.registered)
|
|
34
|
-
this.ui.setWidget(WIDGET_KEY, undefined);
|
|
35
|
-
this.registered = false;
|
|
36
|
-
this.tui = undefined;
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (!this.registered) {
|
|
40
|
-
this.ui.setWidget(WIDGET_KEY, (tui, theme) => {
|
|
41
|
-
this.tui = tui;
|
|
42
|
-
return {
|
|
43
|
-
render: (width) => this.render(theme, width),
|
|
44
|
-
invalidate: () => {
|
|
45
|
-
this.registered = false;
|
|
46
|
-
this.tui = undefined;
|
|
47
|
-
this.invalidateRenderCache();
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
}, { placement: "aboveEditor" });
|
|
51
|
-
this.registered = true;
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
this.tui?.requestRender();
|
|
55
|
-
}
|
|
56
|
-
/** Track new completions for a short confirmation window; hide historical ones. */
|
|
57
|
-
syncVisibilityFromState(state) {
|
|
58
|
-
const now = Date.now();
|
|
59
|
-
const nextStatuses = new Map();
|
|
60
|
-
for (const item of state.items) {
|
|
61
|
-
nextStatuses.set(item.id, item.status);
|
|
62
|
-
const previousStatus = this.knownStatuses.get(item.id);
|
|
63
|
-
if (item.status !== "completed") {
|
|
64
|
-
this.completedAt.delete(item.id);
|
|
65
|
-
this.hiddenCompleted.delete(item.id);
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
if (previousStatus === undefined) {
|
|
69
|
-
// A replayed/reloaded completion is old from this overlay's point of
|
|
70
|
-
// view. Keep the live surface focused on current work.
|
|
71
|
-
this.hiddenCompleted.add(item.id);
|
|
72
|
-
this.completedAt.delete(item.id);
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
if (previousStatus !== "completed") {
|
|
76
|
-
this.completedAt.set(item.id, now);
|
|
77
|
-
this.hiddenCompleted.delete(item.id);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
for (const id of this.knownStatuses.keys()) {
|
|
81
|
-
if (nextStatuses.has(id))
|
|
82
|
-
continue;
|
|
83
|
-
this.completedAt.delete(id);
|
|
84
|
-
this.hiddenCompleted.delete(id);
|
|
85
|
-
}
|
|
86
|
-
this.knownStatuses = nextStatuses;
|
|
87
|
-
for (const [id, completedAt] of this.completedAt) {
|
|
88
|
-
if (now - completedAt < RECENT_COMPLETION_MS)
|
|
89
|
-
continue;
|
|
90
|
-
this.completedAt.delete(id);
|
|
91
|
-
this.hiddenCompleted.add(id);
|
|
92
|
-
}
|
|
93
|
-
this.scheduleCompletionHide();
|
|
94
|
-
}
|
|
95
|
-
scheduleCompletionHide() {
|
|
96
|
-
this.clearCompletionHideTimer();
|
|
97
|
-
let earliestExpiry = Infinity;
|
|
98
|
-
for (const completedAt of this.completedAt.values()) {
|
|
99
|
-
earliestExpiry = Math.min(earliestExpiry, completedAt + RECENT_COMPLETION_MS);
|
|
100
|
-
}
|
|
101
|
-
if (!Number.isFinite(earliestExpiry))
|
|
102
|
-
return;
|
|
103
|
-
this.completionHideTimer = setTimeout(() => {
|
|
104
|
-
this.completionHideTimer = undefined;
|
|
105
|
-
this.update();
|
|
106
|
-
}, Math.max(10, earliestExpiry - Date.now()));
|
|
107
|
-
}
|
|
108
|
-
clearCompletionHideTimer() {
|
|
109
|
-
if (this.completionHideTimer === undefined)
|
|
110
|
-
return;
|
|
111
|
-
clearTimeout(this.completionHideTimer);
|
|
112
|
-
this.completionHideTimer = undefined;
|
|
113
|
-
}
|
|
114
|
-
invalidateRenderCache() {
|
|
115
|
-
this.cachedWidth = undefined;
|
|
116
|
-
this.cachedLines = undefined;
|
|
117
|
-
}
|
|
118
|
-
render(theme, width) {
|
|
119
|
-
const normalizedWidth = Math.max(1, width);
|
|
120
|
-
if (this.cachedLines !== undefined && this.cachedWidth === normalizedWidth)
|
|
121
|
-
return this.cachedLines;
|
|
122
|
-
const lines = renderOverlayLines(getTodoState(), theme, normalizedWidth, this.hiddenCompleted);
|
|
123
|
-
this.cachedWidth = normalizedWidth;
|
|
124
|
-
this.cachedLines = lines;
|
|
125
|
-
return lines;
|
|
126
|
-
}
|
|
127
|
-
dispose() {
|
|
128
|
-
this.ui?.setWidget(WIDGET_KEY, undefined);
|
|
129
|
-
this.tui = undefined;
|
|
130
|
-
this.registered = false;
|
|
131
|
-
this.ui = undefined;
|
|
132
|
-
this.resetVisibility();
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
//# sourceMappingURL=overlay.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../../src/extensions/todo/overlay.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TUI } from \"@earendil-works/pi-tui\";\nimport type { ExtensionUIContext } from \"../../core/extensions/types.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\n\nimport type { TodoState, TodoStatus } from \"./schema.ts\";\nimport { getTodoState } from \"./state.ts\";\nimport { hasVisibleOverlayItems, renderOverlayLines } from \"./view.ts\";\n\nconst WIDGET_KEY = \"todos\";\nconst RECENT_COMPLETION_MS = 30_000;\n\nexport class TodoOverlay {\n\tprivate ui: ExtensionUIContext | undefined;\n\tprivate tui: TUI | undefined;\n\tprivate registered = false;\n\tprivate knownStatuses = new Map<number, TodoStatus>();\n\tprivate completedAt = new Map<number, number>();\n\tprivate hiddenCompleted = new Set<number>();\n\tprivate completionHideTimer: ReturnType<typeof setTimeout> | undefined;\n\t/** Pure render cache: same width + visibility state → skip rebuild. */\n\tprivate cachedWidth: number | undefined;\n\tprivate cachedLines: string[] | undefined;\n\n\tsetUI(ui: ExtensionUIContext): void {\n\t\tif (this.ui === ui) return;\n\t\tthis.dispose();\n\t\tthis.ui = ui;\n\t}\n\n\tresetVisibility(): void {\n\t\tthis.clearCompletionHideTimer();\n\t\tthis.knownStatuses.clear();\n\t\tthis.completedAt.clear();\n\t\tthis.hiddenCompleted.clear();\n\t\tthis.invalidateRenderCache();\n\t}\n\n\tupdate(): void {\n\t\tif (!this.ui) return;\n\t\tconst state = getTodoState();\n\t\tthis.syncVisibilityFromState(state);\n\t\tthis.invalidateRenderCache();\n\n\t\t// Register/unregister based on state, never as a render side effect.\n\t\tif (!hasVisibleOverlayItems(state, this.hiddenCompleted)) {\n\t\t\tif (this.registered) this.ui.setWidget(WIDGET_KEY, undefined);\n\t\t\tthis.registered = false;\n\t\t\tthis.tui = undefined;\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.registered) {\n\t\t\tthis.ui.setWidget(\n\t\t\t\tWIDGET_KEY,\n\t\t\t\t(tui, theme) => {\n\t\t\t\t\tthis.tui = tui;\n\t\t\t\t\treturn {\n\t\t\t\t\t\trender: (width: number) => this.render(theme, width),\n\t\t\t\t\t\tinvalidate: () => {\n\t\t\t\t\t\t\tthis.registered = false;\n\t\t\t\t\t\t\tthis.tui = undefined;\n\t\t\t\t\t\t\tthis.invalidateRenderCache();\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t{ placement: \"aboveEditor\" },\n\t\t\t);\n\t\t\tthis.registered = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.tui?.requestRender();\n\t}\n\n\t/** Track new completions for a short confirmation window; hide historical ones. */\n\tprivate syncVisibilityFromState(state: TodoState): void {\n\t\tconst now = Date.now();\n\t\tconst nextStatuses = new Map<number, TodoStatus>();\n\n\t\tfor (const item of state.items) {\n\t\t\tnextStatuses.set(item.id, item.status);\n\t\t\tconst previousStatus = this.knownStatuses.get(item.id);\n\t\t\tif (item.status !== \"completed\") {\n\t\t\t\tthis.completedAt.delete(item.id);\n\t\t\t\tthis.hiddenCompleted.delete(item.id);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (previousStatus === undefined) {\n\t\t\t\t// A replayed/reloaded completion is old from this overlay's point of\n\t\t\t\t// view. Keep the live surface focused on current work.\n\t\t\t\tthis.hiddenCompleted.add(item.id);\n\t\t\t\tthis.completedAt.delete(item.id);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (previousStatus !== \"completed\") {\n\t\t\t\tthis.completedAt.set(item.id, now);\n\t\t\t\tthis.hiddenCompleted.delete(item.id);\n\t\t\t}\n\t\t}\n\n\t\tfor (const id of this.knownStatuses.keys()) {\n\t\t\tif (nextStatuses.has(id)) continue;\n\t\t\tthis.completedAt.delete(id);\n\t\t\tthis.hiddenCompleted.delete(id);\n\t\t}\n\t\tthis.knownStatuses = nextStatuses;\n\n\t\tfor (const [id, completedAt] of this.completedAt) {\n\t\t\tif (now - completedAt < RECENT_COMPLETION_MS) continue;\n\t\t\tthis.completedAt.delete(id);\n\t\t\tthis.hiddenCompleted.add(id);\n\t\t}\n\t\tthis.scheduleCompletionHide();\n\t}\n\n\tprivate scheduleCompletionHide(): void {\n\t\tthis.clearCompletionHideTimer();\n\t\tlet earliestExpiry = Infinity;\n\t\tfor (const completedAt of this.completedAt.values()) {\n\t\t\tearliestExpiry = Math.min(earliestExpiry, completedAt + RECENT_COMPLETION_MS);\n\t\t}\n\t\tif (!Number.isFinite(earliestExpiry)) return;\n\n\t\tthis.completionHideTimer = setTimeout(\n\t\t\t() => {\n\t\t\t\tthis.completionHideTimer = undefined;\n\t\t\t\tthis.update();\n\t\t\t},\n\t\t\tMath.max(10, earliestExpiry - Date.now()),\n\t\t);\n\t}\n\n\tprivate clearCompletionHideTimer(): void {\n\t\tif (this.completionHideTimer === undefined) return;\n\t\tclearTimeout(this.completionHideTimer);\n\t\tthis.completionHideTimer = undefined;\n\t}\n\n\tprivate invalidateRenderCache(): void {\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tprivate render(theme: Theme, width: number): string[] {\n\t\tconst normalizedWidth = Math.max(1, width);\n\t\tif (this.cachedLines !== undefined && this.cachedWidth === normalizedWidth) return this.cachedLines;\n\n\t\tconst lines = renderOverlayLines(getTodoState(), theme, normalizedWidth, this.hiddenCompleted);\n\t\tthis.cachedWidth = normalizedWidth;\n\t\tthis.cachedLines = lines;\n\t\treturn lines;\n\t}\n\n\tdispose(): void {\n\t\tthis.ui?.setWidget(WIDGET_KEY, undefined);\n\t\tthis.tui = undefined;\n\t\tthis.registered = false;\n\t\tthis.ui = undefined;\n\t\tthis.resetVisibility();\n\t}\n}\n"]}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
# Subagent Example
|
|
2
|
-
|
|
3
|
-
Delegate tasks to specialized subagents with isolated context windows.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Isolated context**: Each subagent runs in a separate `pi` process
|
|
8
|
-
- **Streaming output**: See tool calls and progress as they happen
|
|
9
|
-
- **Parallel streaming**: All parallel tasks stream updates simultaneously
|
|
10
|
-
- **Markdown rendering**: Final output rendered with proper formatting (expanded view)
|
|
11
|
-
- **Usage tracking**: Shows turns, tokens, cost, and context usage per agent
|
|
12
|
-
- **Abort support**: Ctrl+C propagates to kill subagent processes
|
|
13
|
-
|
|
14
|
-
## Structure
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
subagent/
|
|
18
|
-
├── README.md # This file
|
|
19
|
-
├── index.ts # The extension (entry point)
|
|
20
|
-
├── agents.ts # Agent discovery logic
|
|
21
|
-
├── agents/ # Sample agent definitions
|
|
22
|
-
│ ├── scout.md # Fast recon, returns compressed context
|
|
23
|
-
│ ├── planner.md # Creates implementation plans
|
|
24
|
-
│ ├── reviewer.md # Code review
|
|
25
|
-
│ └── worker.md # General-purpose (full capabilities)
|
|
26
|
-
└── prompts/ # Workflow presets (prompt templates)
|
|
27
|
-
├── implement.md # scout -> planner -> worker
|
|
28
|
-
├── scout-and-plan.md # scout -> planner (no implementation)
|
|
29
|
-
└── implement-and-review.md # worker -> reviewer -> worker
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Installation
|
|
33
|
-
|
|
34
|
-
From the repository root, symlink the files:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
# Symlink the extension (must be in a subdirectory with index.ts)
|
|
38
|
-
mkdir -p ~/.pi/agent/extensions/subagent
|
|
39
|
-
ln -sf "$(pwd)/examples/extensions/subagent/index.ts" ~/.pi/agent/extensions/subagent/index.ts
|
|
40
|
-
ln -sf "$(pwd)/examples/extensions/subagent/agents.ts" ~/.pi/agent/extensions/subagent/agents.ts
|
|
41
|
-
|
|
42
|
-
# Symlink agents
|
|
43
|
-
mkdir -p ~/.pi/agent/agents
|
|
44
|
-
for f in examples/extensions/subagent/agents/*.md; do
|
|
45
|
-
ln -sf "$(pwd)/$f" ~/.pi/agent/agents/$(basename "$f")
|
|
46
|
-
done
|
|
47
|
-
|
|
48
|
-
# Symlink workflow prompts
|
|
49
|
-
mkdir -p ~/.pi/agent/prompts
|
|
50
|
-
for f in examples/extensions/subagent/prompts/*.md; do
|
|
51
|
-
ln -sf "$(pwd)/$f" ~/.pi/agent/prompts/$(basename "$f")
|
|
52
|
-
done
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Security Model
|
|
56
|
-
|
|
57
|
-
This tool executes a separate `pi` subprocess with a delegated system prompt and tool/model configuration.
|
|
58
|
-
|
|
59
|
-
**Project-local agents** (`.pi/agents/*.md`) are repo-controlled prompts that can instruct the model to read files, run bash commands, etc.
|
|
60
|
-
|
|
61
|
-
**Default behavior:** Only loads **user-level agents** from `~/.pi/agent/agents`.
|
|
62
|
-
|
|
63
|
-
To enable project-local agents, pass `agentScope: "both"` (or `"project"`). Only do this for repositories you trust.
|
|
64
|
-
|
|
65
|
-
When running interactively, the tool prompts for confirmation before running project-local agents. Set `confirmProjectAgents: false` to disable.
|
|
66
|
-
|
|
67
|
-
## Usage
|
|
68
|
-
|
|
69
|
-
### Single agent
|
|
70
|
-
```
|
|
71
|
-
Use scout to find all authentication code
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Parallel execution
|
|
75
|
-
```
|
|
76
|
-
Run 2 scouts in parallel: one to find models, one to find providers
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### Chained workflow
|
|
80
|
-
```
|
|
81
|
-
Use a chain: first have scout find the read tool, then have planner suggest improvements
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Workflow prompts
|
|
85
|
-
```
|
|
86
|
-
/implement add Redis caching to the session store
|
|
87
|
-
/scout-and-plan refactor auth to support OAuth
|
|
88
|
-
/implement-and-review add input validation to API endpoints
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## Tool Modes
|
|
92
|
-
|
|
93
|
-
| Mode | Parameter | Description |
|
|
94
|
-
|------|-----------|-------------|
|
|
95
|
-
| Single | `{ agent, task }` | One agent, one task |
|
|
96
|
-
| Parallel | `{ tasks: [...] }` | Multiple agents run concurrently (max 8, 4 concurrent) |
|
|
97
|
-
| Chain | `{ chain: [...] }` | Sequential with `{previous}` placeholder |
|
|
98
|
-
|
|
99
|
-
## Output Display
|
|
100
|
-
|
|
101
|
-
**Collapsed view** (default):
|
|
102
|
-
- Status icon (✓/✗/⏳) and agent name
|
|
103
|
-
- Last 5-10 items (tool calls and text)
|
|
104
|
-
- Usage stats: `3 turns ↑input ↓output RcacheRead WcacheWrite $cost ctx:contextTokens model`
|
|
105
|
-
|
|
106
|
-
**Expanded view** (Ctrl+O):
|
|
107
|
-
- Full task text
|
|
108
|
-
- All tool calls with formatted arguments
|
|
109
|
-
- Final output rendered as Markdown
|
|
110
|
-
- Per-task usage (for chain/parallel)
|
|
111
|
-
|
|
112
|
-
**Parallel mode streaming**:
|
|
113
|
-
- Shows all tasks with live status (⏳ running, ✓ done, ✗ failed)
|
|
114
|
-
- Updates as each task makes progress
|
|
115
|
-
- Shows "2/3 done, 1 running" status
|
|
116
|
-
- Returns each completed task's final output to the parent model, capped at 50 KB per task
|
|
117
|
-
- Returns failure diagnostics from stderr/error messages when a child exits before producing output
|
|
118
|
-
|
|
119
|
-
**Tool call formatting** (mimics built-in tools):
|
|
120
|
-
- `$ command` for bash
|
|
121
|
-
- `read ~/path:1-10` for read
|
|
122
|
-
- `grep /pattern/ in ~/path` for grep
|
|
123
|
-
- etc.
|
|
124
|
-
|
|
125
|
-
## Agent Definitions
|
|
126
|
-
|
|
127
|
-
Agents are markdown files with YAML frontmatter:
|
|
128
|
-
|
|
129
|
-
```markdown
|
|
130
|
-
---
|
|
131
|
-
name: my-agent
|
|
132
|
-
description: What this agent does
|
|
133
|
-
tools: read, grep, find, ls
|
|
134
|
-
model: claude-haiku-4-5
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
System prompt for the agent goes here.
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
**Locations:**
|
|
141
|
-
- `~/.pi/agent/agents/*.md` - User-level (always loaded)
|
|
142
|
-
- `.pi/agents/*.md` - Project-level (only with `agentScope: "project"` or `"both"`)
|
|
143
|
-
|
|
144
|
-
Project agents override user agents with the same name when `agentScope: "both"`.
|
|
145
|
-
|
|
146
|
-
## Sample Agents
|
|
147
|
-
|
|
148
|
-
| Agent | Purpose | Model | Tools |
|
|
149
|
-
|-------|---------|-------|-------|
|
|
150
|
-
| `scout` | Fast codebase recon | Haiku | read, grep, find, ls, bash |
|
|
151
|
-
| `planner` | Implementation plans | Sonnet | read, grep, find, ls |
|
|
152
|
-
| `reviewer` | Code review | Sonnet | read, grep, find, ls, bash |
|
|
153
|
-
| `worker` | General-purpose | Sonnet | (all default) |
|
|
154
|
-
|
|
155
|
-
## Workflow Prompts
|
|
156
|
-
|
|
157
|
-
| Prompt | Flow |
|
|
158
|
-
|--------|------|
|
|
159
|
-
| `/implement <query>` | scout → planner → worker |
|
|
160
|
-
| `/scout-and-plan <query>` | scout → planner |
|
|
161
|
-
| `/implement-and-review <query>` | worker → reviewer → worker |
|
|
162
|
-
|
|
163
|
-
## Error Handling
|
|
164
|
-
|
|
165
|
-
- **Exit code != 0**: Tool returns error with stderr/output
|
|
166
|
-
- **stopReason "error"**: LLM error propagated with error message
|
|
167
|
-
- **stopReason "aborted"**: User abort (Ctrl+C) kills subprocess, throws error
|
|
168
|
-
- **Chain mode**: Stops at first failing step, reports which step failed
|
|
169
|
-
|
|
170
|
-
## Limitations
|
|
171
|
-
|
|
172
|
-
- Output truncated to last 10 items in collapsed view (expand to see all)
|
|
173
|
-
- Parallel model-visible output is capped at 50 KB per task; full results remain in tool details
|
|
174
|
-
- Agents discovered fresh on each invocation (allows editing mid-session)
|
|
175
|
-
- Parallel mode limited to 8 tasks, 4 concurrent
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: planner
|
|
3
|
-
description: Creates implementation plans from context and requirements
|
|
4
|
-
tools: read, grep, find, ls
|
|
5
|
-
model: claude-sonnet-4-5
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
You are a planning specialist. You receive context (from a scout) and requirements, then produce a clear implementation plan.
|
|
9
|
-
|
|
10
|
-
You must NOT make any changes. Only read, analyze, and plan.
|
|
11
|
-
|
|
12
|
-
Input format you'll receive:
|
|
13
|
-
- Context/findings from a scout agent
|
|
14
|
-
- Original query or requirements
|
|
15
|
-
|
|
16
|
-
Output format:
|
|
17
|
-
|
|
18
|
-
## Goal
|
|
19
|
-
One sentence summary of what needs to be done.
|
|
20
|
-
|
|
21
|
-
## Plan
|
|
22
|
-
Numbered steps, each small and actionable:
|
|
23
|
-
1. Step one - specific file/function to modify
|
|
24
|
-
2. Step two - what to add/change
|
|
25
|
-
3. ...
|
|
26
|
-
|
|
27
|
-
## Files to Modify
|
|
28
|
-
- `path/to/file.ts` - what changes
|
|
29
|
-
- `path/to/other.ts` - what changes
|
|
30
|
-
|
|
31
|
-
## New Files (if any)
|
|
32
|
-
- `path/to/new.ts` - purpose
|
|
33
|
-
|
|
34
|
-
## Risks
|
|
35
|
-
Anything to watch out for.
|
|
36
|
-
|
|
37
|
-
Keep the plan concrete. The worker agent will execute it verbatim.
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: reviewer
|
|
3
|
-
description: Code review specialist for quality and security analysis
|
|
4
|
-
tools: read, grep, find, ls, bash
|
|
5
|
-
model: claude-sonnet-4-5
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
You are a senior code reviewer. Analyze code for quality, security, and maintainability.
|
|
9
|
-
|
|
10
|
-
Bash is for read-only commands only: `git diff`, `git log`, `git show`. Do NOT modify files or run builds.
|
|
11
|
-
Assume tool permissions are not perfectly enforceable; keep all bash usage strictly read-only.
|
|
12
|
-
|
|
13
|
-
Strategy:
|
|
14
|
-
1. Run `git diff` to see recent changes (if applicable)
|
|
15
|
-
2. Read the modified files
|
|
16
|
-
3. Check for bugs, security issues, code smells
|
|
17
|
-
|
|
18
|
-
Output format:
|
|
19
|
-
|
|
20
|
-
## Files Reviewed
|
|
21
|
-
- `path/to/file.ts` (lines X-Y)
|
|
22
|
-
|
|
23
|
-
## Critical (must fix)
|
|
24
|
-
- `file.ts:42` - Issue description
|
|
25
|
-
|
|
26
|
-
## Warnings (should fix)
|
|
27
|
-
- `file.ts:100` - Issue description
|
|
28
|
-
|
|
29
|
-
## Suggestions (consider)
|
|
30
|
-
- `file.ts:150` - Improvement idea
|
|
31
|
-
|
|
32
|
-
## Summary
|
|
33
|
-
Overall assessment in 2-3 sentences.
|
|
34
|
-
|
|
35
|
-
Be specific with file paths and line numbers.
|