@oh-my-pi/pi-coding-agent 8.0.20 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +105 -0
- package/package.json +14 -11
- package/scripts/generate-wasm-b64.ts +24 -0
- package/src/capability/context-file.ts +1 -1
- package/src/capability/extension-module.ts +1 -1
- package/src/capability/extension.ts +1 -1
- package/src/capability/hook.ts +1 -1
- package/src/capability/instruction.ts +1 -1
- package/src/capability/mcp.ts +1 -1
- package/src/capability/prompt.ts +1 -1
- package/src/capability/rule.ts +1 -1
- package/src/capability/settings.ts +1 -1
- package/src/capability/skill.ts +1 -1
- package/src/capability/slash-command.ts +1 -1
- package/src/capability/ssh.ts +1 -1
- package/src/capability/system-prompt.ts +1 -1
- package/src/capability/tool.ts +1 -1
- package/src/cli/args.ts +1 -1
- package/src/cli/plugin-cli.ts +1 -5
- package/src/commit/agentic/agent.ts +309 -0
- package/src/commit/agentic/fallback.ts +96 -0
- package/src/commit/agentic/index.ts +359 -0
- package/src/commit/agentic/prompts/analyze-file.md +22 -0
- package/src/commit/agentic/prompts/session-user.md +26 -0
- package/src/commit/agentic/prompts/split-confirm.md +1 -0
- package/src/commit/agentic/prompts/system.md +40 -0
- package/src/commit/agentic/state.ts +74 -0
- package/src/commit/agentic/tools/analyze-file.ts +131 -0
- package/src/commit/agentic/tools/git-file-diff.ts +194 -0
- package/src/commit/agentic/tools/git-hunk.ts +50 -0
- package/src/commit/agentic/tools/git-overview.ts +84 -0
- package/src/commit/agentic/tools/index.ts +56 -0
- package/src/commit/agentic/tools/propose-changelog.ts +128 -0
- package/src/commit/agentic/tools/propose-commit.ts +154 -0
- package/src/commit/agentic/tools/recent-commits.ts +81 -0
- package/src/commit/agentic/tools/split-commit.ts +284 -0
- package/src/commit/agentic/topo-sort.ts +44 -0
- package/src/commit/agentic/trivial.ts +51 -0
- package/src/commit/agentic/validation.ts +200 -0
- package/src/commit/analysis/conventional.ts +169 -0
- package/src/commit/analysis/index.ts +4 -0
- package/src/commit/analysis/scope.ts +242 -0
- package/src/commit/analysis/summary.ts +114 -0
- package/src/commit/analysis/validation.ts +66 -0
- package/src/commit/changelog/detect.ts +36 -0
- package/src/commit/changelog/generate.ts +112 -0
- package/src/commit/changelog/index.ts +233 -0
- package/src/commit/changelog/parse.ts +44 -0
- package/src/commit/cli.ts +93 -0
- package/src/commit/git/diff.ts +148 -0
- package/src/commit/git/errors.ts +11 -0
- package/src/commit/git/index.ts +217 -0
- package/src/commit/git/operations.ts +53 -0
- package/src/commit/index.ts +5 -0
- package/src/commit/map-reduce/.map-phase.ts.kate-swp +0 -0
- package/src/commit/map-reduce/index.ts +63 -0
- package/src/commit/map-reduce/map-phase.ts +193 -0
- package/src/commit/map-reduce/reduce-phase.ts +147 -0
- package/src/commit/map-reduce/utils.ts +9 -0
- package/src/commit/message.ts +11 -0
- package/src/commit/model-selection.ts +84 -0
- package/src/commit/pipeline.ts +242 -0
- package/src/commit/prompts/analysis-system.md +155 -0
- package/src/commit/prompts/analysis-user.md +41 -0
- package/src/commit/prompts/changelog-system.md +56 -0
- package/src/commit/prompts/changelog-user.md +19 -0
- package/src/commit/prompts/file-observer-system.md +26 -0
- package/src/commit/prompts/file-observer-user.md +9 -0
- package/src/commit/prompts/reduce-system.md +60 -0
- package/src/commit/prompts/reduce-user.md +17 -0
- package/src/commit/prompts/summary-retry.md +4 -0
- package/src/commit/prompts/summary-system.md +52 -0
- package/src/commit/prompts/summary-user.md +13 -0
- package/src/commit/prompts/types-description.md +2 -0
- package/src/commit/types.ts +109 -0
- package/src/commit/utils/exclusions.ts +42 -0
- package/src/config/file-lock.ts +111 -0
- package/src/config/model-registry.ts +16 -7
- package/src/config/settings-manager.ts +115 -40
- package/src/config.ts +5 -5
- package/src/discovery/agents-md.ts +1 -1
- package/src/discovery/builtin.ts +1 -1
- package/src/discovery/claude.ts +1 -1
- package/src/discovery/cline.ts +1 -1
- package/src/discovery/codex.ts +1 -1
- package/src/discovery/cursor.ts +1 -1
- package/src/discovery/gemini.ts +1 -1
- package/src/discovery/github.ts +1 -1
- package/src/discovery/index.ts +11 -11
- package/src/discovery/mcp-json.ts +1 -1
- package/src/discovery/ssh.ts +1 -1
- package/src/discovery/vscode.ts +1 -1
- package/src/discovery/windsurf.ts +1 -1
- package/src/extensibility/custom-commands/loader.ts +1 -1
- package/src/extensibility/custom-commands/types.ts +1 -1
- package/src/extensibility/custom-tools/loader.ts +1 -1
- package/src/extensibility/custom-tools/types.ts +1 -1
- package/src/extensibility/extensions/loader.ts +1 -1
- package/src/extensibility/extensions/types.ts +1 -1
- package/src/extensibility/hooks/loader.ts +1 -1
- package/src/extensibility/hooks/types.ts +3 -3
- package/src/index.ts +10 -10
- package/src/ipy/executor.ts +97 -1
- package/src/lsp/index.ts +1 -1
- package/src/lsp/render.ts +90 -46
- package/src/main.ts +16 -3
- package/src/mcp/loader.ts +3 -3
- package/src/migrations.ts +3 -3
- package/src/modes/components/assistant-message.ts +29 -1
- package/src/modes/components/tool-execution.ts +5 -3
- package/src/modes/components/tree-selector.ts +1 -1
- package/src/modes/controllers/extension-ui-controller.ts +1 -1
- package/src/modes/controllers/selector-controller.ts +1 -1
- package/src/modes/interactive-mode.ts +5 -3
- package/src/modes/rpc/rpc-client.ts +1 -1
- package/src/modes/rpc/rpc-mode.ts +1 -4
- package/src/modes/rpc/rpc-types.ts +1 -1
- package/src/modes/theme/mermaid-cache.ts +89 -0
- package/src/modes/theme/theme.ts +2 -0
- package/src/modes/types.ts +2 -2
- package/src/patch/index.ts +3 -9
- package/src/patch/shared.ts +33 -5
- package/src/prompts/tools/task.md +2 -0
- package/src/sdk.ts +60 -22
- package/src/session/agent-session.ts +3 -3
- package/src/session/agent-storage.ts +32 -28
- package/src/session/artifacts.ts +24 -1
- package/src/session/auth-storage.ts +25 -10
- package/src/session/storage-migration.ts +12 -53
- package/src/system-prompt.ts +2 -2
- package/src/task/.executor.ts.kate-swp +0 -0
- package/src/task/executor.ts +1 -1
- package/src/task/index.ts +10 -1
- package/src/task/output-manager.ts +94 -0
- package/src/task/render.ts +7 -12
- package/src/task/worker.ts +1 -1
- package/src/tools/ask.ts +35 -13
- package/src/tools/bash.ts +80 -87
- package/src/tools/calculator.ts +42 -40
- package/src/tools/complete.ts +1 -1
- package/src/tools/fetch.ts +67 -104
- package/src/tools/find.ts +83 -86
- package/src/tools/grep.ts +80 -96
- package/src/tools/index.ts +10 -7
- package/src/tools/ls.ts +39 -65
- package/src/tools/notebook.ts +48 -64
- package/src/tools/output-utils.ts +1 -1
- package/src/tools/python.ts +71 -183
- package/src/tools/read.ts +74 -15
- package/src/tools/render-utils.ts +1 -15
- package/src/tools/ssh.ts +43 -24
- package/src/tools/todo-write.ts +27 -15
- package/src/tools/write.ts +93 -64
- package/src/tui/code-cell.ts +115 -0
- package/src/tui/file-list.ts +48 -0
- package/src/tui/index.ts +11 -0
- package/src/tui/output-block.ts +73 -0
- package/src/tui/status-line.ts +40 -0
- package/src/tui/tree-list.ts +56 -0
- package/src/tui/types.ts +17 -0
- package/src/tui/utils.ts +49 -0
- package/src/vendor/photon/photon_rs_bg.wasm.b64.js +1 -0
- package/src/web/search/auth.ts +1 -1
- package/src/web/search/index.ts +1 -1
- package/src/web/search/render.ts +119 -163
- package/tsconfig.json +0 -42
|
@@ -379,12 +379,14 @@ export class ToolExecutionComponent extends Container {
|
|
|
379
379
|
// Check for custom tool rendering
|
|
380
380
|
if (this.tool && (this.tool.renderCall || this.tool.renderResult)) {
|
|
381
381
|
const tool = this.tool;
|
|
382
|
+
const mergeCallAndResult = Boolean((tool as { mergeCallAndResult?: boolean }).mergeCallAndResult);
|
|
382
383
|
// Custom tools use Box for flexible component rendering
|
|
383
384
|
this.contentBox.setBgFn(bgFn);
|
|
384
385
|
this.contentBox.clear();
|
|
385
386
|
|
|
386
387
|
// Render call component
|
|
387
|
-
|
|
388
|
+
const shouldRenderCall = !this.result || !mergeCallAndResult;
|
|
389
|
+
if (shouldRenderCall && tool.renderCall) {
|
|
388
390
|
try {
|
|
389
391
|
const callComponent = tool.renderCall(this.args, theme);
|
|
390
392
|
if (callComponent) {
|
|
@@ -552,13 +554,13 @@ export class ToolExecutionComponent extends Container {
|
|
|
552
554
|
|
|
553
555
|
if (this.toolName === "bash" && this.result) {
|
|
554
556
|
// Pass raw output and expanded state - renderer handles width-aware truncation
|
|
555
|
-
const output = this.getTextOutput().
|
|
557
|
+
const output = this.getTextOutput().trimEnd();
|
|
556
558
|
context.output = output;
|
|
557
559
|
context.expanded = this.expanded;
|
|
558
560
|
context.previewLines = BASH_DEFAULT_PREVIEW_LINES;
|
|
559
561
|
context.timeout = typeof this.args?.timeout === "number" ? this.args.timeout : undefined;
|
|
560
562
|
} else if (this.toolName === "python" && this.result) {
|
|
561
|
-
const output = this.getTextOutput().
|
|
563
|
+
const output = this.getTextOutput().trimEnd();
|
|
562
564
|
context.output = output;
|
|
563
565
|
context.expanded = this.expanded;
|
|
564
566
|
context.previewLines = PYTHON_DEFAULT_PREVIEW_LINES;
|
|
@@ -821,7 +821,7 @@ export class TreeSelectorComponent extends Container {
|
|
|
821
821
|
new TruncatedText(
|
|
822
822
|
theme.fg(
|
|
823
823
|
"muted",
|
|
824
|
-
"
|
|
824
|
+
"Up/Down: move. Left/Right: page. Shift+L: label. Ctrl+O/Shift+Ctrl+O: filter. Alt+D/T/U/L/A: filter. Type to search",
|
|
825
825
|
),
|
|
826
826
|
0,
|
|
827
827
|
0,
|
|
@@ -5,7 +5,7 @@ import type {
|
|
|
5
5
|
ExtensionContextActions,
|
|
6
6
|
ExtensionError,
|
|
7
7
|
ExtensionUIContext,
|
|
8
|
-
} from "@oh-my-pi/pi-coding-agent/extensibility/extensions
|
|
8
|
+
} from "@oh-my-pi/pi-coding-agent/extensibility/extensions";
|
|
9
9
|
import { HookEditorComponent } from "@oh-my-pi/pi-coding-agent/modes/components/hook-editor";
|
|
10
10
|
import { HookInputComponent } from "@oh-my-pi/pi-coding-agent/modes/components/hook-input";
|
|
11
11
|
import { HookSelectorComponent } from "@oh-my-pi/pi-coding-agent/modes/components/hook-selector";
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
} from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
22
22
|
import type { InteractiveModeContext } from "@oh-my-pi/pi-coding-agent/modes/types";
|
|
23
23
|
import { SessionManager } from "@oh-my-pi/pi-coding-agent/session/session-manager";
|
|
24
|
-
import { setPreferredImageProvider, setPreferredWebSearchProvider } from "@oh-my-pi/pi-coding-agent/tools
|
|
24
|
+
import { setPreferredImageProvider, setPreferredWebSearchProvider } from "@oh-my-pi/pi-coding-agent/tools";
|
|
25
25
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
26
26
|
import { Input, Loader, Spacer, Text } from "@oh-my-pi/pi-tui";
|
|
27
27
|
|
|
@@ -8,7 +8,7 @@ import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
|
8
8
|
import type { AssistantMessage, ImageContent, Message, UsageReport } from "@oh-my-pi/pi-ai";
|
|
9
9
|
import { KeybindingsManager } from "@oh-my-pi/pi-coding-agent/config/keybindings";
|
|
10
10
|
import type { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
|
|
11
|
-
import type { ExtensionUIContext } from "@oh-my-pi/pi-coding-agent/extensibility/extensions
|
|
11
|
+
import type { ExtensionUIContext } from "@oh-my-pi/pi-coding-agent/extensibility/extensions";
|
|
12
12
|
import type { CompactOptions } from "@oh-my-pi/pi-coding-agent/extensibility/extensions/types";
|
|
13
13
|
import { loadSlashCommands } from "@oh-my-pi/pi-coding-agent/extensibility/slash-commands";
|
|
14
14
|
import type { AgentSession, AgentSessionEvent } from "@oh-my-pi/pi-coding-agent/session/agent-session";
|
|
@@ -44,6 +44,7 @@ import { EventController } from "./controllers/event-controller";
|
|
|
44
44
|
import { ExtensionUiController } from "./controllers/extension-ui-controller";
|
|
45
45
|
import { InputController } from "./controllers/input-controller";
|
|
46
46
|
import { SelectorController } from "./controllers/selector-controller";
|
|
47
|
+
import { setMermaidRenderCallback } from "./theme/mermaid-cache";
|
|
47
48
|
import type { Theme } from "./theme/theme";
|
|
48
49
|
import { getEditorTheme, getMarkdownTheme, onThemeChange, theme } from "./theme/theme";
|
|
49
50
|
import type { CompactionQueuedMessage, InteractiveModeContext, TodoItem } from "./types";
|
|
@@ -124,7 +125,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
124
125
|
private readonly changelogMarkdown: string | undefined;
|
|
125
126
|
public readonly lspServers: Array<{ name: string; status: "ready" | "error"; fileTypes: string[] }> | undefined =
|
|
126
127
|
undefined;
|
|
127
|
-
public mcpManager?: import("@oh-my-pi/pi-coding-agent/mcp
|
|
128
|
+
public mcpManager?: import("@oh-my-pi/pi-coding-agent/mcp").MCPManager;
|
|
128
129
|
private readonly toolUiContextSetter: (uiContext: ExtensionUIContext, hasUI: boolean) => void;
|
|
129
130
|
|
|
130
131
|
private readonly commandController: CommandController;
|
|
@@ -140,7 +141,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
140
141
|
changelogMarkdown: string | undefined = undefined,
|
|
141
142
|
setToolUIContext: (uiContext: ExtensionUIContext, hasUI: boolean) => void = () => {},
|
|
142
143
|
lspServers: Array<{ name: string; status: "ready" | "error"; fileTypes: string[] }> | undefined = undefined,
|
|
143
|
-
mcpManager?: import("@oh-my-pi/pi-coding-agent/mcp
|
|
144
|
+
mcpManager?: import("@oh-my-pi/pi-coding-agent/mcp").MCPManager,
|
|
144
145
|
) {
|
|
145
146
|
this.session = session;
|
|
146
147
|
this.sessionManager = session.sessionManager;
|
|
@@ -154,6 +155,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
154
155
|
this.mcpManager = mcpManager;
|
|
155
156
|
|
|
156
157
|
this.ui = new TUI(new ProcessTerminal(), this.settingsManager.getShowHardwareCursor());
|
|
158
|
+
setMermaidRenderCallback(() => this.ui.requestRender());
|
|
157
159
|
this.chatContainer = new Container();
|
|
158
160
|
this.pendingMessagesContainer = new Container();
|
|
159
161
|
this.statusContainer = new Container();
|
|
@@ -8,7 +8,7 @@ import type { AgentEvent, AgentMessage, ThinkingLevel } from "@oh-my-pi/pi-agent
|
|
|
8
8
|
import type { ImageContent } from "@oh-my-pi/pi-ai";
|
|
9
9
|
import type { BashResult } from "@oh-my-pi/pi-coding-agent/exec/bash-executor";
|
|
10
10
|
import type { SessionStats } from "@oh-my-pi/pi-coding-agent/session/agent-session";
|
|
11
|
-
import type { CompactionResult } from "@oh-my-pi/pi-coding-agent/session/compaction
|
|
11
|
+
import type { CompactionResult } from "@oh-my-pi/pi-coding-agent/session/compaction";
|
|
12
12
|
import { createSanitizerStream, createSplitterStream, createTextDecoderStream, ptree } from "@oh-my-pi/pi-utils";
|
|
13
13
|
import type { RpcCommand, RpcResponse, RpcSessionState } from "./rpc-types";
|
|
14
14
|
|
|
@@ -11,10 +11,7 @@
|
|
|
11
11
|
* - Extension UI: Extension UI requests are emitted, client responds with extension_ui_response
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import type {
|
|
15
|
-
ExtensionUIContext,
|
|
16
|
-
ExtensionUIDialogOptions,
|
|
17
|
-
} from "@oh-my-pi/pi-coding-agent/extensibility/extensions/index";
|
|
14
|
+
import type { ExtensionUIContext, ExtensionUIDialogOptions } from "@oh-my-pi/pi-coding-agent/extensibility/extensions";
|
|
18
15
|
import { type Theme, theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
19
16
|
import type { AgentSession } from "@oh-my-pi/pi-coding-agent/session/agent-session";
|
|
20
17
|
import { readLines } from "@oh-my-pi/pi-utils";
|
|
@@ -9,7 +9,7 @@ import type { AgentMessage, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
|
9
9
|
import type { ImageContent, Model } from "@oh-my-pi/pi-ai";
|
|
10
10
|
import type { BashResult } from "@oh-my-pi/pi-coding-agent/exec/bash-executor";
|
|
11
11
|
import type { SessionStats } from "@oh-my-pi/pi-coding-agent/session/agent-session";
|
|
12
|
-
import type { CompactionResult } from "@oh-my-pi/pi-coding-agent/session/compaction
|
|
12
|
+
import type { CompactionResult } from "@oh-my-pi/pi-coding-agent/session/compaction";
|
|
13
13
|
|
|
14
14
|
// ============================================================================
|
|
15
15
|
// RPC Commands (stdin)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
extractMermaidBlocks,
|
|
3
|
+
type MermaidImage,
|
|
4
|
+
type MermaidRenderOptions,
|
|
5
|
+
renderMermaidToPng,
|
|
6
|
+
} from "@oh-my-pi/pi-tui";
|
|
7
|
+
|
|
8
|
+
const cache = new Map<string, MermaidImage>();
|
|
9
|
+
const pending = new Map<string, Promise<MermaidImage | null>>();
|
|
10
|
+
|
|
11
|
+
const defaultOptions: MermaidRenderOptions = {
|
|
12
|
+
theme: "dark",
|
|
13
|
+
backgroundColor: "transparent",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
let onRenderNeeded: (() => void) | null = null;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Set callback to trigger TUI re-render when mermaid images become available.
|
|
20
|
+
*/
|
|
21
|
+
export function setMermaidRenderCallback(callback: (() => void) | null): void {
|
|
22
|
+
onRenderNeeded = callback;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get a pre-rendered mermaid image by hash.
|
|
27
|
+
* Returns null if not cached or rendering failed.
|
|
28
|
+
*/
|
|
29
|
+
export function getMermaidImage(hash: string): MermaidImage | null {
|
|
30
|
+
return cache.get(hash) ?? null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Pre-render all mermaid blocks in markdown text.
|
|
35
|
+
* Renders in parallel, deduplicates concurrent requests.
|
|
36
|
+
* Calls render callback when new images are cached.
|
|
37
|
+
*/
|
|
38
|
+
export async function prerenderMermaid(
|
|
39
|
+
markdown: string,
|
|
40
|
+
options: MermaidRenderOptions = defaultOptions,
|
|
41
|
+
): Promise<void> {
|
|
42
|
+
const blocks = extractMermaidBlocks(markdown);
|
|
43
|
+
if (blocks.length === 0) return;
|
|
44
|
+
|
|
45
|
+
const promises: Promise<boolean>[] = [];
|
|
46
|
+
|
|
47
|
+
for (const { source, hash } of blocks) {
|
|
48
|
+
if (cache.has(hash)) continue;
|
|
49
|
+
|
|
50
|
+
let promise = pending.get(hash);
|
|
51
|
+
if (!promise) {
|
|
52
|
+
promise = renderMermaidToPng(source, options);
|
|
53
|
+
pending.set(hash, promise);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
promises.push(
|
|
57
|
+
promise.then((image) => {
|
|
58
|
+
pending.delete(hash);
|
|
59
|
+
if (image) {
|
|
60
|
+
cache.set(hash, image);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const results = await Promise.all(promises);
|
|
69
|
+
const newImages = results.some((added) => added);
|
|
70
|
+
|
|
71
|
+
if (newImages && onRenderNeeded) {
|
|
72
|
+
onRenderNeeded();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Check if markdown contains mermaid blocks that aren't cached yet.
|
|
78
|
+
*/
|
|
79
|
+
export function hasPendingMermaid(markdown: string): boolean {
|
|
80
|
+
const blocks = extractMermaidBlocks(markdown);
|
|
81
|
+
return blocks.some(({ hash }) => !cache.has(hash));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Clear the mermaid cache.
|
|
86
|
+
*/
|
|
87
|
+
export function clearMermaidCache(): void {
|
|
88
|
+
cache.clear();
|
|
89
|
+
}
|
package/src/modes/theme/theme.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { highlight, supportsLanguage } from "cli-highlight";
|
|
|
11
11
|
import darkThemeJson from "./dark.json" with { type: "json" };
|
|
12
12
|
import { defaultThemes } from "./defaults";
|
|
13
13
|
import lightThemeJson from "./light.json" with { type: "json" };
|
|
14
|
+
import { getMermaidImage } from "./mermaid-cache";
|
|
14
15
|
|
|
15
16
|
// ============================================================================
|
|
16
17
|
// Symbol Presets
|
|
@@ -2224,6 +2225,7 @@ export function getMarkdownTheme(): MarkdownTheme {
|
|
|
2224
2225
|
underline: (text: string) => theme.underline(text),
|
|
2225
2226
|
strikethrough: (text: string) => chalk.strikethrough(text),
|
|
2226
2227
|
symbols: getSymbolTheme(),
|
|
2228
|
+
getMermaidImage,
|
|
2227
2229
|
highlightCode: (code: string, lang?: string): string[] => {
|
|
2228
2230
|
// Validate language before highlighting to avoid stderr spam from cli-highlight
|
|
2229
2231
|
const validLang = lang && supportsLanguage(lang) ? lang : undefined;
|
package/src/modes/types.ts
CHANGED
|
@@ -2,9 +2,9 @@ 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 { KeybindingsManager } from "@oh-my-pi/pi-coding-agent/config/keybindings";
|
|
4
4
|
import type { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
|
|
5
|
-
import type { ExtensionUIContext } from "@oh-my-pi/pi-coding-agent/extensibility/extensions
|
|
5
|
+
import type { ExtensionUIContext } from "@oh-my-pi/pi-coding-agent/extensibility/extensions";
|
|
6
6
|
import type { CompactOptions } from "@oh-my-pi/pi-coding-agent/extensibility/extensions/types";
|
|
7
|
-
import type { MCPManager } from "@oh-my-pi/pi-coding-agent/mcp
|
|
7
|
+
import type { MCPManager } from "@oh-my-pi/pi-coding-agent/mcp";
|
|
8
8
|
import type { AgentSession, AgentSessionEvent } from "@oh-my-pi/pi-coding-agent/session/agent-session";
|
|
9
9
|
import type { HistoryStorage } from "@oh-my-pi/pi-coding-agent/session/history-storage";
|
|
10
10
|
import type { SessionContext, SessionManager } from "@oh-my-pi/pi-coding-agent/session/session-manager";
|
package/src/patch/index.ts
CHANGED
|
@@ -18,10 +18,10 @@ import {
|
|
|
18
18
|
flushLspWritethroughBatch,
|
|
19
19
|
type WritethroughCallback,
|
|
20
20
|
writethroughNoop,
|
|
21
|
-
} from "@oh-my-pi/pi-coding-agent/lsp
|
|
21
|
+
} from "@oh-my-pi/pi-coding-agent/lsp";
|
|
22
22
|
import patchDescription from "@oh-my-pi/pi-coding-agent/prompts/tools/patch.md" with { type: "text" };
|
|
23
23
|
import replaceDescription from "@oh-my-pi/pi-coding-agent/prompts/tools/replace.md" with { type: "text" };
|
|
24
|
-
import type { ToolSession } from "@oh-my-pi/pi-coding-agent/tools
|
|
24
|
+
import type { ToolSession } from "@oh-my-pi/pi-coding-agent/tools";
|
|
25
25
|
import { outputMeta } from "@oh-my-pi/pi-coding-agent/tools/output-meta";
|
|
26
26
|
import { resolveToCwd } from "@oh-my-pi/pi-coding-agent/tools/path-utils";
|
|
27
27
|
import { Type } from "@sinclair/typebox";
|
|
@@ -48,13 +48,7 @@ export { computeEditDiff, computePatchDiff, generateDiffString, generateUnifiedD
|
|
|
48
48
|
export { DEFAULT_FUZZY_THRESHOLD, findContextLine, findMatch as findEditMatch, findMatch, seekSequence } from "./fuzzy";
|
|
49
49
|
|
|
50
50
|
// Normalization
|
|
51
|
-
export {
|
|
52
|
-
adjustIndentation,
|
|
53
|
-
detectLineEnding,
|
|
54
|
-
normalizeToLF,
|
|
55
|
-
restoreLineEndings,
|
|
56
|
-
stripBom,
|
|
57
|
-
} from "./normalize";
|
|
51
|
+
export { adjustIndentation, detectLineEnding, normalizeToLF, restoreLineEndings, stripBom } from "./normalize";
|
|
58
52
|
|
|
59
53
|
// Parsing
|
|
60
54
|
export { normalizeCreateContent, normalizeDiff, parseHunks as parseDiffHunks } from "./parser";
|
package/src/patch/shared.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import type { ToolCallContext } from "@oh-my-pi/pi-agent-core";
|
|
6
6
|
import type { RenderResultOptions } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
|
|
7
|
-
import type { FileDiagnosticsResult } from "@oh-my-pi/pi-coding-agent/lsp
|
|
7
|
+
import type { FileDiagnosticsResult } from "@oh-my-pi/pi-coding-agent/lsp";
|
|
8
8
|
import { renderDiff as renderDiffColored } from "@oh-my-pi/pi-coding-agent/modes/components/diff";
|
|
9
9
|
import { getLanguageFromPath, type Theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
10
10
|
import type { OutputMeta } from "@oh-my-pi/pi-coding-agent/tools/output-meta";
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
truncateDiffByHunk,
|
|
18
18
|
} from "@oh-my-pi/pi-coding-agent/tools/render-utils";
|
|
19
19
|
import type { RenderCallOptions } from "@oh-my-pi/pi-coding-agent/tools/renderers";
|
|
20
|
+
import { renderStatusLine } from "@oh-my-pi/pi-coding-agent/tui";
|
|
20
21
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
21
22
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
22
23
|
import type { DiffError, DiffResult, Operation } from "./types";
|
|
@@ -178,9 +179,28 @@ export const editToolRenderer = {
|
|
|
178
179
|
let text = `${ui.title(opTitle)} ${spinner ? `${spinner} ` : ""}${editIcon} ${pathDisplay}`;
|
|
179
180
|
|
|
180
181
|
// Show streaming preview of diff/content
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
if (args.diff && args.op) {
|
|
183
|
+
text += formatStreamingDiff(args.diff, rawPath, uiTheme);
|
|
184
|
+
} else if (args.diff) {
|
|
185
|
+
const previewLines = args.diff.split("\n");
|
|
186
|
+
const maxLines = 6;
|
|
187
|
+
text += "\n\n";
|
|
188
|
+
for (const line of previewLines.slice(0, maxLines)) {
|
|
189
|
+
text += `${uiTheme.fg("toolOutput", ui.truncate(line, 80))}\n`;
|
|
190
|
+
}
|
|
191
|
+
if (previewLines.length > maxLines) {
|
|
192
|
+
text += uiTheme.fg("dim", `${uiTheme.format.ellipsis} ${previewLines.length - maxLines} more lines`);
|
|
193
|
+
}
|
|
194
|
+
} else if (args.newText || args.patch) {
|
|
195
|
+
const previewLines = (args.newText ?? args.patch ?? "").split("\n");
|
|
196
|
+
const maxLines = 6;
|
|
197
|
+
text += "\n\n";
|
|
198
|
+
for (const line of previewLines.slice(0, maxLines)) {
|
|
199
|
+
text += `${uiTheme.fg("toolOutput", ui.truncate(line, 80))}\n`;
|
|
200
|
+
}
|
|
201
|
+
if (previewLines.length > maxLines) {
|
|
202
|
+
text += uiTheme.fg("dim", `${uiTheme.format.ellipsis} ${previewLines.length - maxLines} more lines`);
|
|
203
|
+
}
|
|
184
204
|
}
|
|
185
205
|
|
|
186
206
|
return new Text(text, 0, 0);
|
|
@@ -221,7 +241,15 @@ export const editToolRenderer = {
|
|
|
221
241
|
|
|
222
242
|
// Show operation type for patch mode
|
|
223
243
|
const opTitle = op === "create" ? "Create" : op === "delete" ? "Delete" : "Edit";
|
|
224
|
-
|
|
244
|
+
const header = renderStatusLine(
|
|
245
|
+
{
|
|
246
|
+
icon: result.isError ? "error" : "success",
|
|
247
|
+
title: opTitle,
|
|
248
|
+
description: `${editIcon} ${pathDisplay}`,
|
|
249
|
+
},
|
|
250
|
+
uiTheme,
|
|
251
|
+
);
|
|
252
|
+
let text = header;
|
|
225
253
|
|
|
226
254
|
// Skip metadata line for delete operations
|
|
227
255
|
if (op !== "delete") {
|
|
@@ -59,6 +59,8 @@ Results are keyed by task `id` (e.g., "AuthProvider", "AuthApi").
|
|
|
59
59
|
If you discussed requirements, plans, schemas, or decisions with the user, you MUST include that information in `context`. Subagents cannot see prior messages—they start fresh with only what you explicitly pass them.
|
|
60
60
|
|
|
61
61
|
**Never call Task multiple times in parallel.** Use a single Task call with multiple entries in the `tasks` array. Parallel Task calls waste resources and bypass coordination.
|
|
62
|
+
|
|
63
|
+
**For code changes, subagents write files directly.** Never ask an agent to "return the changes" for you to apply—they have Edit and Write tools. Their context window holds the work; asking them to report back wastes it.
|
|
62
64
|
</critical>
|
|
63
65
|
|
|
64
66
|
<example>
|
package/src/sdk.ts
CHANGED
|
@@ -26,31 +26,34 @@
|
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
+
import { existsSync } from "node:fs";
|
|
30
|
+
import { rename } from "node:fs/promises";
|
|
29
31
|
import { join } from "node:path";
|
|
30
32
|
import { Agent, type AgentEvent, type AgentMessage, type AgentTool, type ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
31
33
|
import { type Message, type Model, supportsXhigh } from "@oh-my-pi/pi-ai";
|
|
32
|
-
|
|
34
|
+
// Import discovery to register all providers on startup
|
|
35
|
+
import { loadCapability } from "@oh-my-pi/pi-coding-agent/capability";
|
|
33
36
|
import { type Rule, ruleCapability } from "@oh-my-pi/pi-coding-agent/capability/rule";
|
|
34
37
|
import { getAgentDir, getConfigDirPaths } from "@oh-my-pi/pi-coding-agent/config";
|
|
35
|
-
import type { Component } from "@oh-my-pi/pi-tui";
|
|
36
|
-
// Import discovery to register all providers on startup
|
|
37
|
-
import { logger, postmortem } from "@oh-my-pi/pi-utils";
|
|
38
|
-
import chalk from "chalk";
|
|
39
|
-
import "./discovery";
|
|
40
38
|
import { CursorExecHandlers } from "@oh-my-pi/pi-coding-agent/cursor";
|
|
41
39
|
import { initializeWithSettings } from "@oh-my-pi/pi-coding-agent/discovery";
|
|
42
40
|
import { TtsrManager } from "@oh-my-pi/pi-coding-agent/export/ttsr";
|
|
43
41
|
import { disposeAllKernelSessions } from "@oh-my-pi/pi-coding-agent/ipy/executor";
|
|
44
42
|
import { closeAllConnections } from "@oh-my-pi/pi-coding-agent/ssh/connection-manager";
|
|
45
43
|
import { unmountAll } from "@oh-my-pi/pi-coding-agent/ssh/sshfs-mount";
|
|
44
|
+
import type { Component } from "@oh-my-pi/pi-tui";
|
|
45
|
+
import { logger, postmortem } from "@oh-my-pi/pi-utils";
|
|
46
|
+
import { YAML } from "bun";
|
|
47
|
+
import chalk from "chalk";
|
|
46
48
|
import { ModelRegistry } from "./config/model-registry";
|
|
47
49
|
import { formatModelString, parseModelString } from "./config/model-resolver";
|
|
48
50
|
import { loadPromptTemplates as loadPromptTemplatesInternal, type PromptTemplate } from "./config/prompt-templates";
|
|
49
51
|
import { type Settings, SettingsManager, type SkillsSettings } from "./config/settings-manager";
|
|
52
|
+
import "./discovery";
|
|
50
53
|
import {
|
|
51
54
|
type CustomCommandsLoadResult,
|
|
52
55
|
loadCustomCommands as loadCustomCommandsInternal,
|
|
53
|
-
} from "./extensibility/custom-commands
|
|
56
|
+
} from "./extensibility/custom-commands";
|
|
54
57
|
import type { CustomTool, CustomToolContext, CustomToolSessionEvent } from "./extensibility/custom-tools/types";
|
|
55
58
|
import {
|
|
56
59
|
discoverAndLoadExtensions,
|
|
@@ -64,7 +67,7 @@ import {
|
|
|
64
67
|
loadExtensions,
|
|
65
68
|
type ToolDefinition,
|
|
66
69
|
wrapRegisteredTools,
|
|
67
|
-
} from "./extensibility/extensions
|
|
70
|
+
} from "./extensibility/extensions";
|
|
68
71
|
import { loadSkills as loadSkillsInternal, type Skill, type SkillWarning } from "./extensibility/skills";
|
|
69
72
|
import { type FileSlashCommand, loadSlashCommands as loadSlashCommandsInternal } from "./extensibility/slash-commands";
|
|
70
73
|
import {
|
|
@@ -74,7 +77,7 @@ import {
|
|
|
74
77
|
RuleProtocolHandler,
|
|
75
78
|
SkillProtocolHandler,
|
|
76
79
|
} from "./internal-urls";
|
|
77
|
-
import { discoverAndLoadMCPTools, type MCPManager, type MCPToolsLoadResult } from "./mcp
|
|
80
|
+
import { discoverAndLoadMCPTools, type MCPManager, type MCPToolsLoadResult } from "./mcp";
|
|
78
81
|
import { AgentSession } from "./session/agent-session";
|
|
79
82
|
import { AuthStorage } from "./session/auth-storage";
|
|
80
83
|
import { convertToLlm } from "./session/messages";
|
|
@@ -84,8 +87,7 @@ import {
|
|
|
84
87
|
buildSystemPrompt as buildSystemPromptInternal,
|
|
85
88
|
loadProjectContextFiles as loadContextFilesInternal,
|
|
86
89
|
} from "./system-prompt";
|
|
87
|
-
import {
|
|
88
|
-
import { getGeminiImageTools } from "./tools/gemini-image";
|
|
90
|
+
import { AgentOutputManager } from "./task/output-manager";
|
|
89
91
|
import {
|
|
90
92
|
BashTool,
|
|
91
93
|
BUILTIN_TOOLS,
|
|
@@ -104,7 +106,9 @@ import {
|
|
|
104
106
|
type ToolSession,
|
|
105
107
|
WriteTool,
|
|
106
108
|
warmupLspServers,
|
|
107
|
-
} from "./tools
|
|
109
|
+
} from "./tools";
|
|
110
|
+
import { ToolContextStore } from "./tools/context";
|
|
111
|
+
import { getGeminiImageTools } from "./tools/gemini-image";
|
|
108
112
|
import { wrapToolsWithMetaNotice } from "./tools/output-meta";
|
|
109
113
|
import { EventBus } from "./utils/event-bus";
|
|
110
114
|
import { time } from "./utils/timings";
|
|
@@ -214,11 +218,11 @@ export type {
|
|
|
214
218
|
ExtensionContext,
|
|
215
219
|
ExtensionFactory,
|
|
216
220
|
ToolDefinition,
|
|
217
|
-
} from "@oh-my-pi/pi-coding-agent/extensibility/extensions
|
|
221
|
+
} from "@oh-my-pi/pi-coding-agent/extensibility/extensions";
|
|
218
222
|
export type { Skill } from "@oh-my-pi/pi-coding-agent/extensibility/skills";
|
|
219
223
|
export type { FileSlashCommand } from "@oh-my-pi/pi-coding-agent/extensibility/slash-commands";
|
|
220
|
-
export type { MCPManager, MCPServerConfig, MCPServerConnection, MCPToolsLoadResult } from "./mcp
|
|
221
|
-
export type { Tool } from "./tools
|
|
224
|
+
export type { MCPManager, MCPServerConfig, MCPServerConnection, MCPToolsLoadResult } from "./mcp";
|
|
225
|
+
export type { Tool } from "./tools";
|
|
222
226
|
|
|
223
227
|
export {
|
|
224
228
|
// Individual tool classes (for custom usage)
|
|
@@ -264,31 +268,64 @@ export async function discoverAuthStorage(agentDir: string = getDefaultAgentDir(
|
|
|
264
268
|
authPaths: [primaryPath, ...fallbackPaths],
|
|
265
269
|
});
|
|
266
270
|
|
|
267
|
-
const storage =
|
|
271
|
+
const storage = await AuthStorage.create(primaryPath, fallbackPaths);
|
|
268
272
|
await storage.reload();
|
|
269
273
|
return storage;
|
|
270
274
|
}
|
|
271
275
|
|
|
272
276
|
/**
|
|
273
277
|
* Create a ModelRegistry with fallback support.
|
|
274
|
-
* Reads from primary path first,
|
|
278
|
+
* Prefers models.yml over models.json. Reads from primary path first,
|
|
279
|
+
* then falls back to legacy paths (.pi, .claude).
|
|
275
280
|
*/
|
|
276
281
|
export async function discoverModels(
|
|
277
282
|
authStorage: AuthStorage,
|
|
278
283
|
agentDir: string = getDefaultAgentDir(),
|
|
279
284
|
): Promise<ModelRegistry> {
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
285
|
+
const yamlPath = join(agentDir, "models.yml");
|
|
286
|
+
const jsonPath = join(agentDir, "models.json");
|
|
287
|
+
|
|
288
|
+
// Migrate models.json to models.yml if yaml doesn't exist but json does
|
|
289
|
+
if (!existsSync(yamlPath) && existsSync(jsonPath)) {
|
|
290
|
+
await migrateModelsJsonToYaml(jsonPath, yamlPath);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Prefer models.yml, fall back to models.json
|
|
294
|
+
const primaryPath = existsSync(yamlPath) ? yamlPath : jsonPath;
|
|
295
|
+
|
|
296
|
+
// Get all models config paths (user-level only), excluding the primary
|
|
297
|
+
const yamlPaths = getConfigDirPaths("models.yml", { project: false });
|
|
298
|
+
const jsonPaths = getConfigDirPaths("models.json", { project: false });
|
|
299
|
+
const allPaths = [...yamlPaths, ...jsonPaths];
|
|
300
|
+
const fallbackPaths = allPaths.filter((p) => p !== primaryPath && existsSync(p));
|
|
284
301
|
|
|
285
302
|
logger.debug("discoverModels", { primaryPath, fallbackPaths });
|
|
286
303
|
|
|
287
304
|
const registry = new ModelRegistry(authStorage, primaryPath, fallbackPaths);
|
|
288
|
-
|
|
305
|
+
registry.refresh();
|
|
289
306
|
return registry;
|
|
290
307
|
}
|
|
291
308
|
|
|
309
|
+
/**
|
|
310
|
+
* Migrate models.json to models.yml.
|
|
311
|
+
* Creates models.yml from models.json and renames the json file to .bak.
|
|
312
|
+
*/
|
|
313
|
+
async function migrateModelsJsonToYaml(jsonPath: string, yamlPath: string): Promise<void> {
|
|
314
|
+
try {
|
|
315
|
+
const content = await Bun.file(jsonPath).text();
|
|
316
|
+
const parsed = JSON.parse(content);
|
|
317
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
318
|
+
logger.warn("migrateModelsJsonToYaml: invalid models.json structure", { path: jsonPath });
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
await Bun.write(yamlPath, YAML.stringify(parsed, null, 2));
|
|
322
|
+
await rename(jsonPath, `${jsonPath}.bak`);
|
|
323
|
+
logger.debug("migrateModelsJsonToYaml: migrated models.json to models.yml", { from: jsonPath, to: yamlPath });
|
|
324
|
+
} catch (error) {
|
|
325
|
+
logger.warn("migrateModelsJsonToYaml: migration failed", { error: String(error) });
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
292
329
|
/**
|
|
293
330
|
* Discover extensions from cwd.
|
|
294
331
|
*/
|
|
@@ -734,6 +771,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
734
771
|
);
|
|
735
772
|
toolSession.internalRouter = internalRouter;
|
|
736
773
|
toolSession.getArtifactsDir = getArtifactsDir;
|
|
774
|
+
toolSession.agentOutputManager = new AgentOutputManager(getArtifactsDir);
|
|
737
775
|
|
|
738
776
|
// Create and wrap tools with meta notice formatting
|
|
739
777
|
const rawBuiltinTools = await createTools(toolSession, options.toolNames);
|
|
@@ -38,9 +38,9 @@ import {
|
|
|
38
38
|
} from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
|
|
39
39
|
import type { SettingsManager, SkillsSettings } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
|
|
40
40
|
import { type BashResult, executeBash as executeBashCommand } from "@oh-my-pi/pi-coding-agent/exec/bash-executor";
|
|
41
|
-
import { exportSessionToHtml } from "@oh-my-pi/pi-coding-agent/export/html
|
|
41
|
+
import { exportSessionToHtml } from "@oh-my-pi/pi-coding-agent/export/html";
|
|
42
42
|
import type { TtsrManager } from "@oh-my-pi/pi-coding-agent/export/ttsr";
|
|
43
|
-
import type { LoadedCustomCommand } from "@oh-my-pi/pi-coding-agent/extensibility/custom-commands
|
|
43
|
+
import type { LoadedCustomCommand } from "@oh-my-pi/pi-coding-agent/extensibility/custom-commands";
|
|
44
44
|
import type {
|
|
45
45
|
ExtensionCommandContext,
|
|
46
46
|
ExtensionRunner,
|
|
@@ -78,7 +78,7 @@ import {
|
|
|
78
78
|
generateBranchSummary,
|
|
79
79
|
prepareCompaction,
|
|
80
80
|
shouldCompact,
|
|
81
|
-
} from "./compaction
|
|
81
|
+
} from "./compaction";
|
|
82
82
|
import {
|
|
83
83
|
type BashExecutionMessage,
|
|
84
84
|
type BranchSummaryMessage,
|