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,117 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { isAbsolute, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
|
+
const FILE_PATH_CANDIDATE = /(?<![\p{L}\p{N}_:])((?:file:\/\/\/|~\/|\.{1,2}\/|\/|[A-Za-z0-9_.@-]+\/)[^\s"'`<>]*)/gu;
|
|
6
|
+
const TRAILING_PUNCTUATION = new Set([".", ",", ";", ")", "]", "}"]);
|
|
7
|
+
export function detectFileLinks(text, cwd) {
|
|
8
|
+
const links = [];
|
|
9
|
+
if (!text.includes("/"))
|
|
10
|
+
return links;
|
|
11
|
+
for (const match of text.matchAll(FILE_PATH_CANDIDATE)) {
|
|
12
|
+
const raw = match[1];
|
|
13
|
+
if (!raw)
|
|
14
|
+
continue;
|
|
15
|
+
const start = match.index + match[0].indexOf(raw);
|
|
16
|
+
const candidate = trimTrailingPunctuation(raw);
|
|
17
|
+
if (!candidate)
|
|
18
|
+
continue;
|
|
19
|
+
const location = resolveExistingFileLocation(candidate, cwd);
|
|
20
|
+
if (!location)
|
|
21
|
+
continue;
|
|
22
|
+
links.push({
|
|
23
|
+
start,
|
|
24
|
+
end: start + candidate.length,
|
|
25
|
+
url: locationUrl(location),
|
|
26
|
+
filePath: location.filePath,
|
|
27
|
+
line: location.line,
|
|
28
|
+
column: location.column,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return mergeOverlappingLinks(links);
|
|
32
|
+
}
|
|
33
|
+
export function hyperlink(text, url) {
|
|
34
|
+
return `\x1b]8;;${url}\x07${text}\x1b]8;;\x07`;
|
|
35
|
+
}
|
|
36
|
+
function locationUrl(location) {
|
|
37
|
+
const url = pathToFileURL(location.filePath).href;
|
|
38
|
+
if (location.line === undefined)
|
|
39
|
+
return url;
|
|
40
|
+
return location.column === undefined ? `${url}:${location.line}` : `${url}:${location.line}:${location.column}`;
|
|
41
|
+
}
|
|
42
|
+
function trimTrailingPunctuation(value) {
|
|
43
|
+
let end = value.length;
|
|
44
|
+
while (end > 0 && TRAILING_PUNCTUATION.has(value[end - 1] ?? ""))
|
|
45
|
+
end -= 1;
|
|
46
|
+
return value.slice(0, end);
|
|
47
|
+
}
|
|
48
|
+
function resolveExistingFileLocation(candidate, cwd) {
|
|
49
|
+
for (const variant of candidatePathVariants(candidate)) {
|
|
50
|
+
const filePath = resolveLocalPath(variant.pathText, cwd);
|
|
51
|
+
if (filePath && isExistingFile(filePath))
|
|
52
|
+
return { filePath, line: variant.line, column: variant.column };
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
function candidatePathVariants(candidate) {
|
|
57
|
+
const variants = [{ pathText: candidate }];
|
|
58
|
+
const locationSuffix = /^(.*?):(\d+)(?::(\d+))?(?:\+\d+)?$/u.exec(candidate);
|
|
59
|
+
if (locationSuffix?.[1] && locationSuffix[1] !== candidate) {
|
|
60
|
+
variants.push({
|
|
61
|
+
pathText: locationSuffix[1],
|
|
62
|
+
line: Number(locationSuffix[2]),
|
|
63
|
+
column: locationSuffix[3] ? Number(locationSuffix[3]) : undefined,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const markdownAnchorSuffix = /^(.*?)#L(\d+)(?:C(\d+))?$/u.exec(candidate);
|
|
67
|
+
if (markdownAnchorSuffix?.[1] && markdownAnchorSuffix[1] !== candidate) {
|
|
68
|
+
variants.push({
|
|
69
|
+
pathText: markdownAnchorSuffix[1],
|
|
70
|
+
line: Number(markdownAnchorSuffix[2]),
|
|
71
|
+
column: markdownAnchorSuffix[3] ? Number(markdownAnchorSuffix[3]) : undefined,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const seen = new Set();
|
|
75
|
+
return variants.filter((variant) => {
|
|
76
|
+
const key = `${variant.pathText}\0${variant.line ?? ""}\0${variant.column ?? ""}`;
|
|
77
|
+
if (seen.has(key))
|
|
78
|
+
return false;
|
|
79
|
+
seen.add(key);
|
|
80
|
+
return true;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function resolveLocalPath(pathText, cwd) {
|
|
84
|
+
if (pathText.startsWith("file:///")) {
|
|
85
|
+
try {
|
|
86
|
+
return fileURLToPath(pathText);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (pathText.startsWith("~/"))
|
|
93
|
+
return resolve(homedir(), pathText.slice(2));
|
|
94
|
+
if (isAbsolute(pathText))
|
|
95
|
+
return pathText;
|
|
96
|
+
if (!cwd)
|
|
97
|
+
return undefined;
|
|
98
|
+
return resolve(cwd, pathText);
|
|
99
|
+
}
|
|
100
|
+
function isExistingFile(filePath) {
|
|
101
|
+
try {
|
|
102
|
+
return existsSync(filePath) && statSync(filePath).isFile();
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function mergeOverlappingLinks(links) {
|
|
109
|
+
const merged = [];
|
|
110
|
+
for (const link of links.sort((left, right) => left.start - right.start || right.end - left.end)) {
|
|
111
|
+
const previous = merged[merged.length - 1];
|
|
112
|
+
if (previous && link.start < previous.end)
|
|
113
|
+
continue;
|
|
114
|
+
merged.push(link);
|
|
115
|
+
}
|
|
116
|
+
return merged;
|
|
117
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function isRecord(value) {
|
|
2
|
+
return typeof value === "object" && value !== null;
|
|
3
|
+
}
|
|
4
|
+
export function isStringArray(value) {
|
|
5
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
6
|
+
}
|
|
7
|
+
export function isNumberArray(value) {
|
|
8
|
+
return Array.isArray(value) && value.every((item) => typeof item === "number");
|
|
9
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export declare const PIX_ICON_THEME_ENV = "PIX_ICON_THEME";
|
|
2
|
+
export declare const PIX_USE_FALLBACK_ICONS_ENV = "PIX_USE_FALLBACK_ICONS";
|
|
3
|
+
declare const NERD_FONT_ICONS: {
|
|
4
|
+
readonly alert: "";
|
|
5
|
+
readonly autoFix: "";
|
|
6
|
+
readonly check: "";
|
|
7
|
+
readonly checkCircle: "";
|
|
8
|
+
readonly circle: "";
|
|
9
|
+
readonly circleOutline: "";
|
|
10
|
+
readonly close: "";
|
|
11
|
+
readonly closeCircle: "";
|
|
12
|
+
readonly deleted: "";
|
|
13
|
+
readonly deferred: "";
|
|
14
|
+
readonly info: "";
|
|
15
|
+
readonly microphone: "";
|
|
16
|
+
readonly plus: "";
|
|
17
|
+
readonly record: "";
|
|
18
|
+
readonly refresh: "";
|
|
19
|
+
readonly user: "";
|
|
20
|
+
readonly compactTools: "";
|
|
21
|
+
readonly thinkingExpanded: "";
|
|
22
|
+
readonly stopCircle: "";
|
|
23
|
+
readonly timerSand: "";
|
|
24
|
+
readonly down: "";
|
|
25
|
+
};
|
|
26
|
+
export type AppIconName = keyof typeof NERD_FONT_ICONS;
|
|
27
|
+
export type AppIconMap = Record<AppIconName, string>;
|
|
28
|
+
export type AppIconThemeName = "nerdFont" | "fallback";
|
|
29
|
+
export declare const APP_ICON_THEMES: Record<AppIconThemeName, AppIconMap>;
|
|
30
|
+
export declare const APP_ICONS: AppIconMap;
|
|
31
|
+
export declare function currentAppIconTheme(): AppIconThemeName;
|
|
32
|
+
export declare function parseAppIconThemeName(value: unknown): AppIconThemeName | undefined;
|
|
33
|
+
export declare function appIconThemeFromFallbackFlag(value: unknown): AppIconThemeName | undefined;
|
|
34
|
+
export declare function resolveAppIconThemeNameFromEnv(env?: NodeJS.ProcessEnv): AppIconThemeName;
|
|
35
|
+
export declare function appIconThemeOverrideFromEnv(env?: NodeJS.ProcessEnv): AppIconThemeName | undefined;
|
|
36
|
+
export declare function setAppIconTheme(themeName: AppIconThemeName): void;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Centralized icon themes. The default theme uses Nerd Font / Material Design
|
|
2
|
+
// private-use glyphs; the fallback theme avoids icon-font codepoints so Pix is
|
|
3
|
+
// still readable when the terminal font is missing.
|
|
4
|
+
//
|
|
5
|
+
// Use codepoint escapes for private-use characters so editors cannot silently
|
|
6
|
+
// substitute visually similar glyphs.
|
|
7
|
+
export const PIX_ICON_THEME_ENV = "PIX_ICON_THEME";
|
|
8
|
+
export const PIX_USE_FALLBACK_ICONS_ENV = "PIX_USE_FALLBACK_ICONS";
|
|
9
|
+
const NERD_FONT_ICONS = {
|
|
10
|
+
alert: "\u{f0026}",
|
|
11
|
+
autoFix: "\u{f0068}",
|
|
12
|
+
check: "\u{f012c}",
|
|
13
|
+
checkCircle: "\u{f05e0}",
|
|
14
|
+
circle: "\u{f0765}",
|
|
15
|
+
circleOutline: "\u{f0766}",
|
|
16
|
+
close: "\u{f0156}",
|
|
17
|
+
closeCircle: "\u{f0159}",
|
|
18
|
+
deleted: "\u{f0159}",
|
|
19
|
+
deferred: "\u{f0377}",
|
|
20
|
+
info: "\u{f02fc}",
|
|
21
|
+
microphone: "\u{f036c}",
|
|
22
|
+
plus: "\u{f0415}",
|
|
23
|
+
record: "\u{f044a}",
|
|
24
|
+
refresh: "\u{f0450}",
|
|
25
|
+
user: "\u{f0004}",
|
|
26
|
+
compactTools: "\u{f035c}",
|
|
27
|
+
thinkingExpanded: "\u{f0335}",
|
|
28
|
+
stopCircle: "\u{f0665}",
|
|
29
|
+
timerSand: "\u{f051f}",
|
|
30
|
+
down: "\u{f0045}",
|
|
31
|
+
};
|
|
32
|
+
const FALLBACK_ICONS = {
|
|
33
|
+
alert: "!",
|
|
34
|
+
autoFix: "*",
|
|
35
|
+
check: "✓",
|
|
36
|
+
checkCircle: "✓",
|
|
37
|
+
circle: "●",
|
|
38
|
+
circleOutline: "○",
|
|
39
|
+
close: "×",
|
|
40
|
+
closeCircle: "×",
|
|
41
|
+
deleted: "×",
|
|
42
|
+
deferred: "↷",
|
|
43
|
+
info: "i",
|
|
44
|
+
microphone: "m",
|
|
45
|
+
plus: "+",
|
|
46
|
+
record: "●",
|
|
47
|
+
refresh: "↻",
|
|
48
|
+
user: "@",
|
|
49
|
+
compactTools: "≡",
|
|
50
|
+
thinkingExpanded: ">",
|
|
51
|
+
stopCircle: "■",
|
|
52
|
+
timerSand: "…",
|
|
53
|
+
down: "v",
|
|
54
|
+
};
|
|
55
|
+
export const APP_ICON_THEMES = {
|
|
56
|
+
nerdFont: NERD_FONT_ICONS,
|
|
57
|
+
fallback: FALLBACK_ICONS,
|
|
58
|
+
};
|
|
59
|
+
let currentAppIconThemeName = resolveAppIconThemeNameFromEnv();
|
|
60
|
+
export const APP_ICONS = { ...APP_ICON_THEMES[currentAppIconThemeName] };
|
|
61
|
+
export function currentAppIconTheme() {
|
|
62
|
+
return currentAppIconThemeName;
|
|
63
|
+
}
|
|
64
|
+
export function parseAppIconThemeName(value) {
|
|
65
|
+
if (typeof value !== "string")
|
|
66
|
+
return undefined;
|
|
67
|
+
const normalized = value.trim().toLowerCase().replace(/[\s_-]+/gu, "");
|
|
68
|
+
if (normalized === "fallback" || normalized === "plain" || normalized === "ascii")
|
|
69
|
+
return "fallback";
|
|
70
|
+
if (normalized === "nerdfont" || normalized === "font" || normalized === "icons")
|
|
71
|
+
return "nerdFont";
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
export function appIconThemeFromFallbackFlag(value) {
|
|
75
|
+
if (typeof value === "boolean")
|
|
76
|
+
return value ? "fallback" : "nerdFont";
|
|
77
|
+
if (typeof value !== "string")
|
|
78
|
+
return undefined;
|
|
79
|
+
const normalized = value.trim().toLowerCase();
|
|
80
|
+
if (["1", "true", "yes", "on", "fallback"].includes(normalized))
|
|
81
|
+
return "fallback";
|
|
82
|
+
if (["0", "false", "no", "off", "nerdfont", "nerd-font"].includes(normalized))
|
|
83
|
+
return "nerdFont";
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
export function resolveAppIconThemeNameFromEnv(env = process.env) {
|
|
87
|
+
return appIconThemeOverrideFromEnv(env) ?? "nerdFont";
|
|
88
|
+
}
|
|
89
|
+
export function appIconThemeOverrideFromEnv(env = process.env) {
|
|
90
|
+
return appIconThemeFromFallbackFlag(env[PIX_USE_FALLBACK_ICONS_ENV])
|
|
91
|
+
?? parseAppIconThemeName(env[PIX_ICON_THEME_ENV])
|
|
92
|
+
?? undefined;
|
|
93
|
+
}
|
|
94
|
+
export function setAppIconTheme(themeName) {
|
|
95
|
+
currentAppIconThemeName = themeName;
|
|
96
|
+
Object.assign(APP_ICONS, APP_ICON_THEMES[themeName]);
|
|
97
|
+
}
|
package/dist/app/id.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createId(prefix: string): string;
|
package/dist/app/id.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ImageContent } from "../input-editor.js";
|
|
2
|
+
import type { RenderedLine, StyledSegment } from "./types.js";
|
|
3
|
+
type ImageLabelStyle = Omit<StyledSegment, "start" | "end">;
|
|
4
|
+
export declare function attachImageClickTargets(lines: RenderedLine[], entryId: string, images: readonly ImageContent[] | undefined, style?: ImageLabelStyle): RenderedLine[];
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const IMAGE_LABEL_PATTERN = /\[Image(?:\s+\d+)?(?::[^\]]+)?\]/g;
|
|
2
|
+
export function attachImageClickTargets(lines, entryId, images, style) {
|
|
3
|
+
if (!images || images.length === 0)
|
|
4
|
+
return lines;
|
|
5
|
+
let fallbackIndex = 0;
|
|
6
|
+
for (const line of lines) {
|
|
7
|
+
const targets = [];
|
|
8
|
+
const segments = [];
|
|
9
|
+
for (const match of line.text.matchAll(IMAGE_LABEL_PATTERN)) {
|
|
10
|
+
const imageIndex = imageIndexForLabel(match[0], fallbackIndex);
|
|
11
|
+
fallbackIndex = Math.max(fallbackIndex, imageIndex + 1);
|
|
12
|
+
if (imageIndex < 0 || imageIndex >= images.length)
|
|
13
|
+
continue;
|
|
14
|
+
const start = match.index ?? 0;
|
|
15
|
+
const end = start + match[0].length;
|
|
16
|
+
targets.push({ start, end, entryId, imageIndex });
|
|
17
|
+
if (style)
|
|
18
|
+
segments.push({ start, end, ...style });
|
|
19
|
+
}
|
|
20
|
+
if (targets.length > 0)
|
|
21
|
+
line.imageTargets = [...(line.imageTargets ?? []), ...targets];
|
|
22
|
+
if (segments.length > 0)
|
|
23
|
+
line.segments = [...(line.segments ?? []), ...segments];
|
|
24
|
+
}
|
|
25
|
+
return lines;
|
|
26
|
+
}
|
|
27
|
+
function imageIndexForLabel(label, fallbackIndex) {
|
|
28
|
+
const numbered = /^\[Image\s+(\d+)(?::|\])/u.exec(label);
|
|
29
|
+
if (numbered?.[1])
|
|
30
|
+
return Number(numbered[1]) - 1;
|
|
31
|
+
return fallbackIndex;
|
|
32
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
export function openImageContent(image) {
|
|
7
|
+
const filePath = writeImageTempFile(image);
|
|
8
|
+
if (!filePath)
|
|
9
|
+
return false;
|
|
10
|
+
return openPathWithSystemViewer(filePath);
|
|
11
|
+
}
|
|
12
|
+
function writeImageTempFile(image) {
|
|
13
|
+
try {
|
|
14
|
+
const data = Buffer.from(image.data, "base64");
|
|
15
|
+
if (data.length === 0)
|
|
16
|
+
return undefined;
|
|
17
|
+
const dir = join(tmpdir(), "pix-image-open");
|
|
18
|
+
mkdirSync(dir, { recursive: true });
|
|
19
|
+
const hash = createHash("sha256").update(image.mimeType).update("\0").update(data).digest("hex").slice(0, 24);
|
|
20
|
+
const filePath = join(dir, `${hash}${imageExtension(image.mimeType)}`);
|
|
21
|
+
if (!existsSync(filePath))
|
|
22
|
+
writeFileSync(filePath, data, { flag: "wx" });
|
|
23
|
+
return filePath;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function imageExtension(mimeType) {
|
|
30
|
+
switch (mimeType.toLowerCase()) {
|
|
31
|
+
case "image/jpeg":
|
|
32
|
+
case "image/jpg":
|
|
33
|
+
return ".jpg";
|
|
34
|
+
case "image/gif":
|
|
35
|
+
return ".gif";
|
|
36
|
+
case "image/webp":
|
|
37
|
+
return ".webp";
|
|
38
|
+
case "image/bmp":
|
|
39
|
+
return ".bmp";
|
|
40
|
+
case "image/svg+xml":
|
|
41
|
+
return ".svg";
|
|
42
|
+
case "image/png":
|
|
43
|
+
default:
|
|
44
|
+
return ".png";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function openPathWithSystemViewer(filePath) {
|
|
48
|
+
if (process.platform === "darwin")
|
|
49
|
+
return spawnDetached("open", [filePath]);
|
|
50
|
+
if (process.platform === "win32")
|
|
51
|
+
return spawnDetached("cmd", ["/c", "start", "", filePath]);
|
|
52
|
+
return spawnDetached("xdg-open", [filePath]);
|
|
53
|
+
}
|
|
54
|
+
function spawnDetached(command, args) {
|
|
55
|
+
try {
|
|
56
|
+
const child = spawn(command, args, { detached: true, stdio: "ignore" });
|
|
57
|
+
child.on("error", () => { });
|
|
58
|
+
child.unref();
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { InputEditor } from "../input-editor.js";
|
|
2
|
+
import type { AgentSessionRuntime } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import type { AppPopupActionController } from "./popup-action-controller.js";
|
|
4
|
+
import type { AppPopupMenuController } from "./popup-menu-controller.js";
|
|
5
|
+
import type { AppQueuedMessageController } from "./queued-message-controller.js";
|
|
6
|
+
import type { AppRequestHistory } from "./request-history.js";
|
|
7
|
+
import { type InteractiveShellCommandResult } from "./shell-command.js";
|
|
8
|
+
import type { Entry, SessionActivity } from "./types.js";
|
|
9
|
+
export type AppInputActionControllerHost = {
|
|
10
|
+
runtime(): AgentSessionRuntime | undefined;
|
|
11
|
+
isRunning(): boolean;
|
|
12
|
+
isSessionSwitching(): boolean;
|
|
13
|
+
inputEditor(): InputEditor;
|
|
14
|
+
requestHistory(): AppRequestHistory;
|
|
15
|
+
clearPersistedInputDraft(): Promise<void>;
|
|
16
|
+
setStatus(status: string): void;
|
|
17
|
+
setSessionStatus(session: AgentSessionRuntime["session"] | undefined): void;
|
|
18
|
+
setSessionActivity(activity: SessionActivity): void;
|
|
19
|
+
addEntry(entry: Entry): void;
|
|
20
|
+
addSessionAbortedEntry(): void;
|
|
21
|
+
showToast(message: string, kind: "success" | "error" | "warning" | "info"): void;
|
|
22
|
+
stopVoiceInput(): Promise<void>;
|
|
23
|
+
isShellCommandRunning(): boolean;
|
|
24
|
+
runChatShellCommand(command: string): Promise<InteractiveShellCommandResult>;
|
|
25
|
+
sendShellInput(text: string): boolean;
|
|
26
|
+
interruptShellCommand(): boolean;
|
|
27
|
+
runInteractiveShellCommand(command: string): Promise<InteractiveShellCommandResult>;
|
|
28
|
+
stop(): Promise<void>;
|
|
29
|
+
render(): void;
|
|
30
|
+
};
|
|
31
|
+
export declare class AppInputActionController {
|
|
32
|
+
private readonly host;
|
|
33
|
+
private readonly popupMenus;
|
|
34
|
+
private readonly popupActions;
|
|
35
|
+
private readonly queuedMessages;
|
|
36
|
+
private abortInFlight;
|
|
37
|
+
constructor(host: AppInputActionControllerHost, popupMenus: AppPopupMenuController, popupActions: AppPopupActionController, queuedMessages: AppQueuedMessageController);
|
|
38
|
+
handleEnter(): void;
|
|
39
|
+
handleInterrupt(): Promise<void>;
|
|
40
|
+
handleEscape(): Promise<void>;
|
|
41
|
+
private abortStreamingSession;
|
|
42
|
+
private restoreSessionState;
|
|
43
|
+
private sessionActivity;
|
|
44
|
+
private submitInput;
|
|
45
|
+
private submitShellInput;
|
|
46
|
+
private submitShellCommand;
|
|
47
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { createId } from "./id.js";
|
|
2
|
+
import { stringifyUnknown } from "./message-content.js";
|
|
3
|
+
import { bangShellCommandFromInput, formatShellCommandEntry, } from "./shell-command.js";
|
|
4
|
+
const ABORT_STATUS_RESTORE_MS = 1200;
|
|
5
|
+
export class AppInputActionController {
|
|
6
|
+
host;
|
|
7
|
+
popupMenus;
|
|
8
|
+
popupActions;
|
|
9
|
+
queuedMessages;
|
|
10
|
+
abortInFlight = false;
|
|
11
|
+
constructor(host, popupMenus, popupActions, queuedMessages) {
|
|
12
|
+
this.host = host;
|
|
13
|
+
this.popupMenus = popupMenus;
|
|
14
|
+
this.popupActions = popupActions;
|
|
15
|
+
this.queuedMessages = queuedMessages;
|
|
16
|
+
}
|
|
17
|
+
handleEnter() {
|
|
18
|
+
if (this.popupMenus.syncActivePopupMenu()) {
|
|
19
|
+
void this.popupActions.submitActivePopupMenu();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
void this.submitInput();
|
|
23
|
+
}
|
|
24
|
+
async handleInterrupt() {
|
|
25
|
+
if (this.host.interruptShellCommand()) {
|
|
26
|
+
this.host.inputEditor().clear();
|
|
27
|
+
await this.host.clearPersistedInputDraft();
|
|
28
|
+
this.host.render();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const runtime = this.host.runtime();
|
|
32
|
+
if (runtime?.session.isCompacting) {
|
|
33
|
+
this.host.setStatus("aborting compaction");
|
|
34
|
+
this.host.render();
|
|
35
|
+
runtime.session.abortCompaction();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (runtime?.session.isStreaming) {
|
|
39
|
+
await this.abortStreamingSession(runtime, { stopIfAlreadyAborting: true });
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
await this.host.stop();
|
|
43
|
+
}
|
|
44
|
+
async handleEscape() {
|
|
45
|
+
const session = this.host.runtime()?.session;
|
|
46
|
+
if (session?.isCompacting) {
|
|
47
|
+
this.host.setStatus("aborting compaction");
|
|
48
|
+
this.host.render();
|
|
49
|
+
session.abortCompaction();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (session?.isStreaming) {
|
|
53
|
+
const runtime = this.host.runtime();
|
|
54
|
+
if (runtime)
|
|
55
|
+
await this.abortStreamingSession(runtime, { stopIfAlreadyAborting: false });
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (this.popupMenus.syncActivePopupMenu())
|
|
59
|
+
this.popupMenus.cancelActivePopupMenu();
|
|
60
|
+
}
|
|
61
|
+
async abortStreamingSession(runtime, options) {
|
|
62
|
+
const session = runtime.session;
|
|
63
|
+
if (this.abortInFlight) {
|
|
64
|
+
session.agent.abort();
|
|
65
|
+
if (options.stopIfAlreadyAborting)
|
|
66
|
+
await this.host.stop();
|
|
67
|
+
else
|
|
68
|
+
this.host.render();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this.abortInFlight = true;
|
|
72
|
+
this.queuedMessages.restoreQueuedMessagesToEditorForAbort();
|
|
73
|
+
this.host.setStatus("aborting");
|
|
74
|
+
this.host.addSessionAbortedEntry();
|
|
75
|
+
this.host.render();
|
|
76
|
+
let restoreTimer = setTimeout(() => {
|
|
77
|
+
if (!this.abortInFlight || this.host.runtime()?.session !== session || !this.host.isRunning())
|
|
78
|
+
return;
|
|
79
|
+
this.restoreSessionState(session);
|
|
80
|
+
this.host.render();
|
|
81
|
+
}, ABORT_STATUS_RESTORE_MS);
|
|
82
|
+
restoreTimer.unref?.();
|
|
83
|
+
try {
|
|
84
|
+
session.agent.abort();
|
|
85
|
+
await session.abort();
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
this.host.addEntry({ id: createId("error"), kind: "error", text: stringifyUnknown(error) });
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
if (restoreTimer)
|
|
92
|
+
clearTimeout(restoreTimer);
|
|
93
|
+
restoreTimer = undefined;
|
|
94
|
+
this.abortInFlight = false;
|
|
95
|
+
this.restoreSessionState(this.host.runtime()?.session);
|
|
96
|
+
if (this.host.isRunning())
|
|
97
|
+
this.host.render();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
restoreSessionState(session) {
|
|
101
|
+
this.host.setSessionStatus(session);
|
|
102
|
+
this.host.setSessionActivity(this.sessionActivity(session));
|
|
103
|
+
}
|
|
104
|
+
sessionActivity(session) {
|
|
105
|
+
return session?.isStreaming || session?.isCompacting ? "running" : "idle";
|
|
106
|
+
}
|
|
107
|
+
async submitInput() {
|
|
108
|
+
await this.host.stopVoiceInput();
|
|
109
|
+
const inputEditor = this.host.inputEditor();
|
|
110
|
+
const rawPromptText = inputEditor.promptText;
|
|
111
|
+
const rawDisplayText = inputEditor.expandedText;
|
|
112
|
+
const promptText = rawPromptText.trimEnd();
|
|
113
|
+
const displayText = rawDisplayText.trimEnd();
|
|
114
|
+
const images = [...inputEditor.images];
|
|
115
|
+
if (this.host.isShellCommandRunning()) {
|
|
116
|
+
await this.submitShellInput(rawDisplayText, images.length);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (!promptText && images.length === 0)
|
|
120
|
+
return;
|
|
121
|
+
const shellCommand = bangShellCommandFromInput(promptText);
|
|
122
|
+
if (shellCommand !== undefined) {
|
|
123
|
+
await this.submitShellCommand(shellCommand.command, displayText, images.length, shellCommand.interactive ? "interactive" : "chat");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (this.host.isSessionSwitching()) {
|
|
127
|
+
this.host.showToast("Wait for the tab to finish loading", "info");
|
|
128
|
+
this.host.render();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (promptText.startsWith("/")) {
|
|
132
|
+
await this.popupActions.submitSlashCommand(promptText);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const message = this.queuedMessages.createSubmittedUserMessage(promptText, displayText, images);
|
|
136
|
+
this.host.requestHistory().add(message.displayText);
|
|
137
|
+
inputEditor.clear();
|
|
138
|
+
await this.host.clearPersistedInputDraft();
|
|
139
|
+
this.host.render();
|
|
140
|
+
try {
|
|
141
|
+
await this.queuedMessages.submitUserMessage(message);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
this.host.addEntry({ id: createId("error"), kind: "error", text: stringifyUnknown(error) });
|
|
145
|
+
}
|
|
146
|
+
if (this.host.isRunning())
|
|
147
|
+
this.host.render();
|
|
148
|
+
}
|
|
149
|
+
async submitShellInput(text, imageCount) {
|
|
150
|
+
if (imageCount > 0) {
|
|
151
|
+
this.host.showToast("Shell stdin cannot include pasted images", "warning");
|
|
152
|
+
this.host.render();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const inputEditor = this.host.inputEditor();
|
|
156
|
+
inputEditor.clear();
|
|
157
|
+
await this.host.clearPersistedInputDraft();
|
|
158
|
+
if (!this.host.sendShellInput(text))
|
|
159
|
+
this.host.showToast("No shell command is waiting for input", "info");
|
|
160
|
+
this.host.render();
|
|
161
|
+
}
|
|
162
|
+
async submitShellCommand(command, displayText, imageCount, mode) {
|
|
163
|
+
if (!command) {
|
|
164
|
+
this.host.showToast(`Enter a shell command after ${mode === "interactive" ? "!!" : "!"}`, "info");
|
|
165
|
+
this.host.render();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (imageCount > 0) {
|
|
169
|
+
this.host.showToast("Shell commands cannot include pasted images", "warning");
|
|
170
|
+
this.host.render();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (this.host.isSessionSwitching()) {
|
|
174
|
+
this.host.showToast("Wait for the tab to finish loading", "info");
|
|
175
|
+
this.host.render();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const session = this.host.runtime()?.session;
|
|
179
|
+
if (session?.isStreaming || session?.isCompacting) {
|
|
180
|
+
this.host.showToast("Wait for the current session turn to finish before running shell commands", "info");
|
|
181
|
+
this.host.render();
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const inputEditor = this.host.inputEditor();
|
|
185
|
+
this.host.requestHistory().add(displayText);
|
|
186
|
+
inputEditor.clear();
|
|
187
|
+
await this.host.clearPersistedInputDraft();
|
|
188
|
+
this.host.setStatus(`shell: ${command}`);
|
|
189
|
+
this.host.render();
|
|
190
|
+
try {
|
|
191
|
+
if (mode === "chat") {
|
|
192
|
+
await this.host.runChatShellCommand(command);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
const result = await this.host.runInteractiveShellCommand(command);
|
|
196
|
+
const entryKind = result.error ? "error" : "system";
|
|
197
|
+
this.host.addEntry({ id: createId(entryKind), kind: entryKind, text: formatShellCommandEntry(command, result, "!!") });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
this.host.addEntry({ id: createId("error"), kind: "error", text: `Shell command failed: ${stringifyUnknown(error)}` });
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
this.restoreSessionState(this.host.runtime()?.session);
|
|
205
|
+
}
|
|
206
|
+
if (this.host.isRunning())
|
|
207
|
+
this.host.render();
|
|
208
|
+
}
|
|
209
|
+
}
|