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,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Excel COM API guidance injected into the system prompt.
|
|
3
|
+
*/
|
|
4
|
+
export const EXCEL_COM_API_GUIDELINES = `
|
|
5
|
+
===========================
|
|
6
|
+
## Excel COM API Guidelines
|
|
7
|
+
===========================
|
|
8
|
+
Multiple agents may operate on the same Excel instance concurrently. Follow these rules to avoid race conditions and ambiguity
|
|
9
|
+
|
|
10
|
+
### Execution environment
|
|
11
|
+
- Your written code is wrapped
|
|
12
|
+
- Calculation is set to manual during code execution and restored to user default afterwards. This means:
|
|
13
|
+
- Formulas you **write** are evaluated immediately (Excel always evaluates on entry)
|
|
14
|
+
- But formulas that **depend on cells you changed** will NOT recalculate until after your code block finishes and calc is restored
|
|
15
|
+
- Do NOT call app.Calculate(), ws.Calculate(), or range.Calculate() inside your code — it pollutes the change tracker with recalculated cells that you didn't directly write
|
|
16
|
+
- If you need to read a dependent formula's updated result, do it in a **follow-up code block** (after calc has been restored), not in the same block where you changed its dependency
|
|
17
|
+
- Events are disabled during code execution
|
|
18
|
+
- ScreenUpdating is left ON intentionally — do not disable it
|
|
19
|
+
|
|
20
|
+
### Before You Start
|
|
21
|
+
- For existing workbooks, use start "" "filepath"
|
|
22
|
+
- For new workbooks, we must skip the splash screen. To do this, create a workbook in the temp dir via openpyxl or use an existing one. Then open it via start
|
|
23
|
+
- Do NOT use /e or other command-line flags — Excel interprets them as file paths
|
|
24
|
+
- If the user references a file that isn't open, explore the filesystem to locate it, then open it
|
|
25
|
+
|
|
26
|
+
### Workbook References — NEVER use ActiveWorkbook
|
|
27
|
+
- At the start of a task, list workbooks to find the right name: [wb.Name for wb in app.Workbooks]
|
|
28
|
+
- Always reference workbooks by name: app.Workbooks("MyFile.xlsx")
|
|
29
|
+
- NEVER use: app.ActiveWorkbook, app.ActiveSheet, app.ActiveCell, app.Selection
|
|
30
|
+
- These are global mutable state — another agent or the user can change them between your lines of code
|
|
31
|
+
|
|
32
|
+
### Sheet References — NEVER use ActiveSheet
|
|
33
|
+
- Always qualify sheets from the workbook: app.Workbooks("Book1.xlsx").Sheets("Sheet1")
|
|
34
|
+
- NEVER use: app.Sheets("Sheet1") (implicitly uses ActiveWorkbook)
|
|
35
|
+
|
|
36
|
+
### Range References — Always Fully Qualified
|
|
37
|
+
- Good: app.Workbooks("Book1.xlsx").Sheets("Sheet1").Range("A1:B10")
|
|
38
|
+
- Bad: app.Range("A1:B10") (uses ActiveSheet of ActiveWorkbook)
|
|
39
|
+
- Store the sheet in a variable for readability:
|
|
40
|
+
wb = app.Workbooks("Book1.xlsx")
|
|
41
|
+
ws = wb.Sheets("Sheet1")
|
|
42
|
+
val = ws.Range("A1").Value
|
|
43
|
+
|
|
44
|
+
### Common Patterns
|
|
45
|
+
- Read a table to Python: ws.Range("A1:D100").Value — returns a tuple of tuples
|
|
46
|
+
- Write a 2D array: ws.Range("A1:B3").Value = ((1,2),(3,4),(5,6))
|
|
47
|
+
- Prefer bulk Range writes over cell-by-cell loops. Each COM call has ~1.4ms overhead; a 1000-row bulk write is ~250x faster than looping
|
|
48
|
+
- Last used row: ws.Cells(ws.Rows.Count, 1).End(-4162).Row (xlUp = -4162)
|
|
49
|
+
- Auto-fit columns: ws.UsedRange.Columns.AutoFit()
|
|
50
|
+
- Add a sheet: wb.Sheets.Add(After=wb.Sheets(wb.Sheets.Count))
|
|
51
|
+
|
|
52
|
+
### VBA / Macros (.xlsm)
|
|
53
|
+
- The COM API fully supports VBA: create modules, run macros, edit code via \`wb.VBProject\`
|
|
54
|
+
- Run a macro: \`app.Run("MacroName")\` or \`app.Run("MacroName", arg1, arg2)\`
|
|
55
|
+
- Access VBA project: \`wb.VBProject.VBComponents\`
|
|
56
|
+
- Save as macro-enabled: \`wb.SaveAs(path, FileFormat=52)\` (52 = xlOpenXMLMacroEnabled)
|
|
57
|
+
- If \`wb.VBProject\` throws "Programmatic access to Visual Basic Project is not trusted", the user must enable it:
|
|
58
|
+
**File → Options → Trust Center → Trust Center Settings → Macro Settings → ✅ "Trust access to the VBA project object model"**
|
|
59
|
+
Guide the user through this if the error occurs
|
|
60
|
+
|
|
61
|
+
### Things to Avoid
|
|
62
|
+
- Do not call .Select() or .Activate() — these change global state and are never needed programmatically
|
|
63
|
+
- Do not assume a workbook is open — wrap in try/except or check app.Workbooks.Count
|
|
64
|
+
- Watch out for indexing: COM collections are 1-based (ws.Cells(1,1) is A1, wb.Sheets(1) is the first sheet), but .Value returns Python tuples which are 0-based (data[0][0] is the first cell)
|
|
65
|
+
`;
|
|
66
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installation system prompt.
|
|
3
|
+
*
|
|
4
|
+
* All steps are always included so the agent has full context.
|
|
5
|
+
* The agent creates the installed marker once setup is verified,
|
|
6
|
+
* so this prompt won't show on subsequent launches.
|
|
7
|
+
*/
|
|
8
|
+
import { join, resolve } from 'path';
|
|
9
|
+
import { getAgentDir, getInstalledMarkerPath } from '../../config.js';
|
|
10
|
+
import { EXCEL_HTTP_URL } from '../constants.js';
|
|
11
|
+
import { getStableXllDir } from '../sync-xll.js';
|
|
12
|
+
export function buildInstallationPrompt() {
|
|
13
|
+
const stableXllDir = resolve(getStableXllDir());
|
|
14
|
+
const modulesDir = join(stableXllDir, 'modules');
|
|
15
|
+
const xllPath = join(stableXllDir, 'ShortcutXL.xll');
|
|
16
|
+
const agentDir = getAgentDir();
|
|
17
|
+
const installedMarker = getInstalledMarkerPath();
|
|
18
|
+
return `\
|
|
19
|
+
You are guiding a first-time user through ShortcutXL setup. Walk them through each step in order.
|
|
20
|
+
ALWAYS ask before starting every step for user permission, you are installing / opening things on their computer.
|
|
21
|
+
Be conversational — confirm each step succeeds before moving on.
|
|
22
|
+
If something fails, troubleshoot with the user before continuing. Skip steps that are already complete.
|
|
23
|
+
|
|
24
|
+
## Background
|
|
25
|
+
|
|
26
|
+
ShortcutXL is a two-part system:
|
|
27
|
+
|
|
28
|
+
1. **ShortcutXL.xll** — A C add-in (DLL) that runs inside Excel's process. It embeds a Python 3.12 runtime and exposes an HTTP server at ${EXCEL_HTTP_URL} so the agent can control Excel.
|
|
29
|
+
2. **shortcutxl** (this CLI) — A Node.js TUI that talks to the XLL over HTTP. The agent sends Python code to execute via POST /exec and writes UDF modules to the filesystem.
|
|
30
|
+
|
|
31
|
+
## Where things live
|
|
32
|
+
|
|
33
|
+
- **XLL binaries**: ${stableXllDir} — Automatically synced from the npm package on every startup. The registry key MUST point to this stable path, not the npm package directory — that path changes on every update.
|
|
34
|
+
- **User modules**: ${modulesDir} — Where shortcut_xl.py (the core helper library) and user-created UDF modules live. The XLL hot-reloads .py files from this directory.
|
|
35
|
+
- **Agent config**: ${agentDir} — Settings, auth tokens, session history.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Step 0: Verify Shell
|
|
40
|
+
|
|
41
|
+
You need Git Bash to be installed. Check to see if it is by running some simple commands, like echo ok && git --version.
|
|
42
|
+
|
|
43
|
+
If Git Bash is not installed, you MUST
|
|
44
|
+
- Ask the user for permission to install Git for Windows.
|
|
45
|
+
- temporarily run cmd or powershell to execute commands. Do NOT use bash syntax. Paths with spaces must be quoted carefully — cmd.exe strips the first and last quote when there are multiple pairs. Prefer short commands like \`git --version\` or \`where bash\`.
|
|
46
|
+
|
|
47
|
+
Bash installation instructions:
|
|
48
|
+
- First check if winget is available. If winget is missing, install it.
|
|
49
|
+
- Then install git, accepting source and package agreements. Tell the user to expect a Windows UAC prompt — they must click Yes. Verify Git installed.
|
|
50
|
+
- Verify bash is now available. If it succeeds, the shell has automatically switched from cmd.exe to Git Bash. All subsequent commands will use bash.
|
|
51
|
+
- sh is installed. Run a simple bash command to confirm bash works. If it fails, the error output will tell the user what to install.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Step 1: Install Python 3.12
|
|
56
|
+
|
|
57
|
+
The XLL embeds a Python interpreter and finds it via the Windows registry. Without Python 3.12 + pywin32, the XLL loads but Python execution fails silently.
|
|
58
|
+
|
|
59
|
+
- Check if Python 3.12 is installed. If missing, ask the user for permission, then download Python 3.12 and run a silent per-user install. Verify that it is installed correctly after
|
|
60
|
+
- Install pywin32 and openpyxl
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Step 2: Connect ShortcutXL to Excel
|
|
65
|
+
|
|
66
|
+
This step tells Excel to load ShortcutXL every time it opens. Once connected, the user gets:
|
|
67
|
+
- **Multi-workbook operations** — read and write across multiple open workbooks simultaneously.
|
|
68
|
+
- **Deep feature control** — full manipulation of pivots, charts, sensitivity tables, iterative recalculations, and more.
|
|
69
|
+
- **VBA access** — read, write, and run macros. Create VBA modules programmatically.
|
|
70
|
+
- **Extensible** — integrate any API or data source by adding a skill file or a custom tool extension.
|
|
71
|
+
|
|
72
|
+
All of this while keeping data local — workbooks, files, and skills stay on the user's machine.
|
|
73
|
+
|
|
74
|
+
**How to register (technical details for you, the agent):**
|
|
75
|
+
Excel checks HKCU\\Software\\Microsoft\\Office\\<version>\\Excel\\Options for keys named OPEN, OPEN1, OPEN2, etc. Each value is a path to an add-in to load at startup.
|
|
76
|
+
|
|
77
|
+
- Check to see if the registry already has ShortcutXL.
|
|
78
|
+
- Ask the user for permission — explain you're adding a small user-level setting (no admin needed) so Excel knows to load ShortcutXL on startup.
|
|
79
|
+
- Detect the Office version, find the next available OPEN slot, and write the key with value /R "${xllPath}".
|
|
80
|
+
- If Excel is already running, ask the user to save their work first, then close and reopen it. Do NOT proceed to Step 3 until Excel has been restarted.
|
|
81
|
+
- If Excel is not running, launch it and wait a few seconds for it to start up.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Step 3: Verify the XLL is Running
|
|
86
|
+
|
|
87
|
+
When Excel opens, it loads the XLL which initializes Python, starts the HTTP server on port 8080.
|
|
88
|
+
- Check: \`curl ${EXCEL_HTTP_URL}/config\`. Expected: JSON with xll_dir and modules_path. Retry one time if Excel is still starting up.
|
|
89
|
+
- Verify the paths match: The config response's \`modules_path\` MUST be \`${modulesDir}\`. If it points elsewhere, the registry key is loading an old or wrong copy of the XLL — fix the registry to point to \`${xllPath}\` and restart Excel.
|
|
90
|
+
- If it fails: check if Excel is open, check File > Options > Add-ins for ShortcutXL, check %TEMP%\\shortcutxl.log for errors.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Step 4: Smoke Test
|
|
95
|
+
|
|
96
|
+
End-to-end verification: agent → HTTP → XLL → Python → COM → Excel.
|
|
97
|
+
|
|
98
|
+
Run via excel_exec:
|
|
99
|
+
\`\`\`python
|
|
100
|
+
print(f"Excel {xl_app().Version}")
|
|
101
|
+
\`\`\`
|
|
102
|
+
|
|
103
|
+
If this returns the Excel version, setup is complete. Create the marker file \`${installedMarker}\`, then use switch_mode to switch to action mode.
|
|
104
|
+
|
|
105
|
+
Tell the user what to expect going forward:
|
|
106
|
+
- **From now on, just run \`shortcut\`** — Excel automatically opens with the agent loaded if it's not already running. No manual setup needed again.
|
|
107
|
+
- Tell the user that they can either ask to do things in Excel right away — rading, writing, sensitivity tables, multi-workbook workflows, etc... AND / OR
|
|
108
|
+
- Explore capabilities and extensibility — the user can ask the agent to build custom tools, connect to APIs (e.g. internal databases, Daloopa, Bloomberg, etc.), and add integrations. The agent can modify itself to add new capabilities on demand.
|
|
109
|
+
- Ask what they'd like to do first!
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Current State
|
|
114
|
+
|
|
115
|
+
- XLL binary (stable path): ${xllPath}
|
|
116
|
+
- Installed marker: ${installedMarker} (does not exist yet — create after smoke test passes)
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Troubleshooting
|
|
121
|
+
|
|
122
|
+
- **ShortcutXL.xll opens as a file** — If the user sees a warning dialog about the file format or ShortcutXL.xll being opened as a spreadsheet, tell them to close that dialog and close Excel entirely. Then ask them to open any Excel file themselves — this one time only, to complete setup. Once they have a spreadsheet open, retry the verification.`;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=installation.js.map
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared prompt guidelines — adapted from backend/agent/prompts/shared.py
|
|
3
|
+
* for the ShortcutXL (desktop Excel + COM API) context.
|
|
4
|
+
*/
|
|
5
|
+
export const EXPLORATION_GUIDELINES = `
|
|
6
|
+
======================
|
|
7
|
+
## DATA EXPLORATION
|
|
8
|
+
======================
|
|
9
|
+
|
|
10
|
+
Perception, defined as understanding relevant context, is almost always the hardest part of your job
|
|
11
|
+
Workbooks have implicit knowledge and conventions stored throughout as labels, notes, comments, formatting, etc
|
|
12
|
+
Once you acquire relevant context, it is generally not difficult to execute on logic
|
|
13
|
+
Therefore, you must explore thoroughly. Don't stop at first match — check surrounding areas and other sheets to understand context
|
|
14
|
+
Pay attention especially to existing conventions, signage labels, and preferences across the workbook
|
|
15
|
+
Only after exploring, write. Never handle multiple pieces at once
|
|
16
|
+
`;
|
|
17
|
+
export const DATA_FORMATTING_GUIDELINES = `
|
|
18
|
+
======================
|
|
19
|
+
## DATA FORMATTING
|
|
20
|
+
======================
|
|
21
|
+
**IMPORTANT**: Do NOT apply new formatting unless specified. Match existing formatting and inspect surrounding data for consistency. Every tab must be visually consistent —
|
|
22
|
+
consistent colors, fonts, number formats, and header styles throughout. DO NOT overwrite cells unless explicitly requested.
|
|
23
|
+
|
|
24
|
+
Model Integrity:
|
|
25
|
+
- Every spreadsheet is a live model. Inputs → assumptions → calculations → outputs. When ANY input changes, every dependent cell must update automatically through formula linkage — no manual intervention
|
|
26
|
+
- Single source of truth: each constant lives in exactly one cell, referenced everywhere else
|
|
27
|
+
- Organize inputs in a dedicated section or sheet (e.g., "Assumptions" tab). Do NOT create named ranges unless explicitly requested
|
|
28
|
+
- Never hardcode numbers in formulas: every number traces back to a labeled input cell. When extracting from sources (PDFs, images, files), extract each value ONCE into an input cell, then reference that cell everywhere else. Never pull the same value from a source twice
|
|
29
|
+
- Formulas should be simple and auditable. Reference cells by position, not by searching for them — you already know where the data is
|
|
30
|
+
- If formulas must be complex, still use formulas — never resort to hardcodes or value insertions. You can first compute internally or via Python, but always use formulas on the sheet itself
|
|
31
|
+
|
|
32
|
+
Color Standards:
|
|
33
|
+
- Blue: inputs/assumptions | Black: formulas | Green: cross-sheet refs | Red: external refs
|
|
34
|
+
- Use subtle styling (borders, bold, light greys/blues). Avoid vibrant colors — they're unprofessional
|
|
35
|
+
|
|
36
|
+
Cell Formatting:
|
|
37
|
+
- Use uniform font size across all cells (detect existing size or default to 12pt). Only vary size for headers/titles
|
|
38
|
+
- Never use fonts smaller than 10pt — they are unreadable on standard screens
|
|
39
|
+
- Standardize number formats, use brackets for negatives
|
|
40
|
+
- Bold titles/sums, include units/currency symbols
|
|
41
|
+
- Label historical vs projected data clearly
|
|
42
|
+
- Hide gridlines for financial models
|
|
43
|
+
- Prefer manual sizing over AutoFit. AutoFit sizes to the longest cell content, which produces uneven, unprofessional column widths across a model
|
|
44
|
+
- Use consistent widths within sections (e.g., all quarterly data columns the same width, all label columns the same width)
|
|
45
|
+
|
|
46
|
+
Organization:
|
|
47
|
+
- Start at B2 (top-left padding), not A1
|
|
48
|
+
- Use 1px borders within models, thicker for section breaks
|
|
49
|
+
- Indent parent/child hierarchies, avoid merging cells
|
|
50
|
+
- Name worksheets clearly (e.g., "Assumptions", not "Sheet1")
|
|
51
|
+
`;
|
|
52
|
+
export const NUMBER_FORMAT_REFERENCE = `
|
|
53
|
+
======================
|
|
54
|
+
## NUMBER FORMAT REFERENCE
|
|
55
|
+
======================
|
|
56
|
+
For currency, use Excel's built-in Accounting or Currency number formats (e.g. ws.Range("A1").NumberFormat = "$#,##0.00"). Do not define overly complex custom currency formats
|
|
57
|
+
|
|
58
|
+
**Format Symbols:**
|
|
59
|
+
- 0 = Required digit (always shows, pads with zeros). Example: 0.00 formats 5 as "5.00"
|
|
60
|
+
- # = Optional digit (only shows if needed). Example: #.## formats 5 as "5"
|
|
61
|
+
- , = Thousands separator | ? = Space for alignment (fractions)
|
|
62
|
+
|
|
63
|
+
**Common Formats:**
|
|
64
|
+
- Numbers: "#,##0" (thousands), "#,##0.00" (decimals)
|
|
65
|
+
- Percentage: "0%" or "0.00%"
|
|
66
|
+
- Date: "yyyy-mm-dd", "mm/dd/yyyy", "dddd, mmmm dd, yyyy"
|
|
67
|
+
- Time: "hh:mm:ss", "hh:mm:ss AM/PM"
|
|
68
|
+
|
|
69
|
+
**Common Mistakes:**
|
|
70
|
+
- Percentages: Cell value must be decimal (0.5 for 50%), not the display value (50)
|
|
71
|
+
- Money: Use a consistent number format for financial values across the workbook
|
|
72
|
+
`;
|
|
73
|
+
export const NOTES_COMMENTS_GUIDELINES = `
|
|
74
|
+
======================
|
|
75
|
+
## NOTES AND COMMENTS
|
|
76
|
+
======================
|
|
77
|
+
Add Excel notes/comments when:
|
|
78
|
+
1. **Canonical input cells ONLY** — Source notes belong ONLY on the single cell where a value is first entered into the workbook. Downstream cells MUST reference this input cell via formula — never re-extract the same value from the source. If a value already exists in an input/assumptions cell, reference it, don't extract again
|
|
79
|
+
2. **Assumptions / Ambiguity / Uncertainty** — See "Additional commentary" below for where to put these
|
|
80
|
+
|
|
81
|
+
**Source reference notes (on the cell itself)**:
|
|
82
|
+
- FORMAT: \`[Filename] | Page [X] | [exact text from source]\`
|
|
83
|
+
- Example: \`Report.pdf | Page 103 | $102.32\`
|
|
84
|
+
- The third field must contain the value exactly as it appears in the source document — preserve original formatting, spacing, and symbols
|
|
85
|
+
- STRICT: The note text MUST contain ONLY this format string — nothing else. No reasoning, no assumptions, no extra text
|
|
86
|
+
- Always include filename, even if only one file is attached
|
|
87
|
+
|
|
88
|
+
**Additional commentary** (assumptions, reasoning, ambiguity flags, uncertainty):
|
|
89
|
+
- Write these in an adjacent cell in the same row (e.g., a "Notes" column to the right of the data), NOT in the Excel note
|
|
90
|
+
- For uncertainty, also highlight the value cell yellow for visual scanning
|
|
91
|
+
|
|
92
|
+
Do NOT add notes for routine formulas or obvious calculations
|
|
93
|
+
|
|
94
|
+
**COM API for notes:**
|
|
95
|
+
- Add: \`ws.Range("A1").AddComment("text")\` (or \`.NoteText("text")\` for older-style notes)
|
|
96
|
+
- Read: \`ws.Range("A1").Comment.Text()\`
|
|
97
|
+
- Delete: \`ws.Range("A1").Comment.Delete()\`
|
|
98
|
+
- Check existence: \`ws.Range("A1").Comment is not None\`
|
|
99
|
+
`;
|
|
100
|
+
export const COMMUNICATION_GUIDELINES = `
|
|
101
|
+
======================
|
|
102
|
+
## Tone and Style
|
|
103
|
+
======================
|
|
104
|
+
- Be clear and direct. Give enough context that the user understands what's happening and why. A sentence or two is usually right, more if the task is complex
|
|
105
|
+
- NEVER include code in responses. Describe intentions briefly per turn. After completing tasks, stop — don't explain what you did
|
|
106
|
+
- No emojis unless requested. Avoid filler phrases like "Here is..." or "Based on...". Be proactive when taking actions, but answer questions directly without jumping to action
|
|
107
|
+
- Reference cells/ranges frequently using Workbook:Sheet!Range or Sheet!Cell format (e.g., "Summary!A1:B10", "Data!C5") — this tells users exactly where to look
|
|
108
|
+
`;
|
|
109
|
+
export const CODING_GUIDELINES = `
|
|
110
|
+
======================
|
|
111
|
+
## WRITING CODE
|
|
112
|
+
======================
|
|
113
|
+
|
|
114
|
+
Execute code as many times as needed before returning the final answer. A core loop is: execute code → verify the results → iterate until the task is complete
|
|
115
|
+
Never ask the user to do anything — just generate the code and execute it
|
|
116
|
+
|
|
117
|
+
**Critical principles for writing onto the spreadsheet:**
|
|
118
|
+
- IMPORTANT: Use bulk Range writes over cell-by-cell loops. Each COM call has ~1.4ms overhead; a 1000-row bulk write is ~250x faster than looping
|
|
119
|
+
- Use AutoFill for formula patterns: \`ws.Range("A1").AutoFill(Destination=ws.Range("A1:A10"))\`
|
|
120
|
+
- If you loop over individual cells, loop over numeric indices. Looping over letters (e.g. incrementing column letters) does not work reliably
|
|
121
|
+
- Do not overwrite existing data, especially existing user-filled data, unless explicitly requested
|
|
122
|
+
- Pay special attention to positive/negative values and decimal conventions. For example, if adjacent tax values are negative, then tax values that you fill in should be negative. Watch for column labels like "(+) Tax" or "(-) Depreciation"
|
|
123
|
+
|
|
124
|
+
**Structural operations (insert/delete rows/columns):**
|
|
125
|
+
Inserting or deleting rows/columns shifts the entire sheet. Addresses you memorized previously may now be wrong
|
|
126
|
+
Excel auto-adjusts formulas for references inside affected ranges, but not always correctly for edge cases (ranges ending at the insertion point, cross-sheet refs, etc.)
|
|
127
|
+
For structural changes, you MUST:
|
|
128
|
+
- Consider whether to check dependents of modified cells to map downstream effects
|
|
129
|
+
- Do the structural change (e.g. \`ws.Rows("5:5").Insert()\`, \`ws.Columns("C:C").Delete()\`) and NOTHING ELSE in that code block
|
|
130
|
+
- In a new code execution, read the affected cells to see what auto-adjusted. Never assume you know what the formulas look like now — your pre-insertion row/column numbers are STALE
|
|
131
|
+
- Check the workbook for errors (especially #REF!) the structural change introduced
|
|
132
|
+
- Only then write corrections, using actual current state you just read — not your mental model of what shifted
|
|
133
|
+
|
|
134
|
+
**Prefer native Excel functionality:**
|
|
135
|
+
- ALWAYS prefer native spreadsheet functionality (pivot tables, tables, data validation, charts, conditional formatting, etc.) over writing values / formulas / styles programmatically for dynamic updates
|
|
136
|
+
- If any request can be naturally solved with pivot tables or pivot analysis, ALWAYS do that instead of programmatically writing values and formulas
|
|
137
|
+
`;
|
|
138
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared usage/cost calculation for Shortcut LLM providers.
|
|
3
|
+
*
|
|
4
|
+
* Both shortcut-stream.ts and shortcut-invoke.ts need identical logic
|
|
5
|
+
* to convert raw token counts into pi-ai Usage objects with cost breakdown.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Build a pi-ai Usage object from raw token counts and model cost rates.
|
|
9
|
+
*/
|
|
10
|
+
export function buildUsage(rawUsage, model) {
|
|
11
|
+
const input = rawUsage.input_tokens ?? 0;
|
|
12
|
+
const output = rawUsage.output_tokens ?? 0;
|
|
13
|
+
const cacheRead = rawUsage.cache_read_input_tokens ?? 0;
|
|
14
|
+
const cacheWrite = rawUsage.cache_creation_input_tokens ?? 0;
|
|
15
|
+
const costInput = (input * model.cost.input) / 1_000_000;
|
|
16
|
+
const costOutput = (output * model.cost.output) / 1_000_000;
|
|
17
|
+
const costCacheRead = (cacheRead * model.cost.cacheRead) / 1_000_000;
|
|
18
|
+
const costCacheWrite = (cacheWrite * model.cost.cacheWrite) / 1_000_000;
|
|
19
|
+
return {
|
|
20
|
+
input,
|
|
21
|
+
output,
|
|
22
|
+
cacheRead,
|
|
23
|
+
cacheWrite,
|
|
24
|
+
totalTokens: input + output,
|
|
25
|
+
cost: {
|
|
26
|
+
input: costInput,
|
|
27
|
+
output: costOutput,
|
|
28
|
+
cacheRead: costCacheRead,
|
|
29
|
+
cacheWrite: costCacheWrite,
|
|
30
|
+
total: costInput + costOutput + costCacheRead + costCacheWrite
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Map backend stop_reason strings to pi-ai StopReason values. */
|
|
35
|
+
export function mapStopReason(raw) {
|
|
36
|
+
return raw === 'tool_use'
|
|
37
|
+
? 'toolUse'
|
|
38
|
+
: raw === 'max_tokens'
|
|
39
|
+
? 'length'
|
|
40
|
+
: 'stop';
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=llm-usage.js.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure conversion functions: pi-ai Context → LangChain request format.
|
|
3
|
+
*
|
|
4
|
+
* These are the types and functions that define the request contract between
|
|
5
|
+
* the TS agent and the Python backend's /api/llm/stream endpoint.
|
|
6
|
+
* Zero I/O — fully testable with no mocking.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Convert pi-ai Context messages to LangChain message format.
|
|
10
|
+
* System prompt becomes a system message. User/assistant/toolResult map to human/ai/tool.
|
|
11
|
+
*/
|
|
12
|
+
export function convertMessages(context) {
|
|
13
|
+
const result = [];
|
|
14
|
+
if (context.systemPrompt) {
|
|
15
|
+
result.push({ role: 'system', content: context.systemPrompt });
|
|
16
|
+
}
|
|
17
|
+
for (const msg of context.messages) {
|
|
18
|
+
if (msg.role === 'user') {
|
|
19
|
+
const text = typeof msg.content === 'string'
|
|
20
|
+
? msg.content
|
|
21
|
+
: msg.content.map((c) => (c.type === 'text' ? c.text : '')).join('');
|
|
22
|
+
result.push({ role: 'human', content: text });
|
|
23
|
+
}
|
|
24
|
+
else if (msg.role === 'assistant') {
|
|
25
|
+
let text = '';
|
|
26
|
+
const toolCalls = [];
|
|
27
|
+
let thinking;
|
|
28
|
+
let thinkingSignature;
|
|
29
|
+
for (const c of msg.content) {
|
|
30
|
+
if (c.type === 'text') {
|
|
31
|
+
text += c.text;
|
|
32
|
+
}
|
|
33
|
+
else if (c.type === 'toolCall') {
|
|
34
|
+
toolCalls.push({
|
|
35
|
+
id: c.id,
|
|
36
|
+
name: c.name,
|
|
37
|
+
arguments: JSON.stringify(c.arguments)
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else if (c.type === 'thinking') {
|
|
41
|
+
thinking = c.thinking;
|
|
42
|
+
thinkingSignature = c.thinkingSignature;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const lcMsg = { role: 'ai', content: text };
|
|
46
|
+
if (toolCalls.length > 0)
|
|
47
|
+
lcMsg.tool_calls = toolCalls;
|
|
48
|
+
if (thinking)
|
|
49
|
+
lcMsg.thinking = thinking;
|
|
50
|
+
if (thinkingSignature)
|
|
51
|
+
lcMsg.thinking_signature = thinkingSignature;
|
|
52
|
+
result.push(lcMsg);
|
|
53
|
+
}
|
|
54
|
+
else if (msg.role === 'toolResult') {
|
|
55
|
+
const text = msg.content.map((c) => (c.type === 'text' ? c.text : '')).join('');
|
|
56
|
+
result.push({ role: 'tool', content: text, tool_call_id: msg.toolCallId });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Convert pi-ai Tool[] to LangChain tool format.
|
|
63
|
+
* Returns undefined if no tools (backend omits the field).
|
|
64
|
+
*/
|
|
65
|
+
export function convertTools(tools) {
|
|
66
|
+
if (!tools || tools.length === 0)
|
|
67
|
+
return undefined;
|
|
68
|
+
return tools.map((t) => ({
|
|
69
|
+
name: t.name,
|
|
70
|
+
description: t.description,
|
|
71
|
+
parameters: t.parameters
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=message-converter.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider identifiers for custom (non-upstream) providers.
|
|
3
|
+
*
|
|
4
|
+
* These are the string IDs passed to modelRegistry.registerProvider()
|
|
5
|
+
* and used in auth checks, model scoping, and provider-specific logic.
|
|
6
|
+
*/
|
|
7
|
+
export const SHORTCUT_PROVIDER_ID = 'shortcut';
|
|
8
|
+
export const OPENAI_CODEX_PROVIDER_ID = 'openai';
|
|
9
|
+
//# sourceMappingURL=provider-ids.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register the OpenAI Codex provider with the model registry.
|
|
3
|
+
*
|
|
4
|
+
* Uses the built-in pi-ai OpenAI Codex OAuth flow (ChatGPT Plus/Pro subscription).
|
|
5
|
+
* Streams via the built-in `openai-codex-responses` API — no custom stream needed.
|
|
6
|
+
*/
|
|
7
|
+
import { openaiCodexOAuthProvider } from '@mariozechner/pi-ai/dist/utils/oauth/openai-codex.js';
|
|
8
|
+
import { OPENAI_CODEX_PROVIDER_ID } from './provider-ids.js';
|
|
9
|
+
export function registerOpenAICodexProvider(modelRegistry) {
|
|
10
|
+
modelRegistry.registerProvider(OPENAI_CODEX_PROVIDER_ID, {
|
|
11
|
+
baseUrl: 'https://chatgpt.com/backend-api',
|
|
12
|
+
api: 'openai-codex-responses',
|
|
13
|
+
oauth: openaiCodexOAuthProvider,
|
|
14
|
+
models: [
|
|
15
|
+
{
|
|
16
|
+
id: 'gpt-5.4',
|
|
17
|
+
name: 'GPT-5.4',
|
|
18
|
+
reasoning: true,
|
|
19
|
+
input: ['text', 'image'],
|
|
20
|
+
cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 2.5 },
|
|
21
|
+
contextWindow: 200000,
|
|
22
|
+
maxTokens: 128000
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=register-openai-codex-provider.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register the Shortcut LLM provider with the model registry.
|
|
3
|
+
*
|
|
4
|
+
* Shortcut provider routes through our Python backend proxy which handles:
|
|
5
|
+
* - JWT auth (via get_user)
|
|
6
|
+
* - Model allowlisting
|
|
7
|
+
* - Credit/usage tracking (via get_llm)
|
|
8
|
+
* - Provider fallback (vertex)
|
|
9
|
+
*/
|
|
10
|
+
import { shortcutOAuth } from '../auth/shortcut-oauth.js';
|
|
11
|
+
import { SHORTCUT_PROVIDER_ID } from './provider-ids.js';
|
|
12
|
+
import { createShortcutInvoke } from './shortcut-invoke.js';
|
|
13
|
+
import { createShortcutStream } from './shortcut-stream.js';
|
|
14
|
+
export function registerShortcutProvider(modelRegistry, proxyUrl, options) {
|
|
15
|
+
const streaming = options?.streaming ?? true;
|
|
16
|
+
modelRegistry.registerProvider(SHORTCUT_PROVIDER_ID, {
|
|
17
|
+
baseUrl: proxyUrl,
|
|
18
|
+
api: 'shortcut-llm',
|
|
19
|
+
streamSimple: streaming ? createShortcutStream(proxyUrl) : createShortcutInvoke(proxyUrl),
|
|
20
|
+
oauth: shortcutOAuth,
|
|
21
|
+
models: [
|
|
22
|
+
{
|
|
23
|
+
id: 'claude-opus-4-6',
|
|
24
|
+
name: 'Claude Opus 4.6',
|
|
25
|
+
reasoning: true,
|
|
26
|
+
input: ['text', 'image'],
|
|
27
|
+
cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
|
|
28
|
+
contextWindow: 200000,
|
|
29
|
+
maxTokens: 128000
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'claude-sonnet-4-6',
|
|
33
|
+
name: 'Claude Sonnet 4.6',
|
|
34
|
+
reasoning: true,
|
|
35
|
+
input: ['text', 'image'],
|
|
36
|
+
cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
37
|
+
contextWindow: 200000,
|
|
38
|
+
maxTokens: 64000
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 'gpt-5.4-2026-03-05',
|
|
42
|
+
name: 'GPT-5.4',
|
|
43
|
+
reasoning: true,
|
|
44
|
+
input: ['text', 'image'],
|
|
45
|
+
cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 2.5 },
|
|
46
|
+
contextWindow: 200000,
|
|
47
|
+
maxTokens: 128000
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=register-shortcut-provider.js.map
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-streaming Shortcut LLM provider.
|
|
3
|
+
*
|
|
4
|
+
* Calls /api/llm/invoke (JSON request/response) instead of /api/llm/stream (SSE).
|
|
5
|
+
* Returns an AssistantMessageEventStream for compatibility with pi-ai's StreamFn interface,
|
|
6
|
+
* but emits only start → done (no deltas).
|
|
7
|
+
*/
|
|
8
|
+
import { createAssistantMessageEventStream } from '@mariozechner/pi-ai';
|
|
9
|
+
import { APP_NAME } from '../../config.js';
|
|
10
|
+
import { buildUsage, mapStopReason } from './llm-usage.js';
|
|
11
|
+
import { convertMessages, convertTools } from './message-converter.js';
|
|
12
|
+
import { SHORTCUT_PROVIDER_ID } from './provider-ids.js';
|
|
13
|
+
import { THINKING_TO_EFFORT } from './sse-protocol.js';
|
|
14
|
+
export function createShortcutInvoke(baseUrl) {
|
|
15
|
+
return function shortcutInvoke(model, context, options) {
|
|
16
|
+
const stream = createAssistantMessageEventStream();
|
|
17
|
+
const body = {
|
|
18
|
+
model: model.id,
|
|
19
|
+
messages: convertMessages(context),
|
|
20
|
+
tools: convertTools(context.tools),
|
|
21
|
+
effort_level: options?.reasoning ? THINKING_TO_EFFORT[options.reasoning] || 'low' : undefined,
|
|
22
|
+
thinking_type: 'adaptive'
|
|
23
|
+
};
|
|
24
|
+
(async () => {
|
|
25
|
+
try {
|
|
26
|
+
const apiKey = options?.apiKey ?? '';
|
|
27
|
+
const response = await fetch(`${baseUrl}/api/llm/invoke`, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers: {
|
|
30
|
+
'Content-Type': 'application/json',
|
|
31
|
+
Authorization: `Bearer ${apiKey}`,
|
|
32
|
+
'User-Agent': `Mozilla/5.0 (compatible; ${APP_NAME}-coding-agent/1.0)`
|
|
33
|
+
},
|
|
34
|
+
body: JSON.stringify(body),
|
|
35
|
+
signal: options?.signal
|
|
36
|
+
});
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
const raw = await response.text();
|
|
39
|
+
const text = raw.split('\n').slice(0, 20).join('\n');
|
|
40
|
+
throw new Error(`LLM proxy error ${response.status}: ${text}`);
|
|
41
|
+
}
|
|
42
|
+
const data = await response.json();
|
|
43
|
+
// Build content array
|
|
44
|
+
const content = [];
|
|
45
|
+
for (const tb of data.thinking) {
|
|
46
|
+
content.push({
|
|
47
|
+
type: 'thinking',
|
|
48
|
+
thinking: tb.thinking,
|
|
49
|
+
redacted: tb.redacted,
|
|
50
|
+
thinkingSignature: tb.signature
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (data.text) {
|
|
54
|
+
content.push({ type: 'text', text: data.text });
|
|
55
|
+
}
|
|
56
|
+
for (const tc of data.tool_calls) {
|
|
57
|
+
let args = {};
|
|
58
|
+
try {
|
|
59
|
+
args = JSON.parse(tc.arguments);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// keep empty
|
|
63
|
+
}
|
|
64
|
+
content.push({
|
|
65
|
+
type: 'toolCall',
|
|
66
|
+
id: tc.id,
|
|
67
|
+
name: tc.name,
|
|
68
|
+
arguments: args
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
const stopReason = mapStopReason(data.stop_reason);
|
|
72
|
+
const message = {
|
|
73
|
+
role: 'assistant',
|
|
74
|
+
content,
|
|
75
|
+
api: 'shortcut-llm',
|
|
76
|
+
provider: SHORTCUT_PROVIDER_ID,
|
|
77
|
+
model: model.id,
|
|
78
|
+
usage: buildUsage(data.usage, model),
|
|
79
|
+
stopReason,
|
|
80
|
+
timestamp: Date.now()
|
|
81
|
+
};
|
|
82
|
+
stream.push({ type: 'start', partial: message });
|
|
83
|
+
stream.push({
|
|
84
|
+
type: 'done',
|
|
85
|
+
reason: stopReason,
|
|
86
|
+
message
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
const isAbort = options?.signal?.aborted ||
|
|
91
|
+
(err instanceof Error && err.name === 'AbortError');
|
|
92
|
+
const errMsg = err instanceof Error ? err.message : 'Request failed';
|
|
93
|
+
const errorMessage = {
|
|
94
|
+
role: 'assistant',
|
|
95
|
+
content: [],
|
|
96
|
+
api: 'shortcut-llm',
|
|
97
|
+
provider: SHORTCUT_PROVIDER_ID,
|
|
98
|
+
model: model.id,
|
|
99
|
+
usage: {
|
|
100
|
+
input: 0,
|
|
101
|
+
output: 0,
|
|
102
|
+
cacheRead: 0,
|
|
103
|
+
cacheWrite: 0,
|
|
104
|
+
totalTokens: 0,
|
|
105
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
|
|
106
|
+
},
|
|
107
|
+
stopReason: isAbort ? 'aborted' : 'error',
|
|
108
|
+
errorMessage: isAbort ? 'Request was aborted' : errMsg,
|
|
109
|
+
timestamp: Date.now()
|
|
110
|
+
};
|
|
111
|
+
stream.push({ type: 'error', reason: isAbort ? 'aborted' : 'error', error: errorMessage });
|
|
112
|
+
}
|
|
113
|
+
})();
|
|
114
|
+
return stream;
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=shortcut-invoke.js.map
|