@oh-my-pi/pi-coding-agent 3.20.1 → 3.24.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 +107 -8
- package/docs/custom-tools.md +3 -3
- package/docs/extensions.md +226 -220
- package/docs/hooks.md +2 -2
- package/docs/sdk.md +50 -53
- package/examples/custom-tools/README.md +2 -17
- package/examples/extensions/README.md +76 -74
- package/examples/extensions/todo.ts +2 -5
- package/examples/hooks/custom-compaction.ts +2 -4
- package/examples/hooks/handoff.ts +1 -1
- package/examples/hooks/qna.ts +1 -1
- package/examples/sdk/02-custom-model.ts +1 -1
- package/examples/sdk/README.md +7 -11
- package/package.json +6 -6
- package/src/cli/args.ts +9 -6
- package/src/cli/file-processor.ts +1 -1
- package/src/cli/list-models.ts +1 -1
- package/src/core/agent-session.ts +16 -5
- package/src/core/auth-storage.ts +1 -1
- package/src/core/compaction/branch-summarization.ts +2 -2
- package/src/core/compaction/compaction.ts +2 -2
- package/src/core/compaction/utils.ts +1 -1
- package/src/core/custom-tools/types.ts +1 -1
- package/src/core/custom-tools/wrapper.ts +0 -1
- package/src/core/extensions/index.ts +1 -6
- package/src/core/extensions/runner.ts +1 -1
- package/src/core/extensions/types.ts +1 -1
- package/src/core/extensions/wrapper.ts +1 -8
- package/src/core/file-mentions.ts +5 -8
- package/src/core/hooks/runner.ts +2 -2
- package/src/core/hooks/types.ts +1 -1
- package/src/core/messages.ts +1 -1
- package/src/core/model-registry.ts +1 -1
- package/src/core/model-resolver.ts +1 -1
- package/src/core/sdk.ts +64 -105
- package/src/core/session-manager.ts +18 -22
- package/src/core/settings-manager.ts +66 -1
- package/src/core/slash-commands.ts +12 -5
- package/src/core/system-prompt.ts +49 -36
- package/src/core/title-generator.ts +2 -2
- package/src/core/tools/ask.ts +98 -4
- package/src/core/tools/bash-interceptor.ts +11 -4
- package/src/core/tools/bash.ts +121 -5
- package/src/core/tools/context.ts +7 -0
- package/src/core/tools/edit-diff.ts +73 -24
- package/src/core/tools/edit.ts +221 -34
- package/src/core/tools/exa/render.ts +4 -16
- package/src/core/tools/find.ts +149 -5
- package/src/core/tools/gemini-image.ts +279 -56
- package/src/core/tools/git.ts +17 -3
- package/src/core/tools/grep.ts +185 -5
- package/src/core/tools/index.test.ts +180 -0
- package/src/core/tools/index.ts +96 -242
- package/src/core/tools/ls.ts +133 -5
- package/src/core/tools/lsp/index.ts +32 -29
- package/src/core/tools/lsp/render.ts +21 -22
- package/src/core/tools/notebook.ts +112 -4
- package/src/core/tools/output.ts +175 -15
- package/src/core/tools/read.ts +127 -25
- package/src/core/tools/render-utils.ts +241 -0
- package/src/core/tools/renderers.ts +40 -828
- package/src/core/tools/review.ts +26 -25
- package/src/core/tools/rulebook.ts +11 -3
- package/src/core/tools/task/agents.ts +28 -7
- package/src/core/tools/task/discovery.ts +0 -6
- package/src/core/tools/task/executor.ts +264 -254
- package/src/core/tools/task/index.ts +48 -208
- package/src/core/tools/task/render.ts +26 -11
- package/src/core/tools/task/types.ts +7 -12
- package/src/core/tools/task/worker-protocol.ts +17 -0
- package/src/core/tools/task/worker.ts +238 -0
- package/src/core/tools/truncate.ts +27 -1
- package/src/core/tools/web-fetch.ts +25 -49
- package/src/core/tools/web-search/index.ts +132 -46
- package/src/core/tools/web-search/providers/anthropic.ts +7 -2
- package/src/core/tools/web-search/providers/exa.ts +2 -1
- package/src/core/tools/web-search/providers/perplexity.ts +6 -1
- package/src/core/tools/web-search/render.ts +6 -4
- package/src/core/tools/web-search/types.ts +13 -0
- package/src/core/tools/write.ts +96 -14
- package/src/core/voice.ts +1 -1
- package/src/discovery/helpers.test.ts +1 -1
- package/src/index.ts +5 -16
- package/src/main.ts +5 -5
- package/src/modes/interactive/components/assistant-message.ts +1 -1
- package/src/modes/interactive/components/custom-message.ts +1 -1
- package/src/modes/interactive/components/extensions/inspector-panel.ts +25 -22
- package/src/modes/interactive/components/extensions/state-manager.ts +12 -0
- package/src/modes/interactive/components/footer.ts +1 -1
- package/src/modes/interactive/components/hook-message.ts +1 -1
- package/src/modes/interactive/components/model-selector.ts +1 -1
- package/src/modes/interactive/components/oauth-selector.ts +1 -1
- package/src/modes/interactive/components/settings-defs.ts +49 -0
- package/src/modes/interactive/components/status-line.ts +1 -1
- package/src/modes/interactive/components/tool-execution.ts +93 -538
- package/src/modes/interactive/interactive-mode.ts +19 -7
- package/src/modes/interactive/theme/theme.ts +4 -4
- package/src/modes/print-mode.ts +1 -1
- package/src/modes/rpc/rpc-client.ts +1 -1
- package/src/modes/rpc/rpc-types.ts +1 -1
- package/src/prompts/system-prompt.md +4 -0
- package/src/prompts/task.md +0 -7
- package/src/prompts/tools/gemini-image.md +5 -1
- package/src/prompts/tools/output.md +6 -2
- package/src/prompts/tools/task.md +68 -0
- package/src/prompts/tools/web-fetch.md +1 -0
- package/src/prompts/tools/web-search.md +2 -0
- package/src/utils/image-convert.ts +8 -2
- package/src/utils/image-magick.ts +247 -0
- package/src/utils/image-resize.ts +53 -13
- package/examples/custom-tools/question/index.ts +0 -84
- package/examples/custom-tools/subagent/README.md +0 -172
- package/examples/custom-tools/subagent/agents/planner.md +0 -37
- package/examples/custom-tools/subagent/agents/scout.md +0 -50
- package/examples/custom-tools/subagent/agents/worker.md +0 -24
- package/examples/custom-tools/subagent/agents.ts +0 -156
- package/examples/custom-tools/subagent/commands/implement-and-review.md +0 -10
- package/examples/custom-tools/subagent/commands/implement.md +0 -10
- package/examples/custom-tools/subagent/commands/scout-and-plan.md +0 -9
- package/examples/custom-tools/subagent/index.ts +0 -1002
- package/examples/sdk/05-tools.ts +0 -94
- package/examples/sdk/12-full-control.ts +0 -95
- package/src/prompts/browser.md +0 -71
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
* Modes use this class and add their own I/O layer on top.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
import type { AssistantMessage, ImageContent, Message, Model, TextContent, Usage } from "@mariozechner/pi-ai";
|
|
17
|
+
import { isContextOverflow, modelsAreEqual, supportsXhigh } from "@mariozechner/pi-ai";
|
|
16
18
|
import type { Agent, AgentEvent, AgentMessage, AgentState, AgentTool, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
17
|
-
import type { AssistantMessage, ImageContent, Message, Model, TextContent, Usage } from "@oh-my-pi/pi-ai";
|
|
18
|
-
import { isContextOverflow, modelsAreEqual, supportsXhigh } from "@oh-my-pi/pi-ai";
|
|
19
19
|
import type { Rule } from "../capability/rule";
|
|
20
20
|
import { getAuthPath } from "../config";
|
|
21
21
|
import { theme } from "../modes/interactive/theme/theme";
|
|
@@ -51,6 +51,7 @@ import { parseModelString } from "./model-resolver";
|
|
|
51
51
|
import { expandPromptTemplate, type PromptTemplate, parseCommandArgs } from "./prompt-templates";
|
|
52
52
|
import type { BranchSummaryEntry, CompactionEntry, NewSessionOptions, SessionManager } from "./session-manager";
|
|
53
53
|
import type { SettingsManager, SkillsSettings } from "./settings-manager";
|
|
54
|
+
import { expandSlashCommand, type FileSlashCommand } from "./slash-commands";
|
|
54
55
|
import type { TtsrManager } from "./ttsr";
|
|
55
56
|
|
|
56
57
|
/** Session-specific events that extend the core AgentEvent */
|
|
@@ -77,6 +78,8 @@ export interface AgentSessionConfig {
|
|
|
77
78
|
scopedModels?: Array<{ model: Model<any>; thinkingLevel: ThinkingLevel }>;
|
|
78
79
|
/** Prompt templates for expansion */
|
|
79
80
|
promptTemplates?: PromptTemplate[];
|
|
81
|
+
/** File-based slash commands for expansion */
|
|
82
|
+
slashCommands?: FileSlashCommand[];
|
|
80
83
|
/** Extension runner (created in main.ts with wrapped tools) */
|
|
81
84
|
extensionRunner?: ExtensionRunner;
|
|
82
85
|
/** Custom commands (TypeScript slash commands) */
|
|
@@ -87,7 +90,7 @@ export interface AgentSessionConfig {
|
|
|
87
90
|
/** Tool registry for LSP and settings */
|
|
88
91
|
toolRegistry?: Map<string, AgentTool>;
|
|
89
92
|
/** System prompt builder that can consider tool availability */
|
|
90
|
-
rebuildSystemPrompt?: (toolNames: string[]) => string;
|
|
93
|
+
rebuildSystemPrompt?: (toolNames: string[], tools: Map<string, AgentTool>) => string;
|
|
91
94
|
/** TTSR manager for time-traveling stream rules */
|
|
92
95
|
ttsrManager?: TtsrManager;
|
|
93
96
|
}
|
|
@@ -175,6 +178,7 @@ export class AgentSession {
|
|
|
175
178
|
|
|
176
179
|
private _scopedModels: Array<{ model: Model<any>; thinkingLevel: ThinkingLevel }>;
|
|
177
180
|
private _promptTemplates: PromptTemplate[];
|
|
181
|
+
private _slashCommands: FileSlashCommand[];
|
|
178
182
|
|
|
179
183
|
// Event subscription state
|
|
180
184
|
private _unsubscribeAgent?: () => void;
|
|
@@ -218,7 +222,7 @@ export class AgentSession {
|
|
|
218
222
|
|
|
219
223
|
// Tool registry and prompt builder for extensions
|
|
220
224
|
private _toolRegistry: Map<string, AgentTool>;
|
|
221
|
-
private _rebuildSystemPrompt: ((toolNames: string[]) => string) | undefined;
|
|
225
|
+
private _rebuildSystemPrompt: ((toolNames: string[], tools: Map<string, AgentTool>) => string) | undefined;
|
|
222
226
|
private _baseSystemPrompt: string;
|
|
223
227
|
|
|
224
228
|
// TTSR manager for time-traveling stream rules
|
|
@@ -232,6 +236,7 @@ export class AgentSession {
|
|
|
232
236
|
this.settingsManager = config.settingsManager;
|
|
233
237
|
this._scopedModels = config.scopedModels ?? [];
|
|
234
238
|
this._promptTemplates = config.promptTemplates ?? [];
|
|
239
|
+
this._slashCommands = config.slashCommands ?? [];
|
|
235
240
|
this._extensionRunner = config.extensionRunner;
|
|
236
241
|
this._customCommands = config.customCommands ?? [];
|
|
237
242
|
this._skillsSettings = config.skillsSettings;
|
|
@@ -598,7 +603,7 @@ export class AgentSession {
|
|
|
598
603
|
|
|
599
604
|
// Rebuild base system prompt with new tool set
|
|
600
605
|
if (this._rebuildSystemPrompt) {
|
|
601
|
-
this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames);
|
|
606
|
+
this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames, this._toolRegistry);
|
|
602
607
|
this.agent.setSystemPrompt(this._baseSystemPrompt);
|
|
603
608
|
}
|
|
604
609
|
}
|
|
@@ -684,6 +689,12 @@ export class AgentSession {
|
|
|
684
689
|
}
|
|
685
690
|
text = customResult;
|
|
686
691
|
}
|
|
692
|
+
|
|
693
|
+
// Try file-based slash commands (markdown files from commands/ directories)
|
|
694
|
+
// Only if text still starts with "/" (wasn't transformed by custom command)
|
|
695
|
+
if (text.startsWith("/")) {
|
|
696
|
+
text = expandSlashCommand(text, this._slashCommands);
|
|
697
|
+
}
|
|
687
698
|
}
|
|
688
699
|
|
|
689
700
|
// Expand file-based prompt templates if requested
|
package/src/core/auth-storage.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* a summary of the branch being left so context isn't lost.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { Model } from "@mariozechner/pi-ai";
|
|
9
|
+
import { completeSimple } from "@mariozechner/pi-ai";
|
|
8
10
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
9
|
-
import type { Model } from "@oh-my-pi/pi-ai";
|
|
10
|
-
import { completeSimple } from "@oh-my-pi/pi-ai";
|
|
11
11
|
import branchSummaryPrompt from "../../prompts/branch-summary.md" with { type: "text" };
|
|
12
12
|
import branchSummaryPreamble from "../../prompts/branch-summary-preamble.md" with { type: "text" };
|
|
13
13
|
import {
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* and after compaction the session is reloaded.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { AssistantMessage, Model, Usage } from "@mariozechner/pi-ai";
|
|
9
|
+
import { complete, completeSimple } from "@mariozechner/pi-ai";
|
|
8
10
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
9
|
-
import type { AssistantMessage, Model, Usage } from "@oh-my-pi/pi-ai";
|
|
10
|
-
import { complete, completeSimple } from "@oh-my-pi/pi-ai";
|
|
11
11
|
import compactionSummaryPrompt from "../../prompts/compaction-summary.md" with { type: "text" };
|
|
12
12
|
import compactionTurnPrefixPrompt from "../../prompts/compaction-turn-prefix.md" with { type: "text" };
|
|
13
13
|
import compactionUpdateSummaryPrompt from "../../prompts/compaction-update-summary.md" with { type: "text" };
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Shared utilities for compaction and branch summarization.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { Message } from "@mariozechner/pi-ai";
|
|
5
6
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
6
|
-
import type { Message } from "@oh-my-pi/pi-ai";
|
|
7
7
|
import summarizationSystemPrompt from "../../prompts/summarization-system.md" with { type: "text" };
|
|
8
8
|
|
|
9
9
|
// ============================================================================
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* They can provide custom rendering for tool calls and results in the TUI.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { Model } from "@mariozechner/pi-ai";
|
|
8
9
|
import type { AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
9
|
-
import type { Model } from "@oh-my-pi/pi-ai";
|
|
10
10
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
11
11
|
import type { Static, TSchema } from "@sinclair/typebox";
|
|
12
12
|
import type { Theme } from "../../modes/interactive/theme/theme";
|
|
@@ -16,7 +16,6 @@ export function wrapCustomTool(tool: CustomTool, getContext: () => CustomToolCon
|
|
|
16
16
|
label: tool.label,
|
|
17
17
|
description: tool.description,
|
|
18
18
|
parameters: tool.parameters,
|
|
19
|
-
hidden: tool.hidden,
|
|
20
19
|
execute: (toolCallId, params, signal, onUpdate, context) =>
|
|
21
20
|
tool.execute(toolCallId, params, onUpdate, context ?? getContext(), signal),
|
|
22
21
|
renderCall: tool.renderCall ? (args, theme) => tool.renderCall?.(args, theme as Theme) : undefined,
|
|
@@ -92,9 +92,4 @@ export {
|
|
|
92
92
|
isReadToolResult,
|
|
93
93
|
isWriteToolResult,
|
|
94
94
|
} from "./types";
|
|
95
|
-
export {
|
|
96
|
-
wrapRegisteredTool,
|
|
97
|
-
wrapRegisteredTools,
|
|
98
|
-
wrapToolsWithExtensions,
|
|
99
|
-
wrapToolWithExtensions,
|
|
100
|
-
} from "./wrapper";
|
|
95
|
+
export { wrapRegisteredTool, wrapRegisteredTools, wrapToolWithExtensions } from "./wrapper";
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Extension runner - executes extensions and manages their lifecycle.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { ImageContent, Model } from "@mariozechner/pi-ai";
|
|
5
6
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
6
|
-
import type { ImageContent, Model } from "@oh-my-pi/pi-ai";
|
|
7
7
|
import type { KeyId } from "@oh-my-pi/pi-tui";
|
|
8
8
|
import { theme } from "../../modes/interactive/theme/theme";
|
|
9
9
|
import type { ModelRegistry } from "../model-registry";
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* - Interact with the user via UI primitives
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import type { ImageContent, Model, TextContent, ToolResultMessage } from "@mariozechner/pi-ai";
|
|
11
12
|
import type { AgentMessage, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
12
|
-
import type { ImageContent, Model, TextContent, ToolResultMessage } from "@oh-my-pi/pi-ai";
|
|
13
13
|
import type { Component, KeyId, TUI } from "@oh-my-pi/pi-tui";
|
|
14
14
|
import type { Static, TSchema } from "@sinclair/typebox";
|
|
15
15
|
import type { Theme } from "../../modes/interactive/theme/theme";
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Tool wrappers for extensions.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { ImageContent, TextContent } from "@mariozechner/pi-ai";
|
|
5
6
|
import type { AgentTool, AgentToolContext, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
6
|
-
import type { ImageContent, TextContent } from "@oh-my-pi/pi-ai";
|
|
7
7
|
import type { Theme } from "../../modes/interactive/theme/theme";
|
|
8
8
|
import type { ExtensionRunner } from "./runner";
|
|
9
9
|
import type { ExtensionContext, RegisteredTool, ToolCallEventResult, ToolResultEventResult } from "./types";
|
|
@@ -138,10 +138,3 @@ export function wrapToolWithExtensions<T>(tool: AgentTool<any, T>, runner: Exten
|
|
|
138
138
|
},
|
|
139
139
|
};
|
|
140
140
|
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Wrap all tools with extension callbacks.
|
|
144
|
-
*/
|
|
145
|
-
export function wrapToolsWithExtensions<T>(tools: AgentTool<any, T>[], runner: ExtensionRunner): AgentTool<any, T>[] {
|
|
146
|
-
return tools.map((tool) => wrapToolWithExtensions(tool, runner));
|
|
147
|
-
}
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* so the agent doesn't need to read them manually.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import path from "node:path";
|
|
9
10
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
10
11
|
import type { FileMentionMessage } from "./messages";
|
|
11
|
-
import { createReadTool } from "./tools/read";
|
|
12
12
|
|
|
13
13
|
/** Regex to match @filepath patterns in text */
|
|
14
14
|
const FILE_MENTION_REGEX = /@((?:[^\s@]+\/)*[^\s@]+\.[a-zA-Z0-9]+)/g;
|
|
@@ -26,17 +26,14 @@ export function extractFileMentions(text: string): string[] {
|
|
|
26
26
|
export async function generateFileMentionMessages(filePaths: string[], cwd: string): Promise<AgentMessage[]> {
|
|
27
27
|
if (filePaths.length === 0) return [];
|
|
28
28
|
|
|
29
|
-
const readTool = createReadTool(cwd);
|
|
30
29
|
const files: FileMentionMessage["files"] = [];
|
|
31
30
|
|
|
32
31
|
for (const filePath of filePaths) {
|
|
33
32
|
try {
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
files.push({ path: filePath, content: textContent.text, lineCount });
|
|
39
|
-
}
|
|
33
|
+
const absolutePath = path.resolve(cwd, filePath);
|
|
34
|
+
const content = await Bun.file(absolutePath).text();
|
|
35
|
+
const lineCount = content.split("\n").length;
|
|
36
|
+
files.push({ path: filePath, content, lineCount });
|
|
40
37
|
} catch {
|
|
41
38
|
// File doesn't exist or isn't readable - skip silently
|
|
42
39
|
}
|
package/src/core/hooks/runner.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Hook runner - executes hooks and manages their lifecycle.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { Model } from "@mariozechner/pi-ai";
|
|
5
6
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
6
|
-
import type { Model } from "@oh-my-pi/pi-ai";
|
|
7
7
|
import { theme } from "../../modes/interactive/theme/theme";
|
|
8
8
|
import type { ModelRegistry } from "../model-registry";
|
|
9
9
|
import type { SessionManager } from "../session-manager";
|
|
@@ -400,7 +400,7 @@ export class HookRunner {
|
|
|
400
400
|
*/
|
|
401
401
|
async emitBeforeAgentStart(
|
|
402
402
|
prompt: string,
|
|
403
|
-
images?: import("@
|
|
403
|
+
images?: import("@mariozechner/pi-ai").ImageContent[],
|
|
404
404
|
): Promise<BeforeAgentStartEventResult | undefined> {
|
|
405
405
|
const ctx = this.createContext();
|
|
406
406
|
let result: BeforeAgentStartEventResult | undefined;
|
package/src/core/hooks/types.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* and interact with the user via UI primitives.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { ImageContent, Message, Model, TextContent, ToolResultMessage } from "@mariozechner/pi-ai";
|
|
8
9
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
9
|
-
import type { ImageContent, Message, Model, TextContent, ToolResultMessage } from "@oh-my-pi/pi-ai";
|
|
10
10
|
import type { Component, TUI } from "@oh-my-pi/pi-tui";
|
|
11
11
|
import type { Theme } from "../../modes/interactive/theme/theme";
|
|
12
12
|
import type { CompactionPreparation, CompactionResult } from "../compaction/index";
|
package/src/core/messages.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* and provides a transformer to convert them to LLM-compatible messages.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { ImageContent, Message, TextContent } from "@mariozechner/pi-ai";
|
|
8
9
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
9
|
-
import type { ImageContent, Message, TextContent } from "@oh-my-pi/pi-ai";
|
|
10
10
|
|
|
11
11
|
export const COMPACTION_SUMMARY_PREFIX = `The conversation history before this point was compacted into the following summary:
|
|
12
12
|
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
type KnownProvider,
|
|
12
12
|
type Model,
|
|
13
13
|
normalizeDomain,
|
|
14
|
-
} from "@
|
|
14
|
+
} from "@mariozechner/pi-ai";
|
|
15
15
|
import { type Static, Type } from "@sinclair/typebox";
|
|
16
16
|
import AjvModule from "ajv";
|
|
17
17
|
import type { AuthStorage } from "./auth-storage";
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Model resolution, scoping, and initial selection
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { type Api, type KnownProvider, type Model, modelsAreEqual } from "@mariozechner/pi-ai";
|
|
5
6
|
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
6
|
-
import { type Api, type KnownProvider, type Model, modelsAreEqual } from "@oh-my-pi/pi-ai";
|
|
7
7
|
import chalk from "chalk";
|
|
8
8
|
import { minimatch } from "minimatch";
|
|
9
9
|
import { isValidThinkingLevel } from "../cli/args";
|
package/src/core/sdk.ts
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* const session = await createAgentSession({
|
|
19
19
|
* model: myModel,
|
|
20
20
|
* getApiKey: async () => process.env.MY_KEY,
|
|
21
|
-
*
|
|
21
|
+
* toolNames: ["read", "bash", "edit", "write"], // Filter tools
|
|
22
22
|
* extensions: [],
|
|
23
23
|
* skills: [],
|
|
24
24
|
* sessionFile: false,
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
import { join } from "node:path";
|
|
30
|
+
import type { Model } from "@mariozechner/pi-ai";
|
|
30
31
|
import { Agent, type AgentTool, type ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
31
|
-
import type { Model } from "@oh-my-pi/pi-ai";
|
|
32
32
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
33
33
|
import chalk from "chalk";
|
|
34
34
|
// Import discovery to register all providers on startup
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
loadExtensionFromFactory,
|
|
56
56
|
type ToolDefinition,
|
|
57
57
|
wrapRegisteredTools,
|
|
58
|
-
|
|
58
|
+
wrapToolWithExtensions,
|
|
59
59
|
} from "./extensions/index";
|
|
60
60
|
import { logger } from "./logger";
|
|
61
61
|
import { discoverAndLoadMCPTools, type MCPManager, type MCPToolsLoadResult } from "./mcp/index";
|
|
@@ -66,6 +66,7 @@ import { loadPromptTemplates as loadPromptTemplatesInternal, type PromptTemplate
|
|
|
66
66
|
import { SessionManager } from "./session-manager";
|
|
67
67
|
import { type Settings, SettingsManager, type SkillsSettings } from "./settings-manager";
|
|
68
68
|
import { loadSkills as loadSkillsInternal, type Skill } from "./skills";
|
|
69
|
+
import { type FileSlashCommand, loadSlashCommands as loadSlashCommandsInternal } from "./slash-commands";
|
|
69
70
|
import {
|
|
70
71
|
buildSystemPrompt as buildSystemPromptInternal,
|
|
71
72
|
loadProjectContextFiles as loadContextFilesInternal,
|
|
@@ -74,46 +75,34 @@ import { time } from "./timings";
|
|
|
74
75
|
import { createToolContextStore } from "./tools/context";
|
|
75
76
|
import { getGeminiImageTools } from "./tools/gemini-image";
|
|
76
77
|
import {
|
|
77
|
-
|
|
78
|
-
applyBashInterception,
|
|
79
|
-
baseCodingToolNames,
|
|
80
|
-
bashTool,
|
|
81
|
-
codingTools,
|
|
82
|
-
createAllTools,
|
|
78
|
+
BUILTIN_TOOLS,
|
|
83
79
|
createBashTool,
|
|
84
|
-
createCodingTools,
|
|
85
80
|
createEditTool,
|
|
86
81
|
createFindTool,
|
|
87
82
|
createGitTool,
|
|
88
83
|
createGrepTool,
|
|
89
84
|
createLsTool,
|
|
90
|
-
createReadOnlyTools,
|
|
91
85
|
createReadTool,
|
|
92
|
-
|
|
86
|
+
createTools,
|
|
93
87
|
createWriteTool,
|
|
94
|
-
editTool,
|
|
95
88
|
filterRulebookRules,
|
|
96
|
-
findTool,
|
|
97
89
|
getWebSearchTools,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
lsTool,
|
|
101
|
-
readOnlyTools,
|
|
102
|
-
readTool,
|
|
90
|
+
setPreferredImageProvider,
|
|
91
|
+
setPreferredWebSearchProvider,
|
|
103
92
|
type Tool,
|
|
104
|
-
type
|
|
93
|
+
type ToolSession,
|
|
105
94
|
warmupLspServers,
|
|
106
|
-
writeTool,
|
|
107
95
|
} from "./tools/index";
|
|
108
96
|
import { createTtsrManager } from "./ttsr";
|
|
109
97
|
|
|
110
98
|
// Types
|
|
111
|
-
|
|
112
99
|
export interface CreateAgentSessionOptions {
|
|
113
100
|
/** Working directory for project-local discovery. Default: process.cwd() */
|
|
114
101
|
cwd?: string;
|
|
115
102
|
/** Global config directory. Default: ~/.omp/agent */
|
|
116
103
|
agentDir?: string;
|
|
104
|
+
/** Spawns to allow. Default: "*" */
|
|
105
|
+
spawns?: string;
|
|
117
106
|
|
|
118
107
|
/** Auth storage for credentials. Default: discoverAuthStorage(agentDir) */
|
|
119
108
|
authStorage?: AuthStorage;
|
|
@@ -130,8 +119,6 @@ export interface CreateAgentSessionOptions {
|
|
|
130
119
|
/** System prompt. String replaces default, function receives default and returns final. */
|
|
131
120
|
systemPrompt?: string | ((defaultPrompt: string) => string);
|
|
132
121
|
|
|
133
|
-
/** Built-in tools to use. Default: all coding tools (read, bash, edit, write, grep, find, ls, lsp, notebook, output, task, web_fetch, web_search) */
|
|
134
|
-
tools?: Tool[];
|
|
135
122
|
/** Custom tools to register (in addition to built-in tools). Accepts both CustomTool and ToolDefinition. */
|
|
136
123
|
customTools?: (CustomTool | ToolDefinition)[];
|
|
137
124
|
/** Inline extensions (merged with discovery). */
|
|
@@ -153,12 +140,14 @@ export interface CreateAgentSessionOptions {
|
|
|
153
140
|
contextFiles?: Array<{ path: string; content: string }>;
|
|
154
141
|
/** Prompt templates. Default: discovered from cwd/.omp/prompts/ + agentDir/prompts/ */
|
|
155
142
|
promptTemplates?: PromptTemplate[];
|
|
143
|
+
/** File-based slash commands. Default: discovered from commands/ directories */
|
|
144
|
+
slashCommands?: FileSlashCommand[];
|
|
156
145
|
|
|
157
146
|
/** Enable MCP server discovery from .mcp.json files. Default: true */
|
|
158
147
|
enableMCP?: boolean;
|
|
159
148
|
|
|
160
149
|
/** Tool names explicitly requested (enables disabled-by-default tools) */
|
|
161
|
-
|
|
150
|
+
toolNames?: string[];
|
|
162
151
|
|
|
163
152
|
/** Session manager. Default: SessionManager.create(cwd) */
|
|
164
153
|
sessionManager?: SessionManager;
|
|
@@ -199,24 +188,15 @@ export type { MCPManager, MCPServerConfig, MCPServerConnection, MCPToolsLoadResu
|
|
|
199
188
|
export type { PromptTemplate } from "./prompt-templates";
|
|
200
189
|
export type { Settings, SkillsSettings } from "./settings-manager";
|
|
201
190
|
export type { Skill } from "./skills";
|
|
191
|
+
export type { FileSlashCommand } from "./slash-commands";
|
|
202
192
|
export type { Tool } from "./tools/index";
|
|
203
193
|
|
|
204
194
|
export {
|
|
205
|
-
//
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
grepTool,
|
|
211
|
-
findTool,
|
|
212
|
-
gitTool,
|
|
213
|
-
lsTool,
|
|
214
|
-
codingTools,
|
|
215
|
-
readOnlyTools,
|
|
216
|
-
allTools as allBuiltInTools,
|
|
217
|
-
// Tool factories (for custom cwd)
|
|
218
|
-
createCodingTools,
|
|
219
|
-
createReadOnlyTools,
|
|
195
|
+
// Tool factories
|
|
196
|
+
BUILTIN_TOOLS,
|
|
197
|
+
createTools,
|
|
198
|
+
type ToolSession,
|
|
199
|
+
// Individual tool factories (for custom usage)
|
|
220
200
|
createReadTool,
|
|
221
201
|
createBashTool,
|
|
222
202
|
createEditTool,
|
|
@@ -315,6 +295,13 @@ export async function discoverPromptTemplates(cwd?: string, agentDir?: string):
|
|
|
315
295
|
});
|
|
316
296
|
}
|
|
317
297
|
|
|
298
|
+
/**
|
|
299
|
+
* Discover file-based slash commands from commands/ directories.
|
|
300
|
+
*/
|
|
301
|
+
export function discoverSlashCommands(cwd?: string): FileSlashCommand[] {
|
|
302
|
+
return loadSlashCommandsInternal({ cwd: cwd ?? process.cwd() });
|
|
303
|
+
}
|
|
304
|
+
|
|
318
305
|
/**
|
|
319
306
|
* Discover custom commands (TypeScript slash commands) from cwd and agentDir.
|
|
320
307
|
*/
|
|
@@ -413,7 +400,6 @@ function customToolToDefinition(tool: CustomTool): ToolDefinition {
|
|
|
413
400
|
label: tool.label,
|
|
414
401
|
description: tool.description,
|
|
415
402
|
parameters: tool.parameters,
|
|
416
|
-
hidden: tool.hidden,
|
|
417
403
|
execute: (toolCallId, params, onUpdate, ctx, signal) =>
|
|
418
404
|
tool.execute(toolCallId, params, onUpdate, createCustomToolContext(ctx), signal),
|
|
419
405
|
onSession: tool.onSession ? (event, ctx) => tool.onSession?.(event, createCustomToolContext(ctx)) : undefined,
|
|
@@ -480,7 +466,7 @@ function createCustomToolsExtension(tools: CustomTool[]): ExtensionFactory {
|
|
|
480
466
|
* const { session } = await createAgentSession();
|
|
481
467
|
*
|
|
482
468
|
* // With explicit model
|
|
483
|
-
* import { getModel } from '@
|
|
469
|
+
* import { getModel } from '@mariozechner/pi-ai';
|
|
484
470
|
* const { session } = await createAgentSession({
|
|
485
471
|
* model: getModel('anthropic', 'claude-opus-4-5'),
|
|
486
472
|
* thinkingLevel: 'high',
|
|
@@ -496,7 +482,7 @@ function createCustomToolsExtension(tools: CustomTool[]): ExtensionFactory {
|
|
|
496
482
|
* model: myModel,
|
|
497
483
|
* getApiKey: async () => process.env.MY_KEY,
|
|
498
484
|
* systemPrompt: 'You are helpful.',
|
|
499
|
-
* tools:
|
|
485
|
+
* tools: codingTools({ cwd: process.cwd() }),
|
|
500
486
|
* skills: [],
|
|
501
487
|
* sessionManager: SessionManager.inMemory(),
|
|
502
488
|
* });
|
|
@@ -517,6 +503,10 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
517
503
|
initializeWithSettings(settingsManager);
|
|
518
504
|
time("initializeWithSettings");
|
|
519
505
|
|
|
506
|
+
// Initialize provider preferences from settings
|
|
507
|
+
setPreferredWebSearchProvider(settingsManager.getWebSearchProvider());
|
|
508
|
+
setPreferredImageProvider(settingsManager.getImageProvider());
|
|
509
|
+
|
|
520
510
|
const sessionManager = options.sessionManager ?? SessionManager.create(cwd);
|
|
521
511
|
time("sessionManager");
|
|
522
512
|
|
|
@@ -613,22 +603,18 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
613
603
|
const contextFiles = options.contextFiles ?? discoverContextFiles(cwd, agentDir);
|
|
614
604
|
time("discoverContextFiles");
|
|
615
605
|
|
|
616
|
-
const
|
|
606
|
+
const toolSession: ToolSession = {
|
|
607
|
+
cwd,
|
|
608
|
+
hasUI: options.hasUI ?? false,
|
|
609
|
+
rulebookRules,
|
|
610
|
+
eventBus,
|
|
617
611
|
getSessionFile: () => sessionManager.getSessionFile() ?? null,
|
|
612
|
+
getSessionSpawns: () => options.spawns ?? "*",
|
|
613
|
+
settings: settingsManager,
|
|
618
614
|
};
|
|
619
|
-
const allBuiltInToolsMap = await createAllTools(cwd, sessionContext, {
|
|
620
|
-
lspFormatOnWrite: settingsManager.getLspFormatOnWrite(),
|
|
621
|
-
lspDiagnosticsOnWrite: settingsManager.getLspDiagnosticsOnWrite(),
|
|
622
|
-
lspDiagnosticsOnEdit: settingsManager.getLspDiagnosticsOnEdit(),
|
|
623
|
-
editFuzzyMatch: settingsManager.getEditFuzzyMatch(),
|
|
624
|
-
readAutoResizeImages: settingsManager.getImageAutoResize(),
|
|
625
|
-
});
|
|
626
|
-
time("createAllTools");
|
|
627
615
|
|
|
628
|
-
const
|
|
629
|
-
|
|
630
|
-
: baseCodingToolNames;
|
|
631
|
-
const initialActiveBuiltInTools = initialActiveToolNames.map((name) => allBuiltInToolsMap[name]);
|
|
616
|
+
const builtinTools = await createTools(toolSession, options.toolNames);
|
|
617
|
+
time("createAllTools");
|
|
632
618
|
|
|
633
619
|
// Discover MCP tools from .mcp.json files
|
|
634
620
|
let mcpManager: MCPManager | undefined;
|
|
@@ -815,61 +801,30 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
815
801
|
hasQueuedMessages: () => session.queuedMessageCount > 0,
|
|
816
802
|
}));
|
|
817
803
|
|
|
804
|
+
// All built-in tools are active (conditional tools like git/ask return null from factory if disabled)
|
|
818
805
|
const toolRegistry = new Map<string, AgentTool>();
|
|
819
|
-
for (const
|
|
820
|
-
toolRegistry.set(name, tool as AgentTool);
|
|
806
|
+
for (const tool of builtinTools) {
|
|
807
|
+
toolRegistry.set(tool.name, tool as AgentTool);
|
|
821
808
|
}
|
|
822
|
-
for (const tool of wrappedExtensionTools
|
|
809
|
+
for (const tool of wrappedExtensionTools) {
|
|
823
810
|
toolRegistry.set(tool.name, tool);
|
|
824
811
|
}
|
|
825
|
-
|
|
826
|
-
let activeToolsArray: Tool[] = [...initialActiveBuiltInTools, ...wrappedExtensionTools];
|
|
827
|
-
|
|
828
|
-
if (rulebookRules.length > 0) {
|
|
829
|
-
activeToolsArray.push(createRulebookTool(rulebookRules));
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
if (options.explicitTools) {
|
|
833
|
-
const explicitSet = new Set(options.explicitTools);
|
|
834
|
-
activeToolsArray = activeToolsArray.filter((tool) => !tool.hidden || explicitSet.has(tool.name));
|
|
835
|
-
} else {
|
|
836
|
-
activeToolsArray = activeToolsArray.filter((tool) => !tool.hidden);
|
|
837
|
-
}
|
|
838
|
-
time("combineTools");
|
|
839
|
-
|
|
840
|
-
if (settingsManager.getBashInterceptorEnabled()) {
|
|
841
|
-
activeToolsArray = applyBashInterception(activeToolsArray);
|
|
842
|
-
}
|
|
843
|
-
time("applyBashInterception");
|
|
844
|
-
|
|
845
|
-
let wrappedToolRegistry: Map<string, AgentTool> | undefined;
|
|
846
812
|
if (extensionRunner) {
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
const wrappedAllTools = wrapToolsWithExtensions(allRegistryTools, extensionRunner);
|
|
850
|
-
wrappedToolRegistry = new Map<string, AgentTool>();
|
|
851
|
-
for (const tool of wrappedAllTools) {
|
|
852
|
-
wrappedToolRegistry.set(tool.name, tool);
|
|
813
|
+
for (const tool of toolRegistry.values()) {
|
|
814
|
+
toolRegistry.set(tool.name, wrapToolWithExtensions(tool, extensionRunner));
|
|
853
815
|
}
|
|
854
816
|
}
|
|
817
|
+
time("combineTools");
|
|
855
818
|
|
|
856
|
-
const rebuildSystemPrompt = (toolNames: string[]): string => {
|
|
857
|
-
|
|
858
|
-
const extraToolDescriptions = toolNames
|
|
859
|
-
.filter((name) => !(name in allBuiltInToolsMap))
|
|
860
|
-
.map((name) => {
|
|
861
|
-
const tool = toolRegistry.get(name);
|
|
862
|
-
if (!tool) return null;
|
|
863
|
-
return { name, description: tool.description || tool.label || "Custom tool" };
|
|
864
|
-
})
|
|
865
|
-
.filter((tool): tool is { name: string; description: string } => tool !== null);
|
|
819
|
+
const rebuildSystemPrompt = (toolNames: string[], tools: Map<string, AgentTool>): string => {
|
|
820
|
+
toolContextStore.setToolNames(toolNames);
|
|
866
821
|
const defaultPrompt = buildSystemPromptInternal({
|
|
867
822
|
cwd,
|
|
868
823
|
skills,
|
|
869
824
|
contextFiles,
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
825
|
+
tools,
|
|
826
|
+
toolNames,
|
|
827
|
+
rules: rulebookRules,
|
|
873
828
|
skillsSettings: settingsManager.getSkillsSettings(),
|
|
874
829
|
});
|
|
875
830
|
|
|
@@ -881,9 +836,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
881
836
|
cwd,
|
|
882
837
|
skills,
|
|
883
838
|
contextFiles,
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
839
|
+
tools,
|
|
840
|
+
toolNames,
|
|
841
|
+
rules: rulebookRules,
|
|
887
842
|
skillsSettings: settingsManager.getSkillsSettings(),
|
|
888
843
|
customPrompt: options.systemPrompt,
|
|
889
844
|
});
|
|
@@ -891,12 +846,15 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
891
846
|
return options.systemPrompt(defaultPrompt);
|
|
892
847
|
};
|
|
893
848
|
|
|
894
|
-
const systemPrompt = rebuildSystemPrompt(
|
|
849
|
+
const systemPrompt = rebuildSystemPrompt(Array.from(toolRegistry.keys()), toolRegistry);
|
|
895
850
|
time("buildSystemPrompt");
|
|
896
851
|
|
|
897
852
|
const promptTemplates = options.promptTemplates ?? (await discoverPromptTemplates(cwd, agentDir));
|
|
898
853
|
time("discoverPromptTemplates");
|
|
899
854
|
|
|
855
|
+
const slashCommands = options.slashCommands ?? discoverSlashCommands(cwd);
|
|
856
|
+
time("discoverSlashCommands");
|
|
857
|
+
|
|
900
858
|
const baseSetUIContext = extensionsResult.setUIContext;
|
|
901
859
|
extensionsResult.setUIContext = (uiContext, hasUI) => {
|
|
902
860
|
baseSetUIContext(uiContext, hasUI);
|
|
@@ -908,7 +866,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
908
866
|
systemPrompt,
|
|
909
867
|
model,
|
|
910
868
|
thinkingLevel,
|
|
911
|
-
tools:
|
|
869
|
+
tools: Array.from(toolRegistry.values()),
|
|
912
870
|
},
|
|
913
871
|
convertToLlm,
|
|
914
872
|
transformContext: extensionRunner
|
|
@@ -951,11 +909,12 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
951
909
|
settingsManager,
|
|
952
910
|
scopedModels: options.scopedModels,
|
|
953
911
|
promptTemplates,
|
|
912
|
+
slashCommands,
|
|
954
913
|
extensionRunner,
|
|
955
914
|
customCommands: customCommandsResult.commands,
|
|
956
915
|
skillsSettings: settingsManager.getSkillsSettings(),
|
|
957
916
|
modelRegistry,
|
|
958
|
-
toolRegistry
|
|
917
|
+
toolRegistry,
|
|
959
918
|
rebuildSystemPrompt,
|
|
960
919
|
ttsrManager,
|
|
961
920
|
});
|