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,81 @@
|
|
|
1
|
+
import { accessSync, constants } from 'node:fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import { isAbsolute, resolve as resolvePath } from 'node:path';
|
|
4
|
+
const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
|
|
5
|
+
const NARROW_NO_BREAK_SPACE = '\u202F';
|
|
6
|
+
function normalizeUnicodeSpaces(str) {
|
|
7
|
+
return str.replace(UNICODE_SPACES, ' ');
|
|
8
|
+
}
|
|
9
|
+
function tryMacOSScreenshotPath(filePath) {
|
|
10
|
+
return filePath.replace(/ (AM|PM)\./g, `${NARROW_NO_BREAK_SPACE}$1.`);
|
|
11
|
+
}
|
|
12
|
+
function tryNFDVariant(filePath) {
|
|
13
|
+
// macOS stores filenames in NFD (decomposed) form, try converting user input to NFD
|
|
14
|
+
return filePath.normalize('NFD');
|
|
15
|
+
}
|
|
16
|
+
function tryCurlyQuoteVariant(filePath) {
|
|
17
|
+
// macOS uses U+2019 (right single quotation mark) in screenshot names like "Capture d'écran"
|
|
18
|
+
// Users typically type U+0027 (straight apostrophe)
|
|
19
|
+
return filePath.replace(/'/g, '\u2019');
|
|
20
|
+
}
|
|
21
|
+
function fileExists(filePath) {
|
|
22
|
+
try {
|
|
23
|
+
accessSync(filePath, constants.F_OK);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function normalizeAtPrefix(filePath) {
|
|
31
|
+
return filePath.startsWith('@') ? filePath.slice(1) : filePath;
|
|
32
|
+
}
|
|
33
|
+
export function expandPath(filePath) {
|
|
34
|
+
const normalized = normalizeUnicodeSpaces(normalizeAtPrefix(filePath));
|
|
35
|
+
if (normalized === '~') {
|
|
36
|
+
return os.homedir();
|
|
37
|
+
}
|
|
38
|
+
if (normalized.startsWith('~/')) {
|
|
39
|
+
return os.homedir() + normalized.slice(1);
|
|
40
|
+
}
|
|
41
|
+
return normalized;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Resolve a path relative to the given cwd.
|
|
45
|
+
* Handles ~ expansion and absolute paths.
|
|
46
|
+
*/
|
|
47
|
+
export function resolveToCwd(filePath, cwd) {
|
|
48
|
+
const expanded = expandPath(filePath);
|
|
49
|
+
if (isAbsolute(expanded)) {
|
|
50
|
+
return expanded;
|
|
51
|
+
}
|
|
52
|
+
return resolvePath(cwd, expanded);
|
|
53
|
+
}
|
|
54
|
+
export function resolveReadPath(filePath, cwd) {
|
|
55
|
+
const resolved = resolveToCwd(filePath, cwd);
|
|
56
|
+
if (fileExists(resolved)) {
|
|
57
|
+
return resolved;
|
|
58
|
+
}
|
|
59
|
+
// Try macOS AM/PM variant (narrow no-break space before AM/PM)
|
|
60
|
+
const amPmVariant = tryMacOSScreenshotPath(resolved);
|
|
61
|
+
if (amPmVariant !== resolved && fileExists(amPmVariant)) {
|
|
62
|
+
return amPmVariant;
|
|
63
|
+
}
|
|
64
|
+
// Try NFD variant (macOS stores filenames in NFD form)
|
|
65
|
+
const nfdVariant = tryNFDVariant(resolved);
|
|
66
|
+
if (nfdVariant !== resolved && fileExists(nfdVariant)) {
|
|
67
|
+
return nfdVariant;
|
|
68
|
+
}
|
|
69
|
+
// Try curly quote variant (macOS uses U+2019 in screenshot names)
|
|
70
|
+
const curlyVariant = tryCurlyQuoteVariant(resolved);
|
|
71
|
+
if (curlyVariant !== resolved && fileExists(curlyVariant)) {
|
|
72
|
+
return curlyVariant;
|
|
73
|
+
}
|
|
74
|
+
// Try combined NFD + curly quote (for French macOS screenshots like "Capture d'écran")
|
|
75
|
+
const nfdCurlyVariant = tryCurlyQuoteVariant(nfdVariant);
|
|
76
|
+
if (nfdCurlyVariant !== resolved && fileExists(nfdCurlyVariant)) {
|
|
77
|
+
return nfdCurlyVariant;
|
|
78
|
+
}
|
|
79
|
+
return resolved;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=path-utils.js.map
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Type } from '@sinclair/typebox';
|
|
2
|
+
import { ABORT_AGENT_MESSAGE } from '../abort.js';
|
|
3
|
+
import { constants } from 'fs';
|
|
4
|
+
import { access as fsAccess, readFile as fsReadFile } from 'fs/promises';
|
|
5
|
+
import { READ } from '../../tool-names.js';
|
|
6
|
+
import { formatDimensionNote, resizeImage } from '../../utils/image-resize.js';
|
|
7
|
+
import { detectSupportedImageMimeTypeFromFile } from '../../utils/mime.js';
|
|
8
|
+
import { resolveReadPath } from './path-utils.js';
|
|
9
|
+
import { DEFAULT_MAX_CHARS, formatSize, truncateHead } from './truncate.js';
|
|
10
|
+
const readSchema = Type.Object({
|
|
11
|
+
path: Type.String({ description: 'Path to the file to read (relative or absolute)' }),
|
|
12
|
+
offset: Type.Optional(Type.Number({ description: 'Line number to start reading from (1-indexed)' })),
|
|
13
|
+
limit: Type.Optional(Type.Number({ description: 'Maximum number of lines to read' }))
|
|
14
|
+
});
|
|
15
|
+
const defaultReadOperations = {
|
|
16
|
+
readFile: (path) => fsReadFile(path),
|
|
17
|
+
access: (path) => fsAccess(path, constants.R_OK),
|
|
18
|
+
detectImageMimeType: detectSupportedImageMimeTypeFromFile
|
|
19
|
+
};
|
|
20
|
+
export function createReadTool(cwd, options) {
|
|
21
|
+
const autoResizeImages = options?.autoResizeImages ?? true;
|
|
22
|
+
const ops = options?.operations ?? defaultReadOperations;
|
|
23
|
+
return {
|
|
24
|
+
name: READ,
|
|
25
|
+
label: READ,
|
|
26
|
+
description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_CHARS} characters. Use offset/limit for large files. When you need the full file, continue with offset until complete.`,
|
|
27
|
+
parameters: readSchema,
|
|
28
|
+
execute: async (_toolCallId, { path, offset, limit }, signal) => {
|
|
29
|
+
const absolutePath = resolveReadPath(path, cwd);
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
// Check if already aborted
|
|
32
|
+
if (signal?.aborted) {
|
|
33
|
+
reject(new Error(ABORT_AGENT_MESSAGE));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
let aborted = false;
|
|
37
|
+
// Set up abort handler
|
|
38
|
+
const onAbort = () => {
|
|
39
|
+
aborted = true;
|
|
40
|
+
reject(new Error(ABORT_AGENT_MESSAGE));
|
|
41
|
+
};
|
|
42
|
+
if (signal) {
|
|
43
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
44
|
+
}
|
|
45
|
+
// Perform the read operation
|
|
46
|
+
(async () => {
|
|
47
|
+
try {
|
|
48
|
+
// Check if file exists
|
|
49
|
+
await ops.access(absolutePath);
|
|
50
|
+
// Check if aborted before reading
|
|
51
|
+
if (aborted) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const mimeType = ops.detectImageMimeType
|
|
55
|
+
? await ops.detectImageMimeType(absolutePath)
|
|
56
|
+
: undefined;
|
|
57
|
+
// Read the file based on type
|
|
58
|
+
let content;
|
|
59
|
+
let details;
|
|
60
|
+
if (mimeType) {
|
|
61
|
+
// Read as image (binary)
|
|
62
|
+
const buffer = await ops.readFile(absolutePath);
|
|
63
|
+
const base64 = buffer.toString('base64');
|
|
64
|
+
if (autoResizeImages) {
|
|
65
|
+
// Resize image if needed
|
|
66
|
+
const resized = await resizeImage({ type: 'image', data: base64, mimeType });
|
|
67
|
+
const dimensionNote = formatDimensionNote(resized);
|
|
68
|
+
let textNote = `Read image file [${resized.mimeType}]`;
|
|
69
|
+
if (dimensionNote) {
|
|
70
|
+
textNote += `\n${dimensionNote}`;
|
|
71
|
+
}
|
|
72
|
+
content = [
|
|
73
|
+
{ type: 'text', text: textNote },
|
|
74
|
+
{ type: 'image', data: resized.data, mimeType: resized.mimeType }
|
|
75
|
+
];
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
const textNote = `Read image file [${mimeType}]`;
|
|
79
|
+
content = [
|
|
80
|
+
{ type: 'text', text: textNote },
|
|
81
|
+
{ type: 'image', data: base64, mimeType }
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// Read as text
|
|
87
|
+
const buffer = await ops.readFile(absolutePath);
|
|
88
|
+
const textContent = buffer.toString('utf-8');
|
|
89
|
+
const allLines = textContent.split('\n');
|
|
90
|
+
const totalFileLines = allLines.length;
|
|
91
|
+
// Apply offset if specified (1-indexed to 0-indexed)
|
|
92
|
+
const startLine = offset ? Math.max(0, offset - 1) : 0;
|
|
93
|
+
const startLineDisplay = startLine + 1; // For display (1-indexed)
|
|
94
|
+
// Check if offset is out of bounds
|
|
95
|
+
if (startLine >= allLines.length) {
|
|
96
|
+
throw new Error(`Offset ${offset} is beyond end of file (${allLines.length} lines total)`);
|
|
97
|
+
}
|
|
98
|
+
// If limit is specified by user, use it; otherwise we'll let truncateHead decide
|
|
99
|
+
let selectedContent;
|
|
100
|
+
let userLimitedLines;
|
|
101
|
+
if (limit !== undefined) {
|
|
102
|
+
const endLine = Math.min(startLine + limit, allLines.length);
|
|
103
|
+
selectedContent = allLines.slice(startLine, endLine).join('\n');
|
|
104
|
+
userLimitedLines = endLine - startLine;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
selectedContent = allLines.slice(startLine).join('\n');
|
|
108
|
+
}
|
|
109
|
+
// Apply truncation (respects both line and byte limits)
|
|
110
|
+
const truncation = truncateHead(selectedContent);
|
|
111
|
+
let outputText;
|
|
112
|
+
if (truncation.truncated) {
|
|
113
|
+
const outputLineCount = truncation.content.split('\n').length;
|
|
114
|
+
const endLineDisplay = startLineDisplay + outputLineCount - 1;
|
|
115
|
+
const nextOffset = endLineDisplay + 1;
|
|
116
|
+
outputText = truncation.content;
|
|
117
|
+
outputText += `\n\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_CHARS)} limit). Use offset=${nextOffset} to continue.]`;
|
|
118
|
+
details = { truncation };
|
|
119
|
+
}
|
|
120
|
+
else if (userLimitedLines !== undefined &&
|
|
121
|
+
startLine + userLimitedLines < allLines.length) {
|
|
122
|
+
// User specified limit, there's more content, but no truncation
|
|
123
|
+
const remaining = allLines.length - (startLine + userLimitedLines);
|
|
124
|
+
const nextOffset = startLine + userLimitedLines + 1;
|
|
125
|
+
outputText = truncation.content;
|
|
126
|
+
outputText += `\n\n[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// No truncation, no user limit exceeded
|
|
130
|
+
outputText = truncation.content;
|
|
131
|
+
}
|
|
132
|
+
content = [{ type: 'text', text: outputText }];
|
|
133
|
+
}
|
|
134
|
+
// Check if aborted after reading
|
|
135
|
+
if (aborted) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// Clean up abort handler
|
|
139
|
+
if (signal) {
|
|
140
|
+
signal.removeEventListener('abort', onAbort);
|
|
141
|
+
}
|
|
142
|
+
resolve({ content, details });
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
// Clean up abort handler
|
|
146
|
+
if (signal) {
|
|
147
|
+
signal.removeEventListener('abort', onAbort);
|
|
148
|
+
}
|
|
149
|
+
if (!aborted) {
|
|
150
|
+
reject(error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
})();
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/** Default read tool using process.cwd() - for backwards compatibility */
|
|
159
|
+
export const readTool = createReadTool(process.cwd());
|
|
160
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared truncation utilities for tool outputs.
|
|
3
|
+
*
|
|
4
|
+
* Single limit: character count (default 20,000 chars).
|
|
5
|
+
* Truncation always happens at line boundaries — never mid-line.
|
|
6
|
+
*/
|
|
7
|
+
export const DEFAULT_MAX_CHARS = 20_000;
|
|
8
|
+
export const GREP_MAX_LINE_LENGTH = 500; // Max chars per grep match line
|
|
9
|
+
export const ERROR_MAX_CHARS_UI = 200; // Max chars for error messages shown to user
|
|
10
|
+
export const ERROR_MAX_CHARS_LLM = 500; // Max chars for error messages sent to LLM context
|
|
11
|
+
/**
|
|
12
|
+
* Format character count as human-readable size.
|
|
13
|
+
*/
|
|
14
|
+
export function formatSize(chars) {
|
|
15
|
+
if (chars < 1000) {
|
|
16
|
+
return `${chars} chars`;
|
|
17
|
+
}
|
|
18
|
+
else if (chars < 1_000_000) {
|
|
19
|
+
return `${(chars / 1000).toFixed(1)}k chars`;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return `${(chars / 1_000_000).toFixed(1)}M chars`;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Truncate content from the head (keep first N chars).
|
|
27
|
+
* Cuts at the last complete line boundary before maxChars.
|
|
28
|
+
* If the first line alone exceeds maxChars, returns it hard-cut at maxChars.
|
|
29
|
+
*/
|
|
30
|
+
export function truncateHead(content, maxChars = DEFAULT_MAX_CHARS) {
|
|
31
|
+
const totalChars = content.length;
|
|
32
|
+
if (totalChars <= maxChars) {
|
|
33
|
+
return { content, truncated: false, totalChars, outputChars: totalChars, maxChars };
|
|
34
|
+
}
|
|
35
|
+
// Find the last newline before the limit
|
|
36
|
+
const cutPoint = content.lastIndexOf('\n', maxChars);
|
|
37
|
+
// If no newline found (single huge line), hard-cut at maxChars
|
|
38
|
+
const truncated = cutPoint > 0 ? content.slice(0, cutPoint) : content.slice(0, maxChars);
|
|
39
|
+
return {
|
|
40
|
+
content: truncated,
|
|
41
|
+
truncated: true,
|
|
42
|
+
totalChars,
|
|
43
|
+
outputChars: truncated.length,
|
|
44
|
+
maxChars
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Truncate content and return a single string with a notice appended if truncated.
|
|
49
|
+
* This is the main entry point for tool outputs going back to the LLM.
|
|
50
|
+
*
|
|
51
|
+
* Returns content as-is if no truncation needed, or:
|
|
52
|
+
* <truncated content>\n\n[Truncated: showing 5.0k of 50.0k chars]
|
|
53
|
+
*/
|
|
54
|
+
export function truncateOutput(content, maxChars = DEFAULT_MAX_CHARS) {
|
|
55
|
+
const result = truncateHead(content, maxChars);
|
|
56
|
+
if (!result.truncated)
|
|
57
|
+
return content;
|
|
58
|
+
return `${result.content}\n\n[Truncated: showing ${formatSize(result.outputChars)} of ${formatSize(result.totalChars)}]`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Truncate a single line to max characters, adding [truncated] suffix.
|
|
62
|
+
* Used for grep match lines.
|
|
63
|
+
*/
|
|
64
|
+
export function truncateLine(line, maxChars = GREP_MAX_LINE_LENGTH) {
|
|
65
|
+
if (line.length <= maxChars) {
|
|
66
|
+
return { text: line, wasTruncated: false };
|
|
67
|
+
}
|
|
68
|
+
return { text: `${line.slice(0, maxChars)}... [truncated]`, wasTruncated: true };
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=truncate.js.map
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Type } from '@sinclair/typebox';
|
|
2
|
+
import { mkdir as fsMkdir, writeFile as fsWriteFile } from 'fs/promises';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
import { ABORT_AGENT_MESSAGE } from '../abort.js';
|
|
5
|
+
import { WRITE } from '../../tool-names.js';
|
|
6
|
+
import { resolveToCwd } from './path-utils.js';
|
|
7
|
+
const writeSchema = Type.Object({
|
|
8
|
+
path: Type.String({ description: 'Path to the file to write (relative or absolute)' }),
|
|
9
|
+
content: Type.String({ description: 'Content to write to the file' })
|
|
10
|
+
});
|
|
11
|
+
const defaultWriteOperations = {
|
|
12
|
+
writeFile: (path, content) => fsWriteFile(path, content, 'utf-8'),
|
|
13
|
+
mkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => { })
|
|
14
|
+
};
|
|
15
|
+
export function createWriteTool(cwd, options) {
|
|
16
|
+
const ops = options?.operations ?? defaultWriteOperations;
|
|
17
|
+
return {
|
|
18
|
+
name: WRITE,
|
|
19
|
+
label: WRITE,
|
|
20
|
+
description: "Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",
|
|
21
|
+
parameters: writeSchema,
|
|
22
|
+
execute: async (_toolCallId, { path, content }, signal) => {
|
|
23
|
+
const absolutePath = resolveToCwd(path, cwd);
|
|
24
|
+
const dir = dirname(absolutePath);
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
// Check if already aborted
|
|
27
|
+
if (signal?.aborted) {
|
|
28
|
+
reject(new Error(ABORT_AGENT_MESSAGE));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
let aborted = false;
|
|
32
|
+
// Set up abort handler
|
|
33
|
+
const onAbort = () => {
|
|
34
|
+
aborted = true;
|
|
35
|
+
reject(new Error(ABORT_AGENT_MESSAGE));
|
|
36
|
+
};
|
|
37
|
+
if (signal) {
|
|
38
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
39
|
+
}
|
|
40
|
+
// Perform the write operation
|
|
41
|
+
(async () => {
|
|
42
|
+
try {
|
|
43
|
+
// Create parent directories if needed
|
|
44
|
+
await ops.mkdir(dir);
|
|
45
|
+
// Check if aborted before writing
|
|
46
|
+
if (aborted) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Write the file
|
|
50
|
+
await ops.writeFile(absolutePath, content);
|
|
51
|
+
// Check if aborted after writing
|
|
52
|
+
if (aborted) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// Clean up abort handler
|
|
56
|
+
if (signal) {
|
|
57
|
+
signal.removeEventListener('abort', onAbort);
|
|
58
|
+
}
|
|
59
|
+
resolve({
|
|
60
|
+
content: [
|
|
61
|
+
{ type: 'text', text: `Successfully wrote ${content.length} bytes to ${path}` }
|
|
62
|
+
],
|
|
63
|
+
details: undefined
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
// Clean up abort handler
|
|
68
|
+
if (signal) {
|
|
69
|
+
signal.removeEventListener('abort', onAbort);
|
|
70
|
+
}
|
|
71
|
+
if (!aborted) {
|
|
72
|
+
reject(error);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
})();
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** Default write tool using process.cwd() - for backwards compatibility */
|
|
81
|
+
export const writeTool = createWriteTool(process.cwd());
|
|
82
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BASH, EDIT, EXCEL_EXEC, GREP, READ, SWITCH_MODE, TASK, TODO_LIST, WRITE } from '../../tool-names.js';
|
|
2
|
+
import { buildActionPrompt } from '../prompts/action.js';
|
|
3
|
+
const ACTION_TOOLS = [READ, BASH, EDIT, WRITE, GREP, EXCEL_EXEC, TASK, TODO_LIST, SWITCH_MODE];
|
|
4
|
+
export function actionAgent() {
|
|
5
|
+
return {
|
|
6
|
+
name: 'action',
|
|
7
|
+
description: 'Normal agent mode with Excel superpowers',
|
|
8
|
+
systemPrompt: buildActionPrompt(),
|
|
9
|
+
tools: ACTION_TOOLS,
|
|
10
|
+
switchTo: ['installation']
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=action.js.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document reader subagent — extracts structured data from PDFs, images, and documents.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the backend's DocumentReaderSubagent but runs locally.
|
|
5
|
+
* Tools: bash (programmatic extraction) + llm_analysis (multimodal LLM).
|
|
6
|
+
*/
|
|
7
|
+
import { BASH, LLM_ANALYSIS } from '../../tool-names.js';
|
|
8
|
+
export const documentReaderAgent = {
|
|
9
|
+
name: 'document_reader',
|
|
10
|
+
description: `\
|
|
11
|
+
Extract structured data from PDFs, images, and documents with high accuracy.
|
|
12
|
+
Tools: bash (Python packages for programmatic extraction) and llm_analysis (multimodal LLM for visual/complex content).
|
|
13
|
+
Use for: PDF table extraction, financial statement parsing, image/chart analysis, document scanning, and data verification.
|
|
14
|
+
Prefers programmatic extraction for large structured data (>500 data points), multimodal LLMs for visual content and verification.`,
|
|
15
|
+
systemPrompt: `\
|
|
16
|
+
======================
|
|
17
|
+
DOCUMENT READER AGENT
|
|
18
|
+
======================
|
|
19
|
+
You extract structured data from files (PDFs, images, HTML, documents) with 100% accuracy as the goal.
|
|
20
|
+
You must extract values exactly as they appear in the source: preserve original formatting, spacing, and symbols.
|
|
21
|
+
|
|
22
|
+
WORKFLOW:
|
|
23
|
+
1. Scan the document structure first using llm_analysis to understand the layout, sections, and where key data lives.
|
|
24
|
+
2. For structured data (>500 data points): use programmatic extraction via bash (Python packages). This is fast, cheap, and deterministic.
|
|
25
|
+
3. For everything else (images, charts, complex layouts, scanned docs): use llm_analysis with multimodal LLMs.
|
|
26
|
+
4. Always sanity-check and verify extractions — use both methods and compare when accuracy is critical.
|
|
27
|
+
|
|
28
|
+
PROGRAMMATIC EXTRACTION (bash + Python):
|
|
29
|
+
- camelot: Default for tables. Returns pre-split DataFrame columns. Use flavor='stream' for borderless tables.
|
|
30
|
+
- pdftotext -layout: Cleanest column-aligned output (CLI tool).
|
|
31
|
+
- PyMuPDF (fitz): Fastest Python-native option. Use sort=True for layout-aware extraction.
|
|
32
|
+
- pdfplumber: Good table detection but loses internal spaces.
|
|
33
|
+
- Use multiple methods and compare results to minimize errors.
|
|
34
|
+
|
|
35
|
+
MULTIMODAL LLM EXTRACTION (llm_analysis):
|
|
36
|
+
- Slower and more expensive — use when programmatic extraction fails or visual understanding is required.
|
|
37
|
+
- Handles images, charts, tables, and complex visual layouts.
|
|
38
|
+
- For large PDFs, split into chunks <20 pages for best accuracy.
|
|
39
|
+
- Call llm_analysis multiple times concurrently for different sections.
|
|
40
|
+
- Models: gemini-3-flash-preview (best for images/tables), claude-haiku-4-5-20251001 (quick scanning).
|
|
41
|
+
|
|
42
|
+
PAGE SPLITTING:
|
|
43
|
+
- Use qpdf to split PDFs: qpdf "input.pdf" --pages . 1-10 -- "output.pdf"
|
|
44
|
+
- Always wrap file paths in double quotes.
|
|
45
|
+
- For filenames with $, use single quotes to prevent shell expansion.
|
|
46
|
+
|
|
47
|
+
LARGE FILE HANDLING:
|
|
48
|
+
- If llm_analysis fails due to file size, downsample via ghostscript: gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dBATCH -sOutputFile=output.pdf input.pdf
|
|
49
|
+
|
|
50
|
+
SEC FILINGS:
|
|
51
|
+
- Do NOT parse XBRL or use EdgarTools.
|
|
52
|
+
- Convert SEC filings to PDF first, then extract.
|
|
53
|
+
|
|
54
|
+
REFERENCING:
|
|
55
|
+
- Note page numbers, table/chart/section names above data sections.
|
|
56
|
+
- Use absolute page numbers (bottom-right of page images), NOT internal document numbering.
|
|
57
|
+
- Flag uncertainties, ambiguities, and conflicting data.
|
|
58
|
+
|
|
59
|
+
OUTPUT:
|
|
60
|
+
- Use pipe | as delimiter for structured data. Handle empty values as "| |".
|
|
61
|
+
- Large structured outputs (>500 entries): JSON format. Smaller/unstructured: markdown.
|
|
62
|
+
- Do NOT create summary, README, or "simplified" files.
|
|
63
|
+
- Do NOT consolidate data into a single file unless you can do it programmatically.
|
|
64
|
+
- Once data is extracted, list file paths and STOP.`,
|
|
65
|
+
tools: [BASH, LLM_ANALYSIS],
|
|
66
|
+
model: 'shortcut/claude-opus-4-6',
|
|
67
|
+
thinkingLevel: 'low',
|
|
68
|
+
timeoutSeconds: 900
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=document-reader.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* General-purpose subagent — research, computation, and Excel tasks.
|
|
3
|
+
*/
|
|
4
|
+
import { BASH, EXCEL_EXEC } from '../../tool-names.js';
|
|
5
|
+
export const generalAgent = {
|
|
6
|
+
name: 'general',
|
|
7
|
+
description: `\
|
|
8
|
+
General-purpose agent for research, computation, and Excel tasks.
|
|
9
|
+
Tools: bash (includes curl/wget for web) and excel_exec (Excel COM API via Python).
|
|
10
|
+
Use for: data analysis, web research, file manipulation, spreadsheet operations, multi-step computations.
|
|
11
|
+
Each agent can handle approximately 50 tool calls per task. Launch multiple concurrently for large workloads.`,
|
|
12
|
+
systemPrompt: `\
|
|
13
|
+
You are a general-purpose agent. You handle research, computation, data processing, and Excel tasks.
|
|
14
|
+
Use bash for computation, file processing, and fetching URLs (curl/wget).
|
|
15
|
+
Use excel_exec to read/write Excel workbooks via the COM API.
|
|
16
|
+
|
|
17
|
+
OUTPUT:
|
|
18
|
+
- Be concise and precise. Report findings directly.
|
|
19
|
+
- If you create files, list the file paths at the end.
|
|
20
|
+
- Do NOT create summary or README files unless asked.`,
|
|
21
|
+
tools: [BASH, EXCEL_EXEC],
|
|
22
|
+
model: 'shortcut/claude-opus-4-6',
|
|
23
|
+
thinkingLevel: 'low',
|
|
24
|
+
timeoutSeconds: 900
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=general.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent registry — single source of truth for all agent definitions.
|
|
3
|
+
*
|
|
4
|
+
* Both interactive modes (installation, action) and subagents (general)
|
|
5
|
+
* are defined here using the same AgentDefinition type.
|
|
6
|
+
*
|
|
7
|
+
* To add a new agent:
|
|
8
|
+
* 1. Create a new file in this directory
|
|
9
|
+
* 2. Define and export an AgentDefinition
|
|
10
|
+
* 3. Import it here and add to the appropriate array
|
|
11
|
+
*/
|
|
12
|
+
export { actionAgent } from './action.js';
|
|
13
|
+
export { installationAgent } from './installation.js';
|
|
14
|
+
import { documentReaderAgent } from './document-reader.js';
|
|
15
|
+
import { generalAgent } from './general.js';
|
|
16
|
+
/** All subagent definitions (used internally by accessor functions below) */
|
|
17
|
+
const SUBAGENTS = [documentReaderAgent, generalAgent];
|
|
18
|
+
/** Get a subagent config by name */
|
|
19
|
+
export function getSubagent(name) {
|
|
20
|
+
return SUBAGENTS.find((a) => a.name === name);
|
|
21
|
+
}
|
|
22
|
+
/** Get all subagent names (for task tool enum) */
|
|
23
|
+
export function getSubagentNames() {
|
|
24
|
+
return SUBAGENTS.map((a) => a.name);
|
|
25
|
+
}
|
|
26
|
+
/** Build the task tool description from the subagent registry */
|
|
27
|
+
export function buildTaskToolDescription() {
|
|
28
|
+
const preamble = `\
|
|
29
|
+
Launch a subagent to handle a complex task autonomously. Each subagent runs in its own context window with its own set of tools (see descriptions below).
|
|
30
|
+
|
|
31
|
+
Task queries should be self-contained, clear, and concise. The subagent CANNOT see your conversation history.
|
|
32
|
+
Include file paths, sheet names, cell ranges, and specific instructions in the query.
|
|
33
|
+
|
|
34
|
+
When multiple tasks are needed, launch them concurrently. NEVER call them sequentially — each agent takes time to complete.
|
|
35
|
+
|
|
36
|
+
Choose the subagent_type carefully based on the task:
|
|
37
|
+
- document_reader: PDFs, images, document extraction (has llm_analysis for multimodal + bash for programmatic extraction)
|
|
38
|
+
- general: research, computation, Excel tasks (has excel_exec + bash)`;
|
|
39
|
+
const lines = [preamble];
|
|
40
|
+
for (const agent of SUBAGENTS) {
|
|
41
|
+
lines.push('');
|
|
42
|
+
lines.push('================');
|
|
43
|
+
lines.push(agent.name);
|
|
44
|
+
lines.push('================');
|
|
45
|
+
lines.push(agent.description.trim());
|
|
46
|
+
}
|
|
47
|
+
return lines.join('\n');
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BASH, EDIT, EXCEL_EXEC, GREP, READ, SWITCH_MODE, WRITE } from '../../tool-names.js';
|
|
2
|
+
import { buildInstallationPrompt } from '../prompts/installation.js';
|
|
3
|
+
const INSTALLATION_TOOLS = [READ, BASH, EDIT, WRITE, GREP, EXCEL_EXEC, SWITCH_MODE];
|
|
4
|
+
export function installationAgent() {
|
|
5
|
+
return {
|
|
6
|
+
name: 'installation',
|
|
7
|
+
description: 'First-time setup for ShortcutXL',
|
|
8
|
+
systemPrompt: buildInstallationPrompt(),
|
|
9
|
+
tools: INSTALLATION_TOOLS,
|
|
10
|
+
switchTo: ['action']
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=installation.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proactive OAuth token refresh timer.
|
|
3
|
+
*
|
|
4
|
+
* Web clients use BaseTokenManager.scheduleRefresh() to refresh tokens before
|
|
5
|
+
* they expire. The agent has no equivalent — it only refreshes reactively when
|
|
6
|
+
* getApiKey() is called. If the TUI is idle, the token expires silently.
|
|
7
|
+
*
|
|
8
|
+
* This module adds a simple timer that calls getApiKey() periodically to
|
|
9
|
+
* trigger the reactive refresh logic in AuthStorage before the token expires.
|
|
10
|
+
*/
|
|
11
|
+
const REFRESH_INTERVAL_MS = 60 * 1000; // Check every 60 seconds
|
|
12
|
+
let timer = null;
|
|
13
|
+
/**
|
|
14
|
+
* Start a background timer that keeps OAuth tokens fresh.
|
|
15
|
+
* Calls authStorage.getApiKey() periodically, which triggers refresh
|
|
16
|
+
* when the token is within the buffer window of expiry.
|
|
17
|
+
*/
|
|
18
|
+
export function startProactiveRefresh(authStorage, providerId) {
|
|
19
|
+
stopProactiveRefresh();
|
|
20
|
+
timer = setInterval(() => {
|
|
21
|
+
// Fire-and-forget — getApiKey() handles refresh internally
|
|
22
|
+
void authStorage.getApiKey(providerId);
|
|
23
|
+
}, REFRESH_INTERVAL_MS);
|
|
24
|
+
// Don't block process exit
|
|
25
|
+
timer.unref();
|
|
26
|
+
}
|
|
27
|
+
function stopProactiveRefresh() {
|
|
28
|
+
if (timer) {
|
|
29
|
+
clearInterval(timer);
|
|
30
|
+
timer = null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=refresh-timer.js.map
|