@nghyane/arcane 0.1.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/CHANGELOG.md +3 -0
- package/README.md +12 -0
- package/examples/README.md +21 -0
- package/examples/custom-tools/README.md +109 -0
- package/examples/custom-tools/hello/index.ts +20 -0
- package/examples/custom-tools/todo/index.ts +206 -0
- package/examples/extensions/README.md +143 -0
- package/examples/extensions/api-demo.ts +89 -0
- package/examples/extensions/chalk-logger.ts +25 -0
- package/examples/extensions/hello.ts +32 -0
- package/examples/extensions/pirate.ts +43 -0
- package/examples/extensions/plan-mode.ts +550 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/todo.ts +296 -0
- package/examples/extensions/tools.ts +144 -0
- package/examples/extensions/with-deps/index.ts +35 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +16 -0
- package/examples/hooks/README.md +56 -0
- package/examples/hooks/auto-commit-on-exit.ts +48 -0
- package/examples/hooks/confirm-destructive.ts +58 -0
- package/examples/hooks/custom-compaction.ts +116 -0
- package/examples/hooks/dirty-repo-guard.ts +51 -0
- package/examples/hooks/file-trigger.ts +40 -0
- package/examples/hooks/git-checkpoint.ts +52 -0
- package/examples/hooks/handoff.ts +150 -0
- package/examples/hooks/permission-gate.ts +33 -0
- package/examples/hooks/protected-paths.ts +29 -0
- package/examples/hooks/qna.ts +119 -0
- package/examples/hooks/status-line.ts +39 -0
- package/examples/sdk/01-minimal.ts +21 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +43 -0
- package/examples/sdk/04-skills.ts +43 -0
- package/examples/sdk/06-extensions.ts +80 -0
- package/examples/sdk/06-hooks.ts +61 -0
- package/examples/sdk/07-context-files.ts +35 -0
- package/examples/sdk/08-prompt-templates.ts +36 -0
- package/examples/sdk/08-slash-commands.ts +41 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
- package/examples/sdk/11-sessions.ts +47 -0
- package/examples/sdk/README.md +150 -0
- package/package.json +464 -0
- package/scripts/format-prompts.ts +184 -0
- package/scripts/generate-docs-index.ts +40 -0
- package/scripts/generate-template.ts +32 -0
- package/src/bun-imports.d.ts +22 -0
- package/src/capability/context-file.ts +39 -0
- package/src/capability/extension-module.ts +33 -0
- package/src/capability/extension.ts +47 -0
- package/src/capability/fs.ts +89 -0
- package/src/capability/hook.ts +39 -0
- package/src/capability/index.ts +432 -0
- package/src/capability/instruction.ts +36 -0
- package/src/capability/mcp.ts +60 -0
- package/src/capability/prompt.ts +34 -0
- package/src/capability/rule.ts +223 -0
- package/src/capability/settings.ts +34 -0
- package/src/capability/skill.ts +48 -0
- package/src/capability/slash-command.ts +39 -0
- package/src/capability/ssh.ts +41 -0
- package/src/capability/system-prompt.ts +34 -0
- package/src/capability/tool.ts +37 -0
- package/src/capability/types.ts +156 -0
- package/src/cli/args.ts +259 -0
- package/src/cli/config-cli.ts +357 -0
- package/src/cli/file-processor.ts +124 -0
- package/src/cli/grep-cli.ts +152 -0
- package/src/cli/jupyter-cli.ts +106 -0
- package/src/cli/list-models.ts +103 -0
- package/src/cli/plugin-cli.ts +661 -0
- package/src/cli/session-picker.ts +42 -0
- package/src/cli/setup-cli.ts +376 -0
- package/src/cli/shell-cli.ts +174 -0
- package/src/cli/ssh-cli.ts +179 -0
- package/src/cli/stats-cli.ts +197 -0
- package/src/cli/update-cli.ts +286 -0
- package/src/cli/web-search-cli.ts +143 -0
- package/src/cli.ts +65 -0
- package/src/commands/commit.ts +36 -0
- package/src/commands/config.ts +51 -0
- package/src/commands/grep.ts +41 -0
- package/src/commands/jupyter.ts +32 -0
- package/src/commands/launch.ts +139 -0
- package/src/commands/plugin.ts +70 -0
- package/src/commands/setup.ts +42 -0
- package/src/commands/shell.ts +29 -0
- package/src/commands/ssh.ts +60 -0
- package/src/commands/stats.ts +29 -0
- package/src/commands/update.ts +21 -0
- package/src/commands/web-search.ts +42 -0
- package/src/commit/agentic/agent.ts +311 -0
- package/src/commit/agentic/fallback.ts +96 -0
- package/src/commit/agentic/index.ts +359 -0
- package/src/commit/agentic/prompts/analyze-file.md +22 -0
- package/src/commit/agentic/prompts/session-user.md +25 -0
- package/src/commit/agentic/prompts/split-confirm.md +1 -0
- package/src/commit/agentic/prompts/system.md +38 -0
- package/src/commit/agentic/state.ts +69 -0
- package/src/commit/agentic/tools/analyze-file.ts +118 -0
- package/src/commit/agentic/tools/git-file-diff.ts +194 -0
- package/src/commit/agentic/tools/git-hunk.ts +50 -0
- package/src/commit/agentic/tools/git-overview.ts +84 -0
- package/src/commit/agentic/tools/index.ts +56 -0
- package/src/commit/agentic/tools/propose-changelog.ts +128 -0
- package/src/commit/agentic/tools/propose-commit.ts +154 -0
- package/src/commit/agentic/tools/recent-commits.ts +81 -0
- package/src/commit/agentic/tools/split-commit.ts +280 -0
- package/src/commit/agentic/topo-sort.ts +44 -0
- package/src/commit/agentic/trivial.ts +51 -0
- package/src/commit/agentic/validation.ts +200 -0
- package/src/commit/analysis/conventional.ts +165 -0
- package/src/commit/analysis/index.ts +4 -0
- package/src/commit/analysis/scope.ts +242 -0
- package/src/commit/analysis/summary.ts +112 -0
- package/src/commit/analysis/validation.ts +66 -0
- package/src/commit/changelog/detect.ts +37 -0
- package/src/commit/changelog/generate.ts +110 -0
- package/src/commit/changelog/index.ts +234 -0
- package/src/commit/changelog/parse.ts +44 -0
- package/src/commit/cli.ts +93 -0
- package/src/commit/git/diff.ts +148 -0
- package/src/commit/git/errors.ts +9 -0
- package/src/commit/git/index.ts +211 -0
- package/src/commit/git/operations.ts +54 -0
- package/src/commit/index.ts +5 -0
- package/src/commit/map-reduce/index.ts +64 -0
- package/src/commit/map-reduce/map-phase.ts +178 -0
- package/src/commit/map-reduce/reduce-phase.ts +145 -0
- package/src/commit/map-reduce/utils.ts +9 -0
- package/src/commit/message.ts +11 -0
- package/src/commit/model-selection.ts +69 -0
- package/src/commit/pipeline.ts +243 -0
- package/src/commit/prompts/analysis-system.md +148 -0
- package/src/commit/prompts/analysis-user.md +38 -0
- package/src/commit/prompts/changelog-system.md +50 -0
- package/src/commit/prompts/changelog-user.md +18 -0
- package/src/commit/prompts/file-observer-system.md +24 -0
- package/src/commit/prompts/file-observer-user.md +8 -0
- package/src/commit/prompts/reduce-system.md +50 -0
- package/src/commit/prompts/reduce-user.md +17 -0
- package/src/commit/prompts/summary-retry.md +3 -0
- package/src/commit/prompts/summary-system.md +38 -0
- package/src/commit/prompts/summary-user.md +13 -0
- package/src/commit/prompts/types-description.md +2 -0
- package/src/commit/types.ts +109 -0
- package/src/commit/utils/exclusions.ts +42 -0
- package/src/config/file-lock.ts +121 -0
- package/src/config/keybindings.ts +280 -0
- package/src/config/model-registry.ts +1140 -0
- package/src/config/model-resolver.ts +812 -0
- package/src/config/prompt-templates.ts +526 -0
- package/src/config/resolve-config-value.ts +92 -0
- package/src/config/settings-schema.ts +1236 -0
- package/src/config/settings.ts +706 -0
- package/src/config.ts +414 -0
- package/src/cursor.ts +239 -0
- package/src/debug/index.ts +431 -0
- package/src/debug/log-formatting.ts +60 -0
- package/src/debug/log-viewer.ts +903 -0
- package/src/debug/profiler.ts +158 -0
- package/src/debug/report-bundle.ts +366 -0
- package/src/debug/system-info.ts +112 -0
- package/src/discovery/agents-md.ts +68 -0
- package/src/discovery/agents.ts +199 -0
- package/src/discovery/builtin.ts +815 -0
- package/src/discovery/claude-plugins.ts +205 -0
- package/src/discovery/claude.ts +506 -0
- package/src/discovery/cline.ts +83 -0
- package/src/discovery/codex.ts +532 -0
- package/src/discovery/cursor.ts +218 -0
- package/src/discovery/gemini.ts +395 -0
- package/src/discovery/github.ts +117 -0
- package/src/discovery/helpers.ts +698 -0
- package/src/discovery/index.ts +89 -0
- package/src/discovery/mcp-json.ts +156 -0
- package/src/discovery/opencode.ts +394 -0
- package/src/discovery/ssh.ts +160 -0
- package/src/discovery/vscode.ts +103 -0
- package/src/discovery/windsurf.ts +145 -0
- package/src/exa/company.ts +57 -0
- package/src/exa/index.ts +62 -0
- package/src/exa/linkedin.ts +57 -0
- package/src/exa/mcp-client.ts +289 -0
- package/src/exa/render.ts +244 -0
- package/src/exa/researcher.ts +89 -0
- package/src/exa/search.ts +330 -0
- package/src/exa/types.ts +166 -0
- package/src/exa/websets.ts +247 -0
- package/src/exec/bash-executor.ts +184 -0
- package/src/exec/exec.ts +53 -0
- package/src/export/custom-share.ts +65 -0
- package/src/export/html/index.ts +162 -0
- package/src/export/html/template.css +889 -0
- package/src/export/html/template.generated.ts +2 -0
- package/src/export/html/template.html +45 -0
- package/src/export/html/template.js +1329 -0
- package/src/export/html/template.macro.ts +24 -0
- package/src/export/html/vendor/highlight.min.js +1213 -0
- package/src/export/html/vendor/marked.min.js +6 -0
- package/src/export/ttsr.ts +434 -0
- package/src/extensibility/custom-commands/bundled/review/index.ts +433 -0
- package/src/extensibility/custom-commands/index.ts +15 -0
- package/src/extensibility/custom-commands/loader.ts +231 -0
- package/src/extensibility/custom-commands/types.ts +111 -0
- package/src/extensibility/custom-tools/index.ts +22 -0
- package/src/extensibility/custom-tools/loader.ts +235 -0
- package/src/extensibility/custom-tools/types.ts +226 -0
- package/src/extensibility/custom-tools/wrapper.ts +45 -0
- package/src/extensibility/extensions/index.ts +136 -0
- package/src/extensibility/extensions/loader.ts +520 -0
- package/src/extensibility/extensions/runner.ts +774 -0
- package/src/extensibility/extensions/types.ts +1293 -0
- package/src/extensibility/extensions/wrapper.ts +188 -0
- package/src/extensibility/hooks/index.ts +16 -0
- package/src/extensibility/hooks/loader.ts +273 -0
- package/src/extensibility/hooks/runner.ts +441 -0
- package/src/extensibility/hooks/tool-wrapper.ts +106 -0
- package/src/extensibility/hooks/types.ts +817 -0
- package/src/extensibility/plugins/doctor.ts +65 -0
- package/src/extensibility/plugins/git-url.ts +281 -0
- package/src/extensibility/plugins/index.ts +33 -0
- package/src/extensibility/plugins/installer.ts +192 -0
- package/src/extensibility/plugins/loader.ts +338 -0
- package/src/extensibility/plugins/manager.ts +716 -0
- package/src/extensibility/plugins/parser.ts +105 -0
- package/src/extensibility/plugins/types.ts +190 -0
- package/src/extensibility/skills.ts +385 -0
- package/src/extensibility/slash-commands.ts +287 -0
- package/src/extensibility/tool-proxy.ts +25 -0
- package/src/index.ts +275 -0
- package/src/internal-urls/agent-protocol.ts +136 -0
- package/src/internal-urls/artifact-protocol.ts +97 -0
- package/src/internal-urls/docs-index.generated.ts +54 -0
- package/src/internal-urls/docs-protocol.ts +84 -0
- package/src/internal-urls/index.ts +31 -0
- package/src/internal-urls/json-query.ts +126 -0
- package/src/internal-urls/memory-protocol.ts +133 -0
- package/src/internal-urls/router.ts +70 -0
- package/src/internal-urls/rule-protocol.ts +55 -0
- package/src/internal-urls/skill-protocol.ts +111 -0
- package/src/internal-urls/types.ts +52 -0
- package/src/ipy/executor.ts +556 -0
- package/src/ipy/gateway-coordinator.ts +426 -0
- package/src/ipy/kernel.ts +892 -0
- package/src/ipy/modules.ts +109 -0
- package/src/ipy/prelude.py +831 -0
- package/src/ipy/prelude.ts +3 -0
- package/src/ipy/runtime.ts +222 -0
- package/src/lsp/client.ts +867 -0
- package/src/lsp/clients/biome-client.ts +202 -0
- package/src/lsp/clients/index.ts +50 -0
- package/src/lsp/clients/lsp-linter-client.ts +93 -0
- package/src/lsp/clients/swiftlint-client.ts +120 -0
- package/src/lsp/config.ts +397 -0
- package/src/lsp/defaults.json +464 -0
- package/src/lsp/edits.ts +109 -0
- package/src/lsp/index.ts +1268 -0
- package/src/lsp/lspmux.ts +250 -0
- package/src/lsp/render.ts +689 -0
- package/src/lsp/types.ts +414 -0
- package/src/lsp/utils.ts +549 -0
- package/src/main.ts +773 -0
- package/src/mcp/client.ts +239 -0
- package/src/mcp/config-writer.ts +215 -0
- package/src/mcp/config.ts +363 -0
- package/src/mcp/index.ts +55 -0
- package/src/mcp/json-rpc.ts +84 -0
- package/src/mcp/loader.ts +124 -0
- package/src/mcp/manager.ts +490 -0
- package/src/mcp/oauth-discovery.ts +274 -0
- package/src/mcp/oauth-flow.ts +229 -0
- package/src/mcp/render.ts +123 -0
- package/src/mcp/tool-bridge.ts +372 -0
- package/src/mcp/tool-cache.ts +121 -0
- package/src/mcp/transports/http.ts +332 -0
- package/src/mcp/transports/index.ts +6 -0
- package/src/mcp/transports/stdio.ts +281 -0
- package/src/mcp/types.ts +248 -0
- package/src/memories/index.ts +1099 -0
- package/src/memories/storage.ts +563 -0
- package/src/modes/components/agent-dashboard.ts +1130 -0
- package/src/modes/components/assistant-message.ts +144 -0
- package/src/modes/components/bash-execution.ts +218 -0
- package/src/modes/components/bordered-loader.ts +41 -0
- package/src/modes/components/branch-summary-message.ts +45 -0
- package/src/modes/components/codemode-group.ts +369 -0
- package/src/modes/components/compaction-summary-message.ts +51 -0
- package/src/modes/components/countdown-timer.ts +46 -0
- package/src/modes/components/custom-editor.ts +181 -0
- package/src/modes/components/custom-message.ts +91 -0
- package/src/modes/components/diff.ts +186 -0
- package/src/modes/components/dynamic-border.ts +25 -0
- package/src/modes/components/extensions/extension-dashboard.ts +325 -0
- package/src/modes/components/extensions/extension-list.ts +484 -0
- package/src/modes/components/extensions/index.ts +9 -0
- package/src/modes/components/extensions/inspector-panel.ts +321 -0
- package/src/modes/components/extensions/state-manager.ts +586 -0
- package/src/modes/components/extensions/types.ts +191 -0
- package/src/modes/components/footer.ts +315 -0
- package/src/modes/components/history-search.ts +157 -0
- package/src/modes/components/hook-editor.ts +101 -0
- package/src/modes/components/hook-input.ts +72 -0
- package/src/modes/components/hook-message.ts +100 -0
- package/src/modes/components/hook-selector.ts +155 -0
- package/src/modes/components/index.ts +41 -0
- package/src/modes/components/keybinding-hints.ts +65 -0
- package/src/modes/components/login-dialog.ts +164 -0
- package/src/modes/components/mcp-add-wizard.ts +1295 -0
- package/src/modes/components/model-selector.ts +625 -0
- package/src/modes/components/oauth-selector.ts +210 -0
- package/src/modes/components/plugin-settings.ts +477 -0
- package/src/modes/components/python-execution.ts +196 -0
- package/src/modes/components/queue-mode-selector.ts +56 -0
- package/src/modes/components/read-tool-group.ts +119 -0
- package/src/modes/components/session-selector.ts +242 -0
- package/src/modes/components/settings-defs.ts +340 -0
- package/src/modes/components/settings-selector.ts +529 -0
- package/src/modes/components/show-images-selector.ts +45 -0
- package/src/modes/components/skill-message.ts +90 -0
- package/src/modes/components/status-line/index.ts +4 -0
- package/src/modes/components/status-line/presets.ts +94 -0
- package/src/modes/components/status-line/segments.ts +352 -0
- package/src/modes/components/status-line/separators.ts +55 -0
- package/src/modes/components/status-line/types.ts +75 -0
- package/src/modes/components/status-line-segment-editor.ts +354 -0
- package/src/modes/components/status-line.ts +421 -0
- package/src/modes/components/theme-selector.ts +63 -0
- package/src/modes/components/thinking-selector.ts +64 -0
- package/src/modes/components/todo-display.ts +115 -0
- package/src/modes/components/todo-reminder.ts +40 -0
- package/src/modes/components/tool-execution.ts +703 -0
- package/src/modes/components/tree-selector.ts +904 -0
- package/src/modes/components/ttsr-notification.ts +80 -0
- package/src/modes/components/user-message-selector.ts +146 -0
- package/src/modes/components/user-message.ts +22 -0
- package/src/modes/components/visual-truncate.ts +63 -0
- package/src/modes/components/welcome.ts +247 -0
- package/src/modes/controllers/command-controller.ts +1120 -0
- package/src/modes/controllers/event-controller.ts +479 -0
- package/src/modes/controllers/extension-ui-controller.ts +778 -0
- package/src/modes/controllers/input-controller.ts +671 -0
- package/src/modes/controllers/mcp-command-controller.ts +1315 -0
- package/src/modes/controllers/selector-controller.ts +712 -0
- package/src/modes/controllers/ssh-command-controller.ts +452 -0
- package/src/modes/index.ts +15 -0
- package/src/modes/interactive-mode.ts +1027 -0
- package/src/modes/print-mode.ts +191 -0
- package/src/modes/rpc/rpc-client.ts +583 -0
- package/src/modes/rpc/rpc-mode.ts +700 -0
- package/src/modes/rpc/rpc-types.ts +236 -0
- package/src/modes/theme/dark.json +95 -0
- package/src/modes/theme/defaults/alabaster.json +93 -0
- package/src/modes/theme/defaults/amethyst.json +96 -0
- package/src/modes/theme/defaults/anthracite.json +93 -0
- package/src/modes/theme/defaults/basalt.json +91 -0
- package/src/modes/theme/defaults/birch.json +95 -0
- package/src/modes/theme/defaults/dark-abyss.json +91 -0
- package/src/modes/theme/defaults/dark-arctic.json +104 -0
- package/src/modes/theme/defaults/dark-aurora.json +95 -0
- package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
- package/src/modes/theme/defaults/dark-cavern.json +91 -0
- package/src/modes/theme/defaults/dark-copper.json +95 -0
- package/src/modes/theme/defaults/dark-cosmos.json +90 -0
- package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
- package/src/modes/theme/defaults/dark-dracula.json +98 -0
- package/src/modes/theme/defaults/dark-eclipse.json +91 -0
- package/src/modes/theme/defaults/dark-ember.json +95 -0
- package/src/modes/theme/defaults/dark-equinox.json +90 -0
- package/src/modes/theme/defaults/dark-forest.json +96 -0
- package/src/modes/theme/defaults/dark-github.json +105 -0
- package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
- package/src/modes/theme/defaults/dark-lavender.json +95 -0
- package/src/modes/theme/defaults/dark-lunar.json +89 -0
- package/src/modes/theme/defaults/dark-midnight.json +95 -0
- package/src/modes/theme/defaults/dark-monochrome.json +94 -0
- package/src/modes/theme/defaults/dark-monokai.json +98 -0
- package/src/modes/theme/defaults/dark-nebula.json +90 -0
- package/src/modes/theme/defaults/dark-nord.json +97 -0
- package/src/modes/theme/defaults/dark-ocean.json +101 -0
- package/src/modes/theme/defaults/dark-one.json +100 -0
- package/src/modes/theme/defaults/dark-rainforest.json +91 -0
- package/src/modes/theme/defaults/dark-reef.json +91 -0
- package/src/modes/theme/defaults/dark-retro.json +92 -0
- package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
- package/src/modes/theme/defaults/dark-sakura.json +95 -0
- package/src/modes/theme/defaults/dark-slate.json +95 -0
- package/src/modes/theme/defaults/dark-solarized.json +97 -0
- package/src/modes/theme/defaults/dark-solstice.json +90 -0
- package/src/modes/theme/defaults/dark-starfall.json +91 -0
- package/src/modes/theme/defaults/dark-sunset.json +99 -0
- package/src/modes/theme/defaults/dark-swamp.json +90 -0
- package/src/modes/theme/defaults/dark-synthwave.json +103 -0
- package/src/modes/theme/defaults/dark-taiga.json +91 -0
- package/src/modes/theme/defaults/dark-terminal.json +95 -0
- package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
- package/src/modes/theme/defaults/dark-tundra.json +91 -0
- package/src/modes/theme/defaults/dark-twilight.json +91 -0
- package/src/modes/theme/defaults/dark-volcanic.json +91 -0
- package/src/modes/theme/defaults/graphite.json +92 -0
- package/src/modes/theme/defaults/index.ts +195 -0
- package/src/modes/theme/defaults/light-arctic.json +107 -0
- package/src/modes/theme/defaults/light-aurora-day.json +91 -0
- package/src/modes/theme/defaults/light-canyon.json +91 -0
- package/src/modes/theme/defaults/light-catppuccin.json +106 -0
- package/src/modes/theme/defaults/light-cirrus.json +90 -0
- package/src/modes/theme/defaults/light-coral.json +95 -0
- package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
- package/src/modes/theme/defaults/light-dawn.json +90 -0
- package/src/modes/theme/defaults/light-dunes.json +91 -0
- package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
- package/src/modes/theme/defaults/light-forest.json +100 -0
- package/src/modes/theme/defaults/light-frost.json +95 -0
- package/src/modes/theme/defaults/light-github.json +115 -0
- package/src/modes/theme/defaults/light-glacier.json +91 -0
- package/src/modes/theme/defaults/light-gruvbox.json +108 -0
- package/src/modes/theme/defaults/light-haze.json +90 -0
- package/src/modes/theme/defaults/light-honeycomb.json +95 -0
- package/src/modes/theme/defaults/light-lagoon.json +91 -0
- package/src/modes/theme/defaults/light-lavender.json +95 -0
- package/src/modes/theme/defaults/light-meadow.json +91 -0
- package/src/modes/theme/defaults/light-mint.json +95 -0
- package/src/modes/theme/defaults/light-monochrome.json +101 -0
- package/src/modes/theme/defaults/light-ocean.json +99 -0
- package/src/modes/theme/defaults/light-one.json +99 -0
- package/src/modes/theme/defaults/light-opal.json +91 -0
- package/src/modes/theme/defaults/light-orchard.json +91 -0
- package/src/modes/theme/defaults/light-paper.json +95 -0
- package/src/modes/theme/defaults/light-prism.json +90 -0
- package/src/modes/theme/defaults/light-retro.json +98 -0
- package/src/modes/theme/defaults/light-sand.json +95 -0
- package/src/modes/theme/defaults/light-savanna.json +91 -0
- package/src/modes/theme/defaults/light-solarized.json +102 -0
- package/src/modes/theme/defaults/light-soleil.json +90 -0
- package/src/modes/theme/defaults/light-sunset.json +99 -0
- package/src/modes/theme/defaults/light-synthwave.json +98 -0
- package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
- package/src/modes/theme/defaults/light-wetland.json +91 -0
- package/src/modes/theme/defaults/light-zenith.json +89 -0
- package/src/modes/theme/defaults/limestone.json +94 -0
- package/src/modes/theme/defaults/mahogany.json +97 -0
- package/src/modes/theme/defaults/marble.json +93 -0
- package/src/modes/theme/defaults/obsidian.json +91 -0
- package/src/modes/theme/defaults/onyx.json +91 -0
- package/src/modes/theme/defaults/pearl.json +93 -0
- package/src/modes/theme/defaults/porcelain.json +91 -0
- package/src/modes/theme/defaults/quartz.json +96 -0
- package/src/modes/theme/defaults/sandstone.json +95 -0
- package/src/modes/theme/defaults/titanium.json +90 -0
- package/src/modes/theme/light.json +93 -0
- package/src/modes/theme/mermaid-cache.ts +111 -0
- package/src/modes/theme/theme-schema.json +429 -0
- package/src/modes/theme/theme.ts +2333 -0
- package/src/modes/types.ts +216 -0
- package/src/modes/utils/ui-helpers.ts +529 -0
- package/src/patch/applicator.ts +1482 -0
- package/src/patch/diff.ts +425 -0
- package/src/patch/fuzzy.ts +784 -0
- package/src/patch/hashline.ts +972 -0
- package/src/patch/index.ts +964 -0
- package/src/patch/normalize.ts +397 -0
- package/src/patch/normative.ts +72 -0
- package/src/patch/parser.ts +532 -0
- package/src/patch/shared.ts +400 -0
- package/src/patch/types.ts +292 -0
- package/src/priority.json +35 -0
- package/src/prompts/agents/explore.md +48 -0
- package/src/prompts/agents/frontmatter.md +9 -0
- package/src/prompts/agents/init.md +36 -0
- package/src/prompts/agents/librarian.md +53 -0
- package/src/prompts/agents/oracle.md +51 -0
- package/src/prompts/agents/reviewer.md +70 -0
- package/src/prompts/agents/task.md +14 -0
- package/src/prompts/compaction/branch-summary-context.md +5 -0
- package/src/prompts/compaction/branch-summary-preamble.md +2 -0
- package/src/prompts/compaction/branch-summary.md +30 -0
- package/src/prompts/compaction/compaction-short-summary.md +9 -0
- package/src/prompts/compaction/compaction-summary-context.md +5 -0
- package/src/prompts/compaction/compaction-summary.md +38 -0
- package/src/prompts/compaction/compaction-turn-prefix.md +17 -0
- package/src/prompts/compaction/compaction-update-summary.md +45 -0
- package/src/prompts/memories/consolidation.md +30 -0
- package/src/prompts/memories/read_path.md +11 -0
- package/src/prompts/memories/stage_one_input.md +6 -0
- package/src/prompts/memories/stage_one_system.md +21 -0
- package/src/prompts/review-request.md +64 -0
- package/src/prompts/system/agent-creation-architect.md +65 -0
- package/src/prompts/system/agent-creation-user.md +6 -0
- package/src/prompts/system/custom-system-prompt.md +68 -0
- package/src/prompts/system/file-operations.md +10 -0
- package/src/prompts/system/subagent-submit-reminder.md +11 -0
- package/src/prompts/system/subagent-system-prompt.md +31 -0
- package/src/prompts/system/subagent-user-prompt.md +8 -0
- package/src/prompts/system/summarization-system.md +3 -0
- package/src/prompts/system/system-prompt.md +300 -0
- package/src/prompts/system/title-system.md +2 -0
- package/src/prompts/system/ttsr-interrupt.md +7 -0
- package/src/prompts/system/web-search.md +28 -0
- package/src/prompts/tools/ask.md +44 -0
- package/src/prompts/tools/bash.md +24 -0
- package/src/prompts/tools/browser.md +33 -0
- package/src/prompts/tools/calculator.md +12 -0
- package/src/prompts/tools/explore.md +29 -0
- package/src/prompts/tools/fetch.md +16 -0
- package/src/prompts/tools/find.md +18 -0
- package/src/prompts/tools/gemini-image.md +23 -0
- package/src/prompts/tools/grep.md +28 -0
- package/src/prompts/tools/hashline.md +232 -0
- package/src/prompts/tools/librarian.md +24 -0
- package/src/prompts/tools/lsp.md +28 -0
- package/src/prompts/tools/oracle.md +26 -0
- package/src/prompts/tools/patch.md +74 -0
- package/src/prompts/tools/python.md +66 -0
- package/src/prompts/tools/read.md +36 -0
- package/src/prompts/tools/replace.md +38 -0
- package/src/prompts/tools/reviewer.md +41 -0
- package/src/prompts/tools/ssh.md +51 -0
- package/src/prompts/tools/task-summary.md +28 -0
- package/src/prompts/tools/task.md +275 -0
- package/src/prompts/tools/todo-write.md +65 -0
- package/src/prompts/tools/undo-edit.md +7 -0
- package/src/prompts/tools/web-search.md +19 -0
- package/src/prompts/tools/write.md +18 -0
- package/src/sdk.ts +1287 -0
- package/src/secrets/index.ts +116 -0
- package/src/secrets/obfuscator.ts +269 -0
- package/src/secrets/regex.ts +21 -0
- package/src/session/agent-session.ts +4669 -0
- package/src/session/agent-storage.ts +621 -0
- package/src/session/artifacts.ts +132 -0
- package/src/session/auth-storage.ts +1433 -0
- package/src/session/blob-store.ts +103 -0
- package/src/session/compaction/branch-summarization.ts +315 -0
- package/src/session/compaction/compaction.ts +864 -0
- package/src/session/compaction/index.ts +7 -0
- package/src/session/compaction/pruning.ts +91 -0
- package/src/session/compaction/utils.ts +171 -0
- package/src/session/history-storage.ts +170 -0
- package/src/session/messages.ts +317 -0
- package/src/session/session-manager.ts +2276 -0
- package/src/session/session-storage.ts +342 -0
- package/src/session/streaming-output.ts +565 -0
- package/src/slash-commands/builtin-registry.ts +439 -0
- package/src/ssh/config-writer.ts +183 -0
- package/src/ssh/connection-manager.ts +444 -0
- package/src/ssh/ssh-executor.ts +127 -0
- package/src/ssh/sshfs-mount.ts +135 -0
- package/src/stt/downloader.ts +71 -0
- package/src/stt/index.ts +3 -0
- package/src/stt/recorder.ts +351 -0
- package/src/stt/setup.ts +52 -0
- package/src/stt/stt-controller.ts +160 -0
- package/src/stt/transcribe.py +70 -0
- package/src/stt/transcriber.ts +91 -0
- package/src/system-prompt.ts +685 -0
- package/src/task/agents.ts +155 -0
- package/src/task/batch.ts +102 -0
- package/src/task/commands.ts +134 -0
- package/src/task/discovery.ts +126 -0
- package/src/task/executor.ts +908 -0
- package/src/task/index.ts +223 -0
- package/src/task/output-manager.ts +107 -0
- package/src/task/parallel.ts +84 -0
- package/src/task/render.ts +326 -0
- package/src/task/subprocess-tool-registry.ts +88 -0
- package/src/task/template.ts +32 -0
- package/src/task/types.ts +144 -0
- package/src/tools/ask.ts +523 -0
- package/src/tools/bash-interactive.ts +419 -0
- package/src/tools/bash-interceptor.ts +105 -0
- package/src/tools/bash-normalize.ts +107 -0
- package/src/tools/bash-skill-urls.ts +177 -0
- package/src/tools/bash.ts +347 -0
- package/src/tools/browser.ts +1374 -0
- package/src/tools/calculator.ts +537 -0
- package/src/tools/context.ts +39 -0
- package/src/tools/explore.ts +23 -0
- package/src/tools/fetch.ts +1091 -0
- package/src/tools/find.ts +540 -0
- package/src/tools/fs-cache-invalidation.ts +28 -0
- package/src/tools/gemini-image.ts +907 -0
- package/src/tools/grep.ts +489 -0
- package/src/tools/index.ts +337 -0
- package/src/tools/json-tree.ts +231 -0
- package/src/tools/jtd-to-json-schema.ts +247 -0
- package/src/tools/jtd-to-typescript.ts +198 -0
- package/src/tools/librarian.ts +33 -0
- package/src/tools/list-limit.ts +40 -0
- package/src/tools/notebook.ts +287 -0
- package/src/tools/oracle.ts +40 -0
- package/src/tools/output-meta.ts +459 -0
- package/src/tools/output-utils.ts +63 -0
- package/src/tools/path-utils.ts +116 -0
- package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
- package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
- package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
- package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
- package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
- package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
- package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
- package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
- package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
- package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
- package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
- package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
- package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
- package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
- package/src/tools/python.ts +1118 -0
- package/src/tools/read.ts +1193 -0
- package/src/tools/render-utils.ts +680 -0
- package/src/tools/renderers.ts +60 -0
- package/src/tools/reviewer-tool.ts +41 -0
- package/src/tools/ssh.ts +326 -0
- package/src/tools/subagent-tool.ts +169 -0
- package/src/tools/submit-result.ts +152 -0
- package/src/tools/todo-write.ts +255 -0
- package/src/tools/tool-errors.ts +92 -0
- package/src/tools/tool-result.ts +86 -0
- package/src/tools/undo-edit.ts +145 -0
- package/src/tools/undo-history.ts +22 -0
- package/src/tools/write.ts +274 -0
- package/src/tui/code-cell.ts +108 -0
- package/src/tui/file-list.ts +47 -0
- package/src/tui/index.ts +11 -0
- package/src/tui/output-block.ts +144 -0
- package/src/tui/status-line.ts +39 -0
- package/src/tui/tree-list.ts +53 -0
- package/src/tui/types.ts +16 -0
- package/src/tui/utils.ts +116 -0
- package/src/utils/changelog.ts +98 -0
- package/src/utils/event-bus.ts +33 -0
- package/src/utils/external-editor.ts +59 -0
- package/src/utils/file-display-mode.ts +36 -0
- package/src/utils/file-mentions.ts +384 -0
- package/src/utils/frontmatter.ts +101 -0
- package/src/utils/fuzzy.ts +108 -0
- package/src/utils/ignore-files.ts +119 -0
- package/src/utils/image-convert.ts +27 -0
- package/src/utils/image-resize.ts +236 -0
- package/src/utils/mime.ts +30 -0
- package/src/utils/open.ts +20 -0
- package/src/utils/shell-snapshot.ts +199 -0
- package/src/utils/timings.ts +26 -0
- package/src/utils/title-generator.ts +167 -0
- package/src/utils/tools-manager.ts +362 -0
- package/src/web/scrapers/artifacthub.ts +215 -0
- package/src/web/scrapers/arxiv.ts +88 -0
- package/src/web/scrapers/aur.ts +175 -0
- package/src/web/scrapers/biorxiv.ts +141 -0
- package/src/web/scrapers/bluesky.ts +284 -0
- package/src/web/scrapers/brew.ts +177 -0
- package/src/web/scrapers/cheatsh.ts +78 -0
- package/src/web/scrapers/chocolatey.ts +158 -0
- package/src/web/scrapers/choosealicense.ts +110 -0
- package/src/web/scrapers/cisa-kev.ts +100 -0
- package/src/web/scrapers/clojars.ts +180 -0
- package/src/web/scrapers/coingecko.ts +184 -0
- package/src/web/scrapers/crates-io.ts +128 -0
- package/src/web/scrapers/crossref.ts +149 -0
- package/src/web/scrapers/devto.ts +177 -0
- package/src/web/scrapers/discogs.ts +307 -0
- package/src/web/scrapers/discourse.ts +221 -0
- package/src/web/scrapers/dockerhub.ts +160 -0
- package/src/web/scrapers/fdroid.ts +158 -0
- package/src/web/scrapers/firefox-addons.ts +214 -0
- package/src/web/scrapers/flathub.ts +239 -0
- package/src/web/scrapers/github-gist.ts +68 -0
- package/src/web/scrapers/github.ts +490 -0
- package/src/web/scrapers/gitlab.ts +456 -0
- package/src/web/scrapers/go-pkg.ts +275 -0
- package/src/web/scrapers/hackage.ts +94 -0
- package/src/web/scrapers/hackernews.ts +208 -0
- package/src/web/scrapers/hex.ts +121 -0
- package/src/web/scrapers/huggingface.ts +385 -0
- package/src/web/scrapers/iacr.ts +86 -0
- package/src/web/scrapers/index.ts +249 -0
- package/src/web/scrapers/jetbrains-marketplace.ts +169 -0
- package/src/web/scrapers/lemmy.ts +220 -0
- package/src/web/scrapers/lobsters.ts +186 -0
- package/src/web/scrapers/mastodon.ts +310 -0
- package/src/web/scrapers/maven.ts +152 -0
- package/src/web/scrapers/mdn.ts +172 -0
- package/src/web/scrapers/metacpan.ts +253 -0
- package/src/web/scrapers/musicbrainz.ts +272 -0
- package/src/web/scrapers/npm.ts +114 -0
- package/src/web/scrapers/nuget.ts +205 -0
- package/src/web/scrapers/nvd.ts +243 -0
- package/src/web/scrapers/ollama.ts +265 -0
- package/src/web/scrapers/open-vsx.ts +119 -0
- package/src/web/scrapers/opencorporates.ts +275 -0
- package/src/web/scrapers/openlibrary.ts +319 -0
- package/src/web/scrapers/orcid.ts +298 -0
- package/src/web/scrapers/osv.ts +192 -0
- package/src/web/scrapers/packagist.ts +174 -0
- package/src/web/scrapers/pub-dev.ts +185 -0
- package/src/web/scrapers/pubmed.ts +177 -0
- package/src/web/scrapers/pypi.ts +129 -0
- package/src/web/scrapers/rawg.ts +124 -0
- package/src/web/scrapers/readthedocs.ts +125 -0
- package/src/web/scrapers/reddit.ts +104 -0
- package/src/web/scrapers/repology.ts +262 -0
- package/src/web/scrapers/rfc.ts +209 -0
- package/src/web/scrapers/rubygems.ts +117 -0
- package/src/web/scrapers/searchcode.ts +217 -0
- package/src/web/scrapers/sec-edgar.ts +274 -0
- package/src/web/scrapers/semantic-scholar.ts +190 -0
- package/src/web/scrapers/snapcraft.ts +200 -0
- package/src/web/scrapers/sourcegraph.ts +373 -0
- package/src/web/scrapers/spdx.ts +121 -0
- package/src/web/scrapers/spotify.ts +217 -0
- package/src/web/scrapers/stackoverflow.ts +124 -0
- package/src/web/scrapers/terraform.ts +304 -0
- package/src/web/scrapers/tldr.ts +51 -0
- package/src/web/scrapers/twitter.ts +97 -0
- package/src/web/scrapers/types.ts +200 -0
- package/src/web/scrapers/utils.ts +142 -0
- package/src/web/scrapers/vimeo.ts +152 -0
- package/src/web/scrapers/vscode-marketplace.ts +195 -0
- package/src/web/scrapers/w3c.ts +163 -0
- package/src/web/scrapers/wikidata.ts +357 -0
- package/src/web/scrapers/wikipedia.ts +95 -0
- package/src/web/scrapers/youtube.ts +312 -0
- package/src/web/search/auth.ts +178 -0
- package/src/web/search/index.ts +598 -0
- package/src/web/search/provider.ts +77 -0
- package/src/web/search/providers/anthropic.ts +284 -0
- package/src/web/search/providers/base.ts +22 -0
- package/src/web/search/providers/brave.ts +165 -0
- package/src/web/search/providers/codex.ts +377 -0
- package/src/web/search/providers/exa.ts +158 -0
- package/src/web/search/providers/gemini.ts +437 -0
- package/src/web/search/providers/jina.ts +99 -0
- package/src/web/search/providers/kimi.ts +196 -0
- package/src/web/search/providers/perplexity.ts +546 -0
- package/src/web/search/providers/synthetic.ts +136 -0
- package/src/web/search/providers/zai.ts +352 -0
- package/src/web/search/render.ts +299 -0
- package/src/web/search/types.ts +437 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for edit tool TUI rendering.
|
|
3
|
+
*/
|
|
4
|
+
import type { ToolCallContext } from "@nghyane/arcane-agent";
|
|
5
|
+
import type { Component } from "@nghyane/arcane-tui";
|
|
6
|
+
import { Text } from "@nghyane/arcane-tui";
|
|
7
|
+
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
8
|
+
import type { FileDiagnosticsResult } from "../lsp";
|
|
9
|
+
import { renderDiff as renderDiffColored } from "../modes/components/diff";
|
|
10
|
+
import { getLanguageFromPath, type Theme } from "../modes/theme/theme";
|
|
11
|
+
import type { OutputMeta } from "../tools/output-meta";
|
|
12
|
+
import {
|
|
13
|
+
formatExpandHint,
|
|
14
|
+
formatStatusIcon,
|
|
15
|
+
getDiffStats,
|
|
16
|
+
PREVIEW_LIMITS,
|
|
17
|
+
replaceTabs,
|
|
18
|
+
shortenPath,
|
|
19
|
+
ToolUIKit,
|
|
20
|
+
truncateDiffByHunk,
|
|
21
|
+
} from "../tools/render-utils";
|
|
22
|
+
import { Ellipsis, Hasher, type RenderCache, renderStatusLine, truncateToWidth } from "../tui";
|
|
23
|
+
import type { DiffError, DiffResult, Operation } from "./types";
|
|
24
|
+
|
|
25
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
26
|
+
// LSP Batching
|
|
27
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
28
|
+
|
|
29
|
+
const LSP_BATCH_TOOLS = new Set(["edit", "write"]);
|
|
30
|
+
|
|
31
|
+
export function getLspBatchRequest(toolCall: ToolCallContext | undefined): { id: string; flush: boolean } | undefined {
|
|
32
|
+
if (!toolCall) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const hasOtherWrites = toolCall.toolCalls.some(
|
|
36
|
+
(call, index) => index !== toolCall.index && LSP_BATCH_TOOLS.has(call.name),
|
|
37
|
+
);
|
|
38
|
+
if (!hasOtherWrites) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
const hasLaterWrites = toolCall.toolCalls.slice(toolCall.index + 1).some(call => LSP_BATCH_TOOLS.has(call.name));
|
|
42
|
+
return { id: toolCall.batchId, flush: !hasLaterWrites };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
46
|
+
// Tool Details Types
|
|
47
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
48
|
+
|
|
49
|
+
export interface EditToolDetails {
|
|
50
|
+
/** Unified diff of the changes made */
|
|
51
|
+
diff: string;
|
|
52
|
+
/** Line number of the first change in the new file (for editor navigation) */
|
|
53
|
+
firstChangedLine?: number;
|
|
54
|
+
/** Diagnostic result (if available) */
|
|
55
|
+
diagnostics?: FileDiagnosticsResult;
|
|
56
|
+
/** Operation type (patch mode only) */
|
|
57
|
+
op?: Operation;
|
|
58
|
+
/** New path after move/rename (patch mode only) */
|
|
59
|
+
rename?: string;
|
|
60
|
+
/** Structured output metadata */
|
|
61
|
+
meta?: OutputMeta;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
65
|
+
// TUI Renderer
|
|
66
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
67
|
+
|
|
68
|
+
interface EditRenderArgs {
|
|
69
|
+
path?: string;
|
|
70
|
+
file_path?: string;
|
|
71
|
+
oldText?: string;
|
|
72
|
+
newText?: string;
|
|
73
|
+
patch?: string;
|
|
74
|
+
all?: boolean;
|
|
75
|
+
// Patch mode fields
|
|
76
|
+
op?: Operation;
|
|
77
|
+
rename?: string;
|
|
78
|
+
diff?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Computed preview diff (used when tool args don't include a diff, e.g. hashline mode).
|
|
81
|
+
*/
|
|
82
|
+
previewDiff?: string;
|
|
83
|
+
// Hashline mode fields
|
|
84
|
+
edits?: HashlineEditPreview[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
type HashlineEditPreview =
|
|
88
|
+
| { target: string; new_content: string[] }
|
|
89
|
+
| { first: string; last: string; new_content: string[] }
|
|
90
|
+
| { before?: string; after?: string; inserted_lines: string[] }
|
|
91
|
+
| { old_text: string; new_text: string; all?: boolean };
|
|
92
|
+
|
|
93
|
+
/** Extended context for edit tool rendering */
|
|
94
|
+
export interface EditRenderContext {
|
|
95
|
+
/** Pre-computed diff preview (computed before tool executes) */
|
|
96
|
+
editDiffPreview?: DiffResult | DiffError;
|
|
97
|
+
/** Function to render diff text with syntax highlighting */
|
|
98
|
+
renderDiff?: (diffText: string, options?: { filePath?: string }) => string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const EDIT_STREAMING_PREVIEW_LINES = 12;
|
|
102
|
+
|
|
103
|
+
function countLines(text: string): number {
|
|
104
|
+
if (!text) return 0;
|
|
105
|
+
return text.split("\n").length;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function formatStreamingDiff(diff: string, rawPath: string, uiTheme: Theme, label = "streaming"): string {
|
|
109
|
+
if (!diff) return "";
|
|
110
|
+
const lines = diff.split("\n");
|
|
111
|
+
const total = lines.length;
|
|
112
|
+
const displayLines = lines.slice(-EDIT_STREAMING_PREVIEW_LINES);
|
|
113
|
+
const hidden = total - displayLines.length;
|
|
114
|
+
let text = "\n\n";
|
|
115
|
+
if (hidden > 0) {
|
|
116
|
+
text += uiTheme.fg("dim", `… (${hidden} earlier lines)\n`);
|
|
117
|
+
}
|
|
118
|
+
text += renderDiffColored(displayLines.join("\n"), { filePath: rawPath });
|
|
119
|
+
text += uiTheme.fg("dim", `\n… (${label})`);
|
|
120
|
+
return text;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function formatStreamingHashlineEdits(edits: unknown[], uiTheme: Theme, ui: ToolUIKit): string {
|
|
124
|
+
const MAX_EDITS = 4;
|
|
125
|
+
const MAX_DST_LINES = 8;
|
|
126
|
+
let text = "\n\n";
|
|
127
|
+
text += uiTheme.fg("dim", `[${edits.length} hashline edit${edits.length === 1 ? "" : "s"}]`);
|
|
128
|
+
text += "\n";
|
|
129
|
+
let shownEdits = 0;
|
|
130
|
+
let shownDstLines = 0;
|
|
131
|
+
for (const edit of edits) {
|
|
132
|
+
shownEdits++;
|
|
133
|
+
if (shownEdits > MAX_EDITS) break;
|
|
134
|
+
const formatted = formatHashlineEdit(edit);
|
|
135
|
+
text += uiTheme.fg("toolOutput", ui.truncate(replaceTabs(formatted.srcLabel), 120));
|
|
136
|
+
text += "\n";
|
|
137
|
+
if (formatted.dst === "") {
|
|
138
|
+
text += uiTheme.fg("dim", ui.truncate(" (delete)", 120));
|
|
139
|
+
text += "\n";
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
for (const dstLine of formatted.dst.split("\n")) {
|
|
143
|
+
shownDstLines++;
|
|
144
|
+
if (shownDstLines > MAX_DST_LINES) break;
|
|
145
|
+
text += uiTheme.fg("toolOutput", ui.truncate(replaceTabs(`+ ${dstLine}`), 120));
|
|
146
|
+
text += "\n";
|
|
147
|
+
}
|
|
148
|
+
if (shownDstLines > MAX_DST_LINES) break;
|
|
149
|
+
}
|
|
150
|
+
if (edits.length > MAX_EDITS) {
|
|
151
|
+
text += uiTheme.fg("dim", `… (${edits.length - MAX_EDITS} more edits)`);
|
|
152
|
+
}
|
|
153
|
+
if (shownDstLines > MAX_DST_LINES) {
|
|
154
|
+
text += uiTheme.fg("dim", `\n… (${shownDstLines - MAX_DST_LINES} more dst lines)`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return text.trimEnd();
|
|
158
|
+
function formatHashlineEdit(edit: unknown): { srcLabel: string; dst: string } {
|
|
159
|
+
const asRecord = (value: unknown): Record<string, unknown> | undefined => {
|
|
160
|
+
if (typeof value === "object" && value !== null) return value as Record<string, unknown>;
|
|
161
|
+
return undefined;
|
|
162
|
+
};
|
|
163
|
+
const editRecord = asRecord(edit);
|
|
164
|
+
if (!editRecord) {
|
|
165
|
+
return {
|
|
166
|
+
srcLabel: "• (incomplete edit)",
|
|
167
|
+
dst: "",
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
if ("target" in editRecord) {
|
|
171
|
+
const target = typeof editRecord.target === "string" ? editRecord.target : "…";
|
|
172
|
+
const newContent = editRecord.new_content;
|
|
173
|
+
return {
|
|
174
|
+
srcLabel: `• line ${target}`,
|
|
175
|
+
dst: Array.isArray(newContent) ? (newContent as string[]).join("\n") : "",
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
if ("first" in editRecord || "last" in editRecord) {
|
|
179
|
+
const first = typeof editRecord.first === "string" ? editRecord.first : "…";
|
|
180
|
+
const last = typeof editRecord.last === "string" ? editRecord.last : "…";
|
|
181
|
+
const newContent = editRecord.new_content;
|
|
182
|
+
return {
|
|
183
|
+
srcLabel: `• range ${first}..${last}`,
|
|
184
|
+
dst: Array.isArray(newContent) ? (newContent as string[]).join("\n") : "",
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if ("old_text" in editRecord || "new_text" in editRecord) {
|
|
188
|
+
const all = typeof editRecord.all === "boolean" ? editRecord.all : false;
|
|
189
|
+
return {
|
|
190
|
+
srcLabel: `• replace old_text→new_text${all ? " (all)" : ""}`,
|
|
191
|
+
dst: typeof editRecord.new_text === "string" ? editRecord.new_text : "",
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
if ("inserted_lines" in editRecord || "before" in editRecord || "after" in editRecord) {
|
|
195
|
+
const after = typeof editRecord.after === "string" ? editRecord.after : undefined;
|
|
196
|
+
const before = typeof editRecord.before === "string" ? editRecord.before : undefined;
|
|
197
|
+
const insertedLines = editRecord.inserted_lines;
|
|
198
|
+
const text = Array.isArray(insertedLines) ? (insertedLines as string[]).join("\n") : "";
|
|
199
|
+
const refs = [after, before].filter(Boolean).join("..") || "…";
|
|
200
|
+
return {
|
|
201
|
+
srcLabel: `• insert ${refs}`,
|
|
202
|
+
dst: text,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
srcLabel: "• (incomplete edit)",
|
|
207
|
+
dst: "",
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function formatMetadataLine(lineCount: number | null, language: string | undefined, uiTheme: Theme): string {
|
|
212
|
+
const icon = uiTheme.getLangIcon(language);
|
|
213
|
+
if (lineCount !== null) {
|
|
214
|
+
return uiTheme.fg("dim", `${icon} ${lineCount} lines`);
|
|
215
|
+
}
|
|
216
|
+
return uiTheme.fg("dim", `${icon}`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function renderDiffSection(
|
|
220
|
+
diff: string,
|
|
221
|
+
rawPath: string,
|
|
222
|
+
expanded: boolean,
|
|
223
|
+
uiTheme: Theme,
|
|
224
|
+
ui: ToolUIKit,
|
|
225
|
+
renderDiffFn: (t: string, o?: { filePath?: string }) => string,
|
|
226
|
+
): string {
|
|
227
|
+
let text = "";
|
|
228
|
+
const diffStats = getDiffStats(diff);
|
|
229
|
+
text += `\n${uiTheme.fg("dim", uiTheme.format.bracketLeft)}${ui.formatDiffStats(
|
|
230
|
+
diffStats.added,
|
|
231
|
+
diffStats.removed,
|
|
232
|
+
diffStats.hunks,
|
|
233
|
+
)}${uiTheme.fg("dim", uiTheme.format.bracketRight)}`;
|
|
234
|
+
|
|
235
|
+
const {
|
|
236
|
+
text: truncatedDiff,
|
|
237
|
+
hiddenHunks,
|
|
238
|
+
hiddenLines,
|
|
239
|
+
} = expanded
|
|
240
|
+
? { text: diff, hiddenHunks: 0, hiddenLines: 0 }
|
|
241
|
+
: truncateDiffByHunk(diff, PREVIEW_LIMITS.DIFF_COLLAPSED_HUNKS, PREVIEW_LIMITS.DIFF_COLLAPSED_LINES);
|
|
242
|
+
|
|
243
|
+
text += `\n\n${renderDiffFn(truncatedDiff, { filePath: rawPath })}`;
|
|
244
|
+
if (!expanded && (hiddenHunks > 0 || hiddenLines > 0)) {
|
|
245
|
+
const remainder: string[] = [];
|
|
246
|
+
if (hiddenHunks > 0) remainder.push(`${hiddenHunks} more hunks`);
|
|
247
|
+
if (hiddenLines > 0) remainder.push(`${hiddenLines} more lines`);
|
|
248
|
+
text += uiTheme.fg("toolOutput", `\n… (${remainder.join(", ")}) ${formatExpandHint(uiTheme)}`);
|
|
249
|
+
}
|
|
250
|
+
return text;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export const editToolRenderer = {
|
|
254
|
+
mergeCallAndResult: true,
|
|
255
|
+
|
|
256
|
+
renderCall(args: EditRenderArgs, options: RenderResultOptions, uiTheme: Theme): Component {
|
|
257
|
+
const ui = new ToolUIKit(uiTheme);
|
|
258
|
+
const rawPath = args.file_path || args.path || "";
|
|
259
|
+
const filePath = shortenPath(rawPath);
|
|
260
|
+
const editLanguage = getLanguageFromPath(rawPath) ?? "text";
|
|
261
|
+
const editIcon = uiTheme.fg("muted", uiTheme.getLangIcon(editLanguage));
|
|
262
|
+
let pathDisplay = filePath ? uiTheme.fg("accent", filePath) : uiTheme.fg("toolOutput", "…");
|
|
263
|
+
|
|
264
|
+
// Add arrow for move/rename operations
|
|
265
|
+
if (args.rename) {
|
|
266
|
+
pathDisplay += ` ${uiTheme.fg("dim", "→")} ${uiTheme.fg("accent", shortenPath(args.rename))}`;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Show operation type for patch mode
|
|
270
|
+
const opTitle = args.op === "create" ? "Create" : args.op === "delete" ? "Delete" : "Edit";
|
|
271
|
+
const spinner =
|
|
272
|
+
options?.spinnerFrame !== undefined ? formatStatusIcon("running", uiTheme, options.spinnerFrame) : "";
|
|
273
|
+
let text = `${ui.title(opTitle)} ${spinner ? `${spinner} ` : ""}${editIcon} ${pathDisplay}`;
|
|
274
|
+
|
|
275
|
+
// Show streaming preview of diff/content
|
|
276
|
+
if (args.previewDiff) {
|
|
277
|
+
text += formatStreamingDiff(args.previewDiff, rawPath, uiTheme, "preview");
|
|
278
|
+
} else if (args.diff && args.op) {
|
|
279
|
+
text += formatStreamingDiff(args.diff, rawPath, uiTheme);
|
|
280
|
+
} else if (args.edits && args.edits.length > 0) {
|
|
281
|
+
text += formatStreamingHashlineEdits(args.edits, uiTheme, ui);
|
|
282
|
+
} else if (args.diff) {
|
|
283
|
+
const previewLines = args.diff.split("\n");
|
|
284
|
+
const maxLines = 6;
|
|
285
|
+
text += "\n\n";
|
|
286
|
+
for (const line of previewLines.slice(0, maxLines)) {
|
|
287
|
+
text += `${uiTheme.fg("toolOutput", ui.truncate(replaceTabs(line), 80))}\n`;
|
|
288
|
+
}
|
|
289
|
+
if (previewLines.length > maxLines) {
|
|
290
|
+
text += uiTheme.fg("dim", `… ${previewLines.length - maxLines} more lines`);
|
|
291
|
+
}
|
|
292
|
+
} else if (args.newText || args.patch) {
|
|
293
|
+
const previewLines = (args.newText ?? args.patch ?? "").split("\n");
|
|
294
|
+
const maxLines = 6;
|
|
295
|
+
text += "\n\n";
|
|
296
|
+
for (const line of previewLines.slice(0, maxLines)) {
|
|
297
|
+
text += `${uiTheme.fg("toolOutput", ui.truncate(replaceTabs(line), 80))}\n`;
|
|
298
|
+
}
|
|
299
|
+
if (previewLines.length > maxLines) {
|
|
300
|
+
text += uiTheme.fg("dim", `… ${previewLines.length - maxLines} more lines`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return new Text(text, 0, 0);
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
renderResult(
|
|
308
|
+
result: { content: Array<{ type: string; text?: string }>; details?: EditToolDetails; isError?: boolean },
|
|
309
|
+
options: RenderResultOptions & { renderContext?: EditRenderContext },
|
|
310
|
+
uiTheme: Theme,
|
|
311
|
+
args?: EditRenderArgs,
|
|
312
|
+
): Component {
|
|
313
|
+
const ui = new ToolUIKit(uiTheme);
|
|
314
|
+
const rawPath = args?.file_path || args?.path || "";
|
|
315
|
+
const filePath = shortenPath(rawPath);
|
|
316
|
+
const editLanguage = getLanguageFromPath(rawPath) ?? "text";
|
|
317
|
+
const editIcon = uiTheme.fg("muted", uiTheme.getLangIcon(editLanguage));
|
|
318
|
+
|
|
319
|
+
const op = args?.op || result.details?.op;
|
|
320
|
+
const rename = args?.rename || result.details?.rename;
|
|
321
|
+
const opTitle = op === "create" ? "Create" : op === "delete" ? "Delete" : "Edit";
|
|
322
|
+
|
|
323
|
+
// Pre-compute metadata line (static across renders)
|
|
324
|
+
const lineCountSource = args?.newText ?? args?.oldText ?? args?.diff ?? args?.patch ?? null;
|
|
325
|
+
const metadataLine =
|
|
326
|
+
op !== "delete"
|
|
327
|
+
? `\n${formatMetadataLine(lineCountSource ? countLines(lineCountSource) : null, editLanguage, uiTheme)}`
|
|
328
|
+
: "";
|
|
329
|
+
|
|
330
|
+
// Pre-compute error text (static)
|
|
331
|
+
const errorText = result.isError ? (result.content?.find(c => c.type === "text")?.text ?? "") : "";
|
|
332
|
+
|
|
333
|
+
let cached: RenderCache | undefined;
|
|
334
|
+
|
|
335
|
+
return {
|
|
336
|
+
render(width) {
|
|
337
|
+
const { expanded, renderContext } = options;
|
|
338
|
+
const editDiffPreview = renderContext?.editDiffPreview;
|
|
339
|
+
const renderDiffFn = renderContext?.renderDiff ?? ((t: string) => t);
|
|
340
|
+
const key = new Hasher().bool(expanded).u32(width).digest();
|
|
341
|
+
if (cached?.key === key) return cached.lines;
|
|
342
|
+
|
|
343
|
+
// Build path display with line number
|
|
344
|
+
let pathDisplay = filePath ? uiTheme.fg("accent", filePath) : uiTheme.fg("toolOutput", "…");
|
|
345
|
+
const firstChangedLine =
|
|
346
|
+
(editDiffPreview && "firstChangedLine" in editDiffPreview
|
|
347
|
+
? editDiffPreview.firstChangedLine
|
|
348
|
+
: undefined) || (result.details && !result.isError ? result.details.firstChangedLine : undefined);
|
|
349
|
+
if (firstChangedLine) {
|
|
350
|
+
pathDisplay += uiTheme.fg("warning", `:${firstChangedLine}`);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Add arrow for rename operations
|
|
354
|
+
if (rename) {
|
|
355
|
+
pathDisplay += ` ${uiTheme.fg("dim", "→")} ${uiTheme.fg("accent", shortenPath(rename))}`;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const header = renderStatusLine(
|
|
359
|
+
{
|
|
360
|
+
icon: result.isError ? "error" : "success",
|
|
361
|
+
title: opTitle,
|
|
362
|
+
description: `${editIcon} ${pathDisplay}`,
|
|
363
|
+
},
|
|
364
|
+
uiTheme,
|
|
365
|
+
);
|
|
366
|
+
let text = header;
|
|
367
|
+
text += metadataLine;
|
|
368
|
+
|
|
369
|
+
if (result.isError) {
|
|
370
|
+
if (errorText) {
|
|
371
|
+
text += `\n\n${uiTheme.fg("error", replaceTabs(errorText))}`;
|
|
372
|
+
}
|
|
373
|
+
} else if (result.details?.diff) {
|
|
374
|
+
text += renderDiffSection(result.details.diff, rawPath, expanded, uiTheme, ui, renderDiffFn);
|
|
375
|
+
} else if (editDiffPreview) {
|
|
376
|
+
if ("error" in editDiffPreview) {
|
|
377
|
+
text += `\n\n${uiTheme.fg("error", replaceTabs(editDiffPreview.error))}`;
|
|
378
|
+
} else if (editDiffPreview.diff) {
|
|
379
|
+
text += renderDiffSection(editDiffPreview.diff, rawPath, expanded, uiTheme, ui, renderDiffFn);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Show LSP diagnostics if available
|
|
384
|
+
if (result.details?.diagnostics) {
|
|
385
|
+
text += ui.formatDiagnostics(result.details.diagnostics, expanded, (fp: string) =>
|
|
386
|
+
uiTheme.getLangIcon(getLanguageFromPath(fp)),
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const lines =
|
|
391
|
+
width > 0 ? text.split("\n").map(line => truncateToWidth(line, width, Ellipsis.Omit)) : text.split("\n");
|
|
392
|
+
cached = { key, lines };
|
|
393
|
+
return lines;
|
|
394
|
+
},
|
|
395
|
+
invalidate() {
|
|
396
|
+
cached = undefined;
|
|
397
|
+
},
|
|
398
|
+
};
|
|
399
|
+
},
|
|
400
|
+
};
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the edit tool module.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
6
|
+
// File System Abstraction
|
|
7
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
8
|
+
|
|
9
|
+
/** Abstraction for file system operations to support LSP writethrough */
|
|
10
|
+
export interface FileSystem {
|
|
11
|
+
exists(path: string): Promise<boolean>;
|
|
12
|
+
read(path: string): Promise<string>;
|
|
13
|
+
readBinary?: (path: string) => Promise<Uint8Array>;
|
|
14
|
+
write(path: string, content: string): Promise<void>;
|
|
15
|
+
delete(path: string): Promise<void>;
|
|
16
|
+
mkdir(path: string): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
20
|
+
// Fuzzy Matching Types
|
|
21
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
22
|
+
|
|
23
|
+
/** Result of a fuzzy match operation */
|
|
24
|
+
export interface FuzzyMatch {
|
|
25
|
+
/** The actual text that was matched */
|
|
26
|
+
actualText: string;
|
|
27
|
+
/** Character index where the match starts */
|
|
28
|
+
startIndex: number;
|
|
29
|
+
/** Line number where the match starts (1-indexed) */
|
|
30
|
+
startLine: number;
|
|
31
|
+
/** Confidence score (0-1, where 1 is exact match) */
|
|
32
|
+
confidence: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Outcome of attempting to find a match */
|
|
36
|
+
export interface MatchOutcome {
|
|
37
|
+
/** The match if found with sufficient confidence */
|
|
38
|
+
match?: FuzzyMatch;
|
|
39
|
+
/** The closest match found (may be below threshold) */
|
|
40
|
+
closest?: FuzzyMatch;
|
|
41
|
+
/** Number of occurrences if multiple exact matches found */
|
|
42
|
+
occurrences?: number;
|
|
43
|
+
/** Line numbers where occurrences were found (1-indexed) */
|
|
44
|
+
occurrenceLines?: number[];
|
|
45
|
+
/** Preview snippets for each occurrence (up to 5) */
|
|
46
|
+
occurrencePreviews?: string[];
|
|
47
|
+
/** Number of fuzzy matches above threshold */
|
|
48
|
+
fuzzyMatches?: number;
|
|
49
|
+
/** True when a dominant fuzzy match was accepted despite multiple candidates */
|
|
50
|
+
dominantFuzzy?: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Result of a sequence search */
|
|
54
|
+
export type SequenceMatchStrategy =
|
|
55
|
+
| "exact"
|
|
56
|
+
| "trim-trailing"
|
|
57
|
+
| "trim"
|
|
58
|
+
| "comment-prefix"
|
|
59
|
+
| "unicode"
|
|
60
|
+
| "prefix"
|
|
61
|
+
| "substring"
|
|
62
|
+
| "fuzzy"
|
|
63
|
+
| "fuzzy-dominant"
|
|
64
|
+
| "character";
|
|
65
|
+
|
|
66
|
+
export interface SequenceSearchResult {
|
|
67
|
+
/** Starting line index of the match (0-indexed) */
|
|
68
|
+
index: number | undefined;
|
|
69
|
+
/** Confidence score (1.0 for exact match, lower for fuzzy) */
|
|
70
|
+
confidence: number;
|
|
71
|
+
/** Number of matches at the same confidence level (for ambiguity detection) */
|
|
72
|
+
matchCount?: number;
|
|
73
|
+
/** Sample of matching indices (0-indexed, up to a small limit) */
|
|
74
|
+
matchIndices?: number[];
|
|
75
|
+
/** Matching strategy used */
|
|
76
|
+
strategy?: SequenceMatchStrategy;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Result of a context line search */
|
|
80
|
+
export type ContextMatchStrategy = "exact" | "trim" | "unicode" | "prefix" | "substring" | "fuzzy";
|
|
81
|
+
|
|
82
|
+
export interface ContextLineResult {
|
|
83
|
+
/** Index of the matching line (0-indexed) */
|
|
84
|
+
index: number | undefined;
|
|
85
|
+
/** Confidence score (1.0 for exact match, lower for fuzzy) */
|
|
86
|
+
confidence: number;
|
|
87
|
+
/** Number of matches at the same confidence level (for ambiguity detection) */
|
|
88
|
+
matchCount?: number;
|
|
89
|
+
/** Sample of matching indices (0-indexed, up to a small limit) */
|
|
90
|
+
matchIndices?: number[];
|
|
91
|
+
/** Matching strategy used */
|
|
92
|
+
strategy?: ContextMatchStrategy;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
96
|
+
// Patch Types
|
|
97
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
98
|
+
|
|
99
|
+
export type Operation = "create" | "delete" | "update";
|
|
100
|
+
|
|
101
|
+
/** Input for a patch operation */
|
|
102
|
+
export interface PatchInput {
|
|
103
|
+
/** File path (relative or absolute) */
|
|
104
|
+
path: string;
|
|
105
|
+
/** Operation type */
|
|
106
|
+
op: Operation;
|
|
107
|
+
/** New path for rename (update only) */
|
|
108
|
+
rename?: string;
|
|
109
|
+
/** File content (create) or diff hunks (update) */
|
|
110
|
+
diff?: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Normalized patch input used internally by the applicator. */
|
|
114
|
+
export interface NormalizedPatchInput {
|
|
115
|
+
path: string;
|
|
116
|
+
op: Operation;
|
|
117
|
+
rename?: string;
|
|
118
|
+
diff?: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function normalizePatchInput(input: PatchInput): NormalizedPatchInput {
|
|
122
|
+
return {
|
|
123
|
+
path: input.path,
|
|
124
|
+
op: input.op ?? "update",
|
|
125
|
+
rename: input.rename,
|
|
126
|
+
diff: input.diff,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** A single hunk/chunk in a diff */
|
|
131
|
+
export interface DiffHunk {
|
|
132
|
+
/** Context line to narrow down position (e.g., class/method definition) */
|
|
133
|
+
changeContext?: string;
|
|
134
|
+
/** 1-based line hint from unified diff headers (old file) */
|
|
135
|
+
oldStartLine?: number;
|
|
136
|
+
/** 1-based line hint from unified diff headers (new file) */
|
|
137
|
+
newStartLine?: number;
|
|
138
|
+
/** True if the hunk contains context lines (space-prefixed) */
|
|
139
|
+
hasContextLines: boolean;
|
|
140
|
+
/** Lines to be replaced (old content) */
|
|
141
|
+
oldLines: string[];
|
|
142
|
+
/** Lines to replace with (new content) */
|
|
143
|
+
newLines: string[];
|
|
144
|
+
/** If true, oldLines must occur at end of file */
|
|
145
|
+
isEndOfFile: boolean;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Describes a change made to a file */
|
|
149
|
+
export interface FileChange {
|
|
150
|
+
type: Operation;
|
|
151
|
+
path: string;
|
|
152
|
+
newPath?: string;
|
|
153
|
+
oldContent?: string;
|
|
154
|
+
newContent?: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Result of applying a patch */
|
|
158
|
+
export interface ApplyPatchResult {
|
|
159
|
+
change: FileChange;
|
|
160
|
+
warnings?: string[];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Options for applying a patch */
|
|
164
|
+
export interface ApplyPatchOptions {
|
|
165
|
+
/** Working directory for resolving relative paths */
|
|
166
|
+
cwd: string;
|
|
167
|
+
/** Dry run - compute changes without writing */
|
|
168
|
+
dryRun?: boolean;
|
|
169
|
+
/** Similarity threshold for fuzzy matching */
|
|
170
|
+
fuzzyThreshold?: number;
|
|
171
|
+
/** Allow fuzzy/partial matching when applying hunks */
|
|
172
|
+
allowFuzzy?: boolean;
|
|
173
|
+
/** File system abstraction (defaults to Bun-based implementation) */
|
|
174
|
+
fs?: FileSystem;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
178
|
+
// Diff Generation Types
|
|
179
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
180
|
+
|
|
181
|
+
/** Result of generating a diff */
|
|
182
|
+
export interface DiffResult {
|
|
183
|
+
/** The unified diff string */
|
|
184
|
+
diff: string;
|
|
185
|
+
/** Line number of the first change in the new file */
|
|
186
|
+
firstChangedLine: number | undefined;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Error from diff computation */
|
|
190
|
+
export interface DiffError {
|
|
191
|
+
error: string;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
195
|
+
// Hashline Types
|
|
196
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Hashline edit operation/input types are schema-derived in `patch/index.ts`
|
|
200
|
+
* via `Static<typeof hashlineEditItemSchema>` and `Static<typeof hashlineEditSchema>`.
|
|
201
|
+
*/
|
|
202
|
+
|
|
203
|
+
/** A single hash mismatch found during validation */
|
|
204
|
+
export interface HashMismatch {
|
|
205
|
+
/** 1-indexed line number */
|
|
206
|
+
line: number;
|
|
207
|
+
/** Hash the caller provided */
|
|
208
|
+
expected: string;
|
|
209
|
+
/** Hash computed from the current file content */
|
|
210
|
+
actual: string;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
214
|
+
// Error Classes
|
|
215
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
216
|
+
|
|
217
|
+
export class ParseError extends Error {
|
|
218
|
+
constructor(
|
|
219
|
+
message: string,
|
|
220
|
+
public readonly lineNumber?: number,
|
|
221
|
+
) {
|
|
222
|
+
super(lineNumber !== undefined ? `Line ${lineNumber}: ${message}` : message);
|
|
223
|
+
this.name = "ParseError";
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export class ApplyPatchError extends Error {
|
|
228
|
+
constructor(message: string) {
|
|
229
|
+
super(message);
|
|
230
|
+
this.name = "ApplyPatchError";
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export class EditMatchError extends Error {
|
|
235
|
+
constructor(
|
|
236
|
+
public readonly path: string,
|
|
237
|
+
public readonly searchText: string,
|
|
238
|
+
public readonly closest: FuzzyMatch | undefined,
|
|
239
|
+
public readonly options: { allowFuzzy: boolean; threshold: number; fuzzyMatches?: number },
|
|
240
|
+
) {
|
|
241
|
+
super(EditMatchError.formatMessage(path, searchText, closest, options));
|
|
242
|
+
this.name = "EditMatchError";
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
static formatMessage(
|
|
246
|
+
path: string,
|
|
247
|
+
searchText: string,
|
|
248
|
+
closest: FuzzyMatch | undefined,
|
|
249
|
+
options: { allowFuzzy: boolean; threshold: number; fuzzyMatches?: number },
|
|
250
|
+
): string {
|
|
251
|
+
if (!closest) {
|
|
252
|
+
return options.allowFuzzy
|
|
253
|
+
? `Could not find a close enough match in ${path}.`
|
|
254
|
+
: `Could not find the exact text in ${path}. The old text must match exactly including all whitespace and newlines.`;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const similarity = Math.round(closest.confidence * 100);
|
|
258
|
+
const searchLines = searchText.split("\n");
|
|
259
|
+
const actualLines = closest.actualText.split("\n");
|
|
260
|
+
const { oldLine, newLine } = findFirstDifferentLine(searchLines, actualLines);
|
|
261
|
+
const thresholdPercent = Math.round(options.threshold * 100);
|
|
262
|
+
|
|
263
|
+
const hint = options.allowFuzzy
|
|
264
|
+
? options.fuzzyMatches && options.fuzzyMatches > 1
|
|
265
|
+
? `Found ${options.fuzzyMatches} high-confidence matches. Provide more context to make it unique.`
|
|
266
|
+
: `Closest match was below the ${thresholdPercent}% similarity threshold.`
|
|
267
|
+
: "Fuzzy matching is disabled. Enable 'Edit fuzzy match' in settings to accept high-confidence matches.";
|
|
268
|
+
|
|
269
|
+
return [
|
|
270
|
+
options.allowFuzzy
|
|
271
|
+
? `Could not find a close enough match in ${path}.`
|
|
272
|
+
: `Could not find the exact text in ${path}.`,
|
|
273
|
+
``,
|
|
274
|
+
`Closest match (${similarity}% similar) at line ${closest.startLine}:`,
|
|
275
|
+
` - ${oldLine}`,
|
|
276
|
+
` + ${newLine}`,
|
|
277
|
+
hint,
|
|
278
|
+
].join("\n");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function findFirstDifferentLine(oldLines: string[], newLines: string[]): { oldLine: string; newLine: string } {
|
|
283
|
+
const max = Math.max(oldLines.length, newLines.length);
|
|
284
|
+
for (let i = 0; i < max; i++) {
|
|
285
|
+
const oldLine = oldLines[i] ?? "";
|
|
286
|
+
const newLine = newLines[i] ?? "";
|
|
287
|
+
if (oldLine !== newLine) {
|
|
288
|
+
return { oldLine, newLine };
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return { oldLine: oldLines[0] ?? "", newLine: newLines[0] ?? "" };
|
|
292
|
+
}
|