gsd-pi 2.19.0 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/cli.js +3 -3
- package/dist/onboarding.d.ts +3 -1
- package/dist/onboarding.js +77 -3
- package/dist/remote-questions-config.d.ts +1 -1
- package/dist/resources/extensions/google-search/index.ts +164 -47
- package/dist/resources/extensions/gsd/auto-prompts.ts +103 -24
- package/dist/resources/extensions/gsd/auto-worktree.ts +93 -9
- package/dist/resources/extensions/gsd/auto.ts +424 -30
- package/dist/resources/extensions/gsd/commands.ts +518 -36
- package/dist/resources/extensions/gsd/context-budget.ts +243 -0
- package/dist/resources/extensions/gsd/context-store.ts +195 -0
- package/dist/resources/extensions/gsd/dashboard-overlay.ts +41 -3
- package/dist/resources/extensions/gsd/db-writer.ts +341 -0
- package/dist/resources/extensions/gsd/debug-logger.ts +178 -0
- package/dist/resources/extensions/gsd/dispatch-guard.ts +0 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +54 -0
- package/dist/resources/extensions/gsd/doctor-proactive.ts +286 -0
- package/dist/resources/extensions/gsd/doctor.ts +283 -2
- package/dist/resources/extensions/gsd/export.ts +81 -2
- package/dist/resources/extensions/gsd/files.ts +39 -9
- package/dist/resources/extensions/gsd/git-service.ts +6 -0
- package/dist/resources/extensions/gsd/gsd-db.ts +752 -0
- package/dist/resources/extensions/gsd/guided-flow.ts +26 -1
- package/dist/resources/extensions/gsd/history.ts +0 -1
- package/dist/resources/extensions/gsd/index.ts +277 -1
- package/dist/resources/extensions/gsd/md-importer.ts +526 -0
- package/dist/resources/extensions/gsd/metrics.ts +39 -3
- package/dist/resources/extensions/gsd/notifications.ts +0 -1
- package/dist/resources/extensions/gsd/post-unit-hooks.ts +70 -1
- package/dist/resources/extensions/gsd/preferences.ts +125 -150
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -5
- package/dist/resources/extensions/gsd/prompts/heal-skill.md +45 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +48 -0
- package/dist/resources/extensions/gsd/prompts/system.md +2 -1
- package/dist/resources/extensions/gsd/quick.ts +156 -0
- package/dist/resources/extensions/gsd/skill-discovery.ts +5 -3
- package/dist/resources/extensions/gsd/skill-health.ts +417 -0
- package/dist/resources/extensions/gsd/skill-telemetry.ts +127 -0
- package/dist/resources/extensions/gsd/state.ts +30 -0
- package/dist/resources/extensions/gsd/templates/preferences.md +1 -0
- package/dist/resources/extensions/gsd/tests/context-budget.test.ts +283 -0
- package/dist/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/context-store.test.ts +462 -0
- package/dist/resources/extensions/gsd/tests/continue-here.test.ts +204 -0
- package/dist/resources/extensions/gsd/tests/dashboard-budget.test.ts +346 -0
- package/dist/resources/extensions/gsd/tests/db-writer.test.ts +602 -0
- package/dist/resources/extensions/gsd/tests/debug-logger.test.ts +185 -0
- package/dist/resources/extensions/gsd/tests/derive-state-db.test.ts +406 -0
- package/dist/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +22 -0
- package/dist/resources/extensions/gsd/tests/doctor-proactive.test.ts +244 -0
- package/dist/resources/extensions/gsd/tests/doctor-runtime.test.ts +303 -0
- package/dist/resources/extensions/gsd/tests/gsd-db.test.ts +353 -0
- package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +125 -0
- package/dist/resources/extensions/gsd/tests/gsd-tools.test.ts +326 -0
- package/dist/resources/extensions/gsd/tests/integration-edge.test.ts +228 -0
- package/dist/resources/extensions/gsd/tests/integration-lifecycle.test.ts +277 -0
- package/dist/resources/extensions/gsd/tests/md-importer.test.ts +411 -0
- package/dist/resources/extensions/gsd/tests/metrics.test.ts +197 -0
- package/dist/resources/extensions/gsd/tests/model-isolation.test.ts +99 -0
- package/dist/resources/extensions/gsd/tests/parsers.test.ts +40 -0
- package/dist/resources/extensions/gsd/tests/post-unit-hooks.test.ts +41 -1
- package/dist/resources/extensions/gsd/tests/preferences-git.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/preferences-mode.test.ts +110 -0
- package/dist/resources/extensions/gsd/tests/preferences-models.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +464 -0
- package/dist/resources/extensions/gsd/tests/prompt-db.test.ts +385 -0
- package/dist/resources/extensions/gsd/tests/remote-questions.test.ts +262 -1
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +17 -29
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +2 -8
- package/dist/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
- package/dist/resources/extensions/gsd/tests/stop-auto-remote.test.ts +31 -8
- package/dist/resources/extensions/gsd/tests/token-savings.test.ts +366 -0
- package/dist/resources/extensions/gsd/tests/unit-runtime.test.ts +25 -1
- package/dist/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +145 -0
- package/dist/resources/extensions/gsd/tests/visualizer-data.test.ts +92 -0
- package/dist/resources/extensions/gsd/tests/visualizer-overlay.test.ts +120 -0
- package/dist/resources/extensions/gsd/tests/visualizer-views.test.ts +228 -5
- package/dist/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
- package/dist/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
- package/dist/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
- package/dist/resources/extensions/gsd/types.ts +29 -0
- package/dist/resources/extensions/gsd/undo.ts +0 -1
- package/dist/resources/extensions/gsd/unit-runtime.ts +5 -1
- package/dist/resources/extensions/gsd/visualizer-data.ts +352 -1
- package/dist/resources/extensions/gsd/visualizer-overlay.ts +166 -22
- package/dist/resources/extensions/gsd/visualizer-views.ts +464 -2
- package/dist/resources/extensions/gsd/worktree-command.ts +18 -0
- package/dist/resources/extensions/gsd/worktree-manager.ts +11 -4
- package/dist/resources/extensions/remote-questions/config.ts +4 -2
- package/dist/resources/extensions/remote-questions/discord-adapter.ts +2 -4
- package/dist/resources/extensions/remote-questions/format.ts +154 -8
- package/dist/resources/extensions/remote-questions/manager.ts +9 -7
- package/dist/resources/extensions/remote-questions/remote-command.ts +100 -4
- package/dist/resources/extensions/remote-questions/slack-adapter.ts +58 -2
- package/dist/resources/extensions/remote-questions/telegram-adapter.ts +161 -0
- package/dist/resources/extensions/remote-questions/types.ts +2 -1
- package/dist/resources/extensions/ttsr/ttsr-manager.ts +26 -0
- package/dist/resources/extensions/voice/index.ts +4 -3
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +12 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +25 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.js +106 -3
- package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp.md +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.d.ts +35 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/types.js +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.js +45 -0
- package/packages/pi-coding-agent/dist/core/lsp/utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +43 -11
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +7 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -0
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +5 -0
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +13 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +6 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +26 -0
- package/packages/pi-coding-agent/src/core/lsp/index.ts +157 -2
- package/packages/pi-coding-agent/src/core/lsp/lsp.md +6 -0
- package/packages/pi-coding-agent/src/core/lsp/types.ts +53 -0
- package/packages/pi-coding-agent/src/core/lsp/utils.ts +56 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +41 -11
- package/packages/pi-coding-agent/src/core/system-prompt.ts +7 -1
- package/packages/pi-coding-agent/src/core/tools/edit.ts +3 -0
- package/packages/pi-coding-agent/src/core/tools/write.ts +3 -0
- package/src/resources/extensions/google-search/index.ts +164 -47
- package/src/resources/extensions/gsd/auto-prompts.ts +103 -24
- package/src/resources/extensions/gsd/auto-worktree.ts +93 -9
- package/src/resources/extensions/gsd/auto.ts +424 -30
- package/src/resources/extensions/gsd/commands.ts +518 -36
- package/src/resources/extensions/gsd/context-budget.ts +243 -0
- package/src/resources/extensions/gsd/context-store.ts +195 -0
- package/src/resources/extensions/gsd/dashboard-overlay.ts +41 -3
- package/src/resources/extensions/gsd/db-writer.ts +341 -0
- package/src/resources/extensions/gsd/debug-logger.ts +178 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +0 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +54 -0
- package/src/resources/extensions/gsd/doctor-proactive.ts +286 -0
- package/src/resources/extensions/gsd/doctor.ts +283 -2
- package/src/resources/extensions/gsd/export.ts +81 -2
- package/src/resources/extensions/gsd/files.ts +39 -9
- package/src/resources/extensions/gsd/git-service.ts +6 -0
- package/src/resources/extensions/gsd/gsd-db.ts +752 -0
- package/src/resources/extensions/gsd/guided-flow.ts +26 -1
- package/src/resources/extensions/gsd/history.ts +0 -1
- package/src/resources/extensions/gsd/index.ts +277 -1
- package/src/resources/extensions/gsd/md-importer.ts +526 -0
- package/src/resources/extensions/gsd/metrics.ts +39 -3
- package/src/resources/extensions/gsd/notifications.ts +0 -1
- package/src/resources/extensions/gsd/post-unit-hooks.ts +70 -1
- package/src/resources/extensions/gsd/preferences.ts +125 -150
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -5
- package/src/resources/extensions/gsd/prompts/heal-skill.md +45 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +48 -0
- package/src/resources/extensions/gsd/prompts/system.md +2 -1
- package/src/resources/extensions/gsd/quick.ts +156 -0
- package/src/resources/extensions/gsd/skill-discovery.ts +5 -3
- package/src/resources/extensions/gsd/skill-health.ts +417 -0
- package/src/resources/extensions/gsd/skill-telemetry.ts +127 -0
- package/src/resources/extensions/gsd/state.ts +30 -0
- package/src/resources/extensions/gsd/templates/preferences.md +1 -0
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +283 -0
- package/src/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/context-store.test.ts +462 -0
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +204 -0
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +346 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +602 -0
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +185 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +406 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +22 -0
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +244 -0
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +353 -0
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +326 -0
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +228 -0
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +277 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +411 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +197 -0
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/parsers.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +41 -1
- package/src/resources/extensions/gsd/tests/preferences-git.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/preferences-mode.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/preferences-models.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +464 -0
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +385 -0
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +262 -1
- package/src/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +17 -29
- package/src/resources/extensions/gsd/tests/resolve-ts.mjs +2 -8
- package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
- package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +31 -8
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +366 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +228 -5
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
- package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
- package/src/resources/extensions/gsd/types.ts +29 -0
- package/src/resources/extensions/gsd/undo.ts +0 -1
- package/src/resources/extensions/gsd/unit-runtime.ts +5 -1
- package/src/resources/extensions/gsd/visualizer-data.ts +352 -1
- package/src/resources/extensions/gsd/visualizer-overlay.ts +166 -22
- package/src/resources/extensions/gsd/visualizer-views.ts +464 -2
- package/src/resources/extensions/gsd/worktree-command.ts +18 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +11 -4
- package/src/resources/extensions/remote-questions/config.ts +4 -2
- package/src/resources/extensions/remote-questions/discord-adapter.ts +2 -4
- package/src/resources/extensions/remote-questions/format.ts +154 -8
- package/src/resources/extensions/remote-questions/manager.ts +9 -7
- package/src/resources/extensions/remote-questions/remote-command.ts +100 -4
- package/src/resources/extensions/remote-questions/slack-adapter.ts +58 -2
- package/src/resources/extensions/remote-questions/telegram-adapter.ts +161 -0
- package/src/resources/extensions/remote-questions/types.ts +2 -1
- package/src/resources/extensions/ttsr/ttsr-manager.ts +26 -0
- package/src/resources/extensions/voice/index.ts +4 -3
|
@@ -1356,6 +1356,7 @@ export class AgentSession {
|
|
|
1356
1356
|
this.agent.reset();
|
|
1357
1357
|
// Update cwd to current process directory — auto-mode may have chdir'd
|
|
1358
1358
|
// into a worktree since the original session was created.
|
|
1359
|
+
const previousCwd = this._cwd;
|
|
1359
1360
|
this._cwd = process.cwd();
|
|
1360
1361
|
this.sessionManager.newSession({ parentSession: options?.parentSession });
|
|
1361
1362
|
this.agent.sessionId = this.sessionManager.getSessionId();
|
|
@@ -1365,6 +1366,17 @@ export class AgentSession {
|
|
|
1365
1366
|
|
|
1366
1367
|
this.sessionManager.appendThinkingLevelChange(this.thinkingLevel);
|
|
1367
1368
|
|
|
1369
|
+
// Rebuild tools when cwd changed (e.g., auto-mode entered a worktree).
|
|
1370
|
+
// Tools capture cwd at creation time for path resolution — without
|
|
1371
|
+
// rebuilding, write/read/edit/bash resolve relative paths against
|
|
1372
|
+
// the original project root instead of the worktree (#633).
|
|
1373
|
+
if (this._cwd !== previousCwd) {
|
|
1374
|
+
this._buildRuntime({
|
|
1375
|
+
activeToolNames: this.getActiveToolNames(),
|
|
1376
|
+
includeAllExtensionTools: true,
|
|
1377
|
+
});
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1368
1380
|
// Run setup callback if provided (e.g., to append initial messages)
|
|
1369
1381
|
if (options?.setup) {
|
|
1370
1382
|
await options.setup(this.sessionManager);
|
|
@@ -2331,7 +2343,7 @@ export class AgentSession {
|
|
|
2331
2343
|
|
|
2332
2344
|
const defaultActiveToolNames = this._baseToolsOverride
|
|
2333
2345
|
? Object.keys(this._baseToolsOverride)
|
|
2334
|
-
: ["read", "bash", "edit", "write"];
|
|
2346
|
+
: ["read", "bash", "edit", "write", "lsp"];
|
|
2335
2347
|
const baseActiveToolNames = options.activeToolNames ?? defaultActiveToolNames;
|
|
2336
2348
|
this._refreshToolRegistry({
|
|
2337
2349
|
activeToolNames: baseActiveToolNames,
|
|
@@ -19,6 +19,7 @@ import * as _bundledPiTui from "@gsd/pi-tui";
|
|
|
19
19
|
// These MUST be static so Bun bundles them into the compiled binary.
|
|
20
20
|
// The virtualModules option then makes them available to extensions.
|
|
21
21
|
import * as _bundledTypebox from "@sinclair/typebox";
|
|
22
|
+
import * as _bundledYaml from "yaml";
|
|
22
23
|
import { getAgentDir, isBunBinary } from "../../config.js";
|
|
23
24
|
// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,
|
|
24
25
|
// avoiding a circular dependency. Extensions can import from @gsd/pi-coding-agent.
|
|
@@ -46,6 +47,7 @@ const VIRTUAL_MODULES: Record<string, unknown> = {
|
|
|
46
47
|
"@gsd/pi-ai": _bundledPiAi,
|
|
47
48
|
"@gsd/pi-ai/oauth": _bundledPiAiOauth,
|
|
48
49
|
"@gsd/pi-coding-agent": _bundledPiCodingAgent,
|
|
50
|
+
"yaml": _bundledYaml,
|
|
49
51
|
// Aliases for external PI ecosystem packages that import from the original scope
|
|
50
52
|
"@mariozechner/pi-agent-core": _bundledPiAgentCore,
|
|
51
53
|
"@mariozechner/pi-tui": _bundledPiTui,
|
|
@@ -70,6 +72,9 @@ function getAliases(): Record<string, string> {
|
|
|
70
72
|
const typeboxEntry = require.resolve("@sinclair/typebox");
|
|
71
73
|
const typeboxRoot = typeboxEntry.replace(/[\\/]build[\\/]cjs[\\/]index\.js$/, "");
|
|
72
74
|
|
|
75
|
+
const yamlEntry = require.resolve("yaml");
|
|
76
|
+
const yamlRoot = yamlEntry.replace(/[\\/]dist[\\/]index\.js$/, "");
|
|
77
|
+
|
|
73
78
|
const packagesRoot = path.resolve(__dirname, "../../../../");
|
|
74
79
|
const resolveWorkspaceOrImport = (workspaceRelativePath: string, specifier: string): string => {
|
|
75
80
|
const workspacePath = path.join(packagesRoot, workspaceRelativePath);
|
|
@@ -86,6 +91,7 @@ function getAliases(): Record<string, string> {
|
|
|
86
91
|
"@gsd/pi-ai": resolveWorkspaceOrImport("ai/dist/index.js", "@gsd/pi-ai"),
|
|
87
92
|
"@gsd/pi-ai/oauth": resolveWorkspaceOrImport("ai/dist/oauth.js", "@gsd/pi-ai/oauth"),
|
|
88
93
|
"@sinclair/typebox": typeboxRoot,
|
|
94
|
+
"yaml": yamlRoot,
|
|
89
95
|
// Aliases for external PI ecosystem packages that import from the original scope
|
|
90
96
|
"@mariozechner/pi-coding-agent": packageIndex,
|
|
91
97
|
"@mariozechner/pi-agent-core": resolveWorkspaceOrImport("agent/dist/index.js", "@gsd/pi-agent-core"),
|
|
@@ -124,6 +124,18 @@ const CLIENT_CAPABILITIES = {
|
|
|
124
124
|
properties: ["edit"],
|
|
125
125
|
},
|
|
126
126
|
},
|
|
127
|
+
callHierarchy: {
|
|
128
|
+
dynamicRegistration: false,
|
|
129
|
+
},
|
|
130
|
+
signatureHelp: {
|
|
131
|
+
dynamicRegistration: false,
|
|
132
|
+
signatureInformation: {
|
|
133
|
+
documentationFormat: ["markdown", "plaintext"],
|
|
134
|
+
parameterInformation: {
|
|
135
|
+
labelOffsetSupport: true,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
127
139
|
formatting: {
|
|
128
140
|
dynamicRegistration: false,
|
|
129
141
|
},
|
|
@@ -701,6 +713,20 @@ export async function refreshFile(client: LspClient, filePath: string, signal?:
|
|
|
701
713
|
}
|
|
702
714
|
}
|
|
703
715
|
|
|
716
|
+
/**
|
|
717
|
+
* Notify all LSP clients that have the file open that it changed on disk.
|
|
718
|
+
* Synchronous entry point — async refresh runs in background.
|
|
719
|
+
* Swallows errors so editing never fails because of LSP.
|
|
720
|
+
*/
|
|
721
|
+
export function notifyFileChanged(filePath: string): void {
|
|
722
|
+
const uri = fileToUri(filePath);
|
|
723
|
+
for (const client of clients.values()) {
|
|
724
|
+
if (client.openFiles.has(uri)) {
|
|
725
|
+
refreshFile(client, filePath).catch(() => {});
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
704
730
|
/**
|
|
705
731
|
* Shutdown a specific client by key.
|
|
706
732
|
*/
|
|
@@ -15,10 +15,13 @@ import {
|
|
|
15
15
|
WARMUP_TIMEOUT_MS,
|
|
16
16
|
} from "./client.js";
|
|
17
17
|
import { getServersForFile, type LspConfig, loadConfig } from "./config.js";
|
|
18
|
-
import { applyWorkspaceEdit } from "./edits.js";
|
|
18
|
+
import { applyTextEdits, applyWorkspaceEdit } from "./edits.js";
|
|
19
19
|
import { ToolAbortError, clampTimeout, throwIfAborted } from "./helpers.js";
|
|
20
20
|
import { detectLspmux } from "./lspmux.js";
|
|
21
21
|
import {
|
|
22
|
+
type CallHierarchyIncomingCall,
|
|
23
|
+
type CallHierarchyItem,
|
|
24
|
+
type CallHierarchyOutgoingCall,
|
|
22
25
|
type CodeAction,
|
|
23
26
|
type CodeActionContext,
|
|
24
27
|
type Command,
|
|
@@ -32,7 +35,9 @@ import {
|
|
|
32
35
|
type LspToolDetails,
|
|
33
36
|
lspSchema,
|
|
34
37
|
type ServerConfig,
|
|
38
|
+
type SignatureHelp,
|
|
35
39
|
type SymbolInformation,
|
|
40
|
+
type TextEdit,
|
|
36
41
|
type WorkspaceEdit,
|
|
37
42
|
} from "./types.js";
|
|
38
43
|
import {
|
|
@@ -42,12 +47,14 @@ import {
|
|
|
42
47
|
extractHoverText,
|
|
43
48
|
fileToUri,
|
|
44
49
|
filterWorkspaceSymbols,
|
|
50
|
+
formatCallHierarchyItem,
|
|
45
51
|
formatCodeAction,
|
|
46
52
|
formatDiagnostic,
|
|
47
53
|
formatDiagnosticsSummary,
|
|
48
54
|
formatDocumentSymbol,
|
|
49
55
|
formatGroupedDiagnosticMessages,
|
|
50
56
|
formatLocation,
|
|
57
|
+
formatSignatureHelp,
|
|
51
58
|
formatSymbolInformation,
|
|
52
59
|
formatWorkspaceEdit,
|
|
53
60
|
hasGlobPattern,
|
|
@@ -338,7 +345,7 @@ export function createLspTool(cwd: string): AgentTool<typeof lspSchema, LspToolD
|
|
|
338
345
|
signal?: AbortSignal,
|
|
339
346
|
_onUpdate?: AgentToolUpdateCallback<LspToolDetails>,
|
|
340
347
|
): Promise<AgentToolResult<LspToolDetails>> {
|
|
341
|
-
const { action, file, line, symbol, occurrence, query, new_name, apply, timeout } = params;
|
|
348
|
+
const { action, file, line, symbol, occurrence, query, new_name, apply, tab_size, insert_spaces, timeout } = params;
|
|
342
349
|
const timeoutSec = clampTimeout(timeout);
|
|
343
350
|
const timeoutSignal = AbortSignal.timeout(timeoutSec * 1000);
|
|
344
351
|
signal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
@@ -876,6 +883,154 @@ export function createLspTool(cwd: string): AgentTool<typeof lspSchema, LspToolD
|
|
|
876
883
|
break;
|
|
877
884
|
}
|
|
878
885
|
|
|
886
|
+
case "incoming_calls": {
|
|
887
|
+
const prepareResult = (await sendRequest(
|
|
888
|
+
client,
|
|
889
|
+
"textDocument/prepareCallHierarchy",
|
|
890
|
+
{
|
|
891
|
+
textDocument: { uri },
|
|
892
|
+
position,
|
|
893
|
+
},
|
|
894
|
+
signal,
|
|
895
|
+
)) as CallHierarchyItem[] | null;
|
|
896
|
+
|
|
897
|
+
if (!prepareResult || prepareResult.length === 0) {
|
|
898
|
+
output = "No call hierarchy item found at this position";
|
|
899
|
+
break;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
const incomingResult = (await sendRequest(
|
|
903
|
+
client,
|
|
904
|
+
"callHierarchy/incomingCalls",
|
|
905
|
+
{ item: prepareResult[0] },
|
|
906
|
+
signal,
|
|
907
|
+
)) as CallHierarchyIncomingCall[] | null;
|
|
908
|
+
|
|
909
|
+
if (!incomingResult || incomingResult.length === 0) {
|
|
910
|
+
output = `No incoming calls found for ${prepareResult[0].name}`;
|
|
911
|
+
break;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
const incomingLines: string[] = [];
|
|
915
|
+
const limitedIncoming = incomingResult.slice(0, REFERENCE_CONTEXT_LIMIT);
|
|
916
|
+
for (const call of limitedIncoming) {
|
|
917
|
+
const header = formatCallHierarchyItem(call.from, cwd);
|
|
918
|
+
const filePath = uriToFile(call.from.uri);
|
|
919
|
+
const callLine = call.fromRanges[0]?.start.line ?? call.from.selectionRange.start.line;
|
|
920
|
+
const context = await readLocationContext(filePath, callLine + 1, LOCATION_CONTEXT_LINES);
|
|
921
|
+
if (context.length > 0) {
|
|
922
|
+
incomingLines.push(` ${header}\n${context.map(l => ` ${l}`).join("\n")}`);
|
|
923
|
+
} else {
|
|
924
|
+
incomingLines.push(` ${header}`);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
const truncation = incomingResult.length > REFERENCE_CONTEXT_LIMIT
|
|
929
|
+
? `\n ... ${incomingResult.length - REFERENCE_CONTEXT_LIMIT} additional caller(s) omitted`
|
|
930
|
+
: "";
|
|
931
|
+
output = `${incomingResult.length} caller(s) of ${prepareResult[0].name}:\n${incomingLines.join("\n")}${truncation}`;
|
|
932
|
+
break;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
case "outgoing_calls": {
|
|
936
|
+
const prepareResult = (await sendRequest(
|
|
937
|
+
client,
|
|
938
|
+
"textDocument/prepareCallHierarchy",
|
|
939
|
+
{
|
|
940
|
+
textDocument: { uri },
|
|
941
|
+
position,
|
|
942
|
+
},
|
|
943
|
+
signal,
|
|
944
|
+
)) as CallHierarchyItem[] | null;
|
|
945
|
+
|
|
946
|
+
if (!prepareResult || prepareResult.length === 0) {
|
|
947
|
+
output = "No call hierarchy item found at this position";
|
|
948
|
+
break;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
const outgoingResult = (await sendRequest(
|
|
952
|
+
client,
|
|
953
|
+
"callHierarchy/outgoingCalls",
|
|
954
|
+
{ item: prepareResult[0] },
|
|
955
|
+
signal,
|
|
956
|
+
)) as CallHierarchyOutgoingCall[] | null;
|
|
957
|
+
|
|
958
|
+
if (!outgoingResult || outgoingResult.length === 0) {
|
|
959
|
+
output = `No outgoing calls found from ${prepareResult[0].name}`;
|
|
960
|
+
break;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
const outgoingLines: string[] = [];
|
|
964
|
+
const limitedOutgoing = outgoingResult.slice(0, REFERENCE_CONTEXT_LIMIT);
|
|
965
|
+
for (const call of limitedOutgoing) {
|
|
966
|
+
const header = formatCallHierarchyItem(call.to, cwd);
|
|
967
|
+
const filePath = uriToFile(call.to.uri);
|
|
968
|
+
const callLine = call.to.selectionRange.start.line;
|
|
969
|
+
const context = await readLocationContext(filePath, callLine + 1, LOCATION_CONTEXT_LINES);
|
|
970
|
+
if (context.length > 0) {
|
|
971
|
+
outgoingLines.push(` ${header}\n${context.map(l => ` ${l}`).join("\n")}`);
|
|
972
|
+
} else {
|
|
973
|
+
outgoingLines.push(` ${header}`);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
const outTruncation = outgoingResult.length > REFERENCE_CONTEXT_LIMIT
|
|
978
|
+
? `\n ... ${outgoingResult.length - REFERENCE_CONTEXT_LIMIT} additional callee(s) omitted`
|
|
979
|
+
: "";
|
|
980
|
+
output = `${outgoingResult.length} callee(s) from ${prepareResult[0].name}:\n${outgoingLines.join("\n")}${outTruncation}`;
|
|
981
|
+
break;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
case "format": {
|
|
985
|
+
if (!targetFile) {
|
|
986
|
+
output = "Error: file parameter required for format";
|
|
987
|
+
break;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
const formatResult = (await sendRequest(
|
|
991
|
+
client,
|
|
992
|
+
"textDocument/formatting",
|
|
993
|
+
{
|
|
994
|
+
textDocument: { uri },
|
|
995
|
+
options: {
|
|
996
|
+
tabSize: tab_size ?? 4,
|
|
997
|
+
insertSpaces: insert_spaces ?? true,
|
|
998
|
+
},
|
|
999
|
+
},
|
|
1000
|
+
signal,
|
|
1001
|
+
)) as TextEdit[] | null;
|
|
1002
|
+
|
|
1003
|
+
if (!formatResult || formatResult.length === 0) {
|
|
1004
|
+
const relPath = path.relative(cwd, targetFile);
|
|
1005
|
+
output = `${relPath}: already formatted (no changes)`;
|
|
1006
|
+
break;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
await applyTextEdits(targetFile, formatResult);
|
|
1010
|
+
const relPath = path.relative(cwd, targetFile);
|
|
1011
|
+
output = `Formatted ${relPath}: ${formatResult.length} edit(s) applied`;
|
|
1012
|
+
break;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
case "signature": {
|
|
1016
|
+
const sigResult = (await sendRequest(
|
|
1017
|
+
client,
|
|
1018
|
+
"textDocument/signatureHelp",
|
|
1019
|
+
{
|
|
1020
|
+
textDocument: { uri },
|
|
1021
|
+
position,
|
|
1022
|
+
},
|
|
1023
|
+
signal,
|
|
1024
|
+
)) as SignatureHelp | null;
|
|
1025
|
+
|
|
1026
|
+
if (!sigResult || !sigResult.signatures || sigResult.signatures.length === 0) {
|
|
1027
|
+
output = "No signature information at this position";
|
|
1028
|
+
} else {
|
|
1029
|
+
output = formatSignatureHelp(sigResult);
|
|
1030
|
+
}
|
|
1031
|
+
break;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
879
1034
|
case "rename": {
|
|
880
1035
|
if (!new_name) {
|
|
881
1036
|
return {
|
|
@@ -8,8 +8,12 @@ Interacts with Language Server Protocol servers for code intelligence.
|
|
|
8
8
|
- `references`: Find references → locations with 3-line source context (first 50), remaining location-only
|
|
9
9
|
- `hover`: Get type info and documentation → type signature + docs
|
|
10
10
|
- `symbols`: List symbols in file, or search workspace (with query, no file)
|
|
11
|
+
- `incoming_calls`: Find all callers of a function → call sites with context
|
|
12
|
+
- `outgoing_calls`: Find all functions called by a function → callees with context
|
|
11
13
|
- `rename`: Rename symbol across codebase → preview or apply edits
|
|
12
14
|
- `code_actions`: List available quick-fixes/refactors/import actions; apply one when `apply: true` and `query` matches title or index
|
|
15
|
+
- `format`: Format file using language server formatter → applies edits in-place
|
|
16
|
+
- `signature`: Get function signature and parameter info at cursor position
|
|
13
17
|
- `status`: Show active language servers
|
|
14
18
|
- `reload`: Restart the language server
|
|
15
19
|
</operations>
|
|
@@ -22,6 +26,8 @@ Interacts with Language Server Protocol servers for code intelligence.
|
|
|
22
26
|
- `query`: Symbol search query, code-action kind filter (list mode), or code-action selector (apply mode)
|
|
23
27
|
- `new_name`: Required for rename
|
|
24
28
|
- `apply`: Apply edits for rename/code_actions (default true for rename, list mode for code_actions unless explicitly true)
|
|
29
|
+
- `tab_size`: Tab size for formatting (default: 4)
|
|
30
|
+
- `insert_spaces`: Use spaces for formatting (default: true)
|
|
25
31
|
- `timeout`: Request timeout in seconds (clamped to 5-60, default 20)
|
|
26
32
|
</parameters>
|
|
27
33
|
|
|
@@ -29,6 +29,10 @@ export const lspSchema = Type.Object({
|
|
|
29
29
|
"code_actions",
|
|
30
30
|
"type_definition",
|
|
31
31
|
"implementation",
|
|
32
|
+
"incoming_calls",
|
|
33
|
+
"outgoing_calls",
|
|
34
|
+
"format",
|
|
35
|
+
"signature",
|
|
32
36
|
"status",
|
|
33
37
|
"reload",
|
|
34
38
|
],
|
|
@@ -43,6 +47,8 @@ export const lspSchema = Type.Object({
|
|
|
43
47
|
query: Type.Optional(Type.String({ description: "Search query or SSR pattern" })),
|
|
44
48
|
new_name: Type.Optional(Type.String({ description: "New name for rename" })),
|
|
45
49
|
apply: Type.Optional(Type.Boolean({ description: "Apply edits (default: true)" })),
|
|
50
|
+
tab_size: Type.Optional(Type.Number({ description: "Tab size for formatting (default: 4)" })),
|
|
51
|
+
insert_spaces: Type.Optional(Type.Boolean({ description: "Use spaces for formatting (default: true)" })),
|
|
46
52
|
timeout: Type.Optional(Type.Number({ description: "Request timeout in seconds" })),
|
|
47
53
|
});
|
|
48
54
|
|
|
@@ -419,3 +425,50 @@ export interface LspJsonRpcNotification {
|
|
|
419
425
|
method: string;
|
|
420
426
|
params?: unknown;
|
|
421
427
|
}
|
|
428
|
+
|
|
429
|
+
// =============================================================================
|
|
430
|
+
// Call Hierarchy
|
|
431
|
+
// =============================================================================
|
|
432
|
+
|
|
433
|
+
export interface CallHierarchyItem {
|
|
434
|
+
name: string;
|
|
435
|
+
kind: SymbolKind;
|
|
436
|
+
tags?: number[];
|
|
437
|
+
detail?: string;
|
|
438
|
+
uri: string;
|
|
439
|
+
range: Range;
|
|
440
|
+
selectionRange: Range;
|
|
441
|
+
data?: unknown;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export interface CallHierarchyIncomingCall {
|
|
445
|
+
from: CallHierarchyItem;
|
|
446
|
+
fromRanges: Range[];
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
export interface CallHierarchyOutgoingCall {
|
|
450
|
+
to: CallHierarchyItem;
|
|
451
|
+
fromRanges: Range[];
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// =============================================================================
|
|
455
|
+
// Signature Help
|
|
456
|
+
// =============================================================================
|
|
457
|
+
|
|
458
|
+
export interface ParameterInformation {
|
|
459
|
+
label: string | [number, number];
|
|
460
|
+
documentation?: string | MarkupContent;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export interface SignatureInformation {
|
|
464
|
+
label: string;
|
|
465
|
+
documentation?: string | MarkupContent;
|
|
466
|
+
parameters?: ParameterInformation[];
|
|
467
|
+
activeParameter?: number;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
export interface SignatureHelp {
|
|
471
|
+
signatures: SignatureInformation[];
|
|
472
|
+
activeSignature?: number;
|
|
473
|
+
activeParameter?: number;
|
|
474
|
+
}
|
|
@@ -3,12 +3,15 @@ import path from "node:path";
|
|
|
3
3
|
import { glob } from "glob";
|
|
4
4
|
import { isEnoent } from "./helpers.js";
|
|
5
5
|
import type {
|
|
6
|
+
CallHierarchyItem,
|
|
6
7
|
CodeAction,
|
|
7
8
|
Command,
|
|
8
9
|
Diagnostic,
|
|
9
10
|
DiagnosticSeverity,
|
|
10
11
|
DocumentSymbol,
|
|
11
12
|
Location,
|
|
13
|
+
MarkupContent,
|
|
14
|
+
SignatureHelp,
|
|
12
15
|
SymbolInformation,
|
|
13
16
|
SymbolKind,
|
|
14
17
|
TextEdit,
|
|
@@ -680,3 +683,56 @@ export async function readLocationContext(filePath: string, line: number, contex
|
|
|
680
683
|
throw error;
|
|
681
684
|
}
|
|
682
685
|
}
|
|
686
|
+
|
|
687
|
+
// =============================================================================
|
|
688
|
+
// Call Hierarchy Formatting
|
|
689
|
+
// =============================================================================
|
|
690
|
+
|
|
691
|
+
export function formatCallHierarchyItem(item: CallHierarchyItem, cwd: string): string {
|
|
692
|
+
const icon = symbolKindToIcon(item.kind);
|
|
693
|
+
const detail = item.detail ? ` ${item.detail}` : "";
|
|
694
|
+
const relPath = path.relative(cwd, uriToFile(item.uri));
|
|
695
|
+
const line = item.selectionRange.start.line + 1;
|
|
696
|
+
return `${icon} ${item.name}${detail} @ ${relPath}:${line}`;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// =============================================================================
|
|
700
|
+
// Signature Help Formatting
|
|
701
|
+
// =============================================================================
|
|
702
|
+
|
|
703
|
+
function extractDocText(doc: string | MarkupContent | undefined): string {
|
|
704
|
+
if (!doc) return "";
|
|
705
|
+
if (typeof doc === "string") return doc;
|
|
706
|
+
return doc.value;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
export function formatSignatureHelp(result: SignatureHelp): string {
|
|
710
|
+
if (!result.signatures || result.signatures.length === 0) {
|
|
711
|
+
return "No signature information";
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const activeIdx = result.activeSignature ?? 0;
|
|
715
|
+
const sig = result.signatures[activeIdx] ?? result.signatures[0];
|
|
716
|
+
const activeParam = result.activeParameter ?? sig.activeParameter;
|
|
717
|
+
|
|
718
|
+
const lines: string[] = [sig.label];
|
|
719
|
+
|
|
720
|
+
const sigDoc = extractDocText(sig.documentation);
|
|
721
|
+
if (sigDoc) {
|
|
722
|
+
lines.push("", sigDoc);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
if (sig.parameters && sig.parameters.length > 0) {
|
|
726
|
+
lines.push("", "Parameters:");
|
|
727
|
+
for (let i = 0; i < sig.parameters.length; i++) {
|
|
728
|
+
const p = sig.parameters[i];
|
|
729
|
+
const label = typeof p.label === "string" ? p.label : sig.label.slice(p.label[0], p.label[1]);
|
|
730
|
+
const active = i === activeParam ? " <-- active" : "";
|
|
731
|
+
const doc = extractDocText(p.documentation);
|
|
732
|
+
const docSuffix = doc ? ` — ${doc}` : "";
|
|
733
|
+
lines.push(` ${label}${docSuffix}${active}`);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
return lines.join("\n");
|
|
738
|
+
}
|
|
@@ -473,6 +473,16 @@ export class SettingsManager {
|
|
|
473
473
|
this.errors.push({ scope, error: normalizedError });
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
+
/**
|
|
477
|
+
* Check if project-level settings are active (loaded from a file).
|
|
478
|
+
* Used to scope model persistence to the project when possible,
|
|
479
|
+
* preventing model config bleed between concurrent instances (#650).
|
|
480
|
+
*/
|
|
481
|
+
private hasProjectSettings(): boolean {
|
|
482
|
+
// Project settings are active if we loaded them and they weren't empty/errored
|
|
483
|
+
return !this.projectSettingsLoadError && Object.keys(this.projectSettings).length > 0;
|
|
484
|
+
}
|
|
485
|
+
|
|
476
486
|
private clearModifiedScope(scope: SettingsScope): void {
|
|
477
487
|
if (scope === "global") {
|
|
478
488
|
this.modifiedFields.clear();
|
|
@@ -595,23 +605,43 @@ export class SettingsManager {
|
|
|
595
605
|
}
|
|
596
606
|
|
|
597
607
|
setDefaultProvider(provider: string): void {
|
|
598
|
-
this.
|
|
599
|
-
|
|
600
|
-
|
|
608
|
+
if (this.hasProjectSettings()) {
|
|
609
|
+
this.projectSettings.defaultProvider = provider;
|
|
610
|
+
this.markProjectModified("defaultProvider");
|
|
611
|
+
this.saveProjectSettings(this.projectSettings);
|
|
612
|
+
} else {
|
|
613
|
+
this.globalSettings.defaultProvider = provider;
|
|
614
|
+
this.markModified("defaultProvider");
|
|
615
|
+
this.save();
|
|
616
|
+
}
|
|
601
617
|
}
|
|
602
618
|
|
|
603
619
|
setDefaultModel(modelId: string): void {
|
|
604
|
-
this.
|
|
605
|
-
|
|
606
|
-
|
|
620
|
+
if (this.hasProjectSettings()) {
|
|
621
|
+
this.projectSettings.defaultModel = modelId;
|
|
622
|
+
this.markProjectModified("defaultModel");
|
|
623
|
+
this.saveProjectSettings(this.projectSettings);
|
|
624
|
+
} else {
|
|
625
|
+
this.globalSettings.defaultModel = modelId;
|
|
626
|
+
this.markModified("defaultModel");
|
|
627
|
+
this.save();
|
|
628
|
+
}
|
|
607
629
|
}
|
|
608
630
|
|
|
609
631
|
setDefaultModelAndProvider(provider: string, modelId: string): void {
|
|
610
|
-
this.
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
632
|
+
if (this.hasProjectSettings()) {
|
|
633
|
+
this.projectSettings.defaultProvider = provider;
|
|
634
|
+
this.projectSettings.defaultModel = modelId;
|
|
635
|
+
this.markProjectModified("defaultProvider");
|
|
636
|
+
this.markProjectModified("defaultModel");
|
|
637
|
+
this.saveProjectSettings(this.projectSettings);
|
|
638
|
+
} else {
|
|
639
|
+
this.globalSettings.defaultProvider = provider;
|
|
640
|
+
this.globalSettings.defaultModel = modelId;
|
|
641
|
+
this.markModified("defaultProvider");
|
|
642
|
+
this.markModified("defaultModel");
|
|
643
|
+
this.save();
|
|
644
|
+
}
|
|
615
645
|
}
|
|
616
646
|
|
|
617
647
|
getSteeringMode(): "all" | "one-at-a-time" {
|
|
@@ -159,7 +159,13 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): strin
|
|
|
159
159
|
// LSP guideline
|
|
160
160
|
if (hasLsp) {
|
|
161
161
|
addGuideline(
|
|
162
|
-
|
|
162
|
+
`Use lsp as the primary tool for code navigation in typed codebases:
|
|
163
|
+
- Navigation: definition, type_definition, implementation, references, incoming_calls, outgoing_calls
|
|
164
|
+
- Understanding: hover (types + docs), signature (parameter info), symbols (file/workspace search)
|
|
165
|
+
- Refactoring: rename (project-wide), code_actions (quick-fixes, imports, refactors), format (formatter)
|
|
166
|
+
- Verification: diagnostics after edits to catch type errors immediately
|
|
167
|
+
- Never grep for a symbol definition when lsp can resolve it semantically
|
|
168
|
+
- Never shell out to a formatter when lsp format is available`,
|
|
163
169
|
);
|
|
164
170
|
}
|
|
165
171
|
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
restoreLineEndings,
|
|
12
12
|
stripBom,
|
|
13
13
|
} from "./edit-diff.js";
|
|
14
|
+
import { notifyFileChanged } from "../lsp/client.js";
|
|
14
15
|
import { resolveToCwd } from "./path-utils.js";
|
|
15
16
|
|
|
16
17
|
const editSchema = Type.Object({
|
|
@@ -187,6 +188,8 @@ export function createEditTool(cwd: string, options?: EditToolOptions): AgentToo
|
|
|
187
188
|
const finalContent = bom + restoreLineEndings(newContent, originalEnding);
|
|
188
189
|
await ops.writeFile(absolutePath, finalContent);
|
|
189
190
|
|
|
191
|
+
try { notifyFileChanged(absolutePath); } catch { /* best-effort */ }
|
|
192
|
+
|
|
190
193
|
// Check if aborted after writing
|
|
191
194
|
if (aborted) {
|
|
192
195
|
return;
|
|
@@ -2,6 +2,7 @@ import type { AgentTool } from "@gsd/pi-agent-core";
|
|
|
2
2
|
import { type Static, Type } from "@sinclair/typebox";
|
|
3
3
|
import { mkdir as fsMkdir, writeFile as fsWriteFile } from "fs/promises";
|
|
4
4
|
import { dirname } from "path";
|
|
5
|
+
import { notifyFileChanged } from "../lsp/client.js";
|
|
5
6
|
import { resolveToCwd } from "./path-utils.js";
|
|
6
7
|
|
|
7
8
|
const writeSchema = Type.Object({
|
|
@@ -83,6 +84,8 @@ export function createWriteTool(cwd: string, options?: WriteToolOptions): AgentT
|
|
|
83
84
|
// Write the file
|
|
84
85
|
await ops.writeFile(absolutePath, content);
|
|
85
86
|
|
|
87
|
+
try { notifyFileChanged(absolutePath); } catch { /* best-effort */ }
|
|
88
|
+
|
|
86
89
|
// Check if aborted after writing
|
|
87
90
|
if (aborted) {
|
|
88
91
|
return;
|