@oh-my-pi/pi-coding-agent 16.0.5 → 16.0.7

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 (223) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/dist/cli.js +1945 -1386
  3. package/dist/types/advisor/advise-tool.d.ts +22 -19
  4. package/dist/types/autoresearch/tools/init-experiment.d.ts +13 -17
  5. package/dist/types/autoresearch/tools/log-experiment.d.ts +17 -19
  6. package/dist/types/autoresearch/tools/run-experiment.d.ts +3 -4
  7. package/dist/types/autoresearch/tools/update-notes.d.ts +4 -5
  8. package/dist/types/cli/ttsr-cli.d.ts +39 -0
  9. package/dist/types/commands/ttsr.d.ts +57 -0
  10. package/dist/types/commit/agentic/tools/analyze-file.d.ts +4 -5
  11. package/dist/types/commit/agentic/tools/git-file-diff.d.ts +4 -5
  12. package/dist/types/commit/agentic/tools/git-hunk.d.ts +5 -6
  13. package/dist/types/commit/agentic/tools/git-overview.d.ts +4 -5
  14. package/dist/types/commit/agentic/tools/propose-changelog.d.ts +23 -24
  15. package/dist/types/commit/agentic/tools/propose-commit.d.ts +11 -32
  16. package/dist/types/commit/agentic/tools/recent-commits.d.ts +3 -4
  17. package/dist/types/commit/agentic/tools/schemas.d.ts +6 -27
  18. package/dist/types/commit/agentic/tools/split-commit.d.ts +28 -49
  19. package/dist/types/commit/changelog/generate.d.ts +12 -13
  20. package/dist/types/commit/shared-llm.d.ts +10 -37
  21. package/dist/types/config/config-file.d.ts +4 -4
  22. package/dist/types/config/keybindings.d.ts +5 -0
  23. package/dist/types/config/models-config-schema.d.ts +625 -990
  24. package/dist/types/config/models-config.d.ts +229 -217
  25. package/dist/types/config/settings-schema.d.ts +53 -23
  26. package/dist/types/edit/hashline/params.d.ts +7 -11
  27. package/dist/types/edit/index.d.ts +2 -1
  28. package/dist/types/edit/modes/apply-patch.d.ts +4 -5
  29. package/dist/types/edit/modes/patch.d.ts +15 -24
  30. package/dist/types/edit/modes/replace.d.ts +16 -17
  31. package/dist/types/eval/js/index.d.ts +1 -0
  32. package/dist/types/extensibility/custom-commands/types.d.ts +6 -3
  33. package/dist/types/extensibility/custom-tools/types.d.ts +8 -5
  34. package/dist/types/extensibility/extensions/types.d.ts +6 -3
  35. package/dist/types/extensibility/hooks/types.d.ts +7 -4
  36. package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +13 -5
  37. package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +17 -0
  38. package/dist/types/extensibility/typebox.d.ts +80 -58
  39. package/dist/types/goals/tools/goal-tool.d.ts +11 -24
  40. package/dist/types/index.d.ts +2 -0
  41. package/dist/types/lsp/index.d.ts +11 -26
  42. package/dist/types/lsp/types.d.ts +12 -28
  43. package/dist/types/mcp/client.d.ts +8 -0
  44. package/dist/types/modes/components/btw-panel.d.ts +1 -0
  45. package/dist/types/modes/components/custom-editor.d.ts +3 -1
  46. package/dist/types/modes/controllers/btw-controller.d.ts +2 -0
  47. package/dist/types/modes/controllers/input-controller.d.ts +1 -0
  48. package/dist/types/modes/interactive-mode.d.ts +3 -0
  49. package/dist/types/modes/setup-wizard/index.d.ts +1 -0
  50. package/dist/types/modes/setup-wizard/startup-splash.d.ts +7 -0
  51. package/dist/types/modes/theme/theme.d.ts +1 -1
  52. package/dist/types/modes/types.d.ts +3 -0
  53. package/dist/types/sdk.d.ts +5 -0
  54. package/dist/types/session/agent-session.d.ts +4 -0
  55. package/dist/types/startup-splash.d.ts +12 -0
  56. package/dist/types/task/types.d.ts +47 -48
  57. package/dist/types/tools/ask.d.ts +26 -27
  58. package/dist/types/tools/ast-edit.d.ts +17 -17
  59. package/dist/types/tools/ast-grep.d.ts +12 -13
  60. package/dist/types/tools/bash.d.ts +20 -17
  61. package/dist/types/tools/browser.d.ts +46 -71
  62. package/dist/types/tools/checkpoint.d.ts +14 -15
  63. package/dist/types/tools/debug.d.ts +82 -145
  64. package/dist/types/tools/eval.d.ts +30 -40
  65. package/dist/types/tools/find.d.ts +17 -18
  66. package/dist/types/tools/gh.d.ts +49 -78
  67. package/dist/types/tools/image-gen.d.ts +20 -36
  68. package/dist/types/tools/inspect-image.d.ts +10 -11
  69. package/dist/types/tools/irc.d.ts +22 -33
  70. package/dist/types/tools/job.d.ts +11 -12
  71. package/dist/types/tools/learn.d.ts +21 -28
  72. package/dist/types/tools/manage-skill.d.ts +13 -22
  73. package/dist/types/tools/memory-edit.d.ts +15 -24
  74. package/dist/types/tools/memory-recall.d.ts +7 -8
  75. package/dist/types/tools/memory-reflect.d.ts +9 -10
  76. package/dist/types/tools/memory-retain.d.ts +13 -14
  77. package/dist/types/tools/read.d.ts +7 -8
  78. package/dist/types/tools/resolve.d.ts +11 -18
  79. package/dist/types/tools/review.d.ts +9 -15
  80. package/dist/types/tools/search-tool-bm25.d.ts +9 -10
  81. package/dist/types/tools/search.d.ts +16 -17
  82. package/dist/types/tools/ssh.d.ts +14 -15
  83. package/dist/types/tools/todo.d.ts +27 -43
  84. package/dist/types/tools/tts.d.ts +8 -9
  85. package/dist/types/tools/write.d.ts +9 -10
  86. package/dist/types/tui/index.d.ts +1 -0
  87. package/dist/types/tui/width-aware-text.d.ts +23 -0
  88. package/dist/types/utils/markit.d.ts +10 -1
  89. package/dist/types/web/search/index.d.ts +17 -28
  90. package/dist/types/web/search/providers/perplexity.d.ts +0 -2
  91. package/dist/types/web/search/types.d.ts +32 -26
  92. package/package.json +14 -13
  93. package/scripts/omp +1 -1
  94. package/src/advisor/__tests__/advisor.test.ts +44 -1
  95. package/src/advisor/advise-tool.ts +34 -11
  96. package/src/autoresearch/tools/init-experiment.ts +13 -16
  97. package/src/autoresearch/tools/log-experiment.ts +15 -18
  98. package/src/autoresearch/tools/run-experiment.ts +3 -3
  99. package/src/autoresearch/tools/update-notes.ts +4 -4
  100. package/src/cli/ttsr-cli.ts +995 -0
  101. package/src/cli-commands.ts +1 -0
  102. package/src/cli.ts +7 -1
  103. package/src/commands/ttsr.ts +125 -0
  104. package/src/commit/agentic/tools/analyze-file.ts +4 -4
  105. package/src/commit/agentic/tools/git-file-diff.ts +4 -4
  106. package/src/commit/agentic/tools/git-hunk.ts +7 -5
  107. package/src/commit/agentic/tools/git-overview.ts +4 -4
  108. package/src/commit/agentic/tools/propose-changelog.ts +18 -15
  109. package/src/commit/agentic/tools/propose-commit.ts +6 -6
  110. package/src/commit/agentic/tools/recent-commits.ts +3 -3
  111. package/src/commit/agentic/tools/schemas.ts +8 -20
  112. package/src/commit/agentic/tools/split-commit.ts +19 -23
  113. package/src/commit/analysis/summary.ts +7 -5
  114. package/src/commit/changelog/generate.ts +15 -11
  115. package/src/commit/shared-llm.ts +17 -24
  116. package/src/config/config-file.ts +13 -15
  117. package/src/config/keybindings.ts +6 -0
  118. package/src/config/models-config-schema.ts +206 -179
  119. package/src/config/settings-schema.ts +34 -0
  120. package/src/discovery/builtin-rules/index.ts +2 -0
  121. package/src/discovery/builtin-rules/ts-import-type.md +2 -2
  122. package/src/discovery/builtin-rules/ts-no-any.md +11 -2
  123. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
  124. package/src/edit/hashline/params.ts +12 -11
  125. package/src/edit/index.ts +5 -4
  126. package/src/edit/modes/apply-patch.ts +4 -4
  127. package/src/edit/modes/patch.ts +15 -18
  128. package/src/edit/modes/replace.ts +13 -17
  129. package/src/edit/renderer.ts +0 -1
  130. package/src/eval/agent-bridge.ts +11 -13
  131. package/src/eval/completion-bridge.ts +25 -17
  132. package/src/eval/js/context-manager.ts +17 -2
  133. package/src/eval/js/index.ts +1 -1
  134. package/src/eval/py/executor.ts +2 -2
  135. package/src/extensibility/custom-commands/loader.ts +5 -3
  136. package/src/extensibility/custom-commands/types.ts +6 -3
  137. package/src/extensibility/custom-tools/loader.ts +4 -2
  138. package/src/extensibility/custom-tools/types.ts +8 -5
  139. package/src/extensibility/extensions/loader.ts +4 -2
  140. package/src/extensibility/extensions/types.ts +6 -3
  141. package/src/extensibility/hooks/loader.ts +5 -2
  142. package/src/extensibility/hooks/types.ts +7 -4
  143. package/src/extensibility/legacy-pi-ai-shim.ts +42 -5
  144. package/src/extensibility/legacy-pi-coding-agent-shim.ts +113 -0
  145. package/src/extensibility/plugins/legacy-pi-compat.ts +13 -13
  146. package/src/extensibility/tool-proxy.ts +4 -1
  147. package/src/extensibility/typebox.ts +778 -251
  148. package/src/goals/guided-setup.ts +12 -3
  149. package/src/goals/tools/goal-tool.ts +6 -6
  150. package/src/index.ts +2 -0
  151. package/src/internal-urls/docs-index.generated.ts +11 -9
  152. package/src/lsp/types.ts +13 -27
  153. package/src/main.ts +19 -18
  154. package/src/mcp/client.ts +38 -13
  155. package/src/mcp/render.ts +102 -89
  156. package/src/modes/components/agent-hub.ts +11 -4
  157. package/src/modes/components/btw-panel.ts +5 -1
  158. package/src/modes/components/custom-editor.ts +18 -0
  159. package/src/modes/components/status-line/component.ts +8 -1
  160. package/src/modes/components/tool-execution.ts +17 -10
  161. package/src/modes/controllers/btw-controller.ts +69 -1
  162. package/src/modes/controllers/input-controller.ts +29 -0
  163. package/src/modes/interactive-mode.ts +38 -8
  164. package/src/modes/setup-wizard/index.ts +1 -0
  165. package/src/modes/setup-wizard/scenes/sign-in.ts +77 -5
  166. package/src/modes/setup-wizard/startup-splash.ts +107 -0
  167. package/src/modes/theme/theme.ts +133 -143
  168. package/src/modes/types.ts +3 -0
  169. package/src/modes/utils/context-usage.ts +9 -5
  170. package/src/modes/utils/hotkeys-markdown.ts +1 -0
  171. package/src/prompts/system/system-prompt.md +1 -0
  172. package/src/sdk.ts +21 -4
  173. package/src/session/agent-session.ts +173 -33
  174. package/src/session/session-history-format.ts +11 -2
  175. package/src/session/snapcompact-inline.ts +1 -1
  176. package/src/slash-commands/builtin-registry.ts +3 -10
  177. package/src/startup-splash.ts +19 -0
  178. package/src/task/executor.ts +11 -6
  179. package/src/task/types.ts +44 -41
  180. package/src/tool-discovery/tool-index.ts +17 -4
  181. package/src/tools/ask.ts +14 -14
  182. package/src/tools/ast-edit.ts +17 -14
  183. package/src/tools/ast-grep.ts +10 -9
  184. package/src/tools/bash.ts +15 -10
  185. package/src/tools/browser/launch.ts +13 -0
  186. package/src/tools/browser.ts +26 -32
  187. package/src/tools/checkpoint.ts +7 -7
  188. package/src/tools/debug.ts +72 -69
  189. package/src/tools/eval.ts +18 -19
  190. package/src/tools/find.ts +20 -13
  191. package/src/tools/gh.ts +29 -49
  192. package/src/tools/image-gen.ts +27 -32
  193. package/src/tools/inspect-image.ts +8 -9
  194. package/src/tools/irc.ts +12 -12
  195. package/src/tools/job.ts +6 -6
  196. package/src/tools/learn.ts +11 -14
  197. package/src/tools/manage-skill.ts +19 -23
  198. package/src/tools/memory-edit.ts +8 -8
  199. package/src/tools/memory-recall.ts +4 -4
  200. package/src/tools/memory-reflect.ts +5 -5
  201. package/src/tools/memory-retain.ts +9 -11
  202. package/src/tools/puppeteer/02_stealth_hairline.txt +1 -1
  203. package/src/tools/puppeteer/04_stealth_iframe.txt +4 -4
  204. package/src/tools/puppeteer/05_stealth_webgl.txt +1 -1
  205. package/src/tools/puppeteer/10_stealth_plugins.txt +6 -4
  206. package/src/tools/puppeteer/12_stealth_codecs.txt +2 -2
  207. package/src/tools/puppeteer/13_stealth_worker.txt +1 -1
  208. package/src/tools/read.ts +169 -13
  209. package/src/tools/report-tool-issue.ts +6 -6
  210. package/src/tools/resolve.ts +6 -6
  211. package/src/tools/review.ts +10 -12
  212. package/src/tools/search-tool-bm25.ts +5 -5
  213. package/src/tools/search.ts +20 -29
  214. package/src/tools/ssh.ts +8 -8
  215. package/src/tools/todo.ts +16 -19
  216. package/src/tools/tts.ts +16 -15
  217. package/src/tools/write.ts +5 -5
  218. package/src/tui/index.ts +1 -0
  219. package/src/tui/width-aware-text.ts +58 -0
  220. package/src/utils/markit.ts +17 -2
  221. package/src/web/search/index.ts +9 -9
  222. package/src/web/search/providers/perplexity.ts +373 -126
  223. package/src/web/search/types.ts +28 -48
@@ -1,18 +1,19 @@
1
1
  /**
2
- * Zod schema for the `edit` tool's hashline mode payload. The schema is
3
- * deliberately permissive (`.passthrough()`) so providers can attach extra
2
+ * Arktype schema for the `edit` tool's hashline mode payload. The schema is
3
+ * deliberately permissive (allows extra keys) so providers can attach extra
4
4
  * keys without rejection; only `input` is required. `_input` is accepted as a
5
5
  * provider-emitted alias for `input`.
6
6
  */
7
- import { z } from "zod/v4";
7
+ import { type } from "arktype";
8
8
 
9
- export const hashlineEditParamsSchema = z.preprocess(raw => {
10
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) return raw;
9
+ const requiredInputSchema = type({ input: "string" });
10
+ const inputAliasSchema = type({ "input?": "string", "_input?": "string" });
11
11
 
12
- const record = raw as Record<string, unknown>;
13
- if (typeof record.input === "string" || typeof record._input !== "string") return raw;
12
+ export const hashlineEditParamsSchema = inputAliasSchema
13
+ .pipe(raw => {
14
+ if (raw.input !== undefined || raw._input === undefined) return raw;
15
+ return { ...raw, input: raw._input };
16
+ })
17
+ .pipe(requiredInputSchema);
14
18
 
15
- return { ...record, input: record._input };
16
- }, z.object({ input: z.string() }).passthrough());
17
-
18
- export type HashlineParams = z.infer<typeof hashlineEditParamsSchema>;
19
+ export type HashlineParams = Parameters<typeof hashlineEditParamsSchema.assert>[0];
package/src/edit/index.ts CHANGED
@@ -4,7 +4,6 @@ import hashlineDescription from "@oh-my-pi/hashline/prompt.md" with { type: "tex
4
4
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
5
5
  import type { ToolExample } from "@oh-my-pi/pi-ai";
6
6
  import { prompt } from "@oh-my-pi/pi-utils";
7
- import type { z } from "zod/v4";
8
7
  import {
9
8
  createLspWritethrough,
10
9
  type FileDiagnosticsResult,
@@ -20,7 +19,7 @@ import type { DeferredDiagnosticsEntry, ToolSession } from "../tools";
20
19
  import { truncateForPrompt } from "../tools/approval";
21
20
  import { isInternalUrlPath } from "../tools/path-utils";
22
21
  import { type EditMode, normalizeEditMode, resolveEditMode } from "../utils/edit-mode";
23
- import { executeHashlineSingle, type HashlineParams, hashlineEditParamsSchema } from "./hashline";
22
+ import { executeHashlineSingle, hashlineEditParamsSchema } from "./hashline";
24
23
  import { type ApplyPatchParams, applyPatchSchema, expandApplyPatchToEntries } from "./modes/apply-patch";
25
24
  import applyPatchGrammar from "./modes/apply-patch.lark" with { type: "text" };
26
25
  import { executePatchSingle, type PatchEditEntry, type PatchParams, patchEditSchema } from "./modes/patch";
@@ -47,6 +46,8 @@ type TInput =
47
46
  | typeof hashlineEditParamsSchema
48
47
  | typeof applyPatchSchema;
49
48
 
49
+ type HashlineParams = typeof hashlineEditParamsSchema.infer;
50
+
50
51
  type EditParams = ReplaceParams | PatchParams | HashlineParams | ApplyPatchParams;
51
52
 
52
53
  type EditModeDefinition = {
@@ -443,7 +444,7 @@ export class EditTool implements AgentTool<TInput> {
443
444
  caption: "Multiple entries",
444
445
  note: "All entries in one call apply to the top-level `path`; use separate calls for different files.",
445
446
  },
446
- ] satisfies readonly ToolExample<z.input<typeof patchEditSchema>>[],
447
+ ] satisfies readonly ToolExample<PatchParams>[],
447
448
  execute: (
448
449
  tool: EditTool,
449
450
  params: EditParams,
@@ -479,7 +480,7 @@ export class EditTool implements AgentTool<TInput> {
479
480
  input: '*** Begin Patch\n*** Add File: hello.txt\n+Hello world\n*** Update File: src/app.py\n*** Move to: src/main.py\n@@ def greet():\n-print("Hi")\n+print("Hello, world!")\n*** Delete File: obsolete.txt\n*** End Patch\n',
480
481
  },
481
482
  },
482
- ] satisfies readonly ToolExample<z.input<typeof applyPatchSchema>>[],
483
+ ] satisfies readonly ToolExample<ApplyPatchParams>[],
483
484
  execute: (
484
485
  tool: EditTool,
485
486
  params: EditParams,
@@ -8,16 +8,16 @@
8
8
  * the `patch` mode.
9
9
  */
10
10
 
11
- import { z } from "zod/v4";
11
+ import { type } from "arktype";
12
12
  import { parseApplyPatch, parseApplyPatchStreaming } from "../apply-patch/parser";
13
13
  import { ApplyPatchError } from "../diff";
14
14
  import type { PatchEditEntry } from "./patch";
15
15
 
16
- export const applyPatchSchema = z.object({
17
- input: z.string().describe("apply_patch envelope"),
16
+ export const applyPatchSchema = type({
17
+ input: "string",
18
18
  });
19
19
 
20
- export type ApplyPatchParams = z.infer<typeof applyPatchSchema>;
20
+ export type ApplyPatchParams = typeof applyPatchSchema.infer;
21
21
 
22
22
  export type ApplyPatchEntry = PatchEditEntry & { path: string };
23
23
 
@@ -9,7 +9,7 @@ import * as fs from "node:fs";
9
9
  import * as path from "node:path";
10
10
  import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
11
11
  import { isEnoent } from "@oh-my-pi/pi-utils";
12
- import { z } from "zod/v4";
12
+ import { type } from "arktype";
13
13
  import {
14
14
  type FileDiagnosticsResult,
15
15
  flushLspWritethroughBatch,
@@ -1631,23 +1631,20 @@ export async function computePatchDiff(
1631
1631
  }
1632
1632
  }
1633
1633
 
1634
- export const patchEditEntrySchema = z
1635
- .object({
1636
- op: z.enum(["create", "delete", "update"]).optional().describe("operation (default update)"),
1637
- rename: z.string().describe("new path for move").optional(),
1638
- diff: z.string().describe("diff hunks or full content for create").optional(),
1639
- })
1640
- .strict();
1641
-
1642
- export const patchEditSchema = z
1643
- .object({
1644
- path: z.string().describe("file path"),
1645
- edits: z.array(patchEditEntrySchema).min(1).describe("patch operations"),
1646
- })
1647
- .strict();
1648
-
1649
- export type PatchEditEntry = z.infer<typeof patchEditEntrySchema>;
1650
- export type PatchParams = z.infer<typeof patchEditSchema>;
1634
+ export const patchEditEntrySchema = type({
1635
+ "op?": "'create' | 'delete' | 'update'",
1636
+ "rename?": "string",
1637
+ "diff?": "string",
1638
+ });
1639
+
1640
+ export type PatchEditEntry = typeof patchEditEntrySchema.infer;
1641
+
1642
+ export const patchEditSchema = type({
1643
+ path: "string",
1644
+ edits: patchEditEntrySchema.array(),
1645
+ });
1646
+
1647
+ export type PatchParams = typeof patchEditSchema.infer;
1651
1648
 
1652
1649
  export interface ExecutePatchSingleOptions {
1653
1650
  session: ToolSession;
@@ -5,7 +5,7 @@
5
5
  * fallback strategies for finding text in files.
6
6
  */
7
7
  import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
8
- import { z } from "zod/v4";
8
+ import { type } from "arktype";
9
9
  import type { WritethroughCallback, WritethroughDeferredHandle } from "../../lsp";
10
10
  import type { ToolSession } from "../../tools";
11
11
  import { invalidateFsScanAfterWrite } from "../../tools/fs-cache-invalidation";
@@ -1010,23 +1010,19 @@ export function findContextLine(
1010
1010
  return { index: undefined, confidence: bestScore };
1011
1011
  }
1012
1012
 
1013
- export const replaceEditEntrySchema = z
1014
- .object({
1015
- old_text: z.string().describe("text to find"),
1016
- new_text: z.string().describe("replacement text"),
1017
- all: z.boolean().describe("replace all occurrences").optional(),
1018
- })
1019
- .strict();
1013
+ export const replaceEditEntrySchema = type({
1014
+ old_text: "string",
1015
+ new_text: "string",
1016
+ "all?": "boolean",
1017
+ });
1020
1018
 
1021
- export const replaceEditSchema = z
1022
- .object({
1023
- path: z.string().describe("file path"),
1024
- edits: z.array(replaceEditEntrySchema).min(1).describe("replacements"),
1025
- })
1026
- .strict();
1019
+ export const replaceEditSchema = type({
1020
+ path: "string",
1021
+ edits: replaceEditEntrySchema.array(),
1022
+ });
1027
1023
 
1028
- export type ReplaceEditEntry = z.infer<typeof replaceEditEntrySchema>;
1029
- export type ReplaceParams = z.infer<typeof replaceEditSchema>;
1024
+ export type ReplaceEditEntry = typeof replaceEditEntrySchema.infer;
1025
+ export type ReplaceParams = typeof replaceEditSchema.infer;
1030
1026
 
1031
1027
  export interface ExecuteReplaceSingleOptions {
1032
1028
  session: ToolSession;
@@ -1042,7 +1038,7 @@ export interface ExecuteReplaceSingleOptions {
1042
1038
 
1043
1039
  export async function executeReplaceSingle(
1044
1040
  options: ExecuteReplaceSingleOptions,
1045
- ): Promise<AgentToolResult<EditToolDetails, typeof replaceEditEntrySchema>> {
1041
+ ): Promise<AgentToolResult<EditToolDetails, ReplaceEditEntry>> {
1046
1042
  const {
1047
1043
  session,
1048
1044
  path,
@@ -591,7 +591,6 @@ export const editToolRenderer = {
591
591
  uiTheme: Theme,
592
592
  ): Component {
593
593
  const renderContext = options.renderContext;
594
-
595
594
  const editArgs = args as EditRenderArgs;
596
595
  const hashlineInputSummary = getHashlineInputRenderSummary(editArgs, renderContext?.editMode);
597
596
  const applyPatchSummary = getApplyPatchRenderSummary(editArgs, options.isPartial, renderContext?.editMode);
@@ -5,7 +5,7 @@ import * as fs from "node:fs/promises";
5
5
  import * as os from "node:os";
6
6
  import * as path from "node:path";
7
7
  import { prompt, Snowflake } from "@oh-my-pi/pi-utils";
8
- import { z } from "zod/v4";
8
+ import { type } from "arktype";
9
9
  import { resolveAgentModelPatterns } from "../config/model-resolver";
10
10
  import type { LocalProtocolOptions } from "../internal-urls";
11
11
  import { MCPManager } from "../mcp/manager";
@@ -31,12 +31,12 @@ export const EVAL_AGENT_MAX_DEPTH = 3;
31
31
  const DEFAULT_AGENT_TYPE = "task";
32
32
  const DEFAULT_AGENT_LABEL = "EvalAgent";
33
33
 
34
- const agentArgsSchema = z.object({
35
- prompt: z.string().min(1, "prompt must be a non-empty string"),
36
- agentType: z.string().min(1).optional(),
37
- model: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]).optional(),
38
- label: z.string().optional(),
39
- schema: z.unknown().optional(),
34
+ const agentArgsSchema = type({
35
+ prompt: "string>0",
36
+ "agentType?": "string>0",
37
+ "model?": "string>0|string>0[]",
38
+ "label?": "string",
39
+ "schema?": "unknown",
40
40
  });
41
41
 
42
42
  interface EvalAgentArgs {
@@ -64,13 +64,11 @@ export interface EvalAgentResult {
64
64
  }
65
65
 
66
66
  function parseAgentArgs(args: unknown): EvalAgentArgs {
67
- const parsed = agentArgsSchema.safeParse(args);
68
- if (!parsed.success) {
69
- const issue = parsed.error.issues[0];
70
- const where = issue?.path.length ? `${issue.path.join(".")}: ` : "";
71
- throw new ToolError(`agent() received invalid arguments: ${where}${issue?.message ?? "bad input"}`);
67
+ const result = agentArgsSchema(args);
68
+ if (result instanceof type.errors) {
69
+ throw new ToolError(`agent() received invalid arguments: ${result.summary}`);
72
70
  }
73
- return parsed.data;
71
+ return result;
74
72
  }
75
73
 
76
74
  function assertDepthAllowed(session: ToolSession): void {
@@ -14,7 +14,7 @@
14
14
  import { instrumentedCompleteSimple, resolveTelemetry } from "@oh-my-pi/pi-agent-core";
15
15
  import { type Api, Effort, type Model, type Tool } from "@oh-my-pi/pi-ai";
16
16
  import { getSupportedEfforts } from "@oh-my-pi/pi-catalog/model-thinking";
17
- import { z } from "zod/v4";
17
+ import { type } from "arktype";
18
18
  import { extractTextContent, extractToolCall, parseJsonPayload } from "../commit/utils";
19
19
 
20
20
  import {
@@ -42,11 +42,11 @@ const TIER_TO_PATTERN: Record<CompletionTier, string> = {
42
42
  slow: "pi/slow",
43
43
  };
44
44
 
45
- const completionArgsSchema = z.object({
46
- prompt: z.string().min(1, "prompt must be a non-empty string"),
47
- model: z.enum(["smol", "default", "slow"]).default("default"),
48
- system: z.string().optional(),
49
- schema: z.record(z.string(), z.unknown()).optional(),
45
+ const completionArgsSchema = type({
46
+ prompt: "string>0",
47
+ "model?": "'smol'|'default'|'slow'",
48
+ "system?": "string",
49
+ "schema?": "Record<string,unknown>",
50
50
  });
51
51
 
52
52
  export interface EvalCompletionBridgeOptions {
@@ -107,18 +107,18 @@ export async function runEvalCompletion(
107
107
  args: unknown,
108
108
  options: EvalCompletionBridgeOptions,
109
109
  ): Promise<EvalCompletionResult> {
110
- const parsed = completionArgsSchema.safeParse(args);
111
- if (!parsed.success) {
112
- const issue = parsed.error.issues[0];
113
- const where = issue?.path.length ? `${issue.path.join(".")}: ` : "";
114
- throw new ToolError(`completion() received invalid arguments: ${where}${issue?.message ?? "bad input"}`);
110
+ const parsed = completionArgsSchema(args);
111
+ if (parsed instanceof type.errors) {
112
+ throw new ToolError(`completion() received invalid arguments: ${parsed.summary}`);
115
113
  }
116
- const { prompt, model: tier, system, schema } = parsed.data;
114
+ const { prompt, model: modelTier, system, schema } = parsed;
115
+ // Apply default value for model if not provided
116
+ const finalTier: CompletionTier = modelTier ?? "default";
117
117
 
118
- const model = resolveTierModel(tier, options.session);
118
+ const model = resolveTierModel(finalTier, options.session);
119
119
  if (!model) {
120
120
  throw new ToolError(
121
- `completion() could not resolve a model for the "${tier}" tier. Configure modelRoles.${tier === "default" ? "default" : tier} or ensure a provider is available.`,
121
+ `completion() could not resolve a model for the "${finalTier}" tier. Configure modelRoles.${finalTier === "default" ? "default" : finalTier} or ensure a provider is available.`,
122
122
  );
123
123
  }
124
124
 
@@ -162,7 +162,7 @@ export async function runEvalCompletion(
162
162
  {
163
163
  apiKey: registry.resolver(model, options.session.getSessionId?.() ?? undefined),
164
164
  signal: options.signal,
165
- reasoning: reasoningForTier(tier, model),
165
+ reasoning: reasoningForTier(finalTier, model),
166
166
  toolChoice: schema ? { type: "tool", name: STRUCTURED_TOOL_NAME } : undefined,
167
167
  },
168
168
  { telemetry, oneshotKind: "eval_completion" },
@@ -197,7 +197,15 @@ export async function runEvalCompletion(
197
197
  if (!resultText) throw new ToolError("completion() returned no text output.");
198
198
  }
199
199
 
200
- options.emitStatus?.({ op: "completion", model: formatModelString(model), tier, chars: resultText.length });
200
+ options.emitStatus?.({
201
+ op: "completion",
202
+ model: formatModelString(model),
203
+ tier: finalTier,
204
+ chars: resultText.length,
205
+ });
201
206
 
202
- return { text: resultText, details: { model: formatModelString(model), tier, structured: Boolean(schema) } };
207
+ return {
208
+ text: resultText,
209
+ details: { model: formatModelString(model), tier: finalTier, structured: Boolean(schema) },
210
+ };
203
211
  }
@@ -44,6 +44,8 @@ interface PendingRun {
44
44
 
45
45
  interface JsSession {
46
46
  sessionKey: string;
47
+ sessionId: string;
48
+ cwd: string;
47
49
  worker: WorkerHandle;
48
50
  state: "alive" | "dead";
49
51
  pending: Map<string, PendingRun>;
@@ -151,7 +153,14 @@ export async function disposeAllVmContexts(): Promise<void> {
151
153
  */
152
154
  export async function smokeTestJsEvalWorker(): Promise<void> {
153
155
  const worker = spawnJsWorker();
154
- const session: JsSession = { sessionKey: "smoke", worker, state: "alive", pending: new Map() };
156
+ const session: JsSession = {
157
+ sessionKey: "smoke",
158
+ sessionId: "smoke",
159
+ cwd: process.cwd(),
160
+ worker,
161
+ state: "alive",
162
+ pending: new Map(),
163
+ };
155
164
  try {
156
165
  await initWorker(session, { cwd: process.cwd(), sessionId: "smoke" }, WORKER_INIT_TIMEOUT_MS);
157
166
  if (worker.mode !== "worker") {
@@ -219,7 +228,11 @@ async function runOnce(
219
228
 
220
229
  async function acquireSession(sessionKey: string, snapshot: SessionSnapshot, timeoutMs?: number): Promise<JsSession> {
221
230
  const existing = sessions.get(sessionKey);
222
- if (existing && existing.state === "alive") return existing;
231
+ if (existing && existing.state === "alive") {
232
+ existing.sessionId = snapshot.sessionId;
233
+ existing.cwd = snapshot.cwd;
234
+ return existing;
235
+ }
223
236
  const starting = startingSessions.get(sessionKey);
224
237
  if (starting) return await starting;
225
238
 
@@ -231,6 +244,8 @@ async function acquireSession(sessionKey: string, snapshot: SessionSnapshot, tim
231
244
  const worker = spawnJsWorker();
232
245
  const session: JsSession = {
233
246
  sessionKey,
247
+ sessionId: snapshot.sessionId,
248
+ cwd: snapshot.cwd,
234
249
  worker,
235
250
  state: "alive",
236
251
  pending: new Map(),
@@ -9,7 +9,7 @@ import { executeJs } from "./executor";
9
9
 
10
10
  const JS_SESSION_PREFIX = "js:";
11
11
 
12
- function namespaceSessionId(sessionId: string): string {
12
+ export function namespaceSessionId(sessionId: string): string {
13
13
  return sessionId.startsWith(JS_SESSION_PREFIX) ? sessionId : `${JS_SESSION_PREFIX}${sessionId}`;
14
14
  }
15
15
 
@@ -632,7 +632,7 @@ async function executePerCall(code: string, cwd: string, options: PythonExecutor
632
632
  }
633
633
  const kernel = await startKernel(cwd, options);
634
634
  try {
635
- return await executeWithKernel(kernel, code, { ...options, cwd: undefined });
635
+ return await executeWithKernel(kernel, code, { ...options, cwd });
636
636
  } finally {
637
637
  await kernel.shutdown().catch(() => undefined);
638
638
  }
@@ -682,7 +682,7 @@ async function executeOnSession(code: string, cwd: string, options: PythonExecut
682
682
  throw new PythonExecutionCancelledError(false);
683
683
  }
684
684
  }
685
- const runOptions = { ...options, cwd: undefined };
685
+ const runOptions = { ...options, cwd };
686
686
  try {
687
687
  return await executeWithKernel(session.kernel, code, runOptions);
688
688
  } catch (err) {
@@ -1,13 +1,14 @@
1
1
  /**
2
2
  * Custom command loader - loads TypeScript command modules using native Bun import.
3
3
  *
4
- * Dependencies (the zod-backed typebox shim and pi-coding-agent) are injected via the
4
+ * Dependencies (the arktype validation and pi-coding-agent) are injected via the
5
5
  * CustomCommandAPI to avoid import resolution issues with custom commands loaded from user directories.
6
6
  */
7
7
  import * as fs from "node:fs";
8
8
  import * as path from "node:path";
9
9
  import { getAgentDir, getProjectDir, isEnoent, logger } from "@oh-my-pi/pi-utils";
10
- import { z as zod } from "zod/v4";
10
+ import * as arktype from "arktype";
11
+ import * as zodModule from "zod/v4";
11
12
  import { getConfigDirs } from "../../config";
12
13
  import { execCommand } from "../../exec/exec";
13
14
  // Runtime self-reference: dereference this namespace only inside loader functions to keep the index.ts cycle safe.
@@ -186,7 +187,8 @@ export async function loadCustomCommands(options: LoadCustomCommandsOptions = {}
186
187
  exec: (command: string, args: string[], execOptions) =>
187
188
  execCommand(command, args, execOptions?.cwd ?? cwd, execOptions),
188
189
  typebox,
189
- zod,
190
+ arktype,
191
+ zod: zodModule,
190
192
  pi: PiCodingAgent,
191
193
  };
192
194
 
@@ -5,7 +5,8 @@
5
5
  * Unlike markdown commands which expand to prompts, custom commands can execute
6
6
  * arbitrary logic with full access to the hook context.
7
7
  */
8
- import type { z } from "zod/v4";
8
+ import type * as arktype from "arktype";
9
+ import type * as zod from "zod/v4";
9
10
  import type { ExecOptions, ExecResult, HookCommandContext } from "../../extensibility/hooks/types";
10
11
  import type * as PiCodingAgent from "../../index";
11
12
  import type * as TypeBox from "../typebox";
@@ -24,8 +25,10 @@ export interface CustomCommandAPI {
24
25
  exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
25
26
  /** Injected zod-backed typebox shim (legacy/compat). */
26
27
  typebox: typeof TypeBox;
27
- /** Injected zod module for Zod-authored custom commands. */
28
- zod: typeof z;
28
+ /** Injected arktype module for validation in custom commands. */
29
+ arktype: typeof arktype;
30
+ /** Injected zod/v4 module for canonical command validation. */
31
+ zod: typeof zod;
29
32
  /** Injected pi-coding-agent exports */
30
33
  pi: typeof PiCodingAgent;
31
34
  }
@@ -7,7 +7,8 @@
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 { z } from "zod/v4";
10
+ import { type } from "arktype";
11
+ import * as zodModule from "zod/v4";
11
12
  import { toolCapability } from "../../capability/tool";
12
13
  import { type CustomTool, loadCapability } from "../../discovery";
13
14
  import type { ExecOptions } from "../../exec/exec";
@@ -108,7 +109,8 @@ export class CustomToolLoader {
108
109
  hasUI: false,
109
110
  logger,
110
111
  typebox,
111
- zod: z,
112
+ arktype: type,
113
+ zod: zodModule,
112
114
  pi,
113
115
  pushPendingAction: action => {
114
116
  if (!pushPendingAction) {
@@ -15,7 +15,8 @@ import type { CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
15
15
  import type { FetchImpl, Model, Static, TSchema } from "@oh-my-pi/pi-ai";
16
16
  import type { Component } from "@oh-my-pi/pi-tui";
17
17
  import type { logger as PiLogger } from "@oh-my-pi/pi-utils";
18
- import type { z } from "zod/v4";
18
+ import type { type as ArkType } from "arktype";
19
+ import type * as zod from "zod/v4";
19
20
  import type { Rule } from "../../capability/rule";
20
21
  import type { ModelRegistry } from "../../config/model-registry";
21
22
  import type { Settings } from "../../config/settings";
@@ -61,10 +62,12 @@ export interface CustomToolAPI {
61
62
  hasUI: boolean;
62
63
  /** File logger for error/warning/debug messages */
63
64
  logger: typeof PiLogger;
64
- /** Injected zod-backed typebox shim (legacy/compat — Zod-authored tools are preferred). */
65
+ /** Injected typebox shim (legacy/compat — arktype-authored tools are preferred). */
65
66
  typebox: typeof TypeBox;
66
- /** Injected zod module for Zod-authored custom tools. */
67
- zod: typeof z;
67
+ /** Injected arktype module for arktype-authored custom tools. */
68
+ arktype: typeof ArkType;
69
+ /** Injected zod/v4 module for canonical parameter schemas. */
70
+ zod: typeof zod;
68
71
  /** Injected pi-coding-agent exports */
69
72
  pi: typeof PiCodingAgent;
70
73
  /** Push a preview action that can later be resolved with the hidden resolve tool */
@@ -195,7 +198,7 @@ export interface CustomTool<TParams extends TSchema = TSchema, TDetails = any> {
195
198
  strict?: boolean;
196
199
  /** Description for LLM */
197
200
  description: string;
198
- /** Parameter schema (Zod or TypeBox; TypeBox is auto-lifted to Zod at registration). */
201
+ /** Parameter schema (arktype, TypeBox, or legacy formats). */
199
202
  parameters: TParams;
200
203
  /** If true, tool is excluded unless explicitly listed in --tools or agent's tools field */
201
204
  hidden?: boolean;
@@ -8,7 +8,8 @@ import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
8
8
  import type { ImageContent, Model, TextContent, TSchema } 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 { z } from "zod/v4";
11
+ import { Type } from "arktype";
12
+ import * as zodModule from "zod/v4";
12
13
  import { type ExtensionModule, extensionModuleCapability } from "../../capability/extension-module";
13
14
  import { type Hook, hookCapability } from "../../capability/hook";
14
15
  import { loadCapability } from "../../discovery";
@@ -123,7 +124,8 @@ export class ExtensionRuntime implements IExtensionRuntime {
123
124
  class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
124
125
  readonly logger = logger;
125
126
  readonly typebox = TypeBox;
126
- readonly zod = z;
127
+ readonly arktype = Type;
128
+ readonly zod = zodModule;
127
129
  readonly flagValues = new Map<string, boolean | string>();
128
130
  readonly pendingProviderRegistrations: Array<{
129
131
  name: string;
@@ -32,7 +32,8 @@ import type {
32
32
  import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/oauth/types";
33
33
  import type { AutocompleteItem, Component, EditorTheme, KeyId, TUI } from "@oh-my-pi/pi-tui";
34
34
  import type { logger as PiLogger } from "@oh-my-pi/pi-utils";
35
- import type { z } from "zod/v4";
35
+ import type { Type as arktype } from "arktype";
36
+ import type * as zod from "zod/v4";
36
37
  import type { KeybindingsManager } from "../../config/keybindings";
37
38
  import type { ModelRegistry } from "../../config/model-registry";
38
39
  import type { EditToolDetails } from "../../edit";
@@ -948,8 +949,10 @@ export interface ExtensionAPI {
948
949
  /** Injected zod-backed typebox shim for legacy `Type.Object(...)` parameter authoring. */
949
950
  typebox: typeof TypeBox;
950
951
 
951
- /** Injected zod module for Zod-authored extension tools (canonical going forward). */
952
- zod: typeof z;
952
+ /** Injected arktype module for arktype-authored extension tools (canonical going forward). */
953
+ arktype: typeof arktype;
954
+ /** Injected zod/v4 module for canonical extension tool parameter schemas. */
955
+ zod: typeof zod;
953
956
 
954
957
  /** Injected pi-coding-agent exports for accessing SDK utilities */
955
958
  pi: typeof PiCodingAgent;
@@ -3,7 +3,8 @@
3
3
  */
4
4
  import * as path from "node:path";
5
5
  import { logger } from "@oh-my-pi/pi-utils";
6
- import { z as zod } from "zod/v4";
6
+ import * as arktype from "arktype";
7
+ import * as zodModule from "zod/v4";
7
8
  import { hookCapability } from "../../capability/hook";
8
9
  import type { Hook } from "../../discovery";
9
10
  import { loadCapability } from "../../discovery";
@@ -139,7 +140,9 @@ async function createHookAPI(
139
140
  },
140
141
  logger,
141
142
  typebox,
142
- zod,
143
+ // HookAPI.arktype is typed as the arktype `Type` constructor; expose it from the module namespace.
144
+ arktype: arktype.Type,
145
+ zod: zodModule,
143
146
  pi: PiCodingAgent,
144
147
  } as HookAPI;
145
148
 
@@ -1,7 +1,8 @@
1
1
  import type { ImageContent, Message, Model, TextContent } from "@oh-my-pi/pi-ai";
2
2
  import type { Component, TUI } from "@oh-my-pi/pi-tui";
3
3
  import type { logger as PiLogger } from "@oh-my-pi/pi-utils";
4
- import type { z } from "zod/v4";
4
+ import type { Type } from "arktype";
5
+ import type * as zod from "zod/v4";
5
6
  import type { ModelRegistry } from "../../config/model-registry";
6
7
  import type { EditToolDetails } from "../../edit";
7
8
  import type { ExecOptions, ExecResult } from "../../exec/exec";
@@ -582,10 +583,12 @@ export interface HookAPI {
582
583
 
583
584
  /** File logger for error/warning/debug messages */
584
585
  logger: typeof PiLogger;
585
- /** Injected zod-backed typebox shim (legacy/compat — prefer `zod`). */
586
+ /** Injected zod-backed typebox shim (legacy/compat — prefer `arktype`). */
586
587
  typebox: typeof TypeBox;
587
- /** Injected zod module for Zod-authored hooks. */
588
- zod: typeof z;
588
+ /** Injected arktype module for arktype-authored hooks. */
589
+ arktype: typeof Type;
590
+ /** Injected zod/v4 module for canonical hook validation. */
591
+ zod: typeof zod;
589
592
  /** Injected pi-coding-agent exports */
590
593
  pi: typeof PiCodingAgent;
591
594
  }