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,166 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_EVENTS_LOG_MAX_BYTES = 0;
|
|
5
|
+
export const DEFAULT_DEBUG_EVENTS_LOG_MAX_BYTES = 32 * 1024 * 1024;
|
|
6
|
+
export const DEFAULT_STDERR_LOG_MAX_BYTES = 8 * 1024 * 1024;
|
|
7
|
+
export const DEFAULT_RPC_EVENT_LINE_MAX_CHARS = 8 * 1024 * 1024;
|
|
8
|
+
|
|
9
|
+
export interface SubagentLogLimits {
|
|
10
|
+
eventsMaxBytes: number;
|
|
11
|
+
stderrMaxBytes: number;
|
|
12
|
+
rpcEventLineMaxChars: number;
|
|
13
|
+
debugLogs: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface BoundedFileWriter {
|
|
17
|
+
readonly bytesWritten: number;
|
|
18
|
+
readonly truncated: boolean;
|
|
19
|
+
write(chunk: string | Buffer): void;
|
|
20
|
+
end(): void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface DeferredFileWriter extends BoundedFileWriter {
|
|
24
|
+
flush(): void;
|
|
25
|
+
discard(): void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function resolveSubagentLogLimits(env: NodeJS.ProcessEnv = process.env): SubagentLogLimits {
|
|
29
|
+
const debugLogs = isTruthyEnv(env.ASYNC_SUBAGENTS_DEBUG_LOGS) || isTruthyEnv(env.PI_SUBAGENTS_DEBUG_LOGS);
|
|
30
|
+
return {
|
|
31
|
+
eventsMaxBytes: envLimit(env, ["ASYNC_SUBAGENTS_MAX_EVENTS_BYTES", "PI_SUBAGENTS_MAX_EVENTS_BYTES"], debugLogs ? DEFAULT_DEBUG_EVENTS_LOG_MAX_BYTES : DEFAULT_EVENTS_LOG_MAX_BYTES),
|
|
32
|
+
stderrMaxBytes: envLimit(env, ["ASYNC_SUBAGENTS_MAX_STDERR_BYTES", "PI_SUBAGENTS_MAX_STDERR_BYTES"], DEFAULT_STDERR_LOG_MAX_BYTES),
|
|
33
|
+
rpcEventLineMaxChars: envLimit(env, ["ASYNC_SUBAGENTS_MAX_RPC_LINE_CHARS", "PI_SUBAGENTS_MAX_RPC_LINE_CHARS"], DEFAULT_RPC_EVENT_LINE_MAX_CHARS),
|
|
34
|
+
debugLogs,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function createBoundedFileWriter(filePath: string, maxBytes: number, label: string): BoundedFileWriter {
|
|
39
|
+
const limit = Math.max(0, Math.floor(maxBytes));
|
|
40
|
+
let fd: number | undefined;
|
|
41
|
+
let written = 0;
|
|
42
|
+
let truncated = false;
|
|
43
|
+
let closed = false;
|
|
44
|
+
|
|
45
|
+
function open(): number {
|
|
46
|
+
if (fd === undefined) fd = fs.openSync(filePath, "w");
|
|
47
|
+
return fd;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function writeWithinLimit(buffer: Buffer): void {
|
|
51
|
+
if (closed || buffer.length === 0 || written >= limit) return;
|
|
52
|
+
const slice = buffer.subarray(0, Math.min(buffer.length, limit - written));
|
|
53
|
+
written += slice.length;
|
|
54
|
+
fs.writeSync(open(), slice);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
get bytesWritten() {
|
|
59
|
+
return written;
|
|
60
|
+
},
|
|
61
|
+
get truncated() {
|
|
62
|
+
return truncated;
|
|
63
|
+
},
|
|
64
|
+
write(chunk: string | Buffer): void {
|
|
65
|
+
if (closed) return;
|
|
66
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
67
|
+
if (limit === 0) {
|
|
68
|
+
if (!truncated) truncated = true;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (written + buffer.length <= limit) {
|
|
72
|
+
written += buffer.length;
|
|
73
|
+
fs.writeSync(open(), buffer);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (!truncated) {
|
|
77
|
+
const marker = Buffer.from(`\n[${label} truncated after ${written} bytes; dropped additional output starting with ${buffer.length} bytes]\n`, "utf8");
|
|
78
|
+
const availableForChunk = Math.max(0, limit - written - marker.length);
|
|
79
|
+
if (availableForChunk > 0) writeWithinLimit(buffer.subarray(0, availableForChunk));
|
|
80
|
+
truncated = true;
|
|
81
|
+
writeWithinLimit(marker);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
end(): void {
|
|
85
|
+
if (closed) return;
|
|
86
|
+
closed = true;
|
|
87
|
+
if (fd !== undefined) fs.closeSync(fd);
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function createDeferredFileWriter(filePath: string, maxBytes: number, label: string): DeferredFileWriter {
|
|
93
|
+
const limit = Math.max(0, Math.floor(maxBytes));
|
|
94
|
+
const chunks: Buffer[] = [];
|
|
95
|
+
let written = 0;
|
|
96
|
+
let truncated = false;
|
|
97
|
+
let closed = false;
|
|
98
|
+
|
|
99
|
+
function appendWithinLimit(buffer: Buffer): void {
|
|
100
|
+
if (closed || buffer.length === 0 || written >= limit) return;
|
|
101
|
+
const slice = buffer.subarray(0, Math.min(buffer.length, limit - written));
|
|
102
|
+
written += slice.length;
|
|
103
|
+
chunks.push(Buffer.from(slice));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function write(chunk: string | Buffer): void {
|
|
107
|
+
if (closed) return;
|
|
108
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
109
|
+
if (limit === 0) {
|
|
110
|
+
if (!truncated) truncated = true;
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (written + buffer.length <= limit) {
|
|
114
|
+
written += buffer.length;
|
|
115
|
+
chunks.push(Buffer.from(buffer));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (!truncated) {
|
|
119
|
+
const marker = Buffer.from(`\n[${label} truncated after ${written} bytes; dropped additional output starting with ${buffer.length} bytes]\n`, "utf8");
|
|
120
|
+
const availableForChunk = Math.max(0, limit - written - marker.length);
|
|
121
|
+
if (availableForChunk > 0) appendWithinLimit(buffer.subarray(0, availableForChunk));
|
|
122
|
+
truncated = true;
|
|
123
|
+
appendWithinLimit(marker);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function discard(): void {
|
|
128
|
+
if (closed) return;
|
|
129
|
+
closed = true;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
get bytesWritten() {
|
|
134
|
+
return written;
|
|
135
|
+
},
|
|
136
|
+
get truncated() {
|
|
137
|
+
return truncated;
|
|
138
|
+
},
|
|
139
|
+
write,
|
|
140
|
+
flush(): void {
|
|
141
|
+
if (closed) return;
|
|
142
|
+
closed = true;
|
|
143
|
+
if (chunks.length === 0) return;
|
|
144
|
+
if (!fs.existsSync(path.dirname(filePath))) return;
|
|
145
|
+
fs.writeFileSync(filePath, Buffer.concat(chunks));
|
|
146
|
+
},
|
|
147
|
+
discard,
|
|
148
|
+
end(): void {
|
|
149
|
+
discard();
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function envLimit(env: NodeJS.ProcessEnv, keys: readonly string[], fallback: number): number {
|
|
155
|
+
for (const key of keys) {
|
|
156
|
+
const value = env[key]?.trim();
|
|
157
|
+
if (!value) continue;
|
|
158
|
+
const parsed = Number(value);
|
|
159
|
+
if (Number.isFinite(parsed) && parsed >= 0) return parsed;
|
|
160
|
+
}
|
|
161
|
+
return fallback;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function isTruthyEnv(value: string | undefined): boolean {
|
|
165
|
+
return value === "1" || value?.toLowerCase() === "true" || value?.toLowerCase() === "yes";
|
|
166
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import type { AgentCompletionHandler } from "./types.js";
|
|
4
|
+
|
|
5
|
+
const exhaustedModels = new Set<string>();
|
|
6
|
+
const exhaustedProviders = new Set<string>();
|
|
7
|
+
const fallbackByModel = new Map<string, string>();
|
|
8
|
+
const fallbackByProvider = new Map<string, string>();
|
|
9
|
+
const ANTIGRAVITY_ALL_ACCOUNTS_EXHAUSTED_MARKER = "antigravity_all_accounts_exhausted";
|
|
10
|
+
|
|
11
|
+
export interface SessionModelFallbackSelection {
|
|
12
|
+
model: string;
|
|
13
|
+
fellBack: boolean;
|
|
14
|
+
fromModel?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function selectSessionModelWithFallback(model: string | undefined, fallbackModels: string[] = []): SessionModelFallbackSelection | undefined {
|
|
18
|
+
if (!model) return undefined;
|
|
19
|
+
const chain = normalizeFallbackChain(model, fallbackModels);
|
|
20
|
+
let current = model;
|
|
21
|
+
const seen = new Set<string>();
|
|
22
|
+
|
|
23
|
+
while (isSessionModelUnavailable(current) && !seen.has(current)) {
|
|
24
|
+
seen.add(current);
|
|
25
|
+
const mapped = fallbackByModel.get(current) ?? fallbackByProvider.get(modelProvider(current));
|
|
26
|
+
if (mapped && chain.includes(mapped) && !seen.has(mapped) && !isSessionModelUnavailable(mapped)) {
|
|
27
|
+
current = mapped;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const next = firstAvailableFallback(current, chain);
|
|
32
|
+
if (!next) break;
|
|
33
|
+
fallbackByModel.set(current, next);
|
|
34
|
+
current = next;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return current === model
|
|
38
|
+
? { model, fellBack: false }
|
|
39
|
+
: { model: current, fellBack: true, fromModel: model };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function nextFallbackModel(failedModel: string | undefined, fallbackModels: string[] = []): string | undefined {
|
|
43
|
+
if (!failedModel) return undefined;
|
|
44
|
+
const chain = normalizeFallbackChain(failedModel, fallbackModels);
|
|
45
|
+
return firstAvailableFallback(failedModel, chain);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function rememberSessionModelFallback(failedModel: string | undefined, fallbackModel: string | undefined): void {
|
|
49
|
+
if (!failedModel) return;
|
|
50
|
+
exhaustedModels.add(failedModel);
|
|
51
|
+
const provider = modelProvider(failedModel);
|
|
52
|
+
if (shouldRememberProviderExhaustion(provider)) exhaustedProviders.add(provider);
|
|
53
|
+
if (fallbackModel && fallbackModel !== failedModel) {
|
|
54
|
+
fallbackByModel.set(failedModel, fallbackModel);
|
|
55
|
+
if (shouldRememberProviderExhaustion(provider) && modelProvider(fallbackModel) !== provider) fallbackByProvider.set(provider, fallbackModel);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function isQuotaLimitCompletion(completion: Parameters<AgentCompletionHandler>[0], model?: string): boolean {
|
|
60
|
+
if (completion.exitCode === 0 || completion.state.status === "stopped") return false;
|
|
61
|
+
const text = [
|
|
62
|
+
readIfExists(path.join(completion.agentDir, "result.md")),
|
|
63
|
+
readIfExists(path.join(completion.agentDir, "stderr.log")),
|
|
64
|
+
readRecentEvents(completion.agentDir),
|
|
65
|
+
].filter(Boolean).join("\n").toLowerCase();
|
|
66
|
+
if (!text.trim()) return false;
|
|
67
|
+
if (modelProvider(model ?? "") === "antigravity") return text.includes(ANTIGRAVITY_ALL_ACCOUNTS_EXHAUSTED_MARKER);
|
|
68
|
+
|
|
69
|
+
return [
|
|
70
|
+
/\b429\b/,
|
|
71
|
+
/too many requests/,
|
|
72
|
+
/rate[-_\s]?limit(?:ed|s| reached| exceeded)?/,
|
|
73
|
+
/quota(?:\s+|[-_])?(?:exceeded|exhausted|limit|reached)/,
|
|
74
|
+
/insufficient[_\s-]?quota/,
|
|
75
|
+
/resource[_\s-]?exhausted/,
|
|
76
|
+
/usage(?:\s+|[-_])?limit(?:\s+|[-_])?(?:exceeded|reached)/,
|
|
77
|
+
/billing(?:\s+|[-_])?(?:hard\s+)?limit/,
|
|
78
|
+
].some((pattern) => pattern.test(text));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function resetSessionModelFallbacks(): void {
|
|
82
|
+
exhaustedModels.clear();
|
|
83
|
+
exhaustedProviders.clear();
|
|
84
|
+
fallbackByModel.clear();
|
|
85
|
+
fallbackByProvider.clear();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function normalizeFallbackChain(model: string, fallbackModels: string[]): string[] {
|
|
89
|
+
const seen = new Set<string>([model]);
|
|
90
|
+
const chain: string[] = [];
|
|
91
|
+
for (const fallback of fallbackModels) {
|
|
92
|
+
const trimmed = fallback.trim();
|
|
93
|
+
if (!trimmed || seen.has(trimmed)) continue;
|
|
94
|
+
seen.add(trimmed);
|
|
95
|
+
chain.push(trimmed);
|
|
96
|
+
}
|
|
97
|
+
return chain;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function firstAvailableFallback(failedModel: string, fallbackModels: string[]): string | undefined {
|
|
101
|
+
const failedIndex = fallbackModels.indexOf(failedModel);
|
|
102
|
+
const candidates = failedIndex >= 0 ? fallbackModels.slice(failedIndex + 1) : fallbackModels;
|
|
103
|
+
const failedProvider = modelProvider(failedModel);
|
|
104
|
+
return candidates.find((candidate) => modelProvider(candidate) !== failedProvider && !isSessionModelUnavailable(candidate));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function isSessionModelUnavailable(model: string): boolean {
|
|
108
|
+
return exhaustedModels.has(model) || exhaustedProviders.has(modelProvider(model));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function shouldRememberProviderExhaustion(provider: string): boolean {
|
|
112
|
+
return !!provider && provider !== "antigravity";
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function modelProvider(model: string): string {
|
|
116
|
+
const slash = model.indexOf("/");
|
|
117
|
+
return slash > 0 ? model.slice(0, slash) : model;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function readIfExists(file: string): string {
|
|
121
|
+
try {
|
|
122
|
+
return fs.existsSync(file) ? fs.readFileSync(file, "utf-8") : "";
|
|
123
|
+
} catch {
|
|
124
|
+
return "";
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function readRecentEvents(agentDir: string): string {
|
|
129
|
+
const text = readIfExists(path.join(agentDir, "events.jsonl"));
|
|
130
|
+
if (!text) return "";
|
|
131
|
+
const lines = text.split("\n").filter(Boolean);
|
|
132
|
+
return lines.slice(-20).join("\n");
|
|
133
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
|
|
4
|
+
export function getRunRoot(cwd: string): string {
|
|
5
|
+
return path.join(cwd, ".pi", "subagents");
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function createRunDir(cwd: string, slug?: string): string {
|
|
9
|
+
if (slug) validateBasename(slug, "slug");
|
|
10
|
+
const runRoot = getRunRoot(cwd);
|
|
11
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
12
|
+
const baseName = `${timestamp}${slug ? `-${slug}` : ""}`;
|
|
13
|
+
let runDir = path.join(runRoot, baseName);
|
|
14
|
+
let suffix = 2;
|
|
15
|
+
while (fs.existsSync(runDir)) {
|
|
16
|
+
runDir = path.join(runRoot, `${baseName}-${suffix}`);
|
|
17
|
+
suffix++;
|
|
18
|
+
}
|
|
19
|
+
fs.mkdirSync(path.join(runDir, "prompts"), { recursive: true });
|
|
20
|
+
return runDir;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function resolveRunDir(cwd: string, runDir: string): string {
|
|
24
|
+
if (path.isAbsolute(runDir)) return runDir;
|
|
25
|
+
return path.resolve(cwd, runDir);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function isDir(p: string): boolean {
|
|
29
|
+
try {
|
|
30
|
+
return fs.statSync(p).isDirectory();
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const SAFE_BASENAME = /^[A-Za-z0-9._-]+$/;
|
|
37
|
+
|
|
38
|
+
export function validateBasename(value: string, label: string): void {
|
|
39
|
+
if (!SAFE_BASENAME.test(value)) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Invalid ${label}: "${value}". Must match ${SAFE_BASENAME.source}`,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
if (value.includes("..")) {
|
|
45
|
+
throw new Error(`Invalid ${label}: "${value}". Must not contain ".."`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
|
|
4
|
+
export function getPiInvocation(args: string[]): {
|
|
5
|
+
command: string;
|
|
6
|
+
args: string[];
|
|
7
|
+
} {
|
|
8
|
+
const currentScript = process.argv[1];
|
|
9
|
+
const isBunVirtualScript = currentScript?.startsWith("/$bunfs/root/");
|
|
10
|
+
|
|
11
|
+
if (
|
|
12
|
+
currentScript &&
|
|
13
|
+
!isBunVirtualScript &&
|
|
14
|
+
fs.existsSync(currentScript) &&
|
|
15
|
+
isPiEntrypoint(currentScript)
|
|
16
|
+
) {
|
|
17
|
+
return { command: process.execPath, args: [currentScript, ...args] };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const execName = path.basename(process.execPath).toLowerCase();
|
|
21
|
+
const isGenericRuntime = /^(node|bun)(\.exe)?$/.test(execName);
|
|
22
|
+
if (!isGenericRuntime) {
|
|
23
|
+
return { command: process.execPath, args };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return { command: "pi", args };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function isPiEntrypoint(scriptPath: string): boolean {
|
|
30
|
+
const scriptName = path.basename(scriptPath).toLowerCase();
|
|
31
|
+
return (
|
|
32
|
+
/^pi(\.(cjs|js|mjs|ts))?$/.test(scriptName) ||
|
|
33
|
+
(scriptName === "cli.js" && scriptPath.includes("pi-coding-agent"))
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import * as piCodingAgent from "@earendil-works/pi-coding-agent";
|
|
4
|
+
|
|
5
|
+
export interface SubagentPresetSelectionState {
|
|
6
|
+
activePreset?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let runtimeSessionPresetOverride: string | undefined;
|
|
10
|
+
|
|
11
|
+
export function getSessionSubagentPresetOverride(env: NodeJS.ProcessEnv = process.env): string | undefined {
|
|
12
|
+
return runtimeSessionPresetOverride ?? trimString(env.AGENTS_PRESET);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getActiveSubagentPresetName(env: NodeJS.ProcessEnv = process.env): string | undefined {
|
|
16
|
+
return getSessionSubagentPresetOverride(env) ?? loadSubagentPresetSelection(env).activePreset;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function setSessionSubagentPresetOverride(name: string | undefined): void {
|
|
20
|
+
runtimeSessionPresetOverride = trimString(name);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getSubagentPresetSelectionPath(env: NodeJS.ProcessEnv = process.env): string {
|
|
24
|
+
const explicit = trimString(env.ASYNC_SUBAGENTS_ACTIVE_PRESET_FILE || env.PI_SUBAGENTS_ACTIVE_PRESET_FILE);
|
|
25
|
+
return explicit ? resolve(expandHome(explicit)) : resolve(getPiAgentDir(env), "subagent-preset-selection.json");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function loadSubagentPresetSelection(env: NodeJS.ProcessEnv = process.env): SubagentPresetSelectionState {
|
|
29
|
+
const statePath = getSubagentPresetSelectionPath(env);
|
|
30
|
+
if (!existsSync(statePath)) return {};
|
|
31
|
+
|
|
32
|
+
const parsed = JSON.parse(readFileSync(statePath, "utf-8")) as unknown;
|
|
33
|
+
if (!isRecord(parsed)) throw new Error(`${statePath} must contain an object.`);
|
|
34
|
+
return { activePreset: trimString(parsed.activePreset) };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function saveSubagentPresetSelection(state: SubagentPresetSelectionState, env: NodeJS.ProcessEnv = process.env): void {
|
|
38
|
+
const statePath = getSubagentPresetSelectionPath(env);
|
|
39
|
+
mkdirSync(dirname(statePath), { recursive: true });
|
|
40
|
+
writeFileSync(statePath, `${JSON.stringify(compactSelectionState(state), null, 2)}\n`, "utf-8");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function setActiveSubagentPreset(name: string | undefined, env: NodeJS.ProcessEnv = process.env): void {
|
|
44
|
+
saveSubagentPresetSelection({ activePreset: trimString(name) }, env);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function compactSelectionState(state: SubagentPresetSelectionState): SubagentPresetSelectionState {
|
|
48
|
+
return state.activePreset ? { activePreset: state.activePreset } : {};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function trimString(value: unknown): string | undefined {
|
|
52
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function expandHome(value: string): string {
|
|
56
|
+
if (value === "~") return process.env.HOME || value;
|
|
57
|
+
return value.startsWith("~/") ? `${process.env.HOME || "~"}/${value.slice(2)}` : value;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function getPiAgentDir(env: NodeJS.ProcessEnv): string {
|
|
61
|
+
const getAgentDir = (piCodingAgent as { getAgentDir?: () => string }).getAgentDir;
|
|
62
|
+
return getAgentDir ? getAgentDir() : resolve(env.HOME || process.cwd(), ".pi", "agent");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
66
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
67
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
export type ProcessSignal = "SIGTERM" | "SIGINT" | "SIGKILL";
|
|
4
|
+
|
|
5
|
+
export function terminateProcess(pid: number, signal: ProcessSignal): void {
|
|
6
|
+
if (process.platform === "win32") {
|
|
7
|
+
const result = spawnSync("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
8
|
+
stdio: "ignore",
|
|
9
|
+
timeout: 1_000,
|
|
10
|
+
windowsHide: true,
|
|
11
|
+
});
|
|
12
|
+
if (!result.error && result.status === 0) return;
|
|
13
|
+
}
|
|
14
|
+
process.kill(pid, signal);
|
|
15
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import type { AgentTask } from "./types.js";
|
|
4
|
+
|
|
5
|
+
export function generatePrompt(task: AgentTask): string {
|
|
6
|
+
const parentObjective = task.parentObjective || "current user task";
|
|
7
|
+
const scopeLine = task.scope ? `- Relevant files/areas: ${task.scope}\n` : "";
|
|
8
|
+
const imagePaths = task.imagePaths && task.imagePaths.length > 0 ? task.imagePaths.join(", ") : "";
|
|
9
|
+
const imageLine = imagePaths ? `- Attached image files: ${imagePaths}\n` : "";
|
|
10
|
+
const focusLine = task.focus ? `\nVisual focus / attention instructions:\n${task.focus}\n` : "";
|
|
11
|
+
|
|
12
|
+
const basePrompt = task.promptOverride ? renderPromptTemplate(task.promptOverride, task) : `You are a pi sub-agent launched by a parent agent.
|
|
13
|
+
|
|
14
|
+
Parent objective:
|
|
15
|
+
${parentObjective}
|
|
16
|
+
|
|
17
|
+
Your focused task:
|
|
18
|
+
${task.task}
|
|
19
|
+
${focusLine}
|
|
20
|
+
|
|
21
|
+
Scope and constraints:
|
|
22
|
+
- Work in the current repository only.
|
|
23
|
+
- Do not spawn other agents or background jobs unless explicitly allowed.
|
|
24
|
+
${scopeLine}${imageLine}- Follow the parent task's constraints and repository instructions.
|
|
25
|
+
- Keep output compact by default.
|
|
26
|
+
- If the task explicitly asks for verbatim/raw file contents, command output, logs, or exact text, output only that content exactly and do not summarize it.
|
|
27
|
+
- If requested raw content is very large, include the requested relevant portion and clearly say what was omitted.
|
|
28
|
+
|
|
29
|
+
Output format:
|
|
30
|
+
- If the task explicitly requests a raw/verbatim/exact output format, follow that request instead and do not add the standard summary sections below.
|
|
31
|
+
- Otherwise use:
|
|
32
|
+
1. Summary, max 5 bullets
|
|
33
|
+
2. Evidence / files inspected, paths first
|
|
34
|
+
3. Recommended changes or patch plan
|
|
35
|
+
4. Files changed, if any
|
|
36
|
+
5. Tests/commands run, with short results
|
|
37
|
+
6. Risks / open questions
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
return task.promptAppend
|
|
41
|
+
? `${basePrompt.trimEnd()}\n\nAdditional instructions from sub-agent profile:\n${renderPromptTemplate(task.promptAppend, task).trimEnd()}\n`
|
|
42
|
+
: basePrompt;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function renderPromptTemplate(template: string, task: AgentTask): string {
|
|
46
|
+
const values: Record<string, string> = {
|
|
47
|
+
id: task.id,
|
|
48
|
+
task: task.task,
|
|
49
|
+
scope: task.scope ?? "",
|
|
50
|
+
parentObjective: task.parentObjective || "current user task",
|
|
51
|
+
subagentType: task.subagentType ?? "",
|
|
52
|
+
model: task.model ?? "",
|
|
53
|
+
thinking: task.thinking ?? "",
|
|
54
|
+
focus: task.focus ?? "",
|
|
55
|
+
imagePaths: task.imagePaths?.join(", ") ?? "",
|
|
56
|
+
};
|
|
57
|
+
return template.replace(/\{(id|task|scope|parentObjective|subagentType|model|thinking|focus|imagePaths)\}/g, (_match, key: string) => values[key] ?? "");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function writePromptFile(runDir: string, task: AgentTask): string {
|
|
61
|
+
const promptDir = path.join(runDir, "prompts");
|
|
62
|
+
fs.mkdirSync(promptDir, { recursive: true });
|
|
63
|
+
const promptPath = path.join(promptDir, `${task.id}.md`);
|
|
64
|
+
fs.writeFileSync(promptPath, generatePrompt(task), "utf-8");
|
|
65
|
+
return promptPath;
|
|
66
|
+
}
|