@oh-my-pi/pi-coding-agent 9.3.1 → 9.6.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 +98 -0
- package/examples/hooks/snake.ts +5 -5
- package/package.json +9 -8
- package/src/capability/index.ts +7 -9
- package/src/cli/config-cli.ts +86 -73
- package/src/cli/update-cli.ts +45 -3
- package/src/commit/agentic/agent.ts +4 -4
- package/src/commit/agentic/index.ts +6 -5
- package/src/commit/agentic/tools/analyze-file.ts +5 -7
- package/src/commit/agentic/tools/index.ts +3 -3
- package/src/commit/model-selection.ts +13 -17
- package/src/commit/pipeline.ts +5 -5
- package/src/config/model-registry.ts +7 -0
- package/src/config/settings-schema.ts +836 -0
- package/src/config/settings.ts +702 -0
- package/src/discovery/helpers.ts +55 -11
- package/src/exa/index.ts +1 -1
- package/src/exec/bash-executor.ts +13 -13
- package/src/exec/shell-session.ts +15 -3
- package/src/export/ttsr.ts +1 -1
- package/src/extensibility/skills.ts +40 -9
- package/src/index.ts +2 -10
- package/src/ipy/gateway-coordinator.ts +5 -159
- package/src/ipy/kernel.ts +6 -171
- package/src/ipy/runtime.ts +198 -0
- package/src/lsp/client.ts +14 -1
- package/src/lsp/defaults.json +0 -6
- package/src/lsp/index.ts +1 -1
- package/src/lsp/types.ts +2 -0
- package/src/main.ts +26 -48
- package/src/modes/components/armin.ts +7 -7
- package/src/modes/components/extensions/extension-dashboard.ts +33 -13
- package/src/modes/components/extensions/extension-list.ts +2 -2
- package/src/modes/components/footer.ts +5 -5
- package/src/modes/components/history-search.ts +2 -1
- package/src/modes/components/hook-selector.ts +2 -2
- package/src/modes/components/index.ts +1 -1
- package/src/modes/components/model-selector.ts +7 -7
- package/src/modes/components/session-selector.ts +2 -1
- package/src/modes/components/settings-defs.ts +210 -915
- package/src/modes/components/settings-selector.ts +80 -106
- package/src/modes/components/status-line/types.ts +2 -8
- package/src/modes/components/status-line-segment-editor.ts +4 -4
- package/src/modes/components/status-line.ts +28 -5
- package/src/modes/components/welcome.ts +3 -3
- package/src/modes/controllers/command-controller.ts +2 -2
- package/src/modes/controllers/event-controller.ts +9 -8
- package/src/modes/controllers/input-controller.ts +19 -15
- package/src/modes/controllers/selector-controller.ts +30 -14
- package/src/modes/interactive-mode.ts +10 -10
- package/src/modes/rpc/rpc-mode.ts +10 -0
- package/src/modes/rpc/rpc-types.ts +3 -0
- package/src/modes/types.ts +2 -2
- package/src/modes/utils/ui-helpers.ts +4 -3
- package/src/patch/index.ts +7 -7
- package/src/patch/normalize.ts +3 -1
- package/src/prompts/system/plan-mode-active.md +5 -4
- package/src/prompts/system/system-prompt.md +0 -1
- package/src/prompts/tools/bash.md +12 -2
- package/src/prompts/tools/task.md +180 -73
- package/src/sdk.ts +38 -61
- package/src/session/agent-session.ts +66 -55
- package/src/session/agent-storage.ts +1 -1
- package/src/session/session-manager.ts +10 -10
- package/src/system-prompt.ts +2 -2
- package/src/task/executor.ts +9 -9
- package/src/task/index.ts +2 -2
- package/src/tools/ask.ts +5 -6
- package/src/tools/bash-interceptor.ts +39 -1
- package/src/tools/bash-normalize.ts +126 -0
- package/src/tools/bash.ts +31 -5
- package/src/tools/find.ts +51 -33
- package/src/tools/gemini-image.ts +7 -8
- package/src/tools/index.ts +5 -23
- package/src/tools/plan-mode-guard.ts +1 -6
- package/src/tools/python.ts +29 -4
- package/src/tools/read.ts +2 -2
- package/src/tools/write.ts +2 -2
- package/src/tui/output-block.ts +2 -2
- package/src/tui/utils.ts +2 -2
- package/src/utils/ignore-files.ts +119 -0
- package/src/web/search/auth.ts +6 -58
- package/src/web/search/index.ts +2 -6
- package/src/web/search/providers/anthropic.ts +6 -6
- package/src/web/search/providers/exa.ts +2 -62
- package/src/web/search/providers/perplexity.ts +7 -53
- package/examples/sdk/10-settings.ts +0 -37
- package/src/config/settings-manager.ts +0 -2015
|
@@ -3,6 +3,7 @@ import type { OAuthProvider } from "@oh-my-pi/pi-ai";
|
|
|
3
3
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
4
4
|
import { Input, Loader, Spacer, Text } from "@oh-my-pi/pi-tui";
|
|
5
5
|
import { getAgentDbPath } from "../../config";
|
|
6
|
+
import { settings } from "../../config/settings";
|
|
6
7
|
import { DebugSelectorComponent } from "../../debug";
|
|
7
8
|
import { disableProvider, enableProvider } from "../../discovery";
|
|
8
9
|
import { AssistantMessageComponent } from "../../modes/components/assistant-message";
|
|
@@ -51,7 +52,6 @@ export class SelectorController {
|
|
|
51
52
|
getAvailableThemes().then(availableThemes => {
|
|
52
53
|
this.showSelector(done => {
|
|
53
54
|
const selector = new SettingsSelectorComponent(
|
|
54
|
-
this.ctx.settingsManager,
|
|
55
55
|
{
|
|
56
56
|
availableThinkingLevels: this.ctx.session.getAvailableThinkingLevels(),
|
|
57
57
|
thinkingLevel: this.ctx.session.thinkingLevel,
|
|
@@ -68,10 +68,16 @@ export class SelectorController {
|
|
|
68
68
|
}
|
|
69
69
|
});
|
|
70
70
|
},
|
|
71
|
-
onStatusLinePreview:
|
|
71
|
+
onStatusLinePreview: previewSettings => {
|
|
72
72
|
// Update status line with preview settings
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
this.ctx.statusLine.updateSettings({
|
|
74
|
+
preset: settings.get("statusLine.preset"),
|
|
75
|
+
leftSegments: settings.get("statusLine.leftSegments"),
|
|
76
|
+
rightSegments: settings.get("statusLine.rightSegments"),
|
|
77
|
+
separator: settings.get("statusLine.separator"),
|
|
78
|
+
showHookStatus: settings.get("statusLine.showHookStatus"),
|
|
79
|
+
...previewSettings,
|
|
80
|
+
});
|
|
75
81
|
this.ctx.updateEditorTopBorder();
|
|
76
82
|
this.ctx.ui.requestRender();
|
|
77
83
|
},
|
|
@@ -86,7 +92,13 @@ export class SelectorController {
|
|
|
86
92
|
onCancel: () => {
|
|
87
93
|
done();
|
|
88
94
|
// Restore status line to saved settings
|
|
89
|
-
this.ctx.statusLine.updateSettings(
|
|
95
|
+
this.ctx.statusLine.updateSettings({
|
|
96
|
+
preset: settings.get("statusLine.preset"),
|
|
97
|
+
leftSegments: settings.get("statusLine.leftSegments"),
|
|
98
|
+
rightSegments: settings.get("statusLine.rightSegments"),
|
|
99
|
+
separator: settings.get("statusLine.separator"),
|
|
100
|
+
showHookStatus: settings.get("statusLine.showHookStatus"),
|
|
101
|
+
});
|
|
90
102
|
this.ctx.updateEditorTopBorder();
|
|
91
103
|
this.ctx.ui.requestRender();
|
|
92
104
|
},
|
|
@@ -123,11 +135,7 @@ export class SelectorController {
|
|
|
123
135
|
* Replaces /status with a unified view of all providers and extensions.
|
|
124
136
|
*/
|
|
125
137
|
async showExtensionsDashboard(): Promise<void> {
|
|
126
|
-
const dashboard = await ExtensionDashboard.create(
|
|
127
|
-
process.cwd(),
|
|
128
|
-
this.ctx.settingsManager,
|
|
129
|
-
this.ctx.ui.terminal.rows,
|
|
130
|
-
);
|
|
138
|
+
const dashboard = await ExtensionDashboard.create(process.cwd(), this.ctx.settings, this.ctx.ui.terminal.rows);
|
|
131
139
|
this.showSelector(done => {
|
|
132
140
|
dashboard.onClose = () => {
|
|
133
141
|
done();
|
|
@@ -142,7 +150,7 @@ export class SelectorController {
|
|
|
142
150
|
* Most settings are saved directly via SettingsManager in the definitions.
|
|
143
151
|
* This handles side effects and session-specific settings.
|
|
144
152
|
*/
|
|
145
|
-
handleSettingChange(id: string, value:
|
|
153
|
+
handleSettingChange(id: string, value: unknown): void {
|
|
146
154
|
// Discovery provider toggles
|
|
147
155
|
if (id.startsWith("discovery.")) {
|
|
148
156
|
const providerId = id.replace("discovery.", "");
|
|
@@ -232,7 +240,15 @@ export class SelectorController {
|
|
|
232
240
|
case "statusLineGitShowUntracked":
|
|
233
241
|
case "statusLineTimeFormat":
|
|
234
242
|
case "statusLineTimeShowSeconds": {
|
|
235
|
-
|
|
243
|
+
const statusLineSettings = {
|
|
244
|
+
preset: settings.get("statusLine.preset"),
|
|
245
|
+
leftSegments: settings.get("statusLine.leftSegments"),
|
|
246
|
+
rightSegments: settings.get("statusLine.rightSegments"),
|
|
247
|
+
separator: settings.get("statusLine.separator"),
|
|
248
|
+
showHookStatus: settings.get("statusLine.showHookStatus"),
|
|
249
|
+
segmentOptions: settings.get("statusLine.segmentOptions"),
|
|
250
|
+
};
|
|
251
|
+
this.ctx.statusLine.updateSettings(statusLineSettings);
|
|
236
252
|
this.ctx.updateEditorTopBorder();
|
|
237
253
|
this.ctx.ui.requestRender();
|
|
238
254
|
break;
|
|
@@ -256,7 +272,7 @@ export class SelectorController {
|
|
|
256
272
|
const selector = new ModelSelectorComponent(
|
|
257
273
|
this.ctx.ui,
|
|
258
274
|
this.ctx.session.model,
|
|
259
|
-
this.ctx.
|
|
275
|
+
this.ctx.settings,
|
|
260
276
|
this.ctx.session.modelRegistry,
|
|
261
277
|
this.ctx.session.scopedModels,
|
|
262
278
|
async (model, role) => {
|
|
@@ -369,7 +385,7 @@ export class SelectorController {
|
|
|
369
385
|
let wantsSummary = false;
|
|
370
386
|
let customInstructions: string | undefined;
|
|
371
387
|
|
|
372
|
-
const branchSummariesEnabled =
|
|
388
|
+
const branchSummariesEnabled = settings.get("branchSummary.enabled");
|
|
373
389
|
|
|
374
390
|
while (branchSummariesEnabled) {
|
|
375
391
|
const summaryChoice = await this.ctx.showHookSelector("Summarize branch?", [
|
|
@@ -19,7 +19,7 @@ import { isEnoent, logger, postmortem } from "@oh-my-pi/pi-utils";
|
|
|
19
19
|
import chalk from "chalk";
|
|
20
20
|
import { KeybindingsManager } from "../config/keybindings";
|
|
21
21
|
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
22
|
-
import type
|
|
22
|
+
import { type Settings, settings } from "../config/settings";
|
|
23
23
|
import type { ExtensionUIContext, ExtensionUIDialogOptions } from "../extensibility/extensions";
|
|
24
24
|
import type { CompactOptions } from "../extensibility/extensions/types";
|
|
25
25
|
import { loadSlashCommands } from "../extensibility/slash-commands";
|
|
@@ -72,7 +72,7 @@ export interface InteractiveModeOptions {
|
|
|
72
72
|
export class InteractiveMode implements InteractiveModeContext {
|
|
73
73
|
public session: AgentSession;
|
|
74
74
|
public sessionManager: SessionManager;
|
|
75
|
-
public
|
|
75
|
+
public settings: Settings;
|
|
76
76
|
public keybindings: KeybindingsManager;
|
|
77
77
|
public agent: AgentSession["agent"];
|
|
78
78
|
public historyStorage?: HistoryStorage;
|
|
@@ -159,7 +159,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
159
159
|
) {
|
|
160
160
|
this.session = session;
|
|
161
161
|
this.sessionManager = session.sessionManager;
|
|
162
|
-
this.
|
|
162
|
+
this.settings = session.settings;
|
|
163
163
|
this.keybindings = KeybindingsManager.inMemory();
|
|
164
164
|
this.agent = session.agent;
|
|
165
165
|
this.version = version;
|
|
@@ -168,7 +168,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
168
168
|
this.lspServers = lspServers;
|
|
169
169
|
this.mcpManager = mcpManager;
|
|
170
170
|
|
|
171
|
-
this.ui = new TUI(new ProcessTerminal(),
|
|
171
|
+
this.ui = new TUI(new ProcessTerminal(), settings.get("showHardwareCursor"));
|
|
172
172
|
setMermaidRenderCallback(() => this.ui.requestRender());
|
|
173
173
|
this.chatContainer = new Container();
|
|
174
174
|
this.pendingMessagesContainer = new Container();
|
|
@@ -193,7 +193,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
193
193
|
this.statusLine = new StatusLineComponent(session);
|
|
194
194
|
this.statusLine.setAutoCompactEnabled(session.autoCompactionEnabled);
|
|
195
195
|
|
|
196
|
-
this.hideThinkingBlock =
|
|
196
|
+
this.hideThinkingBlock = settings.get("hideThinkingBlock");
|
|
197
197
|
|
|
198
198
|
// Define slash commands for autocomplete
|
|
199
199
|
const slashCommands: SlashCommand[] = [
|
|
@@ -240,7 +240,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
240
240
|
|
|
241
241
|
// Build skill commands from session.skills (if enabled)
|
|
242
242
|
const skillCommandList: SlashCommand[] = [];
|
|
243
|
-
if (
|
|
243
|
+
if (settings.get("skills.enableSkillCommands")) {
|
|
244
244
|
for (const skill of this.session.skills) {
|
|
245
245
|
const commandName = `skill:${skill.name}`;
|
|
246
246
|
this.skillCommands.set(commandName, skill.filePath);
|
|
@@ -300,7 +300,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
300
300
|
fileTypes: s.fileTypes,
|
|
301
301
|
})) ?? [];
|
|
302
302
|
|
|
303
|
-
const startupQuiet =
|
|
303
|
+
const startupQuiet = settings.get("startup.quiet");
|
|
304
304
|
|
|
305
305
|
if (!startupQuiet) {
|
|
306
306
|
// Add welcome header
|
|
@@ -314,7 +314,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
314
314
|
// Add changelog if provided
|
|
315
315
|
if (this.changelogMarkdown) {
|
|
316
316
|
this.ui.addChild(new DynamicBorder());
|
|
317
|
-
if (
|
|
317
|
+
if (settings.get("collapseChangelog")) {
|
|
318
318
|
const versionMatch = this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/);
|
|
319
319
|
const latestVersion = versionMatch ? versionMatch[1] : this.version;
|
|
320
320
|
const condensedText = `Updated to v${latestVersion}. Use ${theme.bold("/changelog")} to view full changelog.`;
|
|
@@ -330,7 +330,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
// Set terminal title if session already has one (resumed session)
|
|
333
|
-
const existingTitle = this.sessionManager.
|
|
333
|
+
const existingTitle = this.sessionManager.getSessionName();
|
|
334
334
|
if (existingTitle) {
|
|
335
335
|
setTerminalTitle(`pi: ${existingTitle}`);
|
|
336
336
|
}
|
|
@@ -494,7 +494,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
494
494
|
private resolvePlanFilePath(planFilePath: string): string {
|
|
495
495
|
if (planFilePath.startsWith("plan://")) {
|
|
496
496
|
return resolvePlanUrlToPath(planFilePath, {
|
|
497
|
-
getPlansDirectory: this.
|
|
497
|
+
getPlansDirectory: () => this.settings.getPlansDirectory(),
|
|
498
498
|
cwd: this.sessionManager.getCwd(),
|
|
499
499
|
});
|
|
500
500
|
}
|
|
@@ -448,6 +448,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
448
448
|
interruptMode: session.interruptMode,
|
|
449
449
|
sessionFile: session.sessionFile,
|
|
450
450
|
sessionId: session.sessionId,
|
|
451
|
+
sessionName: session.sessionName,
|
|
451
452
|
autoCompactionEnabled: session.autoCompactionEnabled,
|
|
452
453
|
messageCount: session.messages.length,
|
|
453
454
|
queuedMessageCount: session.queuedMessageCount,
|
|
@@ -594,6 +595,15 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
594
595
|
return success(id, "get_last_assistant_text", { text });
|
|
595
596
|
}
|
|
596
597
|
|
|
598
|
+
case "set_session_name": {
|
|
599
|
+
const name = command.name.trim();
|
|
600
|
+
if (!name) {
|
|
601
|
+
return error(id, "set_session_name", "Session name cannot be empty");
|
|
602
|
+
}
|
|
603
|
+
session.setSessionName(name);
|
|
604
|
+
return success(id, "set_session_name");
|
|
605
|
+
}
|
|
606
|
+
|
|
597
607
|
// =================================================================
|
|
598
608
|
// Messages
|
|
599
609
|
// =================================================================
|
|
@@ -58,6 +58,7 @@ export type RpcCommand =
|
|
|
58
58
|
| { id?: string; type: "branch"; entryId: string }
|
|
59
59
|
| { id?: string; type: "get_branch_messages" }
|
|
60
60
|
| { id?: string; type: "get_last_assistant_text" }
|
|
61
|
+
| { id?: string; type: "set_session_name"; name: string }
|
|
61
62
|
|
|
62
63
|
// Messages
|
|
63
64
|
| { id?: string; type: "get_messages" };
|
|
@@ -76,6 +77,7 @@ export interface RpcSessionState {
|
|
|
76
77
|
interruptMode: "immediate" | "wait";
|
|
77
78
|
sessionFile?: string;
|
|
78
79
|
sessionId: string;
|
|
80
|
+
sessionName?: string;
|
|
79
81
|
autoCompactionEnabled: boolean;
|
|
80
82
|
messageCount: number;
|
|
81
83
|
queuedMessageCount: number;
|
|
@@ -166,6 +168,7 @@ export type RpcResponse =
|
|
|
166
168
|
success: true;
|
|
167
169
|
data: { text: string | null };
|
|
168
170
|
}
|
|
171
|
+
| { id?: string; type: "response"; command: "set_session_name"; success: true }
|
|
169
172
|
|
|
170
173
|
// Messages
|
|
171
174
|
| { id?: string; type: "response"; command: "get_messages"; success: true; data: { messages: AgentMessage[] } }
|
package/src/modes/types.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
|
2
2
|
import type { AssistantMessage, ImageContent, Message, UsageReport } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import type { Component, Container, Loader, Spacer, Text, TUI } from "@oh-my-pi/pi-tui";
|
|
4
4
|
import type { KeybindingsManager } from "../config/keybindings";
|
|
5
|
-
import type {
|
|
5
|
+
import type { Settings } from "../config/settings";
|
|
6
6
|
import type { ExtensionUIContext, ExtensionUIDialogOptions } from "../extensibility/extensions";
|
|
7
7
|
import type { CompactOptions } from "../extensibility/extensions/types";
|
|
8
8
|
import type { MCPManager } from "../mcp";
|
|
@@ -46,7 +46,7 @@ export interface InteractiveModeContext {
|
|
|
46
46
|
// Session access
|
|
47
47
|
session: AgentSession;
|
|
48
48
|
sessionManager: SessionManager;
|
|
49
|
-
|
|
49
|
+
settings: Settings;
|
|
50
50
|
keybindings: KeybindingsManager;
|
|
51
51
|
agent: AgentSession["agent"];
|
|
52
52
|
historyStorage?: HistoryStorage;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import type { AssistantMessage, Message } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import { Spacer, Text, TruncatedText } from "@oh-my-pi/pi-tui";
|
|
4
|
+
import { settings } from "../../config/settings";
|
|
4
5
|
import { AssistantMessageComponent } from "../../modes/components/assistant-message";
|
|
5
6
|
import { BashExecutionComponent } from "../../modes/components/bash-execution";
|
|
6
7
|
import { BranchSummaryMessageComponent } from "../../modes/components/branch-summary-message";
|
|
@@ -224,9 +225,9 @@ export class UiHelpers {
|
|
|
224
225
|
content.name,
|
|
225
226
|
content.arguments,
|
|
226
227
|
{
|
|
227
|
-
showImages:
|
|
228
|
-
editFuzzyThreshold:
|
|
229
|
-
editAllowFuzzy:
|
|
228
|
+
showImages: settings.get("terminal.showImages"),
|
|
229
|
+
editFuzzyThreshold: settings.get("edit.fuzzyThreshold"),
|
|
230
|
+
editAllowFuzzy: settings.get("edit.fuzzyMatch"),
|
|
230
231
|
},
|
|
231
232
|
tool,
|
|
232
233
|
this.ctx.ui,
|
package/src/patch/index.ts
CHANGED
|
@@ -26,7 +26,7 @@ import { outputMeta } from "../tools/output-meta";
|
|
|
26
26
|
import { enforcePlanModeWrite, resolvePlanPath } from "../tools/plan-mode-guard";
|
|
27
27
|
import { applyPatch } from "./applicator";
|
|
28
28
|
import { generateDiffString, generateUnifiedDiffString, replaceText } from "./diff";
|
|
29
|
-
import {
|
|
29
|
+
import { findMatch } from "./fuzzy";
|
|
30
30
|
import { detectLineEnding, normalizeToLF, restoreLineEndings, stripBom } from "./normalize";
|
|
31
31
|
import { buildNormativeUpdateInput } from "./normative";
|
|
32
32
|
import { type EditToolDetails, getLspBatchRequest } from "./shared";
|
|
@@ -233,14 +233,14 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
233
233
|
this.allowFuzzy = false;
|
|
234
234
|
break;
|
|
235
235
|
case "auto":
|
|
236
|
-
this.allowFuzzy = session.settings
|
|
236
|
+
this.allowFuzzy = session.settings.get("edit.fuzzyMatch");
|
|
237
237
|
break;
|
|
238
238
|
default:
|
|
239
239
|
throw new Error(`Invalid OMP_EDIT_FUZZY: ${editFuzzy}`);
|
|
240
240
|
}
|
|
241
241
|
switch (editFuzzyThreshold) {
|
|
242
242
|
case "auto":
|
|
243
|
-
this.fuzzyThreshold = session.settings
|
|
243
|
+
this.fuzzyThreshold = session.settings.get("edit.fuzzyThreshold");
|
|
244
244
|
break;
|
|
245
245
|
default:
|
|
246
246
|
this.fuzzyThreshold = parseFloat(editFuzzyThreshold);
|
|
@@ -251,8 +251,8 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
const enableLsp = session.enableLsp ?? true;
|
|
254
|
-
const enableDiagnostics = enableLsp
|
|
255
|
-
const enableFormat = enableLsp
|
|
254
|
+
const enableDiagnostics = enableLsp && session.settings.get("lsp.diagnosticsOnEdit");
|
|
255
|
+
const enableFormat = enableLsp && session.settings.get("lsp.formatOnWrite");
|
|
256
256
|
this.writethrough = enableLsp
|
|
257
257
|
? createLspWritethrough(session.cwd, { enableFormat, enableDiagnostics })
|
|
258
258
|
: writethroughNoop;
|
|
@@ -268,11 +268,11 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
268
268
|
|
|
269
269
|
// Auto mode: check model-specific settings
|
|
270
270
|
const activeModel = this.session.getActiveModelString?.();
|
|
271
|
-
const modelVariant = this.session.settings
|
|
271
|
+
const modelVariant = this.session.settings.getEditVariantForModel(activeModel);
|
|
272
272
|
if (modelVariant === "replace") return false;
|
|
273
273
|
if (modelVariant === "patch") return true;
|
|
274
274
|
|
|
275
|
-
return this.session.settings
|
|
275
|
+
return this.session.settings.get("edit.patchMode");
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
/**
|
package/src/patch/normalize.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Handles line endings, BOM, whitespace, and Unicode normalization.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { padding } from "@oh-my-pi/pi-tui";
|
|
8
|
+
|
|
7
9
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
8
10
|
// Line Ending Utilities
|
|
9
11
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -194,7 +196,7 @@ export function convertLeadingTabsToSpaces(text: string, spacesPerTab: number):
|
|
|
194
196
|
if (trimmed.length === 0) return line;
|
|
195
197
|
const leading = getLeadingWhitespace(line);
|
|
196
198
|
if (!leading.includes("\t") || leading.includes(" ")) return line;
|
|
197
|
-
const converted =
|
|
199
|
+
const converted = padding(leading.length * spacesPerTab);
|
|
198
200
|
return converted + trimmed;
|
|
199
201
|
})
|
|
200
202
|
.join("\n");
|
|
@@ -18,6 +18,7 @@ Create your plan at `{{planFilePath}}`.
|
|
|
18
18
|
{{/if}}
|
|
19
19
|
|
|
20
20
|
The plan file is the ONLY file you may write or edit.
|
|
21
|
+
Use `{{editToolName}}` for incremental updates; use `{{writeToolName}}` only when creating or fully replacing the plan.
|
|
21
22
|
|
|
22
23
|
<important>
|
|
23
24
|
Plan execution runs in a fresh context (session cleared). Make the plan file self-contained: include any requirements, decisions, key findings, and remaining todos needed to continue without prior session history.
|
|
@@ -55,8 +56,8 @@ Use `ask` to clarify:
|
|
|
55
56
|
- Preferences for UI/UX, performance, edge cases
|
|
56
57
|
|
|
57
58
|
Batch questions. Do not ask what you can answer by exploring.
|
|
58
|
-
### 3.
|
|
59
|
-
|
|
59
|
+
### 3. Update Incrementally
|
|
60
|
+
Use `{{editToolName}}` to update the plan file as you learn. Do not wait until the end.
|
|
60
61
|
### 4. Calibrate
|
|
61
62
|
- Large unspecified task → multiple interview rounds
|
|
62
63
|
- Smaller task → fewer or no questions
|
|
@@ -86,8 +87,8 @@ Draft approach based on exploration. Consider trade-offs briefly, then choose.
|
|
|
86
87
|
### Phase 3: Review
|
|
87
88
|
Read critical files. Verify plan matches original request. Use `ask` to clarify remaining questions.
|
|
88
89
|
|
|
89
|
-
### Phase 4:
|
|
90
|
-
|
|
90
|
+
### Phase 4: Update Plan
|
|
91
|
+
Update `{{planFilePath}}` (use `{{editToolName}}` for changes, `{{writeToolName}}` only if creating from scratch):
|
|
91
92
|
- Recommended approach only
|
|
92
93
|
- Paths of critical files to modify
|
|
93
94
|
- Verification section
|
|
@@ -330,7 +330,6 @@ Write what you can defend.
|
|
|
330
330
|
{{#if isCoordinator}}
|
|
331
331
|
{{#has tools "task"}}
|
|
332
332
|
<critical id="coordinator">
|
|
333
|
-
As the coordinator, **ALWAYS prefer** delegation via Task tool for all SUBSTANTIAL work.
|
|
334
333
|
Your context window is limited—especially the output. Work in discrete steps and run each step using Task tool. Avoid putting substantial work in the main context when possible. Run multiple tasks in parallel whenever possible.
|
|
335
334
|
|
|
336
335
|
## Triggers requiring Task tool
|
|
@@ -12,7 +12,7 @@ Executes a bash command in a shell session for terminal operations like git, bun
|
|
|
12
12
|
|
|
13
13
|
<output>
|
|
14
14
|
Returns stdout, stderr, and exit code from command execution.
|
|
15
|
-
- Output truncated after 50KB or 2000 lines (whichever comes first); use
|
|
15
|
+
- Output truncated after 50KB or 2000 lines (whichever comes first); use `head` parameter to limit output
|
|
16
16
|
- If output is truncated, full output is stored under $ARTIFACTS and referenced as `artifact://<id>` in metadata
|
|
17
17
|
- Exit codes shown on non-zero exit; stderr captured
|
|
18
18
|
</output>
|
|
@@ -24,4 +24,14 @@ Do NOT use Bash for these operations—specialized tools exist:
|
|
|
24
24
|
- Finding files by pattern → Find tool
|
|
25
25
|
- Content-addressed edits → Edit tool
|
|
26
26
|
- Writing new files → Write tool
|
|
27
|
-
</critical>
|
|
27
|
+
</critical>
|
|
28
|
+
|
|
29
|
+
<avoid>
|
|
30
|
+
Do NOT pipe through `head` or `tail`—use the `head` and `tail` parameters instead:
|
|
31
|
+
- `command | head -n 50` → use `head: 50` parameter
|
|
32
|
+
- `command | tail -n 100` → use `tail: 100` parameter
|
|
33
|
+
|
|
34
|
+
The pipe pattern breaks streaming output and prevents artifact storage.
|
|
35
|
+
|
|
36
|
+
Do NOT use `2>&1`—stdout and stderr are already merged.
|
|
37
|
+
</avoid>
|