pi-ui-extend 0.1.1
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/README.md +307 -0
- package/bin/pix.mjs +219 -0
- package/dist/app/app.d.ts +96 -0
- package/dist/app/app.js +871 -0
- package/dist/app/blink-controller.d.ts +23 -0
- package/dist/app/blink-controller.js +82 -0
- package/dist/app/cli.d.ts +8 -0
- package/dist/app/cli.js +83 -0
- package/dist/app/clipboard.d.ts +1 -0
- package/dist/app/clipboard.js +24 -0
- package/dist/app/command-controller.d.ts +18 -0
- package/dist/app/command-controller.js +58 -0
- package/dist/app/command-host.d.ts +44 -0
- package/dist/app/command-host.js +1 -0
- package/dist/app/command-model-actions.d.ts +12 -0
- package/dist/app/command-model-actions.js +176 -0
- package/dist/app/command-navigation-actions.d.ts +19 -0
- package/dist/app/command-navigation-actions.js +267 -0
- package/dist/app/command-registry.d.ts +32 -0
- package/dist/app/command-registry.js +225 -0
- package/dist/app/command-runtime.d.ts +5 -0
- package/dist/app/command-runtime.js +32 -0
- package/dist/app/command-session-actions.d.ts +20 -0
- package/dist/app/command-session-actions.js +295 -0
- package/dist/app/constants.d.ts +52 -0
- package/dist/app/constants.js +103 -0
- package/dist/app/conversation-entry-renderer.d.ts +21 -0
- package/dist/app/conversation-entry-renderer.js +81 -0
- package/dist/app/conversation-shell-renderer.d.ts +5 -0
- package/dist/app/conversation-shell-renderer.js +43 -0
- package/dist/app/conversation-tool-renderer.d.ts +16 -0
- package/dist/app/conversation-tool-renderer.js +216 -0
- package/dist/app/conversation-viewport.d.ts +55 -0
- package/dist/app/conversation-viewport.js +252 -0
- package/dist/app/dcp-stats.d.ts +2 -0
- package/dist/app/dcp-stats.js +116 -0
- package/dist/app/editor-layout-renderer.d.ts +31 -0
- package/dist/app/editor-layout-renderer.js +211 -0
- package/dist/app/editor-panels.d.ts +4 -0
- package/dist/app/editor-panels.js +130 -0
- package/dist/app/extension-actions-controller.d.ts +22 -0
- package/dist/app/extension-actions-controller.js +60 -0
- package/dist/app/extension-event-bus.d.ts +3 -0
- package/dist/app/extension-event-bus.js +23 -0
- package/dist/app/extension-ui-controller.d.ts +57 -0
- package/dist/app/extension-ui-controller.js +532 -0
- package/dist/app/file-link-opener.d.ts +2 -0
- package/dist/app/file-link-opener.js +66 -0
- package/dist/app/file-links.d.ts +10 -0
- package/dist/app/file-links.js +117 -0
- package/dist/app/guards.d.ts +3 -0
- package/dist/app/guards.js +9 -0
- package/dist/app/icons.d.ts +37 -0
- package/dist/app/icons.js +97 -0
- package/dist/app/id.d.ts +1 -0
- package/dist/app/id.js +4 -0
- package/dist/app/image-click-targets.d.ts +5 -0
- package/dist/app/image-click-targets.js +32 -0
- package/dist/app/image-opener.d.ts +2 -0
- package/dist/app/image-opener.js +64 -0
- package/dist/app/input-action-controller.d.ts +47 -0
- package/dist/app/input-action-controller.js +209 -0
- package/dist/app/input-controller.d.ts +60 -0
- package/dist/app/input-controller.js +425 -0
- package/dist/app/input-paste-handler.d.ts +27 -0
- package/dist/app/input-paste-handler.js +146 -0
- package/dist/app/menu-items-controller.d.ts +32 -0
- package/dist/app/menu-items-controller.js +182 -0
- package/dist/app/message-content.d.ts +8 -0
- package/dist/app/message-content.js +115 -0
- package/dist/app/model-ref.d.ts +13 -0
- package/dist/app/model-ref.js +50 -0
- package/dist/app/model-usage-controller.d.ts +35 -0
- package/dist/app/model-usage-controller.js +99 -0
- package/dist/app/model-usage-status.d.ts +125 -0
- package/dist/app/model-usage-status.js +749 -0
- package/dist/app/mouse-controller.d.ts +182 -0
- package/dist/app/mouse-controller.js +968 -0
- package/dist/app/native-modifiers.d.ts +3 -0
- package/dist/app/native-modifiers.js +60 -0
- package/dist/app/nerd-font-controller.d.ts +11 -0
- package/dist/app/nerd-font-controller.js +90 -0
- package/dist/app/popup-action-controller.d.ts +44 -0
- package/dist/app/popup-action-controller.js +278 -0
- package/dist/app/popup-menu-controller.d.ts +183 -0
- package/dist/app/popup-menu-controller.js +1070 -0
- package/dist/app/prompt-enhancer-controller.d.ts +40 -0
- package/dist/app/prompt-enhancer-controller.js +215 -0
- package/dist/app/queued-message-controller.d.ts +62 -0
- package/dist/app/queued-message-controller.js +377 -0
- package/dist/app/render-controller.d.ts +41 -0
- package/dist/app/render-controller.js +378 -0
- package/dist/app/render-text.d.ts +19 -0
- package/dist/app/render-text.js +67 -0
- package/dist/app/request-history.d.ts +23 -0
- package/dist/app/request-history.js +131 -0
- package/dist/app/runtime.d.ts +39 -0
- package/dist/app/runtime.js +195 -0
- package/dist/app/screen-selection.d.ts +6 -0
- package/dist/app/screen-selection.js +9 -0
- package/dist/app/screen-styler.d.ts +34 -0
- package/dist/app/screen-styler.js +168 -0
- package/dist/app/scroll-controller.d.ts +51 -0
- package/dist/app/scroll-controller.js +207 -0
- package/dist/app/session-event-controller.d.ts +69 -0
- package/dist/app/session-event-controller.js +338 -0
- package/dist/app/session-history.d.ts +23 -0
- package/dist/app/session-history.js +164 -0
- package/dist/app/session-lifecycle-controller.d.ts +55 -0
- package/dist/app/session-lifecycle-controller.js +116 -0
- package/dist/app/session-search.d.ts +24 -0
- package/dist/app/session-search.js +215 -0
- package/dist/app/shell-command.d.ts +27 -0
- package/dist/app/shell-command.js +176 -0
- package/dist/app/shell-controller.d.ts +28 -0
- package/dist/app/shell-controller.js +124 -0
- package/dist/app/slash-commands.d.ts +6 -0
- package/dist/app/slash-commands.js +75 -0
- package/dist/app/startup-checks.d.ts +8 -0
- package/dist/app/startup-checks.js +59 -0
- package/dist/app/startup-info.d.ts +3 -0
- package/dist/app/startup-info.js +176 -0
- package/dist/app/status-controller.d.ts +35 -0
- package/dist/app/status-controller.js +105 -0
- package/dist/app/status-line-renderer.d.ts +68 -0
- package/dist/app/status-line-renderer.js +453 -0
- package/dist/app/subagents-files.d.ts +10 -0
- package/dist/app/subagents-files.js +193 -0
- package/dist/app/subagents-model.d.ts +23 -0
- package/dist/app/subagents-model.js +224 -0
- package/dist/app/subagents-widget-controller.d.ts +43 -0
- package/dist/app/subagents-widget-controller.js +311 -0
- package/dist/app/tab-line-renderer.d.ts +26 -0
- package/dist/app/tab-line-renderer.js +222 -0
- package/dist/app/tabs-controller.d.ts +100 -0
- package/dist/app/tabs-controller.js +885 -0
- package/dist/app/terminal-controller.d.ts +40 -0
- package/dist/app/terminal-controller.js +135 -0
- package/dist/app/terminal-edit-shortcuts.d.ts +23 -0
- package/dist/app/terminal-edit-shortcuts.js +138 -0
- package/dist/app/terminal-output-buffer.d.ts +20 -0
- package/dist/app/terminal-output-buffer.js +52 -0
- package/dist/app/toast-controller.d.ts +13 -0
- package/dist/app/toast-controller.js +40 -0
- package/dist/app/toast-renderer.d.ts +9 -0
- package/dist/app/toast-renderer.js +79 -0
- package/dist/app/todo-model.d.ts +22 -0
- package/dist/app/todo-model.js +179 -0
- package/dist/app/todo-widget-controller.d.ts +21 -0
- package/dist/app/todo-widget-controller.js +59 -0
- package/dist/app/tool-block-renderer.d.ts +26 -0
- package/dist/app/tool-block-renderer.js +439 -0
- package/dist/app/types.d.ts +550 -0
- package/dist/app/types.js +1 -0
- package/dist/app/update.d.ts +36 -0
- package/dist/app/update.js +315 -0
- package/dist/app/voice-controller.d.ts +52 -0
- package/dist/app/voice-controller.js +600 -0
- package/dist/app/workspace-actions-controller.d.ts +40 -0
- package/dist/app/workspace-actions-controller.js +215 -0
- package/dist/app/workspace-undo.d.ts +44 -0
- package/dist/app/workspace-undo.js +215 -0
- package/dist/config.d.ts +62 -0
- package/dist/config.js +527 -0
- package/dist/context-progress-bar.d.ts +17 -0
- package/dist/context-progress-bar.js +48 -0
- package/dist/default-pix-config.d.ts +1 -0
- package/dist/default-pix-config.js +375 -0
- package/dist/fuzzy.d.ts +23 -0
- package/dist/fuzzy.js +165 -0
- package/dist/input-editor-files.d.ts +15 -0
- package/dist/input-editor-files.js +62 -0
- package/dist/input-editor.d.ts +186 -0
- package/dist/input-editor.js +835 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +12 -0
- package/dist/markdown-format.d.ts +22 -0
- package/dist/markdown-format.js +542 -0
- package/dist/sdk.d.ts +3 -0
- package/dist/sdk.js +1 -0
- package/dist/syntax-highlight.d.ts +22 -0
- package/dist/syntax-highlight.js +528 -0
- package/dist/terminal-width.d.ts +6 -0
- package/dist/terminal-width.js +245 -0
- package/dist/theme.d.ts +56 -0
- package/dist/theme.js +118 -0
- package/dist/tool-renderers/apply-patch.d.ts +2 -0
- package/dist/tool-renderers/apply-patch.js +36 -0
- package/dist/tool-renderers/ast.d.ts +2 -0
- package/dist/tool-renderers/ast.js +5 -0
- package/dist/tool-renderers/compress.d.ts +2 -0
- package/dist/tool-renderers/compress.js +126 -0
- package/dist/tool-renderers/index.d.ts +3 -0
- package/dist/tool-renderers/index.js +44 -0
- package/dist/tool-renderers/question.d.ts +2 -0
- package/dist/tool-renderers/question.js +88 -0
- package/dist/tool-renderers/read.d.ts +2 -0
- package/dist/tool-renderers/read.js +36 -0
- package/dist/tool-renderers/repo.d.ts +2 -0
- package/dist/tool-renderers/repo.js +13 -0
- package/dist/tool-renderers/shell.d.ts +3 -0
- package/dist/tool-renderers/shell.js +27 -0
- package/dist/tool-renderers/skill.d.ts +2 -0
- package/dist/tool-renderers/skill.js +132 -0
- package/dist/tool-renderers/subagents.d.ts +2 -0
- package/dist/tool-renderers/subagents.js +51 -0
- package/dist/tool-renderers/todo.d.ts +2 -0
- package/dist/tool-renderers/todo.js +9 -0
- package/dist/tool-renderers/types.d.ts +42 -0
- package/dist/tool-renderers/types.js +1 -0
- package/dist/tool-renderers/utils.d.ts +31 -0
- package/dist/tool-renderers/utils.js +230 -0
- package/dist/tool-renderers/web.d.ts +3 -0
- package/dist/tool-renderers/web.js +9 -0
- package/dist/tool-renderers/write.d.ts +2 -0
- package/dist/tool-renderers/write.js +42 -0
- package/dist/ui.d.ts +56 -0
- package/dist/ui.js +94 -0
- package/docs/release.md +81 -0
- package/extensions/question/contract.ts +100 -0
- package/extensions/question/index.ts +34 -0
- package/extensions/question/render.ts +28 -0
- package/extensions/question/result.ts +86 -0
- package/extensions/question/tool-description.ts +11 -0
- package/extensions/question/tui.ts +629 -0
- package/extensions/question/types.ts +123 -0
- package/extensions/session-title/config.ts +169 -0
- package/extensions/session-title/index.ts +459 -0
- package/extensions/terminal-bell/index.ts +315 -0
- package/external/pi-tools-suite/README.md +242 -0
- package/external/pi-tools-suite/index.ts +1 -0
- package/external/pi-tools-suite/licenses/ollama-pi-web-search.MIT +21 -0
- package/external/pi-tools-suite/licenses/opencode-mystatus-MIT.txt +21 -0
- package/external/pi-tools-suite/package.json +53 -0
- package/external/pi-tools-suite/src/antigravity-auth/auth-store.ts +194 -0
- package/external/pi-tools-suite/src/antigravity-auth/commands.ts +80 -0
- package/external/pi-tools-suite/src/antigravity-auth/constants.ts +26 -0
- package/external/pi-tools-suite/src/antigravity-auth/headers.ts +20 -0
- package/external/pi-tools-suite/src/antigravity-auth/index.ts +104 -0
- package/external/pi-tools-suite/src/antigravity-auth/models.ts +86 -0
- package/external/pi-tools-suite/src/antigravity-auth/oauth.ts +305 -0
- package/external/pi-tools-suite/src/antigravity-auth/payload.ts +423 -0
- package/external/pi-tools-suite/src/antigravity-auth/status.ts +78 -0
- package/external/pi-tools-suite/src/antigravity-auth/stream.ts +302 -0
- package/external/pi-tools-suite/src/antigravity-auth/types.ts +113 -0
- package/external/pi-tools-suite/src/ast-grep/index.ts +6 -0
- package/external/pi-tools-suite/src/ast-grep/render.ts +70 -0
- package/external/pi-tools-suite/src/ast-grep/schema.ts +109 -0
- package/external/pi-tools-suite/src/ast-grep/tool.ts +345 -0
- package/external/pi-tools-suite/src/ast-grep/types.ts +55 -0
- package/external/pi-tools-suite/src/ast-grep/utils.ts +65 -0
- package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +222 -0
- package/external/pi-tools-suite/src/async-subagents/commands.ts +518 -0
- package/external/pi-tools-suite/src/async-subagents/constants.ts +11 -0
- package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +74 -0
- package/external/pi-tools-suite/src/async-subagents/core/attachment-bridge.ts +133 -0
- package/external/pi-tools-suite/src/async-subagents/core/cleanup.ts +66 -0
- package/external/pi-tools-suite/src/async-subagents/core/concurrency.ts +90 -0
- package/external/pi-tools-suite/src/async-subagents/core/config.ts +819 -0
- package/external/pi-tools-suite/src/async-subagents/core/log-limits.ts +166 -0
- package/external/pi-tools-suite/src/async-subagents/core/model-fallback.ts +133 -0
- package/external/pi-tools-suite/src/async-subagents/core/paths.ts +47 -0
- package/external/pi-tools-suite/src/async-subagents/core/pi-invocation.ts +35 -0
- package/external/pi-tools-suite/src/async-subagents/core/presets.ts +67 -0
- package/external/pi-tools-suite/src/async-subagents/core/process.ts +15 -0
- package/external/pi-tools-suite/src/async-subagents/core/prompt.ts +66 -0
- package/external/pi-tools-suite/src/async-subagents/core/registry.ts +224 -0
- package/external/pi-tools-suite/src/async-subagents/core/retry.ts +191 -0
- package/external/pi-tools-suite/src/async-subagents/core/routing.ts +259 -0
- package/external/pi-tools-suite/src/async-subagents/core/sessions.ts +138 -0
- package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +688 -0
- package/external/pi-tools-suite/src/async-subagents/core/state.ts +281 -0
- package/external/pi-tools-suite/src/async-subagents/core/stop.ts +131 -0
- package/external/pi-tools-suite/src/async-subagents/core/structured-result.ts +237 -0
- package/external/pi-tools-suite/src/async-subagents/core/tool-guard.ts +34 -0
- package/external/pi-tools-suite/src/async-subagents/core/types.ts +150 -0
- package/external/pi-tools-suite/src/async-subagents/core/ultrawork-auto.ts +184 -0
- package/external/pi-tools-suite/src/async-subagents/core/utils.ts +11 -0
- package/external/pi-tools-suite/src/async-subagents/format.ts +41 -0
- package/external/pi-tools-suite/src/async-subagents/index.ts +422 -0
- package/external/pi-tools-suite/src/async-subagents/lib.ts +88 -0
- package/external/pi-tools-suite/src/async-subagents/live.ts +10 -0
- package/external/pi-tools-suite/src/async-subagents/polling.ts +83 -0
- package/external/pi-tools-suite/src/async-subagents/render.ts +230 -0
- package/external/pi-tools-suite/src/async-subagents/subagent-overlay.ts +77 -0
- package/external/pi-tools-suite/src/async-subagents/tasks.ts +120 -0
- package/external/pi-tools-suite/src/async-subagents/tools/cleanup.ts +99 -0
- package/external/pi-tools-suite/src/async-subagents/tools/result.ts +179 -0
- package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +372 -0
- package/external/pi-tools-suite/src/async-subagents/tools/status.ts +60 -0
- package/external/pi-tools-suite/src/async-subagents/tools/stop.ts +79 -0
- package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +152 -0
- package/external/pi-tools-suite/src/async-subagents/tools/wait.ts +67 -0
- package/external/pi-tools-suite/src/async-subagents/types.ts +45 -0
- package/external/pi-tools-suite/src/async-subagents/ui.ts +5 -0
- package/external/pi-tools-suite/src/compress/commands.ts +440 -0
- package/external/pi-tools-suite/src/compress/compress-tool.ts +368 -0
- package/external/pi-tools-suite/src/compress/compression-blocks.ts +524 -0
- package/external/pi-tools-suite/src/compress/config.ts +310 -0
- package/external/pi-tools-suite/src/compress/dcp-tui-filter.ts +498 -0
- package/external/pi-tools-suite/src/compress/index.ts +397 -0
- package/external/pi-tools-suite/src/compress/prompts.ts +269 -0
- package/external/pi-tools-suite/src/compress/pruner-candidates.ts +176 -0
- package/external/pi-tools-suite/src/compress/pruner-compression-blocks.ts +260 -0
- package/external/pi-tools-suite/src/compress/pruner-message-ids.ts +147 -0
- package/external/pi-tools-suite/src/compress/pruner-metadata.ts +268 -0
- package/external/pi-tools-suite/src/compress/pruner-nudge.ts +315 -0
- package/external/pi-tools-suite/src/compress/pruner-tools.ts +263 -0
- package/external/pi-tools-suite/src/compress/pruner-types.ts +25 -0
- package/external/pi-tools-suite/src/compress/pruner.ts +92 -0
- package/external/pi-tools-suite/src/compress/state.ts +486 -0
- package/external/pi-tools-suite/src/compress/ui.ts +308 -0
- package/external/pi-tools-suite/src/config.ts +176 -0
- package/external/pi-tools-suite/src/context-usage.ts +31 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +355 -0
- package/external/pi-tools-suite/src/index.ts +46 -0
- package/external/pi-tools-suite/src/lib/lsp.ts +62 -0
- package/external/pi-tools-suite/src/lib/project.ts +42 -0
- package/external/pi-tools-suite/src/lib/tool-args.ts +137 -0
- package/external/pi-tools-suite/src/lsp/_shared/config.ts +156 -0
- package/external/pi-tools-suite/src/lsp/_shared/glob.ts +60 -0
- package/external/pi-tools-suite/src/lsp/_shared/output.ts +102 -0
- package/external/pi-tools-suite/src/lsp/_shared/paths.ts +138 -0
- package/external/pi-tools-suite/src/lsp/_shared/runner.ts +64 -0
- package/external/pi-tools-suite/src/lsp/_shared/template.ts +23 -0
- package/external/pi-tools-suite/src/lsp/_shared/trust.ts +116 -0
- package/external/pi-tools-suite/src/lsp/_shared/types.ts +98 -0
- package/external/pi-tools-suite/src/lsp/async.ts +29 -0
- package/external/pi-tools-suite/src/lsp/child-process.ts +81 -0
- package/external/pi-tools-suite/src/lsp/client.ts +340 -0
- package/external/pi-tools-suite/src/lsp/constants.ts +9 -0
- package/external/pi-tools-suite/src/lsp/diagnostics-store.ts +64 -0
- package/external/pi-tools-suite/src/lsp/documents.ts +24 -0
- package/external/pi-tools-suite/src/lsp/index.ts +31 -0
- package/external/pi-tools-suite/src/lsp/lsp-utils.ts +37 -0
- package/external/pi-tools-suite/src/lsp/manager.ts +190 -0
- package/external/pi-tools-suite/src/lsp/mutation-events.ts +78 -0
- package/external/pi-tools-suite/src/lsp/renderer.ts +1 -0
- package/external/pi-tools-suite/src/lsp/tool-result.ts +6 -0
- package/external/pi-tools-suite/src/lsp/tsserver.ts +107 -0
- package/external/pi-tools-suite/src/lsp/types.ts +15 -0
- package/external/pi-tools-suite/src/model-tools/apply-patch.ts +590 -0
- package/external/pi-tools-suite/src/model-tools/index.ts +430 -0
- package/external/pi-tools-suite/src/model-tools/path-utils.ts +6 -0
- package/external/pi-tools-suite/src/model-tools/tool-args.ts +11 -0
- package/external/pi-tools-suite/src/prompt-commands/index.ts +349 -0
- package/external/pi-tools-suite/src/repo-discovery/index.ts +384 -0
- package/external/pi-tools-suite/src/repo-discovery/project.ts +7 -0
- package/external/pi-tools-suite/src/startup-section.ts +13 -0
- package/external/pi-tools-suite/src/terminal-bell/index.ts +309 -0
- package/external/pi-tools-suite/src/todo/index.ts +201 -0
- package/external/pi-tools-suite/src/todo/state/auto-clear.ts +13 -0
- package/external/pi-tools-suite/src/todo/state/invariants.ts +21 -0
- package/external/pi-tools-suite/src/todo/state/persistence.ts +94 -0
- package/external/pi-tools-suite/src/todo/state/replay.ts +38 -0
- package/external/pi-tools-suite/src/todo/state/selectors.ts +49 -0
- package/external/pi-tools-suite/src/todo/state/state-reducer.ts +362 -0
- package/external/pi-tools-suite/src/todo/state/state.ts +18 -0
- package/external/pi-tools-suite/src/todo/state/store.ts +52 -0
- package/external/pi-tools-suite/src/todo/state/task-graph.ts +57 -0
- package/external/pi-tools-suite/src/todo/todo.ts +487 -0
- package/external/pi-tools-suite/src/todo/tool/response-envelope.ts +143 -0
- package/external/pi-tools-suite/src/todo/tool/types.ts +188 -0
- package/external/pi-tools-suite/src/todo/view/format.ts +18 -0
- package/external/pi-tools-suite/src/todo/view/labels.ts +13 -0
- package/external/pi-tools-suite/src/tool-descriptions.ts +369 -0
- package/external/pi-tools-suite/src/usage/index.ts +152 -0
- package/external/pi-tools-suite/src/usage/lib/copilot.ts +535 -0
- package/external/pi-tools-suite/src/usage/lib/google.ts +478 -0
- package/external/pi-tools-suite/src/usage/lib/openai.ts +268 -0
- package/external/pi-tools-suite/src/usage/lib/types.ts +114 -0
- package/external/pi-tools-suite/src/usage/lib/utils.ts +134 -0
- package/external/pi-tools-suite/src/usage/lib/zhipu.ts +228 -0
- package/external/pi-tools-suite/src/web-search/index.ts +397 -0
- package/package.json +89 -0
- package/skills/context7/SKILL.md +69 -0
- package/skills/context7/scripts/context7.sh +73 -0
- package/skills/handoff/SKILL.md +15 -0
- package/skills/pdf/LICENSE.txt +30 -0
- package/skills/pdf/SKILL.md +314 -0
- package/skills/pdf/forms.md +294 -0
- package/skills/pdf/reference.md +612 -0
- package/skills/pdf/scripts/check_bounding_boxes.py +65 -0
- package/skills/pdf/scripts/check_fillable_fields.py +11 -0
- package/skills/pdf/scripts/convert_pdf_to_images.py +33 -0
- package/skills/pdf/scripts/create_validation_image.py +37 -0
- package/skills/pdf/scripts/extract_form_field_info.py +122 -0
- package/skills/pdf/scripts/extract_form_structure.py +115 -0
- package/skills/pdf/scripts/fill_fillable_fields.py +98 -0
- package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
- package/skills/playwright-cli/SKILL.md +388 -0
- package/skills/playwright-cli/references/element-attributes.md +23 -0
- package/skills/playwright-cli/references/playwright-tests.md +39 -0
- package/skills/playwright-cli/references/request-mocking.md +87 -0
- package/skills/playwright-cli/references/running-code.md +241 -0
- package/skills/playwright-cli/references/session-management.md +225 -0
- package/skills/playwright-cli/references/spec-driven-testing.md +305 -0
- package/skills/playwright-cli/references/storage-state.md +275 -0
- package/skills/playwright-cli/references/test-generation.md +134 -0
- package/skills/playwright-cli/references/tracing.md +139 -0
- package/skills/playwright-cli/references/video-recording.md +143 -0
- package/skills/simplify/SKILL.md +51 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/SKILL.md +485 -0
- package/skills/skill-creator/agents/analyzer.md +274 -0
- package/skills/skill-creator/agents/comparator.md +202 -0
- package/skills/skill-creator/agents/grader.md +223 -0
- package/skills/skill-creator/assets/eval_review.html +146 -0
- package/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/skills/skill-creator/references/schemas.md +430 -0
- package/skills/skill-creator/scripts/__init__.py +0 -0
- package/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/skills/skill-creator/scripts/generate_report.py +326 -0
- package/skills/skill-creator/scripts/improve_description.py +247 -0
- package/skills/skill-creator/scripts/package_skill.py +136 -0
- package/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/skills/skill-creator/scripts/run_eval.py +310 -0
- package/skills/skill-creator/scripts/run_loop.py +328 -0
- package/skills/skill-creator/scripts/utils.py +47 -0
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import {
|
|
5
|
+
copySubagentConfigSample,
|
|
6
|
+
ensureSessionFileLink,
|
|
7
|
+
existingSubagentConfigFiles,
|
|
8
|
+
findSubagentSessionByFile,
|
|
9
|
+
getActiveSubagentPresetName,
|
|
10
|
+
getDefaultSubagentConfigPath,
|
|
11
|
+
getSessionSubagentPresetOverride,
|
|
12
|
+
getSubagentConfigInitTargetPath,
|
|
13
|
+
getSubagentConfigSamplePath,
|
|
14
|
+
getSubagentPresetSelectionPath,
|
|
15
|
+
getRunState,
|
|
16
|
+
listRunDirs,
|
|
17
|
+
listSubagentSessionRecords,
|
|
18
|
+
loadSubagentConfig,
|
|
19
|
+
readParentSessionLink,
|
|
20
|
+
readReturnSessionLink,
|
|
21
|
+
resolveRunDir,
|
|
22
|
+
setActiveSubagentPreset,
|
|
23
|
+
setSessionSubagentPresetOverride,
|
|
24
|
+
shouldPersistSubagentSessions,
|
|
25
|
+
stopAgents,
|
|
26
|
+
validateBasename,
|
|
27
|
+
writeParentSessionLink,
|
|
28
|
+
writeReturnSessionLink,
|
|
29
|
+
} from "./lib.js";
|
|
30
|
+
import { formatAgentStatus } from "./format.js";
|
|
31
|
+
import type { SubagentPreset } from "./lib.js";
|
|
32
|
+
|
|
33
|
+
interface CommandContext {
|
|
34
|
+
cwd: string;
|
|
35
|
+
hasUI: boolean;
|
|
36
|
+
ui: {
|
|
37
|
+
notify(message: string, type?: "info" | "warning" | "error"): void;
|
|
38
|
+
select(title: string, options: string[]): Promise<string | undefined>;
|
|
39
|
+
};
|
|
40
|
+
waitForIdle?: () => Promise<void>;
|
|
41
|
+
sessionManager: { getSessionFile(): string | undefined };
|
|
42
|
+
switchSession(sessionPath: string, options?: { withSession?: (ctx: CommandContext) => Promise<void> }): Promise<{ cancelled: boolean }>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type MessageSender = ExtensionAPI & {
|
|
46
|
+
sendUserMessage?: (message: string) => void;
|
|
47
|
+
sendMessage?: unknown;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const CLEAR_ACTIVE_PRESET_LABEL = "Use no active preset";
|
|
51
|
+
const COPY_SAMPLE_CONFIG_LABEL = "Copy sample asyncSubagents config";
|
|
52
|
+
|
|
53
|
+
export const ULTRAWORK_PROMPT = `Run ultrawork mode for the current objective.
|
|
54
|
+
|
|
55
|
+
Use subagents when independent parallel tracks help. Pick subagentType from configured roles: quick, scan, research, docs, frontend, implement, tests, review, deep, vision. Use review for security/performance/audit tracks, implement for refactors, deep for debugging/root-cause. Use frontend for UI/UX and visual frontend implementation; use vision only for screenshots/images when the parent model is a non-vision GLM-series model.
|
|
56
|
+
|
|
57
|
+
Keep parent context lean: spawn for broad parallel work, read results only when needed, and finish unless genuinely blocked.`;
|
|
58
|
+
|
|
59
|
+
const HYPERPLAN_PROMPT = `Run hyperplan mode for the current objective.
|
|
60
|
+
|
|
61
|
+
Before implementation, use subagents to pressure-test the plan with configured roles such as deep, implement, frontend, tests, review, and docs. Synthesize the strongest objections into a revised plan before editing.`;
|
|
62
|
+
|
|
63
|
+
export function buildUltraworkPrompt(objective: string): string {
|
|
64
|
+
const trimmed = objective.trim();
|
|
65
|
+
return trimmed
|
|
66
|
+
? `${ULTRAWORK_PROMPT}\n\nObjective:\n${trimmed}`
|
|
67
|
+
: ULTRAWORK_PROMPT;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function isUltraworkEnvEnabled(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
71
|
+
const value = env.ULTRAWORK;
|
|
72
|
+
return typeof value === "string" && /^(1|true|yes|on|run)$/i.test(value.trim());
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function registerCommands(pi: ExtensionAPI): void {
|
|
76
|
+
const persistSessions = shouldPersistSubagentSessions();
|
|
77
|
+
registerPresetCommands(pi);
|
|
78
|
+
registerOrchestrationCommands(pi);
|
|
79
|
+
|
|
80
|
+
pi.registerCommand("sub-status", {
|
|
81
|
+
description: "Show status of async sub-agents in a run directory",
|
|
82
|
+
handler: async (args: string, ctx: CommandContext) => {
|
|
83
|
+
if (!ctx.hasUI) return;
|
|
84
|
+
|
|
85
|
+
const runDir = args.trim() || listRunDirs(ctx.cwd)[0] || "";
|
|
86
|
+
if (!runDir) {
|
|
87
|
+
ctx.ui.notify("Usage: /sub-status [run-dir]", "warning");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const resolved = resolveRunDir(ctx.cwd, runDir);
|
|
92
|
+
const state = getRunState(resolved);
|
|
93
|
+
|
|
94
|
+
if (state.agents.length === 0) {
|
|
95
|
+
ctx.ui.notify(`No agents found in ${resolved}`, "warning");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const lines = state.agents.map((a) => `${formatAgentStatus(a.status)} ${a.id}`);
|
|
100
|
+
ctx.ui.notify(lines.join("\n"), "info");
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if (persistSessions) registerSessionCommands(pi);
|
|
105
|
+
|
|
106
|
+
pi.registerCommand("sub-stop", {
|
|
107
|
+
description: "Stop running async sub-agents in a run directory",
|
|
108
|
+
handler: async (args: string, ctx: CommandContext) => {
|
|
109
|
+
if (!ctx.hasUI) return;
|
|
110
|
+
|
|
111
|
+
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
112
|
+
const force = parts.includes("--force") || parts.includes("-f");
|
|
113
|
+
const values = parts.filter((part) => part !== "--force" && part !== "-f");
|
|
114
|
+
const runDirArg = values.shift();
|
|
115
|
+
if (!runDirArg) {
|
|
116
|
+
ctx.ui.notify("Usage: /sub-stop <run-dir> [agent-id ...] [--force]", "warning");
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
for (const id of values) validateBasename(id, "agentId");
|
|
122
|
+
const resolved = resolveRunDir(ctx.cwd, runDirArg);
|
|
123
|
+
const results = stopAgents(resolved, values.length ? values : undefined, { signal: force ? "SIGKILL" : "SIGTERM" });
|
|
124
|
+
|
|
125
|
+
if (results.length === 0) {
|
|
126
|
+
ctx.ui.notify(`No agents found in ${resolved}`, "warning");
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const lines = results.map((result) => {
|
|
131
|
+
if (result.stopped) return `[stopped] ${result.id}${result.pid ? ` (pid ${result.pid})` : ""}`;
|
|
132
|
+
const suffix = result.error ? `error=${result.error}` : result.message;
|
|
133
|
+
return `${formatAgentStatus(result.previousStatus)} ${result.id}: ${suffix}`;
|
|
134
|
+
});
|
|
135
|
+
ctx.ui.notify(lines.join("\n"), results.some((result) => result.error) ? "error" : "info");
|
|
136
|
+
} catch (error) {
|
|
137
|
+
ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function registerOrchestrationCommands(pi: MessageSender): void {
|
|
144
|
+
pi.registerCommand("ultrawork", {
|
|
145
|
+
description: "Start an oh-my-openagent-style parallel sub-agent workflow for the current objective",
|
|
146
|
+
handler: async (args: string, ctx: CommandContext) => triggerOrchestrationPrompt(pi, ctx, args, ULTRAWORK_PROMPT, "ultrawork"),
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
pi.registerCommand("ulw", {
|
|
150
|
+
description: "Alias for /ultrawork",
|
|
151
|
+
handler: async (args: string, ctx: CommandContext) => triggerOrchestrationPrompt(pi, ctx, args, ULTRAWORK_PROMPT, "ultrawork"),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
pi.registerCommand("hyperplan", {
|
|
155
|
+
description: "Spawn hostile planning critics before implementation",
|
|
156
|
+
handler: async (args: string, ctx: CommandContext) => triggerOrchestrationPrompt(pi, ctx, args, HYPERPLAN_PROMPT, "hyperplan"),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function triggerOrchestrationPrompt(
|
|
161
|
+
pi: MessageSender,
|
|
162
|
+
ctx: CommandContext,
|
|
163
|
+
args: string,
|
|
164
|
+
basePrompt: string,
|
|
165
|
+
modeName: string,
|
|
166
|
+
): Promise<void> {
|
|
167
|
+
await ctx.waitForIdle?.();
|
|
168
|
+
const objective = args.trim();
|
|
169
|
+
const prompt = modeName === "ultrawork"
|
|
170
|
+
? buildUltraworkPrompt(objective)
|
|
171
|
+
: objective
|
|
172
|
+
? `${basePrompt}\n\nObjective:\n${objective}`
|
|
173
|
+
: basePrompt;
|
|
174
|
+
|
|
175
|
+
if (typeof pi.sendUserMessage === "function") {
|
|
176
|
+
pi.sendUserMessage(prompt);
|
|
177
|
+
} else if (typeof pi.sendMessage === "function") {
|
|
178
|
+
pi.sendMessage({ customType: `async-subagents-${modeName}`, content: prompt, display: false }, { triggerTurn: true, deliverAs: "followUp" });
|
|
179
|
+
} else {
|
|
180
|
+
ctx.ui.notify(`Cannot trigger /${modeName}: this Pi runtime does not expose sendUserMessage/sendMessage.`, "error");
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
ctx.ui.notify(`Triggered /${modeName}.`, "info");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function registerPresetCommands(pi: ExtensionAPI): void {
|
|
188
|
+
pi.registerCommand("subagent-preset", {
|
|
189
|
+
description: "Select a sub-agent preset defined in asyncSubagents config, run session <name> for a process override, or init to copy the sample config",
|
|
190
|
+
getArgumentCompletions: (prefix: string) => {
|
|
191
|
+
const names = existingSubagentConfigFiles(process.cwd()).length > 0
|
|
192
|
+
? sortedPresetNames(loadSubagentConfig(process.cwd()).presets ?? {}, getActiveSubagentPresetName())
|
|
193
|
+
: [];
|
|
194
|
+
return [...names, ...names.map((name) => `session ${name}`), "list", "path", "config", "init", "clear", "session", "session-clear"]
|
|
195
|
+
.filter((name) => name.startsWith(prefix))
|
|
196
|
+
.map((name) => ({ value: name, label: name }));
|
|
197
|
+
},
|
|
198
|
+
handler: async (args: string, ctx: CommandContext) => {
|
|
199
|
+
const name = args.trim();
|
|
200
|
+
if (!name) return showSubagentPresetSelector(ctx);
|
|
201
|
+
if (name === "session") return ctx.ui.notify("Usage: /subagent-preset session <name>", "warning");
|
|
202
|
+
if (name.startsWith("session ")) return setSessionActiveSubagentPreset(ctx, name.slice("session ".length).trim());
|
|
203
|
+
if (name === "session-clear") return clearSessionActiveSubagentPreset(ctx);
|
|
204
|
+
if (name === "list") return listSubagentPresets(ctx);
|
|
205
|
+
if (name === "path") return showSubagentPresetPaths(ctx);
|
|
206
|
+
if (name === "config") return showSubagentPresetConfigurator(ctx);
|
|
207
|
+
if (name === "init") return initSubagentConfigSample(ctx);
|
|
208
|
+
if (name === "clear") return clearActiveSubagentPreset(ctx);
|
|
209
|
+
if (existingSubagentConfigFiles(ctx.cwd).length === 0) return ctx.ui.notify(missingSubagentConfigMessage(ctx), "warning");
|
|
210
|
+
|
|
211
|
+
const config = loadSubagentConfig(ctx.cwd);
|
|
212
|
+
const preset = config.presets?.[name];
|
|
213
|
+
if (!preset) return ctx.ui.notify(`Unknown sub-agent preset "${name}". Define it in asyncSubagents config or run /subagent-preset list.`, "error");
|
|
214
|
+
setActiveSubagentPreset(name);
|
|
215
|
+
notifyActiveSubagentPreset(ctx, name, preset);
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
pi.registerCommand("subagent-preset-config", {
|
|
220
|
+
description: "Select sub-agent presets defined in asyncSubagents config",
|
|
221
|
+
handler: async (_args: string, ctx: CommandContext) => showSubagentPresetConfigurator(ctx),
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async function showSubagentPresetSelector(ctx: CommandContext): Promise<void> {
|
|
226
|
+
if (!ctx.hasUI) return ctx.ui.notify("Sub-agent preset selector requires interactive UI. Use /subagent-preset <name>.", "warning");
|
|
227
|
+
if (existingSubagentConfigFiles(ctx.cwd).length === 0) return showMissingSubagentConfigSelector(ctx);
|
|
228
|
+
|
|
229
|
+
const config = loadSubagentConfig(ctx.cwd);
|
|
230
|
+
const activePreset = getActiveSubagentPresetName();
|
|
231
|
+
const presets = config.presets ?? {};
|
|
232
|
+
const names = sortedPresetNames(presets, activePreset);
|
|
233
|
+
const presetLabels = names.map((name) => subagentPresetLabel(name, presets[name], activePreset));
|
|
234
|
+
const labels = [...presetLabels];
|
|
235
|
+
if (activePreset) labels.push(CLEAR_ACTIVE_PRESET_LABEL);
|
|
236
|
+
if (labels.length === 0) {
|
|
237
|
+
ctx.ui.notify("No sub-agent presets are defined in asyncSubagents config.", "warning");
|
|
238
|
+
showSubagentPresetPaths(ctx);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const labelToName = new Map(presetLabels.map((label, index) => [label, names[index]]));
|
|
242
|
+
const selected = await ctx.ui.select(names.length > 0 ? "Select active sub-agent preset" : "No sub-agent presets in asyncSubagents config", labels);
|
|
243
|
+
if (!selected) return;
|
|
244
|
+
if (selected === CLEAR_ACTIVE_PRESET_LABEL) return clearActiveSubagentPreset(ctx);
|
|
245
|
+
|
|
246
|
+
const name = labelToName.get(selected);
|
|
247
|
+
if (!name) return;
|
|
248
|
+
setActiveSubagentPreset(name);
|
|
249
|
+
notifyActiveSubagentPreset(ctx, name, presets[name]);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async function showSubagentPresetConfigurator(ctx: CommandContext): Promise<void> {
|
|
253
|
+
if (!ctx.hasUI) return ctx.ui.notify("Sub-agent preset selector requires interactive UI.", "warning");
|
|
254
|
+
return showSubagentPresetSelector(ctx);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async function showMissingSubagentConfigSelector(ctx: CommandContext): Promise<void> {
|
|
258
|
+
const selected = await ctx.ui.select("No asyncSubagents config found", [COPY_SAMPLE_CONFIG_LABEL]);
|
|
259
|
+
if (selected === COPY_SAMPLE_CONFIG_LABEL) initSubagentConfigSample(ctx);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function listSubagentPresets(ctx: CommandContext): void {
|
|
263
|
+
if (existingSubagentConfigFiles(ctx.cwd).length === 0) {
|
|
264
|
+
ctx.ui.notify(missingSubagentConfigMessage(ctx), "warning");
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const config = loadSubagentConfig(ctx.cwd);
|
|
268
|
+
const activePreset = getActiveSubagentPresetName();
|
|
269
|
+
const presets = config.presets ?? {};
|
|
270
|
+
const names = sortedPresetNames(presets, activePreset);
|
|
271
|
+
if (names.length === 0) return ctx.ui.notify("No sub-agent presets are defined in asyncSubagents config.", "warning");
|
|
272
|
+
ctx.ui.notify([
|
|
273
|
+
"Sub-agent presets from asyncSubagents config:",
|
|
274
|
+
...names.map((name) => `- ${subagentPresetLabel(name, presets[name], activePreset)}`),
|
|
275
|
+
].join("\n"), "info");
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function showSubagentPresetPaths(ctx: CommandContext): void {
|
|
279
|
+
ctx.ui.notify([
|
|
280
|
+
"Preset definitions: asyncSubagents in ~/.config/pi/pi-tools-suite.jsonc, $PI_CONFIG_DIR/pi-tools-suite.jsonc, or project .pi/pi-tools-suite.jsonc",
|
|
281
|
+
"Explicit override files are still supported via ASYNC_SUBAGENTS_CONFIG / PI_SUBAGENTS_CONFIG.",
|
|
282
|
+
`Default config target: ${getDefaultSubagentConfigPath()}`,
|
|
283
|
+
`Sample config: ${getSubagentConfigSamplePath()}`,
|
|
284
|
+
`Copy sample target: ${getSubagentConfigInitTargetPath(ctx.cwd)}`,
|
|
285
|
+
`Active selection state: ${getSubagentPresetSelectionPath()}`,
|
|
286
|
+
`Session override: ${formatSessionPresetOverride()}`,
|
|
287
|
+
"Use /subagent-preset session <name> to override only the current Pi process; use /subagent-preset session-clear to clear that runtime override.",
|
|
288
|
+
"Run /subagent-preset init to copy the bundled sample only when no config exists.",
|
|
289
|
+
].join("\n"), "info");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function initSubagentConfigSample(ctx: CommandContext): void {
|
|
293
|
+
try {
|
|
294
|
+
const result = copySubagentConfigSample(ctx.cwd);
|
|
295
|
+
if (result.copied) {
|
|
296
|
+
ctx.ui.notify(`Copied sample asyncSubagents config:\n${result.samplePath}\n→ ${result.targetPath}`, "info");
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
ctx.ui.notify(`AsyncSubagents config already exists; not overwriting:\n${result.existingFiles.join("\n") || result.targetPath}`, "warning");
|
|
300
|
+
} catch (error) {
|
|
301
|
+
ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function missingSubagentConfigMessage(ctx: CommandContext): string {
|
|
306
|
+
return [
|
|
307
|
+
"No asyncSubagents config found in pi-tools-suite config.",
|
|
308
|
+
`Sample config: ${getSubagentConfigSamplePath()}`,
|
|
309
|
+
`Copy target: ${getSubagentConfigInitTargetPath(ctx.cwd)}`,
|
|
310
|
+
"Run /subagent-preset init to copy the bundled sample into the shared config.",
|
|
311
|
+
].join("\n");
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function clearActiveSubagentPreset(ctx: CommandContext): void {
|
|
315
|
+
setActiveSubagentPreset(undefined);
|
|
316
|
+
const override = getSessionSubagentPresetOverride();
|
|
317
|
+
ctx.ui.notify(override
|
|
318
|
+
? `Saved sub-agent preset selection cleared, but ${formatSessionPresetOverride()} still overrides this session.`
|
|
319
|
+
: "Sub-agent presets disabled. Future sub-agents use task/profile/env defaults until another preset is selected.", "info");
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function setSessionActiveSubagentPreset(ctx: CommandContext, name: string): void {
|
|
323
|
+
if (!name) return ctx.ui.notify("Usage: /subagent-preset session <name>", "warning");
|
|
324
|
+
if (existingSubagentConfigFiles(ctx.cwd).length === 0) return ctx.ui.notify(missingSubagentConfigMessage(ctx), "warning");
|
|
325
|
+
const config = loadSubagentConfig(ctx.cwd);
|
|
326
|
+
const preset = config.presets?.[name];
|
|
327
|
+
if (!preset) return ctx.ui.notify(`Unknown sub-agent preset "${name}". Define it in asyncSubagents config or run /subagent-preset list.`, "error");
|
|
328
|
+
setSessionSubagentPresetOverride(name);
|
|
329
|
+
ctx.ui.notify(`Session-only sub-agent preset "${name}": ${subagentPresetDescription(preset)}\nApplies to future sub-agent spawns only until this Pi process exits or /subagent-preset session-clear is run. Saved preset selection is unchanged.`, "info");
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function clearSessionActiveSubagentPreset(ctx: CommandContext): void {
|
|
333
|
+
setSessionSubagentPresetOverride(undefined);
|
|
334
|
+
const envOverride = typeof process.env.AGENTS_PRESET === "string" && process.env.AGENTS_PRESET.trim() ? process.env.AGENTS_PRESET.trim() : undefined;
|
|
335
|
+
ctx.ui.notify(envOverride
|
|
336
|
+
? `Runtime session override cleared, but AGENTS_PRESET=${envOverride} still overrides this process.`
|
|
337
|
+
: "Runtime session sub-agent preset override cleared. Future sub-agents use AGENTS_PRESET, saved preset, or task/profile/env defaults.", "info");
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function formatSessionPresetOverride(): string {
|
|
341
|
+
const override = getSessionSubagentPresetOverride();
|
|
342
|
+
if (!override) return "not set";
|
|
343
|
+
const envOverride = typeof process.env.AGENTS_PRESET === "string" && process.env.AGENTS_PRESET.trim() ? process.env.AGENTS_PRESET.trim() : undefined;
|
|
344
|
+
return envOverride === override ? `AGENTS_PRESET=${override}` : `runtime=${override}`;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function notifyActiveSubagentPreset(ctx: CommandContext, name: string, preset: SubagentPreset): void {
|
|
348
|
+
ctx.ui.notify(`Active sub-agent preset "${name}": ${subagentPresetDescription(preset)}\nApplies to future sub-agent spawns in all sessions until changed.`, "info");
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function subagentPresetLabel(name: string, preset: SubagentPreset, activePreset?: string): string {
|
|
352
|
+
return `${name} — ${subagentPresetDescription(preset)}${activePreset === name ? " ✓ active" : ""}`;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function sortedPresetNames(presets: Record<string, SubagentPreset>, activePreset?: string): string[] {
|
|
356
|
+
const names = Object.keys(presets).sort();
|
|
357
|
+
return activePreset && presets[activePreset]
|
|
358
|
+
? [activePreset, ...names.filter((name) => name !== activePreset)]
|
|
359
|
+
: names;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function subagentPresetDescription(preset: SubagentPreset): string {
|
|
363
|
+
const parts: string[] = [];
|
|
364
|
+
if (preset.description) parts.push(preset.description);
|
|
365
|
+
if (preset.model) parts.push(`model:${preset.model}`);
|
|
366
|
+
if (preset.fallbackModels && preset.fallbackModels.length > 0) parts.push(`fallbacks:${preset.fallbackModels.join(",")}`);
|
|
367
|
+
if (preset.thinking) parts.push(`thinking:${preset.thinking}`);
|
|
368
|
+
if (preset.extraArgs && preset.extraArgs.length > 0) parts.push(`args:${preset.extraArgs.join(" ")}`);
|
|
369
|
+
if (preset.types && Object.keys(preset.types).length > 0) parts.push(`types:${Object.keys(preset.types).sort().join(",")}`);
|
|
370
|
+
return parts.length > 0 ? parts.join(", ") : "empty";
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function registerSessionCommands(pi: ExtensionAPI): void {
|
|
374
|
+
pi.registerCommand("sub-open", {
|
|
375
|
+
description: "Switch to a persisted sub-agent session. Use /sub-back to return.",
|
|
376
|
+
getArgumentCompletions: (prefix: string) => completeRunAndAgent(prefix, process.cwd()),
|
|
377
|
+
handler: async (args: string, ctx: CommandContext) => {
|
|
378
|
+
if (!ctx.hasUI) return;
|
|
379
|
+
|
|
380
|
+
try {
|
|
381
|
+
const target = await chooseOpenTarget(args, ctx);
|
|
382
|
+
if (!target) return;
|
|
383
|
+
|
|
384
|
+
const sessionFile = ensureSessionFileLink(target.agentDir);
|
|
385
|
+
if (!sessionFile) {
|
|
386
|
+
ctx.ui.notify(`No session file recorded for ${target.agentId}. The agent may not have produced a persisted session yet.`, "warning");
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (!fs.existsSync(sessionFile)) {
|
|
390
|
+
ctx.ui.notify(`Sub-agent session is known but not flushed yet:\n${sessionFile}\nWait until the agent produces output or completes.`, "warning");
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const currentSession = ctx.sessionManager.getSessionFile();
|
|
395
|
+
if (!currentSession) {
|
|
396
|
+
ctx.ui.notify("Current session is ephemeral; cannot open a sub-agent session with /sub-back return support.", "error");
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
writeReturnSessionLink(target.agentDir, currentSession);
|
|
401
|
+
if (!readParentSessionLink(target.agentDir)) writeParentSessionLink(target.agentDir, currentSession);
|
|
402
|
+
|
|
403
|
+
const runName = path.basename(target.runDir);
|
|
404
|
+
const agentId = target.agentId;
|
|
405
|
+
const result = await ctx.switchSession(sessionFile, {
|
|
406
|
+
withSession: async (nextCtx) => {
|
|
407
|
+
nextCtx.ui.notify(`Opened sub-agent ${agentId} from ${runName}. Use /sub-back to return.`, "info");
|
|
408
|
+
},
|
|
409
|
+
});
|
|
410
|
+
if (result.cancelled) ctx.ui.notify("Sub-agent session switch cancelled.", "warning");
|
|
411
|
+
} catch (error) {
|
|
412
|
+
ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
pi.registerCommand("sub-back", {
|
|
418
|
+
description: "Return from a sub-agent session opened with /sub-open",
|
|
419
|
+
handler: async (_args: string, ctx: CommandContext) => {
|
|
420
|
+
if (!ctx.hasUI) return;
|
|
421
|
+
|
|
422
|
+
try {
|
|
423
|
+
const currentSession = ctx.sessionManager.getSessionFile();
|
|
424
|
+
const record = findSubagentSessionByFile(ctx.cwd, currentSession);
|
|
425
|
+
if (!record) {
|
|
426
|
+
ctx.ui.notify("This session is not a known sub-agent session.", "warning");
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const returnSession = readReturnSessionLink(record.agentDir) ?? readParentSessionLink(record.agentDir);
|
|
431
|
+
if (!returnSession) {
|
|
432
|
+
ctx.ui.notify(`No return session recorded for ${record.agentId}.`, "error");
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
if (!fs.existsSync(returnSession)) {
|
|
436
|
+
ctx.ui.notify(`Return session does not exist:\n${returnSession}`, "error");
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const agentId = record.agentId;
|
|
441
|
+
const runName = record.runName;
|
|
442
|
+
const result = await ctx.switchSession(returnSession, {
|
|
443
|
+
withSession: async (nextCtx) => {
|
|
444
|
+
nextCtx.ui.notify(`Returned from sub-agent ${agentId} (${runName}).`, "info");
|
|
445
|
+
},
|
|
446
|
+
});
|
|
447
|
+
if (result.cancelled) ctx.ui.notify("Return session switch cancelled.", "warning");
|
|
448
|
+
} catch (error) {
|
|
449
|
+
ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
pi.registerCommand("sub-where", {
|
|
455
|
+
description: "Show whether the current session belongs to a sub-agent",
|
|
456
|
+
handler: async (_args: string, ctx: CommandContext) => {
|
|
457
|
+
if (!ctx.hasUI) return;
|
|
458
|
+
const currentSession = ctx.sessionManager.getSessionFile();
|
|
459
|
+
const record = findSubagentSessionByFile(ctx.cwd, currentSession);
|
|
460
|
+
if (!record) {
|
|
461
|
+
ctx.ui.notify(`Current session is not a known sub-agent session.\n${currentSession ?? "ephemeral session"}`, "info");
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
const returnSession = readReturnSessionLink(record.agentDir) ?? readParentSessionLink(record.agentDir) ?? "not recorded";
|
|
465
|
+
ctx.ui.notify([
|
|
466
|
+
`Sub-agent session: ${record.agentId}`,
|
|
467
|
+
`Run: ${record.runDir}`,
|
|
468
|
+
`Status: ${record.state ? formatAgentStatus(record.state.status) : "unknown"}`,
|
|
469
|
+
`Return: ${returnSession}`,
|
|
470
|
+
].join("\n"), "info");
|
|
471
|
+
},
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
async function chooseOpenTarget(args: string, ctx: CommandContext): Promise<{ runDir: string; agentDir: string; agentId: string } | undefined> {
|
|
476
|
+
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
477
|
+
let runDirArg = parts[0];
|
|
478
|
+
let agentId = parts[1];
|
|
479
|
+
|
|
480
|
+
if (parts.length > 2) throw new Error("Usage: /sub-open [run-dir] [agent-id]");
|
|
481
|
+
|
|
482
|
+
if (!runDirArg) {
|
|
483
|
+
const selectedRun = await ctx.ui.select("Open sub-agent run:", listRunDirs(ctx.cwd));
|
|
484
|
+
if (!selectedRun) return undefined;
|
|
485
|
+
runDirArg = selectedRun;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const runDir = resolveRunDir(ctx.cwd, runDirArg);
|
|
489
|
+
if (!fs.existsSync(runDir) || !fs.statSync(runDir).isDirectory())
|
|
490
|
+
throw new Error(`Run directory not found: ${runDir}`);
|
|
491
|
+
|
|
492
|
+
const agentIds = getRunState(runDir).agents.map((agent) => agent.id).sort();
|
|
493
|
+
if (agentIds.length === 0) throw new Error(`No agents found in ${runDir}`);
|
|
494
|
+
|
|
495
|
+
if (!agentId) {
|
|
496
|
+
const selectedAgent = await ctx.ui.select("Open sub-agent:", agentIds);
|
|
497
|
+
if (!selectedAgent) return undefined;
|
|
498
|
+
agentId = selectedAgent;
|
|
499
|
+
}
|
|
500
|
+
validateBasename(agentId, "agentId");
|
|
501
|
+
if (!agentIds.includes(agentId)) throw new Error(`Agent "${agentId}" not found in ${runDir}`);
|
|
502
|
+
|
|
503
|
+
return { runDir, agentId, agentDir: path.join(runDir, agentId) };
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function completeRunAndAgent(prefix: string, cwd: string): { value: string; label: string; description?: string }[] | null {
|
|
507
|
+
const records = listSubagentSessionRecords(cwd);
|
|
508
|
+
const items = records.map((record) => {
|
|
509
|
+
const value = `${record.runDir} ${record.agentId}`;
|
|
510
|
+
return {
|
|
511
|
+
value,
|
|
512
|
+
label: `${record.runName} ${record.agentId}`,
|
|
513
|
+
description: record.state?.status,
|
|
514
|
+
};
|
|
515
|
+
});
|
|
516
|
+
const filtered = items.filter((item) => item.value.startsWith(prefix) || item.label.includes(prefix));
|
|
517
|
+
return filtered.length ? filtered : null;
|
|
518
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const DEFAULT_SPAWN_WATCH_SECONDS = 300;
|
|
2
|
+
export const DEFAULT_UPDATE_INTERVAL_SECONDS = 1;
|
|
3
|
+
export const MAX_WATCH_SECONDS = 300;
|
|
4
|
+
|
|
5
|
+
export const INLINE_RENDERING = {
|
|
6
|
+
// Newer runtimes use inline/mergeCallAndResult, older runtimes use renderShell: "self".
|
|
7
|
+
// Keep all three so extension tools render without the default tinted tool box where supported.
|
|
8
|
+
mergeCallAndResult: true,
|
|
9
|
+
inline: true,
|
|
10
|
+
renderShell: "self",
|
|
11
|
+
} as const;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { isGptLikeModel } from "./ultrawork-auto.js";
|
|
2
|
+
|
|
3
|
+
export type AgentStrategyName = "parallel-first" | "deep-work";
|
|
4
|
+
|
|
5
|
+
export interface AgentStrategyOptions {
|
|
6
|
+
modelRef?: string;
|
|
7
|
+
customPrompt?: boolean;
|
|
8
|
+
env?: NodeJS.ProcessEnv;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const FALSE_ENV_PATTERN = /^(0|false|off|no|disabled|none)$/i;
|
|
12
|
+
const TRUE_ENV_PATTERN = /^(1|true|on|yes|auto)$/i;
|
|
13
|
+
|
|
14
|
+
const PARALLEL_FIRST_STRATEGY_PROMPT = `<agent_strategy name="parallel-first">
|
|
15
|
+
This is an orchestration hint for Pi, not a replacement for the user's instructions.
|
|
16
|
+
|
|
17
|
+
Default posture: orchestration-first for non-GPT models. For broad, multi-file, ambiguous, review/audit, frontend, test-strategy, architecture, or root-cause work, prefer ultrawork mode: split independent tracks and spawn focused async subagents with the configured roles. Keep the parent context lean, collect compact results only when needed, synthesize the findings, then verify before finishing.
|
|
18
|
+
|
|
19
|
+
Do not over-delegate trivial work. For a simple question, one known file, exact lookup, typo, or narrow edit, solve directly with the cheapest suitable tool.
|
|
20
|
+
</agent_strategy>`;
|
|
21
|
+
|
|
22
|
+
const DEEP_WORK_STRATEGY_PROMPT = `<agent_strategy name="deep-work">
|
|
23
|
+
This is a GPT-compatible execution hint for Pi, not a replacement for the user's instructions.
|
|
24
|
+
|
|
25
|
+
Default posture: autonomous deep worker. Build context directly, make concrete progress, edit and verify end-to-end. Use async subagents and ultrawork mode when the user asks for parallel/delegated work or when independent tracks will clearly reduce risk, but do not force orchestration onto narrow tasks.
|
|
26
|
+
|
|
27
|
+
For broad work, keep delegation explicit and bounded: spawn focused review/research/tests/frontend/deep tracks, read compact results, make the final decisions in the parent session, and report only what matters.
|
|
28
|
+
</agent_strategy>`;
|
|
29
|
+
|
|
30
|
+
export function agentStrategyPrompt(options: AgentStrategyOptions = {}): string | undefined {
|
|
31
|
+
const env = options.env ?? process.env;
|
|
32
|
+
const override = strategyOverride(env);
|
|
33
|
+
if (override === "off") return undefined;
|
|
34
|
+
if (options.customPrompt && shouldSkipCustomPrompt(env)) return undefined;
|
|
35
|
+
|
|
36
|
+
const strategy = override ?? (isGptLikeModel(options.modelRef) ? "deep-work" : "parallel-first");
|
|
37
|
+
return strategy === "deep-work" ? DEEP_WORK_STRATEGY_PROMPT : PARALLEL_FIRST_STRATEGY_PROMPT;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function appendAgentStrategyPrompt(systemPrompt: string, strategyPrompt: string): string {
|
|
41
|
+
const base = systemPrompt.trimEnd();
|
|
42
|
+
return base ? `${base}\n\n${strategyPrompt}` : strategyPrompt;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function strategyOverride(env: NodeJS.ProcessEnv): AgentStrategyName | "off" | undefined {
|
|
46
|
+
const raw = firstEnv(env, "PI_AGENT_STRATEGY", "ASYNC_SUBAGENTS_AGENT_STRATEGY");
|
|
47
|
+
if (!raw) return undefined;
|
|
48
|
+
const value = normalizeStrategyName(raw);
|
|
49
|
+
if (FALSE_ENV_PATTERN.test(value)) return "off";
|
|
50
|
+
if (value === "parallel-first") return "parallel-first";
|
|
51
|
+
if (value === "deep-work") return "deep-work";
|
|
52
|
+
if (TRUE_ENV_PATTERN.test(value)) return undefined;
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function shouldSkipCustomPrompt(env: NodeJS.ProcessEnv): boolean {
|
|
57
|
+
const raw = firstEnv(env, "PI_AGENT_STRATEGY_WITH_CUSTOM_PROMPT", "ASYNC_SUBAGENTS_AGENT_STRATEGY_WITH_CUSTOM_PROMPT");
|
|
58
|
+
return raw ? !TRUE_ENV_PATTERN.test(raw.trim()) : true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function normalizeStrategyName(raw: string): string {
|
|
62
|
+
const value = raw.trim().toLowerCase().replace(/_/g, "-");
|
|
63
|
+
if (value === "parallel" || value === "parallel-first") return "parallel-first";
|
|
64
|
+
if (value === "deep" || value === "deep-work") return "deep-work";
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function firstEnv(env: NodeJS.ProcessEnv, ...keys: string[]): string | undefined {
|
|
69
|
+
for (const key of keys) {
|
|
70
|
+
const value = env[key];
|
|
71
|
+
if (typeof value === "string" && value.trim()) return value;
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|