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,238 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { basename, join } from 'path';
|
|
3
|
+
import { APP_NAME, getExportTemplateDir } from '../../config.js';
|
|
4
|
+
import { CORE_TOOL_NAMES } from '../../tool-names.js';
|
|
5
|
+
import { convertToLlm } from '../messages.js';
|
|
6
|
+
import { SessionManager, buildSessionContext } from '../session-manager.js';
|
|
7
|
+
import { getResolvedThemeColors, getThemeExportColors } from '../theme.js';
|
|
8
|
+
/** Parse a color string to RGB values. Supports hex (#RRGGBB) and rgb(r,g,b) formats. */
|
|
9
|
+
function parseColor(color) {
|
|
10
|
+
const hexMatch = color.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);
|
|
11
|
+
if (hexMatch) {
|
|
12
|
+
return {
|
|
13
|
+
r: Number.parseInt(hexMatch[1], 16),
|
|
14
|
+
g: Number.parseInt(hexMatch[2], 16),
|
|
15
|
+
b: Number.parseInt(hexMatch[3], 16)
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const rgbMatch = color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/);
|
|
19
|
+
if (rgbMatch) {
|
|
20
|
+
return {
|
|
21
|
+
r: Number.parseInt(rgbMatch[1], 10),
|
|
22
|
+
g: Number.parseInt(rgbMatch[2], 10),
|
|
23
|
+
b: Number.parseInt(rgbMatch[3], 10)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
/** Calculate relative luminance of a color (0-1, higher = lighter). */
|
|
29
|
+
function getLuminance(r, g, b) {
|
|
30
|
+
const toLinear = (c) => {
|
|
31
|
+
const s = c / 255;
|
|
32
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
33
|
+
};
|
|
34
|
+
return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
|
|
35
|
+
}
|
|
36
|
+
/** Adjust color brightness. Factor > 1 lightens, < 1 darkens. */
|
|
37
|
+
function adjustBrightness(color, factor) {
|
|
38
|
+
const parsed = parseColor(color);
|
|
39
|
+
if (!parsed)
|
|
40
|
+
return color;
|
|
41
|
+
const adjust = (c) => Math.min(255, Math.max(0, Math.round(c * factor)));
|
|
42
|
+
return `rgb(${adjust(parsed.r)}, ${adjust(parsed.g)}, ${adjust(parsed.b)})`;
|
|
43
|
+
}
|
|
44
|
+
/** Derive export background colors from a base color (e.g., userMessageBg). */
|
|
45
|
+
function deriveExportColors(baseColor) {
|
|
46
|
+
const parsed = parseColor(baseColor);
|
|
47
|
+
if (!parsed) {
|
|
48
|
+
return {
|
|
49
|
+
pageBg: 'rgb(24, 24, 30)',
|
|
50
|
+
cardBg: 'rgb(30, 30, 36)',
|
|
51
|
+
infoBg: 'rgb(60, 55, 40)'
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const luminance = getLuminance(parsed.r, parsed.g, parsed.b);
|
|
55
|
+
const isLight = luminance > 0.5;
|
|
56
|
+
if (isLight) {
|
|
57
|
+
return {
|
|
58
|
+
pageBg: adjustBrightness(baseColor, 0.96),
|
|
59
|
+
cardBg: baseColor,
|
|
60
|
+
infoBg: `rgb(${Math.min(255, parsed.r + 10)}, ${Math.min(255, parsed.g + 5)}, ${Math.max(0, parsed.b - 20)})`
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
pageBg: adjustBrightness(baseColor, 0.7),
|
|
65
|
+
cardBg: adjustBrightness(baseColor, 0.85),
|
|
66
|
+
infoBg: `rgb(${Math.min(255, parsed.r + 20)}, ${Math.min(255, parsed.g + 15)}, ${parsed.b})`
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Generate CSS custom property declarations from theme colors.
|
|
71
|
+
*/
|
|
72
|
+
function generateThemeVars(themeName) {
|
|
73
|
+
const colors = getResolvedThemeColors(themeName);
|
|
74
|
+
const lines = [];
|
|
75
|
+
for (const [key, value] of Object.entries(colors)) {
|
|
76
|
+
lines.push(`--${key}: ${value};`);
|
|
77
|
+
}
|
|
78
|
+
// Use explicit theme export colors if available, otherwise derive from userMessageBg
|
|
79
|
+
const themeExport = getThemeExportColors(themeName);
|
|
80
|
+
const userMessageBg = colors.userMessageBg || '#343541';
|
|
81
|
+
const derivedColors = deriveExportColors(userMessageBg);
|
|
82
|
+
lines.push(`--exportPageBg: ${themeExport.pageBg ?? derivedColors.pageBg};`);
|
|
83
|
+
lines.push(`--exportCardBg: ${themeExport.cardBg ?? derivedColors.cardBg};`);
|
|
84
|
+
lines.push(`--exportInfoBg: ${themeExport.infoBg ?? derivedColors.infoBg};`);
|
|
85
|
+
return lines.join('\n ');
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Build the LLM message array for export, annotated with source info.
|
|
89
|
+
* Runs buildSessionContext → convertToLlm (the real pipeline) and tags each
|
|
90
|
+
* output message with the original AgentMessage role so the HTML can show
|
|
91
|
+
* where it came from (e.g. bashExecution → user, compactionSummary → user).
|
|
92
|
+
*/
|
|
93
|
+
function buildAnnotatedLlmMessages(entries, leafId) {
|
|
94
|
+
const { messages: agentMessages } = buildSessionContext(entries, leafId ?? undefined);
|
|
95
|
+
const llmMessages = convertToLlm(agentMessages);
|
|
96
|
+
// Annotate each message with its original AgentMessage role.
|
|
97
|
+
// We walk both arrays in lockstep. convertToLlm maps each non-filtered
|
|
98
|
+
// AgentMessage to one Message (same order). The agent loop already
|
|
99
|
+
// synthesizes toolResults for aborted/errored assistant messages, so
|
|
100
|
+
// orphaned tool calls should not appear here.
|
|
101
|
+
//
|
|
102
|
+
// For robustness, we use a simple heuristic: maintain an index into the
|
|
103
|
+
// agent messages and advance it for each LLM message that matches the
|
|
104
|
+
// expected role. Unmatched messages are tagged as synthetic.
|
|
105
|
+
const annotated = [];
|
|
106
|
+
let agentIdx = 0;
|
|
107
|
+
for (const msg of llmMessages) {
|
|
108
|
+
// Skip filtered agent messages to stay in sync
|
|
109
|
+
while (agentIdx < agentMessages.length &&
|
|
110
|
+
agentMessages[agentIdx].role === 'bashExecution' &&
|
|
111
|
+
agentMessages[agentIdx].excludeFromContext) {
|
|
112
|
+
agentIdx++;
|
|
113
|
+
}
|
|
114
|
+
if (agentIdx < agentMessages.length) {
|
|
115
|
+
const agentMsg = agentMessages[agentIdx];
|
|
116
|
+
const source = agentMsg.role === 'custom'
|
|
117
|
+
? 'custom:' + (agentMsg.customType || '')
|
|
118
|
+
: agentMsg.role;
|
|
119
|
+
annotated.push({ ...msg, _source: source });
|
|
120
|
+
agentIdx++;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
annotated.push({ ...msg, _source: 'synthetic' });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return annotated;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Core HTML generation logic shared by both export functions.
|
|
130
|
+
*/
|
|
131
|
+
function generateHtml(sessionData, themeName, title) {
|
|
132
|
+
const templateDir = getExportTemplateDir();
|
|
133
|
+
const template = readFileSync(join(templateDir, 'template.html'), 'utf-8');
|
|
134
|
+
const templateCss = readFileSync(join(templateDir, 'template.css'), 'utf-8');
|
|
135
|
+
const templateJs = readFileSync(join(templateDir, 'template.js'), 'utf-8');
|
|
136
|
+
const markedJs = readFileSync(join(templateDir, 'vendor', 'marked.min.js'), 'utf-8');
|
|
137
|
+
const hljsJs = readFileSync(join(templateDir, 'vendor', 'highlight.min.js'), 'utf-8');
|
|
138
|
+
const themeVars = generateThemeVars(themeName);
|
|
139
|
+
const colors = getResolvedThemeColors(themeName);
|
|
140
|
+
const exportColors = deriveExportColors(colors.userMessageBg || '#343541');
|
|
141
|
+
const bodyBg = exportColors.pageBg;
|
|
142
|
+
const containerBg = exportColors.cardBg;
|
|
143
|
+
const infoBg = exportColors.infoBg;
|
|
144
|
+
// Base64 encode session data to avoid escaping issues
|
|
145
|
+
const sessionDataBase64 = Buffer.from(JSON.stringify(sessionData)).toString('base64');
|
|
146
|
+
// Build the CSS with theme variables injected
|
|
147
|
+
const css = templateCss
|
|
148
|
+
.replace('{{THEME_VARS}}', themeVars)
|
|
149
|
+
.replace('{{BODY_BG}}', bodyBg)
|
|
150
|
+
.replace('{{CONTAINER_BG}}', containerBg)
|
|
151
|
+
.replace('{{INFO_BG}}', infoBg);
|
|
152
|
+
// Use function replacements to avoid $ special patterns in replacement strings
|
|
153
|
+
// (highlight.min.js contains $& and $' which String.replace interprets specially)
|
|
154
|
+
return template
|
|
155
|
+
.replace('{{TITLE}}', title || 'Session Export')
|
|
156
|
+
.replace('{{CSS}}', () => css)
|
|
157
|
+
.replace('{{JS}}', () => templateJs)
|
|
158
|
+
.replace('{{SESSION_DATA}}', () => sessionDataBase64)
|
|
159
|
+
.replace('{{MARKED_JS}}', () => markedJs)
|
|
160
|
+
.replace('{{HIGHLIGHT_JS}}', () => hljsJs);
|
|
161
|
+
}
|
|
162
|
+
/** Built-in tool names that have custom rendering in template.js */
|
|
163
|
+
const BUILTIN_TOOLS = CORE_TOOL_NAMES;
|
|
164
|
+
/**
|
|
165
|
+
* Pre-render custom tools to HTML using their TUI renderers.
|
|
166
|
+
*/
|
|
167
|
+
function preRenderCustomTools(entries, toolRenderer) {
|
|
168
|
+
const renderedTools = {};
|
|
169
|
+
for (const entry of entries) {
|
|
170
|
+
if (entry.type !== 'message')
|
|
171
|
+
continue;
|
|
172
|
+
const msg = entry.message;
|
|
173
|
+
// Find tool calls in assistant messages
|
|
174
|
+
if (msg.role === 'assistant' && Array.isArray(msg.content)) {
|
|
175
|
+
for (const block of msg.content) {
|
|
176
|
+
if (block.type === 'toolCall' && !BUILTIN_TOOLS.has(block.name)) {
|
|
177
|
+
const callHtml = toolRenderer.renderCall(block.name, block.arguments);
|
|
178
|
+
if (callHtml) {
|
|
179
|
+
renderedTools[block.id] = { callHtml };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// Find tool results
|
|
185
|
+
if (msg.role === 'toolResult' && msg.toolCallId) {
|
|
186
|
+
const toolName = msg.toolName || '';
|
|
187
|
+
// Only render if we have a pre-rendered call OR it's not a built-in tool
|
|
188
|
+
const existing = renderedTools[msg.toolCallId];
|
|
189
|
+
if (existing || !BUILTIN_TOOLS.has(toolName)) {
|
|
190
|
+
const resultHtml = toolRenderer.renderResult(toolName, msg.content, msg.details, msg.isError || false);
|
|
191
|
+
if (resultHtml) {
|
|
192
|
+
renderedTools[msg.toolCallId] = {
|
|
193
|
+
...existing,
|
|
194
|
+
resultHtml
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return renderedTools;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Export session JSONL to HTML. Single export path — everything comes from the JSONL
|
|
204
|
+
* (system prompt, tool definitions, messages). Optional toolRenderer for custom tool HTML.
|
|
205
|
+
*/
|
|
206
|
+
export async function exportFromFile(inputPath, options) {
|
|
207
|
+
const opts = typeof options === 'string' ? { outputPath: options } : options || {};
|
|
208
|
+
if (!existsSync(inputPath)) {
|
|
209
|
+
throw new Error(`File not found: ${inputPath}`);
|
|
210
|
+
}
|
|
211
|
+
const sm = SessionManager.open(inputPath);
|
|
212
|
+
const entries = sm.getEntries();
|
|
213
|
+
const leafId = sm.getLeafId();
|
|
214
|
+
// Pre-render custom tools if a tool renderer is provided
|
|
215
|
+
let renderedTools;
|
|
216
|
+
if (opts.toolRenderer) {
|
|
217
|
+
renderedTools = preRenderCustomTools(entries, opts.toolRenderer);
|
|
218
|
+
if (Object.keys(renderedTools).length === 0) {
|
|
219
|
+
renderedTools = undefined;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const sessionData = {
|
|
223
|
+
header: sm.getHeader(),
|
|
224
|
+
entries,
|
|
225
|
+
leafId,
|
|
226
|
+
renderedTools,
|
|
227
|
+
llmMessages: buildAnnotatedLlmMessages(entries, leafId)
|
|
228
|
+
};
|
|
229
|
+
const html = generateHtml(sessionData, opts.themeName, opts.title);
|
|
230
|
+
let outputPath = opts.outputPath;
|
|
231
|
+
if (!outputPath) {
|
|
232
|
+
const inputBasename = basename(inputPath, '.jsonl');
|
|
233
|
+
outputPath = `${APP_NAME}-session-${inputBasename}.html`;
|
|
234
|
+
}
|
|
235
|
+
writeFileSync(outputPath, html, 'utf8');
|
|
236
|
+
return outputPath;
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure data transformations for session HTML export.
|
|
3
|
+
*
|
|
4
|
+
* This module takes raw session entries and produces view models
|
|
5
|
+
* consumed by template.js. All functions are pure — no DOM, no side effects.
|
|
6
|
+
*
|
|
7
|
+
* The boundary: session-manager.ts defines the JSONL schema (SessionEntry union),
|
|
8
|
+
* this module transforms it into renderable structures, and template.js handles DOM.
|
|
9
|
+
*/
|
|
10
|
+
/** Cast helper for entries that may include unknown types (custom, session_info, etc.) */
|
|
11
|
+
export function asEntry(raw) {
|
|
12
|
+
return raw;
|
|
13
|
+
}
|
|
14
|
+
function isMessage(entry) {
|
|
15
|
+
return entry.type === 'message';
|
|
16
|
+
}
|
|
17
|
+
/** All entry type discriminators that the renderer knows about. */
|
|
18
|
+
export const KNOWN_ENTRY_TYPES = [
|
|
19
|
+
'message',
|
|
20
|
+
'turn_start',
|
|
21
|
+
'turn_end',
|
|
22
|
+
'system_prompt',
|
|
23
|
+
'model_change',
|
|
24
|
+
'thinking_level_change',
|
|
25
|
+
'compaction',
|
|
26
|
+
'branch_summary',
|
|
27
|
+
'custom_message',
|
|
28
|
+
'label',
|
|
29
|
+
'custom',
|
|
30
|
+
'session_info',
|
|
31
|
+
'tool_definitions'
|
|
32
|
+
];
|
|
33
|
+
/** Build all indexes from raw entries. O(n) per index. */
|
|
34
|
+
export function buildIndexes(entries) {
|
|
35
|
+
const byId = new Map();
|
|
36
|
+
for (const entry of entries) {
|
|
37
|
+
byId.set(entry.id, entry);
|
|
38
|
+
}
|
|
39
|
+
const toolCallMap = new Map();
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
if (isMessage(entry) && entry.message.role === 'assistant') {
|
|
42
|
+
const content = entry.message.content;
|
|
43
|
+
if (Array.isArray(content)) {
|
|
44
|
+
for (const block of content) {
|
|
45
|
+
if (block.type === 'toolCall') {
|
|
46
|
+
toolCallMap.set(block.id, { name: block.name, arguments: block.arguments });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const labelMap = new Map();
|
|
53
|
+
for (const entry of entries) {
|
|
54
|
+
if (entry.type === 'label' && entry.targetId && entry.label) {
|
|
55
|
+
labelMap.set(entry.targetId, entry.label);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Build turn_start → turn_end map, then map first-message-after-turn → turn info
|
|
59
|
+
const turnEndByStartId = new Map();
|
|
60
|
+
for (const entry of entries) {
|
|
61
|
+
if (entry.type === 'turn_end') {
|
|
62
|
+
let current = byId.get(entry.parentId ?? '');
|
|
63
|
+
while (current) {
|
|
64
|
+
if (current.type === 'turn_start') {
|
|
65
|
+
turnEndByStartId.set(current.id, entry);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
if (!current.parentId || current.parentId === current.id)
|
|
69
|
+
break;
|
|
70
|
+
current = byId.get(current.parentId);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const turnInfoByMessageId = new Map();
|
|
75
|
+
for (const entry of entries) {
|
|
76
|
+
if (entry.type === 'turn_start') {
|
|
77
|
+
for (const child of entries) {
|
|
78
|
+
if (child.parentId === entry.id && child.type === 'message') {
|
|
79
|
+
const turnEnd = turnEndByStartId.get(entry.id);
|
|
80
|
+
turnInfoByMessageId.set(child.id, {
|
|
81
|
+
turnIndex: entry.turnIndex,
|
|
82
|
+
durationMs: turnEnd?.durationMs
|
|
83
|
+
});
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { byId, toolCallMap, labelMap, turnInfoByMessageId };
|
|
90
|
+
}
|
|
91
|
+
/** Build tree from flat entries. */
|
|
92
|
+
export function buildTree(entries, labelMap) {
|
|
93
|
+
const nodeMap = new Map();
|
|
94
|
+
const roots = [];
|
|
95
|
+
for (const entry of entries) {
|
|
96
|
+
nodeMap.set(entry.id, {
|
|
97
|
+
entry,
|
|
98
|
+
children: [],
|
|
99
|
+
label: labelMap.get(entry.id)
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
for (const entry of entries) {
|
|
103
|
+
const node = nodeMap.get(entry.id);
|
|
104
|
+
if (entry.parentId === null || entry.parentId === undefined || entry.parentId === entry.id) {
|
|
105
|
+
roots.push(node);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const parent = nodeMap.get(entry.parentId);
|
|
109
|
+
if (parent) {
|
|
110
|
+
parent.children.push(node);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
roots.push(node);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function sortChildren(node) {
|
|
118
|
+
node.children.sort((a, b) => new Date(a.entry.timestamp).getTime() - new Date(b.entry.timestamp).getTime());
|
|
119
|
+
node.children.forEach(sortChildren);
|
|
120
|
+
}
|
|
121
|
+
roots.forEach(sortChildren);
|
|
122
|
+
return roots;
|
|
123
|
+
}
|
|
124
|
+
// ============================================================
|
|
125
|
+
// PATH
|
|
126
|
+
// ============================================================
|
|
127
|
+
/** Get path from root to target (the conversation thread). */
|
|
128
|
+
export function getPath(targetId, byId) {
|
|
129
|
+
const path = [];
|
|
130
|
+
let current = byId.get(targetId);
|
|
131
|
+
while (current) {
|
|
132
|
+
path.unshift(current);
|
|
133
|
+
if (!current.parentId || current.parentId === current.id)
|
|
134
|
+
break;
|
|
135
|
+
current = byId.get(current.parentId);
|
|
136
|
+
}
|
|
137
|
+
return path;
|
|
138
|
+
}
|
|
139
|
+
/** Build set of entry IDs on path from root to target. */
|
|
140
|
+
export function buildActivePathIds(targetId, byId) {
|
|
141
|
+
const ids = new Set();
|
|
142
|
+
let current = byId.get(targetId);
|
|
143
|
+
while (current) {
|
|
144
|
+
ids.add(current.id);
|
|
145
|
+
if (!current.parentId || current.parentId === current.id)
|
|
146
|
+
break;
|
|
147
|
+
current = byId.get(current.parentId);
|
|
148
|
+
}
|
|
149
|
+
return ids;
|
|
150
|
+
}
|
|
151
|
+
/** Find the tool result entry matching a tool call ID. */
|
|
152
|
+
export function findToolResult(toolCallId, entries) {
|
|
153
|
+
for (const entry of entries) {
|
|
154
|
+
if (isMessage(entry) && entry.message.role === 'toolResult') {
|
|
155
|
+
if (entry.message.toolCallId === toolCallId) {
|
|
156
|
+
return {
|
|
157
|
+
content: entry.message.content,
|
|
158
|
+
isError: entry.message.isError || false,
|
|
159
|
+
details: entry.message.details
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
/** Compute aggregate stats from a list of entries. */
|
|
167
|
+
export function computeStats(entryList) {
|
|
168
|
+
let userMessages = 0;
|
|
169
|
+
let assistantMessages = 0;
|
|
170
|
+
let toolResults = 0;
|
|
171
|
+
let customMessages = 0;
|
|
172
|
+
let compactions = 0;
|
|
173
|
+
let branchSummaries = 0;
|
|
174
|
+
let toolCalls = 0;
|
|
175
|
+
let turnCount = 0;
|
|
176
|
+
let totalDurationMs = 0;
|
|
177
|
+
let totalLlmDurationMs = 0;
|
|
178
|
+
let totalToolDurationMs = 0;
|
|
179
|
+
const tokens = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
180
|
+
const cost = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
181
|
+
const models = new Set();
|
|
182
|
+
for (const entry of entryList) {
|
|
183
|
+
if (entry.type === 'turn_end') {
|
|
184
|
+
turnCount++;
|
|
185
|
+
if (typeof entry.durationMs === 'number')
|
|
186
|
+
totalDurationMs += entry.durationMs;
|
|
187
|
+
}
|
|
188
|
+
if (isMessage(entry)) {
|
|
189
|
+
const msg = entry.message;
|
|
190
|
+
if (msg.role === 'user')
|
|
191
|
+
userMessages++;
|
|
192
|
+
if (msg.role === 'assistant') {
|
|
193
|
+
assistantMessages++;
|
|
194
|
+
if (msg.model) {
|
|
195
|
+
models.add(msg.provider ? `${msg.provider}/${msg.model}` : String(msg.model));
|
|
196
|
+
}
|
|
197
|
+
const usage = msg.usage;
|
|
198
|
+
if (usage) {
|
|
199
|
+
tokens.input += usage.input || 0;
|
|
200
|
+
tokens.output += usage.output || 0;
|
|
201
|
+
tokens.cacheRead += usage.cacheRead || 0;
|
|
202
|
+
tokens.cacheWrite += usage.cacheWrite || 0;
|
|
203
|
+
const usageCost = usage.cost;
|
|
204
|
+
if (usageCost) {
|
|
205
|
+
cost.input += usageCost.input || 0;
|
|
206
|
+
cost.output += usageCost.output || 0;
|
|
207
|
+
cost.cacheRead += usageCost.cacheRead || 0;
|
|
208
|
+
cost.cacheWrite += usageCost.cacheWrite || 0;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const content = msg.content;
|
|
212
|
+
if (Array.isArray(content)) {
|
|
213
|
+
toolCalls += content.filter((c) => c.type === 'toolCall').length;
|
|
214
|
+
}
|
|
215
|
+
if (typeof entry.durationMs === 'number')
|
|
216
|
+
totalLlmDurationMs += entry.durationMs;
|
|
217
|
+
}
|
|
218
|
+
if (msg.role === 'toolResult') {
|
|
219
|
+
toolResults++;
|
|
220
|
+
if (typeof entry.durationMs === 'number')
|
|
221
|
+
totalToolDurationMs += entry.durationMs;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else if (entry.type === 'compaction') {
|
|
225
|
+
compactions++;
|
|
226
|
+
}
|
|
227
|
+
else if (entry.type === 'branch_summary') {
|
|
228
|
+
branchSummaries++;
|
|
229
|
+
}
|
|
230
|
+
else if (entry.type === 'custom_message') {
|
|
231
|
+
customMessages++;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
userMessages,
|
|
236
|
+
assistantMessages,
|
|
237
|
+
toolResults,
|
|
238
|
+
customMessages,
|
|
239
|
+
compactions,
|
|
240
|
+
branchSummaries,
|
|
241
|
+
toolCalls,
|
|
242
|
+
turnCount,
|
|
243
|
+
totalDurationMs,
|
|
244
|
+
totalLlmDurationMs,
|
|
245
|
+
totalToolDurationMs,
|
|
246
|
+
tokens,
|
|
247
|
+
cost,
|
|
248
|
+
models: Array.from(models)
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
// ============================================================
|
|
252
|
+
// FORMATTING UTILITIES
|
|
253
|
+
// ============================================================
|
|
254
|
+
export function formatTokens(count) {
|
|
255
|
+
if (count >= 1_000_000)
|
|
256
|
+
return (count / 1_000_000).toFixed(1) + 'M';
|
|
257
|
+
if (count >= 1_000)
|
|
258
|
+
return (count / 1_000).toFixed(1) + 'k';
|
|
259
|
+
return String(count);
|
|
260
|
+
}
|
|
261
|
+
export function formatDuration(ms) {
|
|
262
|
+
if (ms < 1000)
|
|
263
|
+
return ms + 'ms';
|
|
264
|
+
const s = ms / 1000;
|
|
265
|
+
if (s < 60)
|
|
266
|
+
return s.toFixed(1) + 's';
|
|
267
|
+
const m = Math.floor(s / 60);
|
|
268
|
+
const rem = Math.round(s % 60);
|
|
269
|
+
return m + 'm' + (rem > 0 ? rem + 's' : '');
|
|
270
|
+
}
|
|
271
|
+
export function formatTimestamp(ts) {
|
|
272
|
+
if (!ts)
|
|
273
|
+
return '';
|
|
274
|
+
try {
|
|
275
|
+
return new Date(ts).toLocaleTimeString();
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
return '';
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/** Entry types considered "settings" — hidden in default filter mode. */
|
|
282
|
+
const SETTINGS_TYPES = new Set([
|
|
283
|
+
'label',
|
|
284
|
+
'custom',
|
|
285
|
+
'model_change',
|
|
286
|
+
'thinking_level_change',
|
|
287
|
+
'turn_start',
|
|
288
|
+
'turn_end',
|
|
289
|
+
'system_prompt',
|
|
290
|
+
'tool_definitions'
|
|
291
|
+
]);
|
|
292
|
+
export function hasTextContent(content) {
|
|
293
|
+
if (typeof content === 'string')
|
|
294
|
+
return content.trim().length > 0;
|
|
295
|
+
if (Array.isArray(content)) {
|
|
296
|
+
for (const c of content) {
|
|
297
|
+
if (c.type === 'text' && c.text && c.text.trim().length > 0)
|
|
298
|
+
return true;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
export function extractContent(content) {
|
|
304
|
+
if (typeof content === 'string')
|
|
305
|
+
return content;
|
|
306
|
+
if (Array.isArray(content)) {
|
|
307
|
+
return content
|
|
308
|
+
.filter((c) => c.type === 'text' && c.text)
|
|
309
|
+
.map((c) => c.text)
|
|
310
|
+
.join('');
|
|
311
|
+
}
|
|
312
|
+
return '';
|
|
313
|
+
}
|
|
314
|
+
/** Test whether an entry passes the current filter. */
|
|
315
|
+
export function passesFilter(item, mode, currentLeafId) {
|
|
316
|
+
const { entry, label } = item;
|
|
317
|
+
// Always show current leaf
|
|
318
|
+
if (entry.id === currentLeafId)
|
|
319
|
+
return true;
|
|
320
|
+
// Hide assistant messages with only tool calls (no text) unless error/aborted
|
|
321
|
+
if (isMessage(entry) && entry.message.role === 'assistant') {
|
|
322
|
+
const msg = entry.message;
|
|
323
|
+
const hasText = hasTextContent(msg.content);
|
|
324
|
+
const isErrorOrAborted = msg.stopReason && msg.stopReason !== 'stop' && msg.stopReason !== 'toolUse';
|
|
325
|
+
if (!hasText && !isErrorOrAborted)
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
const isSettings = SETTINGS_TYPES.has(entry.type);
|
|
329
|
+
switch (mode) {
|
|
330
|
+
case 'user-only':
|
|
331
|
+
return isMessage(entry) && entry.message.role === 'user';
|
|
332
|
+
case 'no-tools':
|
|
333
|
+
return !isSettings && !(isMessage(entry) && entry.message.role === 'toolResult');
|
|
334
|
+
case 'labeled-only':
|
|
335
|
+
return label !== undefined;
|
|
336
|
+
case 'all':
|
|
337
|
+
return true;
|
|
338
|
+
default: // 'default'
|
|
339
|
+
return !isSettings;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
//# sourceMappingURL=session-view-model.js.map
|