@oh-my-pi/pi-coding-agent 15.0.2 → 15.1.1

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.
Files changed (138) hide show
  1. package/CHANGELOG.md +56 -1
  2. package/examples/custom-tools/README.md +11 -7
  3. package/examples/custom-tools/hello/index.ts +2 -2
  4. package/examples/extensions/README.md +19 -8
  5. package/examples/extensions/api-demo.ts +15 -19
  6. package/examples/extensions/hello.ts +5 -6
  7. package/examples/extensions/plan-mode.ts +1 -1
  8. package/examples/extensions/reload-runtime.ts +4 -3
  9. package/examples/extensions/with-deps/index.ts +4 -3
  10. package/examples/sdk/06-extensions.ts +4 -2
  11. package/package.json +7 -17
  12. package/src/autoresearch/tools/init-experiment.ts +38 -41
  13. package/src/autoresearch/tools/log-experiment.ts +32 -41
  14. package/src/autoresearch/tools/run-experiment.ts +3 -3
  15. package/src/autoresearch/tools/update-notes.ts +11 -11
  16. package/src/commit/agentic/tools/analyze-file.ts +4 -4
  17. package/src/commit/agentic/tools/git-file-diff.ts +4 -4
  18. package/src/commit/agentic/tools/git-hunk.ts +5 -5
  19. package/src/commit/agentic/tools/git-overview.ts +4 -4
  20. package/src/commit/agentic/tools/propose-changelog.ts +13 -13
  21. package/src/commit/agentic/tools/propose-commit.ts +6 -6
  22. package/src/commit/agentic/tools/recent-commits.ts +3 -3
  23. package/src/commit/agentic/tools/schemas.ts +28 -28
  24. package/src/commit/agentic/tools/split-commit.ts +22 -21
  25. package/src/commit/analysis/summary.ts +4 -4
  26. package/src/commit/changelog/generate.ts +7 -11
  27. package/src/commit/shared-llm.ts +22 -34
  28. package/src/config/config-file.ts +35 -13
  29. package/src/config/model-registry.ts +9 -190
  30. package/src/config/models-config-schema.ts +166 -0
  31. package/src/config/settings-schema.ts +18 -0
  32. package/src/edit/index.ts +2 -2
  33. package/src/edit/modes/apply-patch.ts +7 -6
  34. package/src/edit/modes/patch.ts +18 -25
  35. package/src/edit/modes/replace.ts +18 -20
  36. package/src/eval/js/shared/rewrite-imports.ts +131 -10
  37. package/src/eval/py/executor.ts +233 -623
  38. package/src/eval/py/kernel.ts +27 -2
  39. package/src/exa/factory.ts +5 -4
  40. package/src/exa/mcp-client.ts +1 -1
  41. package/src/exa/researcher.ts +9 -20
  42. package/src/exa/search.ts +26 -52
  43. package/src/exa/types.ts +1 -1
  44. package/src/exa/websets.ts +54 -53
  45. package/src/exec/bash-executor.ts +2 -1
  46. package/src/extensibility/custom-commands/loader.ts +5 -3
  47. package/src/extensibility/custom-commands/types.ts +4 -2
  48. package/src/extensibility/custom-tools/loader.ts +5 -3
  49. package/src/extensibility/custom-tools/types.ts +7 -6
  50. package/src/extensibility/custom-tools/wrapper.ts +1 -1
  51. package/src/extensibility/extensions/loader.ts +7 -3
  52. package/src/extensibility/extensions/types.ts +9 -5
  53. package/src/extensibility/extensions/wrapper.ts +1 -2
  54. package/src/extensibility/hooks/loader.ts +3 -1
  55. package/src/extensibility/hooks/tool-wrapper.ts +1 -1
  56. package/src/extensibility/hooks/types.ts +4 -2
  57. package/src/extensibility/plugins/legacy-pi-compat.ts +30 -0
  58. package/src/extensibility/shared-events.ts +1 -1
  59. package/src/extensibility/typebox.ts +391 -0
  60. package/src/goals/tools/goal-tool.ts +6 -12
  61. package/src/hashline/types.ts +4 -4
  62. package/src/hindsight/state.ts +2 -2
  63. package/src/index.ts +0 -2
  64. package/src/internal-urls/docs-index.generated.ts +7 -7
  65. package/src/lsp/types.ts +30 -38
  66. package/src/mcp/manager.ts +1 -1
  67. package/src/mcp/tool-bridge.ts +1 -1
  68. package/src/modes/components/session-observer-overlay.ts +12 -1
  69. package/src/modes/components/status-line/segments.ts +2 -1
  70. package/src/modes/controllers/command-controller.ts +27 -2
  71. package/src/modes/controllers/event-controller.ts +3 -4
  72. package/src/modes/interactive-mode.ts +1 -1
  73. package/src/modes/rpc/host-tools.ts +1 -1
  74. package/src/modes/rpc/rpc-client.ts +1 -1
  75. package/src/modes/rpc/rpc-types.ts +1 -1
  76. package/src/modes/theme/theme.ts +111 -117
  77. package/src/modes/types.ts +1 -1
  78. package/src/modes/utils/context-usage.ts +2 -2
  79. package/src/sdk.ts +31 -8
  80. package/src/session/agent-session.ts +74 -104
  81. package/src/session/messages.ts +16 -51
  82. package/src/session/session-manager.ts +22 -2
  83. package/src/session/streaming-output.ts +16 -6
  84. package/src/task/executor.ts +208 -86
  85. package/src/task/index.ts +15 -11
  86. package/src/task/render.ts +32 -5
  87. package/src/task/types.ts +54 -39
  88. package/src/tools/ask.ts +12 -12
  89. package/src/tools/ast-edit.ts +11 -15
  90. package/src/tools/ast-grep.ts +9 -10
  91. package/src/tools/bash.ts +9 -23
  92. package/src/tools/browser.ts +39 -53
  93. package/src/tools/calculator.ts +12 -11
  94. package/src/tools/checkpoint.ts +7 -7
  95. package/src/tools/debug.ts +40 -43
  96. package/src/tools/eval.ts +6 -8
  97. package/src/tools/find.ts +10 -13
  98. package/src/tools/gh.ts +71 -128
  99. package/src/tools/hindsight-recall.ts +4 -6
  100. package/src/tools/hindsight-reflect.ts +5 -5
  101. package/src/tools/hindsight-retain.ts +15 -17
  102. package/src/tools/image-gen.ts +32 -82
  103. package/src/tools/index.ts +4 -1
  104. package/src/tools/inspect-image.ts +8 -9
  105. package/src/tools/irc.ts +15 -27
  106. package/src/tools/job.ts +14 -21
  107. package/src/tools/read.ts +7 -8
  108. package/src/tools/recipe/index.ts +7 -9
  109. package/src/tools/render-mermaid.ts +12 -12
  110. package/src/tools/report-tool-issue.ts +4 -4
  111. package/src/tools/resolve.ts +11 -11
  112. package/src/tools/review.ts +14 -26
  113. package/src/tools/search-tool-bm25.ts +7 -9
  114. package/src/tools/search.ts +19 -22
  115. package/src/tools/ssh.ts +7 -7
  116. package/src/tools/todo-write.ts +26 -34
  117. package/src/tools/vim.ts +10 -26
  118. package/src/tools/write.ts +5 -5
  119. package/src/tools/yield.ts +100 -54
  120. package/src/web/search/index.ts +9 -24
  121. package/src/prompts/compaction/branch-summary-context.md +0 -5
  122. package/src/prompts/compaction/branch-summary-preamble.md +0 -2
  123. package/src/prompts/compaction/branch-summary.md +0 -30
  124. package/src/prompts/compaction/compaction-short-summary.md +0 -9
  125. package/src/prompts/compaction/compaction-summary-context.md +0 -5
  126. package/src/prompts/compaction/compaction-summary.md +0 -38
  127. package/src/prompts/compaction/compaction-turn-prefix.md +0 -17
  128. package/src/prompts/compaction/compaction-update-summary.md +0 -45
  129. package/src/prompts/system/auto-handoff-threshold-focus.md +0 -1
  130. package/src/prompts/system/file-operations.md +0 -10
  131. package/src/prompts/system/handoff-document.md +0 -49
  132. package/src/prompts/system/summarization-system.md +0 -3
  133. package/src/session/compaction/branch-summarization.ts +0 -324
  134. package/src/session/compaction/compaction.ts +0 -1420
  135. package/src/session/compaction/errors.ts +0 -31
  136. package/src/session/compaction/index.ts +0 -8
  137. package/src/session/compaction/pruning.ts +0 -91
  138. package/src/session/compaction/utils.ts +0 -184
package/src/tools/job.ts CHANGED
@@ -2,7 +2,7 @@ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallb
2
2
  import type { Component } from "@oh-my-pi/pi-tui";
3
3
  import { Text } from "@oh-my-pi/pi-tui";
4
4
  import { prompt } from "@oh-my-pi/pi-utils";
5
- import { type Static, Type } from "@sinclair/typebox";
5
+ import * as z from "zod/v4";
6
6
  import { type AsyncJob, AsyncJobManager, isBackgroundJobSupportEnabled } from "../async";
7
7
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
8
8
  import type { Theme } from "../modes/theme/theme";
@@ -22,28 +22,21 @@ import {
22
22
  } from "./render-utils";
23
23
  import { ToolError } from "./tool-errors";
24
24
 
25
- const jobSchema = Type.Object({
26
- poll: Type.Optional(
27
- Type.Array(Type.String(), {
28
- description: "background job ids to wait for; omit (with no `cancel`) to wait on all running jobs",
29
- examples: [["job-1234"]],
30
- }),
31
- ),
32
- cancel: Type.Optional(
33
- Type.Array(Type.String(), {
34
- description: "background job ids to cancel",
35
- examples: [["job-1234"]],
36
- }),
37
- ),
38
- list: Type.Optional(
39
- Type.Boolean({
40
- description:
41
- "Return an immediate snapshot of every job spawned by this agent (running + completed within retention). Read-only \u2014 cannot be combined with `poll` or `cancel`.",
42
- }),
43
- ),
25
+ const jobSchema = z.object({
26
+ poll: z
27
+ .array(z.string())
28
+ .optional()
29
+ .describe("background job ids to wait for; omit (with no `cancel`) to wait on all running jobs"),
30
+ cancel: z.array(z.string()).optional().describe("background job ids to cancel"),
31
+ list: z
32
+ .boolean()
33
+ .optional()
34
+ .describe(
35
+ "Return an immediate snapshot of every job spawned by this agent (running + completed within retention). Read-only \u2014 cannot be combined with `poll` or `cancel`.",
36
+ ),
44
37
  });
45
38
 
46
- type JobParams = Static<typeof jobSchema>;
39
+ type JobParams = z.infer<typeof jobSchema>;
47
40
 
48
41
  const WAIT_DURATION_MS: Record<string, number> = {
49
42
  "5s": 5_000,
package/src/tools/read.ts CHANGED
@@ -7,7 +7,7 @@ import { glob, type SummaryResult, summarizeCode } from "@oh-my-pi/pi-natives";
7
7
  import type { Component } from "@oh-my-pi/pi-tui";
8
8
  import { Text } from "@oh-my-pi/pi-tui";
9
9
  import { getRemoteDir, logger, prompt, readImageMetadata, untilAborted } from "@oh-my-pi/pi-utils";
10
- import { type Static, Type } from "@sinclair/typebox";
10
+ import * as z from "zod/v4";
11
11
  import { getFileReadCache } from "../edit/file-read-cache";
12
12
  import { isNotebookPath, readEditableNotebookText } from "../edit/notebook";
13
13
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
@@ -473,14 +473,13 @@ function prependSuffixResolutionNotice(text: string, suffixResolution?: { from:
473
473
  return text ? `${notice}\n${text}` : notice;
474
474
  }
475
475
 
476
- const readSchema = Type.Object({
477
- path: Type.String({
478
- description: 'path or url; append :<sel> for line ranges or raw mode (e.g. "src/foo.ts:50-100")',
479
- examples: ["src/foo.ts", "src/foo.ts:50-100", "https://example.com/:1-40"],
480
- }),
481
- });
476
+ const readSchema = z
477
+ .object({
478
+ path: z.string().describe('path or url; append :<sel> for line ranges or raw mode (e.g. "src/foo.ts:50-100")'),
479
+ })
480
+ .strict();
482
481
 
483
- export type ReadToolInput = Static<typeof readSchema>;
482
+ export type ReadToolInput = z.infer<typeof readSchema>;
484
483
 
485
484
  export interface ReadToolDetails {
486
485
  kind?: "file" | "url";
@@ -1,7 +1,7 @@
1
1
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
2
2
  import type { Component } from "@oh-my-pi/pi-tui";
3
3
  import { prompt } from "@oh-my-pi/pi-utils";
4
- import { type Static, Type } from "@sinclair/typebox";
4
+ import * as z from "zod/v4";
5
5
  import type { RenderResultOptions } from "../../extensibility/custom-tools/types";
6
6
  import type { Theme } from "../../modes/theme/theme";
7
7
  import recipeDescription from "../../prompts/tools/recipe.md" with { type: "text" };
@@ -11,14 +11,12 @@ import { createRecipeToolRenderer, type RecipeRenderArgs } from "./render";
11
11
  import { buildPromptModel, type DetectedRunner, resolveCommand } from "./runner";
12
12
  import { RUNNERS } from "./runners";
13
13
 
14
- const recipeSchema = Type.Object({
15
- op: Type.String({
16
- description: 'task name and args, e.g. "test" or "build --release"',
17
- examples: ["test", "build --release", "pkg:test --watch"],
18
- }),
19
- });
20
-
21
- type RecipeParams = Static<typeof recipeSchema>;
14
+ const recipeSchema = z
15
+ .object({
16
+ op: z.string().describe('task name and args, e.g. "test" or "build --release"'),
17
+ })
18
+ .strict();
19
+ type RecipeParams = z.infer<typeof recipeSchema>;
22
20
 
23
21
  type RecipeRenderResult = {
24
22
  content: Array<{ type: string; text?: string }>;
@@ -1,22 +1,22 @@
1
1
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
2
2
  import { type MermaidAsciiRenderOptions, prompt, renderMermaidAscii } from "@oh-my-pi/pi-utils";
3
- import { type Static, Type } from "@sinclair/typebox";
3
+ import * as z from "zod/v4";
4
4
  import renderMermaidDescription from "../prompts/tools/render-mermaid.md" with { type: "text" };
5
5
  import type { ToolSession } from "./index";
6
6
 
7
- const renderMermaidSchema = Type.Object({
8
- mermaid: Type.String({ description: "mermaid source", examples: ["graph TD; A-->B"] }),
9
- config: Type.Optional(
10
- Type.Object({
11
- useAscii: Type.Optional(Type.Boolean()),
12
- paddingX: Type.Optional(Type.Number()),
13
- paddingY: Type.Optional(Type.Number()),
14
- boxBorderPadding: Type.Optional(Type.Number()),
15
- }),
16
- ),
7
+ const renderMermaidSchema = z.object({
8
+ mermaid: z.string().describe("mermaid source"),
9
+ config: z
10
+ .object({
11
+ useAscii: z.boolean().optional(),
12
+ paddingX: z.number().optional(),
13
+ paddingY: z.number().optional(),
14
+ boxBorderPadding: z.number().optional(),
15
+ })
16
+ .optional(),
17
17
  });
18
18
 
19
- type RenderMermaidParams = Static<typeof renderMermaidSchema>;
19
+ type RenderMermaidParams = z.infer<typeof renderMermaidSchema>;
20
20
 
21
21
  function sanitizeRenderConfig(config: MermaidAsciiRenderOptions | undefined): MermaidAsciiRenderOptions | undefined {
22
22
  if (!config) return undefined;
@@ -9,13 +9,13 @@ import { Database } from "bun:sqlite";
9
9
  import path from "node:path";
10
10
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
11
11
  import { $flag, getAgentDir, logger, VERSION } from "@oh-my-pi/pi-utils";
12
- import { Type } from "@sinclair/typebox";
12
+ import * as z from "zod/v4";
13
13
  import type { Settings } from "..";
14
14
  import type { ToolSession } from "./index";
15
15
 
16
- const ReportToolIssueParams = Type.Object({
17
- tool: Type.String({ description: "tool name", examples: ["bash", "read"] }),
18
- report: Type.String({ description: "unexpected behavior" }),
16
+ const ReportToolIssueParams = z.object({
17
+ tool: z.string().describe("tool name"),
18
+ report: z.string().describe("unexpected behavior"),
19
19
  });
20
20
 
21
21
  export function isAutoQaEnabled(settings?: Settings): boolean {
@@ -2,7 +2,7 @@ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallb
2
2
  import type { Component } from "@oh-my-pi/pi-tui";
3
3
  import { Text } from "@oh-my-pi/pi-tui";
4
4
  import { prompt, untilAborted } from "@oh-my-pi/pi-utils";
5
- import { type Static, Type } from "@sinclair/typebox";
5
+ import * as z from "zod/v4";
6
6
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
7
7
  import type { Theme } from "../modes/theme/theme";
8
8
  import resolveDescription from "../prompts/tools/resolve.md" with { type: "text" };
@@ -11,18 +11,18 @@ import type { ToolSession } from ".";
11
11
  import { replaceTabs } from "./render-utils";
12
12
  import { ToolError } from "./tool-errors";
13
13
 
14
- const resolveSchema = Type.Object({
15
- action: Type.Union([Type.Literal("apply"), Type.Literal("discard")]),
16
- reason: Type.String({ description: "reason for action", examples: ["approved by user"] }),
17
- extra: Type.Optional(
18
- Type.Record(Type.String(), Type.Unknown(), {
19
- description:
20
- 'Free-form metadata interpreted by the resolving tool (e.g. plan-mode approval requires `{ title: "<PLAN_TITLE>" }`).',
21
- }),
22
- ),
14
+ const resolveSchema = z.object({
15
+ action: z.union([z.literal("apply"), z.literal("discard")]),
16
+ reason: z.string().describe("reason for action"),
17
+ extra: z
18
+ .record(z.string(), z.unknown())
19
+ .optional()
20
+ .describe(
21
+ 'Free-form metadata interpreted by the resolving tool (e.g. plan-mode approval requires `{ title: "<PLAN_TITLE>" }`).',
22
+ ),
23
23
  });
24
24
 
25
- type ResolveParams = Static<typeof resolveSchema>;
25
+ type ResolveParams = z.infer<typeof resolveSchema>;
26
26
 
27
27
  export interface ResolveToolDetails {
28
28
  action: "apply" | "discard";
@@ -6,18 +6,15 @@
6
6
  * Reviewers finish via `yield` tool with SubmitReviewDetails schema.
7
7
  */
8
8
  // ─────────────────────────────────────────────────────────────────────────────
9
- // Subprocess tool handlers - registered for extraction/rendering in task tool
10
- // ─────────────────────────────────────────────────────────────────────────────
9
+
11
10
  import path from "node:path";
12
11
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
13
- import { StringEnum } from "@oh-my-pi/pi-ai";
14
12
  import type { Component } from "@oh-my-pi/pi-tui";
15
13
  import { Container, Text } from "@oh-my-pi/pi-tui";
16
14
  import { isRecord } from "@oh-my-pi/pi-utils";
17
- import { Type } from "@sinclair/typebox";
15
+ import * as z from "zod/v4";
18
16
  import type { Theme, ThemeColor } from "../modes/theme/theme";
19
17
  import { subprocessToolRegistry } from "../task/subprocess-tool-registry";
20
-
21
18
  export type FindingPriority = "P0" | "P1" | "P2" | "P3";
22
19
 
23
20
  export interface FindingPriorityInfo {
@@ -53,27 +50,18 @@ function getPriorityDisplay(
53
50
  }
54
51
 
55
52
  // report_finding schema
56
- const ReportFindingParams = Type.Object({
57
- title: Type.String({
58
- description: "prefixed imperative title",
59
- examples: ["[P1] un-padding wrong dimension"],
60
- }),
61
- body: Type.String({
62
- description: "problem explanation",
63
- }),
64
- priority: StringEnum(["P0", "P1", "P2", "P3"], {
65
- description: "priority 0-3",
66
- }),
67
- confidence: Type.Number({
68
- minimum: 0,
69
- maximum: 1,
70
- description: "confidence score",
71
- examples: [0.0, 0.5, 1.0],
72
- }),
73
- file_path: Type.String({ description: "file path" }),
74
- line_start: Type.Number({ description: "start line" }),
75
- line_end: Type.Number({ description: "end line" }),
76
- });
53
+ // report_finding schema
54
+ const ReportFindingParams = z
55
+ .object({
56
+ title: z.string().describe("prefixed imperative title"),
57
+ body: z.string().describe("problem explanation"),
58
+ priority: z.enum(["P0", "P1", "P2", "P3"] as const).describe("priority 0-3"),
59
+ confidence: z.number().min(0).max(1).describe("confidence score"),
60
+ file_path: z.string().describe("file path"),
61
+ line_start: z.number().describe("start line"),
62
+ line_end: z.number().describe("end line"),
63
+ })
64
+ .strict();
77
65
 
78
66
  interface ReportFindingDetails {
79
67
  title: string;
@@ -1,7 +1,8 @@
1
1
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
2
- import { type Component, Text } from "@oh-my-pi/pi-tui";
2
+ import type { Component } from "@oh-my-pi/pi-tui";
3
+ import { Text } from "@oh-my-pi/pi-tui";
3
4
  import { prompt } from "@oh-my-pi/pi-utils";
4
- import { type Static, Type } from "@sinclair/typebox";
5
+ import * as z from "zod/v4";
5
6
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
6
7
  import type { Theme } from "../modes/theme/theme";
7
8
  import searchToolBm25Description from "../prompts/tools/search-tool-bm25.md" with { type: "text" };
@@ -30,15 +31,12 @@ const COLLAPSED_MATCH_LIMIT = 5;
30
31
  const MATCH_LABEL_LEN = 72;
31
32
  const MATCH_DESCRIPTION_LEN = 96;
32
33
 
33
- const searchToolBm25Schema = Type.Object({
34
- query: Type.String({
35
- description: "tool search query",
36
- examples: ["kubernetes pod", "image processing", "git commit"],
37
- }),
38
- limit: Type.Optional(Type.Integer({ description: "max matches", minimum: 1 })),
34
+ const searchToolBm25Schema = z.object({
35
+ query: z.string().describe("tool search query"),
36
+ limit: z.number().int().min(1).optional().describe("max matches"),
39
37
  });
40
38
 
41
- type SearchToolBm25Params = Static<typeof searchToolBm25Schema>;
39
+ type SearchToolBm25Params = z.infer<typeof searchToolBm25Schema>;
42
40
 
43
41
  interface SearchToolBm25Match {
44
42
  name: string;
@@ -1,11 +1,10 @@
1
1
  import * as path from "node:path";
2
2
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
3
-
4
3
  import { type GrepMatch, GrepOutputMode, type GrepResult, grep } from "@oh-my-pi/pi-natives";
5
4
  import type { Component } from "@oh-my-pi/pi-tui";
6
5
  import { Text } from "@oh-my-pi/pi-tui";
7
6
  import { prompt, untilAborted } from "@oh-my-pi/pi-utils";
8
- import { type Static, Type } from "@sinclair/typebox";
7
+ import * as z from "zod/v4";
9
8
  import { getFileReadCache } from "../edit/file-read-cache";
10
9
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
11
10
  import type { Theme } from "../modes/theme/theme";
@@ -31,25 +30,23 @@ import {
31
30
  import { ToolError } from "./tool-errors";
32
31
  import { toolResult } from "./tool-result";
33
32
 
34
- const searchSchema = Type.Object({
35
- pattern: Type.String({ description: "regex pattern", examples: ["function\\s+\\w+", "TODO"] }),
36
- paths: Type.Array(Type.String({ description: "file, directory, glob, or internal URL to search" }), {
37
- minItems: 1,
38
- description: "files, directories, globs, or internal URLs to search",
39
- examples: [["src/"], ["src/foo.ts"], ["src/**/*.ts"], ["src/", "packages/"]],
40
- }),
41
- i: Type.Optional(Type.Boolean({ description: "case-insensitive search", default: false })),
42
- gitignore: Type.Optional(Type.Boolean({ description: "respect gitignore", default: true })),
43
- skip: Type.Optional(
44
- Type.Number({
45
- description:
46
- "files to skip before collecting results — use to paginate when the prior call hit the file limit",
47
- default: 0,
48
- }),
49
- ),
50
- });
51
-
52
- export type SearchToolInput = Static<typeof searchSchema>;
33
+ const searchSchema = z
34
+ .object({
35
+ pattern: z.string().describe("regex pattern"),
36
+ paths: z
37
+ .array(z.string().describe("file, directory, glob, or internal URL to search"))
38
+ .min(1)
39
+ .describe("files, directories, globs, or internal URLs to search"),
40
+ i: z.boolean().optional().describe("case-insensitive search"),
41
+ gitignore: z.boolean().optional().describe("respect gitignore"),
42
+ skip: z
43
+ .number()
44
+ .optional()
45
+ .describe("files to skip before collecting results — use to paginate when the prior call hit the file limit"),
46
+ })
47
+ .strict();
48
+
49
+ export type SearchToolInput = z.infer<typeof searchSchema>;
53
50
 
54
51
  /** Maximum number of distinct files surfaced in a single response. The
55
52
  * agent paginates further pages via `skip`. */
@@ -89,7 +86,7 @@ export interface SearchToolDetails {
89
86
  missingPaths?: string[];
90
87
  }
91
88
 
92
- type SearchParams = Static<typeof searchSchema>;
89
+ type SearchParams = z.infer<typeof searchSchema>;
93
90
 
94
91
  export class SearchTool implements AgentTool<typeof searchSchema, SearchToolDetails> {
95
92
  readonly name = "search";
package/src/tools/ssh.ts CHANGED
@@ -2,7 +2,7 @@ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallb
2
2
  import type { Component } from "@oh-my-pi/pi-tui";
3
3
  import { Text } from "@oh-my-pi/pi-tui";
4
4
  import { prompt } from "@oh-my-pi/pi-utils";
5
- import { type Static, Type } from "@sinclair/typebox";
5
+ import * as z from "zod/v4";
6
6
  import type { SSHHost } from "../capability/ssh";
7
7
  import { sshCapability } from "../capability/ssh";
8
8
  import { loadCapability } from "../discovery";
@@ -21,11 +21,11 @@ import { ToolError } from "./tool-errors";
21
21
  import { toolResult } from "./tool-result";
22
22
  import { clampTimeout } from "./tool-timeouts";
23
23
 
24
- const sshSchema = Type.Object({
25
- host: Type.String({ description: "ssh host", examples: ["my-server", "prod-1"] }),
26
- command: Type.String({ description: "remote command", examples: ["ls -la", "uptime"] }),
27
- cwd: Type.Optional(Type.String({ description: "remote working directory", examples: ["/var/log"] })),
28
- timeout: Type.Optional(Type.Number({ description: "timeout in seconds", default: 60 })),
24
+ const sshSchema = z.object({
25
+ host: z.string().describe("ssh host"),
26
+ command: z.string().describe("remote command"),
27
+ cwd: z.string().optional().describe("remote working directory"),
28
+ timeout: z.number().optional().describe("timeout in seconds").default(60),
29
29
  });
30
30
 
31
31
  export interface SSHToolDetails {
@@ -116,7 +116,7 @@ async function loadHosts(session: ToolSession): Promise<{
116
116
  return { hostNames, hostsByName };
117
117
  }
118
118
 
119
- type SshToolParams = Static<typeof sshSchema>;
119
+ type SshToolParams = z.infer<typeof sshSchema>;
120
120
 
121
121
  export class SshTool implements AgentTool<typeof sshSchema, SSHToolDetails> {
122
122
  readonly name = "ssh";
@@ -1,10 +1,9 @@
1
1
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
2
- import { StringEnum } from "@oh-my-pi/pi-ai";
3
2
  import type { Component } from "@oh-my-pi/pi-tui";
4
3
  import { Text } from "@oh-my-pi/pi-tui";
5
4
  import { prompt } from "@oh-my-pi/pi-utils";
6
- import { type Static, Type } from "@sinclair/typebox";
7
5
  import chalk from "chalk";
6
+ import * as z from "zod/v4";
8
7
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
9
8
  import type { Theme } from "../modes/theme/theme";
10
9
  import todoWriteDescription from "../prompts/tools/todo-write.md" with { type: "text" };
@@ -45,45 +44,38 @@ export interface TodoWriteToolDetails {
45
44
  // Schema
46
45
  // =============================================================================
47
46
 
48
- const TodoOp = StringEnum(["init", "start", "done", "rm", "drop", "append", "note"] as const, {
49
- description: "operation to apply",
50
- });
47
+ const TodoOp = z
48
+ .enum(["init", "start", "done", "rm", "drop", "append", "note"] as const)
49
+ .describe("operation to apply");
51
50
 
52
- const InitListEntry = Type.Object({
53
- phase: Type.String({ description: "phase name (short noun phrase)", examples: ["Foundation", "Auth"] }),
54
- items: Type.Array(Type.String({ description: "task content (5-10 words)" }), {
55
- minItems: 1,
56
- description: "tasks for this phase, in execution order; all start as pending",
57
- }),
51
+ const InitListEntry = z.object({
52
+ phase: z.string().describe("phase name (short noun phrase)"),
53
+ items: z
54
+ .array(z.string().describe("task content (5-10 words)"))
55
+ .min(1)
56
+ .describe("tasks for this phase, in execution order; all start as pending"),
58
57
  });
59
58
 
60
- const TodoOpEntry = Type.Object({
59
+ const TodoOpEntry = z.object({
61
60
  op: TodoOp,
62
- list: Type.Optional(Type.Array(InitListEntry, { description: "phased task list for op=init" })),
63
- task: Type.Optional(
64
- Type.String({ description: "task content for start/done/rm/drop/note", examples: ["Run tests"] }),
65
- ),
66
- phase: Type.Optional(Type.String({ description: "phase name for done/rm/drop/append", examples: ["Auth"] })),
67
- items: Type.Optional(
68
- Type.Array(Type.String({ description: "task content (5-10 words)" }), {
69
- minItems: 1,
70
- description: "tasks to append to `phase` for op=append",
71
- }),
72
- ),
73
- text: Type.Optional(Type.String({ description: "note text for op=note (appended with newline)" })),
61
+ list: z.array(InitListEntry).optional().describe("phased task list for op=init"),
62
+ task: z.string().optional().describe("task content for start/done/rm/drop/note"),
63
+ phase: z.string().optional().describe("phase name for done/rm/drop/append"),
64
+ items: z
65
+ .array(z.string().describe("task content (5-10 words)"))
66
+ .min(1)
67
+ .optional()
68
+ .describe("tasks to append to `phase` for op=append"),
69
+ text: z.string().optional().describe("note text for op=note (appended with newline)"),
74
70
  });
75
71
 
76
- const todoWriteSchema = Type.Object(
77
- {
78
- ops: Type.Array(TodoOpEntry, {
79
- minItems: 1,
80
- description: "ordered todo operations",
81
- }),
82
- },
83
- { description: "Apply ordered todo operations" },
84
- );
72
+ const todoWriteSchema = z
73
+ .object({
74
+ ops: z.array(TodoOpEntry).min(1).describe("ordered todo operations"),
75
+ })
76
+ .describe("Apply ordered todo operations");
85
77
 
86
- type TodoWriteParams = Static<typeof todoWriteSchema>;
78
+ type TodoWriteParams = z.infer<typeof todoWriteSchema>;
87
79
  type TodoOpEntryValue = TodoWriteParams["ops"][number];
88
80
 
89
81
  // =============================================================================
package/src/tools/vim.ts CHANGED
@@ -2,8 +2,8 @@ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallb
2
2
  import type { Component } from "@oh-my-pi/pi-tui";
3
3
  import { extractSegments, sliceWithWidth, Text } from "@oh-my-pi/pi-tui";
4
4
  import { isEnoent, logger, prompt, untilAborted } from "@oh-my-pi/pi-utils";
5
- import { type Static, Type } from "@sinclair/typebox";
6
5
  import * as Diff from "diff";
6
+ import * as z from "zod/v4";
7
7
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
8
8
  import { createLspWritethrough, type FileDiagnosticsResult, type WritethroughCallback, writethroughNoop } from "../lsp";
9
9
  import { getLanguageFromPath, highlightCode, type Theme } from "../modes/theme/theme";
@@ -36,35 +36,19 @@ import { toolResult } from "./tool-result";
36
36
  const INTERNAL_URL_PREFIX = /^(agent|artifact|skill|rule|local|mcp):\/\//;
37
37
  const utf8Decoder = new TextDecoder("utf-8", { fatal: true });
38
38
 
39
- const vimStepSchema = Type.Object({
40
- kbd: Type.Array(Type.String(), {
41
- description: "vim key sequences",
42
- examples: [["ggdGi"], ["3Go"], ["dd"]],
43
- }),
44
- insert: Type.Optional(
45
- Type.String({
46
- description: "raw text to insert",
47
- examples: ["hello world"],
48
- }),
49
- ),
39
+ const vimStepSchema = z.object({
40
+ kbd: z.array(z.string()).describe("vim key sequences"),
41
+ insert: z.string().optional().describe("raw text to insert"),
50
42
  });
51
43
 
52
- const vimSchema = Type.Object({
53
- file: Type.String({ description: "file path", examples: ["src/foo.ts"] }),
54
- steps: Type.Optional(
55
- Type.Array(vimStepSchema, {
56
- description: "editing steps",
57
- }),
58
- ),
59
- pause: Type.Optional(
60
- Type.Boolean({
61
- description: "skip auto-save",
62
- }),
63
- ),
44
+ const vimSchema = z.object({
45
+ file: z.string().describe("file path"),
46
+ steps: z.array(vimStepSchema).optional().describe("editing steps"),
47
+ pause: z.boolean().optional().describe("skip auto-save"),
64
48
  });
65
49
 
66
- type VimParams = Static<typeof vimSchema>;
67
- type VimStep = Static<typeof vimStepSchema>;
50
+ type VimParams = z.infer<typeof vimSchema>;
51
+ type VimStep = z.infer<typeof vimStepSchema>;
68
52
 
69
53
  interface VimRenderStep {
70
54
  kbd?: string[];
@@ -5,7 +5,7 @@ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallb
5
5
  import type { Component } from "@oh-my-pi/pi-tui";
6
6
  import { Text } from "@oh-my-pi/pi-tui";
7
7
  import { isEnoent, isRecord, prompt, untilAborted } from "@oh-my-pi/pi-utils";
8
- import { type Static, Type } from "@sinclair/typebox";
8
+ import * as z from "zod/v4";
9
9
  import { stripHashlinePrefixes } from "../edit";
10
10
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
11
11
  import { InternalUrlRouter } from "../internal-urls";
@@ -58,12 +58,12 @@ async function loadFflate(): Promise<typeof import("fflate")> {
58
58
  return fflateModulePromise;
59
59
  }
60
60
 
61
- const writeSchema = Type.Object({
62
- path: Type.String({ description: "file path", examples: ["src/new.ts"] }),
63
- content: Type.String({ description: "file content" }),
61
+ const writeSchema = z.object({
62
+ path: z.string().describe("file path"),
63
+ content: z.string().describe("file content"),
64
64
  });
65
65
 
66
- export type WriteToolInput = Static<typeof writeSchema>;
66
+ export type WriteToolInput = z.infer<typeof writeSchema>;
67
67
 
68
68
  /** Details returned by the write tool for TUI rendering */
69
69
  export interface WriteToolDetails {