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,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensure Excel is running with the ShortcutXL add-in loaded.
|
|
3
|
+
*
|
|
4
|
+
* 1. Ping the XLL HTTP server.
|
|
5
|
+
* 2. If unreachable, launch Excel via COM (no splash screen) and register the XLL.
|
|
6
|
+
* 3. Wait for the HTTP server to become available.
|
|
7
|
+
*/
|
|
8
|
+
import { execSync } from 'child_process';
|
|
9
|
+
import { existsSync } from 'fs';
|
|
10
|
+
import { getXllPath } from '../config.js';
|
|
11
|
+
import { EXCEL_HTTP_URL } from './constants.js';
|
|
12
|
+
function resolveXllPath() {
|
|
13
|
+
const candidate = getXllPath();
|
|
14
|
+
return existsSync(candidate) ? candidate : null;
|
|
15
|
+
}
|
|
16
|
+
async function isXllReachable(url) {
|
|
17
|
+
try {
|
|
18
|
+
const res = await fetch(`${url}/ping`, { signal: AbortSignal.timeout(2000) });
|
|
19
|
+
return res.ok;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function launchExcelWithXll(xllPath) {
|
|
26
|
+
const script = [
|
|
27
|
+
'$xl = New-Object -ComObject Excel.Application',
|
|
28
|
+
'$xl.Visible = $true',
|
|
29
|
+
'$xl.Workbooks.Add() | Out-Null',
|
|
30
|
+
`$xl.RegisterXLL('${xllPath.replace(/'/g, "''")}') | Out-Null`
|
|
31
|
+
].join('; ');
|
|
32
|
+
// Base64-encode the script to avoid all shell quoting issues.
|
|
33
|
+
const encoded = Buffer.from(script, 'utf16le').toString('base64');
|
|
34
|
+
execSync(`powershell -NoProfile -EncodedCommand ${encoded}`, {
|
|
35
|
+
stdio: 'ignore',
|
|
36
|
+
timeout: 30_000
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Ensure Excel + XLL are running. Returns true if the HTTP server is reachable
|
|
41
|
+
* after this call, false if we couldn't start Excel.
|
|
42
|
+
*/
|
|
43
|
+
export async function ensureExcel() {
|
|
44
|
+
if (await isXllReachable(EXCEL_HTTP_URL))
|
|
45
|
+
return true;
|
|
46
|
+
const xllPath = resolveXllPath();
|
|
47
|
+
if (!xllPath)
|
|
48
|
+
return false;
|
|
49
|
+
try {
|
|
50
|
+
launchExcelWithXll(xllPath);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
// Wait for the HTTP server to come up (XLL init takes a moment)
|
|
56
|
+
for (let i = 0; i < 15; i++) {
|
|
57
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
58
|
+
if (await isXllReachable(EXCEL_HTTP_URL))
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=ensure-excel.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discover ShortcutXL paths by calling GET /config on the XLL's HTTP server.
|
|
3
|
+
*
|
|
4
|
+
* Returns { xll_dir, modules_path } or null if Excel isn't running.
|
|
5
|
+
* Retries a few times on startup since Excel may still be loading the XLL.
|
|
6
|
+
*/
|
|
7
|
+
import { EXCEL_HTTP_URL } from './constants.js';
|
|
8
|
+
/**
|
|
9
|
+
* Fetch XLL config from the running Excel instance.
|
|
10
|
+
* Retries up to `maxRetries` times with `intervalMs` between attempts.
|
|
11
|
+
* Returns null if Excel/XLL is unreachable after all retries.
|
|
12
|
+
*/
|
|
13
|
+
export async function fetchExcelConfig(options) {
|
|
14
|
+
const maxRetries = options?.maxRetries ?? 5;
|
|
15
|
+
const intervalMs = options?.intervalMs ?? 2000;
|
|
16
|
+
const baseUrl = options?.url ?? EXCEL_HTTP_URL;
|
|
17
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
18
|
+
try {
|
|
19
|
+
const response = await fetch(`${baseUrl}/config`);
|
|
20
|
+
if (!response.ok)
|
|
21
|
+
continue;
|
|
22
|
+
const data = (await response.json());
|
|
23
|
+
if (data.xll_dir && data.modules_path) {
|
|
24
|
+
return { xllDir: data.xll_dir, modulesPath: data.modules_path };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Connection refused — Excel not running or XLL not loaded yet
|
|
29
|
+
}
|
|
30
|
+
if (attempt < maxRetries) {
|
|
31
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=excel-config.js.map
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic pre-flight setup for ShortcutXL.
|
|
3
|
+
*
|
|
4
|
+
* Runs before the TUI starts on first install (!isInstalled()).
|
|
5
|
+
* Best-effort: installs what it can, the installation agent handles the rest.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { spawn as cpSpawn, spawnSync } from 'child_process';
|
|
9
|
+
import { existsSync } from 'fs';
|
|
10
|
+
import { resolve } from 'path';
|
|
11
|
+
import { createInterface } from 'readline';
|
|
12
|
+
import { getXllPath } from '../config.js';
|
|
13
|
+
import { resetShellConfig } from '../utils/shell.js';
|
|
14
|
+
import { EXCEL_HTTP_URL } from './constants.js';
|
|
15
|
+
import { fetchExcelConfig } from './excel-config.js';
|
|
16
|
+
import { getStableXllDir } from './sync-xll.js';
|
|
17
|
+
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
18
|
+
function log(msg) {
|
|
19
|
+
console.log(chalk.cyan(' → ') + msg);
|
|
20
|
+
}
|
|
21
|
+
function ok(msg) {
|
|
22
|
+
console.log(chalk.green(' ✓ ') + msg);
|
|
23
|
+
}
|
|
24
|
+
function warn(msg) {
|
|
25
|
+
console.log(chalk.yellow(' ⚠ ') + msg);
|
|
26
|
+
}
|
|
27
|
+
function header(step) {
|
|
28
|
+
console.log();
|
|
29
|
+
console.log(chalk.bold.white(` ${step}`));
|
|
30
|
+
console.log(chalk.dim(' ' + '─'.repeat(40)));
|
|
31
|
+
}
|
|
32
|
+
/** Prompt user for yes/no confirmation. */
|
|
33
|
+
function promptConfirm(message) {
|
|
34
|
+
return new Promise((res) => {
|
|
35
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
36
|
+
rl.question(`${chalk.yellow(' ⚠')} ${message} [y/N] `, (answer) => {
|
|
37
|
+
rl.close();
|
|
38
|
+
res(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/** Run a command synchronously and return { ok, stdout, stderr }. */
|
|
43
|
+
function run(cmd, options) {
|
|
44
|
+
try {
|
|
45
|
+
const result = spawnSync(cmd, {
|
|
46
|
+
encoding: 'utf-8',
|
|
47
|
+
timeout: options?.timeout ?? 30_000,
|
|
48
|
+
shell: true,
|
|
49
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
ok: result.status === 0,
|
|
53
|
+
stdout: (result.stdout ?? '').trim(),
|
|
54
|
+
stderr: (result.stderr ?? '').trim()
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return { ok: false, stdout: '', stderr: 'command failed' };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// ── Progress spinner ────────────────────────────────────────────────────
|
|
62
|
+
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
63
|
+
/**
|
|
64
|
+
* Run a command asynchronously with a live spinner that shows streaming output.
|
|
65
|
+
* Used for long-running installs (winget, pip) so the user sees progress.
|
|
66
|
+
*/
|
|
67
|
+
function runWithProgress(cmd, options) {
|
|
68
|
+
const label = options?.label ?? 'Working';
|
|
69
|
+
const timeout = options?.timeout ?? 120_000;
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
const child = cpSpawn(cmd, { shell: true, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
72
|
+
let stdout = '';
|
|
73
|
+
let stderr = '';
|
|
74
|
+
let lastLine = '';
|
|
75
|
+
let frame = 0;
|
|
76
|
+
let done = false;
|
|
77
|
+
const spinner = setInterval(() => {
|
|
78
|
+
if (done)
|
|
79
|
+
return;
|
|
80
|
+
const icon = chalk.cyan(SPINNER_FRAMES[frame % SPINNER_FRAMES.length]);
|
|
81
|
+
const status = lastLine
|
|
82
|
+
? chalk.dim(lastLine.length > 60 ? lastLine.slice(0, 57) + '...' : lastLine)
|
|
83
|
+
: '';
|
|
84
|
+
process.stderr.write(`\r ${icon} ${label} ${status}\x1b[K`);
|
|
85
|
+
frame++;
|
|
86
|
+
}, 80);
|
|
87
|
+
const timer = setTimeout(() => {
|
|
88
|
+
child.kill();
|
|
89
|
+
finish(false);
|
|
90
|
+
}, timeout);
|
|
91
|
+
function onData(stream, chunk) {
|
|
92
|
+
const text = chunk.toString('utf-8');
|
|
93
|
+
if (stream === 'stdout')
|
|
94
|
+
stdout += text;
|
|
95
|
+
else
|
|
96
|
+
stderr += text;
|
|
97
|
+
// Extract last non-empty line for status display
|
|
98
|
+
const lines = text.split(/\r?\n/).filter((l) => l.trim());
|
|
99
|
+
if (lines.length > 0) {
|
|
100
|
+
lastLine = lines[lines.length - 1].trim();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
child.stdout?.on('data', (chunk) => onData('stdout', chunk));
|
|
104
|
+
child.stderr?.on('data', (chunk) => onData('stderr', chunk));
|
|
105
|
+
function finish(success) {
|
|
106
|
+
if (done)
|
|
107
|
+
return;
|
|
108
|
+
done = true;
|
|
109
|
+
clearInterval(spinner);
|
|
110
|
+
clearTimeout(timer);
|
|
111
|
+
// Clear spinner line
|
|
112
|
+
process.stderr.write('\r\x1b[K');
|
|
113
|
+
resolve({ ok: success, stdout: stdout.trim(), stderr: stderr.trim() });
|
|
114
|
+
}
|
|
115
|
+
child.on('close', (code) => finish(code === 0));
|
|
116
|
+
child.on('error', () => finish(false));
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
// ── Step implementations ─────────────────────────────────────────────────
|
|
120
|
+
async function ensureGitBash() {
|
|
121
|
+
header('Git');
|
|
122
|
+
const bashCheck = run('bash --version');
|
|
123
|
+
if (bashCheck.ok) {
|
|
124
|
+
ok('Installed.');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
warn('Git Bash not found.');
|
|
128
|
+
const confirmed = await promptConfirm('Install Git Bash for Windows? ShortcutXL needs this to work on your machine.');
|
|
129
|
+
if (!confirmed) {
|
|
130
|
+
warn('Skipped — the setup agent will help.');
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
// Ensure winget is available
|
|
134
|
+
const wingetCheck = run('winget --version');
|
|
135
|
+
if (!wingetCheck.ok) {
|
|
136
|
+
log('Installing package manager...');
|
|
137
|
+
run('powershell -Command "Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe"', { timeout: 60_000 });
|
|
138
|
+
const retry = run('winget --version');
|
|
139
|
+
if (!retry.ok) {
|
|
140
|
+
warn('Auto-install failed — the setup agent will help.');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
log('Installing Git (you may see a permissions prompt — click Yes)...');
|
|
145
|
+
const result = await runWithProgress('winget install --id Git.Git -e -h --accept-source-agreements --accept-package-agreements', { timeout: 120_000, label: 'Installing Git' });
|
|
146
|
+
if (!result.ok && !result.stdout.includes('already installed')) {
|
|
147
|
+
warn('Install failed — the setup agent will help.');
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Reset shell cache so it re-detects bash
|
|
151
|
+
resetShellConfig();
|
|
152
|
+
const gitCheck = run('git --version');
|
|
153
|
+
if (!gitCheck.ok) {
|
|
154
|
+
warn('Installed but not detected yet — try restarting your terminal.');
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
ok(`Installed.`);
|
|
158
|
+
}
|
|
159
|
+
async function ensurePython() {
|
|
160
|
+
header('Python');
|
|
161
|
+
let pythonCmd = null;
|
|
162
|
+
// Check for Python 3.12 specifically
|
|
163
|
+
const pyCheck = run('python --version');
|
|
164
|
+
if (pyCheck.ok && pyCheck.stdout.includes('3.12')) {
|
|
165
|
+
ok(`${pyCheck.stdout}`);
|
|
166
|
+
pythonCmd = 'python';
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// Also check py launcher
|
|
170
|
+
const pyLauncher = run('py -3.12 --version');
|
|
171
|
+
if (pyLauncher.ok) {
|
|
172
|
+
ok(`${pyLauncher.stdout}`);
|
|
173
|
+
pythonCmd = 'py -3.12';
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (!pythonCmd) {
|
|
177
|
+
const confirmed = await promptConfirm('Install Python and register ShortcutXL with Excel? This is needed for it to control Excel.');
|
|
178
|
+
if (!confirmed) {
|
|
179
|
+
warn('Skipped — the setup agent will help.');
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
log('Installing Python 3.12...');
|
|
183
|
+
const result = await runWithProgress('winget install --id Python.Python.3.12 -e -h --accept-source-agreements --accept-package-agreements', { timeout: 120_000, label: 'Installing Python 3.12' });
|
|
184
|
+
if (!result.ok && !result.stdout.includes('already installed')) {
|
|
185
|
+
warn('Install failed — the setup agent will help.');
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
// Verify
|
|
189
|
+
const verify = run('python --version');
|
|
190
|
+
if (verify.ok && verify.stdout.includes('3.12')) {
|
|
191
|
+
ok(`${verify.stdout}`);
|
|
192
|
+
pythonCmd = 'python';
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
const verifyPy = run('py -3.12 --version');
|
|
196
|
+
if (verifyPy.ok) {
|
|
197
|
+
ok(`${verifyPy.stdout}`);
|
|
198
|
+
pythonCmd = 'py -3.12';
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
warn('Installed but not detected yet — try restarting your terminal.');
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// Install pywin32 + openpyxl
|
|
207
|
+
log('Installing required packages...');
|
|
208
|
+
const pipResult = await runWithProgress(`${pythonCmd} -m pip install pywin32 openpyxl`, {
|
|
209
|
+
timeout: 120_000,
|
|
210
|
+
label: 'Installing packages'
|
|
211
|
+
});
|
|
212
|
+
if (pipResult.ok) {
|
|
213
|
+
ok('Packages installed.');
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
warn('Package install had issues — the setup agent will help.');
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/** Run a PowerShell script via base64-encoded command. */
|
|
220
|
+
function runPS(script, options) {
|
|
221
|
+
const encoded = Buffer.from(script, 'utf16le').toString('base64');
|
|
222
|
+
return run(`powershell -NoProfile -EncodedCommand ${encoded}`, options);
|
|
223
|
+
}
|
|
224
|
+
function ensureXllRegistry() {
|
|
225
|
+
header('Excel Add-in');
|
|
226
|
+
const xllPath = resolve(getXllPath()).replace(/\//g, '\\');
|
|
227
|
+
if (!existsSync(xllPath)) {
|
|
228
|
+
warn(`Add-in file not found — the setup agent will help.`);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
// Find Office version and write the OPEN key so Excel loads the XLL on startup.
|
|
232
|
+
// Creates the Options key if it doesn't exist yet (fresh Office installs).
|
|
233
|
+
const result = runPS(`
|
|
234
|
+
$ErrorActionPreference = 'Stop'
|
|
235
|
+
$xllValue = '/R "${xllPath}"'
|
|
236
|
+
$versions = @('16.0', '15.0', '14.0')
|
|
237
|
+
$officeVer = $null
|
|
238
|
+
|
|
239
|
+
foreach ($ver in $versions) {
|
|
240
|
+
$excelKey = "HKCU:\\Software\\Microsoft\\Office\\$ver\\Excel"
|
|
241
|
+
if (Test-Path $excelKey) { $officeVer = $ver; break }
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (-not $officeVer) {
|
|
245
|
+
Write-Output "NO_OFFICE"
|
|
246
|
+
exit 0
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
$optionsKey = "HKCU:\\Software\\Microsoft\\Office\\$officeVer\\Excel\\Options"
|
|
250
|
+
|
|
251
|
+
if (-not (Test-Path $optionsKey)) {
|
|
252
|
+
New-Item -Path $optionsKey -Force | Out-Null
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
# Check if already registered
|
|
256
|
+
$props = Get-ItemProperty -Path $optionsKey -ErrorAction SilentlyContinue
|
|
257
|
+
if ($props) {
|
|
258
|
+
foreach ($p in $props.PSObject.Properties) {
|
|
259
|
+
if ($p.Name -match '^OPEN' -and $p.Value -match 'ShortcutXL') {
|
|
260
|
+
Write-Output ('ALREADY:' + $officeVer)
|
|
261
|
+
exit 0
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
# Find next available OPEN slot
|
|
267
|
+
$openKeys = @()
|
|
268
|
+
if ($props) {
|
|
269
|
+
$openKeys = @($props.PSObject.Properties | Where-Object { $_.Name -match '^OPEN' } | ForEach-Object { $_.Name })
|
|
270
|
+
}
|
|
271
|
+
if ($openKeys.Count -eq 0) {
|
|
272
|
+
$slot = 'OPEN'
|
|
273
|
+
} else {
|
|
274
|
+
$nums = @($openKeys | ForEach-Object { if ($_ -eq 'OPEN') { 0 } else { [int]($_ -replace 'OPEN','') } })
|
|
275
|
+
$next = ($nums | Measure-Object -Maximum).Maximum + 1
|
|
276
|
+
$slot = "OPEN$next"
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
New-ItemProperty -Path $optionsKey -Name $slot -Value $xllValue -PropertyType String -Force | Out-Null
|
|
280
|
+
Write-Output ('REGISTERED:' + $officeVer + ':' + $slot)
|
|
281
|
+
`);
|
|
282
|
+
if (result.stdout.includes('ALREADY:')) {
|
|
283
|
+
ok('Already registered.');
|
|
284
|
+
}
|
|
285
|
+
else if (result.stdout.includes('REGISTERED:')) {
|
|
286
|
+
ok(`Registered with Excel.`);
|
|
287
|
+
}
|
|
288
|
+
else if (result.stdout.includes('NO_OFFICE')) {
|
|
289
|
+
warn('Excel not found — the setup agent will help.');
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
warn(`Registration failed — the setup agent will help.`);
|
|
293
|
+
if (result.stderr)
|
|
294
|
+
log(chalk.dim(result.stderr));
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
async function ensureExcelAndXll() {
|
|
298
|
+
header('Launch Excel');
|
|
299
|
+
// Check if XLL is already reachable
|
|
300
|
+
try {
|
|
301
|
+
const res = await fetch(`${EXCEL_HTTP_URL}/ping`, { signal: AbortSignal.timeout(2000) });
|
|
302
|
+
if (res.ok) {
|
|
303
|
+
ok('Excel is running with ShortcutXL.');
|
|
304
|
+
await verifyXllConfig();
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
// Not running
|
|
310
|
+
}
|
|
311
|
+
// Check if Excel is running without XLL
|
|
312
|
+
const tasklist = run('tasklist /FI "IMAGENAME eq EXCEL.EXE" /NH');
|
|
313
|
+
const excelRunning = tasklist.ok && tasklist.stdout.includes('EXCEL.EXE');
|
|
314
|
+
if (excelRunning) {
|
|
315
|
+
warn('Excel is running but ShortcutXL is not loaded.');
|
|
316
|
+
const confirmed = await promptConfirm('Close all Excel instances to reload with ShortcutXL? Unsaved work will be lost.');
|
|
317
|
+
if (!confirmed) {
|
|
318
|
+
warn('Skipped — close Excel manually and re-run setup.');
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
log('Closing Excel...');
|
|
322
|
+
run('taskkill /F /IM EXCEL.EXE', { timeout: 10_000 });
|
|
323
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
324
|
+
}
|
|
325
|
+
log('Opening Excel...');
|
|
326
|
+
run('start excel', { timeout: 10_000 });
|
|
327
|
+
log('Waiting for ShortcutXL to start...');
|
|
328
|
+
for (let i = 0; i < 10; i++) {
|
|
329
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
330
|
+
try {
|
|
331
|
+
const res = await fetch(`${EXCEL_HTTP_URL}/ping`, { signal: AbortSignal.timeout(2000) });
|
|
332
|
+
if (res.ok) {
|
|
333
|
+
ok('ShortcutXL is ready.');
|
|
334
|
+
await verifyXllConfig();
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
// Keep waiting
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
warn('ShortcutXL did not start — the setup agent will help.');
|
|
343
|
+
}
|
|
344
|
+
async function verifyXllConfig() {
|
|
345
|
+
const expectedModulesDir = resolve(getStableXllDir(), 'modules');
|
|
346
|
+
const config = await fetchExcelConfig({ maxRetries: 2, intervalMs: 1000 });
|
|
347
|
+
if (!config) {
|
|
348
|
+
warn('Could not verify add-in config.');
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
const actualModules = resolve(config.modulesPath);
|
|
352
|
+
if (actualModules !== expectedModulesDir) {
|
|
353
|
+
warn(`Add-in config mismatch — the setup agent will help.`);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
ok('Add-in config verified.');
|
|
357
|
+
}
|
|
358
|
+
async function smokeTest() {
|
|
359
|
+
header('Connection Test');
|
|
360
|
+
log('Verifying Excel connection...');
|
|
361
|
+
try {
|
|
362
|
+
const res = await fetch(`${EXCEL_HTTP_URL}/exec`, {
|
|
363
|
+
method: 'POST',
|
|
364
|
+
headers: { 'Content-Type': 'application/json' },
|
|
365
|
+
body: JSON.stringify({
|
|
366
|
+
code: 'from shortcut_xl import xl_app\nprint(f"Excel {xl_app().Version}")'
|
|
367
|
+
}),
|
|
368
|
+
signal: AbortSignal.timeout(10_000)
|
|
369
|
+
});
|
|
370
|
+
if (!res.ok) {
|
|
371
|
+
warn(`Connection error (${res.status}).`);
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
const data = (await res.json());
|
|
375
|
+
if (data.error) {
|
|
376
|
+
warn(`Connection failed: ${data.error}`);
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
ok(`${data.output?.trim()}`);
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
catch (e) {
|
|
383
|
+
warn(`Connection failed: ${e instanceof Error ? e.message : e}`);
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
// ── Main entry point ─────────────────────────────────────────────────────
|
|
388
|
+
/**
|
|
389
|
+
* Run deterministic pre-flight checks and auto-install prerequisites.
|
|
390
|
+
* Best-effort — installs what it can, the installation agent handles the rest.
|
|
391
|
+
*
|
|
392
|
+
* Returns true if the smoke test passed (setup fully complete).
|
|
393
|
+
*/
|
|
394
|
+
export async function runPreflight() {
|
|
395
|
+
console.log();
|
|
396
|
+
console.log(chalk.bold.white(' Setting up ShortcutXL...'));
|
|
397
|
+
console.log(chalk.dim(' ' + '─'.repeat(40)));
|
|
398
|
+
// Git Bash (only needed on Windows when no bash is found)
|
|
399
|
+
if (process.platform === 'win32') {
|
|
400
|
+
await ensureGitBash();
|
|
401
|
+
}
|
|
402
|
+
// Python 3.12 + pip packages
|
|
403
|
+
await ensurePython();
|
|
404
|
+
// Registry key for XLL
|
|
405
|
+
ensureXllRegistry();
|
|
406
|
+
// Excel + XLL running
|
|
407
|
+
await ensureExcelAndXll();
|
|
408
|
+
// Smoke test — if this passes, everything works
|
|
409
|
+
const passed = await smokeTest();
|
|
410
|
+
if (passed) {
|
|
411
|
+
console.log();
|
|
412
|
+
ok('Preflight passed! The installation agent will verify everything.');
|
|
413
|
+
console.log();
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
console.log();
|
|
417
|
+
warn('Some steps need attention — the setup agent will help.');
|
|
418
|
+
console.log();
|
|
419
|
+
}
|
|
420
|
+
return passed;
|
|
421
|
+
}
|
|
422
|
+
//# sourceMappingURL=preflight.js.map
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action-mode system prompt for the Shortcut agent.
|
|
3
|
+
*
|
|
4
|
+
* This is the normal post-installation prompt. Passed as `customPrompt` to
|
|
5
|
+
* the core buildSystemPrompt(), which automatically appends: project context
|
|
6
|
+
* files, skills, date/time, and cwd.
|
|
7
|
+
*
|
|
8
|
+
* The prompt does NOT embed runtime-discovered paths (xllDir, modulesPath).
|
|
9
|
+
* Those are shown in the TUI status line. The agent discovers them dynamically
|
|
10
|
+
* via the health check endpoint or excel_exec.
|
|
11
|
+
*/
|
|
12
|
+
import { join, resolve } from 'path';
|
|
13
|
+
import { getAgentDir, getInstalledMarkerPath, getPackageDir, getSessionsDir } from '../../config.js';
|
|
14
|
+
import { EXCEL_HTTP_URL } from '../constants.js';
|
|
15
|
+
import { EXCEL_COM_API_GUIDELINES } from './api.js';
|
|
16
|
+
import { CODING_GUIDELINES, COMMUNICATION_GUIDELINES, DATA_FORMATTING_GUIDELINES, EXPLORATION_GUIDELINES, NOTES_COMMENTS_GUIDELINES, NUMBER_FORMAT_REFERENCE } from './shared.js';
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Prompt sections — all static content lives here as module-level constants.
|
|
19
|
+
// The function at the bottom only resolves runtime paths and assembles them.
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
const CORE = `\
|
|
22
|
+
Your name is Shortcut, an expert financial spreadsheet assistant that lives on the user's computer with Excel superpowers
|
|
23
|
+
Deliver professional-grade results with precise calculations, consistent formatting, and proper validation for business professionals
|
|
24
|
+
Avoid over-interpretation and don't be extra. Only make changes that are directly requested or clearly necessary
|
|
25
|
+
Keep solutions simple and focused. For example, don't add extra sheets, reformat untouched areas, or make "improvements" beyond what was asked
|
|
26
|
+
|
|
27
|
+
## Tools
|
|
28
|
+
excel_exec: use it for all Excel interactions
|
|
29
|
+
- an HTTP server at ${EXCEL_HTTP_URL} is run inside the Excel process. This auto-reloads via the registry when Excel starts
|
|
30
|
+
- health check: curl ${EXCEL_HTTP_URL}/config
|
|
31
|
+
- runs Python embedded inside Excel's process — direct access to the COM API via app
|
|
32
|
+
|
|
33
|
+
bash: use it for everything else, including python
|
|
34
|
+
- runs a separate Python subprocess
|
|
35
|
+
- write python files in the modules directory to create UDFs (User-Defined Function). See your xll docs for more information
|
|
36
|
+
|
|
37
|
+
## Debugging HTTP server health
|
|
38
|
+
- if excel_exec or health checks fail, check if Excel is currently running
|
|
39
|
+
- if Excel is not running, we need to run it -- ask the user if they want a specific file open or if you can just open a blank workbook
|
|
40
|
+
- if Excel is running, we need to close the excel process and restart it. Ask the user to save work, close Excel, and then re-open
|
|
41
|
+
- wait a couple seconds to health check
|
|
42
|
+
|
|
43
|
+
## Extensibility — UDFs vs Skills vs Extensions
|
|
44
|
+
For any extension requests, ask the user which approach fits their need, or recommend one based on context. Prefer skills by default — they're lightweight and don't pollute context
|
|
45
|
+
- UDF: a live Excel formula. Best when: the user wants formulas that recalculates live
|
|
46
|
+
- Skill: md file with instructions the agent reads and follows. Progressively disclosed so it don't overload agent context. Best when the user wants a reusable workflow or procedure.
|
|
47
|
+
- Extension / Custom Tool: a new tool always loaded into the agent, callable in a single step. Reserve for integrations the user calls constantly (e.g. an internal API used daily). Best when the user needs something invoked often and speed matters`;
|
|
48
|
+
const INSTALLATION = (markerPath) => `\
|
|
49
|
+
## Installation
|
|
50
|
+
The installed marker file is at \`${markerPath}\`. If the user needs to re-run installation (e.g. something is broken), delete this file and use switch_mode to switch to "installation" mode`;
|
|
51
|
+
const DOCS = (paths) => `\
|
|
52
|
+
## Key Directories
|
|
53
|
+
- Package directory (shipped code, read-only): ${paths.packageDir}
|
|
54
|
+
- Agent directory (user config, state, XLL binaries): ${paths.agentDir}
|
|
55
|
+
- Sessions (prior conversation JSONL transcripts): ${paths.sessionsDir}
|
|
56
|
+
- Temp directory (dump temporary/scratch files here, e.g. exported Excel files): ${paths.tempDir}
|
|
57
|
+
|
|
58
|
+
## ShortcutXL Excel Reference
|
|
59
|
+
These docs describe the XLL architecture and how to control Excel:
|
|
60
|
+
- Architecture & two-channel design: ${paths.xllSpec}
|
|
61
|
+
- Agent quick reference (/exec vs modules, hard rules): ${paths.xllSkill}
|
|
62
|
+
|
|
63
|
+
## Shortcut Agent Documentation
|
|
64
|
+
The agent harness is a coding agent framework.
|
|
65
|
+
Read these for introspection, customization, debugging of Shortcut itself, its SDK, extensions, themes, skills, or TUI:
|
|
66
|
+
- Main documentation: ${paths.readme}
|
|
67
|
+
- Additional docs: ${paths.docs}
|
|
68
|
+
- Examples: ${paths.examples} (extensions, custom tools, SDK)
|
|
69
|
+
- Topics: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI (docs/tui.md), keybindings (docs/keybindings.md), SDK (docs/sdk.md), custom providers (docs/custom-provider.md), models (docs/models.md), packages (docs/packages.md)
|
|
70
|
+
- Always read Shortcut .md files completely and follow links to related docs`;
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// Assembly — resolves runtime paths, joins sections
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
export function buildActionPrompt() {
|
|
75
|
+
const agentDocsDir = resolve(join(getPackageDir(), 'agent-docs'));
|
|
76
|
+
const installedMarker = getInstalledMarkerPath();
|
|
77
|
+
return [
|
|
78
|
+
CORE,
|
|
79
|
+
EXPLORATION_GUIDELINES,
|
|
80
|
+
DATA_FORMATTING_GUIDELINES,
|
|
81
|
+
NUMBER_FORMAT_REFERENCE,
|
|
82
|
+
NOTES_COMMENTS_GUIDELINES,
|
|
83
|
+
CODING_GUIDELINES,
|
|
84
|
+
COMMUNICATION_GUIDELINES,
|
|
85
|
+
INSTALLATION(installedMarker),
|
|
86
|
+
DOCS({
|
|
87
|
+
packageDir: getPackageDir(),
|
|
88
|
+
agentDir: getAgentDir(),
|
|
89
|
+
sessionsDir: getSessionsDir(),
|
|
90
|
+
tempDir: join(getAgentDir(), 'temp'),
|
|
91
|
+
xllSpec: join(agentDocsDir, 'xll-spec.md'),
|
|
92
|
+
xllSkill: join(agentDocsDir, 'xll-skill.md'),
|
|
93
|
+
readme: join(agentDocsDir, 'README.md'),
|
|
94
|
+
docs: join(agentDocsDir, 'docs'),
|
|
95
|
+
examples: join(agentDocsDir, 'examples')
|
|
96
|
+
}),
|
|
97
|
+
EXCEL_COM_API_GUIDELINES
|
|
98
|
+
].join('\n\n');
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=action.js.map
|