@codex-infinity/pi-infinity 0.52.4 → 0.60.2
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 +387 -0
- package/README.md +97 -66
- package/dist/bun/cli.d.ts +3 -0
- package/dist/bun/cli.d.ts.map +1 -0
- package/dist/bun/cli.js +6 -0
- package/dist/bun/cli.js.map +1 -0
- package/dist/bun/register-bedrock.d.ts +2 -0
- package/dist/bun/register-bedrock.d.ts.map +1 -0
- package/dist/bun/register-bedrock.js +4 -0
- package/dist/bun/register-bedrock.js.map +1 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +17 -6
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/initial-message.d.ts +18 -0
- package/dist/cli/initial-message.d.ts.map +1 -0
- package/dist/cli/initial-message.js +22 -0
- package/dist/cli/initial-message.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session.d.ts +42 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +346 -72
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +1 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +27 -2
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts +6 -7
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +8 -107
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +1 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +6 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +3 -0
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +16 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +7 -3
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/index.d.ts +5 -2
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +4 -3
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.js +11 -14
- package/dist/core/export-html/tool-renderer.d.ts +5 -2
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +17 -4
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +37 -11
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +8 -4
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +77 -8
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +56 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts +4 -11
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +4 -78
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +6 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +83 -37
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +3 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +22 -12
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-registry.d.ts +11 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +56 -16
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +6 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +122 -39
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +19 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +290 -57
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +43 -8
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +4 -7
- package/dist/core/resource-loader.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 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +1 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +21 -15
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +10 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +59 -5
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +3 -2
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +29 -8
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +3 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts +4 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +43 -29
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +8 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +77 -69
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +1 -0
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +6 -3
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +116 -36
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +5 -2
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +9 -0
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +8 -23
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +1 -1
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +1 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +1 -1
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +1 -1
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +15 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +5 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +5 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +5 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +7 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +158 -7
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +21 -2
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +127 -10
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +1 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +12 -0
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +5 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +215 -71
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +5 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/rpc/jsonl.d.ts +17 -0
- package/dist/modes/rpc/jsonl.d.ts.map +1 -0
- package/dist/modes/rpc/jsonl.js +49 -0
- package/dist/modes/rpc/jsonl.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -11
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +9 -11
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/child-process.d.ts +11 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +78 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +94 -11
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +1 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +27 -16
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts +5 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -0
- package/dist/utils/exif-orientation.js +158 -0
- package/dist/utils/exif-orientation.js.map +1 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +5 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +6 -1
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +66 -21
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/compaction.md +2 -0
- package/docs/custom-provider.md +57 -9
- package/docs/extensions.md +125 -12
- package/docs/keybindings.md +11 -1
- package/docs/models.md +44 -2
- package/docs/packages.md +9 -0
- package/docs/providers.md +10 -1
- package/docs/rpc.md +44 -7
- package/docs/sdk.md +2 -2
- package/docs/settings.md +11 -0
- package/docs/terminal-setup.md +39 -3
- package/docs/tmux.md +61 -0
- package/docs/tree.md +9 -0
- package/examples/extensions/README.md +2 -0
- package/examples/extensions/antigravity-image-gen.ts +8 -5
- package/examples/extensions/built-in-tool-renderer.ts +246 -0
- 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/custom-provider-gitlab-duo/test.ts +2 -2
- package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
- package/examples/extensions/dynamic-tools.ts +74 -0
- package/examples/extensions/overlay-qa-tests.ts +468 -1
- package/examples/extensions/preset.ts +2 -3
- package/examples/extensions/provider-payload.ts +14 -0
- package/examples/extensions/sandbox/index.ts +2 -3
- package/examples/extensions/subagent/agents.ts +2 -3
- package/examples/extensions/tool-override.ts +2 -3
- package/examples/extensions/with-deps/index.ts +1 -5
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +10 -7
package/docs/terminal-setup.md
CHANGED
|
@@ -8,13 +8,30 @@ Work out of the box.
|
|
|
8
8
|
|
|
9
9
|
## Ghostty
|
|
10
10
|
|
|
11
|
-
Add to your Ghostty config (`~/.config/ghostty/config`):
|
|
11
|
+
Add to your Ghostty config (`~/Library/Application Support/com.mitchellh.ghostty/config` on macOS, `~/.config/ghostty/config` on Linux):
|
|
12
12
|
|
|
13
13
|
```
|
|
14
14
|
keybind = alt+backspace=text:\x1b\x7f
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Older Claude Code versions may have added this Ghostty mapping:
|
|
18
|
+
|
|
19
|
+
```
|
|
15
20
|
keybind = shift+enter=text:\n
|
|
16
21
|
```
|
|
17
22
|
|
|
23
|
+
That mapping sends a raw linefeed byte. Inside pi, that is indistinguishable from `Ctrl+J`, so tmux and pi no longer see a real `shift+enter` key event.
|
|
24
|
+
|
|
25
|
+
If Claude Code 2.x or newer is the only reason you added that mapping, you can remove it, unless you want to use Claude Code in tmux, where it still requires that Ghostty mapping.
|
|
26
|
+
|
|
27
|
+
If you want `Shift+Enter` to keep working in tmux via that remap, add `ctrl+j` to your pi `newLine` keybinding in `~/.pi/agent/keybindings.json`:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"newLine": ["shift+enter", "ctrl+j"]
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
18
35
|
## WezTerm
|
|
19
36
|
|
|
20
37
|
Create `~/.wezterm.lua`:
|
|
@@ -46,7 +63,7 @@ Add to `keybindings.json` to enable `Shift+Enter` for multi-line input:
|
|
|
46
63
|
|
|
47
64
|
## Windows Terminal
|
|
48
65
|
|
|
49
|
-
Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file):
|
|
66
|
+
Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file) to forward the modified Enter keys pi uses:
|
|
50
67
|
|
|
51
68
|
```json
|
|
52
69
|
{
|
|
@@ -54,12 +71,31 @@ Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file):
|
|
|
54
71
|
{
|
|
55
72
|
"command": { "action": "sendInput", "input": "\u001b[13;2u" },
|
|
56
73
|
"keys": "shift+enter"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"command": { "action": "sendInput", "input": "\u001b[13;3u" },
|
|
77
|
+
"keys": "alt+enter"
|
|
57
78
|
}
|
|
58
79
|
]
|
|
59
80
|
}
|
|
60
81
|
```
|
|
61
82
|
|
|
62
|
-
|
|
83
|
+
- `Shift+Enter` inserts a new line.
|
|
84
|
+
- Windows Terminal binds `Alt+Enter` to fullscreen by default. That prevents pi from receiving `Alt+Enter` for follow-up queueing.
|
|
85
|
+
- Remapping `Alt+Enter` to `sendInput` forwards the real key chord to pi instead.
|
|
86
|
+
|
|
87
|
+
If you already have an `actions` array, add the objects to it. If the old fullscreen behavior persists, fully close and reopen Windows Terminal.
|
|
88
|
+
|
|
89
|
+
## xfce4-terminal, terminator
|
|
90
|
+
|
|
91
|
+
These terminals have limited escape sequence support. Modified Enter keys like `Ctrl+Enter` and `Shift+Enter` cannot be distinguished from plain `Enter`, preventing custom keybindings such as `submit: ["ctrl+enter"]` from working.
|
|
92
|
+
|
|
93
|
+
For the best experience, use a terminal that supports the Kitty keyboard protocol:
|
|
94
|
+
- [Kitty](https://sw.kovidgoyal.net/kitty/)
|
|
95
|
+
- [Ghostty](https://ghostty.org/)
|
|
96
|
+
- [WezTerm](https://wezfurlong.org/wezterm/)
|
|
97
|
+
- [iTerm2](https://iterm2.com/)
|
|
98
|
+
- [Alacritty](https://github.com/alacritty/alacritty) (requires compilation with Kitty protocol support)
|
|
63
99
|
|
|
64
100
|
## IntelliJ IDEA (Integrated Terminal)
|
|
65
101
|
|
package/docs/tmux.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# tmux Setup
|
|
2
|
+
|
|
3
|
+
Pi works inside tmux, but tmux strips modifier information from certain keys by default. Without configuration, `Shift+Enter` and `Ctrl+Enter` are usually indistinguishable from plain `Enter`.
|
|
4
|
+
|
|
5
|
+
## Recommended Configuration
|
|
6
|
+
|
|
7
|
+
Add to `~/.tmux.conf`:
|
|
8
|
+
|
|
9
|
+
```tmux
|
|
10
|
+
set -g extended-keys on
|
|
11
|
+
set -g extended-keys-format csi-u
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Then restart tmux fully:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
tmux kill-server
|
|
18
|
+
tmux
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Pi requests extended key reporting automatically when Kitty keyboard protocol is not available. With `extended-keys-format csi-u`, tmux forwards modified keys in CSI-u format, which is the most reliable configuration.
|
|
22
|
+
|
|
23
|
+
## Why `csi-u` Is Recommended
|
|
24
|
+
|
|
25
|
+
With only:
|
|
26
|
+
|
|
27
|
+
```tmux
|
|
28
|
+
set -g extended-keys on
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
tmux defaults to `extended-keys-format xterm`. When an application requests extended key reporting, modified keys are forwarded in xterm `modifyOtherKeys` format such as:
|
|
32
|
+
|
|
33
|
+
- `Ctrl+C` → `\x1b[27;5;99~`
|
|
34
|
+
- `Ctrl+D` → `\x1b[27;5;100~`
|
|
35
|
+
- `Ctrl+Enter` → `\x1b[27;5;13~`
|
|
36
|
+
|
|
37
|
+
With `extended-keys-format csi-u`, the same keys are forwarded as:
|
|
38
|
+
|
|
39
|
+
- `Ctrl+C` → `\x1b[99;5u`
|
|
40
|
+
- `Ctrl+D` → `\x1b[100;5u`
|
|
41
|
+
- `Ctrl+Enter` → `\x1b[13;5u`
|
|
42
|
+
|
|
43
|
+
Pi supports both formats, but `csi-u` is the recommended tmux setup.
|
|
44
|
+
|
|
45
|
+
## What This Fixes
|
|
46
|
+
|
|
47
|
+
Without tmux extended keys, modified Enter keys collapse to legacy sequences:
|
|
48
|
+
|
|
49
|
+
| Key | Without extkeys | With `csi-u` |
|
|
50
|
+
|-----|-----------------|--------------|
|
|
51
|
+
| Enter | `\r` | `\r` |
|
|
52
|
+
| Shift+Enter | `\r` | `\x1b[13;2u` |
|
|
53
|
+
| Ctrl+Enter | `\r` | `\x1b[13;5u` |
|
|
54
|
+
| Alt/Option+Enter | `\x1b\r` | `\x1b[13;3u` |
|
|
55
|
+
|
|
56
|
+
This affects the default keybindings (`Enter` to submit, `Shift+Enter` for newline) and any custom keybindings using modified Enter.
|
|
57
|
+
|
|
58
|
+
## Requirements
|
|
59
|
+
|
|
60
|
+
- tmux 3.2 or later (run `tmux -V` to check)
|
|
61
|
+
- A terminal emulator that supports extended keys (Ghostty, Kitty, iTerm2, WezTerm, Windows Terminal)
|
package/docs/tree.md
CHANGED
|
@@ -33,16 +33,25 @@ Sessions are stored as trees where each entry has an `id` and `parentId`. The "l
|
|
|
33
33
|
| Key | Action |
|
|
34
34
|
|-----|--------|
|
|
35
35
|
| ↑/↓ | Navigate (depth-first order) |
|
|
36
|
+
| ←/→ | Page up/down |
|
|
37
|
+
| Ctrl+←/Ctrl+→ or Alt+←/Alt+→ | Fold/unfold and jump between branch segments |
|
|
36
38
|
| Enter | Select node |
|
|
37
39
|
| Escape/Ctrl+C | Cancel |
|
|
38
40
|
| Ctrl+U | Toggle: user messages only |
|
|
39
41
|
| Ctrl+O | Toggle: show all (including custom/label entries) |
|
|
40
42
|
|
|
43
|
+
`Ctrl+←` or `Alt+←` folds the current node if it is foldable. Foldable nodes are roots and branch segment starts that have visible children. If the current node is not foldable, or is already folded, the selection jumps up to the previous visible branch segment start.
|
|
44
|
+
|
|
45
|
+
`Ctrl+→` or `Alt+→` unfolds the current node if it is folded. Otherwise, the selection jumps down to the next visible branch segment start, or to the branch end when there is no further branch point.
|
|
46
|
+
|
|
41
47
|
### Display
|
|
42
48
|
|
|
43
49
|
- Height: half terminal height
|
|
44
50
|
- Current leaf marked with `← active`
|
|
45
51
|
- Labels shown inline: `[label-name]`
|
|
52
|
+
- Foldable branch starts show `⊟` in the connector. Folded branches show `⊞`
|
|
53
|
+
- Active path marker `•` appears after the fold indicator when applicable
|
|
54
|
+
- Search and filter changes reset all folds
|
|
46
55
|
- Default filter hides `label` and `custom` entries (shown in Ctrl+O mode)
|
|
47
56
|
- Children sorted by timestamp (oldest first)
|
|
48
57
|
|
|
@@ -33,6 +33,8 @@ cp permission-gate.ts ~/.pi/agent/extensions/
|
|
|
33
33
|
| `question.ts` | Demonstrates `ctx.ui.select()` for asking the user questions with custom UI |
|
|
34
34
|
| `questionnaire.ts` | Multi-question input with tab bar navigation between questions |
|
|
35
35
|
| `tool-override.ts` | Override built-in tools (e.g., add logging/access control to `read`) |
|
|
36
|
+
| `dynamic-tools.ts` | Register tools after startup (`session_start`) and at runtime via command, with prompt snippets and tool-specific prompt guidelines |
|
|
37
|
+
| `built-in-tool-renderer.ts` | Custom compact rendering for built-in tools (read, bash, edit, write) while keeping original behavior |
|
|
36
38
|
| `minimal-mode.ts` | Override built-in tool rendering for minimal display (only tool calls, no output in collapsed mode) |
|
|
37
39
|
| `truncated-tool.ts` | Wraps ripgrep with proper output truncation (50KB/2000 lines) |
|
|
38
40
|
| `antigravity-image-gen.ts` | Generate images via Google Antigravity with optional save-to-disk modes |
|
|
@@ -28,10 +28,9 @@
|
|
|
28
28
|
import { randomUUID } from "node:crypto";
|
|
29
29
|
import { existsSync, readFileSync } from "node:fs";
|
|
30
30
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
31
|
-
import { homedir } from "node:os";
|
|
32
31
|
import { join } from "node:path";
|
|
33
32
|
import { StringEnum } from "@mariozechner/pi-ai";
|
|
34
|
-
import type
|
|
33
|
+
import { type ExtensionAPI, getAgentDir } from "@mariozechner/pi-coding-agent";
|
|
35
34
|
import { type Static, Type } from "@sinclair/typebox";
|
|
36
35
|
|
|
37
36
|
const PROVIDER = "google-antigravity";
|
|
@@ -49,8 +48,10 @@ type SaveMode = (typeof SAVE_MODES)[number];
|
|
|
49
48
|
|
|
50
49
|
const ANTIGRAVITY_ENDPOINT = "https://daily-cloudcode-pa.sandbox.googleapis.com";
|
|
51
50
|
|
|
51
|
+
const DEFAULT_ANTIGRAVITY_VERSION = "1.18.3";
|
|
52
|
+
|
|
52
53
|
const ANTIGRAVITY_HEADERS = {
|
|
53
|
-
"User-Agent":
|
|
54
|
+
"User-Agent": `antigravity/${process.env.PI_AI_ANTIGRAVITY_VERSION || DEFAULT_ANTIGRAVITY_VERSION} darwin/arm64`,
|
|
54
55
|
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
|
|
55
56
|
"Client-Metadata": JSON.stringify({
|
|
56
57
|
ideType: "IDE_UNSPECIFIED",
|
|
@@ -182,7 +183,8 @@ function readConfigFile(path: string): ExtensionConfig {
|
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
function loadConfig(cwd: string): ExtensionConfig {
|
|
185
|
-
const
|
|
186
|
+
const globalPath = join(getAgentDir(), "extensions", "antigravity-image-gen.json");
|
|
187
|
+
const globalConfig = readConfigFile(globalPath);
|
|
186
188
|
const projectConfig = readConfigFile(join(cwd, ".pi", "extensions", "antigravity-image-gen.json"));
|
|
187
189
|
return { ...globalConfig, ...projectConfig };
|
|
188
190
|
}
|
|
@@ -202,7 +204,8 @@ function resolveSaveConfig(params: ToolParams, cwd: string): SaveConfig {
|
|
|
202
204
|
}
|
|
203
205
|
|
|
204
206
|
if (mode === "global") {
|
|
205
|
-
|
|
207
|
+
const outputDir = join(getAgentDir(), "generated-images");
|
|
208
|
+
return { mode, outputDir };
|
|
206
209
|
}
|
|
207
210
|
|
|
208
211
|
if (mode === "custom") {
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Tool Renderer Example - Custom rendering for built-in tools
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates how to override the rendering of built-in tools (read, bash,
|
|
5
|
+
* edit, write) without changing their behavior. Each tool is re-registered
|
|
6
|
+
* with the same name, delegating execution to the original implementation
|
|
7
|
+
* while providing compact custom renderCall/renderResult functions.
|
|
8
|
+
*
|
|
9
|
+
* This is useful for users who prefer more concise tool output, or who want
|
|
10
|
+
* to highlight specific information (e.g., showing only the diff stats for
|
|
11
|
+
* edit, or just the exit code for bash).
|
|
12
|
+
*
|
|
13
|
+
* How it works:
|
|
14
|
+
* - registerTool() with the same name as a built-in replaces it entirely
|
|
15
|
+
* - We create instances of the original tools via createReadTool(), etc.
|
|
16
|
+
* and delegate execute() to them
|
|
17
|
+
* - renderCall() controls what's shown when the tool is invoked
|
|
18
|
+
* - renderResult() controls what's shown after execution completes
|
|
19
|
+
* - The `expanded` flag in renderResult indicates whether the user has
|
|
20
|
+
* toggled the tool output open (via ctrl+e or clicking)
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* pi -e ./built-in-tool-renderer.ts
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import type { BashToolDetails, EditToolDetails, ExtensionAPI, ReadToolDetails } from "@mariozechner/pi-coding-agent";
|
|
27
|
+
import { createBashTool, createEditTool, createReadTool, createWriteTool } from "@mariozechner/pi-coding-agent";
|
|
28
|
+
import { Text } from "@mariozechner/pi-tui";
|
|
29
|
+
|
|
30
|
+
export default function (pi: ExtensionAPI) {
|
|
31
|
+
const cwd = process.cwd();
|
|
32
|
+
|
|
33
|
+
// --- Read tool: show path and line count ---
|
|
34
|
+
const originalRead = createReadTool(cwd);
|
|
35
|
+
pi.registerTool({
|
|
36
|
+
name: "read",
|
|
37
|
+
label: "read",
|
|
38
|
+
description: originalRead.description,
|
|
39
|
+
parameters: originalRead.parameters,
|
|
40
|
+
|
|
41
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
42
|
+
return originalRead.execute(toolCallId, params, signal, onUpdate);
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
renderCall(args, theme) {
|
|
46
|
+
let text = theme.fg("toolTitle", theme.bold("read "));
|
|
47
|
+
text += theme.fg("accent", args.path);
|
|
48
|
+
if (args.offset || args.limit) {
|
|
49
|
+
const parts: string[] = [];
|
|
50
|
+
if (args.offset) parts.push(`offset=${args.offset}`);
|
|
51
|
+
if (args.limit) parts.push(`limit=${args.limit}`);
|
|
52
|
+
text += theme.fg("dim", ` (${parts.join(", ")})`);
|
|
53
|
+
}
|
|
54
|
+
return new Text(text, 0, 0);
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
renderResult(result, { expanded, isPartial }, theme) {
|
|
58
|
+
if (isPartial) return new Text(theme.fg("warning", "Reading..."), 0, 0);
|
|
59
|
+
|
|
60
|
+
const details = result.details as ReadToolDetails | undefined;
|
|
61
|
+
const content = result.content[0];
|
|
62
|
+
|
|
63
|
+
if (content?.type === "image") {
|
|
64
|
+
return new Text(theme.fg("success", "Image loaded"), 0, 0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (content?.type !== "text") {
|
|
68
|
+
return new Text(theme.fg("error", "No content"), 0, 0);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const lineCount = content.text.split("\n").length;
|
|
72
|
+
let text = theme.fg("success", `${lineCount} lines`);
|
|
73
|
+
|
|
74
|
+
if (details?.truncation?.truncated) {
|
|
75
|
+
text += theme.fg("warning", ` (truncated from ${details.truncation.totalLines})`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (expanded) {
|
|
79
|
+
const lines = content.text.split("\n").slice(0, 15);
|
|
80
|
+
for (const line of lines) {
|
|
81
|
+
text += `\n${theme.fg("dim", line)}`;
|
|
82
|
+
}
|
|
83
|
+
if (lineCount > 15) {
|
|
84
|
+
text += `\n${theme.fg("muted", `... ${lineCount - 15} more lines`)}`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return new Text(text, 0, 0);
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// --- Bash tool: show command and exit code ---
|
|
93
|
+
const originalBash = createBashTool(cwd);
|
|
94
|
+
pi.registerTool({
|
|
95
|
+
name: "bash",
|
|
96
|
+
label: "bash",
|
|
97
|
+
description: originalBash.description,
|
|
98
|
+
parameters: originalBash.parameters,
|
|
99
|
+
|
|
100
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
101
|
+
return originalBash.execute(toolCallId, params, signal, onUpdate);
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
renderCall(args, theme) {
|
|
105
|
+
let text = theme.fg("toolTitle", theme.bold("$ "));
|
|
106
|
+
const cmd = args.command.length > 80 ? `${args.command.slice(0, 77)}...` : args.command;
|
|
107
|
+
text += theme.fg("accent", cmd);
|
|
108
|
+
if (args.timeout) {
|
|
109
|
+
text += theme.fg("dim", ` (timeout: ${args.timeout}s)`);
|
|
110
|
+
}
|
|
111
|
+
return new Text(text, 0, 0);
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
renderResult(result, { expanded, isPartial }, theme) {
|
|
115
|
+
if (isPartial) return new Text(theme.fg("warning", "Running..."), 0, 0);
|
|
116
|
+
|
|
117
|
+
const details = result.details as BashToolDetails | undefined;
|
|
118
|
+
const content = result.content[0];
|
|
119
|
+
const output = content?.type === "text" ? content.text : "";
|
|
120
|
+
|
|
121
|
+
const exitMatch = output.match(/exit code: (\d+)/);
|
|
122
|
+
const exitCode = exitMatch ? parseInt(exitMatch[1], 10) : null;
|
|
123
|
+
const lineCount = output.split("\n").filter((l) => l.trim()).length;
|
|
124
|
+
|
|
125
|
+
let text = "";
|
|
126
|
+
if (exitCode === 0 || exitCode === null) {
|
|
127
|
+
text += theme.fg("success", "done");
|
|
128
|
+
} else {
|
|
129
|
+
text += theme.fg("error", `exit ${exitCode}`);
|
|
130
|
+
}
|
|
131
|
+
text += theme.fg("dim", ` (${lineCount} lines)`);
|
|
132
|
+
|
|
133
|
+
if (details?.truncation?.truncated) {
|
|
134
|
+
text += theme.fg("warning", " [truncated]");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (expanded) {
|
|
138
|
+
const lines = output.split("\n").slice(0, 20);
|
|
139
|
+
for (const line of lines) {
|
|
140
|
+
text += `\n${theme.fg("dim", line)}`;
|
|
141
|
+
}
|
|
142
|
+
if (output.split("\n").length > 20) {
|
|
143
|
+
text += `\n${theme.fg("muted", "... more output")}`;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return new Text(text, 0, 0);
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// --- Edit tool: show path and diff stats ---
|
|
152
|
+
const originalEdit = createEditTool(cwd);
|
|
153
|
+
pi.registerTool({
|
|
154
|
+
name: "edit",
|
|
155
|
+
label: "edit",
|
|
156
|
+
description: originalEdit.description,
|
|
157
|
+
parameters: originalEdit.parameters,
|
|
158
|
+
|
|
159
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
160
|
+
return originalEdit.execute(toolCallId, params, signal, onUpdate);
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
renderCall(args, theme) {
|
|
164
|
+
let text = theme.fg("toolTitle", theme.bold("edit "));
|
|
165
|
+
text += theme.fg("accent", args.path);
|
|
166
|
+
return new Text(text, 0, 0);
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
renderResult(result, { expanded, isPartial }, theme) {
|
|
170
|
+
if (isPartial) return new Text(theme.fg("warning", "Editing..."), 0, 0);
|
|
171
|
+
|
|
172
|
+
const details = result.details as EditToolDetails | undefined;
|
|
173
|
+
const content = result.content[0];
|
|
174
|
+
|
|
175
|
+
if (content?.type === "text" && content.text.startsWith("Error")) {
|
|
176
|
+
return new Text(theme.fg("error", content.text.split("\n")[0]), 0, 0);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (!details?.diff) {
|
|
180
|
+
return new Text(theme.fg("success", "Applied"), 0, 0);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Count additions and removals from the diff
|
|
184
|
+
const diffLines = details.diff.split("\n");
|
|
185
|
+
let additions = 0;
|
|
186
|
+
let removals = 0;
|
|
187
|
+
for (const line of diffLines) {
|
|
188
|
+
if (line.startsWith("+") && !line.startsWith("+++")) additions++;
|
|
189
|
+
if (line.startsWith("-") && !line.startsWith("---")) removals++;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
let text = theme.fg("success", `+${additions}`);
|
|
193
|
+
text += theme.fg("dim", " / ");
|
|
194
|
+
text += theme.fg("error", `-${removals}`);
|
|
195
|
+
|
|
196
|
+
if (expanded) {
|
|
197
|
+
for (const line of diffLines.slice(0, 30)) {
|
|
198
|
+
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
199
|
+
text += `\n${theme.fg("success", line)}`;
|
|
200
|
+
} else if (line.startsWith("-") && !line.startsWith("---")) {
|
|
201
|
+
text += `\n${theme.fg("error", line)}`;
|
|
202
|
+
} else {
|
|
203
|
+
text += `\n${theme.fg("dim", line)}`;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (diffLines.length > 30) {
|
|
207
|
+
text += `\n${theme.fg("muted", `... ${diffLines.length - 30} more diff lines`)}`;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return new Text(text, 0, 0);
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// --- Write tool: show path and size ---
|
|
216
|
+
const originalWrite = createWriteTool(cwd);
|
|
217
|
+
pi.registerTool({
|
|
218
|
+
name: "write",
|
|
219
|
+
label: "write",
|
|
220
|
+
description: originalWrite.description,
|
|
221
|
+
parameters: originalWrite.parameters,
|
|
222
|
+
|
|
223
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
224
|
+
return originalWrite.execute(toolCallId, params, signal, onUpdate);
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
renderCall(args, theme) {
|
|
228
|
+
let text = theme.fg("toolTitle", theme.bold("write "));
|
|
229
|
+
text += theme.fg("accent", args.path);
|
|
230
|
+
const lineCount = args.content.split("\n").length;
|
|
231
|
+
text += theme.fg("dim", ` (${lineCount} lines)`);
|
|
232
|
+
return new Text(text, 0, 0);
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
renderResult(result, { isPartial }, theme) {
|
|
236
|
+
if (isPartial) return new Text(theme.fg("warning", "Writing..."), 0, 0);
|
|
237
|
+
|
|
238
|
+
const content = result.content[0];
|
|
239
|
+
if (content?.type === "text" && content.text.startsWith("Error")) {
|
|
240
|
+
return new Text(theme.fg("error", content.text.split("\n")[0]), 0, 0);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return new Text(theme.fg("success", "Written"), 0, 0);
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-custom-provider",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-custom-provider",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.11.2",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.52.0"
|
|
12
12
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import { type Api, type Context, type Model, registerApiProvider, streamSimple } from "@mariozechner/pi-ai";
|
|
12
12
|
import { readFileSync } from "fs";
|
|
13
|
-
import {
|
|
13
|
+
import { getAgentDir } from "packages/coding-agent/src/config.js";
|
|
14
14
|
import { join } from "path";
|
|
15
15
|
import { MODELS, streamGitLabDuo } from "./index.js";
|
|
16
16
|
|
|
@@ -28,7 +28,7 @@ async function main() {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
// Read auth
|
|
31
|
-
const authPath = join(
|
|
31
|
+
const authPath = join(getAgentDir(), "extensions", "auth.json");
|
|
32
32
|
const authData = JSON.parse(readFileSync(authPath, "utf-8"));
|
|
33
33
|
const gitlabCred = authData["gitlab-duo"];
|
|
34
34
|
if (!gitlabCred?.access) {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic Tools Extension
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates registering tools after session initialization.
|
|
5
|
+
*
|
|
6
|
+
* - Registers one tool during session_start
|
|
7
|
+
* - Registers additional tools at runtime via /add-echo-tool <name>
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
11
|
+
import { Type } from "@sinclair/typebox";
|
|
12
|
+
|
|
13
|
+
const ECHO_PARAMS = Type.Object({
|
|
14
|
+
message: Type.String({ description: "Message to echo" }),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
function normalizeToolName(input: string): string | undefined {
|
|
18
|
+
const trimmed = input.trim().toLowerCase();
|
|
19
|
+
if (!trimmed) return undefined;
|
|
20
|
+
if (!/^[a-z0-9_]+$/.test(trimmed)) return undefined;
|
|
21
|
+
return trimmed;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default function dynamicToolsExtension(pi: ExtensionAPI) {
|
|
25
|
+
const registeredToolNames = new Set<string>();
|
|
26
|
+
|
|
27
|
+
const registerEchoTool = (name: string, label: string, prefix: string): boolean => {
|
|
28
|
+
if (registeredToolNames.has(name)) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
registeredToolNames.add(name);
|
|
33
|
+
pi.registerTool({
|
|
34
|
+
name,
|
|
35
|
+
label,
|
|
36
|
+
description: `Echo a message with prefix: ${prefix}`,
|
|
37
|
+
promptSnippet: `Echo back user-provided text with ${prefix.trim()} prefix`,
|
|
38
|
+
promptGuidelines: ["Use this tool when the user asks for exact echo output."],
|
|
39
|
+
parameters: ECHO_PARAMS,
|
|
40
|
+
async execute(_toolCallId, params) {
|
|
41
|
+
return {
|
|
42
|
+
content: [{ type: "text", text: `${prefix}${params.message}` }],
|
|
43
|
+
details: { tool: name, prefix },
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return true;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
pi.on("session_start", (_event, ctx) => {
|
|
52
|
+
registerEchoTool("echo_session", "Echo Session", "[session] ");
|
|
53
|
+
ctx.ui.notify("Registered dynamic tool: echo_session", "info");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
pi.registerCommand("add-echo-tool", {
|
|
57
|
+
description: "Register a new echo tool dynamically: /add-echo-tool <tool_name>",
|
|
58
|
+
handler: async (args, ctx) => {
|
|
59
|
+
const toolName = normalizeToolName(args);
|
|
60
|
+
if (!toolName) {
|
|
61
|
+
ctx.ui.notify("Usage: /add-echo-tool <tool_name> (lowercase, numbers, underscores)", "warning");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const created = registerEchoTool(toolName, `Echo ${toolName}`, `[${toolName}] `);
|
|
66
|
+
if (!created) {
|
|
67
|
+
ctx.ui.notify(`Tool already registered: ${toolName}`, "warning");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
ctx.ui.notify(`Registered dynamic tool: ${toolName}`, "info");
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
}
|