@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
@@ -106,7 +106,7 @@ export const TAB_METADATA: Record<SettingTab, { label: string; icon: `tab.${stri
106
106
  */
107
107
  export const TAB_GROUPS: Record<SettingTab, readonly string[]> = {
108
108
  appearance: ["Theme", "Status Line", "Display", "Images"],
109
- model: ["Thinking", "Sampling", "Prompt", "Retry & Fallback", "Advisor"],
109
+ model: ["Thinking", "Sampling", "Prompt", "Retry & Fallback", "Advisor", "Vision"],
110
110
  interaction: [
111
111
  "Input",
112
112
  "Approvals",
@@ -117,6 +117,7 @@ export const TAB_GROUPS: Record<SettingTab, readonly string[]> = {
117
117
  "Startup & Updates",
118
118
  "Power (macOS)",
119
119
  "Agent",
120
+ "Git",
120
121
  ],
121
122
  context: ["General", "Compaction", "Rules (TTSR)", "Experimental"],
122
123
  memory: ["General", "Auto-Learn", "Mnemopi", "Hindsight"],
@@ -414,7 +415,36 @@ export const SETTINGS_SCHEMA = {
414
415
  "Pause the main agent for up to 30 seconds if the advisor falls behind by this many turns. Off disables catch-up delays.",
415
416
  },
416
417
  },
418
+ "advisor.immuneTurns": {
419
+ type: "number",
420
+ default: 1,
421
+ ui: {
422
+ tab: "model",
423
+ group: "Advisor",
424
+ label: "Advisor Immune Turns",
425
+ description:
426
+ "After an advisor concern or blocker interrupts, route further concerns/blockers non-interruptingly for this many primary turns.",
427
+ options: [
428
+ { value: "0", label: "0 turns", description: "Allow every concern/blocker to interrupt." },
429
+ { value: "1", label: "1 turn", description: "Default." },
430
+ { value: "2", label: "2 turns" },
431
+ { value: "3", label: "3 turns" },
432
+ { value: "4", label: "4 turns" },
433
+ { value: "5", label: "5 turns" },
434
+ ],
435
+ },
436
+ },
417
437
  shellPath: { type: "string", default: undefined },
438
+ "git.enabled": {
439
+ type: "boolean",
440
+ default: true,
441
+ ui: {
442
+ tab: "interaction",
443
+ group: "Git",
444
+ label: "Enable Git Integration",
445
+ description: "Show git branch, status, and PR information in the TUI and watch repository metadata.",
446
+ },
447
+ },
418
448
 
419
449
  extensions: { type: "array", default: EMPTY_STRING_ARRAY },
420
450
 
@@ -712,6 +742,18 @@ export const SETTINGS_SCHEMA = {
712
742
  },
713
743
  },
714
744
 
745
+ "images.describeForTextModels": {
746
+ type: "boolean",
747
+ default: true,
748
+ ui: {
749
+ tab: "model",
750
+ group: "Vision",
751
+ label: "Describe Images for Text Models",
752
+ description:
753
+ "When an image is attached to a model without vision support, save it under local:// and inject a description from a vision-capable model instead of dropping it",
754
+ },
755
+ },
756
+
715
757
  "tui.maxInlineImageColumns": {
716
758
  type: "number",
717
759
  default: 100,
@@ -757,6 +799,16 @@ export const SETTINGS_SCHEMA = {
757
799
  "Wrap paths and URLs in OSC 8 hyperlinks for terminal-native click-to-open (auto: detect support; off: never; always: unconditional)",
758
800
  },
759
801
  },
802
+ "tui.tight": {
803
+ type: "boolean",
804
+ default: false,
805
+ ui: {
806
+ tab: "appearance",
807
+ group: "Display",
808
+ label: "Tight Layout",
809
+ description: "Remove the 1-character horizontal padding from the left and right of the terminal output",
810
+ },
811
+ },
760
812
  // Display rendering
761
813
  "display.tabWidth": {
762
814
  type: "number",
@@ -845,6 +897,28 @@ export const SETTINGS_SCHEMA = {
845
897
  },
846
898
  },
847
899
 
900
+ "model.loopGuard.enabled": {
901
+ type: "boolean",
902
+ default: true,
903
+ ui: {
904
+ tab: "model",
905
+ group: "Thinking",
906
+ label: "Loop Guard",
907
+ description: "Enable automatic stream loop detection for Gemini and DeepSeek models",
908
+ },
909
+ },
910
+
911
+ "model.loopGuard.checkAssistantContent": {
912
+ type: "boolean",
913
+ default: true,
914
+ ui: {
915
+ tab: "model",
916
+ group: "Thinking",
917
+ label: "Loop Guard Scan Prose",
918
+ description: "Apply loop guard to assistant prose messages in addition to thinking logs",
919
+ },
920
+ },
921
+
848
922
  repeatToolDescriptions: {
849
923
  type: "boolean",
850
924
  default: false,
@@ -1284,6 +1358,18 @@ export const SETTINGS_SCHEMA = {
1284
1358
  },
1285
1359
  },
1286
1360
 
1361
+ "startup.showSplash": {
1362
+ type: "boolean",
1363
+ default: false,
1364
+ ui: {
1365
+ tab: "interaction",
1366
+ group: "Startup & Updates",
1367
+ label: "Show Startup Splash",
1368
+ description:
1369
+ "Show the full animated setup splash on normal interactive startup without rerunning setup. Quiet Startup still suppresses it.",
1370
+ },
1371
+ },
1372
+
1287
1373
  "startup.setupWizard": {
1288
1374
  type: "boolean",
1289
1375
  default: true,
@@ -1505,7 +1591,7 @@ export const SETTINGS_SCHEMA = {
1505
1591
  // Context promotion
1506
1592
  "contextPromotion.enabled": {
1507
1593
  type: "boolean",
1508
- default: true,
1594
+ default: false,
1509
1595
  ui: {
1510
1596
  tab: "context",
1511
1597
  group: "General",
@@ -1769,6 +1855,7 @@ export const SETTINGS_SCHEMA = {
1769
1855
  "qwen3",
1770
1856
  "gemini",
1771
1857
  "gemma",
1858
+ "minimax",
1772
1859
  ] as const,
1773
1860
  default: "auto",
1774
1861
  ui: {
@@ -1795,6 +1882,7 @@ export const SETTINGS_SCHEMA = {
1795
1882
  { value: "qwen3", label: "Qwen3", description: "Use the Qwen3 owned dialect." },
1796
1883
  { value: "gemini", label: "Gemini", description: "Use the Gemini owned dialect." },
1797
1884
  { value: "gemma", label: "Gemma", description: "Use the Gemma owned dialect." },
1885
+ { value: "minimax", label: "MiniMax", description: "Use the MiniMax owned dialect." },
1798
1886
  ],
1799
1887
  },
1800
1888
  },
@@ -3857,6 +3945,34 @@ export const SETTINGS_SCHEMA = {
3857
3945
  description: "Providers that web_search should never use, even as fallbacks",
3858
3946
  },
3859
3947
  },
3948
+ "providers.antigravityEndpoint": {
3949
+ type: "enum",
3950
+ values: ["auto", "production", "sandbox"] as const,
3951
+ default: "auto",
3952
+ ui: {
3953
+ tab: "providers",
3954
+ group: "Services",
3955
+ label: "Antigravity Endpoint Mode",
3956
+ description: "Endpoint routing strategy for google-antigravity providers (chat, search, image, discovery)",
3957
+ options: [
3958
+ {
3959
+ value: "auto",
3960
+ label: "Auto",
3961
+ description: "Try production endpoint, fail over to sandbox on 5xx/429",
3962
+ },
3963
+ {
3964
+ value: "production",
3965
+ label: "Production Only",
3966
+ description: "Force production endpoint only",
3967
+ },
3968
+ {
3969
+ value: "sandbox",
3970
+ label: "Sandbox Only",
3971
+ description: "Force sandbox endpoint only",
3972
+ },
3973
+ ],
3974
+ },
3975
+ },
3860
3976
  "providers.image": {
3861
3977
  type: "enum",
3862
3978
  values: ["auto", "openai", "antigravity", "xai", "gemini", "openrouter"] as const,
@@ -19,6 +19,7 @@ import tsImportType from "./ts-import-type.md" with { type: "text" };
19
19
  import tsNoAny from "./ts-no-any.md" with { type: "text" };
20
20
  import tsNoDeprecatedLeftovers from "./ts-no-deprecated-leftovers.md" with { type: "text" };
21
21
  import tsNoDynamicImport from "./ts-no-dynamic-import.md" with { type: "text" };
22
+ import tsNoInlineCastAccess from "./ts-no-inline-cast-access.md" with { type: "text" };
22
23
  import tsNoReturnType from "./ts-no-return-type.md" with { type: "text" };
23
24
  import tsNoTestTimers from "./ts-no-test-timers.md" with { type: "text" };
24
25
  import tsNoTinyFunctions from "./ts-no-tiny-functions.md" with { type: "text" };
@@ -45,6 +46,7 @@ export const BUILTIN_RULE_SOURCES: readonly BuiltinRuleSource[] = [
45
46
  { name: "ts-no-any", content: tsNoAny },
46
47
  { name: "ts-no-deprecated-leftovers", content: tsNoDeprecatedLeftovers },
47
48
  { name: "ts-no-dynamic-import", content: tsNoDynamicImport },
49
+ { name: "ts-no-inline-cast-access", content: tsNoInlineCastAccess },
48
50
  { name: "ts-no-return-type", content: tsNoReturnType },
49
51
  { name: "ts-no-test-timers", content: tsNoTestTimers },
50
52
  { name: "ts-no-tiny-functions", content: tsNoTinyFunctions },
@@ -17,7 +17,7 @@ Use top-level `import type` declarations for type-only dependencies. NEVER write
17
17
 
18
18
  ```typescript
19
19
  // Bad — inline imports hide dependencies in signatures.
20
- function run(client: import("some-sdk").Client, input: import("zod/v4").infer<Schema>): Promise<Output>;
20
+ function run(client: import("some-sdk").Client, input: import("arktype").infer<Schema>): Promise<Output>;
21
21
 
22
22
  // Bad — annotations become path dumps.
23
23
  const options: import("some-sdk/config").ClientOptions = { ... };
@@ -28,7 +28,7 @@ const options: import("some-sdk/config").ClientOptions = { ... };
28
28
  ```typescript
29
29
  import type { Client } from "some-sdk";
30
30
  import type { ClientOptions } from "some-sdk/config";
31
- import type { infer as Infer } from "zod/v4";
31
+ import type { infer as Infer } from "arktype";
32
32
 
33
33
  function run(client: Client, input: Infer<Schema>): Promise<Output>;
34
34
  const options: ClientOptions = { ... };
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Never use `any` in TypeScript annotations or assertions — use `unknown`, generics, or the actual type"
2
+ description: "Never use `any` in TypeScript annotations or assertions — use `unknown`, generics, a schema parse at trust boundaries, or the actual type"
3
3
  condition: ": any|as any"
4
4
  scope: "tool:edit(*.ts), tool:edit(*.tsx), tool:write(*.ts), tool:write(*.tsx)"
5
5
  ---
@@ -9,6 +9,7 @@ Never use `: any` or `as any`. They disable type checking exactly where the boun
9
9
  ## Use instead
10
10
 
11
11
  - `unknown` for unvalidated input.
12
+ - A schema parse (Zod, Valibot, …; e.g. Zod v4 when it is already in the project) for untrusted or external input — validate once, then consume a typed value.
12
13
  - A domain type when the shape is known.
13
14
  - A generic when the caller supplies the shape.
14
15
  - A type guard when runtime checks establish shape.
@@ -25,7 +26,7 @@ function readId(value: any): any {
25
26
  // Good — validate unknown input.
26
27
  function readId(value: unknown): string | undefined {
27
28
  if (value && typeof value === "object" && "id" in value) {
28
- const candidate = (value as { id: unknown }).id;
29
+ const candidate = value.id; // `in` narrowing types this as unknown — no cast needed
29
30
  return typeof candidate === "string" ? candidate : undefined;
30
31
  }
31
32
  }
@@ -53,4 +54,12 @@ const config = { port: 3000 } as any as ServerConfig;
53
54
  const config = { port: 3000 } satisfies ServerConfig;
54
55
  ```
55
56
 
57
+ ## Choosing: guard vs schema vs unchecked cast
58
+
59
+ | Situation | Reach for |
60
+ | --- | --- |
61
+ | Data from outside your control — network/RPC, parsed JSON, config files, env vars, CLI/IPC, persisted blobs — or a shape reused across the codebase | **Schema parse** (Zod/Valibot/…): runtime validation, typed output, and a clear error on bad shape |
62
+ | In-process value the compiler merely lost track of — an `unknown` from a generic, a union to discriminate, a one-off read of a field or two | **Type guard** (`in` / `typeof`): no dependency, but it only checks what you write, so keep the checked surface small |
63
+ | You genuinely know more than the compiler *and* a runtime check is impossible or meaningless — a well-known DOM node (`as HTMLElement`), structurally-identical types inference can't unify, a library type that is wrong or unexpressible, `as const` | **Unchecked cast** (`as` / `as unknown as T`): assign to a named const with a one-line reason; never for raw external input |
64
+
56
65
  If a library boundary truly requires an unchecked cast, use `as unknown as T` with a short reason. Never leave a bare `any`.
@@ -0,0 +1,55 @@
1
+ ---
2
+ description: "Don't assert an inline object type and immediately read a property — `(x as { y: T }).y` trusts an unchecked shape; validate with a schema parse at trust boundaries, narrow with `in`/`typeof`, or use a validated named type"
3
+ scope: "tool:edit(*.{ts,tsx,mts,cts}), tool:write(*.{ts,tsx,mts,cts})"
4
+ interruptMode: tool-only
5
+ astCondition:
6
+ - "($X as { $$$BODY }).$PROP"
7
+ - "($X as { $$$BODY })?.$PROP"
8
+ - "($X as { $$$BODY })[$IDX]"
9
+ ---
10
+
11
+ **Don't assert an inline object type just to read a property.** `(value as { content: unknown }).content` fabricates a shape the compiler never verified, then trusts it for exactly one access. If `value` isn't that shape, the read is silently wrong and no type error ever fires.
12
+
13
+ ## Why it's wrong
14
+
15
+ - The cast is an unchecked assertion — it suppresses the type error instead of proving the shape.
16
+ - It localizes the lie to one expression, so the next reader can't tell whether the value was ever validated.
17
+ - It almost always stands in for the real fix: runtime narrowing or a validated type at the boundary.
18
+
19
+ ## Avoid
20
+
21
+ ```ts
22
+ const content = (value as { content: unknown }).content;
23
+ const id = (resp as { data: { id: string } }).data.id;
24
+ const name = (payload as { name?: string })?.name;
25
+ const flag = (opts as { enabled: boolean })["enabled"];
26
+ ```
27
+
28
+ ## Use
29
+
30
+ Prefer a schema parse at the boundary when a validator is available (Zod, Valibot, …) — validate once, then read from a fully typed value. If Zod is already in the project (e.g. Zod v4):
31
+
32
+ ```ts
33
+ import { z } from "zod/v4";
34
+
35
+ const Resp = z.object({ data: z.object({ id: z.string() }) });
36
+
37
+ const resp = Resp.parse(raw); // throws on bad input; resp.data.id is typed string
38
+ const id = resp.data.id;
39
+ ```
40
+
41
+ For a one-off read of a single field, narrow with `in` / `typeof` so the access is actually checked — TypeScript infers `unknown` for the property after `"content" in value`:
42
+
43
+ ```ts
44
+ if (value && typeof value === "object" && "content" in value) {
45
+ const content = value.content; // unknown — validate before use
46
+ }
47
+ ```
48
+
49
+ ## Choosing: guard vs schema vs unchecked cast
50
+
51
+ | Situation | Reach for |
52
+ | --- | --- |
53
+ | Data from outside your control — network/RPC, parsed JSON, config files, env vars, CLI/IPC, persisted blobs — or a shape reused across the codebase | **Schema parse** (Zod/Valibot/…): runtime validation, typed output, and a clear error on bad shape |
54
+ | In-process value the compiler merely lost track of — an `unknown` from a generic, a union to discriminate, a one-off read of a field or two | **Type guard** (`in` / `typeof`): no dependency, but it only checks what you write, so keep the checked surface small |
55
+ | You genuinely know more than the compiler *and* a runtime check is impossible or meaningless — a well-known DOM node (`as HTMLElement`), structurally-identical types inference can't unify, a library type that's wrong or unexpressible, `as const` | **Unchecked cast** (`as`): assign to a named const with a one-line reason; never for raw external input, never inlined into a member access |
@@ -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
  }