@oh-my-pi/pi-coding-agent 8.1.0 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/docs/session.md +111 -46
- package/examples/custom-tools/hello/index.ts +1 -1
- package/examples/custom-tools/todo/index.ts +3 -4
- package/examples/extensions/api-demo.ts +0 -1
- package/examples/extensions/chalk-logger.ts +2 -3
- package/examples/extensions/hello.ts +0 -1
- package/examples/extensions/pirate.ts +0 -1
- package/examples/extensions/plan-mode.ts +15 -16
- package/examples/extensions/todo.ts +3 -4
- package/examples/extensions/tools.ts +1 -2
- package/examples/extensions/with-deps/index.ts +0 -1
- package/examples/hooks/auto-commit-on-exit.ts +1 -2
- package/examples/hooks/confirm-destructive.ts +0 -1
- package/examples/hooks/custom-compaction.ts +1 -2
- package/examples/hooks/dirty-repo-guard.ts +0 -1
- package/examples/hooks/file-trigger.ts +3 -4
- package/examples/hooks/git-checkpoint.ts +0 -1
- package/examples/hooks/handoff.ts +3 -4
- package/examples/hooks/permission-gate.ts +1 -2
- package/examples/hooks/protected-paths.ts +1 -2
- package/examples/hooks/qna.ts +2 -3
- package/examples/hooks/snake.ts +4 -5
- package/examples/hooks/status-line.ts +0 -1
- package/examples/sdk/01-minimal.ts +2 -3
- package/examples/sdk/02-custom-model.ts +2 -3
- package/examples/sdk/03-custom-prompt.ts +3 -4
- package/examples/sdk/04-skills.ts +2 -3
- package/examples/sdk/06-extensions.ts +1 -2
- package/examples/sdk/06-hooks.ts +6 -7
- package/examples/sdk/07-context-files.ts +0 -1
- package/examples/sdk/08-prompt-templates.ts +0 -1
- package/examples/sdk/08-slash-commands.ts +0 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +0 -1
- package/examples/sdk/10-settings.ts +0 -1
- package/examples/sdk/11-sessions.ts +0 -1
- package/package.json +51 -23
- package/scripts/format-prompts.ts +0 -1
- package/src/capability/context-file.ts +2 -3
- package/src/capability/extension-module.ts +2 -3
- package/src/capability/extension.ts +2 -3
- package/src/capability/fs.ts +20 -21
- package/src/capability/hook.ts +2 -3
- package/src/capability/index.ts +15 -16
- package/src/capability/instruction.ts +2 -3
- package/src/capability/mcp.ts +2 -3
- package/src/capability/prompt.ts +2 -3
- package/src/capability/rule.ts +2 -3
- package/src/capability/settings.ts +1 -2
- package/src/capability/skill.ts +2 -3
- package/src/capability/slash-command.ts +2 -3
- package/src/capability/ssh.ts +2 -3
- package/src/capability/system-prompt.ts +2 -3
- package/src/capability/tool.ts +2 -3
- package/src/cli/args.ts +5 -6
- package/src/cli/config-cli.ts +6 -7
- package/src/cli/file-processor.ts +19 -17
- package/src/cli/jupyter-cli.ts +105 -0
- package/src/cli/list-models.ts +10 -11
- package/src/cli/plugin-cli.ts +20 -21
- package/src/cli/session-picker.ts +2 -3
- package/src/cli/setup-cli.ts +2 -3
- package/src/cli/stats-cli.ts +2 -3
- package/src/cli/update-cli.ts +25 -22
- package/src/commit/agentic/agent.ts +21 -23
- package/src/commit/agentic/fallback.ts +9 -9
- package/src/commit/agentic/index.ts +30 -38
- package/src/commit/agentic/state.ts +1 -6
- package/src/commit/agentic/tools/analyze-file.ts +15 -15
- package/src/commit/agentic/tools/git-file-diff.ts +3 -3
- package/src/commit/agentic/tools/git-hunk.ts +7 -7
- package/src/commit/agentic/tools/git-overview.ts +5 -5
- package/src/commit/agentic/tools/index.ts +14 -14
- package/src/commit/agentic/tools/propose-changelog.ts +6 -6
- package/src/commit/agentic/tools/propose-commit.ts +8 -8
- package/src/commit/agentic/tools/recent-commits.ts +2 -2
- package/src/commit/agentic/tools/split-commit.ts +19 -23
- package/src/commit/agentic/topo-sort.ts +1 -1
- package/src/commit/agentic/trivial.ts +3 -3
- package/src/commit/agentic/validation.ts +12 -12
- package/src/commit/analysis/conventional.ts +7 -11
- package/src/commit/analysis/index.ts +4 -4
- package/src/commit/analysis/scope.ts +4 -4
- package/src/commit/analysis/summary.ts +7 -9
- package/src/commit/analysis/validation.ts +1 -1
- package/src/commit/changelog/detect.ts +6 -6
- package/src/commit/changelog/generate.ts +7 -9
- package/src/commit/changelog/index.ts +13 -13
- package/src/commit/changelog/parse.ts +2 -2
- package/src/commit/cli.ts +1 -1
- package/src/commit/git/diff.ts +3 -3
- package/src/commit/git/index.ts +19 -24
- package/src/commit/index.ts +1 -1
- package/src/commit/map-reduce/index.ts +9 -9
- package/src/commit/map-reduce/map-phase.ts +19 -34
- package/src/commit/map-reduce/reduce-phase.ts +9 -11
- package/src/commit/message.ts +2 -2
- package/src/commit/model-selection.ts +3 -7
- package/src/commit/pipeline.ts +20 -22
- package/src/commit/utils/exclusions.ts +3 -3
- package/src/config/file-lock.ts +17 -7
- package/src/config/keybindings.ts +6 -8
- package/src/config/model-registry.ts +55 -37
- package/src/config/model-resolver.ts +18 -19
- package/src/config/prompt-templates.ts +11 -11
- package/src/config/settings-manager.ts +50 -34
- package/src/config.ts +60 -62
- package/src/cursor.ts +11 -9
- package/src/discovery/agents-md.ts +11 -12
- package/src/discovery/builtin.ts +68 -73
- package/src/discovery/claude.ts +41 -42
- package/src/discovery/cline.ts +11 -12
- package/src/discovery/codex.ts +52 -53
- package/src/discovery/cursor.ts +9 -10
- package/src/discovery/gemini.ts +17 -22
- package/src/discovery/github.ts +13 -14
- package/src/discovery/helpers.ts +35 -34
- package/src/discovery/index.ts +16 -18
- package/src/discovery/mcp-json.ts +8 -9
- package/src/discovery/ssh.ts +8 -9
- package/src/discovery/vscode.ts +4 -5
- package/src/discovery/windsurf.ts +6 -7
- package/src/exa/company.ts +1 -2
- package/src/exa/index.ts +2 -3
- package/src/exa/linkedin.ts +1 -2
- package/src/exa/mcp-client.ts +14 -16
- package/src/exa/render.ts +10 -11
- package/src/exa/researcher.ts +1 -2
- package/src/exa/search.ts +1 -2
- package/src/exa/types.ts +0 -1
- package/src/exa/websets.ts +1 -2
- package/src/exec/bash-executor.ts +3 -4
- package/src/exec/exec.ts +0 -1
- package/src/export/custom-share.ts +5 -6
- package/src/export/html/index.ts +24 -21
- package/src/export/ttsr.ts +2 -3
- package/src/extensibility/custom-commands/bundled/review/index.ts +7 -8
- package/src/extensibility/custom-commands/loader.ts +17 -14
- package/src/extensibility/custom-commands/types.ts +1 -2
- package/src/extensibility/custom-tools/loader.ts +10 -11
- package/src/extensibility/custom-tools/types.ts +6 -7
- package/src/extensibility/custom-tools/wrapper.ts +2 -3
- package/src/extensibility/extensions/loader.ts +75 -53
- package/src/extensibility/extensions/runner.ts +11 -12
- package/src/extensibility/extensions/types.ts +19 -26
- package/src/extensibility/extensions/wrapper.ts +3 -4
- package/src/extensibility/hooks/index.ts +1 -1
- package/src/extensibility/hooks/loader.ts +8 -9
- package/src/extensibility/hooks/runner.ts +7 -8
- package/src/extensibility/hooks/tool-wrapper.ts +0 -1
- package/src/extensibility/hooks/types.ts +10 -17
- package/src/extensibility/plugins/doctor.ts +3 -3
- package/src/extensibility/plugins/installer.ts +27 -27
- package/src/extensibility/plugins/loader.ts +59 -56
- package/src/extensibility/plugins/manager.ts +211 -171
- package/src/extensibility/plugins/parser.ts +1 -1
- package/src/extensibility/plugins/paths.ts +8 -8
- package/src/extensibility/skills.ts +63 -60
- package/src/extensibility/slash-commands.ts +10 -10
- package/src/index.ts +46 -46
- package/src/internal-urls/agent-protocol.ts +21 -11
- package/src/internal-urls/artifact-protocol.ts +17 -13
- package/src/internal-urls/router.ts +1 -2
- package/src/internal-urls/rule-protocol.ts +3 -4
- package/src/internal-urls/skill-protocol.ts +3 -4
- package/src/ipy/executor.ts +14 -10
- package/src/ipy/gateway-coordinator.ts +79 -90
- package/src/ipy/kernel.ts +32 -30
- package/src/ipy/modules.ts +13 -13
- package/src/lsp/client.ts +21 -10
- package/src/lsp/clients/biome-client.ts +1 -2
- package/src/lsp/clients/index.ts +3 -3
- package/src/lsp/clients/lsp-linter-client.ts +4 -5
- package/src/lsp/config.ts +15 -15
- package/src/lsp/edits.ts +4 -5
- package/src/lsp/index.ts +43 -44
- package/src/lsp/lspmux.ts +8 -8
- package/src/lsp/render.ts +10 -16
- package/src/lsp/utils.ts +3 -3
- package/src/main.ts +55 -34
- package/src/mcp/client.ts +2 -3
- package/src/mcp/config.ts +5 -6
- package/src/mcp/json-rpc.ts +0 -1
- package/src/mcp/loader.ts +3 -4
- package/src/mcp/manager.ts +17 -18
- package/src/mcp/tool-bridge.ts +4 -9
- package/src/mcp/tool-cache.ts +2 -3
- package/src/mcp/transports/http.ts +2 -4
- package/src/mcp/transports/stdio.ts +1 -2
- package/src/migrations.ts +60 -49
- package/src/modes/components/armin.ts +4 -5
- package/src/modes/components/assistant-message.ts +6 -6
- package/src/modes/components/bash-execution.ts +7 -8
- package/src/modes/components/bordered-loader.ts +3 -3
- package/src/modes/components/branch-summary-message.ts +3 -3
- package/src/modes/components/compaction-summary-message.ts +3 -3
- package/src/modes/components/countdown-timer.ts +0 -1
- package/src/modes/components/custom-message.ts +5 -5
- package/src/modes/components/diff.ts +1 -1
- package/src/modes/components/dynamic-border.ts +2 -2
- package/src/modes/components/extensions/extension-dashboard.ts +6 -7
- package/src/modes/components/extensions/extension-list.ts +2 -3
- package/src/modes/components/extensions/inspector-panel.ts +3 -4
- package/src/modes/components/extensions/state-manager.ts +25 -26
- package/src/modes/components/extensions/types.ts +1 -2
- package/src/modes/components/footer.ts +47 -43
- package/src/modes/components/history-search.ts +2 -2
- package/src/modes/components/hook-editor.ts +3 -4
- package/src/modes/components/hook-input.ts +2 -3
- package/src/modes/components/hook-message.ts +5 -5
- package/src/modes/components/hook-selector.ts +2 -3
- package/src/modes/components/keybinding-hints.ts +2 -3
- package/src/modes/components/login-dialog.ts +2 -2
- package/src/modes/components/model-selector.ts +12 -12
- package/src/modes/components/oauth-selector.ts +2 -2
- package/src/modes/components/plugin-settings.ts +20 -20
- package/src/modes/components/python-execution.ts +7 -8
- package/src/modes/components/queue-mode-selector.ts +3 -3
- package/src/modes/components/read-tool-group.ts +2 -2
- package/src/modes/components/session-selector.ts +4 -4
- package/src/modes/components/settings-defs.ts +77 -69
- package/src/modes/components/settings-selector.ts +16 -16
- package/src/modes/components/show-images-selector.ts +2 -2
- package/src/modes/components/status-line/segments.ts +4 -4
- package/src/modes/components/status-line/separators.ts +1 -1
- package/src/modes/components/status-line/types.ts +2 -2
- package/src/modes/components/status-line-segment-editor.ts +7 -8
- package/src/modes/components/status-line.ts +12 -12
- package/src/modes/components/theme-selector.ts +8 -7
- package/src/modes/components/thinking-selector.ts +4 -4
- package/src/modes/components/todo-display.ts +2 -2
- package/src/modes/components/todo-reminder.ts +4 -4
- package/src/modes/components/tool-execution.ts +11 -16
- package/src/modes/components/tree-selector.ts +11 -11
- package/src/modes/components/ttsr-notification.ts +5 -5
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +1 -1
- package/src/modes/components/visual-truncate.ts +0 -1
- package/src/modes/components/welcome.ts +4 -4
- package/src/modes/controllers/command-controller.ts +46 -47
- package/src/modes/controllers/event-controller.ts +16 -20
- package/src/modes/controllers/extension-ui-controller.ts +40 -46
- package/src/modes/controllers/input-controller.ts +17 -18
- package/src/modes/controllers/selector-controller.ts +103 -91
- package/src/modes/index.ts +3 -3
- package/src/modes/interactive-mode.ts +27 -29
- package/src/modes/print-mode.ts +12 -13
- package/src/modes/rpc/rpc-client.ts +7 -8
- package/src/modes/rpc/rpc-mode.ts +24 -25
- package/src/modes/rpc/rpc-types.ts +3 -4
- package/src/modes/theme/mermaid-cache.ts +2 -2
- package/src/modes/theme/theme.ts +128 -53
- package/src/modes/types.ts +10 -10
- package/src/modes/utils/ui-helpers.ts +17 -17
- package/src/patch/applicator.ts +18 -19
- package/src/patch/diff.ts +1 -2
- package/src/patch/fuzzy.ts +1 -2
- package/src/patch/index.ts +10 -11
- package/src/patch/normalize.ts +4 -4
- package/src/patch/normative.ts +1 -2
- package/src/patch/parser.ts +8 -9
- package/src/patch/shared.ts +12 -13
- package/src/sdk.ts +60 -63
- package/src/session/agent-session.ts +83 -84
- package/src/session/agent-storage.ts +11 -11
- package/src/session/artifacts.ts +8 -9
- package/src/session/auth-storage.ts +25 -29
- package/src/session/compaction/branch-summarization.ts +7 -10
- package/src/session/compaction/compaction.ts +8 -19
- package/src/session/compaction/utils.ts +6 -9
- package/src/session/history-storage.ts +10 -10
- package/src/session/messages.ts +4 -5
- package/src/session/session-manager.ts +76 -65
- package/src/session/session-storage.ts +57 -69
- package/src/session/storage-migration.ts +2 -3
- package/src/session/streaming-output.ts +2 -2
- package/src/ssh/connection-manager.ts +43 -50
- package/src/ssh/ssh-executor.ts +2 -2
- package/src/ssh/sshfs-mount.ts +11 -18
- package/src/system-prompt.ts +27 -34
- package/src/task/agents.ts +45 -30
- package/src/task/commands.ts +6 -7
- package/src/task/discovery.ts +39 -76
- package/src/task/executor.ts +14 -15
- package/src/task/index.ts +33 -36
- package/src/task/output-manager.ts +3 -4
- package/src/task/parallel.ts +0 -1
- package/src/task/render.ts +19 -20
- package/src/task/subprocess-tool-registry.ts +1 -2
- package/src/task/worker-protocol.ts +3 -3
- package/src/task/worker.ts +32 -38
- package/src/task/worktree.ts +19 -19
- package/src/tools/ask.ts +8 -9
- package/src/tools/bash-interceptor.ts +1 -5
- package/src/tools/bash.ts +19 -18
- package/src/tools/calculator.ts +12 -12
- package/src/tools/complete.ts +3 -4
- package/src/tools/context.ts +2 -2
- package/src/tools/fetch.ts +23 -26
- package/src/tools/find.ts +15 -16
- package/src/tools/gemini-image.ts +14 -14
- package/src/tools/grep.ts +27 -27
- package/src/tools/index.ts +78 -56
- package/src/tools/list-limit.ts +1 -1
- package/src/tools/ls.ts +7 -7
- package/src/tools/notebook.ts +5 -5
- package/src/tools/output-meta.ts +3 -4
- package/src/tools/output-utils.ts +1 -1
- package/src/tools/path-utils.ts +5 -5
- package/src/tools/python.ts +36 -37
- package/src/tools/read.ts +23 -23
- package/src/tools/render-utils.ts +8 -9
- package/src/tools/renderers.ts +6 -7
- package/src/tools/review.ts +8 -11
- package/src/tools/ssh.ts +31 -30
- package/src/tools/todo-write.ts +13 -13
- package/src/tools/tool-errors.ts +3 -3
- package/src/tools/tool-result.ts +3 -8
- package/src/tools/write.ts +11 -16
- package/src/tui/code-cell.ts +3 -9
- package/src/tui/file-list.ts +3 -4
- package/src/tui/output-block.ts +1 -2
- package/src/tui/status-line.ts +2 -3
- package/src/tui/tree-list.ts +2 -3
- package/src/tui/types.ts +1 -2
- package/src/tui/utils.ts +2 -3
- package/src/utils/changelog.ts +9 -10
- package/src/utils/clipboard.ts +11 -11
- package/src/utils/file-mentions.ts +4 -10
- package/src/utils/frontmatter.ts +6 -3
- package/src/utils/fuzzy.ts +2 -2
- package/src/utils/image-convert.ts +1 -1
- package/src/utils/image-resize.ts +1 -1
- package/src/utils/mime.ts +2 -2
- package/src/utils/shell-snapshot.ts +11 -13
- package/src/utils/shell.ts +4 -5
- package/src/utils/title-generator.ts +8 -9
- package/src/utils/tools-manager.ts +23 -23
- package/src/vendor/photon/index.js +1099 -1059
- package/src/vendor/photon/photon_rs_bg.wasm +0 -0
- package/src/web/scrapers/artifacthub.ts +1 -1
- package/src/web/scrapers/arxiv.ts +2 -2
- package/src/web/scrapers/bluesky.ts +2 -2
- package/src/web/scrapers/cheatsh.ts +1 -1
- package/src/web/scrapers/chocolatey.ts +2 -2
- package/src/web/scrapers/choosealicense.ts +5 -5
- package/src/web/scrapers/cisa-kev.ts +1 -1
- package/src/web/scrapers/crossref.ts +2 -2
- package/src/web/scrapers/devto.ts +3 -3
- package/src/web/scrapers/discogs.ts +3 -4
- package/src/web/scrapers/discourse.ts +1 -1
- package/src/web/scrapers/dockerhub.ts +1 -1
- package/src/web/scrapers/fdroid.ts +2 -2
- package/src/web/scrapers/firefox-addons.ts +3 -3
- package/src/web/scrapers/flathub.ts +1 -1
- package/src/web/scrapers/github.ts +3 -3
- package/src/web/scrapers/gitlab.ts +4 -4
- package/src/web/scrapers/hackernews.ts +2 -2
- package/src/web/scrapers/huggingface.ts +1 -1
- package/src/web/scrapers/iacr.ts +2 -2
- package/src/web/scrapers/index.ts +0 -1
- package/src/web/scrapers/jetbrains-marketplace.ts +1 -1
- package/src/web/scrapers/lemmy.ts +2 -2
- package/src/web/scrapers/maven.ts +2 -2
- package/src/web/scrapers/mdn.ts +2 -4
- package/src/web/scrapers/metacpan.ts +2 -2
- package/src/web/scrapers/musicbrainz.ts +1 -2
- package/src/web/scrapers/npm.ts +1 -1
- package/src/web/scrapers/nuget.ts +2 -2
- package/src/web/scrapers/nvd.ts +3 -3
- package/src/web/scrapers/ollama.ts +7 -9
- package/src/web/scrapers/opencorporates.ts +2 -2
- package/src/web/scrapers/openlibrary.ts +6 -6
- package/src/web/scrapers/orcid.ts +0 -1
- package/src/web/scrapers/osv.ts +2 -2
- package/src/web/scrapers/packagist.ts +1 -1
- package/src/web/scrapers/pubmed.ts +1 -2
- package/src/web/scrapers/rawg.ts +2 -2
- package/src/web/scrapers/readthedocs.ts +1 -2
- package/src/web/scrapers/repology.ts +2 -2
- package/src/web/scrapers/rfc.ts +1 -1
- package/src/web/scrapers/searchcode.ts +2 -2
- package/src/web/scrapers/semantic-scholar.ts +1 -1
- package/src/web/scrapers/snapcraft.ts +2 -2
- package/src/web/scrapers/sourcegraph.ts +1 -1
- package/src/web/scrapers/spdx.ts +3 -3
- package/src/web/scrapers/spotify.ts +0 -1
- package/src/web/scrapers/twitter.ts +1 -1
- package/src/web/scrapers/types.ts +1 -2
- package/src/web/scrapers/utils.ts +5 -5
- package/src/web/scrapers/wikidata.ts +3 -3
- package/src/web/scrapers/youtube.ts +9 -14
- package/src/web/search/auth.ts +4 -9
- package/src/web/search/index.ts +11 -21
- package/src/web/search/providers/anthropic.ts +3 -9
- package/src/web/search/providers/exa.ts +6 -10
- package/src/web/search/providers/perplexity.ts +5 -5
- package/src/web/search/render.ts +16 -18
- package/scripts/generate-wasm-b64.ts +0 -24
- package/src/commit/map-reduce/.map-phase.ts.kate-swp +0 -0
- package/src/task/.executor.ts.kate-swp +0 -0
- package/src/vendor/photon/photon_rs_bg.wasm.b64.js +0 -1
package/src/patch/applicator.ts
CHANGED
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
* Applies parsed diff hunks to file content using fuzzy matching
|
|
5
5
|
* for robust handling of whitespace and formatting differences.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import { resolveToCwd } from "@oh-my-pi/pi-coding-agent/tools/path-utils";
|
|
7
|
+
import * as fs from "node:fs/promises";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import { resolveToCwd } from "../tools/path-utils";
|
|
11
10
|
import { DEFAULT_FUZZY_THRESHOLD, findContextLine, findMatch, seekSequence } from "./fuzzy";
|
|
12
11
|
import {
|
|
13
12
|
adjustIndentation,
|
|
@@ -51,10 +50,10 @@ export const defaultFileSystem: FileSystem = {
|
|
|
51
50
|
await Bun.write(path, content);
|
|
52
51
|
},
|
|
53
52
|
async delete(path: string): Promise<void> {
|
|
54
|
-
|
|
53
|
+
await fs.unlink(path);
|
|
55
54
|
},
|
|
56
55
|
async mkdir(path: string): Promise<void> {
|
|
57
|
-
|
|
56
|
+
await fs.mkdir(path, { recursive: true });
|
|
58
57
|
},
|
|
59
58
|
};
|
|
60
59
|
|
|
@@ -204,14 +203,14 @@ function adjustLinesIndentation(patternLines: string[], actualLines: string[], n
|
|
|
204
203
|
deltas.push(aIndent - pIndent);
|
|
205
204
|
}
|
|
206
205
|
|
|
207
|
-
if (deltas.length > 0 && deltas.every(
|
|
206
|
+
if (deltas.length > 0 && deltas.every(value => value === deltas[0])) {
|
|
208
207
|
delta = deltas[0];
|
|
209
208
|
}
|
|
210
209
|
|
|
211
210
|
// Track which actual lines we've used to handle duplicate content correctly
|
|
212
211
|
const usedActualLines = new Map<string, number>(); // trimmed content -> count used
|
|
213
212
|
|
|
214
|
-
return newLines.map(
|
|
213
|
+
return newLines.map(newLine => {
|
|
215
214
|
if (newLine.trim().length === 0) {
|
|
216
215
|
return newLine;
|
|
217
216
|
}
|
|
@@ -277,7 +276,7 @@ function trimCommonContext(oldLines: string[], newLines: string[]): HunkVariant
|
|
|
277
276
|
}
|
|
278
277
|
|
|
279
278
|
function collapseConsecutiveSharedLines(oldLines: string[], newLines: string[]): HunkVariant | undefined {
|
|
280
|
-
const shared = new Set(oldLines.filter(
|
|
279
|
+
const shared = new Set(oldLines.filter(line => newLines.includes(line)));
|
|
281
280
|
const collapse = (lines: string[]): string[] => {
|
|
282
281
|
const out: string[] = [];
|
|
283
282
|
let i = 0;
|
|
@@ -302,7 +301,7 @@ function collapseConsecutiveSharedLines(oldLines: string[], newLines: string[]):
|
|
|
302
301
|
}
|
|
303
302
|
|
|
304
303
|
function collapseRepeatedBlocks(oldLines: string[], newLines: string[]): HunkVariant | undefined {
|
|
305
|
-
const shared = new Set(oldLines.filter(
|
|
304
|
+
const shared = new Set(oldLines.filter(line => newLines.includes(line)));
|
|
306
305
|
const collapse = (lines: string[]): string[] => {
|
|
307
306
|
const output = [...lines];
|
|
308
307
|
let changed = false;
|
|
@@ -313,7 +312,7 @@ function collapseRepeatedBlocks(oldLines: string[], newLines: string[]): HunkVar
|
|
|
313
312
|
const first = output.slice(i, i + size);
|
|
314
313
|
const second = output.slice(i + size, i + size * 2);
|
|
315
314
|
if (first.length !== second.length || first.length === 0) continue;
|
|
316
|
-
if (!first.every(
|
|
315
|
+
if (!first.every(line => shared.has(line))) continue;
|
|
317
316
|
let same = true;
|
|
318
317
|
for (let idx = 0; idx < size; idx++) {
|
|
319
318
|
if (first[idx] !== second[idx]) {
|
|
@@ -379,7 +378,7 @@ function buildFallbackVariants(hunk: DiffHunk): HunkVariant[] {
|
|
|
379
378
|
if (singleLine) variants.push(singleLine);
|
|
380
379
|
|
|
381
380
|
const seen = new Set<string>();
|
|
382
|
-
return variants.filter(
|
|
381
|
+
return variants.filter(variant => {
|
|
383
382
|
if (variant.oldLines.length === 0 && variant.newLines.length === 0) return false;
|
|
384
383
|
const key = `${variant.oldLines.join("\n")}||${variant.newLines.join("\n")}`;
|
|
385
384
|
if (seen.has(key)) return false;
|
|
@@ -443,8 +442,8 @@ function findHierarchicalContext(
|
|
|
443
442
|
if (context.includes("\n")) {
|
|
444
443
|
const parts = context
|
|
445
444
|
.split("\n")
|
|
446
|
-
.map(
|
|
447
|
-
.filter(
|
|
445
|
+
.map(p => p.trim())
|
|
446
|
+
.filter(p => p.length > 0);
|
|
448
447
|
let currentStart = startFrom;
|
|
449
448
|
|
|
450
449
|
for (let i = 0; i < parts.length; i++) {
|
|
@@ -488,7 +487,7 @@ function findHierarchicalContext(
|
|
|
488
487
|
}
|
|
489
488
|
|
|
490
489
|
// Try literal context first
|
|
491
|
-
const spaceParts = context.split(/\s+/).filter(
|
|
490
|
+
const spaceParts = context.split(/\s+/).filter(p => p.length > 0);
|
|
492
491
|
const hasSignatureChars = /[(){}[\]]/.test(context);
|
|
493
492
|
if (!hasSignatureChars && spaceParts.length > 2) {
|
|
494
493
|
const outer = spaceParts.slice(0, -1).join(" ");
|
|
@@ -899,7 +898,7 @@ function computeReplacements(
|
|
|
899
898
|
for (const variant of buildFallbackVariants(hunk)) {
|
|
900
899
|
if (variant.oldLines.length !== 1 || variant.newLines.length !== 1) continue;
|
|
901
900
|
const removedLine = variant.oldLines[0];
|
|
902
|
-
const hasSharedDuplicate = hunk.newLines.some(
|
|
901
|
+
const hasSharedDuplicate = hunk.newLines.some(line => line.trim() === removedLine.trim());
|
|
903
902
|
const adjacentIndex = findContextRelativeMatch(
|
|
904
903
|
originalLines,
|
|
905
904
|
removedLine,
|
|
@@ -922,7 +921,7 @@ function computeReplacements(
|
|
|
922
921
|
if (line.trim() === trimmed) occurrenceCount++;
|
|
923
922
|
}
|
|
924
923
|
if (occurrenceCount > 1) {
|
|
925
|
-
const hasSharedDuplicate = hunk.newLines.some(
|
|
924
|
+
const hasSharedDuplicate = hunk.newLines.some(line => line.trim() === trimmed);
|
|
926
925
|
const contextMatch = findContextRelativeMatch(originalLines, pattern[0], contextIndex, hasSharedDuplicate);
|
|
927
926
|
if (contextMatch !== undefined) {
|
|
928
927
|
searchResult = { index: contextMatch, confidence: searchResult.confidence ?? 0.95 };
|
|
@@ -1113,7 +1112,7 @@ async function applyNormalizedPatch(
|
|
|
1113
1112
|
const content = normalizedContent.endsWith("\n") ? normalizedContent : `${normalizedContent}\n`;
|
|
1114
1113
|
|
|
1115
1114
|
if (!dryRun) {
|
|
1116
|
-
const parentDir = dirname(absolutePath);
|
|
1115
|
+
const parentDir = path.dirname(absolutePath);
|
|
1117
1116
|
if (parentDir && parentDir !== ".") {
|
|
1118
1117
|
await fs.mkdir(parentDir);
|
|
1119
1118
|
}
|
|
@@ -1182,7 +1181,7 @@ async function applyNormalizedPatch(
|
|
|
1182
1181
|
|
|
1183
1182
|
if (!dryRun) {
|
|
1184
1183
|
if (isMove) {
|
|
1185
|
-
const parentDir = dirname(destPath);
|
|
1184
|
+
const parentDir = path.dirname(destPath);
|
|
1186
1185
|
if (parentDir && parentDir !== ".") {
|
|
1187
1186
|
await fs.mkdir(parentDir);
|
|
1188
1187
|
}
|
package/src/patch/diff.ts
CHANGED
|
@@ -4,9 +4,8 @@
|
|
|
4
4
|
* Provides diff string generation and the replace-mode edit logic
|
|
5
5
|
* used when not in patch mode.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
import { resolveToCwd } from "@oh-my-pi/pi-coding-agent/tools/path-utils";
|
|
9
7
|
import * as Diff from "diff";
|
|
8
|
+
import { resolveToCwd } from "../tools/path-utils";
|
|
10
9
|
import { previewPatch } from "./applicator";
|
|
11
10
|
import { DEFAULT_FUZZY_THRESHOLD, findMatch } from "./fuzzy";
|
|
12
11
|
import { adjustIndentation, normalizeToLF, stripBom } from "./normalize";
|
package/src/patch/fuzzy.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* Provides both character-level and line-level fuzzy matching with progressive
|
|
5
5
|
* fallback strategies for finding text in files.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
7
|
import { countLeadingWhitespace, normalizeForFuzzy, normalizeUnicode } from "./normalize";
|
|
9
8
|
import type { ContextLineResult, FuzzyMatch, MatchOutcome, SequenceSearchResult } from "./types";
|
|
10
9
|
|
|
@@ -89,7 +88,7 @@ function computeRelativeIndentDepths(lines: string[]): number[] {
|
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
90
|
const minIndent = nonEmptyIndents.length > 0 ? Math.min(...nonEmptyIndents) : 0;
|
|
92
|
-
const indentSteps = nonEmptyIndents.map(
|
|
91
|
+
const indentSteps = nonEmptyIndents.map(indent => indent - minIndent).filter(step => step > 0);
|
|
93
92
|
const indentUnit = indentSteps.length > 0 ? Math.min(...indentSteps) : 1;
|
|
94
93
|
|
|
95
94
|
return lines.map((line, index) => {
|
package/src/patch/index.ts
CHANGED
|
@@ -7,24 +7,23 @@
|
|
|
7
7
|
*
|
|
8
8
|
* The mode is determined by the `edit.patchMode` setting.
|
|
9
9
|
*/
|
|
10
|
-
|
|
11
|
-
import { mkdir } from "node:fs/promises";
|
|
10
|
+
import * as fs from "node:fs/promises";
|
|
12
11
|
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
13
12
|
import { StringEnum } from "@oh-my-pi/pi-ai";
|
|
14
|
-
import {
|
|
13
|
+
import { Type } from "@sinclair/typebox";
|
|
14
|
+
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
15
15
|
import {
|
|
16
16
|
createLspWritethrough,
|
|
17
17
|
type FileDiagnosticsResult,
|
|
18
18
|
flushLspWritethroughBatch,
|
|
19
19
|
type WritethroughCallback,
|
|
20
20
|
writethroughNoop,
|
|
21
|
-
} from "
|
|
22
|
-
import patchDescription from "
|
|
23
|
-
import replaceDescription from "
|
|
24
|
-
import type { ToolSession } from "
|
|
25
|
-
import { outputMeta } from "
|
|
26
|
-
import { resolveToCwd } from "
|
|
27
|
-
import { Type } from "@sinclair/typebox";
|
|
21
|
+
} from "../lsp";
|
|
22
|
+
import patchDescription from "../prompts/tools/patch.md" with { type: "text" };
|
|
23
|
+
import replaceDescription from "../prompts/tools/replace.md" with { type: "text" };
|
|
24
|
+
import type { ToolSession } from "../tools";
|
|
25
|
+
import { outputMeta } from "../tools/output-meta";
|
|
26
|
+
import { resolveToCwd } from "../tools/path-utils";
|
|
28
27
|
import { applyPatch } from "./applicator";
|
|
29
28
|
import { generateDiffString, generateUnifiedDiffString, replaceText } from "./diff";
|
|
30
29
|
import { DEFAULT_FUZZY_THRESHOLD, findMatch } from "./fuzzy";
|
|
@@ -160,7 +159,7 @@ class LspFileSystem implements FileSystem {
|
|
|
160
159
|
}
|
|
161
160
|
|
|
162
161
|
async mkdir(path: string): Promise<void> {
|
|
163
|
-
await mkdir(path, { recursive: true });
|
|
162
|
+
await fs.mkdir(path, { recursive: true });
|
|
164
163
|
}
|
|
165
164
|
|
|
166
165
|
getDiagnostics(): FileDiagnosticsResult | undefined {
|
package/src/patch/normalize.ts
CHANGED
|
@@ -189,7 +189,7 @@ export function convertLeadingTabsToSpaces(text: string, spacesPerTab: number):
|
|
|
189
189
|
if (spacesPerTab <= 0) return text;
|
|
190
190
|
return text
|
|
191
191
|
.split("\n")
|
|
192
|
-
.map(
|
|
192
|
+
.map(line => {
|
|
193
193
|
const trimmed = line.trimStart();
|
|
194
194
|
if (trimmed.length === 0) return line;
|
|
195
195
|
const leading = getLeadingWhitespace(line);
|
|
@@ -212,7 +212,7 @@ export function normalizeUnicode(s: string): string {
|
|
|
212
212
|
return s
|
|
213
213
|
.trim()
|
|
214
214
|
.split("")
|
|
215
|
-
.map(
|
|
215
|
+
.map(c => {
|
|
216
216
|
const code = c.charCodeAt(0);
|
|
217
217
|
|
|
218
218
|
// Various dash/hyphen code-points → ASCII '-'
|
|
@@ -367,7 +367,7 @@ export function adjustIndentation(oldText: string, actualText: string, newText:
|
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
const delta = deltas[0];
|
|
370
|
-
if (!deltas.every(
|
|
370
|
+
if (!deltas.every(value => value === delta)) {
|
|
371
371
|
return newText;
|
|
372
372
|
}
|
|
373
373
|
|
|
@@ -380,7 +380,7 @@ export function adjustIndentation(oldText: string, actualText: string, newText:
|
|
|
380
380
|
}
|
|
381
381
|
|
|
382
382
|
const indentChar = actualProfile.char ?? oldProfile.char ?? detectIndentChar(actualText);
|
|
383
|
-
const adjusted = newText.split("\n").map(
|
|
383
|
+
const adjusted = newText.split("\n").map(line => {
|
|
384
384
|
if (line.trim().length === 0) {
|
|
385
385
|
return line;
|
|
386
386
|
}
|
package/src/patch/normative.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Normalize applied patch output into a canonical edit tool payload.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
4
|
import { generateUnifiedDiffString } from "./diff";
|
|
6
5
|
import { normalizeToLF, stripBom } from "./normalize";
|
|
7
6
|
import { parseHunks } from "./parser";
|
|
@@ -37,7 +36,7 @@ function applyAnchors(diff: string, anchors: Array<string | undefined> | undefin
|
|
|
37
36
|
|
|
38
37
|
function deriveAnchors(diff: string): Array<string | undefined> {
|
|
39
38
|
const hunks = parseHunks(diff);
|
|
40
|
-
return hunks.map(
|
|
39
|
+
return hunks.map(hunk => {
|
|
41
40
|
if (hunk.oldLines.length === 0 || hunk.newLines.length === 0) {
|
|
42
41
|
return undefined;
|
|
43
42
|
}
|
package/src/patch/parser.ts
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
* - Unified diff format (@@ -X,Y +A,B @@)
|
|
7
7
|
* - Codex-style wrapped patches (*** Begin Patch / *** End Patch)
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
9
|
import type { DiffHunk } from "./types";
|
|
11
10
|
import { ApplyPatchError, ParseError } from "./types";
|
|
12
11
|
|
|
@@ -90,7 +89,7 @@ export function normalizeDiff(diff: string): string {
|
|
|
90
89
|
// Layer 2: Strip Codex-style file operation markers and unified diff metadata
|
|
91
90
|
// NOTE: Do NOT strip "*** End of File" - that's a valid marker within hunks, not a wrapper
|
|
92
91
|
// IMPORTANT: Only strip actual metadata lines, NOT diff content lines (starting with space, +, or -)
|
|
93
|
-
lines = lines.filter(
|
|
92
|
+
lines = lines.filter(line => {
|
|
94
93
|
// Preserve diff content lines even if their content looks like metadata
|
|
95
94
|
// Note: `--- ` and `+++ ` are metadata, not content lines
|
|
96
95
|
if (isDiffContentLine(line)) {
|
|
@@ -130,12 +129,12 @@ export function normalizeDiff(diff: string): string {
|
|
|
130
129
|
*/
|
|
131
130
|
export function normalizeCreateContent(content: string): string {
|
|
132
131
|
const lines = content.split("\n");
|
|
133
|
-
const nonEmptyLines = lines.filter(
|
|
132
|
+
const nonEmptyLines = lines.filter(l => l.length > 0);
|
|
134
133
|
|
|
135
134
|
// Check if all non-empty lines start with "+ " or "+"
|
|
136
|
-
if (nonEmptyLines.length > 0 && nonEmptyLines.every(
|
|
135
|
+
if (nonEmptyLines.length > 0 && nonEmptyLines.every(l => l.startsWith("+ ") || l.startsWith("+"))) {
|
|
137
136
|
return lines
|
|
138
|
-
.map(
|
|
137
|
+
.map(l => {
|
|
139
138
|
if (l.startsWith("+ ")) return l.slice(2);
|
|
140
139
|
if (l.startsWith("+")) return l.slice(1);
|
|
141
140
|
return l;
|
|
@@ -390,18 +389,18 @@ function parseOneHunk(lines: string[], lineNumber: number, allowMissingContext:
|
|
|
390
389
|
}
|
|
391
390
|
|
|
392
391
|
function stripLineNumberPrefixes(hunk: DiffHunk): void {
|
|
393
|
-
const allLines = [...hunk.oldLines, ...hunk.newLines].filter(
|
|
392
|
+
const allLines = [...hunk.oldLines, ...hunk.newLines].filter(line => line.trim().length > 0);
|
|
394
393
|
if (allLines.length < 2) return;
|
|
395
394
|
|
|
396
395
|
const numberMatches = allLines
|
|
397
|
-
.map(
|
|
396
|
+
.map(line => line.match(/^\s*(\d{1,6})\s+(.+)$/u))
|
|
398
397
|
.filter((match): match is RegExpMatchArray => match !== null);
|
|
399
398
|
|
|
400
399
|
if (numberMatches.length < Math.max(2, Math.ceil(allLines.length * 0.6))) {
|
|
401
400
|
return;
|
|
402
401
|
}
|
|
403
402
|
|
|
404
|
-
const numbers = numberMatches.map(
|
|
403
|
+
const numbers = numberMatches.map(match => Number(match[1]));
|
|
405
404
|
let sequential = 0;
|
|
406
405
|
for (let i = 1; i < numbers.length; i++) {
|
|
407
406
|
if (numbers[i] === numbers[i - 1] + 1) {
|
|
@@ -515,7 +514,7 @@ export function parseHunks(diff: string): DiffHunk[] {
|
|
|
515
514
|
continue;
|
|
516
515
|
}
|
|
517
516
|
|
|
518
|
-
if (trimmed.startsWith("@@") && lines.slice(i + 1).every(
|
|
517
|
+
if (trimmed.startsWith("@@") && lines.slice(i + 1).every(l => l.trim() === "")) {
|
|
519
518
|
break;
|
|
520
519
|
}
|
|
521
520
|
|
package/src/patch/shared.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared utilities for edit tool TUI rendering.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
4
|
import type { ToolCallContext } from "@oh-my-pi/pi-agent-core";
|
|
6
|
-
import type {
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
5
|
+
import type { Component } from "@oh-my-pi/pi-tui";
|
|
6
|
+
import { Text } from "@oh-my-pi/pi-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";
|
|
11
12
|
import {
|
|
12
13
|
formatExpandHint,
|
|
13
14
|
formatStatusIcon,
|
|
@@ -15,11 +16,9 @@ import {
|
|
|
15
16
|
shortenPath,
|
|
16
17
|
ToolUIKit,
|
|
17
18
|
truncateDiffByHunk,
|
|
18
|
-
} from "
|
|
19
|
-
import type { RenderCallOptions } from "
|
|
20
|
-
import { renderStatusLine } from "
|
|
21
|
-
import type { Component } from "@oh-my-pi/pi-tui";
|
|
22
|
-
import { Text } from "@oh-my-pi/pi-tui";
|
|
19
|
+
} from "../tools/render-utils";
|
|
20
|
+
import type { RenderCallOptions } from "../tools/renderers";
|
|
21
|
+
import { renderStatusLine } from "../tui";
|
|
23
22
|
import type { DiffError, DiffResult, Operation } from "./types";
|
|
24
23
|
|
|
25
24
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -38,7 +37,7 @@ export function getLspBatchRequest(toolCall: ToolCallContext | undefined): { id:
|
|
|
38
37
|
if (!hasOtherWrites) {
|
|
39
38
|
return undefined;
|
|
40
39
|
}
|
|
41
|
-
const hasLaterWrites = toolCall.toolCalls.slice(toolCall.index + 1).some(
|
|
40
|
+
const hasLaterWrites = toolCall.toolCalls.slice(toolCall.index + 1).some(call => LSP_BATCH_TOOLS.has(call.name));
|
|
42
41
|
return { id: toolCall.batchId, flush: !hasLaterWrites };
|
|
43
42
|
}
|
|
44
43
|
|
|
@@ -259,7 +258,7 @@ export const editToolRenderer = {
|
|
|
259
258
|
|
|
260
259
|
if (result.isError) {
|
|
261
260
|
// Show error from result
|
|
262
|
-
const errorText = result.content?.find(
|
|
261
|
+
const errorText = result.content?.find(c => c.type === "text")?.text ?? "";
|
|
263
262
|
if (errorText) {
|
|
264
263
|
text += `\n\n${uiTheme.fg("error", errorText)}`;
|
|
265
264
|
}
|