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,182 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { fuzzySearch } from "../fuzzy.js";
|
|
3
|
+
import { PI_FAVORITE_MODEL_REFS, THINKING_LEVELS } from "./constants.js";
|
|
4
|
+
import { APP_ICONS } from "./icons.js";
|
|
5
|
+
import { parseScopedModelRef } from "./model-ref.js";
|
|
6
|
+
import { buildUserMessageJumpItems, createSessionInfoMenuItemsLoader } from "./popup-menu-controller.js";
|
|
7
|
+
import { getResourceSlashCommands, getSlashCommandMatches, parseSlashInput } from "./slash-commands.js";
|
|
8
|
+
export class AppMenuItemsController {
|
|
9
|
+
host;
|
|
10
|
+
resumeMenuLoaderCache;
|
|
11
|
+
constructor(host) {
|
|
12
|
+
this.host = host;
|
|
13
|
+
}
|
|
14
|
+
parseSlashInput(text) {
|
|
15
|
+
return parseSlashInput(text);
|
|
16
|
+
}
|
|
17
|
+
getResourceSlashCommands() {
|
|
18
|
+
return getResourceSlashCommands(this.host.runtime(), this.host.getBuiltinSlashCommands());
|
|
19
|
+
}
|
|
20
|
+
getSlashCommandMatches(query, limit) {
|
|
21
|
+
return getSlashCommandMatches(this.getAllSlashCommands(), query, limit);
|
|
22
|
+
}
|
|
23
|
+
getSlashCommandMenuItems(query) {
|
|
24
|
+
return this.getSlashCommandMatches(query).map((match) => ({
|
|
25
|
+
value: match.value,
|
|
26
|
+
label: `/${match.value.name}`,
|
|
27
|
+
description: match.value.description,
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
modelRef(model) {
|
|
31
|
+
return `${model.provider}/${model.id}`;
|
|
32
|
+
}
|
|
33
|
+
getFavoriteScopedModels() {
|
|
34
|
+
const configuredRefs = this.host.runtime()?.services.settingsManager.getEnabledModels();
|
|
35
|
+
const refs = configuredRefs && configuredRefs.length > 0 ? configuredRefs : PI_FAVORITE_MODEL_REFS;
|
|
36
|
+
return this.resolveScopedModelRefs(refs);
|
|
37
|
+
}
|
|
38
|
+
getModelMenuItems(query) {
|
|
39
|
+
const models = [...this.getModelMenuModels()].sort((left, right) => {
|
|
40
|
+
const leftCurrent = this.isCurrentModel(left);
|
|
41
|
+
const rightCurrent = this.isCurrentModel(right);
|
|
42
|
+
if (leftCurrent && !rightCurrent)
|
|
43
|
+
return -1;
|
|
44
|
+
if (!leftCurrent && rightCurrent)
|
|
45
|
+
return 1;
|
|
46
|
+
const providerDelta = left.provider.localeCompare(right.provider);
|
|
47
|
+
return providerDelta === 0 ? left.id.localeCompare(right.id) : providerDelta;
|
|
48
|
+
});
|
|
49
|
+
const items = models.map((model) => {
|
|
50
|
+
const ref = this.modelRef(model);
|
|
51
|
+
const current = this.isCurrentModel(model);
|
|
52
|
+
return {
|
|
53
|
+
value: { model, ref, current },
|
|
54
|
+
label: ref,
|
|
55
|
+
aliases: [model.id, model.name, model.provider],
|
|
56
|
+
keywords: [model.name, `${model.provider} ${model.id}`],
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
return fuzzySearch(items, query).map((match) => ({
|
|
60
|
+
value: match.value,
|
|
61
|
+
label: `${match.value.ref}${match.value.current ? ` ${APP_ICONS.check}` : ""}`,
|
|
62
|
+
description: match.value.model.name,
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
getThinkingMenuItems(query) {
|
|
66
|
+
const session = this.host.runtime()?.session;
|
|
67
|
+
const currentLevel = session?.thinkingLevel ?? "off";
|
|
68
|
+
const availableLevels = session ? session.getAvailableThinkingLevels() : [...THINKING_LEVELS];
|
|
69
|
+
const levels = availableLevels.includes("off") ? availableLevels : ["off", ...availableLevels];
|
|
70
|
+
const items = levels.map((level) => ({
|
|
71
|
+
value: { level, current: level === currentLevel },
|
|
72
|
+
label: level,
|
|
73
|
+
keywords: [
|
|
74
|
+
level === "off" ? "disabled none no reasoning" : "reasoning thinking effort",
|
|
75
|
+
level === "minimal" ? "fast small" : "",
|
|
76
|
+
level === "xhigh" ? "extra highest maximum" : "",
|
|
77
|
+
].filter(Boolean),
|
|
78
|
+
}));
|
|
79
|
+
return fuzzySearch(items, query).map((match) => ({
|
|
80
|
+
value: match.value,
|
|
81
|
+
label: `${match.value.level}${match.value.current ? ` ${APP_ICONS.check}` : ""}`,
|
|
82
|
+
description: this.thinkingLevelDescription(match.value.level),
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
getUserMessageMenuItems() {
|
|
86
|
+
return [
|
|
87
|
+
{ value: "copy", label: "Copy message", description: "Copy the full user message" },
|
|
88
|
+
{ value: "fork", label: "Fork", description: "Create a new session before this message" },
|
|
89
|
+
{ value: "undo", label: "Undo changes", description: "Revert recorded commands and cut session here" },
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
getUserMessageJumpMenuItems(query) {
|
|
93
|
+
return buildUserMessageJumpItems(this.host.getEntries(), query);
|
|
94
|
+
}
|
|
95
|
+
getQueueMessageMenuItems() {
|
|
96
|
+
return [
|
|
97
|
+
{ value: "cancel", label: "Cancel send", description: "Remove this message from the queue" },
|
|
98
|
+
{ value: "edit", label: "Edit", description: "Move it back to the editor" },
|
|
99
|
+
{ value: "send-now", label: "Send immediately", description: "Send now and keep the rest queued" },
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
getResumeMenuItems(query, limit) {
|
|
103
|
+
const sessionFile = this.host.runtime()?.session.sessionFile;
|
|
104
|
+
const currentSessionFile = sessionFile ? resolve(sessionFile) : undefined;
|
|
105
|
+
const loader = this.getResumeMenuItemsLoader(currentSessionFile, query);
|
|
106
|
+
return [
|
|
107
|
+
{ value: { kind: "new" }, label: "new", description: "Create a new session" },
|
|
108
|
+
...loader.items(limit).map((item) => ({
|
|
109
|
+
...item,
|
|
110
|
+
value: { kind: "session", session: item.value },
|
|
111
|
+
})),
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
getResumeMenuItemsLoader(currentSessionFile, query) {
|
|
115
|
+
const sessions = this.host.getResumeSessions();
|
|
116
|
+
const cache = this.resumeMenuLoaderCache;
|
|
117
|
+
if (cache &&
|
|
118
|
+
cache.sessions === sessions &&
|
|
119
|
+
cache.currentSessionFile === currentSessionFile &&
|
|
120
|
+
cache.query === query) {
|
|
121
|
+
return cache.loader;
|
|
122
|
+
}
|
|
123
|
+
const loader = createSessionInfoMenuItemsLoader(sessions, currentSessionFile, query);
|
|
124
|
+
this.resumeMenuLoaderCache = { sessions, currentSessionFile, query, loader };
|
|
125
|
+
return loader;
|
|
126
|
+
}
|
|
127
|
+
getAllSlashCommands() {
|
|
128
|
+
return [...this.host.getBuiltinSlashCommands(), ...this.getResourceSlashCommands()];
|
|
129
|
+
}
|
|
130
|
+
isCurrentModel(model) {
|
|
131
|
+
const current = this.host.runtime()?.session.model;
|
|
132
|
+
return current?.provider === model.provider && current.id === model.id;
|
|
133
|
+
}
|
|
134
|
+
resolveScopedModelRefs(modelRefs) {
|
|
135
|
+
const registry = this.host.runtime()?.services.modelRegistry;
|
|
136
|
+
if (!registry)
|
|
137
|
+
return [];
|
|
138
|
+
registry.refresh();
|
|
139
|
+
const scopedModels = [];
|
|
140
|
+
for (const modelRef of modelRefs) {
|
|
141
|
+
const parsed = parseScopedModelRef(modelRef);
|
|
142
|
+
if (!parsed)
|
|
143
|
+
continue;
|
|
144
|
+
const model = registry.find(parsed.provider, parsed.modelId);
|
|
145
|
+
if (!model)
|
|
146
|
+
continue;
|
|
147
|
+
scopedModels.push({
|
|
148
|
+
model,
|
|
149
|
+
...(parsed.thinkingLevel === undefined ? {} : { thinkingLevel: parsed.thinkingLevel }),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return scopedModels;
|
|
153
|
+
}
|
|
154
|
+
getModelMenuModels() {
|
|
155
|
+
const session = this.host.runtime()?.session;
|
|
156
|
+
const scopedModels = session?.scopedModels.length ? session.scopedModels : this.getFavoriteScopedModels();
|
|
157
|
+
if (!scopedModels.length)
|
|
158
|
+
return [];
|
|
159
|
+
const registry = this.host.runtime()?.services.modelRegistry;
|
|
160
|
+
registry?.refresh();
|
|
161
|
+
return scopedModels.map((scoped) => {
|
|
162
|
+
const refreshed = registry?.find(scoped.model.provider, scoped.model.id);
|
|
163
|
+
return (refreshed ?? scoped.model);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
thinkingLevelDescription(level) {
|
|
167
|
+
switch (level) {
|
|
168
|
+
case "off":
|
|
169
|
+
return "No reasoning/thinking";
|
|
170
|
+
case "minimal":
|
|
171
|
+
return "Minimal reasoning";
|
|
172
|
+
case "low":
|
|
173
|
+
return "Low reasoning";
|
|
174
|
+
case "medium":
|
|
175
|
+
return "Medium reasoning";
|
|
176
|
+
case "high":
|
|
177
|
+
return "High reasoning";
|
|
178
|
+
case "xhigh":
|
|
179
|
+
return "Extra high reasoning";
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ImageContent } from "../input-editor.js";
|
|
2
|
+
export declare function stringifyUnknown(value: unknown): string;
|
|
3
|
+
export declare function formatStructuredText(value: unknown): string;
|
|
4
|
+
export declare function renderContent(content: readonly unknown[]): string;
|
|
5
|
+
export declare function renderUserMessageContent(content: unknown): string;
|
|
6
|
+
export declare function extractImageContents(content: unknown): ImageContent[];
|
|
7
|
+
export declare function isImageContent(item: unknown): item is ImageContent;
|
|
8
|
+
export declare function submittedUserDisplayText(displayText: string, promptText: string, images: readonly ImageContent[]): string;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { isRecord } from "./guards.js";
|
|
2
|
+
export function stringifyUnknown(value) {
|
|
3
|
+
if (typeof value === "string")
|
|
4
|
+
return value;
|
|
5
|
+
if (value instanceof Error)
|
|
6
|
+
return value.message || value.name;
|
|
7
|
+
if (isRecord(value)) {
|
|
8
|
+
const message = typeof value.message === "string" ? value.message : undefined;
|
|
9
|
+
const name = typeof value.name === "string" ? value.name : undefined;
|
|
10
|
+
if (message)
|
|
11
|
+
return name && name !== "Error" ? `${name}: ${message}` : message;
|
|
12
|
+
if (name)
|
|
13
|
+
return name;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
return JSON.stringify(value, null, 2);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return String(value);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function formatStructuredText(value) {
|
|
23
|
+
if (typeof value === "string") {
|
|
24
|
+
const trimmed = value.trim();
|
|
25
|
+
if (!trimmed)
|
|
26
|
+
return "(empty)";
|
|
27
|
+
try {
|
|
28
|
+
return JSON.stringify(JSON.parse(trimmed), null, 2);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return stringifyUnknown(value);
|
|
35
|
+
}
|
|
36
|
+
export function renderContent(content) {
|
|
37
|
+
const parts = [];
|
|
38
|
+
let imageCount = 0;
|
|
39
|
+
for (const item of content) {
|
|
40
|
+
if (!isRecord(item)) {
|
|
41
|
+
parts.push(stringifyUnknown(item));
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (isImageContent(item)) {
|
|
45
|
+
imageCount += 1;
|
|
46
|
+
parts.push(imageContentLabel(item, imageCount));
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (typeof item.text === "string") {
|
|
50
|
+
parts.push(item.text);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (typeof item.thinking === "string") {
|
|
54
|
+
parts.push(item.thinking);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
parts.push(stringifyUnknown(item));
|
|
58
|
+
}
|
|
59
|
+
return parts.join("\n");
|
|
60
|
+
}
|
|
61
|
+
export function renderUserMessageContent(content) {
|
|
62
|
+
if (typeof content === "string")
|
|
63
|
+
return content;
|
|
64
|
+
if (!Array.isArray(content))
|
|
65
|
+
return stringifyUnknown(content);
|
|
66
|
+
const textParts = [];
|
|
67
|
+
let imageCount = 0;
|
|
68
|
+
for (const item of content) {
|
|
69
|
+
if (!isRecord(item)) {
|
|
70
|
+
textParts.push(stringifyUnknown(item));
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (item.type === "image") {
|
|
74
|
+
imageCount += 1;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (typeof item.text === "string") {
|
|
78
|
+
textParts.push(item.text);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
textParts.push(stringifyUnknown(item));
|
|
82
|
+
}
|
|
83
|
+
const text = textParts.join("\n").replace(/\[Image \d+(?:: [^\]]+)?\]/g, "").trimEnd();
|
|
84
|
+
if (imageCount === 0)
|
|
85
|
+
return text;
|
|
86
|
+
const imageText = userImageLabels(imageCount);
|
|
87
|
+
return text ? `${text}\n${imageText}` : imageText;
|
|
88
|
+
}
|
|
89
|
+
export function extractImageContents(content) {
|
|
90
|
+
if (!Array.isArray(content))
|
|
91
|
+
return [];
|
|
92
|
+
return content.filter(isImageContent);
|
|
93
|
+
}
|
|
94
|
+
export function isImageContent(item) {
|
|
95
|
+
return isRecord(item) && item.type === "image" && typeof item.data === "string" && typeof item.mimeType === "string";
|
|
96
|
+
}
|
|
97
|
+
function imageContentLabel(item, index) {
|
|
98
|
+
const label = index === 1 ? "Image" : `Image ${index}`;
|
|
99
|
+
return `[${label}: ${item.mimeType}]`;
|
|
100
|
+
}
|
|
101
|
+
function userImageLabels(count) {
|
|
102
|
+
if (count <= 0)
|
|
103
|
+
return "";
|
|
104
|
+
if (count === 1)
|
|
105
|
+
return "[Image]";
|
|
106
|
+
return Array.from({ length: count }, (_, index) => `[Image ${index + 1}]`).join("\n");
|
|
107
|
+
}
|
|
108
|
+
export function submittedUserDisplayText(displayText, promptText, images) {
|
|
109
|
+
const trimmedDisplay = displayText.trimEnd();
|
|
110
|
+
if (trimmedDisplay)
|
|
111
|
+
return trimmedDisplay;
|
|
112
|
+
if (images.length > 0)
|
|
113
|
+
return userImageLabels(images.length);
|
|
114
|
+
return promptText.trimEnd();
|
|
115
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ThinkingLevel } from "./types.js";
|
|
2
|
+
export declare function parseModelRef(value: string): {
|
|
3
|
+
provider: string;
|
|
4
|
+
modelId: string;
|
|
5
|
+
thinkingLevel?: ThinkingLevel;
|
|
6
|
+
};
|
|
7
|
+
export declare function parseScopedModelRef(value: string): {
|
|
8
|
+
provider: string;
|
|
9
|
+
modelId: string;
|
|
10
|
+
thinkingLevel?: ThinkingLevel;
|
|
11
|
+
} | undefined;
|
|
12
|
+
export declare function isThinkingLevel(value: string): value is ThinkingLevel;
|
|
13
|
+
export declare function stripProviderFromModelRef(value: string): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { THINKING_LEVELS } from "./constants.js";
|
|
2
|
+
export function parseModelRef(value) {
|
|
3
|
+
const [modelPart, thinkingPart] = value.split(":", 2);
|
|
4
|
+
if (!modelPart)
|
|
5
|
+
throw new Error("Model reference cannot be empty");
|
|
6
|
+
const slashIndex = modelPart.indexOf("/");
|
|
7
|
+
if (slashIndex <= 0 || slashIndex === modelPart.length - 1) {
|
|
8
|
+
throw new Error("Model must use provider/model format");
|
|
9
|
+
}
|
|
10
|
+
let thinkingLevel;
|
|
11
|
+
if (thinkingPart) {
|
|
12
|
+
if (!isThinkingLevel(thinkingPart)) {
|
|
13
|
+
throw new Error(`Unknown thinking level: ${thinkingPart}`);
|
|
14
|
+
}
|
|
15
|
+
thinkingLevel = thinkingPart;
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
provider: modelPart.slice(0, slashIndex),
|
|
19
|
+
modelId: modelPart.slice(slashIndex + 1),
|
|
20
|
+
...(thinkingLevel === undefined ? {} : { thinkingLevel }),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export function parseScopedModelRef(value) {
|
|
24
|
+
const slashIndex = value.indexOf("/");
|
|
25
|
+
if (slashIndex <= 0 || slashIndex === value.length - 1)
|
|
26
|
+
return undefined;
|
|
27
|
+
const provider = value.slice(0, slashIndex);
|
|
28
|
+
let modelId = value.slice(slashIndex + 1);
|
|
29
|
+
let thinkingLevel;
|
|
30
|
+
const colonIndex = modelId.lastIndexOf(":");
|
|
31
|
+
if (colonIndex > 0) {
|
|
32
|
+
const suffix = modelId.slice(colonIndex + 1);
|
|
33
|
+
if (isThinkingLevel(suffix)) {
|
|
34
|
+
modelId = modelId.slice(0, colonIndex);
|
|
35
|
+
thinkingLevel = suffix;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
provider,
|
|
40
|
+
modelId,
|
|
41
|
+
...(thinkingLevel === undefined ? {} : { thinkingLevel }),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export function isThinkingLevel(value) {
|
|
45
|
+
return THINKING_LEVELS.includes(value);
|
|
46
|
+
}
|
|
47
|
+
export function stripProviderFromModelRef(value) {
|
|
48
|
+
const slashIndex = value.indexOf("/");
|
|
49
|
+
return slashIndex >= 0 && slashIndex < value.length - 1 ? value.slice(slashIndex + 1) : value;
|
|
50
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AgentSession } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { type ModelUsageDescriptor, type ModelUsageStatus } from "./model-usage-status.js";
|
|
3
|
+
export type AppModelUsageQuery = (descriptor: ModelUsageDescriptor) => Promise<ModelUsageStatus | undefined>;
|
|
4
|
+
export type ModelUsageRefreshResult = "refreshed" | "unavailable" | "failed";
|
|
5
|
+
export type ModelUsageRefreshStart = {
|
|
6
|
+
kind: "started";
|
|
7
|
+
promise: Promise<ModelUsageRefreshResult>;
|
|
8
|
+
} | {
|
|
9
|
+
kind: "in-flight";
|
|
10
|
+
} | {
|
|
11
|
+
kind: "unsupported";
|
|
12
|
+
};
|
|
13
|
+
export type AppModelUsageControllerHost = {
|
|
14
|
+
runtimeSession(): AgentSession | undefined;
|
|
15
|
+
render(): void;
|
|
16
|
+
};
|
|
17
|
+
export declare class AppModelUsageController {
|
|
18
|
+
private readonly host;
|
|
19
|
+
private readonly queryUsageStatus;
|
|
20
|
+
private activeModelKey;
|
|
21
|
+
private readonly statuses;
|
|
22
|
+
private readonly inFlightModelKeys;
|
|
23
|
+
private readonly lastAttemptAt;
|
|
24
|
+
private timer;
|
|
25
|
+
constructor(host: AppModelUsageControllerHost, queryUsageStatus?: AppModelUsageQuery);
|
|
26
|
+
startPolling(): void;
|
|
27
|
+
stopPolling(): void;
|
|
28
|
+
observeSession(session: AgentSession | undefined): void;
|
|
29
|
+
statusLabel(): string;
|
|
30
|
+
refreshNow(): ModelUsageRefreshStart;
|
|
31
|
+
private tick;
|
|
32
|
+
private refresh;
|
|
33
|
+
private syncActiveModel;
|
|
34
|
+
private activeStatus;
|
|
35
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { MODEL_USAGE_POLL_INTERVAL_MS, MODEL_USAGE_STATUS_TICK_MS } from "./constants.js";
|
|
2
|
+
import { formatModelUsageStatusLabel, modelUsageDescriptor, queryModelUsageStatus, } from "./model-usage-status.js";
|
|
3
|
+
export class AppModelUsageController {
|
|
4
|
+
host;
|
|
5
|
+
queryUsageStatus;
|
|
6
|
+
activeModelKey;
|
|
7
|
+
statuses = new Map();
|
|
8
|
+
inFlightModelKeys = new Set();
|
|
9
|
+
lastAttemptAt = new Map();
|
|
10
|
+
timer;
|
|
11
|
+
constructor(host, queryUsageStatus = queryModelUsageStatus) {
|
|
12
|
+
this.host = host;
|
|
13
|
+
this.queryUsageStatus = queryUsageStatus;
|
|
14
|
+
}
|
|
15
|
+
startPolling() {
|
|
16
|
+
if (this.timer)
|
|
17
|
+
return;
|
|
18
|
+
this.timer = setInterval(() => {
|
|
19
|
+
this.tick();
|
|
20
|
+
}, MODEL_USAGE_STATUS_TICK_MS);
|
|
21
|
+
this.timer.unref?.();
|
|
22
|
+
this.tick(true);
|
|
23
|
+
}
|
|
24
|
+
stopPolling() {
|
|
25
|
+
if (!this.timer)
|
|
26
|
+
return;
|
|
27
|
+
clearInterval(this.timer);
|
|
28
|
+
this.timer = undefined;
|
|
29
|
+
}
|
|
30
|
+
observeSession(session) {
|
|
31
|
+
const changed = this.syncActiveModel(session);
|
|
32
|
+
if (changed && this.activeModelKey)
|
|
33
|
+
this.refresh();
|
|
34
|
+
}
|
|
35
|
+
statusLabel() {
|
|
36
|
+
return formatModelUsageStatusLabel(this.activeStatus());
|
|
37
|
+
}
|
|
38
|
+
refreshNow() {
|
|
39
|
+
const session = this.host.runtimeSession();
|
|
40
|
+
this.syncActiveModel(session);
|
|
41
|
+
const descriptor = modelUsageDescriptor(session?.model);
|
|
42
|
+
if (!descriptor)
|
|
43
|
+
return { kind: "unsupported" };
|
|
44
|
+
const promise = this.refresh(true, descriptor);
|
|
45
|
+
return promise ? { kind: "started", promise } : { kind: "in-flight" };
|
|
46
|
+
}
|
|
47
|
+
tick(force = false) {
|
|
48
|
+
this.syncActiveModel(this.host.runtimeSession());
|
|
49
|
+
const descriptor = modelUsageDescriptor(this.host.runtimeSession()?.model);
|
|
50
|
+
if (!descriptor)
|
|
51
|
+
return;
|
|
52
|
+
const lastAttemptAt = this.lastAttemptAt.get(descriptor.modelKey) ?? 0;
|
|
53
|
+
if (force || Date.now() - lastAttemptAt >= MODEL_USAGE_POLL_INTERVAL_MS) {
|
|
54
|
+
this.refresh(force, descriptor);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (this.activeStatus())
|
|
58
|
+
this.host.render();
|
|
59
|
+
}
|
|
60
|
+
refresh(force = false, activeDescriptor) {
|
|
61
|
+
const descriptor = activeDescriptor ?? modelUsageDescriptor(this.host.runtimeSession()?.model);
|
|
62
|
+
if (!descriptor)
|
|
63
|
+
return undefined;
|
|
64
|
+
const modelKey = descriptor.modelKey;
|
|
65
|
+
if (this.inFlightModelKeys.has(modelKey))
|
|
66
|
+
return undefined;
|
|
67
|
+
const lastAttemptAt = this.lastAttemptAt.get(modelKey) ?? 0;
|
|
68
|
+
if (!force && Date.now() - lastAttemptAt < MODEL_USAGE_POLL_INTERVAL_MS)
|
|
69
|
+
return undefined;
|
|
70
|
+
this.inFlightModelKeys.add(modelKey);
|
|
71
|
+
this.lastAttemptAt.set(modelKey, Date.now());
|
|
72
|
+
return this.queryUsageStatus(descriptor).then((status) => {
|
|
73
|
+
if (status) {
|
|
74
|
+
this.statuses.set(modelKey, status);
|
|
75
|
+
return "refreshed";
|
|
76
|
+
}
|
|
77
|
+
this.statuses.delete(modelKey);
|
|
78
|
+
return "unavailable";
|
|
79
|
+
}, () => {
|
|
80
|
+
// Keep the previous value for this model on transient network/auth failures.
|
|
81
|
+
return "failed";
|
|
82
|
+
}).finally(() => {
|
|
83
|
+
this.inFlightModelKeys.delete(modelKey);
|
|
84
|
+
if (this.activeModelKey === modelKey)
|
|
85
|
+
this.host.render();
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
syncActiveModel(session) {
|
|
89
|
+
const nextModelKey = modelUsageDescriptor(session?.model)?.modelKey;
|
|
90
|
+
if (nextModelKey === this.activeModelKey)
|
|
91
|
+
return false;
|
|
92
|
+
this.activeModelKey = nextModelKey;
|
|
93
|
+
this.host.render();
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
activeStatus() {
|
|
97
|
+
return this.activeModelKey ? this.statuses.get(this.activeModelKey) : undefined;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { SessionModel } from "./types.js";
|
|
2
|
+
type BaseModelUsageDescriptor = {
|
|
3
|
+
readonly modelKey: string;
|
|
4
|
+
};
|
|
5
|
+
export type ModelUsageDescriptor = BaseModelUsageDescriptor & ({
|
|
6
|
+
readonly kind: "openai" | "zhipu";
|
|
7
|
+
} | {
|
|
8
|
+
readonly kind: "google-antigravity";
|
|
9
|
+
readonly quotaModelKey: string;
|
|
10
|
+
readonly account: AntigravityQuotaAccount;
|
|
11
|
+
});
|
|
12
|
+
export type ModelUsageLimitWindow = {
|
|
13
|
+
readonly remainingPercent: number;
|
|
14
|
+
readonly resetAt: number;
|
|
15
|
+
readonly windowSeconds: number;
|
|
16
|
+
};
|
|
17
|
+
export type ModelUsageStatus = {
|
|
18
|
+
readonly modelKey: string;
|
|
19
|
+
readonly provider: "openai" | "zhipu" | "google-antigravity";
|
|
20
|
+
readonly updatedAt: number;
|
|
21
|
+
readonly accountEmail?: string;
|
|
22
|
+
readonly weekly?: ModelUsageLimitWindow;
|
|
23
|
+
readonly hourly?: ModelUsageLimitWindow;
|
|
24
|
+
};
|
|
25
|
+
type RateLimitWindow = {
|
|
26
|
+
used_percent: number;
|
|
27
|
+
limit_window_seconds: number;
|
|
28
|
+
reset_after_seconds: number;
|
|
29
|
+
};
|
|
30
|
+
type OpenAIRateLimit = {
|
|
31
|
+
allowed?: boolean;
|
|
32
|
+
limit_reached: boolean;
|
|
33
|
+
primary_window: RateLimitWindow;
|
|
34
|
+
secondary_window: RateLimitWindow | null;
|
|
35
|
+
};
|
|
36
|
+
type OpenAIAdditionalRateLimit = {
|
|
37
|
+
limit_name: string;
|
|
38
|
+
metered_feature?: string;
|
|
39
|
+
rate_limit: OpenAIRateLimit | null;
|
|
40
|
+
};
|
|
41
|
+
export type AccountUsageLimitWindow = {
|
|
42
|
+
readonly label: string;
|
|
43
|
+
readonly remainingPercent: number;
|
|
44
|
+
readonly resetAt: number;
|
|
45
|
+
readonly windowSeconds: number;
|
|
46
|
+
readonly used?: number;
|
|
47
|
+
readonly limit?: number;
|
|
48
|
+
};
|
|
49
|
+
export type AccountUsageReport = {
|
|
50
|
+
readonly openai?: {
|
|
51
|
+
readonly account: string;
|
|
52
|
+
readonly planType?: string;
|
|
53
|
+
readonly windows: readonly AccountUsageLimitWindow[];
|
|
54
|
+
readonly limitReached: boolean;
|
|
55
|
+
readonly additionalLimits?: readonly {
|
|
56
|
+
readonly name: string;
|
|
57
|
+
readonly meteredFeature?: string;
|
|
58
|
+
readonly windows: readonly AccountUsageLimitWindow[];
|
|
59
|
+
readonly limitReached: boolean;
|
|
60
|
+
}[];
|
|
61
|
+
readonly error?: string;
|
|
62
|
+
};
|
|
63
|
+
readonly zai?: {
|
|
64
|
+
readonly account: string;
|
|
65
|
+
readonly windows: readonly AccountUsageLimitWindow[];
|
|
66
|
+
readonly mcp?: AccountUsageLimitWindow;
|
|
67
|
+
readonly error?: string;
|
|
68
|
+
};
|
|
69
|
+
readonly googleAccounts: readonly {
|
|
70
|
+
readonly account: string;
|
|
71
|
+
readonly windows: readonly AccountUsageLimitWindow[];
|
|
72
|
+
readonly limitReached: boolean;
|
|
73
|
+
readonly error?: string;
|
|
74
|
+
}[];
|
|
75
|
+
readonly generatedAt: number;
|
|
76
|
+
};
|
|
77
|
+
export type OpenAIUsageResponse = {
|
|
78
|
+
plan_type: string;
|
|
79
|
+
rate_limit: OpenAIRateLimit | null;
|
|
80
|
+
additional_rate_limits?: OpenAIAdditionalRateLimit[];
|
|
81
|
+
};
|
|
82
|
+
type AntigravityQuotaAccount = {
|
|
83
|
+
readonly email?: string;
|
|
84
|
+
readonly refreshToken: string;
|
|
85
|
+
readonly projectId: string;
|
|
86
|
+
readonly accountIndex?: number;
|
|
87
|
+
readonly accountCount?: number;
|
|
88
|
+
readonly cacheKey: string;
|
|
89
|
+
};
|
|
90
|
+
type GoogleQuotaResponse = {
|
|
91
|
+
models: Record<string, {
|
|
92
|
+
quotaInfo?: {
|
|
93
|
+
remainingFraction?: number;
|
|
94
|
+
resetTime?: string;
|
|
95
|
+
};
|
|
96
|
+
}>;
|
|
97
|
+
};
|
|
98
|
+
export declare function modelUsageDescriptor(model: SessionModel | undefined): ModelUsageDescriptor | undefined;
|
|
99
|
+
export declare function queryModelUsageStatus(descriptor: ModelUsageDescriptor): Promise<ModelUsageStatus | undefined>;
|
|
100
|
+
export declare function queryAccountUsageReport(now?: number): Promise<AccountUsageReport>;
|
|
101
|
+
export declare function formatAccountUsageReport(report: AccountUsageReport, now?: number): string;
|
|
102
|
+
export declare function formatModelUsageStatusLabel(status: ModelUsageStatus | undefined, now?: number): string;
|
|
103
|
+
export declare function modelUsageRemainingPercent(status: ModelUsageStatus | undefined): number | undefined;
|
|
104
|
+
export declare function openAIUsageStatusFromResponse(data: OpenAIUsageResponse, modelKey: string, now?: number): ModelUsageStatus | undefined;
|
|
105
|
+
type ZhipuUsageLimitItem = {
|
|
106
|
+
type: string;
|
|
107
|
+
usage: number;
|
|
108
|
+
currentValue: number;
|
|
109
|
+
percentage: number;
|
|
110
|
+
nextResetTime?: number;
|
|
111
|
+
};
|
|
112
|
+
type ZhipuQuotaResponse = {
|
|
113
|
+
code: number;
|
|
114
|
+
msg: string;
|
|
115
|
+
data: {
|
|
116
|
+
limits: ZhipuUsageLimitItem[];
|
|
117
|
+
};
|
|
118
|
+
success: boolean;
|
|
119
|
+
};
|
|
120
|
+
export declare function zhipuUsageStatusFromResponse(data: ZhipuQuotaResponse, modelKey: string, now?: number): ModelUsageStatus | undefined;
|
|
121
|
+
export declare function resolveAntigravityQuotaModelKey(model: SessionModel): string | undefined;
|
|
122
|
+
export declare function googleAntigravityUsageStatusFromResponse(data: GoogleQuotaResponse, descriptor: Extract<ModelUsageDescriptor, {
|
|
123
|
+
kind: "google-antigravity";
|
|
124
|
+
}>, now?: number): ModelUsageStatus | undefined;
|
|
125
|
+
export {};
|