shortcutxl 0.2.0
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 +59 -0
- package/agent-docs/README.md +397 -0
- package/agent-docs/docs/compaction.md +390 -0
- package/agent-docs/docs/custom-provider.md +580 -0
- package/agent-docs/docs/development.md +69 -0
- package/agent-docs/docs/extensions.md +1971 -0
- package/agent-docs/docs/json.md +79 -0
- package/agent-docs/docs/keybindings.md +174 -0
- package/agent-docs/docs/models.md +293 -0
- package/agent-docs/docs/packages.md +209 -0
- package/agent-docs/docs/prompt-templates.md +67 -0
- package/agent-docs/docs/providers.md +186 -0
- package/agent-docs/docs/rpc.md +1317 -0
- package/agent-docs/docs/sdk.md +962 -0
- package/agent-docs/docs/session.md +412 -0
- package/agent-docs/docs/settings.md +223 -0
- package/agent-docs/docs/shell-aliases.md +13 -0
- package/agent-docs/docs/skills.md +231 -0
- package/agent-docs/docs/terminal-setup.md +70 -0
- package/agent-docs/docs/termux.md +127 -0
- package/agent-docs/docs/themes.md +295 -0
- package/agent-docs/docs/tree.md +219 -0
- package/agent-docs/docs/tui.md +887 -0
- package/agent-docs/docs/windows.md +17 -0
- package/agent-docs/examples/README.md +25 -0
- package/agent-docs/examples/extensions/README.md +205 -0
- package/agent-docs/examples/extensions/antigravity-image-gen.ts +447 -0
- package/agent-docs/examples/extensions/auto-commit-on-exit.ts +49 -0
- package/agent-docs/examples/extensions/bash-spawn-hook.ts +30 -0
- package/agent-docs/examples/extensions/bookmark.ts +50 -0
- package/agent-docs/examples/extensions/built-in-tool-renderer.ts +256 -0
- package/agent-docs/examples/extensions/claude-rules.ts +86 -0
- package/agent-docs/examples/extensions/commands.ts +75 -0
- package/agent-docs/examples/extensions/confirm-destructive.ts +59 -0
- package/agent-docs/examples/extensions/custom-compaction.ts +126 -0
- package/agent-docs/examples/extensions/custom-footer.ts +63 -0
- package/agent-docs/examples/extensions/custom-header.ts +73 -0
- package/agent-docs/examples/extensions/custom-provider-anthropic/index.ts +660 -0
- package/agent-docs/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/agent-docs/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/agent-docs/examples/extensions/custom-provider-gitlab-duo/index.ts +362 -0
- package/agent-docs/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/agent-docs/examples/extensions/custom-provider-gitlab-duo/test.ts +88 -0
- package/agent-docs/examples/extensions/custom-provider-qwen-cli/index.ts +349 -0
- package/agent-docs/examples/extensions/custom-provider-qwen-cli/package.json +16 -0
- package/agent-docs/examples/extensions/dirty-repo-guard.ts +56 -0
- package/agent-docs/examples/extensions/doom-overlay/README.md +46 -0
- package/agent-docs/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/agent-docs/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
- package/agent-docs/examples/extensions/doom-overlay/doom-component.ts +133 -0
- package/agent-docs/examples/extensions/doom-overlay/doom-engine.ts +186 -0
- package/agent-docs/examples/extensions/doom-overlay/doom-keys.ts +108 -0
- package/agent-docs/examples/extensions/doom-overlay/index.ts +74 -0
- package/agent-docs/examples/extensions/doom-overlay/wad-finder.ts +51 -0
- package/agent-docs/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/agent-docs/examples/extensions/dynamic-resources/dynamic.json +79 -0
- package/agent-docs/examples/extensions/dynamic-resources/dynamic.md +5 -0
- package/agent-docs/examples/extensions/dynamic-resources/index.ts +15 -0
- package/agent-docs/examples/extensions/dynamic-tools.ts +77 -0
- package/agent-docs/examples/extensions/event-bus.ts +43 -0
- package/agent-docs/examples/extensions/file-trigger.ts +41 -0
- package/agent-docs/examples/extensions/git-checkpoint.ts +53 -0
- package/agent-docs/examples/extensions/handoff.ts +155 -0
- package/agent-docs/examples/extensions/hello.ts +25 -0
- package/agent-docs/examples/extensions/inline-bash.ts +94 -0
- package/agent-docs/examples/extensions/input-transform.ts +43 -0
- package/agent-docs/examples/extensions/interactive-shell.ts +209 -0
- package/agent-docs/examples/extensions/mac-system-theme.ts +47 -0
- package/agent-docs/examples/extensions/message-renderer.ts +59 -0
- package/agent-docs/examples/extensions/minimal-mode.ts +430 -0
- package/agent-docs/examples/extensions/modal-editor.ts +90 -0
- package/agent-docs/examples/extensions/model-status.ts +31 -0
- package/agent-docs/examples/extensions/notify.ts +55 -0
- package/agent-docs/examples/extensions/overlay-qa-tests.ts +936 -0
- package/agent-docs/examples/extensions/overlay-test.ts +159 -0
- package/agent-docs/examples/extensions/permission-gate.ts +37 -0
- package/agent-docs/examples/extensions/pirate.ts +47 -0
- package/agent-docs/examples/extensions/plan-mode/README.md +65 -0
- package/agent-docs/examples/extensions/plan-mode/index.ts +363 -0
- package/agent-docs/examples/extensions/plan-mode/utils.ts +173 -0
- package/agent-docs/examples/extensions/preset.ts +418 -0
- package/agent-docs/examples/extensions/protected-paths.ts +30 -0
- package/agent-docs/examples/extensions/qna.ts +122 -0
- package/agent-docs/examples/extensions/question.ts +278 -0
- package/agent-docs/examples/extensions/questionnaire.ts +440 -0
- package/agent-docs/examples/extensions/rainbow-editor.ts +90 -0
- package/agent-docs/examples/extensions/reload-runtime.ts +37 -0
- package/agent-docs/examples/extensions/rpc-demo.ts +124 -0
- package/agent-docs/examples/extensions/sandbox/index.ts +324 -0
- package/agent-docs/examples/extensions/sandbox/package-lock.json +92 -0
- package/agent-docs/examples/extensions/sandbox/package.json +19 -0
- package/agent-docs/examples/extensions/send-user-message.ts +97 -0
- package/agent-docs/examples/extensions/session-name.ts +27 -0
- package/agent-docs/examples/extensions/shutdown-command.ts +69 -0
- package/agent-docs/examples/extensions/snake.ts +343 -0
- package/agent-docs/examples/extensions/space-invaders.ts +566 -0
- package/agent-docs/examples/extensions/ssh.ts +233 -0
- package/agent-docs/examples/extensions/status-line.ts +40 -0
- package/agent-docs/examples/extensions/subagent/README.md +172 -0
- package/agent-docs/examples/extensions/subagent/agents/planner.md +37 -0
- package/agent-docs/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/agent-docs/examples/extensions/subagent/agents/scout.md +50 -0
- package/agent-docs/examples/extensions/subagent/agents/worker.md +24 -0
- package/agent-docs/examples/extensions/subagent/agents.ts +130 -0
- package/agent-docs/examples/extensions/subagent/index.ts +1068 -0
- package/agent-docs/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/agent-docs/examples/extensions/subagent/prompts/implement.md +10 -0
- package/agent-docs/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/agent-docs/examples/extensions/summarize.ts +206 -0
- package/agent-docs/examples/extensions/system-prompt-header.ts +17 -0
- package/agent-docs/examples/extensions/timed-confirm.ts +72 -0
- package/agent-docs/examples/extensions/titlebar-spinner.ts +58 -0
- package/agent-docs/examples/extensions/todo.ts +314 -0
- package/agent-docs/examples/extensions/tool-override.ts +146 -0
- package/agent-docs/examples/extensions/tools.ts +145 -0
- package/agent-docs/examples/extensions/trigger-compact.ts +40 -0
- package/agent-docs/examples/extensions/truncated-tool.ts +194 -0
- package/agent-docs/examples/extensions/widget-placement.ts +17 -0
- package/agent-docs/examples/extensions/with-deps/index.ts +37 -0
- package/agent-docs/examples/extensions/with-deps/package-lock.json +31 -0
- package/agent-docs/examples/extensions/with-deps/package.json +22 -0
- package/agent-docs/examples/rpc-extension-ui.ts +654 -0
- package/agent-docs/examples/sdk/01-minimal.ts +22 -0
- package/agent-docs/examples/sdk/02-custom-model.ts +48 -0
- package/agent-docs/examples/sdk/03-custom-prompt.ts +55 -0
- package/agent-docs/examples/sdk/04-skills.ts +53 -0
- package/agent-docs/examples/sdk/05-tools.ts +56 -0
- package/agent-docs/examples/sdk/06-extensions.ts +88 -0
- package/agent-docs/examples/sdk/07-context-files.ts +40 -0
- package/agent-docs/examples/sdk/08-prompt-templates.ts +47 -0
- package/agent-docs/examples/sdk/09-api-keys-and-oauth.ts +48 -0
- package/agent-docs/examples/sdk/10-settings.ts +54 -0
- package/agent-docs/examples/sdk/11-sessions.ts +48 -0
- package/agent-docs/examples/sdk/12-full-control.ts +82 -0
- package/agent-docs/examples/sdk/README.md +144 -0
- package/agent-docs/xll-skill.md +61 -0
- package/agent-docs/xll-spec.md +110 -0
- package/dist/cli/args.js +290 -0
- package/dist/cli/config-selector.js +31 -0
- package/dist/cli/file-processor.js +79 -0
- package/dist/cli/list-models.js +92 -0
- package/dist/cli/package-commands.js +210 -0
- package/dist/cli/report-settings-errors.js +11 -0
- package/dist/cli/session-picker.js +34 -0
- package/dist/cli.js +19 -0
- package/dist/config.js +288 -0
- package/dist/core/abort.js +15 -0
- package/dist/core/agent-loop.js +352 -0
- package/dist/core/agent-session.js +2019 -0
- package/dist/core/agent.js +410 -0
- package/dist/core/auth-storage.js +456 -0
- package/dist/core/bash-executor.js +222 -0
- package/dist/core/compaction/branch-summarization.js +242 -0
- package/dist/core/compaction/compaction.js +610 -0
- package/dist/core/compaction/index.js +7 -0
- package/dist/core/compaction/utils.js +139 -0
- package/dist/core/defaults.js +6 -0
- package/dist/core/diagnostics.js +2 -0
- package/dist/core/event-bus.js +25 -0
- package/dist/core/exec.js +71 -0
- package/dist/core/export-html/ansi-to-html.js +256 -0
- package/dist/core/export-html/index.js +238 -0
- package/dist/core/export-html/session-view-model.js +342 -0
- package/dist/core/export-html/template.css +1110 -0
- package/dist/core/export-html/template.html +76 -0
- package/dist/core/export-html/template.js +1990 -0
- package/dist/core/export-html/tool-renderer.js +63 -0
- package/dist/core/export-html/vendor/highlight.min.js +7725 -0
- package/dist/core/export-html/vendor/marked.min.js +1803 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/loader.js +422 -0
- package/dist/core/extensions/runner.js +651 -0
- package/dist/core/extensions/types.js +35 -0
- package/dist/core/extensions/wrapper.js +102 -0
- package/dist/core/footer-data-provider.js +162 -0
- package/dist/core/index.js +9 -0
- package/dist/core/keybindings.js +153 -0
- package/dist/core/messages.js +133 -0
- package/dist/core/model-registry.js +539 -0
- package/dist/core/model-resolver.js +370 -0
- package/dist/core/package-manager.js +1485 -0
- package/dist/core/prompt-templates.js +253 -0
- package/dist/core/resolve-config-value.js +59 -0
- package/dist/core/resource-loader.js +700 -0
- package/dist/core/sdk.js +197 -0
- package/dist/core/session-bash.js +99 -0
- package/dist/core/session-compaction.js +165 -0
- package/dist/core/session-manager.js +1153 -0
- package/dist/core/session-models.js +99 -0
- package/dist/core/session-retry.js +155 -0
- package/dist/core/settings-manager.js +572 -0
- package/dist/core/skills.js +382 -0
- package/dist/core/slash-commands.js +31 -0
- package/dist/core/system-prompt.js +161 -0
- package/dist/core/theme.js +770 -0
- package/dist/core/timings.js +26 -0
- package/dist/core/tools/bash.js +258 -0
- package/dist/core/tools/edit-diff.js +245 -0
- package/dist/core/tools/edit.js +148 -0
- package/dist/core/tools/find.js +208 -0
- package/dist/core/tools/grep.js +246 -0
- package/dist/core/tools/index.js +67 -0
- package/dist/core/tools/ls.js +123 -0
- package/dist/core/tools/path-utils.js +81 -0
- package/dist/core/tools/read.js +160 -0
- package/dist/core/tools/truncate.js +70 -0
- package/dist/core/tools/write.js +82 -0
- package/dist/custom/agents/action.js +13 -0
- package/dist/custom/agents/document-reader.js +70 -0
- package/dist/custom/agents/general.js +26 -0
- package/dist/custom/agents/index.js +49 -0
- package/dist/custom/agents/installation.js +13 -0
- package/dist/custom/agents/types.js +7 -0
- package/dist/custom/auth/refresh-timer.js +33 -0
- package/dist/custom/auth/shortcut-oauth.js +145 -0
- package/dist/custom/constants.js +21 -0
- package/dist/custom/context/workbook-summary.js +73 -0
- package/dist/custom/credits/shortcut-credits.js +29 -0
- package/dist/custom/cron/cron-daemon-entry.js +18 -0
- package/dist/custom/cron/daemon-ipc.js +131 -0
- package/dist/custom/cron/daemon.js +224 -0
- package/dist/custom/cron/jobs.js +226 -0
- package/dist/custom/cron/run-log.js +51 -0
- package/dist/custom/cron/schedule.js +72 -0
- package/dist/custom/cron/status-line.js +98 -0
- package/dist/custom/cron/store.js +87 -0
- package/dist/custom/cron/types.js +8 -0
- package/dist/custom/dev/index.js +59 -0
- package/dist/custom/dev/trace-export.js +58 -0
- package/dist/custom/ensure-excel.js +63 -0
- package/dist/custom/excel-config.js +36 -0
- package/dist/custom/preflight.js +422 -0
- package/dist/custom/prompts/action.js +100 -0
- package/dist/custom/prompts/api.js +66 -0
- package/dist/custom/prompts/installation.js +124 -0
- package/dist/custom/prompts/shared.js +138 -0
- package/dist/custom/providers/llm-usage.js +42 -0
- package/dist/custom/providers/message-converter.js +74 -0
- package/dist/custom/providers/provider-ids.js +9 -0
- package/dist/custom/providers/register-openai-codex-provider.js +27 -0
- package/dist/custom/providers/register-shortcut-provider.js +52 -0
- package/dist/custom/providers/shortcut-invoke.js +117 -0
- package/dist/custom/providers/shortcut-stream.js +252 -0
- package/dist/custom/providers/sse-protocol.js +38 -0
- package/dist/custom/sync-xll.js +130 -0
- package/dist/custom/tools/cron.js +413 -0
- package/dist/custom/tools/excel-exec.js +167 -0
- package/dist/custom/tools/excel-range.js +50 -0
- package/dist/custom/tools/llm-analysis.js +265 -0
- package/dist/custom/tools/render-helpers.js +38 -0
- package/dist/custom/tools/switch-mode.js +94 -0
- package/dist/custom/tools/task/agents.js +6 -0
- package/dist/custom/tools/task/index.js +8 -0
- package/dist/custom/tools/task/render.js +348 -0
- package/dist/custom/tools/task/subprocess.js +320 -0
- package/dist/custom/tools/task/task.js +205 -0
- package/dist/custom/tools/todo-list.js +195 -0
- package/dist/custom/tracing/session-upload.js +93 -0
- package/dist/index.js +45 -0
- package/dist/main.js +613 -0
- package/dist/migrations.js +265 -0
- package/dist/modes/index.js +8 -0
- package/dist/modes/interactive/components/armin.js +337 -0
- package/dist/modes/interactive/components/assistant-message.js +94 -0
- package/dist/modes/interactive/components/bash-execution.js +171 -0
- package/dist/modes/interactive/components/bordered-loader.js +51 -0
- package/dist/modes/interactive/components/branch-summary-message.js +45 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +46 -0
- package/dist/modes/interactive/components/config-selector.js +488 -0
- package/dist/modes/interactive/components/countdown-timer.js +33 -0
- package/dist/modes/interactive/components/custom-editor.js +93 -0
- package/dist/modes/interactive/components/custom-message.js +81 -0
- package/dist/modes/interactive/components/daxnuts.js +140 -0
- package/dist/modes/interactive/components/diff.js +133 -0
- package/dist/modes/interactive/components/dynamic-border.js +21 -0
- package/dist/modes/interactive/components/extension-editor.js +105 -0
- package/dist/modes/interactive/components/extension-input.js +61 -0
- package/dist/modes/interactive/components/extension-selector.js +78 -0
- package/dist/modes/interactive/components/footer.js +309 -0
- package/dist/modes/interactive/components/index.js +33 -0
- package/dist/modes/interactive/components/keybinding-hints.js +61 -0
- package/dist/modes/interactive/components/layout.js +64 -0
- package/dist/modes/interactive/components/login-dialog.js +148 -0
- package/dist/modes/interactive/components/model-selector.js +237 -0
- package/dist/modes/interactive/components/oauth-selector.js +111 -0
- package/dist/modes/interactive/components/session-selector-search.js +157 -0
- package/dist/modes/interactive/components/session-selector.js +860 -0
- package/dist/modes/interactive/components/settings-selector.js +123 -0
- package/dist/modes/interactive/components/show-images-selector.js +35 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +48 -0
- package/dist/modes/interactive/components/theme-selector.js +47 -0
- package/dist/modes/interactive/components/thinking-selector.js +47 -0
- package/dist/modes/interactive/components/tool-execution.js +789 -0
- package/dist/modes/interactive/components/tool-group.js +106 -0
- package/dist/modes/interactive/components/tree-selector.js +962 -0
- package/dist/modes/interactive/components/user-message-selector.js +115 -0
- package/dist/modes/interactive/components/user-message.js +48 -0
- package/dist/modes/interactive/components/visual-truncate.js +33 -0
- package/dist/modes/interactive/file-attachments.js +135 -0
- package/dist/modes/interactive/interactive-mode.js +3775 -0
- package/dist/modes/interactive/theme/dark.json +85 -0
- package/dist/modes/interactive/theme/light.json +85 -0
- package/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/dist/modes/interactive/theme/theme.js +177 -0
- package/dist/modes/print-mode.js +101 -0
- package/dist/modes/rpc/rpc-client.js +387 -0
- package/dist/modes/rpc/rpc-mode.js +509 -0
- package/dist/modes/rpc/rpc-types.js +8 -0
- package/dist/subagent-entry.js +145 -0
- package/dist/tool-names.js +34 -0
- package/dist/tui/autocomplete.js +596 -0
- package/dist/tui/components/box.js +104 -0
- package/dist/tui/components/cancellable-loader.js +35 -0
- package/dist/tui/components/editor.js +1679 -0
- package/dist/tui/components/image.js +69 -0
- package/dist/tui/components/input.js +433 -0
- package/dist/tui/components/loader.js +49 -0
- package/dist/tui/components/markdown.js +629 -0
- package/dist/tui/components/select-list.js +152 -0
- package/dist/tui/components/settings-list.js +185 -0
- package/dist/tui/components/spacer.js +23 -0
- package/dist/tui/components/text.js +89 -0
- package/dist/tui/components/truncated-text.js +51 -0
- package/dist/tui/editor-component.js +2 -0
- package/dist/tui/fuzzy.js +107 -0
- package/dist/tui/get-east-asian-width/index.js +32 -0
- package/dist/tui/get-east-asian-width/lookup.js +404 -0
- package/dist/tui/index.js +32 -0
- package/dist/tui/keybindings.js +114 -0
- package/dist/tui/keys.js +959 -0
- package/dist/tui/kill-ring.js +44 -0
- package/dist/tui/stdin-buffer.js +317 -0
- package/dist/tui/terminal-image.js +288 -0
- package/dist/tui/terminal.js +249 -0
- package/dist/tui/tui/autocomplete.js +596 -0
- package/dist/tui/tui/components/box.js +106 -0
- package/dist/tui/tui/components/cancellable-loader.js +35 -0
- package/dist/tui/tui/components/editor.js +1679 -0
- package/dist/tui/tui/components/image.js +69 -0
- package/dist/tui/tui/components/input.js +433 -0
- package/dist/tui/tui/components/loader.js +49 -0
- package/dist/tui/tui/components/markdown.js +629 -0
- package/dist/tui/tui/components/select-list.js +152 -0
- package/dist/tui/tui/components/settings-list.js +185 -0
- package/dist/tui/tui/components/spacer.js +23 -0
- package/dist/tui/tui/components/text.js +91 -0
- package/dist/tui/tui/components/truncated-text.js +51 -0
- package/dist/tui/tui/editor-component.js +2 -0
- package/dist/tui/tui/fuzzy.js +107 -0
- package/dist/tui/tui/get-east-asian-width/index.js +32 -0
- package/dist/tui/tui/get-east-asian-width/lookup.js +404 -0
- package/dist/tui/tui/index.js +32 -0
- package/dist/tui/tui/keybindings.js +114 -0
- package/dist/tui/tui/keys.js +959 -0
- package/dist/tui/tui/kill-ring.js +44 -0
- package/dist/tui/tui/stdin-buffer.js +317 -0
- package/dist/tui/tui/terminal-image.js +288 -0
- package/dist/tui/tui/terminal.js +249 -0
- package/dist/tui/tui/tui.js +955 -0
- package/dist/tui/tui/undo-stack.js +25 -0
- package/dist/tui/tui/utils.js +800 -0
- package/dist/tui/tui.js +955 -0
- package/dist/tui/undo-stack.js +25 -0
- package/dist/tui/utils.js +800 -0
- package/dist/utils/changelog.js +87 -0
- package/dist/utils/clipboard-image.js +164 -0
- package/dist/utils/clipboard-native.js +14 -0
- package/dist/utils/clipboard.js +67 -0
- package/dist/utils/frontmatter.js +26 -0
- package/dist/utils/git.js +166 -0
- package/dist/utils/image-convert.js +35 -0
- package/dist/utils/image-resize.js +183 -0
- package/dist/utils/mime.js +26 -0
- package/dist/utils/photon.js +121 -0
- package/dist/utils/shell.js +217 -0
- package/dist/utils/sleep.js +17 -0
- package/dist/utils/tools-manager.js +259 -0
- package/package.json +78 -0
- package/skills/excel-com-api/SKILL.md +74 -0
- package/skills/excel-com-api/excel-type-library.py +27767 -0
- package/skills/excel-com-api/office-type-library.py +10867 -0
- package/skills/integrations/SKILL.md +138 -0
- package/skills/integrations/alphasense.md +457 -0
- package/skills/integrations/bloomberg.md +803 -0
- package/skills/integrations/calcbench.md +315 -0
- package/skills/integrations/capiq.md +848 -0
- package/skills/integrations/dynamics-365-finance.md +354 -0
- package/skills/integrations/earnings_transcripts.md +387 -0
- package/skills/integrations/factset.md +758 -0
- package/skills/integrations/ice-fixed-income.md +344 -0
- package/skills/integrations/moodys-analytics.md +313 -0
- package/skills/integrations/morningstar.md +433 -0
- package/skills/integrations/nasdaq-data-link.md +249 -0
- package/skills/integrations/pitchbook.md +413 -0
- package/skills/integrations/preqin.md +422 -0
- package/skills/integrations/quickbooks.md +289 -0
- package/skills/integrations/quickfs.md +314 -0
- package/skills/integrations/refinitiv.md +473 -0
- package/skills/integrations/sage-intacct.md +401 -0
- package/skills/integrations/visible-alpha.md +320 -0
- package/skills/integrations/xero.md +393 -0
- package/skills/integrations/ycharts.md +306 -0
- package/skills/pdf-creation/SKILL.md +93 -0
- package/skills/pdf-extraction/SKILL.md +32 -0
- package/skills/powerpoint-creation/SKILL.md +110 -0
- package/skills/sec-edgar/SKILL.md +127 -0
- package/skills/sec-edgar/sec_to_pdf.py +109 -0
- package/xll/ShortcutXL.xll +0 -0
- package/xll/modules/debug_render.py +272 -0
- package/xll/modules/gameboy.py +241 -0
- package/xll/modules/pong.py +188 -0
- package/xll/modules/shortcut_xl/__init__.py +18 -0
- package/xll/modules/shortcut_xl/_categorize.py +200 -0
- package/xll/modules/shortcut_xl/_com.py +108 -0
- package/xll/modules/shortcut_xl/_format.py +252 -0
- package/xll/modules/shortcut_xl/_log.py +12 -0
- package/xll/modules/shortcut_xl/_managed.py +116 -0
- package/xll/modules/shortcut_xl/_registry.py +44 -0
- package/xll/modules/shortcut_xl/_threading.py +161 -0
- package/xll/modules/shortcut_xl/_tracking.py +283 -0
- package/xll/modules/stocks.py +100 -0
- package/xll/python3.dll +0 -0
- package/xll/python312.dll +0 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { truncateToWidth, visibleWidth } from '../../../tui/index.js';
|
|
2
|
+
import { theme } from '../../../core/theme.js';
|
|
3
|
+
/**
|
|
4
|
+
* Sanitize text for display in a single-line status.
|
|
5
|
+
* Removes newlines, tabs, carriage returns, and other control characters.
|
|
6
|
+
*/
|
|
7
|
+
function sanitizeStatusText(text) {
|
|
8
|
+
// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces
|
|
9
|
+
return text
|
|
10
|
+
.replace(/[\r\n\t]/g, ' ')
|
|
11
|
+
.replace(/ +/g, ' ')
|
|
12
|
+
.trim();
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Format token counts (similar to web-ui)
|
|
16
|
+
*/
|
|
17
|
+
function formatTokens(count) {
|
|
18
|
+
if (count < 1000)
|
|
19
|
+
return count.toString();
|
|
20
|
+
if (count < 10000)
|
|
21
|
+
return `${(count / 1000).toFixed(1)}k`;
|
|
22
|
+
if (count < 1000000)
|
|
23
|
+
return `${Math.round(count / 1000)}k`;
|
|
24
|
+
if (count < 10000000)
|
|
25
|
+
return `${(count / 1000000).toFixed(1)}M`;
|
|
26
|
+
return `${Math.round(count / 1000000)}M`;
|
|
27
|
+
}
|
|
28
|
+
// ANSI escape helpers for credit tier styling
|
|
29
|
+
const ANSI = {
|
|
30
|
+
bold: '\x1b[1m',
|
|
31
|
+
brightWhite: '\x1b[97m',
|
|
32
|
+
cyan: '\x1b[36m',
|
|
33
|
+
brightCyan: '\x1b[96m',
|
|
34
|
+
reset: '\x1b[0m',
|
|
35
|
+
resetFg: '\x1b[39m',
|
|
36
|
+
resetBold: '\x1b[22m'
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Style credit text based on usage tiers.
|
|
40
|
+
* Higher spend = more visually prominent = more "achievement" feel.
|
|
41
|
+
*
|
|
42
|
+
* 0 → dim (haven't started yet)
|
|
43
|
+
* 1-29 → normal (getting going)
|
|
44
|
+
* 30-99 → bold bright white (making progress)
|
|
45
|
+
* 100-299 → cyan (power user)
|
|
46
|
+
* 300+ → bright cyan + bold (legend)
|
|
47
|
+
*/
|
|
48
|
+
function styleCreditText(text, creditsUsed) {
|
|
49
|
+
if (creditsUsed <= 0)
|
|
50
|
+
return theme.fg('dim', text);
|
|
51
|
+
if (creditsUsed < 30)
|
|
52
|
+
return text;
|
|
53
|
+
if (creditsUsed < 100)
|
|
54
|
+
return `${ANSI.bold}${ANSI.brightWhite}${text}${ANSI.resetBold}${ANSI.resetFg}`;
|
|
55
|
+
if (creditsUsed < 300)
|
|
56
|
+
return `${ANSI.cyan}${text}${ANSI.resetFg}`;
|
|
57
|
+
return `${ANSI.bold}${ANSI.brightCyan}${text}${ANSI.resetBold}${ANSI.resetFg}`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Count user queries (user messages) in the session.
|
|
61
|
+
*/
|
|
62
|
+
function countUserQueries(session) {
|
|
63
|
+
let count = 0;
|
|
64
|
+
for (const entry of session.sessionManager.getEntries()) {
|
|
65
|
+
if (entry.type === 'message' && entry.message.role === 'user') {
|
|
66
|
+
count++;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return count;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Footer component that shows pwd, token stats, and context usage.
|
|
73
|
+
* Computes token/context stats from session, gets git branch and extension statuses from provider.
|
|
74
|
+
*
|
|
75
|
+
* Shortcut credit users get a gamified footer:
|
|
76
|
+
* - Credits styled by spend tier (dim → normal → bold → cyan → bright cyan)
|
|
77
|
+
* - Context % colored by usage AND query count (orange at 50%/10q, red at 75%/15q)
|
|
78
|
+
* - Separator line on top
|
|
79
|
+
*/
|
|
80
|
+
export class FooterComponent {
|
|
81
|
+
session;
|
|
82
|
+
footerData;
|
|
83
|
+
constructor(session, footerData) {
|
|
84
|
+
this.session = session;
|
|
85
|
+
this.footerData = footerData;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* No-op: git branch caching now handled by provider.
|
|
89
|
+
* Kept for compatibility with existing call sites in interactive-mode.
|
|
90
|
+
*/
|
|
91
|
+
invalidate() {
|
|
92
|
+
// No-op: git branch is cached/invalidated by provider
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Clean up resources.
|
|
96
|
+
* Git watcher cleanup now handled by provider.
|
|
97
|
+
*/
|
|
98
|
+
dispose() {
|
|
99
|
+
// Git watcher cleanup handled by provider
|
|
100
|
+
}
|
|
101
|
+
render(width) {
|
|
102
|
+
const state = this.session.state;
|
|
103
|
+
// Calculate cumulative usage from ALL session entries (not just post-compaction messages)
|
|
104
|
+
let totalInput = 0;
|
|
105
|
+
let totalOutput = 0;
|
|
106
|
+
let totalCacheRead = 0;
|
|
107
|
+
let totalCacheWrite = 0;
|
|
108
|
+
let totalCost = 0;
|
|
109
|
+
for (const entry of this.session.sessionManager.getEntries()) {
|
|
110
|
+
if (entry.type === 'message' && entry.message.role === 'assistant') {
|
|
111
|
+
totalInput += entry.message.usage.input;
|
|
112
|
+
totalOutput += entry.message.usage.output;
|
|
113
|
+
totalCacheRead += entry.message.usage.cacheRead;
|
|
114
|
+
totalCacheWrite += entry.message.usage.cacheWrite;
|
|
115
|
+
totalCost += entry.message.usage.cost.total;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Calculate context usage from session (handles compaction correctly).
|
|
119
|
+
// After compaction, tokens are unknown until the next LLM response.
|
|
120
|
+
const contextUsage = this.session.getContextUsage();
|
|
121
|
+
const contextPercentValue = contextUsage?.percent ?? 0;
|
|
122
|
+
const contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : '?';
|
|
123
|
+
// Count user queries for context heat meter
|
|
124
|
+
const queryCount = countUserQueries(this.session);
|
|
125
|
+
// Build info line: session name only (no branch — user prefers minimal footer)
|
|
126
|
+
const sessionName = this.session.sessionManager.getSessionName();
|
|
127
|
+
const infoLine = sessionName || null;
|
|
128
|
+
// Build stats line
|
|
129
|
+
const statsParts = [];
|
|
130
|
+
// Track plain-text widths for each part (ANSI codes have zero visible width)
|
|
131
|
+
const isShortcutCredits = !!this.footerData.getCreditBalance();
|
|
132
|
+
// If a credit balance is available, show credits with tier styling.
|
|
133
|
+
// If the model uses credits but the balance fetch failed, show tokens only (no $cost).
|
|
134
|
+
// Otherwise show full token breakdown + cost.
|
|
135
|
+
const creditBalance = this.footerData.getCreditBalance();
|
|
136
|
+
if (creditBalance) {
|
|
137
|
+
const creditsUsed = this.footerData.getCreditsUsed();
|
|
138
|
+
if (creditBalance.isUnlimited) {
|
|
139
|
+
statsParts.push(theme.fg('dim', 'credits: ∞'));
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const creditsText = `credits used: ${creditsUsed}`;
|
|
143
|
+
statsParts.push(styleCreditText(creditsText, creditsUsed));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else if (this.footerData.usesCredits) {
|
|
147
|
+
// Credit-based model but balance unavailable — show tokens without $cost
|
|
148
|
+
if (totalInput)
|
|
149
|
+
statsParts.push(`↑${formatTokens(totalInput)}`);
|
|
150
|
+
if (totalOutput)
|
|
151
|
+
statsParts.push(`↓${formatTokens(totalOutput)}`);
|
|
152
|
+
if (totalCacheRead)
|
|
153
|
+
statsParts.push(`R${formatTokens(totalCacheRead)}`);
|
|
154
|
+
if (totalCacheWrite)
|
|
155
|
+
statsParts.push(`W${formatTokens(totalCacheWrite)}`);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
if (totalInput)
|
|
159
|
+
statsParts.push(`↑${formatTokens(totalInput)}`);
|
|
160
|
+
if (totalOutput)
|
|
161
|
+
statsParts.push(`↓${formatTokens(totalOutput)}`);
|
|
162
|
+
if (totalCacheRead)
|
|
163
|
+
statsParts.push(`R${formatTokens(totalCacheRead)}`);
|
|
164
|
+
if (totalCacheWrite)
|
|
165
|
+
statsParts.push(`W${formatTokens(totalCacheWrite)}`);
|
|
166
|
+
const usingSubscription = state.model
|
|
167
|
+
? this.session.modelRegistry.isUsingOAuth(state.model)
|
|
168
|
+
: false;
|
|
169
|
+
if (totalCost || usingSubscription) {
|
|
170
|
+
const costStr = `$${totalCost.toFixed(3)}${usingSubscription ? ' (sub)' : ''}`;
|
|
171
|
+
statsParts.push(costStr);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Colorize context percentage based on usage AND query count.
|
|
175
|
+
// For Shortcut credit users: more aggressive thresholds (50%/75%) + query-based triggers.
|
|
176
|
+
// For non-credit users: original thresholds (70%/90%).
|
|
177
|
+
let contextPercentStr;
|
|
178
|
+
const contextPercentDisplay = contextPercent === '?' ? '? context' : `${contextPercent}% context`;
|
|
179
|
+
if (isShortcutCredits) {
|
|
180
|
+
// Context colored only by context usage %
|
|
181
|
+
if (contextPercentValue >= 75) {
|
|
182
|
+
contextPercentStr = theme.fg('error', contextPercentDisplay);
|
|
183
|
+
}
|
|
184
|
+
else if (contextPercentValue >= 50) {
|
|
185
|
+
contextPercentStr = theme.fg('warning', contextPercentDisplay);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
contextPercentStr = contextPercentDisplay;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// Non-credit users: original thresholds
|
|
193
|
+
const fullDisplay = `${contextPercentDisplay} (auto)`;
|
|
194
|
+
if (contextPercentValue > 90) {
|
|
195
|
+
contextPercentStr = theme.fg('error', fullDisplay);
|
|
196
|
+
}
|
|
197
|
+
else if (contextPercentValue > 70) {
|
|
198
|
+
contextPercentStr = theme.fg('warning', fullDisplay);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
contextPercentStr = fullDisplay;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
statsParts.push(contextPercentStr);
|
|
205
|
+
// Add query count for Shortcut credit users
|
|
206
|
+
if (isShortcutCredits) {
|
|
207
|
+
const queriesText = `${queryCount} queries`;
|
|
208
|
+
// Queries colored only by query count
|
|
209
|
+
let styledQueries;
|
|
210
|
+
if (queryCount > 15) {
|
|
211
|
+
styledQueries = theme.fg('error', queriesText);
|
|
212
|
+
}
|
|
213
|
+
else if (queryCount > 10) {
|
|
214
|
+
styledQueries = theme.fg('warning', queriesText);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
styledQueries = queriesText;
|
|
218
|
+
}
|
|
219
|
+
statsParts.push(styledQueries);
|
|
220
|
+
}
|
|
221
|
+
let statsLeft = statsParts.join(' ');
|
|
222
|
+
// Add model name on the right side, plus thinking level if model supports it
|
|
223
|
+
const modelName = state.model?.id || 'no-model';
|
|
224
|
+
let statsLeftWidth = visibleWidth(statsLeft);
|
|
225
|
+
// If statsLeft is too wide, truncate it
|
|
226
|
+
if (statsLeftWidth > width) {
|
|
227
|
+
// Truncate statsLeft to fit width (no room for right side)
|
|
228
|
+
const plainStatsLeft = statsLeft.replace(/\x1b\[[0-9;]*m/g, '');
|
|
229
|
+
statsLeft = `${plainStatsLeft.substring(0, width - 3)}...`;
|
|
230
|
+
statsLeftWidth = visibleWidth(statsLeft);
|
|
231
|
+
}
|
|
232
|
+
// Calculate available space for padding (minimum 2 spaces between stats and model)
|
|
233
|
+
const minPadding = 2;
|
|
234
|
+
// Add thinking level indicator if model supports reasoning
|
|
235
|
+
let rightSideWithoutProvider = modelName;
|
|
236
|
+
if (state.model?.reasoning) {
|
|
237
|
+
const thinkingLevel = state.thinkingLevel || 'off';
|
|
238
|
+
rightSideWithoutProvider = `${modelName} • thinking: ${thinkingLevel}`;
|
|
239
|
+
}
|
|
240
|
+
// Prepend the provider in parentheses if there are multiple providers and there's enough room
|
|
241
|
+
let rightSide = rightSideWithoutProvider;
|
|
242
|
+
if (this.footerData.getAvailableProviderCount() > 1 && state.model) {
|
|
243
|
+
rightSide = `(${state.model.provider}) ${rightSideWithoutProvider}`;
|
|
244
|
+
if (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {
|
|
245
|
+
// Too wide, fall back
|
|
246
|
+
rightSide = rightSideWithoutProvider;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const rightSideWidth = visibleWidth(rightSide);
|
|
250
|
+
const totalNeeded = statsLeftWidth + minPadding + rightSideWidth;
|
|
251
|
+
let statsLine;
|
|
252
|
+
if (totalNeeded <= width) {
|
|
253
|
+
// Both fit - add padding to right-align model
|
|
254
|
+
const padding = ' '.repeat(width - statsLeftWidth - rightSideWidth);
|
|
255
|
+
statsLine = statsLeft + padding + rightSide;
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
// Need to truncate right side
|
|
259
|
+
const availableForRight = width - statsLeftWidth - minPadding;
|
|
260
|
+
if (availableForRight > 3) {
|
|
261
|
+
// Truncate to fit (strip ANSI codes for length calculation, then truncate raw string)
|
|
262
|
+
const plainRightSide = rightSide.replace(/\x1b\[[0-9;]*m/g, '');
|
|
263
|
+
const truncatedPlain = plainRightSide.substring(0, availableForRight);
|
|
264
|
+
// For simplicity, just use plain truncated version (loses color, but fits)
|
|
265
|
+
const padding = ' '.repeat(width - statsLeftWidth - truncatedPlain.length);
|
|
266
|
+
statsLine = statsLeft + padding + truncatedPlain;
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
// Not enough space for right side at all
|
|
270
|
+
statsLine = statsLeft;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Apply dim to non-credit parts. For credit users, statsLeft already has its own
|
|
274
|
+
// styling (tier colors for credits, theme colors for context). Only dim the
|
|
275
|
+
// right side (model name + padding).
|
|
276
|
+
// For non-credit users, dim everything as before.
|
|
277
|
+
let styledStatsLeft;
|
|
278
|
+
let styledRemainder;
|
|
279
|
+
const remainder = statsLine.slice(statsLeft.length); // padding + rightSide
|
|
280
|
+
if (isShortcutCredits) {
|
|
281
|
+
// Credits line already has ANSI styling — pass through as-is
|
|
282
|
+
styledStatsLeft = statsLeft;
|
|
283
|
+
styledRemainder = theme.fg('dim', remainder);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
styledStatsLeft = theme.fg('dim', statsLeft);
|
|
287
|
+
styledRemainder = theme.fg('dim', remainder);
|
|
288
|
+
}
|
|
289
|
+
// Build lines: separator, optional info line, stats
|
|
290
|
+
const separator = theme.fg('dim', '─'.repeat(width));
|
|
291
|
+
const lines = [separator];
|
|
292
|
+
if (infoLine) {
|
|
293
|
+
lines.push(theme.fg('dim', infoLine));
|
|
294
|
+
}
|
|
295
|
+
lines.push(styledStatsLeft + styledRemainder);
|
|
296
|
+
// SHORTCUT PATCH: render each extension status on its own line (for dev trace paths)
|
|
297
|
+
const extensionStatuses = this.footerData.getExtensionStatuses();
|
|
298
|
+
if (extensionStatuses.size > 0) {
|
|
299
|
+
const sortedStatuses = Array.from(extensionStatuses.entries())
|
|
300
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
301
|
+
.map(([, text]) => sanitizeStatusText(text));
|
|
302
|
+
for (const status of sortedStatuses) {
|
|
303
|
+
lines.push(truncateToWidth(theme.fg('dim', status), width, theme.fg('dim', '...')));
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return lines;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=footer.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// UI Components for extensions
|
|
2
|
+
export { ArminComponent } from './armin.js';
|
|
3
|
+
export { AssistantMessageComponent } from './assistant-message.js';
|
|
4
|
+
export { BashExecutionComponent } from './bash-execution.js';
|
|
5
|
+
export { BorderedLoader } from './bordered-loader.js';
|
|
6
|
+
export { BranchSummaryMessageComponent } from './branch-summary-message.js';
|
|
7
|
+
export { CompactionSummaryMessageComponent } from './compaction-summary-message.js';
|
|
8
|
+
export { CustomEditor } from './custom-editor.js';
|
|
9
|
+
export { CustomMessageComponent } from './custom-message.js';
|
|
10
|
+
export { DaxnutsComponent } from './daxnuts.js';
|
|
11
|
+
export { renderDiff } from './diff.js';
|
|
12
|
+
export { DynamicBorder } from './dynamic-border.js';
|
|
13
|
+
export { ExtensionEditorComponent } from './extension-editor.js';
|
|
14
|
+
export { ExtensionInputComponent } from './extension-input.js';
|
|
15
|
+
export { ExtensionSelectorComponent } from './extension-selector.js';
|
|
16
|
+
export { FooterComponent } from './footer.js';
|
|
17
|
+
export { appKey, appKeyHint, editorKey, keyHint, rawKeyHint } from './keybinding-hints.js';
|
|
18
|
+
export { LoginDialogComponent } from './login-dialog.js';
|
|
19
|
+
export { ModelSelectorComponent } from './model-selector.js';
|
|
20
|
+
export { OAuthSelectorComponent } from './oauth-selector.js';
|
|
21
|
+
// SHORTCUT PATCH: removed ScopedModelsSelectorComponent export — scoped models removed
|
|
22
|
+
export { SessionSelectorComponent } from './session-selector.js';
|
|
23
|
+
export { SettingsSelectorComponent } from './settings-selector.js';
|
|
24
|
+
export { ShowImagesSelectorComponent } from './show-images-selector.js';
|
|
25
|
+
export { SkillInvocationMessageComponent } from './skill-invocation-message.js';
|
|
26
|
+
export { ThemeSelectorComponent } from './theme-selector.js';
|
|
27
|
+
export { ThinkingSelectorComponent } from './thinking-selector.js';
|
|
28
|
+
export { ToolExecutionComponent } from './tool-execution.js';
|
|
29
|
+
export { TreeSelectorComponent } from './tree-selector.js';
|
|
30
|
+
export { UserMessageSelectorComponent } from './user-message-selector.js';
|
|
31
|
+
export { UserMessageComponent } from './user-message.js';
|
|
32
|
+
export { truncateToVisualLines } from './visual-truncate.js';
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for formatting keybinding hints in the UI.
|
|
3
|
+
*/
|
|
4
|
+
import { getEditorKeybindings } from '../../../tui/index.js';
|
|
5
|
+
import { theme } from '../../../core/theme.js';
|
|
6
|
+
/**
|
|
7
|
+
* Format keys array as display string (e.g., ["ctrl+c", "escape"] -> "ctrl+c/escape").
|
|
8
|
+
*/
|
|
9
|
+
function formatKeys(keys) {
|
|
10
|
+
if (keys.length === 0)
|
|
11
|
+
return '';
|
|
12
|
+
if (keys.length === 1)
|
|
13
|
+
return keys[0];
|
|
14
|
+
return keys.join('/');
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get display string for an editor action.
|
|
18
|
+
*/
|
|
19
|
+
export function editorKey(action) {
|
|
20
|
+
return formatKeys(getEditorKeybindings().getKeys(action));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get display string for an app action.
|
|
24
|
+
*/
|
|
25
|
+
export function appKey(keybindings, action) {
|
|
26
|
+
return formatKeys(keybindings.getKeys(action));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Format a keybinding hint with consistent styling: dim key, muted description.
|
|
30
|
+
* Looks up the key from editor keybindings automatically.
|
|
31
|
+
*
|
|
32
|
+
* @param action - Editor action name (e.g., "selectConfirm", "expandTools")
|
|
33
|
+
* @param description - Description text (e.g., "to expand", "cancel")
|
|
34
|
+
* @returns Formatted string with dim key and muted description
|
|
35
|
+
*/
|
|
36
|
+
export function keyHint(action, description) {
|
|
37
|
+
return theme.fg('dim', editorKey(action)) + theme.fg('muted', ` ${description}`);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Format a keybinding hint for app-level actions.
|
|
41
|
+
* Requires the KeybindingsManager instance.
|
|
42
|
+
*
|
|
43
|
+
* @param keybindings - KeybindingsManager instance
|
|
44
|
+
* @param action - App action name (e.g., "interrupt", "externalEditor")
|
|
45
|
+
* @param description - Description text
|
|
46
|
+
* @returns Formatted string with dim key and muted description
|
|
47
|
+
*/
|
|
48
|
+
export function appKeyHint(keybindings, action, description) {
|
|
49
|
+
return theme.fg('dim', appKey(keybindings, action)) + theme.fg('muted', ` ${description}`);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Format a raw key string with description (for non-configurable keys like ↑↓).
|
|
53
|
+
*
|
|
54
|
+
* @param key - Raw key string
|
|
55
|
+
* @param description - Description text
|
|
56
|
+
* @returns Formatted string with dim key and muted description
|
|
57
|
+
*/
|
|
58
|
+
export function rawKeyHint(key, description) {
|
|
59
|
+
return theme.fg('dim', key) + theme.fg('muted', ` ${description}`);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=keybinding-hints.js.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Container } from '../../../tui/index.js';
|
|
2
|
+
import { theme } from '../../../core/theme.js';
|
|
3
|
+
/** Standard horizontal padding for content that uses its own background (e.g. custom messages). */
|
|
4
|
+
export const CONTENT_PAD_X = 1;
|
|
5
|
+
/** Standard vertical padding (0 = no extra blank lines above/below). */
|
|
6
|
+
export const CONTENT_PAD_Y = 0;
|
|
7
|
+
/** Visible character width of the message prefix (symbol + trailing space). */
|
|
8
|
+
export const PREFIX_WIDTH = 2;
|
|
9
|
+
// ── Prefix generators ────────────────────────────────────────────────
|
|
10
|
+
export function userPrefix() {
|
|
11
|
+
return `${theme.fg('accent', '❯')} `;
|
|
12
|
+
}
|
|
13
|
+
export function assistantPrefix() {
|
|
14
|
+
return `${theme.fg('text', '●')} `;
|
|
15
|
+
}
|
|
16
|
+
export function toolPrefix(isPending, isError, blinkOn) {
|
|
17
|
+
if (isPending) {
|
|
18
|
+
return blinkOn ? `${theme.fg('warning', '●')} ` : `${theme.fg('dim', '●')} `;
|
|
19
|
+
}
|
|
20
|
+
return isError ? `${theme.fg('error', '●')} ` : `${theme.fg('success', '●')} `;
|
|
21
|
+
}
|
|
22
|
+
// ── Layout utilities ─────────────────────────────────────────────────
|
|
23
|
+
/**
|
|
24
|
+
* Prefix the first visible line of rendered output with a symbol,
|
|
25
|
+
* and indent all subsequent lines to maintain alignment.
|
|
26
|
+
*
|
|
27
|
+
* Lines before the first visible content (e.g. spacer blanks) are left untouched.
|
|
28
|
+
*/
|
|
29
|
+
export function prefixLines(lines, prefix) {
|
|
30
|
+
const indent = ' '.repeat(PREFIX_WIDTH);
|
|
31
|
+
let firstDone = false;
|
|
32
|
+
for (let i = 0; i < lines.length; i++) {
|
|
33
|
+
if (!firstDone) {
|
|
34
|
+
if (lines[i].trim()) {
|
|
35
|
+
lines[i] = prefix + lines[i];
|
|
36
|
+
firstDone = true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
lines[i] = indent + lines[i];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return lines;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A Container that prefixes children's rendered output with a symbol.
|
|
47
|
+
*
|
|
48
|
+
* Use when only *part* of a component's output should be prefixed
|
|
49
|
+
* (e.g. UserMessage wraps the text portion but not the annotation above it).
|
|
50
|
+
*/
|
|
51
|
+
export class PrefixedContainer extends Container {
|
|
52
|
+
prefix;
|
|
53
|
+
constructor(prefix) {
|
|
54
|
+
super();
|
|
55
|
+
this.prefix = prefix;
|
|
56
|
+
}
|
|
57
|
+
setPrefix(prefix) {
|
|
58
|
+
this.prefix = prefix;
|
|
59
|
+
}
|
|
60
|
+
render(width) {
|
|
61
|
+
return prefixLines(super.render(width - PREFIX_WIDTH), this.prefix);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { getOAuthProviders } from '@mariozechner/pi-ai';
|
|
2
|
+
import { Container, getEditorKeybindings, Input, Spacer, Text } from '../../../tui/index.js';
|
|
3
|
+
import { exec } from 'child_process';
|
|
4
|
+
import { theme } from '../../../core/theme.js';
|
|
5
|
+
import { DynamicBorder } from './dynamic-border.js';
|
|
6
|
+
import { keyHint } from './keybinding-hints.js';
|
|
7
|
+
/**
|
|
8
|
+
* Login dialog component - replaces editor during OAuth login flow
|
|
9
|
+
*/
|
|
10
|
+
export class LoginDialogComponent extends Container {
|
|
11
|
+
onComplete;
|
|
12
|
+
contentContainer;
|
|
13
|
+
input;
|
|
14
|
+
tui;
|
|
15
|
+
abortController = new AbortController();
|
|
16
|
+
inputResolver;
|
|
17
|
+
inputRejecter;
|
|
18
|
+
// Focusable implementation - propagate to input for IME cursor positioning
|
|
19
|
+
_focused = false;
|
|
20
|
+
get focused() {
|
|
21
|
+
return this._focused;
|
|
22
|
+
}
|
|
23
|
+
set focused(value) {
|
|
24
|
+
this._focused = value;
|
|
25
|
+
this.input.focused = value;
|
|
26
|
+
}
|
|
27
|
+
constructor(tui, providerId, onComplete) {
|
|
28
|
+
super();
|
|
29
|
+
this.onComplete = onComplete;
|
|
30
|
+
this.tui = tui;
|
|
31
|
+
const providerInfo = getOAuthProviders().find((p) => p.id === providerId);
|
|
32
|
+
const providerName = providerInfo?.name || providerId;
|
|
33
|
+
// Top border
|
|
34
|
+
this.addChild(new DynamicBorder());
|
|
35
|
+
// Title
|
|
36
|
+
this.addChild(new Text(theme.fg('warning', `Login to ${providerName}`), 1, 0));
|
|
37
|
+
// Dynamic content area
|
|
38
|
+
this.contentContainer = new Container();
|
|
39
|
+
this.addChild(this.contentContainer);
|
|
40
|
+
// Input (always present, used when needed)
|
|
41
|
+
this.input = new Input();
|
|
42
|
+
this.input.onSubmit = () => {
|
|
43
|
+
if (this.inputResolver) {
|
|
44
|
+
this.inputResolver(this.input.getValue());
|
|
45
|
+
this.inputResolver = undefined;
|
|
46
|
+
this.inputRejecter = undefined;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
this.input.onEscape = () => {
|
|
50
|
+
this.cancel();
|
|
51
|
+
};
|
|
52
|
+
// Bottom border
|
|
53
|
+
this.addChild(new DynamicBorder());
|
|
54
|
+
}
|
|
55
|
+
get signal() {
|
|
56
|
+
return this.abortController.signal;
|
|
57
|
+
}
|
|
58
|
+
cancel() {
|
|
59
|
+
this.abortController.abort();
|
|
60
|
+
if (this.inputRejecter) {
|
|
61
|
+
this.inputRejecter(new Error('Login cancelled'));
|
|
62
|
+
this.inputResolver = undefined;
|
|
63
|
+
this.inputRejecter = undefined;
|
|
64
|
+
}
|
|
65
|
+
this.onComplete(false, 'Login cancelled');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Called by onAuth callback - show URL and optional instructions
|
|
69
|
+
*/
|
|
70
|
+
showAuth(url, instructions) {
|
|
71
|
+
this.contentContainer.clear();
|
|
72
|
+
this.contentContainer.addChild(new Spacer(1));
|
|
73
|
+
this.contentContainer.addChild(new Text(theme.fg('accent', url), 1, 0));
|
|
74
|
+
const clickHint = process.platform === 'darwin' ? 'Cmd+click to open' : 'Ctrl+click to open';
|
|
75
|
+
const hyperlink = `\x1b]8;;${url}\x07${clickHint}\x1b]8;;\x07`;
|
|
76
|
+
this.contentContainer.addChild(new Text(theme.fg('dim', hyperlink), 1, 0));
|
|
77
|
+
if (instructions) {
|
|
78
|
+
this.contentContainer.addChild(new Spacer(1));
|
|
79
|
+
this.contentContainer.addChild(new Text(theme.fg('warning', instructions), 1, 0));
|
|
80
|
+
}
|
|
81
|
+
// Try to open browser
|
|
82
|
+
// On Windows, 'start' needs an empty title ("") before the URL, otherwise
|
|
83
|
+
// it interprets the URL as a window title and opens a blank cmd window.
|
|
84
|
+
const openCmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
85
|
+
const cmd = process.platform === 'win32' ? `${openCmd} "" "${url}"` : `${openCmd} "${url}"`;
|
|
86
|
+
exec(cmd);
|
|
87
|
+
this.tui.requestRender();
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Show input for manual code/URL entry (for callback server providers)
|
|
91
|
+
*/
|
|
92
|
+
showManualInput(prompt) {
|
|
93
|
+
this.contentContainer.addChild(new Spacer(1));
|
|
94
|
+
this.contentContainer.addChild(new Text(theme.fg('dim', prompt), 1, 0));
|
|
95
|
+
this.contentContainer.addChild(this.input);
|
|
96
|
+
this.contentContainer.addChild(new Text(`(${keyHint('selectCancel', 'to cancel')})`, 1, 0));
|
|
97
|
+
this.tui.requestRender();
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
this.inputResolver = resolve;
|
|
100
|
+
this.inputRejecter = reject;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Called by onPrompt callback - show prompt and wait for input
|
|
105
|
+
* Note: Does NOT clear content, appends to existing (preserves URL from showAuth)
|
|
106
|
+
*/
|
|
107
|
+
showPrompt(message, placeholder) {
|
|
108
|
+
this.contentContainer.addChild(new Spacer(1));
|
|
109
|
+
this.contentContainer.addChild(new Text(theme.fg('text', message), 1, 0));
|
|
110
|
+
if (placeholder) {
|
|
111
|
+
this.contentContainer.addChild(new Text(theme.fg('dim', `e.g., ${placeholder}`), 1, 0));
|
|
112
|
+
}
|
|
113
|
+
this.contentContainer.addChild(this.input);
|
|
114
|
+
this.contentContainer.addChild(new Text(`(${keyHint('selectCancel', 'to cancel,')} ${keyHint('selectConfirm', 'to submit')})`, 1, 0));
|
|
115
|
+
this.input.setValue('');
|
|
116
|
+
this.tui.requestRender();
|
|
117
|
+
return new Promise((resolve, reject) => {
|
|
118
|
+
this.inputResolver = resolve;
|
|
119
|
+
this.inputRejecter = reject;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Show waiting message (for polling flows like GitHub Copilot)
|
|
124
|
+
*/
|
|
125
|
+
showWaiting(message) {
|
|
126
|
+
this.contentContainer.addChild(new Spacer(1));
|
|
127
|
+
this.contentContainer.addChild(new Text(theme.fg('dim', message), 1, 0));
|
|
128
|
+
this.contentContainer.addChild(new Text(`(${keyHint('selectCancel', 'to cancel')})`, 1, 0));
|
|
129
|
+
this.tui.requestRender();
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Called by onProgress callback
|
|
133
|
+
*/
|
|
134
|
+
showProgress(message) {
|
|
135
|
+
this.contentContainer.addChild(new Text(theme.fg('dim', message), 1, 0));
|
|
136
|
+
this.tui.requestRender();
|
|
137
|
+
}
|
|
138
|
+
handleInput(data) {
|
|
139
|
+
const kb = getEditorKeybindings();
|
|
140
|
+
if (kb.matches(data, 'selectCancel')) {
|
|
141
|
+
this.cancel();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
// Pass to input
|
|
145
|
+
this.input.handleInput(data);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=login-dialog.js.map
|