@oh-my-pi/pi-coding-agent 16.0.4 → 16.0.6

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 (270) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/dist/cli.js +2027 -1396
  3. package/dist/types/advisor/advise-tool.d.ts +31 -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/args.d.ts +1 -0
  9. package/dist/types/cli/bench-cli.d.ts +6 -0
  10. package/dist/types/cli/ttsr-cli.d.ts +39 -0
  11. package/dist/types/commands/launch.d.ts +3 -0
  12. package/dist/types/commands/ttsr.d.ts +57 -0
  13. package/dist/types/commit/agentic/tools/analyze-file.d.ts +4 -5
  14. package/dist/types/commit/agentic/tools/git-file-diff.d.ts +4 -5
  15. package/dist/types/commit/agentic/tools/git-hunk.d.ts +5 -6
  16. package/dist/types/commit/agentic/tools/git-overview.d.ts +4 -5
  17. package/dist/types/commit/agentic/tools/propose-changelog.d.ts +23 -24
  18. package/dist/types/commit/agentic/tools/propose-commit.d.ts +11 -32
  19. package/dist/types/commit/agentic/tools/recent-commits.d.ts +3 -4
  20. package/dist/types/commit/agentic/tools/schemas.d.ts +6 -27
  21. package/dist/types/commit/agentic/tools/split-commit.d.ts +28 -49
  22. package/dist/types/commit/changelog/generate.d.ts +12 -13
  23. package/dist/types/commit/shared-llm.d.ts +10 -37
  24. package/dist/types/config/config-file.d.ts +4 -4
  25. package/dist/types/config/keybindings.d.ts +5 -0
  26. package/dist/types/config/models-config-schema.d.ts +625 -990
  27. package/dist/types/config/models-config.d.ts +229 -217
  28. package/dist/types/config/settings-schema.d.ts +144 -25
  29. package/dist/types/edit/hashline/params.d.ts +7 -11
  30. package/dist/types/edit/index.d.ts +2 -1
  31. package/dist/types/edit/modes/apply-patch.d.ts +4 -5
  32. package/dist/types/edit/modes/patch.d.ts +15 -24
  33. package/dist/types/edit/modes/replace.d.ts +16 -17
  34. package/dist/types/eval/js/index.d.ts +1 -0
  35. package/dist/types/extensibility/custom-commands/types.d.ts +6 -3
  36. package/dist/types/extensibility/custom-tools/types.d.ts +8 -5
  37. package/dist/types/extensibility/extensions/runner.d.ts +5 -2
  38. package/dist/types/extensibility/extensions/types.d.ts +14 -10
  39. package/dist/types/extensibility/hooks/types.d.ts +7 -4
  40. package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +13 -5
  41. package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +17 -0
  42. package/dist/types/extensibility/shared-events.d.ts +22 -1
  43. package/dist/types/extensibility/typebox.d.ts +80 -58
  44. package/dist/types/goals/tools/goal-tool.d.ts +11 -24
  45. package/dist/types/index.d.ts +2 -0
  46. package/dist/types/lsp/index.d.ts +11 -26
  47. package/dist/types/lsp/types.d.ts +12 -28
  48. package/dist/types/main.d.ts +1 -0
  49. package/dist/types/mcp/client.d.ts +8 -0
  50. package/dist/types/modes/components/btw-panel.d.ts +1 -0
  51. package/dist/types/modes/components/custom-editor.d.ts +3 -1
  52. package/dist/types/modes/components/status-line/component.d.ts +1 -1
  53. package/dist/types/modes/components/status-line/context-thresholds.d.ts +0 -1
  54. package/dist/types/modes/controllers/btw-controller.d.ts +2 -0
  55. package/dist/types/modes/controllers/input-controller.d.ts +1 -0
  56. package/dist/types/modes/interactive-mode.d.ts +3 -0
  57. package/dist/types/modes/rpc/rpc-types.d.ts +1 -1
  58. package/dist/types/modes/setup-wizard/index.d.ts +1 -0
  59. package/dist/types/modes/setup-wizard/startup-splash.d.ts +7 -0
  60. package/dist/types/modes/theme/theme.d.ts +1 -1
  61. package/dist/types/modes/types.d.ts +3 -0
  62. package/dist/types/modes/utils/context-usage.d.ts +12 -0
  63. package/dist/types/sdk.d.ts +8 -1
  64. package/dist/types/session/agent-session.d.ts +24 -0
  65. package/dist/types/session/session-persistence.d.ts +4 -0
  66. package/dist/types/startup-splash.d.ts +12 -0
  67. package/dist/types/task/types.d.ts +47 -48
  68. package/dist/types/tools/ask.d.ts +26 -27
  69. package/dist/types/tools/ast-edit.d.ts +17 -17
  70. package/dist/types/tools/ast-grep.d.ts +12 -13
  71. package/dist/types/tools/bash.d.ts +20 -17
  72. package/dist/types/tools/browser.d.ts +46 -71
  73. package/dist/types/tools/checkpoint.d.ts +14 -15
  74. package/dist/types/tools/debug.d.ts +82 -145
  75. package/dist/types/tools/eval.d.ts +30 -40
  76. package/dist/types/tools/find.d.ts +17 -18
  77. package/dist/types/tools/gh.d.ts +49 -78
  78. package/dist/types/tools/image-gen.d.ts +20 -36
  79. package/dist/types/tools/inspect-image.d.ts +10 -11
  80. package/dist/types/tools/irc.d.ts +22 -33
  81. package/dist/types/tools/job.d.ts +11 -12
  82. package/dist/types/tools/learn.d.ts +21 -28
  83. package/dist/types/tools/manage-skill.d.ts +13 -22
  84. package/dist/types/tools/memory-edit.d.ts +15 -24
  85. package/dist/types/tools/memory-recall.d.ts +7 -8
  86. package/dist/types/tools/memory-reflect.d.ts +9 -10
  87. package/dist/types/tools/memory-retain.d.ts +13 -14
  88. package/dist/types/tools/read.d.ts +8 -8
  89. package/dist/types/tools/resolve.d.ts +11 -18
  90. package/dist/types/tools/review.d.ts +9 -15
  91. package/dist/types/tools/search-tool-bm25.d.ts +9 -10
  92. package/dist/types/tools/search.d.ts +16 -17
  93. package/dist/types/tools/ssh.d.ts +14 -15
  94. package/dist/types/tools/todo.d.ts +27 -43
  95. package/dist/types/tools/tts.d.ts +8 -9
  96. package/dist/types/tools/write.d.ts +9 -10
  97. package/dist/types/tui/code-cell.d.ts +2 -0
  98. package/dist/types/tui/index.d.ts +1 -0
  99. package/dist/types/tui/width-aware-text.d.ts +23 -0
  100. package/dist/types/utils/image-vision-fallback.d.ts +28 -0
  101. package/dist/types/utils/markit.d.ts +10 -1
  102. package/dist/types/web/search/index.d.ts +17 -28
  103. package/dist/types/web/search/providers/base.d.ts +1 -0
  104. package/dist/types/web/search/providers/gemini.d.ts +1 -0
  105. package/dist/types/web/search/providers/perplexity.d.ts +0 -2
  106. package/dist/types/web/search/types.d.ts +32 -26
  107. package/package.json +14 -13
  108. package/scripts/omp +1 -1
  109. package/src/advisor/__tests__/advisor.test.ts +103 -1
  110. package/src/advisor/advise-tool.ts +47 -11
  111. package/src/autoresearch/tools/init-experiment.ts +13 -16
  112. package/src/autoresearch/tools/log-experiment.ts +15 -18
  113. package/src/autoresearch/tools/run-experiment.ts +3 -3
  114. package/src/autoresearch/tools/update-notes.ts +4 -4
  115. package/src/cli/args.ts +1 -0
  116. package/src/cli/bench-cli.ts +30 -7
  117. package/src/cli/flag-tables.ts +8 -0
  118. package/src/cli/ttsr-cli.ts +995 -0
  119. package/src/cli-commands.ts +1 -0
  120. package/src/cli.ts +7 -1
  121. package/src/collab/host.ts +2 -2
  122. package/src/commands/launch.ts +3 -0
  123. package/src/commands/ttsr.ts +125 -0
  124. package/src/commit/agentic/tools/analyze-file.ts +4 -4
  125. package/src/commit/agentic/tools/git-file-diff.ts +4 -4
  126. package/src/commit/agentic/tools/git-hunk.ts +7 -5
  127. package/src/commit/agentic/tools/git-overview.ts +4 -4
  128. package/src/commit/agentic/tools/propose-changelog.ts +18 -15
  129. package/src/commit/agentic/tools/propose-commit.ts +6 -6
  130. package/src/commit/agentic/tools/recent-commits.ts +3 -3
  131. package/src/commit/agentic/tools/schemas.ts +8 -20
  132. package/src/commit/agentic/tools/split-commit.ts +19 -23
  133. package/src/commit/analysis/summary.ts +7 -5
  134. package/src/commit/changelog/generate.ts +15 -11
  135. package/src/commit/shared-llm.ts +17 -24
  136. package/src/config/config-file.ts +13 -15
  137. package/src/config/keybindings.ts +6 -0
  138. package/src/config/models-config-schema.ts +206 -179
  139. package/src/config/settings-schema.ts +118 -2
  140. package/src/discovery/builtin-rules/index.ts +2 -0
  141. package/src/discovery/builtin-rules/ts-import-type.md +2 -2
  142. package/src/discovery/builtin-rules/ts-no-any.md +11 -2
  143. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
  144. package/src/edit/hashline/params.ts +12 -11
  145. package/src/edit/index.ts +5 -4
  146. package/src/edit/modes/apply-patch.ts +4 -4
  147. package/src/edit/modes/patch.ts +15 -18
  148. package/src/edit/modes/replace.ts +13 -17
  149. package/src/edit/renderer.ts +0 -1
  150. package/src/eval/agent-bridge.ts +11 -13
  151. package/src/eval/completion-bridge.ts +25 -17
  152. package/src/eval/js/context-manager.ts +17 -2
  153. package/src/eval/js/index.ts +1 -1
  154. package/src/eval/py/executor.ts +2 -2
  155. package/src/eval/py/runner.py +44 -0
  156. package/src/extensibility/custom-commands/loader.ts +5 -3
  157. package/src/extensibility/custom-commands/types.ts +6 -3
  158. package/src/extensibility/custom-tools/loader.ts +4 -2
  159. package/src/extensibility/custom-tools/types.ts +8 -5
  160. package/src/extensibility/extensions/loader.ts +4 -2
  161. package/src/extensibility/extensions/runner.ts +20 -2
  162. package/src/extensibility/extensions/types.ts +22 -8
  163. package/src/extensibility/hooks/loader.ts +5 -2
  164. package/src/extensibility/hooks/types.ts +7 -4
  165. package/src/extensibility/legacy-pi-ai-shim.ts +42 -5
  166. package/src/extensibility/legacy-pi-coding-agent-shim.ts +113 -0
  167. package/src/extensibility/plugins/legacy-pi-compat.ts +13 -13
  168. package/src/extensibility/shared-events.ts +24 -0
  169. package/src/extensibility/tool-proxy.ts +4 -1
  170. package/src/extensibility/typebox.ts +778 -251
  171. package/src/goals/guided-setup.ts +12 -3
  172. package/src/goals/tools/goal-tool.ts +6 -6
  173. package/src/index.ts +2 -0
  174. package/src/internal-urls/docs-index.generated.ts +15 -13
  175. package/src/lsp/types.ts +13 -27
  176. package/src/main.ts +29 -21
  177. package/src/mcp/client.ts +38 -13
  178. package/src/mcp/render.ts +102 -89
  179. package/src/modes/components/agent-hub.ts +11 -4
  180. package/src/modes/components/branch-summary-message.ts +1 -0
  181. package/src/modes/components/btw-panel.ts +5 -1
  182. package/src/modes/components/collab-prompt-message.ts +9 -7
  183. package/src/modes/components/compaction-summary-message.ts +1 -0
  184. package/src/modes/components/custom-editor.ts +18 -0
  185. package/src/modes/components/custom-message.ts +1 -0
  186. package/src/modes/components/footer.ts +6 -5
  187. package/src/modes/components/hook-message.ts +1 -0
  188. package/src/modes/components/read-tool-group.ts +9 -3
  189. package/src/modes/components/skill-message.ts +1 -0
  190. package/src/modes/components/status-line/component.ts +139 -15
  191. package/src/modes/components/status-line/context-thresholds.ts +0 -1
  192. package/src/modes/components/todo-reminder.ts +1 -0
  193. package/src/modes/components/tool-execution.ts +17 -10
  194. package/src/modes/components/ttsr-notification.ts +1 -0
  195. package/src/modes/components/user-message.ts +6 -6
  196. package/src/modes/controllers/btw-controller.ts +69 -1
  197. package/src/modes/controllers/event-controller.ts +2 -7
  198. package/src/modes/controllers/input-controller.ts +29 -0
  199. package/src/modes/controllers/selector-controller.ts +10 -3
  200. package/src/modes/interactive-mode.ts +42 -10
  201. package/src/modes/rpc/rpc-types.ts +1 -1
  202. package/src/modes/setup-wizard/index.ts +1 -0
  203. package/src/modes/setup-wizard/scenes/sign-in.ts +77 -5
  204. package/src/modes/setup-wizard/startup-splash.ts +107 -0
  205. package/src/modes/theme/theme.ts +133 -143
  206. package/src/modes/types.ts +3 -0
  207. package/src/modes/utils/context-usage.ts +37 -20
  208. package/src/modes/utils/hotkeys-markdown.ts +1 -0
  209. package/src/prompts/system/system-prompt.md +1 -0
  210. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  211. package/src/prompts/tools/image-attachment-describe.md +10 -0
  212. package/src/sdk.ts +35 -22
  213. package/src/session/agent-session.ts +715 -255
  214. package/src/session/session-history-format.ts +11 -2
  215. package/src/session/session-loader.ts +19 -32
  216. package/src/session/session-persistence.ts +27 -11
  217. package/src/session/snapcompact-inline.ts +1 -1
  218. package/src/slash-commands/builtin-registry.ts +4 -11
  219. package/src/ssh/connection-manager.ts +3 -2
  220. package/src/startup-splash.ts +19 -0
  221. package/src/task/executor.ts +12 -7
  222. package/src/task/types.ts +44 -41
  223. package/src/tool-discovery/tool-index.ts +17 -4
  224. package/src/tools/ask.ts +14 -14
  225. package/src/tools/ast-edit.ts +17 -14
  226. package/src/tools/ast-grep.ts +10 -9
  227. package/src/tools/bash.ts +15 -10
  228. package/src/tools/browser/launch.ts +13 -0
  229. package/src/tools/browser.ts +26 -32
  230. package/src/tools/checkpoint.ts +7 -7
  231. package/src/tools/debug.ts +72 -69
  232. package/src/tools/eval.ts +18 -19
  233. package/src/tools/find.ts +20 -13
  234. package/src/tools/gh.ts +29 -49
  235. package/src/tools/image-gen.ts +94 -57
  236. package/src/tools/inspect-image.ts +8 -9
  237. package/src/tools/irc.ts +12 -12
  238. package/src/tools/job.ts +6 -6
  239. package/src/tools/learn.ts +11 -14
  240. package/src/tools/manage-skill.ts +19 -23
  241. package/src/tools/memory-edit.ts +8 -8
  242. package/src/tools/memory-recall.ts +4 -4
  243. package/src/tools/memory-reflect.ts +5 -5
  244. package/src/tools/memory-retain.ts +9 -11
  245. package/src/tools/puppeteer/02_stealth_hairline.txt +1 -1
  246. package/src/tools/puppeteer/04_stealth_iframe.txt +4 -4
  247. package/src/tools/puppeteer/05_stealth_webgl.txt +1 -1
  248. package/src/tools/puppeteer/10_stealth_plugins.txt +6 -4
  249. package/src/tools/puppeteer/12_stealth_codecs.txt +2 -2
  250. package/src/tools/puppeteer/13_stealth_worker.txt +1 -1
  251. package/src/tools/read.ts +197 -19
  252. package/src/tools/report-tool-issue.ts +6 -6
  253. package/src/tools/resolve.ts +6 -6
  254. package/src/tools/review.ts +10 -12
  255. package/src/tools/search-tool-bm25.ts +5 -5
  256. package/src/tools/search.ts +20 -29
  257. package/src/tools/ssh.ts +8 -8
  258. package/src/tools/todo.ts +16 -19
  259. package/src/tools/tts.ts +16 -15
  260. package/src/tools/write.ts +5 -5
  261. package/src/tui/code-cell.ts +44 -3
  262. package/src/tui/index.ts +1 -0
  263. package/src/tui/width-aware-text.ts +58 -0
  264. package/src/utils/image-vision-fallback.ts +197 -0
  265. package/src/utils/markit.ts +17 -2
  266. package/src/web/search/index.ts +21 -9
  267. package/src/web/search/providers/base.ts +1 -0
  268. package/src/web/search/providers/gemini.ts +56 -18
  269. package/src/web/search/providers/perplexity.ts +373 -126
  270. package/src/web/search/types.ts +28 -48
@@ -45,6 +45,7 @@ const PRIMARY_ARG_KEYS = [
45
45
  "query",
46
46
  "prompt",
47
47
  "assignment",
48
+ "note",
48
49
  "message",
49
50
  "op",
50
51
  "name",
@@ -74,8 +75,16 @@ function lineCount(text: string): number {
74
75
  }
75
76
 
76
77
  /** Pick the most informative scalar argument of a tool call. */
77
- function primaryArg(args: Record<string, unknown> | undefined): string {
78
+ function primaryArg(name: string, args: Record<string, unknown> | undefined): string {
78
79
  if (!args || typeof args !== "object") return "";
80
+ // Advisor note is the most informative summary; preserve severity too.
81
+ if (name === "advise") {
82
+ const note = typeof args.note === "string" ? args.note : "";
83
+ const severity = typeof args.severity === "string" ? args.severity : "";
84
+ if (note && severity) return oneLine(`${severity}: ${note}`);
85
+ if (note) return oneLine(note);
86
+ if (severity) return oneLine(severity);
87
+ }
79
88
  for (const key of PRIMARY_ARG_KEYS) {
80
89
  const value = args[key];
81
90
  if (typeof value === "string" && value.length > 0) return oneLine(value);
@@ -108,7 +117,7 @@ function toolCallLine(
108
117
  result: ToolResultMessage | undefined,
109
118
  includeToolIntent?: boolean,
110
119
  ): string {
111
- const head = `→ ${name}(${primaryArg(args)})`;
120
+ const head = `→ ${name}(${primaryArg(name, args)})`;
112
121
  let base: string;
113
122
  if (!result) {
114
123
  base = `${head} ⇒ pending`;
@@ -4,7 +4,7 @@ import { BlobStore, isBlobRef, resolveImageData, resolveImageDataUrl } from "./b
4
4
  import { buildSessionContext } from "./session-context";
5
5
  import type { FileEntry, SessionEntry, SessionHeader } from "./session-entries";
6
6
  import { migrateToCurrentVersion } from "./session-migrations";
7
- import { isImageBlock } from "./session-persistence";
7
+ import { isImageBlock, isImageDataPayload } from "./session-persistence";
8
8
  import { FileSessionStorage, type SessionStorage } from "./session-storage";
9
9
 
10
10
  /** Exported for compaction.test.ts */
@@ -44,9 +44,19 @@ function hasImageUrl(value: unknown): value is { image_url: string } {
44
44
  return typeof value === "object" && value !== null && "image_url" in value && typeof value.image_url === "string";
45
45
  }
46
46
 
47
- async function resolvePersistedImageUrlRefs(value: unknown, blobStore: BlobStore): Promise<void> {
47
+ function shouldResolveImagePayload(value: unknown, key: string | undefined): value is { data: string } {
48
+ if (!isImageDataPayload(value) || !isBlobRef(value.data)) return false;
49
+ return (key === "content" && isImageBlock(value)) || key === "images";
50
+ }
51
+
52
+ async function resolvePersistedBlobRefs(value: unknown, blobStore: BlobStore, key?: string): Promise<void> {
53
+ if (shouldResolveImagePayload(value, key)) {
54
+ value.data = await resolveImageData(blobStore, value.data);
55
+ return;
56
+ }
57
+
48
58
  if (Array.isArray(value)) {
49
- await Promise.all(value.map(item => resolvePersistedImageUrlRefs(item, blobStore)));
59
+ await Promise.all(value.map(item => resolvePersistedBlobRefs(item, blobStore, key)));
50
60
  return;
51
61
  }
52
62
 
@@ -56,38 +66,15 @@ async function resolvePersistedImageUrlRefs(value: unknown, blobStore: BlobStore
56
66
  value.image_url = await resolveImageDataUrl(blobStore, value.image_url);
57
67
  }
58
68
 
59
- await Promise.all(Object.values(value).map(item => resolvePersistedImageUrlRefs(item, blobStore)));
69
+ await Promise.all(
70
+ Object.entries(value).map(([childKey, item]) => resolvePersistedBlobRefs(item, blobStore, childKey)),
71
+ );
60
72
  }
61
73
 
62
74
  export async function resolveBlobRefsInEntries(entries: FileEntry[], blobStore: BlobStore): Promise<void> {
63
- const promises: Promise<void>[] = [];
64
-
65
- for (const entry of entries) {
66
- if (entry.type === "session") continue;
67
-
68
- let contentArray: unknown[] | undefined;
69
- if (entry.type === "message" && "content" in entry.message && Array.isArray(entry.message.content)) {
70
- contentArray = entry.message.content;
71
- } else if (entry.type === "custom_message" && Array.isArray(entry.content)) {
72
- contentArray = entry.content;
73
- }
74
-
75
- if (contentArray) {
76
- for (const block of contentArray) {
77
- if (isImageBlock(block) && isBlobRef(block.data)) {
78
- promises.push(
79
- resolveImageData(blobStore, block.data).then(resolved => {
80
- block.data = resolved;
81
- }),
82
- );
83
- }
84
- }
85
- }
86
-
87
- promises.push(resolvePersistedImageUrlRefs(entry, blobStore));
88
- }
89
-
90
- await Promise.all(promises);
75
+ await Promise.all(
76
+ entries.filter(entry => entry.type !== "session").map(entry => resolvePersistedBlobRefs(entry, blobStore)),
77
+ );
91
78
  }
92
79
 
93
80
  /**
@@ -36,10 +36,33 @@ export function isImageBlock(value: unknown): value is { type: "image"; data: st
36
36
  );
37
37
  }
38
38
 
39
+ function isImageMimeType(value: unknown): value is string {
40
+ return typeof value === "string" && value.toLowerCase().startsWith("image/");
41
+ }
42
+
43
+ export function isImageDataPayload(value: unknown): value is { data: string; mimeType?: string } {
44
+ return (
45
+ typeof value === "object" &&
46
+ value !== null &&
47
+ "data" in value &&
48
+ typeof (value as { data?: string }).data === "string" &&
49
+ (isImageBlock(value) || ("mimeType" in value && isImageMimeType((value as { mimeType?: unknown }).mimeType)))
50
+ );
51
+ }
52
+
53
+ function shouldExternalizeImagePayload(
54
+ value: unknown,
55
+ key: string | undefined,
56
+ ): value is { data: string; mimeType?: string } {
57
+ if (!isImageDataPayload(value)) return false;
58
+ if (isBlobRef(value.data) || value.data.length < BLOB_EXTERNALIZE_THRESHOLD) return false;
59
+ return (key === TEXT_CONTENT_KEY && isImageBlock(value)) || key === "images";
60
+ }
61
+
39
62
  /**
40
63
  * Recursively truncate large strings in an object for session persistence.
41
64
  * - Truncates any oversized string fields (key-agnostic)
42
- * - Replaces oversized image blocks with text notices
65
+ * - Externalizes oversized image payloads to blob refs
43
66
  * - Updates lineCount when content is truncated
44
67
  * - Returns original object if no changes needed (structural sharing)
45
68
  *
@@ -50,6 +73,9 @@ export function isImageBlock(value: unknown): value is { type: "image"; data: st
50
73
  */
51
74
  function truncateForPersistence(obj: unknown, blobStore: BlobStore, key?: string): unknown {
52
75
  if (obj === null || obj === undefined) return obj;
76
+ if (shouldExternalizeImagePayload(obj, key)) {
77
+ return { ...obj, data: externalizeImageDataSync(blobStore, obj.data, obj.mimeType) };
78
+ }
53
79
 
54
80
  if (typeof obj === "string") {
55
81
  if (key === "image_url" && isImageDataUrl(obj)) {
@@ -72,16 +98,6 @@ function truncateForPersistence(obj: unknown, blobStore: BlobStore, key?: string
72
98
  const result: unknown[] = new Array(obj.length);
73
99
  for (let i = 0; i < obj.length; i++) {
74
100
  const item = obj[i];
75
- if (
76
- key === TEXT_CONTENT_KEY &&
77
- isImageBlock(item) &&
78
- !isBlobRef(item.data) &&
79
- item.data.length >= BLOB_EXTERNALIZE_THRESHOLD
80
- ) {
81
- changed = true;
82
- result[i] = { ...item, data: externalizeImageDataSync(blobStore, item.data, item.mimeType) };
83
- continue;
84
- }
85
101
  const newItem = truncateForPersistence(item, blobStore, key);
86
102
  if (newItem !== item) changed = true;
87
103
  result[i] = newItem;
@@ -14,8 +14,8 @@
14
14
  * estimate (`estimateInlineSavings`) so the two can never disagree.
15
15
  */
16
16
 
17
+ import { countTokens } from "@oh-my-pi/pi-agent-core";
17
18
  import type { Context, ImageContent, Model, TextContent, ToolResultMessage, UserMessage } from "@oh-my-pi/pi-ai";
18
- import { countTokens } from "@oh-my-pi/pi-natives";
19
19
  import * as snapcompact from "@oh-my-pi/snapcompact";
20
20
  import contextFramesNote from "../prompts/system/snapcompact-context-frames-note.md" with { type: "text" };
21
21
  import contextStub from "../prompts/system/snapcompact-context-stub.md" with { type: "text" };
@@ -240,13 +240,8 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
240
240
  allowArgs: true,
241
241
  handleTui: async (command, runtime) => {
242
242
  const hadArgs = !!command.args;
243
- // Capture state BEFORE the call: when plan mode is already active,
244
- // handlePlanModeCommand may exit it (on confirmed exit) or leave it on (on cancel
245
- // or warning). In every "already active" case the typed args are NOT consumed,
246
- // so preserve them in history regardless of the user's confirm/cancel choice.
247
- const wasPlanModeEnabled = runtime.ctx.planModeEnabled;
248
243
  await runtime.ctx.handlePlanModeCommand(command.args || undefined);
249
- if (hadArgs && wasPlanModeEnabled) {
244
+ if (hadArgs) {
250
245
  runtime.ctx.editor.addToHistory(command.text);
251
246
  }
252
247
  runtime.ctx.editor.setText("");
@@ -275,10 +270,8 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
275
270
  allowArgs: true,
276
271
  handleTui: async (command, runtime) => {
277
272
  const hadArgs = !!command.args;
278
- // Capture state BEFORE the call (see /plan above for rationale).
279
- const wasGoalModeEnabled = runtime.ctx.goalModeEnabled;
280
273
  await runtime.ctx.handleGoalModeCommand(command.args || undefined);
281
- if (hadArgs && wasGoalModeEnabled) {
274
+ if (hadArgs) {
282
275
  runtime.ctx.editor.addToHistory(command.text);
283
276
  }
284
277
  runtime.ctx.editor.setText("");
@@ -308,7 +301,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
308
301
  {
309
302
  name: "model",
310
303
  aliases: ["models"],
311
- description: "Select model (opens selector UI)",
304
+ description: "Switch model for this session",
312
305
  acpDescription: "Show current model selection",
313
306
  handle: async (command, runtime) => {
314
307
  if (command.args) {
@@ -341,7 +334,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
341
334
  return commandConsumed();
342
335
  },
343
336
  handleTui: (_command, runtime) => {
344
- runtime.ctx.showModelSelector();
337
+ runtime.ctx.showModelSelector({ temporaryOnly: true });
345
338
  runtime.ctx.editor.setText("");
346
339
  },
347
340
  },
@@ -65,7 +65,7 @@ async function deleteHostInfoFromDisk(hostName: string): Promise<void> {
65
65
  }
66
66
  }
67
67
 
68
- async function validateKeyPermissions(keyPath?: string): Promise<void> {
68
+ async function validateKeyPermissions(keyPath?: string, platform: SshPlatform = process.platform): Promise<void> {
69
69
  if (!keyPath) return;
70
70
  let stats: fs.Stats;
71
71
  try {
@@ -79,6 +79,7 @@ async function validateKeyPermissions(keyPath?: string): Promise<void> {
79
79
  if (!stats.isFile()) {
80
80
  throw new Error(`SSH key is not a file: ${keyPath}`);
81
81
  }
82
+ if (platform === "win32") return;
82
83
  const mode = stats.mode & 0o777;
83
84
  if ((mode & 0o077) !== 0) {
84
85
  throw new Error(`SSH key permissions must be 600 or stricter: ${keyPath}`);
@@ -402,7 +403,7 @@ export async function buildRemoteCommand(
402
403
  command: string,
403
404
  options?: SSHArgsOptions,
404
405
  ): Promise<string[]> {
405
- await validateKeyPermissions(host.keyPath);
406
+ await validateKeyPermissions(host.keyPath, options?.platform);
406
407
  return [...buildCommonArgs(host, options), buildSshTarget(host.username, host.host), command];
407
408
  }
408
409
 
@@ -0,0 +1,19 @@
1
+ /** Inputs used to decide whether the optional startup splash may run for this process. */
2
+ export interface StartupSplashDecisionOptions {
3
+ readonly configured: boolean;
4
+ readonly isInteractive: boolean;
5
+ readonly resuming: boolean;
6
+ readonly quiet: boolean;
7
+ readonly timing: boolean;
8
+ readonly stdinIsTTY: boolean | undefined;
9
+ readonly stdoutIsTTY: boolean | undefined;
10
+ }
11
+
12
+ /** Returns true only for explicitly enabled, normal interactive TTY startup. */
13
+ export function shouldShowStartupSplash(options: StartupSplashDecisionOptions): boolean {
14
+ if (!options.configured) return false;
15
+ if (!options.isInteractive) return false;
16
+ if (options.resuming || options.quiet) return false;
17
+ if (options.timing) return false;
18
+ return options.stdinIsTTY === true && options.stdoutIsTTY === true;
19
+ }
@@ -516,6 +516,7 @@ export function finalizeSubprocessOutput(args: FinalizeSubprocessOutputArgs): Fi
516
516
  const { yieldItems, reportFindings, doneAborted, signalAborted, outputSchema } = args;
517
517
  let abortedViaYield = false;
518
518
  const hasYield = Array.isArray(yieldItems) && yieldItems.length > 0;
519
+ const hadFailureBeforeYield = exitCode !== 0 && stderr.trim().length > 0;
519
520
 
520
521
  if (hasYield) {
521
522
  const lastYield = yieldItems[yieldItems.length - 1];
@@ -553,12 +554,16 @@ export function finalizeSubprocessOutput(args: FinalizeSubprocessOutputArgs): Fi
553
554
  const errorMessage = err instanceof Error ? err.message : String(err);
554
555
  rawOutput = `{"error":"Failed to serialize yield data: ${errorMessage}"}`;
555
556
  }
556
- exitCode = 0;
557
- stderr = overridden
558
- ? SUBAGENT_WARNING_SCHEMA_OVERRIDDEN
559
- : schemaError
560
- ? `invalid output schema: ${schemaError}`
561
- : "";
557
+ if (!hadFailureBeforeYield) {
558
+ exitCode = 0;
559
+ stderr = overridden
560
+ ? SUBAGENT_WARNING_SCHEMA_OVERRIDDEN
561
+ : schemaError
562
+ ? `invalid output schema: ${schemaError}`
563
+ : "";
564
+ } else if (!stderr) {
565
+ stderr = "Subagent failed after yielding a result.";
566
+ }
562
567
  }
563
568
  }
564
569
  }
@@ -2117,8 +2122,8 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
2117
2122
  void session.abort();
2118
2123
  }
2119
2124
 
2125
+ const pendingExtensionMessages: Array<Promise<unknown>> = [];
2120
2126
  const extensionRunner = session.extensionRunner;
2121
- const pendingExtensionMessages: Promise<unknown>[] = [];
2122
2127
  if (extensionRunner) {
2123
2128
  extensionRunner.initialize(
2124
2129
  {
package/src/task/types.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
2
  import type { Usage } from "@oh-my-pi/pi-ai";
3
3
  import { $env } from "@oh-my-pi/pi-utils";
4
- import { z } from "zod/v4";
4
+ import { type } from "arktype";
5
5
  import type { AgentSessionEvent } from "../session/agent-session";
6
6
  import type { NestedRepoPatch } from "./worktree";
7
7
 
@@ -78,37 +78,23 @@ export interface SubagentLifecyclePayload {
78
78
  export const ROLE_LABEL_MAX = 80;
79
79
  /** Schema bound on the raw `role` input, before it is label-normalized at every use site. */
80
80
  export const ROLE_INPUT_MAX = 256;
81
+ const ROLE_INPUT_SCHEMA = `string <= ${ROLE_INPUT_MAX}` as const;
81
82
 
82
- /**
83
- * One unit of work. The single-spawn schema is `{ agent, ...taskItemSchema }`;
84
- * the batch schema (`task.batch`) is `{ agent, context, tasks: taskItemSchema[] }`.
85
- * When task isolation is enabled, `isolated` joins the item shape (per-item in
86
- * batch form, top-level in the flat form via the spread).
87
- */
88
- const taskItemShape = {
89
- id: z.string().max(48).optional().describe("stable agent id; default generated"),
90
- description: z.string().optional().describe("ui label, not seen by subagent"),
91
- role: z
92
- .string()
93
- .max(ROLE_INPUT_MAX)
94
- .optional()
95
- .describe(
96
- "specialist role/expertise this subagent embodies (e.g. 'Rust async-runtime specialist'); shapes its identity and display name",
97
- ),
98
- assignment: z.string().describe("the work; self-contained instructions"),
99
- };
100
- const isolatedShape = {
101
- isolated: z.boolean().optional().describe("run in isolated env; returns patches"),
102
- };
103
- const agentShape = {
104
- agent: z.string().describe("agent type to spawn"),
105
- };
106
- const contextShape = {
107
- context: z.string().describe("shared background prepended to each assignment"),
108
- };
109
-
110
- export const taskItemSchema = z.object(taskItemShape);
111
- const taskItemSchemaIsolated = z.object({ ...taskItemShape, ...isolatedShape });
83
+ export const taskItemSchema = type({
84
+ "id?": "string",
85
+ "description?": "string",
86
+ "role?": ROLE_INPUT_SCHEMA,
87
+ assignment: "string",
88
+ "+": "delete",
89
+ });
90
+ const taskItemSchemaIsolated = type({
91
+ "id?": "string",
92
+ "description?": "string",
93
+ "role?": ROLE_INPUT_SCHEMA,
94
+ assignment: "string",
95
+ "isolated?": "boolean",
96
+ "+": "delete",
97
+ });
112
98
 
113
99
  /** Single task item. Fields are optional defensively: args stream in token by token. */
114
100
  export interface TaskItem {
@@ -124,17 +110,34 @@ export interface TaskItem {
124
110
  isolated?: boolean;
125
111
  }
126
112
 
127
- export const taskSchema = z.object({ ...agentShape, ...taskItemShape, ...isolatedShape });
128
- const taskSchemaNoIsolation = z.object({ ...agentShape, ...taskItemShape });
129
- const taskSchemaBatch = z.object({
130
- ...agentShape,
131
- ...contextShape,
132
- tasks: z.array(taskItemSchemaIsolated).describe("tasks to spawn; one subagent per item"),
113
+ export const taskSchema = type({
114
+ agent: "string",
115
+ "id?": "string",
116
+ "description?": "string",
117
+ "role?": ROLE_INPUT_SCHEMA,
118
+ assignment: "string",
119
+ "isolated?": "boolean",
120
+ "+": "delete",
121
+ });
122
+ const taskSchemaNoIsolation = type({
123
+ agent: "string",
124
+ "id?": "string",
125
+ "description?": "string",
126
+ "role?": ROLE_INPUT_SCHEMA,
127
+ assignment: "string",
128
+ "+": "delete",
129
+ });
130
+ const taskSchemaBatch = type({
131
+ agent: "string",
132
+ context: "string",
133
+ tasks: taskItemSchemaIsolated.array(),
134
+ "+": "delete",
133
135
  });
134
- const taskSchemaBatchNoIsolation = z.object({
135
- ...agentShape,
136
- ...contextShape,
137
- tasks: z.array(taskItemSchema).describe("tasks to spawn; one subagent per item"),
136
+ const taskSchemaBatchNoIsolation = type({
137
+ agent: "string",
138
+ context: "string",
139
+ tasks: taskItemSchema.array(),
140
+ "+": "delete",
138
141
  });
139
142
  const ALL_TASK_SCHEMAS = [taskSchema, taskSchemaNoIsolation, taskSchemaBatch, taskSchemaBatchNoIsolation] as const;
140
143
 
@@ -1,5 +1,6 @@
1
1
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
2
- import { isZodSchema, zodToWireSchema } from "@oh-my-pi/pi-ai/utils/schema";
2
+ import type { Tool as AiTool } from "@oh-my-pi/pi-ai";
3
+ import { toolWireSchema } from "@oh-my-pi/pi-ai/utils/schema";
3
4
 
4
5
  // ─── Generic Tool Discovery Types ────────────────────────────────────────────
5
6
 
@@ -65,8 +66,13 @@ export function isMCPToolName(name: string): boolean {
65
66
  return name.startsWith("mcp__");
66
67
  }
67
68
 
68
- function getSchemaPropertyKeys(parameters: unknown): string[] {
69
- if (isZodSchema(parameters)) parameters = zodToWireSchema(parameters);
69
+ function getSchemaPropertyKeys(tool: Pick<AiTool, "name" | "description" | "parameters">): string[] {
70
+ let parameters: unknown = tool.parameters;
71
+ try {
72
+ parameters = toolWireSchema(tool as AiTool);
73
+ } catch {
74
+ // Schema may contain functions or cycles; fall back to the raw shape.
75
+ }
70
76
  if (!parameters || typeof parameters !== "object" || Array.isArray(parameters)) return [];
71
77
  const properties = (parameters as { properties?: unknown }).properties;
72
78
  if (!properties || typeof properties !== "object" || Array.isArray(properties)) return [];
@@ -149,7 +155,14 @@ export function getDiscoverableTool(
149
155
  source,
150
156
  serverName: typeof toolRecord.mcpServerName === "string" ? toolRecord.mcpServerName : undefined,
151
157
  mcpToolName: typeof toolRecord.mcpToolName === "string" ? toolRecord.mcpToolName : undefined,
152
- schemaKeys: getSchemaPropertyKeys(toolRecord.parameters),
158
+ schemaKeys:
159
+ toolRecord.parameters === undefined
160
+ ? []
161
+ : getSchemaPropertyKeys({
162
+ name: tool.name,
163
+ description: rawDescription,
164
+ parameters: toolRecord.parameters as AiTool["parameters"],
165
+ }),
153
166
  };
154
167
  }
155
168
 
package/src/tools/ask.ts CHANGED
@@ -19,7 +19,7 @@ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallb
19
19
  import type { ToolExample } from "@oh-my-pi/pi-ai";
20
20
  import { type Component, Markdown, type MarkdownTheme, renderInlineMarkdown, TERMINAL, Text } from "@oh-my-pi/pi-tui";
21
21
  import { prompt, untilAborted } from "@oh-my-pi/pi-utils";
22
- import { z } from "zod/v4";
22
+ import { type as arkType } from "arktype";
23
23
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
24
24
  import type { ExtensionUISelectItem } from "../extensibility/extensions";
25
25
  import { getMarkdownTheme, type Theme, theme } from "../modes/theme/theme";
@@ -34,24 +34,24 @@ import { ToolAbortError } from "./tool-errors";
34
34
  // Types
35
35
  // =============================================================================
36
36
 
37
- const OptionItem = z.object({
38
- label: z.string().describe("display label"),
39
- description: z.string().describe("optional explanatory text displayed below the label").optional(),
37
+ const OptionItem = arkType({
38
+ label: arkType("string").describe("display label"),
39
+ "description?": arkType("string").describe("optional explanatory text displayed below the label"),
40
40
  });
41
41
 
42
- const QuestionItem = z.object({
43
- id: z.string().describe("question id"),
44
- question: z.string().describe("question text"),
45
- options: z.array(OptionItem).describe("available options"),
46
- multi: z.boolean().describe("allow multiple selections").optional(),
47
- recommended: z.number().describe("recommended option index").optional(),
42
+ const QuestionItem = arkType({
43
+ id: arkType("string").describe("question id"),
44
+ question: arkType("string").describe("question text"),
45
+ options: OptionItem.array().describe("available options"),
46
+ "multi?": arkType("boolean").describe("allow multiple selections"),
47
+ "recommended?": arkType("number").describe("recommended option index"),
48
48
  });
49
49
 
50
- const askSchema = z.object({
51
- questions: z.array(QuestionItem).min(1).describe("questions to ask"),
50
+ const askSchema = arkType({
51
+ questions: QuestionItem.array().atLeastLength(1).describe("questions to ask"),
52
52
  });
53
53
 
54
- export type AskToolInput = z.infer<typeof askSchema>;
54
+ export type AskToolInput = typeof askSchema.infer;
55
55
 
56
56
  /** Result for a single question */
57
57
  export interface QuestionResult {
@@ -424,7 +424,7 @@ export class AskTool implements AgentTool<typeof askSchema, AskToolDetails> {
424
424
  readonly parameters = askSchema;
425
425
  readonly strict = true;
426
426
 
427
- readonly examples: readonly ToolExample<z.input<typeof askSchema>>[] = [
427
+ readonly examples: readonly ToolExample<typeof askSchema.infer>[] = [
428
428
  {
429
429
  caption: "Single question",
430
430
  call: {
@@ -6,7 +6,7 @@ import { type AstReplaceChange, type AstReplaceFileChange, astEdit } from "@oh-m
6
6
  import type { Component } from "@oh-my-pi/pi-tui";
7
7
  import { replaceTabs, Text } from "@oh-my-pi/pi-tui";
8
8
  import { $envpos, prompt, untilAborted } from "@oh-my-pi/pi-utils";
9
- import { z } from "zod/v4";
9
+ import { type } from "arktype";
10
10
  import { canonicalSnapshotKey, getFileSnapshotStore } from "../edit/file-snapshot-store";
11
11
  import { normalizeToLF } from "../edit/normalize";
12
12
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
@@ -35,16 +35,17 @@ import { queueResolveHandler } from "./resolve";
35
35
  import { ToolError } from "./tool-errors";
36
36
  import { toolResult } from "./tool-result";
37
37
 
38
- const astEditOpSchema = z.object({
39
- pat: z.string().describe("ast pattern"),
40
- out: z.string().describe("replacement template"),
38
+ const astEditOpSchema = type({
39
+ pat: type("string").describe("ast pattern"),
40
+ out: type("string").describe("replacement template"),
41
41
  });
42
42
 
43
- const astEditSchema = z.object({
44
- ops: z.array(astEditOpSchema).min(1).describe("rewrite ops"),
45
- paths: z
46
- .array(z.string().describe("file, directory, glob, or internal URL to rewrite"))
47
- .min(1)
43
+ const astEditSchema = type({
44
+ ops: astEditOpSchema.array().atLeastLength(1).describe("rewrite ops"),
45
+ paths: type("string")
46
+ .describe("file, directory, glob, or internal URL to rewrite")
47
+ .array()
48
+ .atLeastLength(1)
48
49
  .describe("files, directories, globs, or internal URLs to rewrite"),
49
50
  });
50
51
 
@@ -165,16 +166,18 @@ export interface AstEditToolDetails {
165
166
  cwd?: string;
166
167
  }
167
168
 
169
+ type AstEditSchemaInfer = typeof astEditSchema.infer;
170
+
168
171
  export class AstEditTool implements AgentTool<typeof astEditSchema, AstEditToolDetails> {
169
172
  readonly name = "ast_edit";
170
173
  readonly approval = (args: unknown) => {
171
- const paths = Array.isArray((args as Partial<z.infer<typeof astEditSchema>>).paths)
172
- ? ((args as Partial<z.infer<typeof astEditSchema>>).paths as string[])
174
+ const paths = Array.isArray((args as Partial<AstEditSchemaInfer>).paths)
175
+ ? ((args as Partial<AstEditSchemaInfer>).paths as string[])
173
176
  : [];
174
177
  return paths.length > 0 && paths.every(path => isInternalUrlPath(path)) ? "read" : "write";
175
178
  };
176
179
  readonly formatApprovalDetails = (args: unknown): string[] => {
177
- const params = args as Partial<z.infer<typeof astEditSchema>>;
180
+ const params = args as Partial<AstEditSchemaInfer>;
178
181
  const lines: string[] = [];
179
182
  const ops = Array.isArray(params.ops) ? params.ops : [];
180
183
  const firstOp = ops[0];
@@ -196,7 +199,7 @@ export class AstEditTool implements AgentTool<typeof astEditSchema, AstEditToolD
196
199
  readonly parameters = astEditSchema;
197
200
  readonly strict = true;
198
201
 
199
- readonly examples: readonly ToolExample<z.input<typeof astEditSchema>>[] = [
202
+ readonly examples: readonly ToolExample<AstEditSchemaInfer>[] = [
200
203
  {
201
204
  caption: "Rename a call site across TypeScript files",
202
205
  call: {
@@ -248,7 +251,7 @@ export class AstEditTool implements AgentTool<typeof astEditSchema, AstEditToolD
248
251
 
249
252
  async execute(
250
253
  _toolCallId: string,
251
- params: z.infer<typeof astEditSchema>,
254
+ params: AstEditSchemaInfer,
252
255
  signal?: AbortSignal,
253
256
  _onUpdate?: AgentToolUpdateCallback<AstEditToolDetails>,
254
257
  _context?: AgentToolContext,
@@ -6,7 +6,7 @@ import { type AstFindMatch, astGrep } from "@oh-my-pi/pi-natives";
6
6
  import type { Component } from "@oh-my-pi/pi-tui";
7
7
  import { Text } from "@oh-my-pi/pi-tui";
8
8
  import { prompt, untilAborted } from "@oh-my-pi/pi-utils";
9
- import { z } from "zod/v4";
9
+ import { type } from "arktype";
10
10
  import { recordFileSnapshot, recordSeenLinesFromBody } from "../edit/file-snapshot-store";
11
11
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
12
12
  import type { Theme } from "../modes/theme/theme";
@@ -34,13 +34,14 @@ import {
34
34
  import { ToolError } from "./tool-errors";
35
35
  import { toolResult } from "./tool-result";
36
36
 
37
- const astGrepSchema = z.object({
38
- pat: z.string().describe("ast pattern"),
39
- paths: z
40
- .array(z.string().describe("file, directory, glob, or internal URL to search"))
41
- .min(1)
37
+ const astGrepSchema = type({
38
+ pat: type("string").describe("ast pattern"),
39
+ paths: type("string")
40
+ .describe("file, directory, glob, or internal URL to search")
41
+ .array()
42
+ .atLeastLength(1)
42
43
  .describe("files, directories, globs, or internal URLs to search"),
43
- skip: z.number().default(0).describe("matches to skip").optional(),
44
+ "skip?": type("number").describe("matches to skip"),
44
45
  });
45
46
 
46
47
  async function runMultiTargetAstGrep(
@@ -132,7 +133,7 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
132
133
  readonly parameters = astGrepSchema;
133
134
  readonly strict = true;
134
135
 
135
- readonly examples: readonly ToolExample<z.input<typeof astGrepSchema>>[] = [
136
+ readonly examples: readonly ToolExample<typeof astGrepSchema.inferIn>[] = [
136
137
  {
137
138
  caption: "Search TypeScript files under src",
138
139
  call: { pat: "console.log($$$)", paths: ["src/**/*.ts"] },
@@ -162,7 +163,7 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
162
163
 
163
164
  async execute(
164
165
  _toolCallId: string,
165
- params: z.infer<typeof astGrepSchema>,
166
+ params: typeof astGrepSchema.infer,
166
167
  signal?: AbortSignal,
167
168
  _onUpdate?: AgentToolUpdateCallback<AstGrepToolDetails>,
168
169
  _context?: AgentToolContext,