@oh-my-pi/pi-coding-agent 15.0.1 → 15.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 +94 -1
- package/examples/custom-tools/README.md +11 -7
- package/examples/custom-tools/hello/index.ts +2 -2
- package/examples/extensions/README.md +19 -8
- package/examples/extensions/api-demo.ts +15 -19
- package/examples/extensions/hello.ts +5 -6
- package/examples/extensions/plan-mode.ts +1 -1
- package/examples/extensions/reload-runtime.ts +4 -3
- package/examples/extensions/with-deps/index.ts +4 -3
- package/examples/sdk/06-extensions.ts +4 -2
- package/package.json +8 -18
- package/src/autoresearch/tools/init-experiment.ts +38 -41
- package/src/autoresearch/tools/log-experiment.ts +32 -41
- package/src/autoresearch/tools/run-experiment.ts +3 -3
- package/src/autoresearch/tools/update-notes.ts +11 -11
- package/src/commands/commit.ts +10 -0
- package/src/commit/agentic/tools/analyze-file.ts +4 -4
- package/src/commit/agentic/tools/git-file-diff.ts +4 -4
- package/src/commit/agentic/tools/git-hunk.ts +5 -5
- package/src/commit/agentic/tools/git-overview.ts +4 -4
- package/src/commit/agentic/tools/propose-changelog.ts +13 -13
- package/src/commit/agentic/tools/propose-commit.ts +6 -6
- package/src/commit/agentic/tools/recent-commits.ts +3 -3
- package/src/commit/agentic/tools/schemas.ts +28 -28
- package/src/commit/agentic/tools/split-commit.ts +22 -21
- package/src/commit/analysis/summary.ts +4 -4
- package/src/commit/changelog/generate.ts +7 -11
- package/src/commit/shared-llm.ts +22 -34
- package/src/config/config-file.ts +35 -13
- package/src/config/model-registry.ts +40 -191
- package/src/config/models-config-schema.ts +166 -0
- package/src/config/settings-schema.ts +29 -0
- package/src/discovery/claude-plugins.ts +19 -7
- package/src/edit/index.ts +2 -2
- package/src/edit/modes/apply-patch.ts +7 -6
- package/src/edit/modes/patch.ts +18 -25
- package/src/edit/modes/replace.ts +18 -20
- package/src/eval/js/shared/rewrite-imports.ts +131 -10
- package/src/eval/py/executor.ts +233 -623
- package/src/eval/py/kernel.ts +27 -2
- package/src/eval/py/runner.py +42 -11
- package/src/eval/py/runtime.ts +1 -0
- package/src/exa/factory.ts +5 -4
- package/src/exa/mcp-client.ts +1 -1
- package/src/exa/researcher.ts +9 -20
- package/src/exa/search.ts +26 -52
- package/src/exa/types.ts +1 -1
- package/src/exa/websets.ts +54 -53
- package/src/exec/bash-executor.ts +2 -1
- package/src/extensibility/custom-commands/loader.ts +5 -3
- package/src/extensibility/custom-commands/types.ts +4 -2
- package/src/extensibility/custom-tools/loader.ts +5 -3
- package/src/extensibility/custom-tools/types.ts +7 -6
- package/src/extensibility/custom-tools/wrapper.ts +1 -1
- package/src/extensibility/extensions/get-commands-handler.ts +77 -0
- package/src/extensibility/extensions/loader.ts +7 -3
- package/src/extensibility/extensions/types.ts +9 -5
- package/src/extensibility/extensions/wrapper.ts +1 -2
- package/src/extensibility/hooks/loader.ts +3 -1
- package/src/extensibility/hooks/tool-wrapper.ts +1 -1
- package/src/extensibility/hooks/types.ts +4 -2
- package/src/extensibility/plugins/legacy-pi-compat.ts +78 -31
- package/src/extensibility/shared-events.ts +1 -1
- package/src/extensibility/typebox.ts +391 -0
- package/src/goals/tools/goal-tool.ts +6 -12
- package/src/hashline/input.ts +2 -1
- package/src/hashline/parser.ts +27 -3
- package/src/hashline/types.ts +4 -4
- package/src/hindsight/state.ts +2 -2
- package/src/index.ts +0 -2
- package/src/internal-urls/docs-index.generated.ts +15 -15
- package/src/internal-urls/router.ts +8 -0
- package/src/internal-urls/types.ts +21 -0
- package/src/lsp/config.ts +15 -6
- package/src/lsp/defaults.json +6 -2
- package/src/lsp/types.ts +30 -38
- package/src/mcp/manager.ts +1 -1
- package/src/mcp/tool-bridge.ts +1 -1
- package/src/modes/acp/acp-agent.ts +248 -50
- package/src/modes/components/session-observer-overlay.ts +12 -1
- package/src/modes/components/status-line/segments.ts +39 -4
- package/src/modes/controllers/command-controller.ts +27 -2
- package/src/modes/controllers/event-controller.ts +3 -4
- package/src/modes/controllers/extension-ui-controller.ts +3 -2
- package/src/modes/interactive-mode.ts +1 -1
- package/src/modes/rpc/host-tools.ts +1 -1
- package/src/modes/rpc/host-uris.ts +235 -0
- package/src/modes/rpc/rpc-client.ts +1 -1
- package/src/modes/rpc/rpc-mode.ts +27 -1
- package/src/modes/rpc/rpc-types.ts +58 -1
- package/src/modes/runtime-init.ts +2 -1
- package/src/modes/theme/defaults/dark-poimandres.json +1 -0
- package/src/modes/theme/defaults/light-poimandres.json +1 -0
- package/src/modes/theme/theme.ts +117 -117
- package/src/modes/types.ts +1 -1
- package/src/modes/utils/context-usage.ts +2 -2
- package/src/prompts/tools/github.md +4 -4
- package/src/prompts/tools/hashline.md +22 -26
- package/src/prompts/tools/read.md +55 -37
- package/src/sdk.ts +31 -8
- package/src/session/agent-session.ts +74 -104
- package/src/session/messages.ts +16 -51
- package/src/session/session-manager.ts +22 -2
- package/src/session/streaming-output.ts +16 -6
- package/src/task/discovery.ts +5 -2
- package/src/task/executor.ts +210 -87
- package/src/task/index.ts +15 -11
- package/src/task/render.ts +32 -5
- package/src/task/types.ts +54 -39
- package/src/tools/ask.ts +12 -12
- package/src/tools/ast-edit.ts +11 -15
- package/src/tools/ast-grep.ts +9 -10
- package/src/tools/bash-command-fixup.ts +47 -0
- package/src/tools/bash.ts +48 -38
- package/src/tools/browser/render.ts +2 -2
- package/src/tools/browser.ts +39 -53
- package/src/tools/calculator.ts +12 -11
- package/src/tools/checkpoint.ts +7 -7
- package/src/tools/debug.ts +40 -43
- package/src/tools/eval.ts +16 -10
- package/src/tools/find.ts +10 -13
- package/src/tools/gh.ts +108 -132
- package/src/tools/hindsight-recall.ts +4 -6
- package/src/tools/hindsight-reflect.ts +5 -5
- package/src/tools/hindsight-retain.ts +15 -17
- package/src/tools/image-gen.ts +31 -81
- package/src/tools/index.ts +4 -1
- package/src/tools/inspect-image.ts +8 -9
- package/src/tools/irc.ts +15 -27
- package/src/tools/job.ts +30 -28
- package/src/tools/output-meta.ts +26 -0
- package/src/tools/read.ts +39 -12
- package/src/tools/recipe/index.ts +7 -9
- package/src/tools/render-mermaid.ts +12 -12
- package/src/tools/report-tool-issue.ts +4 -4
- package/src/tools/resolve.ts +11 -11
- package/src/tools/review.ts +14 -26
- package/src/tools/search-tool-bm25.ts +7 -9
- package/src/tools/search.ts +19 -22
- package/src/tools/ssh.ts +10 -9
- package/src/tools/todo-write.ts +26 -34
- package/src/tools/vim.ts +10 -26
- package/src/tools/write.ts +25 -5
- package/src/tools/yield.ts +100 -54
- package/src/web/search/index.ts +9 -24
- package/src/web/search/providers/anthropic.ts +5 -0
- package/src/web/search/providers/exa.ts +3 -0
- package/src/web/search/providers/gemini.ts +5 -0
- package/src/web/search/providers/jina.ts +5 -2
- package/src/web/search/providers/zai.ts +5 -2
- package/src/prompts/compaction/branch-summary-context.md +0 -5
- package/src/prompts/compaction/branch-summary-preamble.md +0 -2
- package/src/prompts/compaction/branch-summary.md +0 -30
- package/src/prompts/compaction/compaction-short-summary.md +0 -9
- package/src/prompts/compaction/compaction-summary-context.md +0 -5
- package/src/prompts/compaction/compaction-summary.md +0 -38
- package/src/prompts/compaction/compaction-turn-prefix.md +0 -17
- package/src/prompts/compaction/compaction-update-summary.md +0 -45
- package/src/prompts/system/auto-handoff-threshold-focus.md +0 -1
- package/src/prompts/system/file-operations.md +0 -10
- package/src/prompts/system/handoff-document.md +0 -49
- package/src/prompts/system/summarization-system.md +0 -3
- package/src/session/compaction/branch-summarization.ts +0 -324
- package/src/session/compaction/compaction.ts +0 -1420
- package/src/session/compaction/errors.ts +0 -31
- package/src/session/compaction/index.ts +0 -8
- package/src/session/compaction/pruning.ts +0 -91
- package/src/session/compaction/utils.ts +0 -184
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Custom tool loader - loads TypeScript tool modules using native Bun import.
|
|
3
3
|
*
|
|
4
|
-
* Dependencies (
|
|
5
|
-
* to avoid import resolution issues with custom tools loaded from user directories.
|
|
4
|
+
* Dependencies (the zod-backed typebox shim and pi-coding-agent) are injected via the
|
|
5
|
+
* CustomToolAPI to avoid import resolution issues with custom tools loaded from user directories.
|
|
6
6
|
*/
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
|
|
9
9
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
10
|
-
import * as
|
|
10
|
+
import * as z from "zod/v4";
|
|
11
11
|
import { toolCapability } from "../../capability/tool";
|
|
12
12
|
import { type CustomTool, loadCapability } from "../../discovery";
|
|
13
13
|
import type { ExecOptions } from "../../exec/exec";
|
|
14
14
|
import { execCommand } from "../../exec/exec";
|
|
15
15
|
import type { HookUIContext } from "../../extensibility/hooks/types";
|
|
16
16
|
import { getAllPluginToolPaths } from "../../extensibility/plugins/loader";
|
|
17
|
+
import * as typebox from "../typebox";
|
|
17
18
|
import { createNoOpUIContext, resolvePath } from "../utils";
|
|
18
19
|
import type { CustomToolAPI, CustomToolFactory, LoadedCustomTool, ToolLoadError } from "./types";
|
|
19
20
|
|
|
@@ -103,6 +104,7 @@ export class CustomToolLoader {
|
|
|
103
104
|
hasUI: false,
|
|
104
105
|
logger,
|
|
105
106
|
typebox,
|
|
107
|
+
zod: z,
|
|
106
108
|
pi,
|
|
107
109
|
pushPendingAction: action => {
|
|
108
110
|
if (!pushPendingAction) {
|
|
@@ -5,16 +5,15 @@
|
|
|
5
5
|
* They can provide custom rendering for tool calls and results in the TUI.
|
|
6
6
|
*/
|
|
7
7
|
import type { AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
8
|
-
import type {
|
|
8
|
+
import type { CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
|
|
9
|
+
import type { Model, Static, TSchema } from "@oh-my-pi/pi-ai";
|
|
9
10
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
10
|
-
import type { Static, TSchema } from "@sinclair/typebox";
|
|
11
11
|
import type { Rule } from "../../capability/rule";
|
|
12
12
|
import type { ModelRegistry } from "../../config/model-registry";
|
|
13
13
|
import type { Settings } from "../../config/settings";
|
|
14
14
|
import type { ExecOptions, ExecResult } from "../../exec/exec";
|
|
15
15
|
import type { HookUIContext } from "../../extensibility/hooks/types";
|
|
16
16
|
import type { Theme } from "../../modes/theme/theme";
|
|
17
|
-
import type { CompactionResult } from "../../session/compaction";
|
|
18
17
|
import type { ReadonlySessionManager } from "../../session/session-manager";
|
|
19
18
|
import type { TodoItem } from "../../tools/todo-write";
|
|
20
19
|
|
|
@@ -52,8 +51,10 @@ export interface CustomToolAPI {
|
|
|
52
51
|
hasUI: boolean;
|
|
53
52
|
/** File logger for error/warning/debug messages */
|
|
54
53
|
logger: typeof import("@oh-my-pi/pi-utils").logger;
|
|
55
|
-
/** Injected
|
|
56
|
-
typebox: typeof import("
|
|
54
|
+
/** Injected zod-backed typebox shim (legacy/compat — Zod-authored tools are preferred). */
|
|
55
|
+
typebox: typeof import("../typebox");
|
|
56
|
+
/** Injected zod module for Zod-authored custom tools. */
|
|
57
|
+
zod: typeof import("zod/v4");
|
|
57
58
|
/** Injected pi-coding-agent exports */
|
|
58
59
|
pi: typeof import("../..");
|
|
59
60
|
/** Push a preview action that can later be resolved with the hidden resolve tool */
|
|
@@ -180,7 +181,7 @@ export interface CustomTool<TParams extends TSchema = TSchema, TDetails = any> {
|
|
|
180
181
|
strict?: boolean;
|
|
181
182
|
/** Description for LLM */
|
|
182
183
|
description: string;
|
|
183
|
-
/** Parameter schema (TypeBox) */
|
|
184
|
+
/** Parameter schema (Zod or TypeBox; TypeBox is auto-lifted to Zod at registration). */
|
|
184
185
|
parameters: TParams;
|
|
185
186
|
/** If true, tool is excluded unless explicitly listed in --tools or agent's tools field */
|
|
186
187
|
hidden?: boolean;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* CustomToolAdapter wraps CustomTool instances into AgentTool for use with the agent.
|
|
3
3
|
*/
|
|
4
4
|
import type { AgentTool, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
5
|
-
import type { Static, TSchema } from "@
|
|
5
|
+
import type { Static, TSchema } from "@oh-my-pi/pi-ai";
|
|
6
6
|
import type { Theme } from "../../modes/theme/theme";
|
|
7
7
|
import { applyToolProxy } from "../tool-proxy";
|
|
8
8
|
import type { CustomTool, CustomToolContext } from "./types";
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper for wiring the `getCommands` action of {@link ExtensionAPI}.
|
|
3
|
+
*
|
|
4
|
+
* Centralizes the union over the three slash-command sources the runtime
|
|
5
|
+
* exposes so the five wiring sites (interactive UI, ACP, RPC, print, child
|
|
6
|
+
* task executor) cannot drift:
|
|
7
|
+
* - extension-registered hook commands (`source: "extension"`)
|
|
8
|
+
* - prompt commands loaded as `LoadedCustomCommand` — user/project/bundled
|
|
9
|
+
* custom commands and MCP prompts (`source: "prompt"`)
|
|
10
|
+
* - skill commands derived from `session.skills`, gated on
|
|
11
|
+
* `skillsSettings.enableSkillCommands` (`source: "skill"`)
|
|
12
|
+
*
|
|
13
|
+
* Built-in slash commands are intentionally excluded; `getCommands()` is the
|
|
14
|
+
* surface extensions use to discover dynamic commands they did not register
|
|
15
|
+
* themselves. Each frontend (interactive-mode, ACP) prepends its own builtins.
|
|
16
|
+
*/
|
|
17
|
+
import type { SkillsSettings } from "../../config/settings";
|
|
18
|
+
import type { CustomCommandSource, LoadedCustomCommand } from "../custom-commands";
|
|
19
|
+
import { getSkillSlashCommandName, type Skill } from "../skills";
|
|
20
|
+
import type { SlashCommandInfo, SlashCommandLocation } from "../slash-commands";
|
|
21
|
+
import type { ExtensionRunner } from "./runner";
|
|
22
|
+
|
|
23
|
+
interface CommandsCapableSession {
|
|
24
|
+
readonly extensionRunner?: ExtensionRunner;
|
|
25
|
+
readonly customCommands: ReadonlyArray<LoadedCustomCommand>;
|
|
26
|
+
readonly skills: ReadonlyArray<Skill>;
|
|
27
|
+
readonly skillsSettings?: SkillsSettings;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function getSessionSlashCommands(session: CommandsCapableSession): SlashCommandInfo[] {
|
|
31
|
+
const out: SlashCommandInfo[] = [];
|
|
32
|
+
|
|
33
|
+
const runner = session.extensionRunner;
|
|
34
|
+
if (runner) {
|
|
35
|
+
for (const cmd of runner.getRegisteredCommands()) {
|
|
36
|
+
out.push({
|
|
37
|
+
name: cmd.name,
|
|
38
|
+
description: cmd.description,
|
|
39
|
+
source: "extension",
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
for (const cmd of session.customCommands) {
|
|
45
|
+
out.push({
|
|
46
|
+
name: cmd.command.name,
|
|
47
|
+
description: cmd.command.description,
|
|
48
|
+
source: "prompt",
|
|
49
|
+
location: customCommandLocation(cmd.source),
|
|
50
|
+
path: cmd.resolvedPath,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (session.skillsSettings?.enableSkillCommands) {
|
|
55
|
+
for (const skill of session.skills) {
|
|
56
|
+
out.push({
|
|
57
|
+
name: getSkillSlashCommandName(skill),
|
|
58
|
+
description: skill.description || undefined,
|
|
59
|
+
source: "skill",
|
|
60
|
+
path: skill.filePath,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function customCommandLocation(source: CustomCommandSource): SlashCommandLocation | undefined {
|
|
69
|
+
switch (source) {
|
|
70
|
+
case "user":
|
|
71
|
+
return "user";
|
|
72
|
+
case "project":
|
|
73
|
+
return "project";
|
|
74
|
+
case "bundled":
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -8,8 +8,7 @@ import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
|
8
8
|
import type { ImageContent, Model, TextContent } from "@oh-my-pi/pi-ai";
|
|
9
9
|
import type { KeyId } from "@oh-my-pi/pi-tui";
|
|
10
10
|
import { hasFsCode, isEacces, isEnoent, logger } from "@oh-my-pi/pi-utils";
|
|
11
|
-
import
|
|
12
|
-
import * as TypeBox from "@sinclair/typebox";
|
|
11
|
+
import * as Zod from "zod/v4";
|
|
13
12
|
import { type ExtensionModule, extensionModuleCapability } from "../../capability/extension-module";
|
|
14
13
|
import { loadCapability } from "../../discovery";
|
|
15
14
|
import { getExtensionNameFromPath } from "../../discovery/helpers";
|
|
@@ -19,6 +18,7 @@ import type { CustomMessage } from "../../session/messages";
|
|
|
19
18
|
import { EventBus } from "../../utils/event-bus";
|
|
20
19
|
import { installLegacyPiSpecifierShim, loadLegacyPiModule } from "../plugins/legacy-pi-compat";
|
|
21
20
|
import { getAllPluginExtensionPaths } from "../plugins/loader";
|
|
21
|
+
import * as TypeBox from "../typebox";
|
|
22
22
|
|
|
23
23
|
import { resolvePath } from "../utils";
|
|
24
24
|
import type {
|
|
@@ -119,6 +119,7 @@ export class ExtensionRuntime implements IExtensionRuntime {
|
|
|
119
119
|
class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
|
|
120
120
|
readonly logger = logger;
|
|
121
121
|
readonly typebox = TypeBox;
|
|
122
|
+
readonly zod = Zod;
|
|
122
123
|
readonly flagValues = new Map<string, boolean | string>();
|
|
123
124
|
readonly pendingProviderRegistrations: Array<{
|
|
124
125
|
name: string;
|
|
@@ -140,7 +141,10 @@ class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
|
|
|
140
141
|
this.extension.handlers.set(event, list);
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
registerTool<
|
|
144
|
+
registerTool<
|
|
145
|
+
TParams extends import("@oh-my-pi/pi-ai").TSchema = import("@oh-my-pi/pi-ai").TSchema,
|
|
146
|
+
TDetails = unknown,
|
|
147
|
+
>(tool: ToolDefinition<TParams, TDetails>): void {
|
|
144
148
|
this.extension.tools.set(tool.name, {
|
|
145
149
|
definition: tool,
|
|
146
150
|
extensionPath: this.extension.path,
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* - Interact with the user via UI primitives
|
|
9
9
|
*/
|
|
10
10
|
import type { AgentMessage, AgentToolResult, AgentToolUpdateCallback, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
11
|
+
import type { CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
|
|
11
12
|
import type {
|
|
12
13
|
Api,
|
|
13
14
|
AssistantMessageEvent,
|
|
@@ -17,12 +18,13 @@ import type {
|
|
|
17
18
|
Model,
|
|
18
19
|
ProviderResponseMetadata,
|
|
19
20
|
SimpleStreamOptions,
|
|
21
|
+
Static,
|
|
20
22
|
TextContent,
|
|
23
|
+
TSchema,
|
|
21
24
|
} from "@oh-my-pi/pi-ai";
|
|
22
25
|
import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/utils/oauth/types";
|
|
23
26
|
import type * as piCodingAgent from "@oh-my-pi/pi-coding-agent";
|
|
24
27
|
import type { AutocompleteItem, Component, EditorTheme, KeyId, TUI } from "@oh-my-pi/pi-tui";
|
|
25
|
-
import type { Static, TSchema } from "@sinclair/typebox";
|
|
26
28
|
import type { KeybindingsManager } from "../../config/keybindings";
|
|
27
29
|
import type { ModelRegistry } from "../../config/model-registry";
|
|
28
30
|
import type { EditToolDetails } from "../../edit";
|
|
@@ -31,7 +33,6 @@ import type { BashResult } from "../../exec/bash-executor";
|
|
|
31
33
|
import type { ExecOptions, ExecResult } from "../../exec/exec";
|
|
32
34
|
import type { CustomEditor } from "../../modes/components/custom-editor";
|
|
33
35
|
import type { Theme } from "../../modes/theme/theme";
|
|
34
|
-
import type { CompactionResult } from "../../session/compaction";
|
|
35
36
|
import type { CustomMessage } from "../../session/messages";
|
|
36
37
|
import type { ReadonlySessionManager, SessionManager } from "../../session/session-manager";
|
|
37
38
|
import type {
|
|
@@ -355,7 +356,7 @@ export interface ToolDefinition<TParams extends TSchema = TSchema, TDetails = un
|
|
|
355
356
|
label: string;
|
|
356
357
|
/** Description for LLM */
|
|
357
358
|
description: string;
|
|
358
|
-
/** Parameter schema (TypeBox) */
|
|
359
|
+
/** Parameter schema (Zod, or TypeBox for legacy/extension compat). */
|
|
359
360
|
parameters: TParams;
|
|
360
361
|
/** If true, tool is excluded unless explicitly listed in --tools or agent's tools field */
|
|
361
362
|
hidden?: boolean;
|
|
@@ -833,8 +834,11 @@ export interface ExtensionAPI {
|
|
|
833
834
|
/** File logger for error/warning/debug messages */
|
|
834
835
|
logger: typeof import("@oh-my-pi/pi-utils").logger;
|
|
835
836
|
|
|
836
|
-
/** Injected
|
|
837
|
-
typebox: typeof import("
|
|
837
|
+
/** Injected zod-backed typebox shim for legacy `Type.Object(...)` parameter authoring. */
|
|
838
|
+
typebox: typeof import("../typebox");
|
|
839
|
+
|
|
840
|
+
/** Injected zod module for Zod-authored extension tools (canonical going forward). */
|
|
841
|
+
zod: typeof import("zod/v4");
|
|
838
842
|
|
|
839
843
|
/** Injected pi-coding-agent exports for accessing SDK utilities */
|
|
840
844
|
pi: typeof piCodingAgent;
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* Tool wrappers for extensions.
|
|
3
3
|
*/
|
|
4
4
|
import type { AgentTool, AgentToolContext, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
5
|
-
import type { ImageContent, TextContent } from "@oh-my-pi/pi-ai";
|
|
6
|
-
import type { Static, TSchema } from "@sinclair/typebox";
|
|
5
|
+
import type { ImageContent, Static, TextContent, TSchema } from "@oh-my-pi/pi-ai";
|
|
7
6
|
import type { Theme } from "../../modes/theme/theme";
|
|
8
7
|
import { applyToolProxy } from "../tool-proxy";
|
|
9
8
|
import type { ExtensionRunner } from "./runner";
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
6
|
-
import * as
|
|
6
|
+
import * as zod from "zod/v4";
|
|
7
7
|
import { hookCapability } from "../../capability/hook";
|
|
8
8
|
import type { Hook } from "../../discovery";
|
|
9
9
|
import { loadCapability } from "../../discovery";
|
|
10
10
|
import type { HookMessage } from "../../session/messages";
|
|
11
11
|
import type { SessionManager } from "../../session/session-manager";
|
|
12
|
+
import * as typebox from "../typebox";
|
|
12
13
|
import { resolvePath } from "../utils";
|
|
13
14
|
import { execCommand } from "./runner";
|
|
14
15
|
import type { ExecOptions, HookAPI, HookFactory, HookMessageRenderer, RegisteredCommand } from "./types";
|
|
@@ -136,6 +137,7 @@ async function createHookAPI(
|
|
|
136
137
|
},
|
|
137
138
|
logger,
|
|
138
139
|
typebox,
|
|
140
|
+
zod,
|
|
139
141
|
pi: await import("@oh-my-pi/pi-coding-agent"),
|
|
140
142
|
} as HookAPI;
|
|
141
143
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Tool wrapper - wraps tools with hook callbacks for interception.
|
|
3
3
|
*/
|
|
4
4
|
import type { AgentTool, AgentToolContext, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
5
|
-
import type { Static, TSchema } from "@
|
|
5
|
+
import type { Static, TSchema } from "@oh-my-pi/pi-ai";
|
|
6
6
|
import { applyToolProxy } from "../tool-proxy";
|
|
7
7
|
import type { HookRunner } from "./runner";
|
|
8
8
|
import type { ToolCallEventResult, ToolResultEventResult } from "./types";
|
|
@@ -571,8 +571,10 @@ export interface HookAPI {
|
|
|
571
571
|
|
|
572
572
|
/** File logger for error/warning/debug messages */
|
|
573
573
|
logger: typeof import("@oh-my-pi/pi-utils").logger;
|
|
574
|
-
/** Injected
|
|
575
|
-
typebox: typeof import("
|
|
574
|
+
/** Injected zod-backed typebox shim (legacy/compat — prefer `zod`). */
|
|
575
|
+
typebox: typeof import("../typebox");
|
|
576
|
+
/** Injected zod module for Zod-authored hooks. */
|
|
577
|
+
zod: typeof import("zod/v4");
|
|
576
578
|
/** Injected pi-coding-agent exports */
|
|
577
579
|
pi: typeof import("../..");
|
|
578
580
|
}
|
|
@@ -3,47 +3,75 @@ import * as os from "node:os";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import * as url from "node:url";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
6
|
+
// Canonical scope for in-process pi packages. Plugins published against any of
|
|
7
|
+
// the aliased scopes below (mariozechner's original publish, earendil-works'
|
|
8
|
+
// fork, or the canonical @oh-my-pi scope itself) are remapped to this scope and
|
|
9
|
+
// resolved against the bundled copy that ships inside the omp binary. This
|
|
10
|
+
// keeps plugins running against the exact runtime state of the host (single
|
|
11
|
+
// module registry, single tool registry, etc.) regardless of which historical
|
|
12
|
+
// scope name they happened to declare in their peerDependencies.
|
|
13
|
+
const CANONICAL_PI_SCOPE = "@oh-my-pi";
|
|
14
|
+
|
|
15
|
+
// Scopes that have historically been used to publish (or alias) the same set
|
|
16
|
+
// of internal pi-* packages. `@oh-my-pi` is intentionally included so that
|
|
17
|
+
// direct imports of the canonical name still flow through `Bun.resolveSync`
|
|
18
|
+
// against the host binary, avoiding a duplicate copy being pulled in from a
|
|
19
|
+
// plugin's own node_modules tree at install time.
|
|
20
|
+
const PI_SCOPE_ALIASES = ["oh-my-pi", "mariozechner", "earendil-works"] as const;
|
|
21
|
+
|
|
22
|
+
// Internal pi-* package basenames bundled inside the omp binary.
|
|
23
|
+
const PI_PACKAGE_NAMES = ["pi-agent-core", "pi-ai", "pi-coding-agent", "pi-natives", "pi-tui", "pi-utils"] as const;
|
|
24
|
+
|
|
25
|
+
const PI_SCOPE_ALTERNATION = PI_SCOPE_ALIASES.join("|");
|
|
26
|
+
const PI_PACKAGE_ALTERNATION = PI_PACKAGE_NAMES.join("|");
|
|
27
|
+
|
|
28
|
+
// Upstream `@mariozechner/*` packages exposed a few subpaths at the package
|
|
29
|
+
// root that we relocated under a different folder. Each entry rewrites
|
|
30
|
+
// `<pkg>/<from>` → `<pkg>/<to>` after the scope has been canonicalised, so
|
|
31
|
+
// plugins importing the upstream layout still resolve to a real file in our
|
|
32
|
+
// bundled copy. Add new entries as `pkg/from -> pkg/to` whenever a plugin
|
|
33
|
+
// surfaces another upstream-only subpath that breaks resolution.
|
|
34
|
+
const PI_SUBPATH_REMAPS: ReadonlyMap<string, string> = new Map<string, string>([
|
|
35
|
+
// `@mariozechner/pi-ai/oauth` re-exported `./utils/oauth/index.js`.
|
|
36
|
+
// Our pi-ai keeps the implementation under `utils/oauth` but never added a
|
|
37
|
+
// root-level re-export, so map the upstream subpath onto it directly.
|
|
38
|
+
["pi-ai/oauth", "pi-ai/utils/oauth"],
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
const LEGACY_PI_SPECIFIER_FILTER = new RegExp(`^@(?:${PI_SCOPE_ALTERNATION})/(?:${PI_PACKAGE_ALTERNATION})(?:/.*)?$`);
|
|
42
|
+
const LEGACY_PI_IMPORT_SPECIFIER_REGEX = new RegExp(
|
|
43
|
+
`((?:from\\s+|import\\s*\\(\\s*)["'])(@(?:${PI_SCOPE_ALTERNATION})/(?:${PI_PACKAGE_ALTERNATION})(?:/[^"'()\\s]+)?)(["'])`,
|
|
44
|
+
"g",
|
|
45
|
+
);
|
|
21
46
|
const LEGACY_PI_FILE_PREFIX = "omp-legacy-pi-file:";
|
|
22
47
|
const LEGACY_PI_FILE_NAMESPACE = "omp-legacy-pi-file";
|
|
23
48
|
const resolvedSpecifierFallbacks = new Map<string, string>();
|
|
24
49
|
|
|
50
|
+
// Extensions that imported `@sinclair/typebox` directly used to resolve against a
|
|
51
|
+
// real `@sinclair/typebox` install. The runtime dep was replaced with the Zod-backed
|
|
52
|
+
// shim under `extensibility/typebox.ts`; plugins still importing the public name
|
|
53
|
+
// are redirected to that shim so existing extensions keep working without code
|
|
54
|
+
// changes. Submodules like `@sinclair/typebox/compiler` are intentionally not
|
|
55
|
+
// remapped — those expose TypeBox-only APIs the shim does not provide and plugins
|
|
56
|
+
// relying on them must vendor `@sinclair/typebox` directly.
|
|
57
|
+
const TYPEBOX_SPECIFIER = "@sinclair/typebox";
|
|
58
|
+
const TYPEBOX_SPECIFIER_FILTER = /^@sinclair\/typebox$/;
|
|
59
|
+
const TYPEBOX_SHIM_PATH = path.resolve(import.meta.dir, "../typebox.ts");
|
|
60
|
+
|
|
25
61
|
let isLegacyPiSpecifierShimInstalled = false;
|
|
26
62
|
|
|
27
63
|
function remapLegacyPiSpecifier(specifier: string): string | null {
|
|
28
|
-
|
|
29
|
-
const legacyPackageName = `${legacyScope}/${packageName}`;
|
|
30
|
-
const mappedPackageName = LEGACY_PI_PACKAGE_MAP[legacyPackageName as keyof typeof LEGACY_PI_PACKAGE_MAP];
|
|
31
|
-
if (!mappedPackageName) {
|
|
64
|
+
if (!LEGACY_PI_SPECIFIER_FILTER.test(specifier)) {
|
|
32
65
|
return null;
|
|
33
66
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const subpath = subpathParts.join("/");
|
|
39
|
-
if (legacyPackageName === "@mariozechner/pi-coding-agent") {
|
|
40
|
-
return (
|
|
41
|
-
LEGACY_PI_CODING_AGENT_SUBPATH_MAP[subpath as keyof typeof LEGACY_PI_CODING_AGENT_SUBPATH_MAP] ??
|
|
42
|
-
`${mappedPackageName}/${subpath}`
|
|
43
|
-
);
|
|
67
|
+
const slashIdx = specifier.indexOf("/", 1);
|
|
68
|
+
// Filter guarantees a slash exists, but guard anyway to keep the type narrow.
|
|
69
|
+
if (slashIdx === -1) {
|
|
70
|
+
return null;
|
|
44
71
|
}
|
|
45
|
-
|
|
46
|
-
|
|
72
|
+
const rest = specifier.slice(slashIdx + 1);
|
|
73
|
+
const remappedSubpath = PI_SUBPATH_REMAPS.get(rest) ?? rest;
|
|
74
|
+
return `${CANONICAL_PI_SCOPE}/${remappedSubpath}`;
|
|
47
75
|
}
|
|
48
76
|
|
|
49
77
|
function getResolvedSpecifier(specifier: string): string {
|
|
@@ -82,6 +110,12 @@ const ANY_IMPORT_SPECIFIER_REGEX = /((?:from\s+|import\s*\(\s*)["'])([^"']+)(["'
|
|
|
82
110
|
|
|
83
111
|
/** Resolve bare imports against the extension directory before loading mirrored legacy Pi files. */
|
|
84
112
|
function isUrlLikeSpecifier(specifier: string): boolean {
|
|
113
|
+
// Windows drive-letter paths (e.g. `C:\foo` or `C:/foo`) also match the URL
|
|
114
|
+
// scheme shape `[A-Za-z][A-Za-z\d+.-]*:`. Treat them as filesystem paths so
|
|
115
|
+
// `toRewrittenImportSpecifier` converts them to `file://` URLs instead of
|
|
116
|
+
// emitting raw paths whose `\n`, `\U`, ... get eaten by TS string-literal
|
|
117
|
+
// escapes inside the mirrored extension file.
|
|
118
|
+
if (/^[a-zA-Z]:[\\/]/.test(specifier)) return false;
|
|
85
119
|
return /^[a-zA-Z][a-zA-Z\d+.-]*:/.test(specifier);
|
|
86
120
|
}
|
|
87
121
|
|
|
@@ -100,6 +134,9 @@ function rewriteBareImportsForLegacyExtension(source: string, importerPath: stri
|
|
|
100
134
|
if (shouldPreserveImportSpecifier(specifier)) {
|
|
101
135
|
return match;
|
|
102
136
|
}
|
|
137
|
+
if (specifier === TYPEBOX_SPECIFIER) {
|
|
138
|
+
return `${prefix}${toRewrittenImportSpecifier(TYPEBOX_SHIM_PATH)}${suffix}`;
|
|
139
|
+
}
|
|
103
140
|
try {
|
|
104
141
|
const resolved = Bun.resolveSync(specifier, importerDir);
|
|
105
142
|
return `${prefix}${toRewrittenImportSpecifier(resolved)}${suffix}`;
|
|
@@ -206,6 +243,10 @@ function resolveLegacyPiSpecifier(args: { path: string }): { path: string } | un
|
|
|
206
243
|
};
|
|
207
244
|
}
|
|
208
245
|
|
|
246
|
+
function resolveTypeBoxSpecifier(): { path: string } {
|
|
247
|
+
return { path: TYPEBOX_SHIM_PATH };
|
|
248
|
+
}
|
|
249
|
+
|
|
209
250
|
export function installLegacyPiSpecifierShim(): void {
|
|
210
251
|
if (isLegacyPiSpecifierShimInstalled) {
|
|
211
252
|
return;
|
|
@@ -221,6 +262,12 @@ export function installLegacyPiSpecifierShim(): void {
|
|
|
221
262
|
resolveLegacyPiSpecifier,
|
|
222
263
|
);
|
|
223
264
|
|
|
265
|
+
build.onResolve({ filter: TYPEBOX_SPECIFIER_FILTER, namespace: "file" }, resolveTypeBoxSpecifier);
|
|
266
|
+
build.onResolve(
|
|
267
|
+
{ filter: TYPEBOX_SPECIFIER_FILTER, namespace: LEGACY_PI_FILE_NAMESPACE },
|
|
268
|
+
resolveTypeBoxSpecifier,
|
|
269
|
+
);
|
|
270
|
+
|
|
224
271
|
build.onResolve({ filter: /^omp-legacy-pi-file:/, namespace: "file" }, args => ({
|
|
225
272
|
path: args.path.slice(LEGACY_PI_FILE_PREFIX.length),
|
|
226
273
|
namespace: LEGACY_PI_FILE_NAMESPACE,
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
* `types.ts` files and is documented there.
|
|
14
14
|
*/
|
|
15
15
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
16
|
+
import type { CompactionPreparation, CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
|
|
16
17
|
import type { ImageContent, TextContent, ToolResultMessage } from "@oh-my-pi/pi-ai";
|
|
17
18
|
import type { Rule } from "../capability/rule";
|
|
18
19
|
import type { Goal, GoalModeState } from "../goals/state";
|
|
19
|
-
import type { CompactionPreparation, CompactionResult } from "../session/compaction";
|
|
20
20
|
import type { BranchSummaryEntry, CompactionEntry, SessionEntry } from "../session/session-manager";
|
|
21
21
|
import type { TodoItem } from "../tools/todo-write";
|
|
22
22
|
|