shortcutxl 0.3.76 → 0.3.78
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/BINARY-INVENTORY.json +813 -813
- package/CHANGELOG.md +14 -0
- package/dist/ai/models.d.ts +10 -6
- package/dist/ai/models.generated.d.ts +72 -0
- package/dist/ai/models.generated.js +33 -0
- package/dist/ai/models.js +36 -13
- package/dist/ai/providers/anthropic.d.ts +4 -2
- package/dist/ai/providers/anthropic.js +59 -29
- package/dist/ai/providers/azure-openai-responses.d.ts +2 -1
- package/dist/ai/providers/azure-openai-responses.js +4 -20
- package/dist/ai/providers/google-vertex.d.ts +8 -2
- package/dist/ai/providers/google-vertex.js +66 -54
- package/dist/ai/providers/google.js +15 -48
- package/dist/ai/providers/openai-completions.d.ts +4 -1
- package/dist/ai/providers/openai-completions.js +26 -10
- package/dist/ai/providers/openai-reasoning.d.ts +5 -0
- package/dist/ai/providers/openai-reasoning.js +13 -0
- package/dist/ai/providers/openai-responses-shared.js +1 -1
- package/dist/ai/providers/openai-responses.d.ts +6 -2
- package/dist/ai/providers/openai-responses.js +28 -23
- package/dist/ai/providers/simple-options.d.ts +2 -3
- package/dist/ai/providers/simple-options.js +4 -6
- package/dist/ai/types.d.ts +19 -2
- package/dist/app/agent-session-runtime-adapter.js +7 -6
- package/dist/app/agent-session.d.ts +0 -15
- package/dist/app/agent-session.js +0 -37
- package/dist/app/approvals/approval-errors.d.ts +15 -0
- package/dist/app/approvals/approval-errors.js +14 -0
- package/dist/app/approvals/runtime-approval-gates.d.ts +1 -2
- package/dist/app/approvals/tool-approval.d.ts +1 -0
- package/dist/app/approvals/tool-approval.js +11 -23
- package/dist/app/approvals/types.d.ts +0 -14
- package/dist/app/approvals/types.js +0 -2
- package/dist/app/background/tool-summaries.js +0 -2
- package/dist/app/extensions/slash-commands.js +1 -3
- package/dist/app/local/tools/execute-code/executor.d.ts +1 -1
- package/dist/app/local/tools/execute-code/executor.js +20 -10
- package/dist/app/local/tools/execute-code/tool.js +21 -2
- package/dist/app/modes/action/agent.js +4 -5
- package/dist/app/modes/ask/agent.js +4 -6
- package/dist/app/modes/index.js +20 -10
- package/dist/app/modes/installation/agent.js +4 -5
- package/dist/app/modes/manage/agent.js +3 -4
- package/dist/app/modes/manage/prompt.js +1 -2
- package/dist/app/modes/metadata.d.ts +31 -0
- package/dist/app/modes/metadata.js +35 -0
- package/dist/app/modes/plan/agent.js +5 -8
- package/dist/app/modes/plan/prompt.js +3 -3
- package/dist/app/permissions/runtime-approval-flow.d.ts +1 -5
- package/dist/app/permissions/runtime-approval-flow.js +0 -28
- package/dist/app/permissions/tool-gates.d.ts +2 -3
- package/dist/app/permissions/tool-gates.js +3 -81
- package/dist/app/prompts/com-api.js +1 -1
- package/dist/app/prompts/shared-guidelines.js +7 -3
- package/dist/app/providers/google-vertex-gateway.js +4 -51
- package/dist/app/providers/model-registry.d.ts +1 -0
- package/dist/app/providers/model-registry.js +39 -0
- package/dist/app/providers/model-resolver.js +10 -7
- package/dist/app/providers/register-shortcut-provider.js +6 -6
- package/dist/app/providers/shortcut-api-v2-transport.js +4 -0
- package/dist/app/providers/shortcut-llm-proxy-client.d.ts +2 -2
- package/dist/app/providers/shortcut-llm-proxy-client.js +1 -0
- package/dist/app/resources/package-manager.js +2 -123
- package/dist/app/resources/resource-patterns.d.ts +9 -0
- package/dist/app/resources/resource-patterns.js +120 -0
- package/dist/app/session/forked-agent.d.ts +2 -2
- package/dist/app/session/model-manager.js +3 -2
- package/dist/app/session/session-lifecycle.js +3 -2
- package/dist/app/session/session-models.d.ts +2 -0
- package/dist/app/session/session-models.js +14 -6
- package/dist/app/settings-manager.d.ts +3 -3
- package/dist/app/shared/tools/execute-code/mog.d.ts +3 -1
- package/dist/app/shared/tools/execute-code/mog.js +18 -2
- package/dist/app/tools/bash.js +3 -3
- package/dist/app/tools/execute-code/index.d.ts +1 -0
- package/dist/app/tools/execute-code/index.js +3 -1
- package/dist/app/tools/find-ignore-files.d.ts +3 -0
- package/dist/app/tools/find-ignore-files.js +33 -0
- package/dist/app/tools/find.js +2 -21
- package/dist/app/tools/llm-analysis.js +0 -2
- package/dist/app/tools/refresh-context.d.ts +1 -1
- package/dist/app/tools/session-settings/update-session-settings.js +2 -2
- package/dist/app/tools/switch-mode.js +2 -2
- package/dist/app/tools/take-screenshot.js +0 -2
- package/dist/app/tools/task/runner.js +1 -2
- package/dist/app/tools/task/task.d.ts +1 -3
- package/dist/app/tools/task/task.js +20 -40
- package/dist/app/tools/web-search.js +12 -2
- package/dist/autocomplete/core.d.ts +33 -0
- package/dist/autocomplete/core.js +113 -0
- package/dist/{tui → autocomplete}/fuzzy.d.ts +0 -1
- package/dist/{tui → autocomplete}/fuzzy.js +0 -1
- package/dist/{tui/autocomplete.d.ts → autocomplete/index.d.ts} +0 -1
- package/dist/{tui/autocomplete.js → autocomplete/index.js} +62 -158
- package/dist/cli/args.js +1 -1
- package/dist/cli/list-models.js +1 -1
- package/dist/cli.js +26227 -30480
- package/dist/constants.d.ts +0 -2
- package/dist/constants.js +0 -3
- package/dist/contracts/agent-session-store.d.ts +1 -1
- package/dist/contracts/agent-settings.d.ts +1 -0
- package/dist/contracts/agent-settings.js +2 -1
- package/dist/contracts/model-call.d.ts +1 -2
- package/dist/contracts/model-call.js +1 -2
- package/dist/contracts/model-stream.d.ts +1 -0
- package/dist/contracts/model-stream.js +1 -0
- package/dist/contracts/wire.d.ts +10 -7
- package/dist/contracts/wire.js +8 -0
- package/dist/core/agent-engine.js +1 -1
- package/dist/core/core-types.d.ts +1 -21
- package/dist/core/defaults.d.ts +1 -1
- package/dist/core/defaults.js +9 -1
- package/dist/core/prompts/agent-guidelines.d.ts +4 -5
- package/dist/core/prompts/agent-guidelines.js +28 -42
- package/dist/core/session-schema.d.ts +1 -1
- package/dist/embedded-agent/ai-invoke.d.ts +1 -2
- package/dist/embedded-agent/ai-invoke.js +2 -70
- package/dist/embedded-agent/anthropic-messages-transport.d.ts +4 -20
- package/dist/embedded-agent/anthropic-messages-transport.js +23 -786
- package/dist/embedded-agent/bootstrap.js +2 -2
- package/dist/embedded-agent/compose.js +8 -7
- package/dist/embedded-agent/gateway-base-url.d.ts +3 -0
- package/dist/embedded-agent/gateway-base-url.js +35 -0
- package/dist/embedded-agent/google-vertex-transport.d.ts +2 -11
- package/dist/embedded-agent/google-vertex-transport.js +20 -117
- package/dist/embedded-agent/host-runtime-options.d.ts +0 -8
- package/dist/embedded-agent/host-runtime-options.js +10 -2
- package/dist/embedded-agent/host-tools/invoke-llm/contract.d.ts +2 -2
- package/dist/embedded-agent/host-tools/invoke-llm/contract.js +4 -2
- package/dist/embedded-agent/host-tools/sandbox-llm/contract.d.ts +8 -3
- package/dist/embedded-agent/host-tools/sandbox-llm/contract.js +12 -8
- package/dist/embedded-agent/host-tools/sandbox-llm/index.d.ts +1 -1
- package/dist/embedded-agent/host-tools/sandbox-llm/index.js +1 -1
- package/dist/embedded-agent/host-tools/shared/index.d.ts +1 -1
- package/dist/embedded-agent/host-tools/shared/index.js +1 -1
- package/dist/embedded-agent/host-tools/shared/llm-stream-error.d.ts +7 -0
- package/dist/embedded-agent/host-tools/shared/llm-stream-error.js +10 -0
- package/dist/embedded-agent/host-tools/take-screenshot/contract.d.ts +0 -2
- package/dist/embedded-agent/host-tools/take-screenshot/contract.js +1 -3
- package/dist/embedded-agent/host-tools/take-screenshot/index.d.ts +1 -1
- package/dist/embedded-agent/host-tools/take-screenshot/index.js +1 -1
- package/dist/embedded-agent/host-tools/task/agents/clone.js +1 -2
- package/dist/embedded-agent/host-tools/task/contract.js +1 -1
- package/dist/embedded-agent/index.d.ts +3 -4
- package/dist/embedded-agent/index.js +2 -3
- package/dist/embedded-agent/model-selection.d.ts +0 -6
- package/dist/embedded-agent/model-selection.js +15 -8
- package/dist/embedded-agent/openai-completions-transport.d.ts +2 -11
- package/dist/embedded-agent/openai-completions-transport.js +20 -120
- package/dist/embedded-agent/openai-responses-transport.d.ts +2 -11
- package/dist/embedded-agent/openai-responses-transport.js +15 -170
- package/dist/embedded-agent/prompt/build.js +1 -2
- package/dist/embedded-agent/prompt/sections.d.ts +1 -1
- package/dist/embedded-agent/prompt/sections.js +2 -0
- package/dist/embedded-agent/provider-native-request.d.ts +29 -0
- package/dist/embedded-agent/provider-native-request.js +65 -0
- package/dist/embedded-agent/run-stats.d.ts +1 -1
- package/dist/embedded-agent/stream.d.ts +10 -96
- package/dist/embedded-agent/stream.js +31 -556
- package/dist/embedded-agent/suggestions.d.ts +1 -1
- package/dist/embedded-agent/suggestions.js +1 -1
- package/dist/embedded-agent/worker-bridge/host-client.d.ts +7 -0
- package/dist/embedded-agent/worker-bridge/host-client.js +15 -0
- package/dist/embedded-agent/worker-bridge/worker-port.js +17 -1
- package/dist/main.js +18 -14
- package/dist/rpc/index.d.ts +1 -1
- package/dist/rpc/rpc-approval-gates.js +1 -2
- package/dist/rpc/rpc-host.d.ts +4 -0
- package/dist/rpc/rpc-host.js +13 -24
- package/dist/rpc/rpc-types.d.ts +6 -17
- package/dist/shared/platform/open.d.ts +4 -1
- package/dist/shared/platform/open.js +14 -2
- package/dist/shell/approvals/runtime-approval-gates.js +1 -3
- package/dist/shell/components/selectors/model-selector.js +2 -1
- package/dist/shell/components/selectors/session-selector-search.js +1 -1
- package/dist/shell/components/selectors/thinking-selector.js +7 -6
- package/dist/shell/index.d.ts +0 -1
- package/dist/shell/index.js +0 -1
- package/dist/shell/interactive/interactive-mode-options.d.ts +10 -0
- package/dist/shell/interactive/interactive-mode.d.ts +6 -12
- package/dist/shell/interactive/interactive-mode.js +39 -158
- package/dist/shell/interactive/slash-commands.d.ts +0 -34
- package/dist/shell/interactive/slash-commands.js +0 -2
- package/dist/shell/links/local-file-link-input.d.ts +15 -0
- package/dist/shell/links/local-file-link-input.js +38 -0
- package/dist/shell/links/local-file-link.d.ts +7 -0
- package/dist/shell/links/local-file-link.js +35 -0
- package/dist/shell/links/local-file-opener.d.ts +16 -0
- package/dist/shell/links/local-file-opener.js +90 -0
- package/dist/shell/session-client.d.ts +0 -1
- package/dist/shell/session-client.js +0 -6
- package/dist/shell/status/update-check-scheduler.d.ts +30 -0
- package/dist/shell/status/update-check-scheduler.js +71 -0
- package/dist/shell/status/update-reminder-controller.d.ts +22 -0
- package/dist/shell/status/update-reminder-controller.js +40 -0
- package/dist/shell/status/update-reminder.d.ts +6 -0
- package/dist/shell/status/update-reminder.js +4 -0
- package/dist/shell/theme/dark.json +1 -2
- package/dist/shell/theme/light.json +1 -2
- package/dist/shell/theme/runtime.d.ts +2 -3
- package/dist/shell/theme/runtime.js +2 -6
- package/dist/shell/theme/theme-schema.json +1 -6
- package/dist/shortcut-model-catalog.d.ts +7 -2
- package/dist/shortcut-model-catalog.js +134 -10
- package/dist/startup/update-manager.d.ts +6 -6
- package/dist/startup/update-manager.js +23 -38
- package/dist/startup/update-prompt.d.ts +1 -0
- package/dist/startup/update-prompt.js +2 -2
- package/dist/tui/components/editor.d.ts +1 -1
- package/dist/tui/components/editor.js +1 -1
- package/dist/tui/components/markdown.js +15 -6
- package/dist/tui/components/settings-list.js +1 -1
- package/dist/tui/editor-component.d.ts +1 -1
- package/dist/tui/index.d.ts +7 -8
- package/dist/tui/index.js +7 -6
- package/dist/tui/tui.d.ts +2 -0
- package/dist/tui/tui.js +16 -1
- package/dist/tui/utils.d.ts +7 -0
- package/dist/tui/utils.js +58 -8
- package/native-app/main/index.js +3200 -48
- package/native-app/main/{photon_rs-SoVDgheu.js → photon_rs-XkYyYTVA.js} +2 -2
- package/native-app/package.json +1 -1
- package/native-app/preload/index.cjs +2 -0
- package/native-app/renderer/assets/{index-CFc-oZuS.js → index-B4jz6epR.js} +825 -155
- package/native-app/renderer/assets/{index-OhGE0UY4.css → index-C__g36ft.css} +412 -162
- package/native-app/renderer/assets/shortcutagent-DxFsGSkw.png +0 -0
- package/native-app/renderer/index.html +2 -2
- package/package.json +17 -3
- package/skills/add-custom-model/SKILL.md +52 -0
- package/user-docs/dist/index.html +1 -1
- package/user-docs/dist/shortcutxl-docs.pdf +0 -0
- package/xll/ShortcutXL.xll +0 -0
- package/xll/modules/shortcut_xl/_managed.py +26 -7
- package/xll/modules/shortcut_xl/_tracking.py +141 -251
- package/xll/modules/shortcut_xl/api/__init__.py +60 -0
- package/xll/modules/shortcut_xl/api/workbook.py +9 -1
- package/xll/modules/shortcut_xl/api/worksheet.py +4 -1
- package/xll/python/Lib/site-packages/httpx-0.28.1.dist-info/RECORD +1 -1
- package/xll/python/Lib/site-packages/idna-3.18.dist-info/RECORD +1 -1
- package/xll/python/Lib/site-packages/pip/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/build_env/__init__.py +25 -0
- package/xll/python/Lib/site-packages/pip/_internal/build_env/base.py +103 -0
- package/xll/python/Lib/site-packages/pip/_internal/build_env/installer.py +333 -0
- package/xll/python/Lib/site-packages/pip/_internal/build_env/noop.py +42 -0
- package/xll/python/Lib/site-packages/pip/_internal/build_env/venv.py +145 -0
- package/xll/python/Lib/site-packages/pip/_internal/build_env/virtual.py +139 -0
- package/xll/python/Lib/site-packages/pip/_internal/cache.py +4 -1
- package/xll/python/Lib/site-packages/pip/_internal/cli/autocompletion.py +4 -1
- package/xll/python/Lib/site-packages/pip/_internal/cli/base_command.py +11 -14
- package/xll/python/Lib/site-packages/pip/_internal/cli/cmdoptions.py +133 -22
- package/xll/python/Lib/site-packages/pip/_internal/cli/index_command.py +11 -6
- package/xll/python/Lib/site-packages/pip/_internal/cli/main.py +2 -1
- package/xll/python/Lib/site-packages/pip/_internal/cli/main_parser.py +1 -2
- package/xll/python/Lib/site-packages/pip/_internal/cli/parser.py +10 -2
- package/xll/python/Lib/site-packages/pip/_internal/cli/progress_bars.py +2 -2
- package/xll/python/Lib/site-packages/pip/_internal/cli/req_command.py +57 -25
- package/xll/python/Lib/site-packages/pip/_internal/cli/status_codes.py +1 -0
- package/xll/python/Lib/site-packages/pip/_internal/commands/cache.py +7 -6
- package/xll/python/Lib/site-packages/pip/_internal/commands/configuration.py +2 -1
- package/xll/python/Lib/site-packages/pip/_internal/commands/debug.py +4 -5
- package/xll/python/Lib/site-packages/pip/_internal/commands/download.py +4 -0
- package/xll/python/Lib/site-packages/pip/_internal/commands/freeze.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/commands/index.py +10 -3
- package/xll/python/Lib/site-packages/pip/_internal/commands/inspect.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/commands/install.py +6 -6
- package/xll/python/Lib/site-packages/pip/_internal/commands/list.py +11 -6
- package/xll/python/Lib/site-packages/pip/_internal/commands/lock.py +4 -6
- package/xll/python/Lib/site-packages/pip/_internal/commands/show.py +14 -8
- package/xll/python/Lib/site-packages/pip/_internal/commands/wheel.py +7 -1
- package/xll/python/Lib/site-packages/pip/_internal/configuration.py +2 -3
- package/xll/python/Lib/site-packages/pip/_internal/distributions/base.py +5 -3
- package/xll/python/Lib/site-packages/pip/_internal/distributions/installed.py +3 -2
- package/xll/python/Lib/site-packages/pip/_internal/distributions/sdist.py +45 -20
- package/xll/python/Lib/site-packages/pip/_internal/distributions/wheel.py +3 -2
- package/xll/python/Lib/site-packages/pip/_internal/exceptions.py +174 -0
- package/xll/python/Lib/site-packages/pip/_internal/index/collector.py +70 -48
- package/xll/python/Lib/site-packages/pip/_internal/index/package_finder.py +46 -7
- package/xll/python/Lib/site-packages/pip/_internal/index/sources.py +1 -2
- package/xll/python/Lib/site-packages/pip/_internal/locations/_sysconfig.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/locations/base.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/metadata/base.py +10 -5
- package/xll/python/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py +8 -3
- package/xll/python/Lib/site-packages/pip/_internal/models/candidate.py +5 -1
- package/xll/python/Lib/site-packages/pip/_internal/models/link.py +53 -13
- package/xll/python/Lib/site-packages/pip/_internal/network/auth.py +38 -21
- package/xll/python/Lib/site-packages/pip/_internal/network/cache.py +2 -2
- package/xll/python/Lib/site-packages/pip/_internal/network/download.py +58 -11
- package/xll/python/Lib/site-packages/pip/_internal/network/session.py +35 -40
- package/xll/python/Lib/site-packages/pip/_internal/network/utils.py +109 -1
- package/xll/python/Lib/site-packages/pip/_internal/operations/check.py +2 -3
- package/xll/python/Lib/site-packages/pip/_internal/operations/install/wheel.py +23 -18
- package/xll/python/Lib/site-packages/pip/_internal/operations/prepare.py +152 -7
- package/xll/python/Lib/site-packages/pip/_internal/req/__init__.py +2 -0
- package/xll/python/Lib/site-packages/pip/_internal/req/constructors.py +54 -69
- package/xll/python/Lib/site-packages/pip/_internal/req/req_file.py +6 -6
- package/xll/python/Lib/site-packages/pip/_internal/req/req_install.py +25 -21
- package/xll/python/Lib/site-packages/pip/_internal/req/req_uninstall.py +13 -8
- package/xll/python/Lib/site-packages/pip/_internal/resolution/base.py +2 -2
- package/xll/python/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py +2 -2
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py +0 -1
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py +39 -52
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py +3 -3
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py +3 -0
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py +9 -0
- package/xll/python/Lib/site-packages/pip/_internal/utils/compat.py +15 -9
- package/xll/python/Lib/site-packages/pip/_internal/utils/deprecation.py +6 -1
- package/xll/python/Lib/site-packages/pip/_internal/utils/filesystem.py +2 -2
- package/xll/python/Lib/site-packages/pip/_internal/utils/logging.py +11 -3
- package/xll/python/Lib/site-packages/pip/_internal/utils/misc.py +48 -4
- package/xll/python/Lib/site-packages/pip/_internal/utils/pylock.py +18 -2
- package/xll/python/Lib/site-packages/pip/_internal/utils/retry.py +2 -1
- package/xll/python/Lib/site-packages/pip/_internal/utils/subprocess.py +4 -3
- package/xll/python/Lib/site-packages/pip/_internal/utils/temp_dir.py +1 -2
- package/xll/python/Lib/site-packages/pip/_internal/utils/unpacking.py +30 -4
- package/xll/python/Lib/site-packages/pip/_internal/utils/urls.py +5 -2
- package/xll/python/Lib/site-packages/pip/_internal/utils/virtualenv.py +2 -36
- package/xll/python/Lib/site-packages/pip/_internal/vcs/git.py +8 -5
- package/xll/python/Lib/site-packages/pip/_internal/vcs/versioncontrol.py +1 -2
- package/xll/python/Lib/site-packages/pip/_internal/wheel_builder.py +5 -1
- package/xll/python/Lib/site-packages/pip/_vendor/bom.cdx.json +231 -0
- package/xll/python/Lib/site-packages/pip/_vendor/certifi/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/certifi/cacert.pem +0 -631
- package/xll/python/Lib/site-packages/pip/_vendor/distlib/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/distlib/compat.py +34 -64
- package/xll/python/Lib/site-packages/pip/_vendor/distlib/resources.py +28 -14
- package/xll/python/Lib/site-packages/pip/_vendor/distlib/scripts.py +7 -3
- package/xll/python/Lib/site-packages/pip/_vendor/distlib/util.py +48 -11
- package/xll/python/Lib/site-packages/pip/_vendor/idna/LICENSE.md +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/idna/__main__.py +6 -0
- package/xll/python/Lib/site-packages/pip/_vendor/idna/cli.py +128 -0
- package/xll/python/Lib/site-packages/pip/_vendor/idna/codec.py +50 -13
- package/xll/python/Lib/site-packages/pip/_vendor/idna/compat.py +26 -0
- package/xll/python/Lib/site-packages/pip/_vendor/idna/core.py +352 -141
- package/xll/python/Lib/site-packages/pip/_vendor/idna/idnadata.py +571 -2983
- package/xll/python/Lib/site-packages/pip/_vendor/idna/intranges.py +5 -7
- package/xll/python/Lib/site-packages/pip/_vendor/idna/package_data.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/idna/uts46data.py +16887 -8832
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/__init__.py +352 -66
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/__main__.py +11 -0
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/_xdg.py +171 -0
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/android.py +92 -41
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/api.py +213 -49
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/macos.py +128 -51
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/unix.py +176 -127
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/version.py +8 -18
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/windows.py +185 -68
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/__init__.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/__main__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/console.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/filter.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py +10 -8
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/formatter.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/lexer.py +7 -5
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py +9 -8
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/lexers/python.py +35 -32
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/modeline.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/plugin.py +3 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/regexopt.py +13 -2
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/scanner.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/sphinxext.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/style.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/token.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/unistring.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/util.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/requests/__init__.py +52 -16
- package/xll/python/Lib/site-packages/pip/_vendor/requests/__version__.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/requests/_internal_utils.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/requests/_types.py +183 -0
- package/xll/python/Lib/site-packages/pip/_vendor/requests/adapters.py +101 -50
- package/xll/python/Lib/site-packages/pip/_vendor/requests/api.py +31 -8
- package/xll/python/Lib/site-packages/pip/_vendor/requests/auth.py +80 -40
- package/xll/python/Lib/site-packages/pip/_vendor/requests/compat.py +9 -3
- package/xll/python/Lib/site-packages/pip/_vendor/requests/cookies.py +143 -79
- package/xll/python/Lib/site-packages/pip/_vendor/requests/exceptions.py +15 -5
- package/xll/python/Lib/site-packages/pip/_vendor/requests/help.py +13 -10
- package/xll/python/Lib/site-packages/pip/_vendor/requests/hooks.py +23 -9
- package/xll/python/Lib/site-packages/pip/_vendor/requests/models.py +265 -126
- package/xll/python/Lib/site-packages/pip/_vendor/requests/py.typed +0 -0
- package/xll/python/Lib/site-packages/pip/_vendor/requests/sessions.py +164 -78
- package/xll/python/Lib/site-packages/pip/_vendor/requests/status_codes.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/requests/structures.py +51 -20
- package/xll/python/Lib/site-packages/pip/_vendor/requests/utils.py +161 -89
- package/xll/python/Lib/site-packages/pip/_vendor/tomli/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/tomli/_parser.py +9 -4
- package/xll/python/Lib/site-packages/pip/_vendor/tomli/_re.py +13 -9
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/_base_connection.py +3 -1
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/_collections.py +0 -1
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/_version.py +8 -18
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/connection.py +4 -4
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py +23 -10
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/contrib/emscripten/response.py +5 -1
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py +7 -8
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/exceptions.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/fields.py +14 -14
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py +8 -6
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/response.py +35 -22
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/util/retry.py +8 -0
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py +11 -61
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py +5 -11
- package/xll/python/Lib/site-packages/pip/_vendor/vendor.txt +8 -8
- package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/METADATA +3 -2
- package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/RECORD +208 -188
- package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/AUTHORS.txt +20 -0
- package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/idna/LICENSE.md +1 -1
- package/xll/python/Lib/site-packages/pywin32-311.dist-info/RECORD +2 -2
- package/xll/python/Scripts/httpx.exe +0 -0
- package/xll/python/Scripts/idna.exe +0 -0
- package/xll/python/Scripts/pip.exe +0 -0
- package/xll/python/Scripts/pip3.13.exe +0 -0
- package/xll/python/Scripts/pip3.exe +0 -0
- package/xll/python/Scripts/pywin32_postinstall.exe +0 -0
- package/xll/python/Scripts/pywin32_testall.exe +0 -0
- package/dist/app/collab/awareness.d.ts +0 -32
- package/dist/app/collab/awareness.js +0 -52
- package/dist/app/collab/collab-client.d.ts +0 -37
- package/dist/app/collab/collab-client.js +0 -208
- package/dist/app/collab/collab-manager.d.ts +0 -91
- package/dist/app/collab/collab-manager.js +0 -218
- package/dist/app/collab/collab-sync.d.ts +0 -62
- package/dist/app/collab/collab-sync.js +0 -215
- package/dist/app/collab/index.d.ts +0 -9
- package/dist/app/collab/index.js +0 -6
- package/dist/app/collab/super-fight.d.ts +0 -90
- package/dist/app/collab/super-fight.js +0 -310
- package/dist/app/collab/sync-bridge.d.ts +0 -35
- package/dist/app/collab/sync-bridge.js +0 -109
- package/dist/app/collab/types.d.ts +0 -75
- package/dist/app/collab/types.js +0 -5
- package/dist/embedded-agent/ai-content.d.ts +0 -52
- package/dist/embedded-agent/ai-content.js +0 -101
- package/dist/embedded-agent/host-tools/shared/llm-stream.d.ts +0 -31
- package/dist/embedded-agent/host-tools/shared/llm-stream.js +0 -136
- package/dist/embedded-agent/model-call-orchestrator.d.ts +0 -22
- package/dist/embedded-agent/model-call-orchestrator.js +0 -22
- package/dist/embedded-agent/stream-errors.d.ts +0 -10
- package/dist/embedded-agent/stream-errors.js +0 -73
- package/dist/embedded-agent/stream-message-state.d.ts +0 -14
- package/dist/embedded-agent/stream-message-state.js +0 -271
- package/dist/embedded-agent/stream-sse.d.ts +0 -78
- package/dist/embedded-agent/stream-sse.js +0 -73
- package/dist/shell/approvals/task-spawn-approval.d.ts +0 -20
- package/dist/shell/approvals/task-spawn-approval.js +0 -93
- package/dist/shell/interactive/collab-command.d.ts +0 -9
- package/dist/shell/interactive/collab-command.js +0 -115
- package/dist/shell/interactive/super-fight-ui.d.ts +0 -80
- package/dist/shell/interactive/super-fight-ui.js +0 -484
- package/dist/shell/status/collab-status.d.ts +0 -18
- package/dist/shell/status/collab-status.js +0 -46
- package/xll/python/Lib/site-packages/pip/_internal/build_env.py +0 -606
- /package/dist/{tui → autocomplete}/skill-autocomplete.js +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/INSTALLER +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/REQUESTED +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/WHEEL +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/entry_points.txt +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/LICENSE.txt +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/certifi/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/distlib/LICENSE.txt +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/distro/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/msgpack/COPYING +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.BSD +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/pkg_resources/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/platformdirs/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/pygments/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/requests/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/resolvelib/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/rich/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/tomli/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/tomli_w/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/truststore/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/urllib3/LICENSE.txt +0 -0
|
Binary file
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Shortcut CLI</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-B4jz6epR.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="./assets/index-C__g36ft.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shortcutxl",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.78",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -33,6 +33,10 @@
|
|
|
33
33
|
"types": "./dist/app/file-uploads.d.ts",
|
|
34
34
|
"default": "./dist/app/file-uploads.js"
|
|
35
35
|
},
|
|
36
|
+
"./app/tool-binaries": {
|
|
37
|
+
"types": "./dist/app/tools/tool-binaries.d.ts",
|
|
38
|
+
"default": "./dist/app/tools/tool-binaries.js"
|
|
39
|
+
},
|
|
36
40
|
"./app/providers/message-converter": {
|
|
37
41
|
"types": "./dist/app/providers/message-converter.d.ts",
|
|
38
42
|
"default": "./dist/app/providers/message-converter.js"
|
|
@@ -145,6 +149,14 @@
|
|
|
145
149
|
"types": "./dist/tui/index.d.ts",
|
|
146
150
|
"default": "./dist/tui/index.js"
|
|
147
151
|
},
|
|
152
|
+
"./autocomplete": {
|
|
153
|
+
"types": "./dist/autocomplete/index.d.ts",
|
|
154
|
+
"default": "./dist/autocomplete/index.js"
|
|
155
|
+
},
|
|
156
|
+
"./autocomplete/core": {
|
|
157
|
+
"types": "./dist/autocomplete/core.d.ts",
|
|
158
|
+
"default": "./dist/autocomplete/core.js"
|
|
159
|
+
},
|
|
148
160
|
"./host-tools": {
|
|
149
161
|
"types": "./dist/embedded-agent/host-tools/index.d.ts",
|
|
150
162
|
"default": "./dist/embedded-agent/host-tools/index.js"
|
|
@@ -255,12 +267,11 @@
|
|
|
255
267
|
"electron": "42.6.1",
|
|
256
268
|
"extract-zip": "^2.0.1",
|
|
257
269
|
"file-type": "^21.3.1",
|
|
258
|
-
"glob": "^13.0.6",
|
|
259
270
|
"hosted-git-info": "^9.0.2",
|
|
260
271
|
"ignore": "^7.0.5",
|
|
261
272
|
"jose": "^6.2.2",
|
|
262
273
|
"marked": "^15.0.12",
|
|
263
|
-
"minimatch": "^10.2.
|
|
274
|
+
"minimatch": "^10.2.6",
|
|
264
275
|
"openai": "6.10.0",
|
|
265
276
|
"partial-json": "^0.1.7",
|
|
266
277
|
"proper-lockfile": "^4.1.2",
|
|
@@ -342,8 +353,11 @@
|
|
|
342
353
|
"test": "pnpm run build:mogruntime && vitest --run",
|
|
343
354
|
"dev:integration": "tsx tests/connectors/runner/run-agentic-integration.ts",
|
|
344
355
|
"test:e2e": "vitest --run --config vitest.e2e.config.ts",
|
|
356
|
+
"test:e2e:provider-native-agentic": "vitest --run --config vitest.e2e.config.ts tests/embedded-agent/provider-native-agentic",
|
|
345
357
|
"test:manual-smoke:whatsapp-live": "vitest --run --config vitest.e2e.config.ts tests/remote-control/whatsapp-cli.live-provider.manual-smoke.test.ts",
|
|
346
358
|
"test:pty": "vitest --run --config vitest.pty.config.ts",
|
|
359
|
+
"test:pty:windows-smoke": "vitest --run --config vitest.pty.config.ts tests/helpers/pty/driver.pty.test.ts",
|
|
360
|
+
"test:windows-approvals": "vitest --run --config vitest.windows-approvals.config.ts",
|
|
347
361
|
"test:tui-sim": "vitest --run --config vitest.tui-sim.config.ts",
|
|
348
362
|
"smoke:rpc": "node scripts/smoke-rpc-host.js",
|
|
349
363
|
"analyze:tui-trace": "node scripts/analyze-tui-render-trace.js",
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: add-custom-model
|
|
3
|
+
description: Add or update a custom model in ShortcutXL. Use when the user wants to connect a hosted model, local model, gateway, or proxy.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Add a Custom Model
|
|
7
|
+
|
|
8
|
+
Add the model to `~/.shortcut/agent/models.json`.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. Read `models.md` from the Agent Docs `Additional docs` path in the system prompt.
|
|
13
|
+
2. Get the following details from the user or the provider's documentation:
|
|
14
|
+
- Provider ID
|
|
15
|
+
- Base URL
|
|
16
|
+
- API type
|
|
17
|
+
- Model ID
|
|
18
|
+
- API key or API-key environment variable
|
|
19
|
+
3. Read the existing `models.json`. Preserve its current providers and models.
|
|
20
|
+
4. Add or update the requested provider and model.
|
|
21
|
+
5. Validate the JSON.
|
|
22
|
+
6. Open `/model` and select the new model. Opening `/model` reloads the file.
|
|
23
|
+
7. Test a response and a tool call.
|
|
24
|
+
|
|
25
|
+
Use one of these API types:
|
|
26
|
+
|
|
27
|
+
- `openai-completions`
|
|
28
|
+
- `openai-responses`
|
|
29
|
+
- `anthropic-messages`
|
|
30
|
+
- `google-generative-ai`
|
|
31
|
+
|
|
32
|
+
Use this minimal configuration:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"providers": {
|
|
37
|
+
"provider-id": {
|
|
38
|
+
"baseUrl": "https://provider.example/v1",
|
|
39
|
+
"api": "openai-completions",
|
|
40
|
+
"apiKey": "PROVIDER_API_KEY",
|
|
41
|
+
"models": [{ "id": "model-id" }]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Prefer an environment-variable name for `apiKey` and confirm that it is set.
|
|
48
|
+
For a local server without authentication, use a non-empty placeholder such as
|
|
49
|
+
`local`. Never expose an API key in the response.
|
|
50
|
+
|
|
51
|
+
If the provider does not support one of the listed APIs, it cannot be added
|
|
52
|
+
through `models.json`.
|
|
@@ -1908,7 +1908,7 @@ Excel automatically loads ShortcutXL on startup. No manual setup needed again.
|
|
|
1908
1908
|
npm update -g shortcutxl
|
|
1909
1909
|
```
|
|
1910
1910
|
|
|
1911
|
-
ShortcutXL
|
|
1911
|
+
ShortcutXL checks for updates asynchronously every 12 hours. When a new version is available, restart the CLI and choose **Update now** in the startup prompt. The Excel add-in auto-syncs with the agent — no separate update needed.
|
|
1912
1912
|
|
|
1913
1913
|
|
|
1914
1914
|
|
|
Binary file
|
package/xll/ShortcutXL.xll
CHANGED
|
Binary file
|
|
@@ -6,7 +6,8 @@ from shortcut_xl._com import xl_app
|
|
|
6
6
|
from shortcut_xl._exec_sandbox import active_exec_sandbox, build_safe_builtins
|
|
7
7
|
from shortcut_xl._log import xl_log
|
|
8
8
|
from shortcut_xl._threading import _run_on_main
|
|
9
|
-
from shortcut_xl._tracking import DirtyTracker
|
|
9
|
+
from shortcut_xl._tracking import DirtyTracker
|
|
10
|
+
from shortcut_xl.api import active_write_tracker
|
|
10
11
|
from shortcut_xl.api.format import format_cell_diff
|
|
11
12
|
from shortcut_xl.api.utils.helpers import (
|
|
12
13
|
address_to_index,
|
|
@@ -39,6 +40,24 @@ class EditModeError(Exception):
|
|
|
39
40
|
"""Raised when Excel is in cell edit mode at request start."""
|
|
40
41
|
|
|
41
42
|
|
|
43
|
+
class _ExcelAppProxy:
|
|
44
|
+
"""Transparent app facade whose module globals participate in the sandbox."""
|
|
45
|
+
|
|
46
|
+
__slots__ = ('_app',)
|
|
47
|
+
|
|
48
|
+
def __init__(self, app):
|
|
49
|
+
object.__setattr__(self, '_app', app)
|
|
50
|
+
|
|
51
|
+
def __getattr__(self, name):
|
|
52
|
+
return getattr(object.__getattribute__(self, '_app'), name)
|
|
53
|
+
|
|
54
|
+
def __setattr__(self, name, value):
|
|
55
|
+
setattr(object.__getattribute__(self, '_app'), name, value)
|
|
56
|
+
|
|
57
|
+
def __repr__(self):
|
|
58
|
+
return repr(object.__getattribute__(self, '_app'))
|
|
59
|
+
|
|
60
|
+
|
|
42
61
|
def _is_edit_mode_error(e):
|
|
43
62
|
"""Check if a COM exception is the Excel cell-edit-mode failure."""
|
|
44
63
|
if hasattr(e, 'hresult') and e.hresult == _EDIT_MODE_SCODE:
|
|
@@ -64,8 +83,8 @@ def run_managed(code_str):
|
|
|
64
83
|
"""Compile and execute user code on the main thread with Excel state managed.
|
|
65
84
|
|
|
66
85
|
Preserves Calculation/Iteration settings, disables Events/Alerts,
|
|
67
|
-
runs code with
|
|
68
|
-
restores Excel state.
|
|
86
|
+
runs code with range-scoped tracking for wrapped API writes, collects
|
|
87
|
+
dirty cells, then restores Excel state.
|
|
69
88
|
|
|
70
89
|
Returns the list of dirty cells. Caller (_exec_entry) is responsible
|
|
71
90
|
for CF highlighting, JSON response building, and stdout capture.
|
|
@@ -99,11 +118,11 @@ def run_managed(code_str):
|
|
|
99
118
|
try:
|
|
100
119
|
app.EnableEvents = False
|
|
101
120
|
app.DisplayAlerts = False
|
|
102
|
-
tracker = DirtyTracker(
|
|
103
|
-
|
|
121
|
+
tracker = DirtyTracker()
|
|
122
|
+
managed_app = _ExcelAppProxy(app)
|
|
104
123
|
safe_builtins = build_safe_builtins()
|
|
105
|
-
ns = {**_USER_GLOBALS, 'app':
|
|
106
|
-
with active_exec_sandbox(safe_builtins):
|
|
124
|
+
ns = {**_USER_GLOBALS, 'app': managed_app, '__builtins__': safe_builtins}
|
|
125
|
+
with active_write_tracker(tracker), active_exec_sandbox(safe_builtins):
|
|
107
126
|
exec(code, ns)
|
|
108
127
|
finally:
|
|
109
128
|
# Collect changes BEFORE restoring calc-related state so we only see
|
|
@@ -1,310 +1,200 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Range-scoped dirty-cell tracking for wrapped Excel API writes.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
execution
|
|
6
|
-
sheets) not O(workbook), and the agent gets raw COM objects for everything
|
|
7
|
-
below the Worksheet level — zero overhead on Range reads/writes.
|
|
3
|
+
Wrapped write operations register their destination COM Range immediately
|
|
4
|
+
before mutation. The tracker snapshots only those ranges and compares them
|
|
5
|
+
after execution. Direct COM writes are intentionally outside this contract.
|
|
8
6
|
"""
|
|
9
7
|
|
|
10
8
|
from typing import Any, TypedDict
|
|
11
9
|
|
|
12
10
|
from shortcut_xl._log import xl_log
|
|
13
11
|
from shortcut_xl.api.utils.com_utils import normalize_2d
|
|
14
|
-
from shortcut_xl.api.utils.helpers import col_letter
|
|
12
|
+
from shortcut_xl.api.utils.helpers import address_to_index, col_letter
|
|
15
13
|
|
|
16
14
|
|
|
17
15
|
class _DirtyCellBase(TypedDict):
|
|
18
|
-
"""Required fields produced
|
|
16
|
+
"""Required fields produced for every changed cell."""
|
|
19
17
|
|
|
20
18
|
sheet: str
|
|
21
|
-
address: str
|
|
19
|
+
address: str
|
|
22
20
|
oldValue: Any
|
|
23
21
|
value: Any
|
|
24
22
|
|
|
25
23
|
|
|
26
24
|
class DirtyCell(_DirtyCellBase, total=False):
|
|
27
|
-
|
|
25
|
+
formula: str
|
|
26
|
+
oldFormula: str
|
|
27
|
+
workbook: str
|
|
28
|
+
numberFormat: str
|
|
28
29
|
|
|
29
|
-
Required: sheet, address, oldValue, value
|
|
30
|
-
Optional fields are added during the enrichment pass in collect_changes().
|
|
31
|
-
"""
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
workbook: str # workbook name — added during enrichment
|
|
36
|
-
numberFormat: str # Excel number format string — added during enrichment
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class _SheetSnapshot:
|
|
40
|
-
"""Immutable snapshot of a worksheet's UsedRange values and formulas."""
|
|
31
|
+
class _RangeSnapshot:
|
|
32
|
+
"""Immutable values and formulas for one explicit COM Range."""
|
|
41
33
|
|
|
42
34
|
__slots__ = ('top_row', 'left_col', 'rows', 'cols', 'data', 'formulas')
|
|
43
35
|
|
|
44
|
-
def __init__(self,
|
|
45
|
-
|
|
46
|
-
self.
|
|
47
|
-
self.
|
|
48
|
-
self.
|
|
49
|
-
self.
|
|
50
|
-
self.data = normalize_2d(ur.Value, self.rows, self.cols)
|
|
36
|
+
def __init__(self, rng):
|
|
37
|
+
self.top_row = rng.Row
|
|
38
|
+
self.left_col = rng.Column
|
|
39
|
+
self.rows = rng.Rows.Count
|
|
40
|
+
self.cols = rng.Columns.Count
|
|
41
|
+
self.data = normalize_2d(rng.Value, self.rows, self.cols)
|
|
51
42
|
try:
|
|
52
|
-
self.formulas = normalize_2d(
|
|
43
|
+
self.formulas = normalize_2d(rng.Formula, self.rows, self.cols)
|
|
53
44
|
except Exception:
|
|
54
45
|
self.formulas = None
|
|
55
46
|
|
|
47
|
+
def contains(self, row: int, col: int) -> bool:
|
|
48
|
+
return self.top_row <= row < self.top_row + self.rows and self.left_col <= col < self.left_col + self.cols
|
|
49
|
+
|
|
50
|
+
def value_at(self, row: int, col: int):
|
|
51
|
+
return self.data[row - self.top_row][col - self.left_col]
|
|
52
|
+
|
|
53
|
+
def formula_at(self, row: int, col: int):
|
|
54
|
+
return _formula_value(self, row - self.top_row, col - self.left_col)
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
|
|
57
|
+
def _formula_value(snap, ri, ci):
|
|
59
58
|
if snap.formulas is None:
|
|
60
59
|
return None
|
|
61
60
|
try:
|
|
62
|
-
|
|
61
|
+
formula = snap.formulas[ri][ci]
|
|
63
62
|
except (IndexError, TypeError):
|
|
64
63
|
return None
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return f
|
|
64
|
+
if isinstance(formula, str) and formula.startswith('='):
|
|
65
|
+
return formula
|
|
68
66
|
return None
|
|
69
67
|
|
|
70
68
|
|
|
71
|
-
def _diff_snapshots(sheet_name: str, before:
|
|
72
|
-
"""Compare two
|
|
73
|
-
|
|
74
|
-
Compares row-by-row first (tuple equality short-circuits) so
|
|
75
|
-
unchanged rows cost almost nothing.
|
|
76
|
-
"""
|
|
69
|
+
def _diff_snapshots(sheet_name: str, before: _RangeSnapshot, after: _RangeSnapshot) -> list[DirtyCell]:
|
|
70
|
+
"""Compare two snapshots, including formula-only changes."""
|
|
77
71
|
changes = []
|
|
78
|
-
|
|
79
|
-
if (
|
|
72
|
+
same_geometry = (
|
|
80
73
|
before.top_row == after.top_row
|
|
81
74
|
and before.left_col == after.left_col
|
|
82
75
|
and before.rows == after.rows
|
|
83
76
|
and before.cols == after.cols
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
addr = f'{col_letter(before.left_col + ci - 1)}{row_num}'
|
|
94
|
-
entry = {
|
|
95
|
-
'sheet': sheet_name,
|
|
96
|
-
'address': addr,
|
|
97
|
-
'oldValue': old,
|
|
98
|
-
'value': new,
|
|
99
|
-
}
|
|
100
|
-
formula = _get_formula(after, ri, ci)
|
|
101
|
-
if formula:
|
|
102
|
-
entry['formula'] = formula
|
|
103
|
-
old_formula = _get_formula(before, ri, ci)
|
|
104
|
-
if old_formula:
|
|
105
|
-
entry['oldFormula'] = old_formula
|
|
106
|
-
changes.append(entry)
|
|
107
|
-
return changes
|
|
108
|
-
|
|
109
|
-
# Different geometry — union bounding box
|
|
110
|
-
min_r = min(before.top_row, after.top_row)
|
|
111
|
-
min_c = min(before.left_col, after.left_col)
|
|
112
|
-
max_r = max(before.top_row + before.rows - 1, after.top_row + after.rows - 1)
|
|
113
|
-
max_c = max(before.left_col + before.cols - 1, after.left_col + after.cols - 1)
|
|
114
|
-
|
|
115
|
-
def _get(snap, row, col):
|
|
116
|
-
r = row - snap.top_row
|
|
117
|
-
c = col - snap.left_col
|
|
118
|
-
if 0 <= r < snap.rows and 0 <= c < snap.cols:
|
|
119
|
-
return snap.data[r][c]
|
|
77
|
+
)
|
|
78
|
+
min_row = min(before.top_row, after.top_row)
|
|
79
|
+
min_col = min(before.left_col, after.left_col)
|
|
80
|
+
max_row = max(before.top_row + before.rows - 1, after.top_row + after.rows - 1)
|
|
81
|
+
max_col = max(before.left_col + before.cols - 1, after.left_col + after.cols - 1)
|
|
82
|
+
|
|
83
|
+
def get_value(snap, row, col):
|
|
84
|
+
if snap.contains(row, col):
|
|
85
|
+
return snap.value_at(row, col)
|
|
120
86
|
return None
|
|
121
87
|
|
|
122
|
-
def
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if 0 <= r < snap.rows and 0 <= c < snap.cols:
|
|
126
|
-
return _get_formula(snap, r, c)
|
|
88
|
+
def get_formula(snap, row, col):
|
|
89
|
+
if snap.contains(row, col):
|
|
90
|
+
return snap.formula_at(row, col)
|
|
127
91
|
return None
|
|
128
92
|
|
|
129
|
-
for row in range(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
93
|
+
for row in range(min_row, max_row + 1):
|
|
94
|
+
if same_geometry:
|
|
95
|
+
row_index = row - before.top_row
|
|
96
|
+
if before.data[row_index] == after.data[row_index] and all(
|
|
97
|
+
_formula_value(before, row_index, col_index) == _formula_value(after, row_index, col_index)
|
|
98
|
+
for col_index in range(before.cols)
|
|
99
|
+
):
|
|
100
|
+
continue
|
|
101
|
+
for col in range(min_col, max_col + 1):
|
|
102
|
+
old = get_value(before, row, col)
|
|
103
|
+
new = get_value(after, row, col)
|
|
104
|
+
old_formula = get_formula(before, row, col)
|
|
105
|
+
formula = get_formula(after, row, col)
|
|
106
|
+
if old == new and old_formula == formula:
|
|
107
|
+
continue
|
|
108
|
+
entry: DirtyCell = {
|
|
109
|
+
'sheet': sheet_name,
|
|
110
|
+
'address': f'{col_letter(col - 1)}{row}',
|
|
111
|
+
'oldValue': old,
|
|
112
|
+
'value': new,
|
|
113
|
+
}
|
|
114
|
+
if formula:
|
|
115
|
+
entry['formula'] = formula
|
|
116
|
+
if old_formula:
|
|
117
|
+
entry['oldFormula'] = old_formula
|
|
118
|
+
changes.append(entry)
|
|
148
119
|
return changes
|
|
149
120
|
|
|
150
121
|
|
|
122
|
+
class _TrackedRange:
|
|
123
|
+
__slots__ = ('rng', 'workbook', 'sheet', 'before')
|
|
124
|
+
|
|
125
|
+
def __init__(self, rng, workbook: str, sheet: str, before: _RangeSnapshot):
|
|
126
|
+
self.rng = rng
|
|
127
|
+
self.workbook = workbook
|
|
128
|
+
self.sheet = sheet
|
|
129
|
+
self.before = before
|
|
130
|
+
|
|
131
|
+
|
|
151
132
|
class DirtyTracker:
|
|
152
|
-
"""Snapshots
|
|
133
|
+
"""Snapshots only ranges registered by wrapped write operations."""
|
|
153
134
|
|
|
154
|
-
__slots__ = ('
|
|
135
|
+
__slots__ = ('_ranges', '_keys', '_originals')
|
|
155
136
|
|
|
156
|
-
def __init__(self
|
|
157
|
-
self.
|
|
158
|
-
self.
|
|
137
|
+
def __init__(self):
|
|
138
|
+
self._ranges: list[_TrackedRange] = []
|
|
139
|
+
self._keys: set[tuple[str, str, int, int, int, int]] = set()
|
|
140
|
+
self._originals: dict[tuple[str, str, int, int], tuple[Any, str | None]] = {}
|
|
159
141
|
|
|
160
|
-
def
|
|
161
|
-
"""Capture a
|
|
142
|
+
def track_range(self, rng) -> None:
|
|
143
|
+
"""Capture a destination range once, before its first exact-range write."""
|
|
162
144
|
try:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
145
|
+
worksheet = rng.Parent
|
|
146
|
+
sheet = worksheet.Name
|
|
147
|
+
workbook = worksheet.Parent.Name
|
|
148
|
+
key = (workbook, sheet, rng.Row, rng.Column, rng.Rows.Count, rng.Columns.Count)
|
|
149
|
+
if key in self._keys:
|
|
150
|
+
return
|
|
151
|
+
before = _RangeSnapshot(rng)
|
|
152
|
+
self._keys.add(key)
|
|
153
|
+
self._ranges.append(_TrackedRange(rng, workbook, sheet, before))
|
|
154
|
+
for row in range(before.top_row, before.top_row + before.rows):
|
|
155
|
+
for col in range(before.left_col, before.left_col + before.cols):
|
|
156
|
+
cell_key = (workbook, sheet, row, col)
|
|
157
|
+
self._originals.setdefault(cell_key, (before.value_at(row, col), before.formula_at(row, col)))
|
|
158
|
+
except Exception as error:
|
|
159
|
+
xl_log(f'DirtyTracker.track_range failed: {error}')
|
|
171
160
|
|
|
172
161
|
def collect_changes(self) -> list[DirtyCell]:
|
|
173
|
-
"""Re-read
|
|
174
|
-
|
|
175
|
-
|
|
162
|
+
"""Re-read registered ranges and return deduplicated final cell changes."""
|
|
163
|
+
candidates: dict[tuple[str, str, str], DirtyCell] = {}
|
|
164
|
+
uniform_formats: dict[tuple[str, str, str], str] = {}
|
|
165
|
+
|
|
166
|
+
for tracked in self._ranges:
|
|
176
167
|
try:
|
|
177
|
-
after =
|
|
178
|
-
changes = _diff_snapshots(
|
|
179
|
-
# Enrich with workbook name + numberFormat
|
|
168
|
+
after = _RangeSnapshot(tracked.rng)
|
|
169
|
+
changes = _diff_snapshots(tracked.sheet, tracked.before, after)
|
|
180
170
|
try:
|
|
181
|
-
|
|
171
|
+
number_format = tracked.rng.NumberFormat if changes else None
|
|
182
172
|
except Exception:
|
|
183
|
-
|
|
173
|
+
number_format = None
|
|
184
174
|
for entry in changes:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
# Thin proxy classes (Application → Workbook → Worksheet access only)
|
|
201
|
-
# ---------------------------------------------------------------------------
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
class TrackedApp:
|
|
205
|
-
"""Proxy around Application. Wraps workbook/sheet access to trigger
|
|
206
|
-
snapshots; everything else passes straight through to COM."""
|
|
207
|
-
|
|
208
|
-
_WB_ATTRS = frozenset(('ActiveWorkbook', 'ThisWorkbook'))
|
|
209
|
-
_SHEET_ACCESSORS = frozenset(('Worksheets', 'Sheets'))
|
|
210
|
-
_SHEET_DIRECT = frozenset(('ActiveSheet',))
|
|
211
|
-
__slots__ = ('_app', '_tracker')
|
|
212
|
-
|
|
213
|
-
def __init__(self, app, tracker):
|
|
214
|
-
object.__setattr__(self, '_app', app)
|
|
215
|
-
object.__setattr__(self, '_tracker', tracker)
|
|
216
|
-
|
|
217
|
-
def __getattr__(self, name):
|
|
218
|
-
val = getattr(object.__getattribute__(self, '_app'), name)
|
|
219
|
-
tracker = object.__getattribute__(self, '_tracker')
|
|
220
|
-
if name in TrackedApp._WB_ATTRS:
|
|
221
|
-
return _TrackedWorkbook(val, tracker)
|
|
222
|
-
if name == 'Workbooks':
|
|
223
|
-
return _TrackedWorkbooks(val, tracker)
|
|
224
|
-
if name in TrackedApp._SHEET_ACCESSORS:
|
|
225
|
-
return _TrackedSheetAccessor(val, tracker)
|
|
226
|
-
if name in TrackedApp._SHEET_DIRECT:
|
|
227
|
-
tracker.snapshot_sheet(val)
|
|
228
|
-
return val
|
|
229
|
-
return val
|
|
230
|
-
|
|
231
|
-
def __setattr__(self, name, value):
|
|
232
|
-
setattr(object.__getattribute__(self, '_app'), name, value)
|
|
233
|
-
|
|
234
|
-
def __repr__(self):
|
|
235
|
-
return repr(object.__getattribute__(self, '_app'))
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
class _TrackedWorkbooks:
|
|
239
|
-
"""Proxy for Workbooks collection."""
|
|
240
|
-
|
|
241
|
-
__slots__ = ('_obj', '_tracker')
|
|
242
|
-
|
|
243
|
-
def __init__(self, obj, tracker):
|
|
244
|
-
object.__setattr__(self, '_obj', obj)
|
|
245
|
-
object.__setattr__(self, '_tracker', tracker)
|
|
246
|
-
|
|
247
|
-
def __call__(self, *args, **kwargs):
|
|
248
|
-
wb = object.__getattribute__(self, '_obj')(*args, **kwargs)
|
|
249
|
-
return _TrackedWorkbook(wb, object.__getattribute__(self, '_tracker'))
|
|
250
|
-
|
|
251
|
-
def __getattr__(self, name):
|
|
252
|
-
return getattr(object.__getattribute__(self, '_obj'), name)
|
|
253
|
-
|
|
254
|
-
def __iter__(self):
|
|
255
|
-
tracker = object.__getattribute__(self, '_tracker')
|
|
256
|
-
for wb in object.__getattribute__(self, '_obj'):
|
|
257
|
-
yield _TrackedWorkbook(wb, tracker)
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
class _TrackedWorkbook:
|
|
261
|
-
"""Proxy for a Workbook — wraps Worksheet/Sheet access."""
|
|
262
|
-
|
|
263
|
-
_SHEET_ACCESSORS = frozenset(('Worksheets', 'Sheets'))
|
|
264
|
-
_SHEET_DIRECT = frozenset(('ActiveSheet',))
|
|
265
|
-
__slots__ = ('_wb', '_tracker')
|
|
266
|
-
|
|
267
|
-
def __init__(self, wb, tracker):
|
|
268
|
-
object.__setattr__(self, '_wb', wb)
|
|
269
|
-
object.__setattr__(self, '_tracker', tracker)
|
|
270
|
-
|
|
271
|
-
def __getattr__(self, name):
|
|
272
|
-
val = getattr(object.__getattribute__(self, '_wb'), name)
|
|
273
|
-
tracker = object.__getattribute__(self, '_tracker')
|
|
274
|
-
if name in _TrackedWorkbook._SHEET_ACCESSORS:
|
|
275
|
-
return _TrackedSheetAccessor(val, tracker)
|
|
276
|
-
if name in _TrackedWorkbook._SHEET_DIRECT:
|
|
277
|
-
tracker.snapshot_sheet(val)
|
|
278
|
-
return val
|
|
279
|
-
return val
|
|
280
|
-
|
|
281
|
-
def __setattr__(self, name, value):
|
|
282
|
-
setattr(object.__getattribute__(self, '_wb'), name, value)
|
|
283
|
-
|
|
284
|
-
def __repr__(self):
|
|
285
|
-
return repr(object.__getattribute__(self, '_wb'))
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
class _TrackedSheetAccessor:
|
|
289
|
-
"""Proxy for Worksheets/Sheets collection — snapshots each sheet
|
|
290
|
-
the first time it is accessed, then returns the real COM Worksheet."""
|
|
291
|
-
|
|
292
|
-
__slots__ = ('_obj', '_tracker')
|
|
293
|
-
|
|
294
|
-
def __init__(self, obj, tracker):
|
|
295
|
-
object.__setattr__(self, '_obj', obj)
|
|
296
|
-
object.__setattr__(self, '_tracker', tracker)
|
|
297
|
-
|
|
298
|
-
def __call__(self, *args, **kwargs):
|
|
299
|
-
ws = object.__getattribute__(self, '_obj')(*args, **kwargs)
|
|
300
|
-
object.__getattribute__(self, '_tracker').snapshot_sheet(ws)
|
|
301
|
-
return ws # real COM object — no more proxying
|
|
302
|
-
|
|
303
|
-
def __getattr__(self, name):
|
|
304
|
-
return getattr(object.__getattribute__(self, '_obj'), name)
|
|
175
|
+
key = (tracked.workbook, tracked.sheet, entry['address'])
|
|
176
|
+
entry['workbook'] = tracked.workbook
|
|
177
|
+
candidates[key] = entry
|
|
178
|
+
if isinstance(number_format, str) and number_format != 'General':
|
|
179
|
+
uniform_formats[key] = number_format
|
|
180
|
+
except Exception as error:
|
|
181
|
+
xl_log(f'DirtyTracker.collect_changes({tracked.workbook}:{tracked.sheet}): {error}')
|
|
182
|
+
|
|
183
|
+
result = []
|
|
184
|
+
for (workbook, sheet, address), candidate in candidates.items():
|
|
185
|
+
row_index, col_index = address_to_index(address)
|
|
186
|
+
old_value, old_formula = self._originals[(workbook, sheet, row_index + 1, col_index + 1)]
|
|
187
|
+
new_formula = candidate.get('formula')
|
|
188
|
+
if old_value == candidate['value'] and old_formula == new_formula:
|
|
189
|
+
continue
|
|
305
190
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
191
|
+
candidate['oldValue'] = old_value
|
|
192
|
+
if old_formula:
|
|
193
|
+
candidate['oldFormula'] = old_formula
|
|
194
|
+
else:
|
|
195
|
+
candidate.pop('oldFormula', None)
|
|
196
|
+
number_format = uniform_formats.get((workbook, sheet, address))
|
|
197
|
+
if number_format:
|
|
198
|
+
candidate['numberFormat'] = number_format
|
|
199
|
+
result.append(candidate)
|
|
200
|
+
return result
|