@oh-my-pi/pi-coding-agent 1.337.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 +1228 -0
- package/README.md +1041 -0
- package/docs/compaction.md +403 -0
- package/docs/custom-tools.md +541 -0
- package/docs/extension-loading.md +1004 -0
- package/docs/hooks.md +867 -0
- package/docs/rpc.md +1040 -0
- package/docs/sdk.md +994 -0
- package/docs/session-tree-plan.md +441 -0
- package/docs/session.md +240 -0
- package/docs/skills.md +290 -0
- package/docs/theme.md +637 -0
- package/docs/tree.md +197 -0
- package/docs/tui.md +341 -0
- package/examples/README.md +21 -0
- package/examples/custom-tools/README.md +124 -0
- package/examples/custom-tools/hello/index.ts +20 -0
- package/examples/custom-tools/question/index.ts +84 -0
- package/examples/custom-tools/subagent/README.md +172 -0
- package/examples/custom-tools/subagent/agents/planner.md +37 -0
- package/examples/custom-tools/subagent/agents/reviewer.md +35 -0
- package/examples/custom-tools/subagent/agents/scout.md +50 -0
- package/examples/custom-tools/subagent/agents/worker.md +24 -0
- package/examples/custom-tools/subagent/agents.ts +156 -0
- package/examples/custom-tools/subagent/commands/implement-and-review.md +10 -0
- package/examples/custom-tools/subagent/commands/implement.md +10 -0
- package/examples/custom-tools/subagent/commands/scout-and-plan.md +9 -0
- package/examples/custom-tools/subagent/index.ts +1002 -0
- package/examples/custom-tools/todo/index.ts +212 -0
- package/examples/hooks/README.md +56 -0
- package/examples/hooks/auto-commit-on-exit.ts +49 -0
- package/examples/hooks/confirm-destructive.ts +59 -0
- package/examples/hooks/custom-compaction.ts +116 -0
- package/examples/hooks/dirty-repo-guard.ts +52 -0
- package/examples/hooks/file-trigger.ts +41 -0
- package/examples/hooks/git-checkpoint.ts +53 -0
- package/examples/hooks/handoff.ts +150 -0
- package/examples/hooks/permission-gate.ts +34 -0
- package/examples/hooks/protected-paths.ts +30 -0
- package/examples/hooks/qna.ts +119 -0
- package/examples/hooks/snake.ts +343 -0
- package/examples/hooks/status-line.ts +40 -0
- package/examples/sdk/01-minimal.ts +22 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +44 -0
- package/examples/sdk/04-skills.ts +44 -0
- package/examples/sdk/05-tools.ts +90 -0
- package/examples/sdk/06-hooks.ts +61 -0
- package/examples/sdk/07-context-files.ts +36 -0
- package/examples/sdk/08-slash-commands.ts +42 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +55 -0
- package/examples/sdk/10-settings.ts +38 -0
- package/examples/sdk/11-sessions.ts +48 -0
- package/examples/sdk/12-full-control.ts +95 -0
- package/examples/sdk/README.md +154 -0
- package/package.json +81 -0
- package/src/cli/args.ts +246 -0
- package/src/cli/file-processor.ts +72 -0
- package/src/cli/list-models.ts +104 -0
- package/src/cli/plugin-cli.ts +650 -0
- package/src/cli/session-picker.ts +41 -0
- package/src/cli.ts +10 -0
- package/src/commands/init.md +20 -0
- package/src/config.ts +159 -0
- package/src/core/agent-session.ts +1900 -0
- package/src/core/auth-storage.ts +236 -0
- package/src/core/bash-executor.ts +196 -0
- package/src/core/compaction/branch-summarization.ts +343 -0
- package/src/core/compaction/compaction.ts +742 -0
- package/src/core/compaction/index.ts +7 -0
- package/src/core/compaction/utils.ts +154 -0
- package/src/core/custom-tools/index.ts +21 -0
- package/src/core/custom-tools/loader.ts +248 -0
- package/src/core/custom-tools/types.ts +169 -0
- package/src/core/custom-tools/wrapper.ts +28 -0
- package/src/core/exec.ts +129 -0
- package/src/core/export-html/index.ts +211 -0
- package/src/core/export-html/template.css +781 -0
- package/src/core/export-html/template.html +54 -0
- package/src/core/export-html/template.js +1185 -0
- package/src/core/export-html/vendor/highlight.min.js +1213 -0
- package/src/core/export-html/vendor/marked.min.js +6 -0
- package/src/core/hooks/index.ts +16 -0
- package/src/core/hooks/loader.ts +312 -0
- package/src/core/hooks/runner.ts +434 -0
- package/src/core/hooks/tool-wrapper.ts +99 -0
- package/src/core/hooks/types.ts +773 -0
- package/src/core/index.ts +52 -0
- package/src/core/mcp/client.ts +158 -0
- package/src/core/mcp/config.ts +154 -0
- package/src/core/mcp/index.ts +45 -0
- package/src/core/mcp/loader.ts +68 -0
- package/src/core/mcp/manager.ts +181 -0
- package/src/core/mcp/tool-bridge.ts +148 -0
- package/src/core/mcp/transports/http.ts +316 -0
- package/src/core/mcp/transports/index.ts +6 -0
- package/src/core/mcp/transports/stdio.ts +252 -0
- package/src/core/mcp/types.ts +220 -0
- package/src/core/messages.ts +189 -0
- package/src/core/model-registry.ts +317 -0
- package/src/core/model-resolver.ts +393 -0
- package/src/core/plugins/doctor.ts +59 -0
- package/src/core/plugins/index.ts +38 -0
- package/src/core/plugins/installer.ts +189 -0
- package/src/core/plugins/loader.ts +338 -0
- package/src/core/plugins/manager.ts +672 -0
- package/src/core/plugins/parser.ts +105 -0
- package/src/core/plugins/paths.ts +32 -0
- package/src/core/plugins/types.ts +190 -0
- package/src/core/sdk.ts +760 -0
- package/src/core/session-manager.ts +1128 -0
- package/src/core/settings-manager.ts +443 -0
- package/src/core/skills.ts +437 -0
- package/src/core/slash-commands.ts +248 -0
- package/src/core/system-prompt.ts +439 -0
- package/src/core/timings.ts +25 -0
- package/src/core/tools/ask.ts +211 -0
- package/src/core/tools/bash-interceptor.ts +120 -0
- package/src/core/tools/bash.ts +250 -0
- package/src/core/tools/context.ts +32 -0
- package/src/core/tools/edit-diff.ts +475 -0
- package/src/core/tools/edit.ts +208 -0
- package/src/core/tools/exa/company.ts +59 -0
- package/src/core/tools/exa/index.ts +64 -0
- package/src/core/tools/exa/linkedin.ts +59 -0
- package/src/core/tools/exa/logger.ts +56 -0
- package/src/core/tools/exa/mcp-client.ts +368 -0
- package/src/core/tools/exa/render.ts +196 -0
- package/src/core/tools/exa/researcher.ts +90 -0
- package/src/core/tools/exa/search.ts +337 -0
- package/src/core/tools/exa/types.ts +168 -0
- package/src/core/tools/exa/websets.ts +248 -0
- package/src/core/tools/find.ts +261 -0
- package/src/core/tools/grep.ts +555 -0
- package/src/core/tools/index.ts +202 -0
- package/src/core/tools/ls.ts +140 -0
- package/src/core/tools/lsp/client.ts +605 -0
- package/src/core/tools/lsp/config.ts +147 -0
- package/src/core/tools/lsp/edits.ts +101 -0
- package/src/core/tools/lsp/index.ts +804 -0
- package/src/core/tools/lsp/render.ts +447 -0
- package/src/core/tools/lsp/rust-analyzer.ts +145 -0
- package/src/core/tools/lsp/types.ts +463 -0
- package/src/core/tools/lsp/utils.ts +486 -0
- package/src/core/tools/notebook.ts +229 -0
- package/src/core/tools/path-utils.ts +61 -0
- package/src/core/tools/read.ts +240 -0
- package/src/core/tools/renderers.ts +540 -0
- package/src/core/tools/task/agents.ts +153 -0
- package/src/core/tools/task/artifacts.ts +114 -0
- package/src/core/tools/task/bundled-agents/browser.md +71 -0
- package/src/core/tools/task/bundled-agents/explore.md +82 -0
- package/src/core/tools/task/bundled-agents/plan.md +54 -0
- package/src/core/tools/task/bundled-agents/reviewer.md +59 -0
- package/src/core/tools/task/bundled-agents/task.md +53 -0
- package/src/core/tools/task/bundled-commands/architect-plan.md +10 -0
- package/src/core/tools/task/bundled-commands/implement-with-critic.md +11 -0
- package/src/core/tools/task/bundled-commands/implement.md +11 -0
- package/src/core/tools/task/commands.ts +213 -0
- package/src/core/tools/task/discovery.ts +208 -0
- package/src/core/tools/task/executor.ts +367 -0
- package/src/core/tools/task/index.ts +388 -0
- package/src/core/tools/task/model-resolver.ts +115 -0
- package/src/core/tools/task/parallel.ts +38 -0
- package/src/core/tools/task/render.ts +232 -0
- package/src/core/tools/task/types.ts +99 -0
- package/src/core/tools/truncate.ts +265 -0
- package/src/core/tools/web-fetch.ts +2370 -0
- package/src/core/tools/web-search/auth.ts +193 -0
- package/src/core/tools/web-search/index.ts +537 -0
- package/src/core/tools/web-search/providers/anthropic.ts +198 -0
- package/src/core/tools/web-search/providers/exa.ts +302 -0
- package/src/core/tools/web-search/providers/perplexity.ts +195 -0
- package/src/core/tools/web-search/render.ts +182 -0
- package/src/core/tools/web-search/types.ts +180 -0
- package/src/core/tools/write.ts +99 -0
- package/src/index.ts +176 -0
- package/src/main.ts +464 -0
- package/src/migrations.ts +135 -0
- package/src/modes/index.ts +43 -0
- package/src/modes/interactive/components/armin.ts +382 -0
- package/src/modes/interactive/components/assistant-message.ts +86 -0
- package/src/modes/interactive/components/bash-execution.ts +196 -0
- package/src/modes/interactive/components/bordered-loader.ts +41 -0
- package/src/modes/interactive/components/branch-summary-message.ts +42 -0
- package/src/modes/interactive/components/compaction-summary-message.ts +45 -0
- package/src/modes/interactive/components/custom-editor.ts +122 -0
- package/src/modes/interactive/components/diff.ts +147 -0
- package/src/modes/interactive/components/dynamic-border.ts +25 -0
- package/src/modes/interactive/components/footer.ts +381 -0
- package/src/modes/interactive/components/hook-editor.ts +117 -0
- package/src/modes/interactive/components/hook-input.ts +64 -0
- package/src/modes/interactive/components/hook-message.ts +96 -0
- package/src/modes/interactive/components/hook-selector.ts +91 -0
- package/src/modes/interactive/components/model-selector.ts +247 -0
- package/src/modes/interactive/components/oauth-selector.ts +120 -0
- package/src/modes/interactive/components/plugin-settings.ts +479 -0
- package/src/modes/interactive/components/queue-mode-selector.ts +56 -0
- package/src/modes/interactive/components/session-selector.ts +204 -0
- package/src/modes/interactive/components/settings-selector.ts +453 -0
- package/src/modes/interactive/components/show-images-selector.ts +45 -0
- package/src/modes/interactive/components/theme-selector.ts +62 -0
- package/src/modes/interactive/components/thinking-selector.ts +64 -0
- package/src/modes/interactive/components/tool-execution.ts +675 -0
- package/src/modes/interactive/components/tree-selector.ts +866 -0
- package/src/modes/interactive/components/user-message-selector.ts +159 -0
- package/src/modes/interactive/components/user-message.ts +18 -0
- package/src/modes/interactive/components/visual-truncate.ts +50 -0
- package/src/modes/interactive/components/welcome.ts +183 -0
- package/src/modes/interactive/interactive-mode.ts +2516 -0
- package/src/modes/interactive/theme/dark.json +101 -0
- package/src/modes/interactive/theme/light.json +98 -0
- package/src/modes/interactive/theme/theme-schema.json +308 -0
- package/src/modes/interactive/theme/theme.ts +998 -0
- package/src/modes/print-mode.ts +128 -0
- package/src/modes/rpc/rpc-client.ts +527 -0
- package/src/modes/rpc/rpc-mode.ts +483 -0
- package/src/modes/rpc/rpc-types.ts +203 -0
- package/src/utils/changelog.ts +99 -0
- package/src/utils/clipboard.ts +265 -0
- package/src/utils/fuzzy.ts +108 -0
- package/src/utils/mime.ts +30 -0
- package/src/utils/shell.ts +276 -0
- package/src/utils/tools-manager.ts +274 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { extname, join } from "node:path";
|
|
4
|
+
import type { ServerConfig } from "./types.js";
|
|
5
|
+
|
|
6
|
+
export interface LspConfig {
|
|
7
|
+
servers: Record<string, ServerConfig>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Predefined server configurations with capabilities
|
|
11
|
+
export const SERVERS: Record<string, ServerConfig> = {
|
|
12
|
+
"rust-analyzer": {
|
|
13
|
+
command: "rust-analyzer",
|
|
14
|
+
args: [],
|
|
15
|
+
fileTypes: [".rs"],
|
|
16
|
+
rootMarkers: ["Cargo.toml", "rust-analyzer.toml"],
|
|
17
|
+
initOptions: {
|
|
18
|
+
checkOnSave: { command: "clippy" },
|
|
19
|
+
cargo: { allFeatures: true },
|
|
20
|
+
procMacro: { enable: true },
|
|
21
|
+
},
|
|
22
|
+
capabilities: {
|
|
23
|
+
flycheck: true,
|
|
24
|
+
ssr: true,
|
|
25
|
+
expandMacro: true,
|
|
26
|
+
runnables: true,
|
|
27
|
+
relatedTests: true,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
"typescript-language-server": {
|
|
31
|
+
command: "typescript-language-server",
|
|
32
|
+
args: ["--stdio"],
|
|
33
|
+
fileTypes: [".ts", ".tsx", ".js", ".jsx"],
|
|
34
|
+
rootMarkers: ["package.json", "tsconfig.json", "jsconfig.json"],
|
|
35
|
+
},
|
|
36
|
+
gopls: {
|
|
37
|
+
command: "gopls",
|
|
38
|
+
args: ["serve"],
|
|
39
|
+
fileTypes: [".go"],
|
|
40
|
+
rootMarkers: ["go.mod", "go.work"],
|
|
41
|
+
},
|
|
42
|
+
pyright: {
|
|
43
|
+
command: "pyright-langserver",
|
|
44
|
+
args: ["--stdio"],
|
|
45
|
+
fileTypes: [".py"],
|
|
46
|
+
rootMarkers: ["pyproject.toml", "setup.py", "requirements.txt", "Pipfile"],
|
|
47
|
+
},
|
|
48
|
+
zls: {
|
|
49
|
+
command: "zls",
|
|
50
|
+
args: [],
|
|
51
|
+
fileTypes: [".zig"],
|
|
52
|
+
rootMarkers: ["build.zig", "build.zig.zon", "zls.json"],
|
|
53
|
+
},
|
|
54
|
+
clangd: {
|
|
55
|
+
command: "clangd",
|
|
56
|
+
args: ["--background-index"],
|
|
57
|
+
fileTypes: [".c", ".cpp", ".cc", ".cxx", ".h", ".hpp"],
|
|
58
|
+
rootMarkers: ["compile_commands.json", "CMakeLists.txt", ".clangd"],
|
|
59
|
+
},
|
|
60
|
+
"lua-language-server": {
|
|
61
|
+
command: "lua-language-server",
|
|
62
|
+
args: [],
|
|
63
|
+
fileTypes: [".lua"],
|
|
64
|
+
rootMarkers: [".luarc.json", ".luarc.jsonc", ".luacheckrc"],
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Check if any root marker file exists in the directory
|
|
70
|
+
*/
|
|
71
|
+
export function hasRootMarkers(cwd: string, markers: string[]): boolean {
|
|
72
|
+
return markers.some((marker) => existsSync(join(cwd, marker)));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Load LSP configuration.
|
|
77
|
+
*
|
|
78
|
+
* Priority:
|
|
79
|
+
* 1. Project-level config from .pi/lsp.json in cwd
|
|
80
|
+
* 2. User-level config from ~/.pi/lsp.json
|
|
81
|
+
* 3. Auto-detect from project markers + available binaries
|
|
82
|
+
*/
|
|
83
|
+
export function loadConfig(cwd: string): LspConfig {
|
|
84
|
+
// Try to load user config
|
|
85
|
+
const configPaths = [join(cwd, ".pi", "lsp.json"), join(homedir(), ".pi", "lsp.json")];
|
|
86
|
+
|
|
87
|
+
for (const configPath of configPaths) {
|
|
88
|
+
if (existsSync(configPath)) {
|
|
89
|
+
try {
|
|
90
|
+
const content = readFileSync(configPath, "utf-8");
|
|
91
|
+
const parsed = JSON.parse(content);
|
|
92
|
+
const servers = parsed.servers || parsed;
|
|
93
|
+
|
|
94
|
+
// Filter to only enabled servers with available commands
|
|
95
|
+
const available: Record<string, ServerConfig> = {};
|
|
96
|
+
for (const [name, config] of Object.entries(servers) as [string, ServerConfig][]) {
|
|
97
|
+
if (config.disabled) continue;
|
|
98
|
+
if (!Bun.which(config.command)) continue;
|
|
99
|
+
available[name] = config;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return { servers: available };
|
|
103
|
+
} catch {
|
|
104
|
+
// Ignore parse errors, fall through to auto-detect
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Auto-detect: find servers based on project markers AND available binaries
|
|
110
|
+
const detected: Record<string, ServerConfig> = {};
|
|
111
|
+
|
|
112
|
+
for (const [name, config] of Object.entries(SERVERS)) {
|
|
113
|
+
// Check if project has root markers for this language
|
|
114
|
+
if (!hasRootMarkers(cwd, config.rootMarkers)) continue;
|
|
115
|
+
|
|
116
|
+
// Check if the language server binary is available
|
|
117
|
+
if (!Bun.which(config.command)) continue;
|
|
118
|
+
|
|
119
|
+
detected[name] = config;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return { servers: detected };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Find the appropriate server for a file based on extension
|
|
127
|
+
*/
|
|
128
|
+
export function getServerForFile(config: LspConfig, filePath: string): [string, ServerConfig] | null {
|
|
129
|
+
const ext = extname(filePath).toLowerCase();
|
|
130
|
+
|
|
131
|
+
for (const [name, serverConfig] of Object.entries(config.servers)) {
|
|
132
|
+
if (serverConfig.fileTypes.includes(ext)) {
|
|
133
|
+
return [name, serverConfig];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Check if a server has a specific capability
|
|
141
|
+
*/
|
|
142
|
+
export function hasCapability(
|
|
143
|
+
config: ServerConfig,
|
|
144
|
+
capability: keyof NonNullable<ServerConfig["capabilities"]>,
|
|
145
|
+
): boolean {
|
|
146
|
+
return config.capabilities?.[capability] === true;
|
|
147
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { mkdir, rename, rm } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import type { CreateFile, DeleteFile, RenameFile, TextDocumentEdit, TextEdit, WorkspaceEdit } from "./types.js";
|
|
4
|
+
import { uriToFile } from "./utils.js";
|
|
5
|
+
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// Text Edit Application
|
|
8
|
+
// =============================================================================
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Apply text edits to a file.
|
|
12
|
+
* Edits are applied in reverse order (bottom-to-top) to preserve line/character indices.
|
|
13
|
+
*/
|
|
14
|
+
export async function applyTextEdits(filePath: string, edits: TextEdit[]): Promise<void> {
|
|
15
|
+
const content = await Bun.file(filePath).text();
|
|
16
|
+
const lines = content.split("\n");
|
|
17
|
+
|
|
18
|
+
// Sort edits in reverse order (bottom-to-top, right-to-left)
|
|
19
|
+
const sortedEdits = [...edits].sort((a, b) => {
|
|
20
|
+
if (a.range.start.line !== b.range.start.line) {
|
|
21
|
+
return b.range.start.line - a.range.start.line;
|
|
22
|
+
}
|
|
23
|
+
return b.range.start.character - a.range.start.character;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
for (const edit of sortedEdits) {
|
|
27
|
+
const { start, end } = edit.range;
|
|
28
|
+
|
|
29
|
+
// Single-line edit: replace substring within same line
|
|
30
|
+
if (start.line === end.line) {
|
|
31
|
+
const line = lines[start.line] || "";
|
|
32
|
+
lines[start.line] = line.slice(0, start.character) + edit.newText + line.slice(end.character);
|
|
33
|
+
} else {
|
|
34
|
+
// Multi-line edit: splice across multiple lines
|
|
35
|
+
const startLine = lines[start.line] || "";
|
|
36
|
+
const endLine = lines[end.line] || "";
|
|
37
|
+
const newContent = startLine.slice(0, start.character) + edit.newText + endLine.slice(end.character);
|
|
38
|
+
lines.splice(start.line, end.line - start.line + 1, ...newContent.split("\n"));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
await Bun.write(filePath, lines.join("\n"));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// =============================================================================
|
|
46
|
+
// Workspace Edit Application
|
|
47
|
+
// =============================================================================
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Apply a workspace edit (collection of file changes).
|
|
51
|
+
* Returns array of applied change descriptions.
|
|
52
|
+
*/
|
|
53
|
+
export async function applyWorkspaceEdit(edit: WorkspaceEdit, cwd: string): Promise<string[]> {
|
|
54
|
+
const applied: string[] = [];
|
|
55
|
+
|
|
56
|
+
// Handle changes map (legacy format)
|
|
57
|
+
if (edit.changes) {
|
|
58
|
+
for (const [uri, textEdits] of Object.entries(edit.changes)) {
|
|
59
|
+
const filePath = uriToFile(uri);
|
|
60
|
+
await applyTextEdits(filePath, textEdits);
|
|
61
|
+
applied.push(`Applied ${textEdits.length} edit(s) to ${path.relative(cwd, filePath)}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Handle documentChanges array (modern format)
|
|
66
|
+
if (edit.documentChanges) {
|
|
67
|
+
for (const change of edit.documentChanges) {
|
|
68
|
+
if ("textDocument" in change && change.textDocument && "edits" in change && change.edits) {
|
|
69
|
+
// TextDocumentEdit
|
|
70
|
+
const docChange = change as TextDocumentEdit;
|
|
71
|
+
const filePath = uriToFile(docChange.textDocument.uri);
|
|
72
|
+
const textEdits = docChange.edits.filter((e): e is TextEdit => "range" in e && "newText" in e);
|
|
73
|
+
await applyTextEdits(filePath, textEdits);
|
|
74
|
+
applied.push(`Applied ${textEdits.length} edit(s) to ${path.relative(cwd, filePath)}`);
|
|
75
|
+
} else if ("kind" in change && change.kind) {
|
|
76
|
+
// Resource operations
|
|
77
|
+
if (change.kind === "create") {
|
|
78
|
+
const createOp = change as CreateFile;
|
|
79
|
+
const filePath = uriToFile(createOp.uri);
|
|
80
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
81
|
+
await Bun.write(filePath, "");
|
|
82
|
+
applied.push(`Created ${path.relative(cwd, filePath)}`);
|
|
83
|
+
} else if (change.kind === "rename") {
|
|
84
|
+
const renameOp = change as RenameFile;
|
|
85
|
+
const oldPath = uriToFile(renameOp.oldUri);
|
|
86
|
+
const newPath = uriToFile(renameOp.newUri);
|
|
87
|
+
await mkdir(path.dirname(newPath), { recursive: true });
|
|
88
|
+
await rename(oldPath, newPath);
|
|
89
|
+
applied.push(`Renamed ${path.relative(cwd, oldPath)} → ${path.relative(cwd, newPath)}`);
|
|
90
|
+
} else if (change.kind === "delete") {
|
|
91
|
+
const deleteOp = change as DeleteFile;
|
|
92
|
+
const filePath = uriToFile(deleteOp.uri);
|
|
93
|
+
await rm(filePath, { recursive: true });
|
|
94
|
+
applied.push(`Deleted ${path.relative(cwd, filePath)}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return applied;
|
|
101
|
+
}
|