@oh-my-pi/pi-coding-agent 1.340.0 → 2.0.1337
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 +115 -1
- package/README.md +1 -1
- package/examples/custom-tools/subagent/index.ts +1 -1
- package/package.json +5 -3
- package/src/cli/args.ts +13 -6
- package/src/cli/file-processor.ts +3 -3
- package/src/cli/list-models.ts +2 -2
- package/src/cli/plugin-cli.ts +1 -1
- package/src/cli/session-picker.ts +2 -2
- package/src/cli.ts +1 -1
- package/src/config.ts +3 -3
- package/src/core/agent-session.ts +189 -29
- package/src/core/bash-executor.ts +50 -10
- package/src/core/compaction/branch-summarization.ts +5 -5
- package/src/core/compaction/compaction.ts +3 -3
- package/src/core/compaction/index.ts +3 -3
- package/src/core/custom-commands/bundled/review/index.ts +156 -0
- package/src/core/custom-commands/index.ts +15 -0
- package/src/core/custom-commands/loader.ts +232 -0
- package/src/core/custom-commands/types.ts +112 -0
- package/src/core/custom-tools/index.ts +3 -3
- package/src/core/custom-tools/loader.ts +10 -8
- package/src/core/custom-tools/types.ts +11 -6
- package/src/core/custom-tools/wrapper.ts +2 -1
- package/src/core/exec.ts +22 -12
- package/src/core/export-html/index.ts +5 -5
- package/src/core/file-mentions.ts +54 -0
- package/src/core/hooks/index.ts +5 -5
- package/src/core/hooks/loader.ts +21 -16
- package/src/core/hooks/runner.ts +6 -6
- package/src/core/hooks/tool-wrapper.ts +2 -2
- package/src/core/hooks/types.ts +12 -15
- package/src/core/index.ts +6 -6
- package/src/core/logger.ts +112 -0
- package/src/core/mcp/client.ts +3 -3
- package/src/core/mcp/config.ts +1 -1
- package/src/core/mcp/index.ts +12 -12
- package/src/core/mcp/loader.ts +2 -2
- package/src/core/mcp/manager.ts +6 -6
- package/src/core/mcp/tool-bridge.ts +3 -3
- package/src/core/mcp/transports/http.ts +1 -1
- package/src/core/mcp/transports/index.ts +2 -2
- package/src/core/mcp/transports/stdio.ts +1 -1
- package/src/core/messages.ts +22 -0
- package/src/core/model-registry.ts +2 -2
- package/src/core/model-resolver.ts +103 -2
- package/src/core/plugins/doctor.ts +1 -1
- package/src/core/plugins/index.ts +6 -6
- package/src/core/plugins/installer.ts +4 -4
- package/src/core/plugins/loader.ts +4 -9
- package/src/core/plugins/manager.ts +5 -5
- package/src/core/plugins/paths.ts +3 -3
- package/src/core/sdk.ts +127 -52
- package/src/core/session-manager.ts +123 -20
- package/src/core/settings-manager.ts +106 -22
- package/src/core/skills.ts +5 -5
- package/src/core/slash-commands.ts +60 -45
- package/src/core/system-prompt.ts +6 -6
- package/src/core/title-generator.ts +94 -0
- package/src/core/tools/bash.ts +33 -157
- package/src/core/tools/context.ts +2 -2
- package/src/core/tools/edit-diff.ts +5 -5
- package/src/core/tools/edit.ts +60 -9
- package/src/core/tools/exa/company.ts +3 -3
- package/src/core/tools/exa/index.ts +16 -17
- package/src/core/tools/exa/linkedin.ts +3 -3
- package/src/core/tools/exa/mcp-client.ts +9 -9
- package/src/core/tools/exa/render.ts +5 -5
- package/src/core/tools/exa/researcher.ts +3 -3
- package/src/core/tools/exa/search.ts +6 -5
- package/src/core/tools/exa/types.ts +5 -6
- package/src/core/tools/exa/websets.ts +3 -3
- package/src/core/tools/find.ts +3 -3
- package/src/core/tools/grep.ts +6 -5
- package/src/core/tools/index.ts +114 -40
- package/src/core/tools/ls.ts +4 -4
- package/src/core/tools/lsp/client.ts +204 -108
- package/src/core/tools/lsp/config.ts +709 -35
- package/src/core/tools/lsp/edits.ts +2 -2
- package/src/core/tools/lsp/index.ts +432 -30
- package/src/core/tools/lsp/render.ts +2 -2
- package/src/core/tools/lsp/rust-analyzer.ts +3 -3
- package/src/core/tools/lsp/types.ts +5 -0
- package/src/core/tools/lsp/utils.ts +1 -1
- package/src/core/tools/notebook.ts +1 -1
- package/src/core/tools/output.ts +175 -0
- package/src/core/tools/read.ts +7 -7
- package/src/core/tools/renderers.ts +92 -13
- package/src/core/tools/review.ts +268 -0
- package/src/core/tools/task/agents.ts +1 -1
- package/src/core/tools/task/bundled-agents/explore.md +1 -1
- package/src/core/tools/task/bundled-agents/reviewer.md +53 -38
- package/src/core/tools/task/discovery.ts +2 -2
- package/src/core/tools/task/executor.ts +145 -28
- package/src/core/tools/task/index.ts +78 -30
- package/src/core/tools/task/model-resolver.ts +72 -13
- package/src/core/tools/task/parallel.ts +1 -1
- package/src/core/tools/task/render.ts +219 -30
- package/src/core/tools/task/subprocess-tool-registry.ts +89 -0
- package/src/core/tools/task/types.ts +36 -2
- package/src/core/tools/web-fetch.ts +5 -3
- package/src/core/tools/web-search/auth.ts +1 -1
- package/src/core/tools/web-search/index.ts +17 -15
- package/src/core/tools/web-search/providers/anthropic.ts +2 -2
- package/src/core/tools/web-search/providers/exa.ts +3 -5
- package/src/core/tools/web-search/providers/perplexity.ts +1 -1
- package/src/core/tools/web-search/render.ts +3 -3
- package/src/core/tools/write.ts +70 -7
- package/src/index.ts +33 -17
- package/src/main.ts +60 -34
- package/src/migrations.ts +3 -3
- package/src/modes/index.ts +5 -5
- package/src/modes/interactive/components/armin.ts +1 -1
- package/src/modes/interactive/components/assistant-message.ts +1 -1
- package/src/modes/interactive/components/bash-execution.ts +4 -4
- package/src/modes/interactive/components/bordered-loader.ts +2 -2
- package/src/modes/interactive/components/branch-summary-message.ts +2 -2
- package/src/modes/interactive/components/compaction-summary-message.ts +2 -2
- package/src/modes/interactive/components/diff.ts +1 -1
- package/src/modes/interactive/components/dynamic-border.ts +1 -1
- package/src/modes/interactive/components/footer.ts +5 -5
- package/src/modes/interactive/components/hook-editor.ts +2 -2
- package/src/modes/interactive/components/hook-input.ts +2 -2
- package/src/modes/interactive/components/hook-message.ts +3 -3
- package/src/modes/interactive/components/hook-selector.ts +2 -2
- package/src/modes/interactive/components/model-selector.ts +341 -41
- package/src/modes/interactive/components/oauth-selector.ts +3 -3
- package/src/modes/interactive/components/plugin-settings.ts +4 -4
- package/src/modes/interactive/components/queue-mode-selector.ts +2 -2
- package/src/modes/interactive/components/session-selector.ts +24 -11
- package/src/modes/interactive/components/settings-defs.ts +51 -3
- package/src/modes/interactive/components/settings-selector.ts +13 -16
- package/src/modes/interactive/components/show-images-selector.ts +2 -2
- package/src/modes/interactive/components/theme-selector.ts +2 -2
- package/src/modes/interactive/components/thinking-selector.ts +2 -2
- package/src/modes/interactive/components/tool-execution.ts +44 -8
- package/src/modes/interactive/components/tree-selector.ts +5 -5
- package/src/modes/interactive/components/user-message-selector.ts +2 -2
- package/src/modes/interactive/components/user-message.ts +1 -1
- package/src/modes/interactive/components/welcome.ts +42 -5
- package/src/modes/interactive/interactive-mode.ts +169 -48
- package/src/modes/interactive/theme/theme.ts +8 -7
- package/src/modes/print-mode.ts +4 -3
- package/src/modes/rpc/rpc-client.ts +4 -4
- package/src/modes/rpc/rpc-mode.ts +21 -11
- package/src/modes/rpc/rpc-types.ts +3 -3
- package/src/utils/changelog.ts +2 -2
- package/src/utils/clipboard.ts +1 -1
- package/src/utils/shell-snapshot.ts +218 -0
- package/src/utils/shell.ts +93 -13
- package/src/utils/tools-manager.ts +1 -1
- package/examples/custom-tools/subagent/agents/reviewer.md +0 -35
- package/src/core/tools/exa/logger.ts +0 -56
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { basename, join } from "node:path";
|
|
1
3
|
import type { AgentState } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { getResolvedThemeColors, getThemeExportColors } from "../../modes/interactive/theme/theme.js";
|
|
6
|
-
import { SessionManager } from "../session-manager.js";
|
|
4
|
+
import { APP_NAME, getExportTemplateDir } from "../../config";
|
|
5
|
+
import { getResolvedThemeColors, getThemeExportColors } from "../../modes/interactive/theme/theme";
|
|
6
|
+
import { SessionManager } from "../session-manager";
|
|
7
7
|
|
|
8
8
|
// Cached minified assets (populated on first use)
|
|
9
9
|
let cachedTemplate: string | null = null;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-read file mentions from user prompts.
|
|
3
|
+
*
|
|
4
|
+
* When users reference files with @path syntax (e.g., "@src/foo.ts"),
|
|
5
|
+
* we automatically inject the file contents as a FileMentionMessage
|
|
6
|
+
* so the agent doesn't need to read them manually.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
10
|
+
import type { FileMentionMessage } from "./messages";
|
|
11
|
+
import { createReadTool } from "./tools/read";
|
|
12
|
+
|
|
13
|
+
/** Regex to match @filepath patterns in text */
|
|
14
|
+
const FILE_MENTION_REGEX = /@((?:[^\s@]+\/)*[^\s@]+\.[a-zA-Z0-9]+)/g;
|
|
15
|
+
|
|
16
|
+
/** Extract all @filepath mentions from text */
|
|
17
|
+
export function extractFileMentions(text: string): string[] {
|
|
18
|
+
const matches = [...text.matchAll(FILE_MENTION_REGEX)];
|
|
19
|
+
return [...new Set(matches.map((m) => m[1]))];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Generate a FileMentionMessage containing the contents of mentioned files.
|
|
24
|
+
* Returns empty array if no files could be read.
|
|
25
|
+
*/
|
|
26
|
+
export async function generateFileMentionMessages(filePaths: string[], cwd: string): Promise<AgentMessage[]> {
|
|
27
|
+
if (filePaths.length === 0) return [];
|
|
28
|
+
|
|
29
|
+
const readTool = createReadTool(cwd);
|
|
30
|
+
const files: FileMentionMessage["files"] = [];
|
|
31
|
+
|
|
32
|
+
for (const filePath of filePaths) {
|
|
33
|
+
try {
|
|
34
|
+
const result = await readTool.execute("auto-read", { path: filePath });
|
|
35
|
+
const textContent = result.content.find((c) => c.type === "text");
|
|
36
|
+
if (textContent && textContent.type === "text") {
|
|
37
|
+
const lineCount = textContent.text.split("\n").length;
|
|
38
|
+
files.push({ path: filePath, content: textContent.text, lineCount });
|
|
39
|
+
}
|
|
40
|
+
} catch {
|
|
41
|
+
// File doesn't exist or isn't readable - skip silently
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (files.length === 0) return [];
|
|
46
|
+
|
|
47
|
+
const message: FileMentionMessage = {
|
|
48
|
+
role: "fileMention",
|
|
49
|
+
files,
|
|
50
|
+
timestamp: Date.now(),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return [message];
|
|
54
|
+
}
|
package/src/core/hooks/index.ts
CHANGED
|
@@ -9,8 +9,8 @@ export {
|
|
|
9
9
|
type NavigateTreeHandler,
|
|
10
10
|
type NewSessionHandler,
|
|
11
11
|
type SendMessageHandler,
|
|
12
|
-
} from "./loader
|
|
13
|
-
export { execCommand, HookRunner, type HookErrorListener } from "./runner
|
|
14
|
-
export { wrapToolsWithHooks, wrapToolWithHooks } from "./tool-wrapper
|
|
15
|
-
export * from "./types
|
|
16
|
-
export type { ReadonlySessionManager } from "../session-manager
|
|
12
|
+
} from "./loader";
|
|
13
|
+
export { execCommand, HookRunner, type HookErrorListener } from "./runner";
|
|
14
|
+
export { wrapToolsWithHooks, wrapToolWithHooks } from "./tool-wrapper";
|
|
15
|
+
export * from "./types";
|
|
16
|
+
export type { ReadonlySessionManager } from "../session-manager";
|
package/src/core/hooks/loader.ts
CHANGED
|
@@ -6,13 +6,14 @@ import * as fs from "node:fs";
|
|
|
6
6
|
import * as os from "node:os";
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import * as typebox from "@sinclair/typebox";
|
|
9
|
-
import { getAgentDir } from "../../config
|
|
10
|
-
import * as piCodingAgent from "../../index
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
9
|
+
import { getAgentDir } from "../../config";
|
|
10
|
+
import * as piCodingAgent from "../../index";
|
|
11
|
+
import { logger } from "../logger";
|
|
12
|
+
import type { HookMessage } from "../messages";
|
|
13
|
+
import { getAllPluginHookPaths } from "../plugins/loader";
|
|
14
|
+
import type { SessionManager } from "../session-manager";
|
|
15
|
+
import { execCommand } from "./runner";
|
|
16
|
+
import type { ExecOptions, HookAPI, HookFactory, HookMessageRenderer, RegisteredCommand } from "./types";
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Generic handler function type.
|
|
@@ -131,12 +132,8 @@ function createHookAPI(
|
|
|
131
132
|
setSendMessageHandler: (handler: SendMessageHandler) => void;
|
|
132
133
|
setAppendEntryHandler: (handler: AppendEntryHandler) => void;
|
|
133
134
|
} {
|
|
134
|
-
let sendMessageHandler: SendMessageHandler
|
|
135
|
-
|
|
136
|
-
};
|
|
137
|
-
let appendEntryHandler: AppendEntryHandler = () => {
|
|
138
|
-
// Default no-op until mode sets the handler
|
|
139
|
-
};
|
|
135
|
+
let sendMessageHandler: SendMessageHandler | null = null;
|
|
136
|
+
let appendEntryHandler: AppendEntryHandler | null = null;
|
|
140
137
|
const messageRenderers = new Map<string, HookMessageRenderer>();
|
|
141
138
|
const commands = new Map<string, RegisteredCommand>();
|
|
142
139
|
|
|
@@ -144,14 +141,21 @@ function createHookAPI(
|
|
|
144
141
|
// but the interface has specific overloads for type safety in hooks
|
|
145
142
|
const api = {
|
|
146
143
|
on(event: string, handler: HandlerFn): void {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
144
|
+
if (!handlers.has(event)) {
|
|
145
|
+
handlers.set(event, []);
|
|
146
|
+
}
|
|
147
|
+
handlers.get(event)!.push(handler);
|
|
150
148
|
},
|
|
151
149
|
sendMessage<T = unknown>(message: HookMessage<T>, triggerTurn?: boolean): void {
|
|
150
|
+
if (!sendMessageHandler) {
|
|
151
|
+
throw new Error("sendMessage handler not initialized");
|
|
152
|
+
}
|
|
152
153
|
sendMessageHandler(message, triggerTurn);
|
|
153
154
|
},
|
|
154
155
|
appendEntry<T = unknown>(customType: string, data?: T): void {
|
|
156
|
+
if (!appendEntryHandler) {
|
|
157
|
+
throw new Error("appendEntry handler not initialized");
|
|
158
|
+
}
|
|
155
159
|
appendEntryHandler(customType, data);
|
|
156
160
|
},
|
|
157
161
|
registerMessageRenderer<T = unknown>(customType: string, renderer: HookMessageRenderer<T>): void {
|
|
@@ -163,6 +167,7 @@ function createHookAPI(
|
|
|
163
167
|
exec(command: string, args: string[], options?: ExecOptions) {
|
|
164
168
|
return execCommand(command, args, options?.cwd ?? cwd, options);
|
|
165
169
|
},
|
|
170
|
+
logger,
|
|
166
171
|
typebox,
|
|
167
172
|
pi: piCodingAgent,
|
|
168
173
|
} as HookAPI;
|
package/src/core/hooks/runner.ts
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
6
6
|
import type { Model } from "@oh-my-pi/pi-ai";
|
|
7
|
-
import { theme } from "../../modes/interactive/theme/theme
|
|
8
|
-
import type { ModelRegistry } from "../model-registry
|
|
9
|
-
import type { SessionManager } from "../session-manager
|
|
7
|
+
import { theme } from "../../modes/interactive/theme/theme";
|
|
8
|
+
import type { ModelRegistry } from "../model-registry";
|
|
9
|
+
import type { SessionManager } from "../session-manager";
|
|
10
10
|
import type {
|
|
11
11
|
AppendEntryHandler,
|
|
12
12
|
BranchHandler,
|
|
@@ -14,7 +14,7 @@ import type {
|
|
|
14
14
|
NavigateTreeHandler,
|
|
15
15
|
NewSessionHandler,
|
|
16
16
|
SendMessageHandler,
|
|
17
|
-
} from "./loader
|
|
17
|
+
} from "./loader";
|
|
18
18
|
import type {
|
|
19
19
|
BeforeAgentStartEvent,
|
|
20
20
|
BeforeAgentStartEventResult,
|
|
@@ -32,7 +32,7 @@ import type {
|
|
|
32
32
|
ToolCallEvent,
|
|
33
33
|
ToolCallEventResult,
|
|
34
34
|
ToolResultEventResult,
|
|
35
|
-
} from "./types
|
|
35
|
+
} from "./types";
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Listener for hook errors.
|
|
@@ -40,7 +40,7 @@ import type {
|
|
|
40
40
|
export type HookErrorListener = (error: HookError) => void;
|
|
41
41
|
|
|
42
42
|
// Re-export execCommand for backward compatibility
|
|
43
|
-
export { execCommand } from "../exec
|
|
43
|
+
export { execCommand } from "../exec";
|
|
44
44
|
|
|
45
45
|
/** No-op UI context used when no UI is available */
|
|
46
46
|
const noOpUIContext: HookUIContext = {
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type { AgentTool, AgentToolContext, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
6
|
-
import type { HookRunner } from "./runner
|
|
7
|
-
import type { ToolCallEventResult, ToolResultEventResult } from "./types
|
|
6
|
+
import type { HookRunner } from "./runner";
|
|
7
|
+
import type { ToolCallEventResult, ToolResultEventResult } from "./types";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Wrap a tool with hook callbacks.
|
package/src/core/hooks/types.ts
CHANGED
|
@@ -8,30 +8,25 @@
|
|
|
8
8
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
9
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
|
-
import type { Theme } from "../../modes/interactive/theme/theme
|
|
12
|
-
import type { CompactionPreparation, CompactionResult } from "../compaction/index
|
|
13
|
-
import type { ExecOptions, ExecResult } from "../exec
|
|
14
|
-
import type {
|
|
15
|
-
import type {
|
|
11
|
+
import type { Theme } from "../../modes/interactive/theme/theme";
|
|
12
|
+
import type { CompactionPreparation, CompactionResult } from "../compaction/index";
|
|
13
|
+
import type { ExecOptions, ExecResult } from "../exec";
|
|
14
|
+
import type { Logger } from "../logger";
|
|
15
|
+
import type { HookMessage } from "../messages";
|
|
16
|
+
import type { ModelRegistry } from "../model-registry";
|
|
16
17
|
import type {
|
|
17
18
|
BranchSummaryEntry,
|
|
18
19
|
CompactionEntry,
|
|
19
20
|
ReadonlySessionManager,
|
|
20
21
|
SessionEntry,
|
|
21
22
|
SessionManager,
|
|
22
|
-
} from "../session-manager
|
|
23
|
+
} from "../session-manager";
|
|
23
24
|
|
|
24
|
-
import type { EditToolDetails } from "../tools/edit
|
|
25
|
-
import type {
|
|
26
|
-
BashToolDetails,
|
|
27
|
-
FindToolDetails,
|
|
28
|
-
GrepToolDetails,
|
|
29
|
-
LsToolDetails,
|
|
30
|
-
ReadToolDetails,
|
|
31
|
-
} from "../tools/index.js";
|
|
25
|
+
import type { EditToolDetails } from "../tools/edit";
|
|
26
|
+
import type { BashToolDetails, FindToolDetails, GrepToolDetails, LsToolDetails, ReadToolDetails } from "../tools/index";
|
|
32
27
|
|
|
33
28
|
// Re-export for backward compatibility
|
|
34
|
-
export type { ExecOptions, ExecResult } from "../exec
|
|
29
|
+
export type { ExecOptions, ExecResult } from "../exec";
|
|
35
30
|
|
|
36
31
|
/**
|
|
37
32
|
* UI context for hooks to request interactive UI from the harness.
|
|
@@ -747,6 +742,8 @@ export interface HookAPI {
|
|
|
747
742
|
*/
|
|
748
743
|
exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
|
|
749
744
|
|
|
745
|
+
/** File logger for error/warning/debug messages */
|
|
746
|
+
logger: Logger;
|
|
750
747
|
/** Injected @sinclair/typebox module */
|
|
751
748
|
typebox: typeof import("@sinclair/typebox");
|
|
752
749
|
/** Injected pi-coding-agent exports */
|
package/src/core/index.ts
CHANGED
|
@@ -10,9 +10,9 @@ export {
|
|
|
10
10
|
type ModelCycleResult,
|
|
11
11
|
type PromptOptions,
|
|
12
12
|
type SessionStats,
|
|
13
|
-
} from "./agent-session
|
|
14
|
-
export { type BashExecutorOptions, type BashResult, executeBash } from "./bash-executor
|
|
15
|
-
export type { CompactionResult } from "./compaction/index
|
|
13
|
+
} from "./agent-session";
|
|
14
|
+
export { type BashExecutorOptions, type BashResult, executeBash } from "./bash-executor";
|
|
15
|
+
export type { CompactionResult } from "./compaction/index";
|
|
16
16
|
export {
|
|
17
17
|
type CustomTool,
|
|
18
18
|
type CustomToolAPI,
|
|
@@ -24,7 +24,7 @@ export {
|
|
|
24
24
|
type LoadedCustomTool,
|
|
25
25
|
loadCustomTools,
|
|
26
26
|
type RenderResultOptions,
|
|
27
|
-
} from "./custom-tools/index
|
|
27
|
+
} from "./custom-tools/index";
|
|
28
28
|
export {
|
|
29
29
|
type HookAPI,
|
|
30
30
|
type HookContext,
|
|
@@ -34,7 +34,7 @@ export {
|
|
|
34
34
|
HookRunner,
|
|
35
35
|
type HookUIContext,
|
|
36
36
|
loadHooks,
|
|
37
|
-
} from "./hooks/index
|
|
37
|
+
} from "./hooks/index";
|
|
38
38
|
export {
|
|
39
39
|
createMCPManager,
|
|
40
40
|
discoverAndLoadMCPTools,
|
|
@@ -49,4 +49,4 @@ export {
|
|
|
49
49
|
type MCPToolDetails,
|
|
50
50
|
type MCPToolsLoadResult,
|
|
51
51
|
type MCPTransport,
|
|
52
|
-
} from "./mcp/index
|
|
52
|
+
} from "./mcp/index";
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized file logger for pi.
|
|
3
|
+
*
|
|
4
|
+
* Logs to ~/.pi/logs/ with size-based rotation, supporting concurrent pi instances.
|
|
5
|
+
* Each log entry includes process.pid for traceability.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import winston from "winston";
|
|
12
|
+
import DailyRotateFile from "winston-daily-rotate-file";
|
|
13
|
+
import { CONFIG_DIR_NAME } from "../config";
|
|
14
|
+
|
|
15
|
+
/** Get the logs directory (~/.pi/logs/) */
|
|
16
|
+
function getLogsDir(): string {
|
|
17
|
+
return join(homedir(), CONFIG_DIR_NAME, "logs");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Ensure logs directory exists */
|
|
21
|
+
function ensureLogsDir(): string {
|
|
22
|
+
const logsDir = getLogsDir();
|
|
23
|
+
if (!existsSync(logsDir)) {
|
|
24
|
+
mkdirSync(logsDir, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
return logsDir;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Custom format that includes pid and flattens metadata */
|
|
30
|
+
const logFormat = winston.format.combine(
|
|
31
|
+
winston.format.timestamp({ format: "YYYY-MM-DDTHH:mm:ss.SSSZ" }),
|
|
32
|
+
winston.format.printf(({ timestamp, level, message, ...meta }) => {
|
|
33
|
+
const entry: Record<string, unknown> = {
|
|
34
|
+
timestamp,
|
|
35
|
+
level,
|
|
36
|
+
pid: process.pid,
|
|
37
|
+
message,
|
|
38
|
+
};
|
|
39
|
+
// Flatten metadata into entry
|
|
40
|
+
for (const [key, value] of Object.entries(meta)) {
|
|
41
|
+
if (key !== "level" && key !== "timestamp" && key !== "message") {
|
|
42
|
+
entry[key] = value;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return JSON.stringify(entry);
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
/** Size-based rotating file transport */
|
|
50
|
+
const fileTransport = new DailyRotateFile({
|
|
51
|
+
dirname: ensureLogsDir(),
|
|
52
|
+
filename: "pi.%DATE%.log",
|
|
53
|
+
datePattern: "YYYY-MM-DD",
|
|
54
|
+
maxSize: "10m",
|
|
55
|
+
maxFiles: 5,
|
|
56
|
+
zippedArchive: true,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
/** The winston logger instance */
|
|
60
|
+
const winstonLogger = winston.createLogger({
|
|
61
|
+
level: "debug",
|
|
62
|
+
format: logFormat,
|
|
63
|
+
transports: [fileTransport],
|
|
64
|
+
// Don't exit on error - logging failures shouldn't crash the app
|
|
65
|
+
exitOnError: false,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
/** Logger type exposed to plugins and internal code */
|
|
69
|
+
export interface Logger {
|
|
70
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
71
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
72
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Centralized logger for pi.
|
|
77
|
+
*
|
|
78
|
+
* Logs to ~/.pi/logs/pi.YYYY-MM-DD.log with size-based rotation.
|
|
79
|
+
* Safe for concurrent access from multiple pi instances.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* import { logger } from "../core/logger";
|
|
84
|
+
*
|
|
85
|
+
* logger.error("MCP request failed", { url, method });
|
|
86
|
+
* logger.warn("Theme file invalid, using fallback", { path });
|
|
87
|
+
* logger.debug("LSP fallback triggered", { reason });
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export const logger: Logger = {
|
|
91
|
+
error(message: string, context?: Record<string, unknown>): void {
|
|
92
|
+
try {
|
|
93
|
+
winstonLogger.error(message, context);
|
|
94
|
+
} catch {
|
|
95
|
+
// Silently ignore logging failures
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
warn(message: string, context?: Record<string, unknown>): void {
|
|
99
|
+
try {
|
|
100
|
+
winstonLogger.warn(message, context);
|
|
101
|
+
} catch {
|
|
102
|
+
// Silently ignore logging failures
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
debug(message: string, context?: Record<string, unknown>): void {
|
|
106
|
+
try {
|
|
107
|
+
winstonLogger.debug(message, context);
|
|
108
|
+
} catch {
|
|
109
|
+
// Silently ignore logging failures
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
};
|
package/src/core/mcp/client.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Handles connection initialization, tool listing, and tool calling.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { createHttpTransport } from "./transports/http
|
|
8
|
-
import { createStdioTransport } from "./transports/stdio
|
|
7
|
+
import { createHttpTransport } from "./transports/http";
|
|
8
|
+
import { createStdioTransport } from "./transports/stdio";
|
|
9
9
|
import type {
|
|
10
10
|
MCPHttpServerConfig,
|
|
11
11
|
MCPInitializeParams,
|
|
@@ -20,7 +20,7 @@ import type {
|
|
|
20
20
|
MCPToolDefinition,
|
|
21
21
|
MCPToolsListResult,
|
|
22
22
|
MCPTransport,
|
|
23
|
-
} from "./types
|
|
23
|
+
} from "./types";
|
|
24
24
|
|
|
25
25
|
/** MCP protocol version we support */
|
|
26
26
|
const PROTOCOL_VERSION = "2025-03-26";
|
package/src/core/mcp/config.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { existsSync, readFileSync } from "node:fs";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
10
|
import { join } from "node:path";
|
|
11
|
-
import type { MCPConfigFile, MCPServerConfig } from "./types
|
|
11
|
+
import type { MCPConfigFile, MCPServerConfig } from "./types";
|
|
12
12
|
|
|
13
13
|
/** Environment variable expansion pattern: ${VAR} or ${VAR:-default} */
|
|
14
14
|
const ENV_VAR_PATTERN = /\$\{([^}:]+)(?::-([^}]*))?\}/g;
|
package/src/core/mcp/index.ts
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
// Client
|
|
9
|
-
export { callTool, connectToServer, disconnectServer, listTools, serverSupportsTools } from "./client
|
|
9
|
+
export { callTool, connectToServer, disconnectServer, listTools, serverSupportsTools } from "./client";
|
|
10
10
|
|
|
11
11
|
// Config
|
|
12
|
-
export type { ExaFilterResult, LoadMCPConfigsOptions, LoadMCPConfigsResult } from "./config
|
|
12
|
+
export type { ExaFilterResult, LoadMCPConfigsOptions, LoadMCPConfigsResult } from "./config";
|
|
13
13
|
export {
|
|
14
14
|
expandEnvVars,
|
|
15
15
|
extractExaApiKey,
|
|
@@ -20,19 +20,19 @@ export {
|
|
|
20
20
|
loadMCPConfigFile,
|
|
21
21
|
mergeMCPConfigs,
|
|
22
22
|
validateServerConfig,
|
|
23
|
-
} from "./config
|
|
23
|
+
} from "./config";
|
|
24
24
|
// Loader (for SDK integration)
|
|
25
|
-
export type { MCPToolsLoadOptions, MCPToolsLoadResult } from "./loader
|
|
26
|
-
export { discoverAndLoadMCPTools } from "./loader
|
|
25
|
+
export type { MCPToolsLoadOptions, MCPToolsLoadResult } from "./loader";
|
|
26
|
+
export { discoverAndLoadMCPTools } from "./loader";
|
|
27
27
|
// Manager
|
|
28
|
-
export type { MCPDiscoverOptions, MCPLoadResult } from "./manager
|
|
29
|
-
export { createMCPManager, MCPManager } from "./manager
|
|
28
|
+
export type { MCPDiscoverOptions, MCPLoadResult } from "./manager";
|
|
29
|
+
export { createMCPManager, MCPManager } from "./manager";
|
|
30
30
|
// Tool bridge
|
|
31
|
-
export type { MCPToolDetails } from "./tool-bridge
|
|
32
|
-
export { createMCPTool, createMCPToolName, createMCPTools, parseMCPToolName } from "./tool-bridge
|
|
31
|
+
export type { MCPToolDetails } from "./tool-bridge";
|
|
32
|
+
export { createMCPTool, createMCPToolName, createMCPTools, parseMCPToolName } from "./tool-bridge";
|
|
33
33
|
// Transports
|
|
34
|
-
export { createHttpTransport, HttpTransport } from "./transports/http
|
|
35
|
-
export { createStdioTransport, StdioTransport } from "./transports/stdio
|
|
34
|
+
export { createHttpTransport, HttpTransport } from "./transports/http";
|
|
35
|
+
export { createStdioTransport, StdioTransport } from "./transports/stdio";
|
|
36
36
|
// Types
|
|
37
37
|
export type {
|
|
38
38
|
MCPConfigFile,
|
|
@@ -46,4 +46,4 @@ export type {
|
|
|
46
46
|
MCPToolDefinition,
|
|
47
47
|
MCPToolWithServer,
|
|
48
48
|
MCPTransport,
|
|
49
|
-
} from "./types
|
|
49
|
+
} from "./types";
|
package/src/core/mcp/loader.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Integrates MCP tool discovery with the custom tools system.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { LoadedCustomTool } from "../custom-tools/types
|
|
8
|
-
import { type MCPLoadResult, MCPManager } from "./manager
|
|
7
|
+
import type { LoadedCustomTool } from "../custom-tools/types";
|
|
8
|
+
import { type MCPLoadResult, MCPManager } from "./manager";
|
|
9
9
|
|
|
10
10
|
/** Result from loading MCP tools */
|
|
11
11
|
export interface MCPToolsLoadResult {
|
package/src/core/mcp/manager.ts
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { TSchema } from "@sinclair/typebox";
|
|
9
|
-
import type { CustomTool } from "../custom-tools/types
|
|
10
|
-
import { connectToServer, disconnectServer, listTools } from "./client
|
|
11
|
-
import { type LoadMCPConfigsOptions, loadAllMCPConfigs, validateServerConfig } from "./config
|
|
12
|
-
import type { MCPToolDetails } from "./tool-bridge
|
|
13
|
-
import { createMCPTools } from "./tool-bridge
|
|
14
|
-
import type { MCPServerConfig, MCPServerConnection } from "./types
|
|
9
|
+
import type { CustomTool } from "../custom-tools/types";
|
|
10
|
+
import { connectToServer, disconnectServer, listTools } from "./client";
|
|
11
|
+
import { type LoadMCPConfigsOptions, loadAllMCPConfigs, validateServerConfig } from "./config";
|
|
12
|
+
import type { MCPToolDetails } from "./tool-bridge";
|
|
13
|
+
import { createMCPTools } from "./tool-bridge";
|
|
14
|
+
import type { MCPServerConfig, MCPServerConnection } from "./types";
|
|
15
15
|
|
|
16
16
|
/** Result of loading MCP tools */
|
|
17
17
|
export interface MCPLoadResult {
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { TSchema } from "@sinclair/typebox";
|
|
8
|
-
import type { CustomTool, CustomToolResult } from "../custom-tools/types
|
|
9
|
-
import { callTool } from "./client
|
|
10
|
-
import type { MCPContent, MCPServerConnection, MCPToolDefinition } from "./types
|
|
8
|
+
import type { CustomTool, CustomToolResult } from "../custom-tools/types";
|
|
9
|
+
import { callTool } from "./client";
|
|
10
|
+
import type { MCPContent, MCPServerConnection, MCPToolDefinition } from "./types";
|
|
11
11
|
|
|
12
12
|
/** Details included in MCP tool results for rendering */
|
|
13
13
|
export interface MCPToolDetails {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Based on MCP spec 2025-03-26.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { JsonRpcResponse, MCPHttpServerConfig, MCPSseServerConfig, MCPTransport } from "../types
|
|
8
|
+
import type { JsonRpcResponse, MCPHttpServerConfig, MCPSseServerConfig, MCPTransport } from "../types";
|
|
9
9
|
|
|
10
10
|
/** Generate unique request ID */
|
|
11
11
|
function generateId(): string {
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
* MCP transport exports.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export { createHttpTransport, HttpTransport } from "./http
|
|
6
|
-
export { createStdioTransport, StdioTransport } from "./stdio
|
|
5
|
+
export { createHttpTransport, HttpTransport } from "./http";
|
|
6
|
+
export { createStdioTransport, StdioTransport } from "./stdio";
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { type Subprocess, spawn } from "bun";
|
|
9
|
-
import type { JsonRpcResponse, MCPStdioServerConfig, MCPTransport } from "../types
|
|
9
|
+
import type { JsonRpcResponse, MCPStdioServerConfig, MCPTransport } from "../types";
|
|
10
10
|
|
|
11
11
|
/** Generate unique request ID */
|
|
12
12
|
function generateId(): string {
|
package/src/core/messages.ts
CHANGED
|
@@ -64,6 +64,19 @@ export interface CompactionSummaryMessage {
|
|
|
64
64
|
timestamp: number;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Message type for auto-read file mentions via @filepath syntax.
|
|
69
|
+
*/
|
|
70
|
+
export interface FileMentionMessage {
|
|
71
|
+
role: "fileMention";
|
|
72
|
+
files: Array<{
|
|
73
|
+
path: string;
|
|
74
|
+
content: string;
|
|
75
|
+
lineCount: number;
|
|
76
|
+
}>;
|
|
77
|
+
timestamp: number;
|
|
78
|
+
}
|
|
79
|
+
|
|
67
80
|
// Extend CustomAgentMessages via declaration merging
|
|
68
81
|
declare module "@oh-my-pi/pi-agent-core" {
|
|
69
82
|
interface CustomAgentMessages {
|
|
@@ -71,6 +84,7 @@ declare module "@oh-my-pi/pi-agent-core" {
|
|
|
71
84
|
hookMessage: HookMessage;
|
|
72
85
|
branchSummary: BranchSummaryMessage;
|
|
73
86
|
compactionSummary: CompactionSummaryMessage;
|
|
87
|
+
fileMention: FileMentionMessage;
|
|
74
88
|
}
|
|
75
89
|
}
|
|
76
90
|
|
|
@@ -175,6 +189,14 @@ export function convertToLlm(messages: AgentMessage[]): Message[] {
|
|
|
175
189
|
],
|
|
176
190
|
timestamp: m.timestamp,
|
|
177
191
|
};
|
|
192
|
+
case "fileMention": {
|
|
193
|
+
const fileContents = m.files.map((f) => `<file path="${f.path}">\n${f.content}\n</file>`).join("\n\n");
|
|
194
|
+
return {
|
|
195
|
+
role: "user",
|
|
196
|
+
content: [{ type: "text" as const, text: `<system-reminder>\n${fileContents}\n</system-reminder>` }],
|
|
197
|
+
timestamp: m.timestamp,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
178
200
|
case "user":
|
|
179
201
|
case "assistant":
|
|
180
202
|
case "toolResult":
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Model registry - manages built-in and custom models, provides API key resolution.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
5
6
|
import {
|
|
6
7
|
type Api,
|
|
7
8
|
getGitHubCopilotBaseUrl,
|
|
@@ -13,8 +14,7 @@ import {
|
|
|
13
14
|
} from "@oh-my-pi/pi-ai";
|
|
14
15
|
import { type Static, Type } from "@sinclair/typebox";
|
|
15
16
|
import AjvModule from "ajv";
|
|
16
|
-
import {
|
|
17
|
-
import type { AuthStorage } from "./auth-storage.js";
|
|
17
|
+
import type { AuthStorage } from "./auth-storage";
|
|
18
18
|
|
|
19
19
|
const Ajv = (AjvModule as any).default || AjvModule;
|
|
20
20
|
|