@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
@@ -11,9 +11,9 @@ import {
11
11
  } from "@oh-my-pi/pi-natives";
12
12
  import type { EditorTheme, MarkdownTheme, SelectListTheme, SettingsListTheme, SymbolTheme } from "@oh-my-pi/pi-tui";
13
13
  import { adjustHsv, colorLuma, getCustomThemesDir, isEnoent, logger, relativeLuminance } from "@oh-my-pi/pi-utils";
14
+ import { type } from "arktype";
14
15
  import chalk from "chalk";
15
16
  import { LRUCache } from "lru-cache/raw";
16
- import { z } from "zod/v4";
17
17
  // Embed theme JSON files at build time
18
18
  import darkThemeJson from "./dark.json" with { type: "json" };
19
19
  import { defaultThemes } from "./defaults";
@@ -972,125 +972,117 @@ function normalizeSpinnerFramesOverride(
972
972
  // Types & Schema
973
973
  // ============================================================================
974
974
 
975
- const colorValueSchema = z.union([
976
- z.string(), // hex "#ff0000", var ref "primary", or empty ""
977
- z.number().int().min(0).max(255), // 256-color index
978
- ]);
979
-
980
- type ColorValue = z.infer<typeof colorValueSchema>;
981
-
982
- const THEME_COLOR_KEYS = [
983
- "accent",
984
- "border",
985
- "borderAccent",
986
- "borderMuted",
987
- "success",
988
- "error",
989
- "warning",
990
- "muted",
991
- "dim",
992
- "text",
993
- "thinkingText",
994
- "selectedBg",
995
- "userMessageBg",
996
- "userMessageText",
997
- "customMessageBg",
998
- "customMessageText",
999
- "customMessageLabel",
1000
- "toolPendingBg",
1001
- "toolSuccessBg",
1002
- "toolErrorBg",
1003
- "toolTitle",
1004
- "toolOutput",
1005
- "mdHeading",
1006
- "mdLink",
1007
- "mdLinkUrl",
1008
- "mdCode",
1009
- "mdCodeBlock",
1010
- "mdCodeBlockBorder",
1011
- "mdQuote",
1012
- "mdQuoteBorder",
1013
- "mdHr",
1014
- "mdListBullet",
1015
- "toolDiffAdded",
1016
- "toolDiffRemoved",
1017
- "toolDiffContext",
1018
- "syntaxComment",
1019
- "syntaxKeyword",
1020
- "syntaxFunction",
1021
- "syntaxVariable",
1022
- "syntaxString",
1023
- "syntaxNumber",
1024
- "syntaxType",
1025
- "syntaxOperator",
1026
- "syntaxPunctuation",
1027
- "thinkingOff",
1028
- "thinkingMinimal",
1029
- "thinkingLow",
1030
- "thinkingMedium",
1031
- "thinkingHigh",
1032
- "thinkingXhigh",
1033
- "bashMode",
1034
- "pythonMode",
1035
- "statusLineBg",
1036
- "statusLineSep",
1037
- "statusLineModel",
1038
- "statusLinePath",
1039
- "statusLineGitClean",
1040
- "statusLineGitDirty",
1041
- "statusLineContext",
1042
- "statusLineSpend",
1043
- "statusLineStaged",
1044
- "statusLineDirty",
1045
- "statusLineUntracked",
1046
- "statusLineOutput",
1047
- "statusLineCost",
1048
- "statusLineSubagents",
1049
- ] as const;
1050
-
1051
- const themeColorsSchema = z.object(
1052
- Object.fromEntries(THEME_COLOR_KEYS.map(key => [key, colorValueSchema])) as unknown as {
1053
- [K in (typeof THEME_COLOR_KEYS)[number]]: typeof colorValueSchema;
1054
- },
1055
- );
1056
-
1057
- const spinnerFramesArraySchema = z.array(z.string().min(1)).min(1);
1058
- const spinnerFramesSchema = z.union([
1059
- spinnerFramesArraySchema,
1060
- z
1061
- .object({
1062
- status: spinnerFramesArraySchema.optional(),
1063
- activity: spinnerFramesArraySchema.optional(),
1064
- })
1065
- .refine(value => value.status !== undefined || value.activity !== undefined, {
1066
- message: "spinnerFrames object must define `status` and/or `activity`",
1067
- }),
1068
- ]);
1069
-
1070
- const symbolPresetSchema = z.enum(["unicode", "nerd", "ascii"]);
1071
-
1072
- const themeJsonSchema = z.object({
1073
- $schema: z.string().optional(),
1074
- name: z.string(),
1075
- vars: z.record(z.string(), colorValueSchema).optional(),
975
+ type ColorValue = string | number;
976
+
977
+ const themeColorsSchema = type({
978
+ accent: "string | number",
979
+ border: "string | number",
980
+ borderAccent: "string | number",
981
+ borderMuted: "string | number",
982
+ success: "string | number",
983
+ error: "string | number",
984
+ warning: "string | number",
985
+ muted: "string | number",
986
+ dim: "string | number",
987
+ text: "string | number",
988
+ thinkingText: "string | number",
989
+ selectedBg: "string | number",
990
+ userMessageBg: "string | number",
991
+ userMessageText: "string | number",
992
+ customMessageBg: "string | number",
993
+ customMessageText: "string | number",
994
+ customMessageLabel: "string | number",
995
+ toolPendingBg: "string | number",
996
+ toolSuccessBg: "string | number",
997
+ toolErrorBg: "string | number",
998
+ toolTitle: "string | number",
999
+ toolOutput: "string | number",
1000
+ mdHeading: "string | number",
1001
+ mdLink: "string | number",
1002
+ mdLinkUrl: "string | number",
1003
+ mdCode: "string | number",
1004
+ mdCodeBlock: "string | number",
1005
+ mdCodeBlockBorder: "string | number",
1006
+ mdQuote: "string | number",
1007
+ mdQuoteBorder: "string | number",
1008
+ mdHr: "string | number",
1009
+ mdListBullet: "string | number",
1010
+ toolDiffAdded: "string | number",
1011
+ toolDiffRemoved: "string | number",
1012
+ toolDiffContext: "string | number",
1013
+ syntaxComment: "string | number",
1014
+ syntaxKeyword: "string | number",
1015
+ syntaxFunction: "string | number",
1016
+ syntaxVariable: "string | number",
1017
+ syntaxString: "string | number",
1018
+ syntaxNumber: "string | number",
1019
+ syntaxType: "string | number",
1020
+ syntaxOperator: "string | number",
1021
+ syntaxPunctuation: "string | number",
1022
+ thinkingOff: "string | number",
1023
+ thinkingMinimal: "string | number",
1024
+ thinkingLow: "string | number",
1025
+ thinkingMedium: "string | number",
1026
+ thinkingHigh: "string | number",
1027
+ thinkingXhigh: "string | number",
1028
+ bashMode: "string | number",
1029
+ pythonMode: "string | number",
1030
+ statusLineBg: "string | number",
1031
+ statusLineSep: "string | number",
1032
+ statusLineModel: "string | number",
1033
+ statusLinePath: "string | number",
1034
+ statusLineGitClean: "string | number",
1035
+ statusLineGitDirty: "string | number",
1036
+ statusLineContext: "string | number",
1037
+ statusLineSpend: "string | number",
1038
+ statusLineStaged: "string | number",
1039
+ statusLineDirty: "string | number",
1040
+ statusLineUntracked: "string | number",
1041
+ statusLineOutput: "string | number",
1042
+ statusLineCost: "string | number",
1043
+ statusLineSubagents: "string | number",
1044
+ });
1045
+ const spinnerFramesSchema = type("unknown").narrow((value): value is SpinnerFramesOverride => {
1046
+ if (Array.isArray(value)) {
1047
+ return value.length >= 1 && value.every(item => typeof item === "string");
1048
+ }
1049
+ if (value && typeof value === "object") {
1050
+ const obj = value as Record<string, unknown>;
1051
+ const status = obj.status;
1052
+ const activity = obj.activity;
1053
+ if (status === undefined && activity === undefined) return false;
1054
+ if (status !== undefined) {
1055
+ if (!Array.isArray(status) || status.length < 1 || !status.every(item => typeof item === "string")) {
1056
+ return false;
1057
+ }
1058
+ }
1059
+ if (activity !== undefined) {
1060
+ if (!Array.isArray(activity) || activity.length < 1 || !activity.every(item => typeof item === "string")) {
1061
+ return false;
1062
+ }
1063
+ }
1064
+ return true;
1065
+ }
1066
+ return false;
1067
+ });
1068
+ const themeJsonSchema = type({
1069
+ "$schema?": "string",
1070
+ name: "string",
1071
+ "vars?": "Record<string, string | number>",
1076
1072
  colors: themeColorsSchema,
1077
- export: z
1078
- .object({
1079
- pageBg: colorValueSchema.optional(),
1080
- cardBg: colorValueSchema.optional(),
1081
- infoBg: colorValueSchema.optional(),
1082
- })
1083
- .optional(),
1084
- symbols: z
1085
- .object({
1086
- preset: symbolPresetSchema.optional(),
1087
- overrides: z.record(z.string(), z.string()).optional(),
1088
- spinnerFrames: spinnerFramesSchema.optional(),
1089
- })
1090
- .optional(),
1073
+ "export?": {
1074
+ "pageBg?": "string | number",
1075
+ "cardBg?": "string | number",
1076
+ "infoBg?": "string | number",
1077
+ },
1078
+ "symbols?": {
1079
+ "preset?": "'unicode' | 'nerd' | 'ascii'",
1080
+ "overrides?": "Record<string, string>",
1081
+ "spinnerFrames?": spinnerFramesSchema,
1082
+ },
1091
1083
  });
1092
1084
 
1093
- type ThemeJson = z.infer<typeof themeJsonSchema>;
1085
+ type ThemeJson = typeof themeJsonSchema.infer;
1094
1086
 
1095
1087
  export type ThemeColor =
1096
1088
  | "accent"
@@ -1952,37 +1944,30 @@ async function loadThemeJson(name: string): Promise<ThemeJson> {
1952
1944
  } catch (error) {
1953
1945
  throw new Error(`Failed to parse theme ${name}: ${error}`);
1954
1946
  }
1955
- const parsed = themeJsonSchema.safeParse(json);
1956
- if (!parsed.success) {
1957
- const missingColors: string[] = [];
1958
- const otherErrors: string[] = [];
1959
-
1960
- for (const issue of parsed.error.issues) {
1961
- const parts = issue.path;
1962
- const colorKey = parts.length === 2 && parts[0] === "colors" && typeof parts[1] === "string" ? parts[1] : null;
1963
-
1964
- if (colorKey && issue.code === "invalid_type" && (issue as { received?: unknown }).received === undefined) {
1965
- missingColors.push(colorKey);
1966
- } else {
1967
- const pathStr = parts.length === 0 ? "/" : `/${parts.map(String).join("/")}`;
1968
- otherErrors.push(` - ${pathStr}: ${issue.message}`);
1969
- }
1947
+ let parsed: ThemeJson;
1948
+ try {
1949
+ parsed = themeJsonSchema(json) as ThemeJson;
1950
+ if (parsed instanceof type.errors) {
1951
+ throw new Error(parsed.summary);
1970
1952
  }
1953
+ } catch (error) {
1954
+ const errorMessage = error instanceof Error ? error.message : String(error);
1955
+ // Extract color key information if available
1956
+ const missingColorMatch = errorMessage.match(/missing keys: (.+)/i);
1957
+ const missingColors: string[] = missingColorMatch ? missingColorMatch[1].split(",").map(s => s.trim()) : [];
1971
1958
 
1972
- let errorMessage = `Invalid theme "${name}":\n`;
1959
+ let fullErrorMessage = `Invalid theme "${name}":\n`;
1973
1960
  if (missingColors.length > 0) {
1974
- errorMessage += `\nMissing required color tokens:\n`;
1975
- errorMessage += missingColors.map(c => ` - ${c}`).join("\n");
1976
- errorMessage += `\n\nPlease add these colors to your theme's "colors" object.`;
1977
- errorMessage += `\nSee the built-in themes (dark.json, light.json) for reference values.`;
1978
- }
1979
- if (otherErrors.length > 0) {
1980
- errorMessage += `\n\nOther errors:\n${otherErrors.join("\n")}`;
1961
+ fullErrorMessage += `\nMissing required color tokens:\n`;
1962
+ fullErrorMessage += missingColors.map(c => ` - ${c}`).join("\n");
1963
+ fullErrorMessage += `\n\nPlease add these colors to your theme's "colors" object.`;
1964
+ fullErrorMessage += `\nSee the built-in themes (dark.json, light.json) for reference values.`;
1981
1965
  }
1966
+ fullErrorMessage += `\n\nValidation error:\n - ${errorMessage}`;
1982
1967
 
1983
- throw new Error(errorMessage);
1968
+ throw new Error(fullErrorMessage);
1984
1969
  }
1985
- return parsed.data;
1970
+ return parsed;
1986
1971
  }
1987
1972
 
1988
1973
  interface CreateThemeOptions {
@@ -2302,8 +2287,13 @@ export function getColorBlindMode(): boolean {
2302
2287
  return currentColorBlindMode;
2303
2288
  }
2304
2289
 
2305
- export function onThemeChange(callback: () => void): void {
2290
+ export function onThemeChange(callback: () => void): () => void {
2306
2291
  onThemeChangeCallback = callback;
2292
+ return () => {
2293
+ if (onThemeChangeCallback === callback) {
2294
+ onThemeChangeCallback = undefined;
2295
+ }
2296
+ };
2307
2297
  }
2308
2298
 
2309
2299
  /**
@@ -339,6 +339,9 @@ export interface InteractiveModeContext {
339
339
  handleTanCommand(work: string): Promise<void>;
340
340
  hasActiveBtw(): boolean;
341
341
  handleBtwEscape(): boolean;
342
+ handleBtwBranchKey(): Promise<boolean>;
343
+ canBranchBtw(): boolean;
344
+ handleBtwBranch(question: string, assistantMessage: AssistantMessage): Promise<void>;
342
345
  handleOmfgCommand(complaint: string): Promise<void>;
343
346
  hasActiveOmfg(): boolean;
344
347
  handleOmfgEscape(): boolean;
@@ -1,8 +1,8 @@
1
+ import { countTokens } from "@oh-my-pi/pi-agent-core";
1
2
  import type { CompactionSettings } from "@oh-my-pi/pi-agent-core/compaction";
2
3
  import { effectiveReserveTokens, estimateTokens, resolveThresholdTokens } from "@oh-my-pi/pi-agent-core/compaction";
3
- import type { Model } from "@oh-my-pi/pi-ai";
4
- import { isZodSchema, zodToWireSchema } from "@oh-my-pi/pi-ai/utils/schema";
5
- import { countTokens } from "@oh-my-pi/pi-natives";
4
+ import type { Tool as AiTool, Model } from "@oh-my-pi/pi-ai";
5
+ import { toolWireSchema } from "@oh-my-pi/pi-ai/utils/schema";
6
6
  import { formatNumber } from "@oh-my-pi/pi-utils";
7
7
  import type { Skill } from "../../extensibility/skills";
8
8
  import type { AgentSession } from "../../session/agent-session";
@@ -61,8 +61,12 @@ export function estimateToolSchemaTokens(
61
61
  for (const tool of tools) {
62
62
  fragments.push(tool.name, tool.description);
63
63
  try {
64
- const params = tool.parameters;
65
- fragments.push(JSON.stringify((isZodSchema(params) ? zodToWireSchema(params) : params) ?? {}));
64
+ const wireTool: AiTool = {
65
+ name: tool.name,
66
+ description: tool.description,
67
+ parameters: tool.parameters as AiTool["parameters"],
68
+ };
69
+ fragments.push(JSON.stringify(toolWireSchema(wireTool) ?? {}));
66
70
  } catch {
67
71
  // Schema may contain functions or cycles; ignore.
68
72
  }
@@ -48,6 +48,7 @@ export function buildHotkeysMarkdown(bindings: HotkeysMarkdownBindings): string
48
48
  `| \`${appKey(bindings, "app.tools.expand")}\` | Toggle tool output expansion |`,
49
49
  `| \`${appKey(bindings, "app.thinking.toggle")}\` | Toggle thinking block visibility |`,
50
50
  `| \`${appKey(bindings, "app.editor.external")}\` | Edit message in external editor |`,
51
+ `| \`${appKey(bindings, "app.retry")}\` | Retry last failed assistant turn |`,
51
52
  `| \`${appKey(bindings, "app.clipboard.pasteImage")}\` | Paste image or text from clipboard |`,
52
53
  "| Hold `Space` | Speech-to-text (push-to-talk): hold to record, release to transcribe |",
53
54
  `| \`${appKey(bindings, "app.agents.hub")}\` / \`${appKey(bindings, "app.session.observe")}\` / double-tap \`←\` (empty editor) | Open the agent hub |`,
@@ -15,6 +15,7 @@ You are a helpful assistant the team trusts with load-bearing changes, operating
15
15
  - You are not alone in this repository. You SHOULD treat unexpected changes as the user's work and adapt.
16
16
  - In user-visible terminal prose and final chat, you MAY use LaTeX math delimiters (such as $ or $$) and LaTeX math commands (such as \text, \times) to format equations, as well as (`\textcolor`, `\colorbox`, `\fcolorbox`) to colorize the output.
17
17
  - To show the user a diagram (flowchart, sequence, state, ER, etc.), you MAY emit a fenced ` ```mermaid ` code block in your final chat — the terminal renders Mermaid source as an ASCII diagram. Keep it for genuine structure/flow; prefer prose for trivial points.
18
+ - When you need a visual separator between sections of prose / sections of code, you MUST use `─` (U+2500).
18
19
 
19
20
  TOOLS
20
21
  ===================================
package/src/sdk.ts CHANGED
@@ -528,6 +528,11 @@ export interface CreateAgentSessionOptions {
528
528
 
529
529
  /** Settings instance. Default: Settings.init({ cwd, agentDir }) */
530
530
  settings?: Settings;
531
+ /**
532
+ * Legacy alias for `settings`. Older Pi extensions pass SettingsManager.create(...)
533
+ * through this field; accept it so their SDK calls keep the configured settings.
534
+ */
535
+ settingsManager?: Settings | Promise<Settings>;
531
536
 
532
537
  /** Whether UI is available (enables interactive tools like ask). Default: false */
533
538
  hasUI?: boolean;
@@ -874,6 +879,10 @@ function isCustomTool(tool: CustomTool | ToolDefinition): tool is CustomTool {
874
879
  return !(tool as any).__isToolDefinition;
875
880
  }
876
881
 
882
+ function isLegacyBuiltinToolDefinition(tool: CustomTool | ToolDefinition): boolean {
883
+ return !isCustomTool(tool) && "__ompLegacyBuiltinTool" in tool && tool.__ompLegacyBuiltinTool === true;
884
+ }
885
+
877
886
  const TOOL_DEFINITION_MARKER = Symbol("__isToolDefinition");
878
887
 
879
888
  /** Matches the truncation applied to per-server instructions inside `rebuildSystemPrompt`. */
@@ -1138,7 +1147,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
1138
1147
  startupCredentialDisabledEvents.push(event);
1139
1148
  }
1140
1149
  });
1141
- const settings = options.settings ?? (await logger.time("settings", Settings.init, { cwd, agentDir }));
1150
+ const settings = await (options.settings ??
1151
+ options.settingsManager ??
1152
+ logger.time("settings", Settings.init, { cwd, agentDir }));
1142
1153
  logger.time("initializeWithSettings", initializeWithSettings, settings);
1143
1154
  if (!options.modelRegistry) {
1144
1155
  modelRegistry.refreshInBackground();
@@ -2008,12 +2019,13 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2008
2019
  const toolContextStore = new ToolContextStore(getSessionContext);
2009
2020
 
2010
2021
  const registeredTools = extensionRunner.getAllRegisteredTools();
2022
+ const sdkCustomTools = options.customTools?.filter(tool => !isLegacyBuiltinToolDefinition(tool)) ?? [];
2011
2023
  const allCustomTools = [
2012
2024
  ...registeredTools,
2013
- ...(options.customTools?.map(tool => {
2025
+ ...sdkCustomTools.map(tool => {
2014
2026
  const definition = isCustomTool(tool) ? customToolToDefinition(tool) : tool;
2015
2027
  return { definition, extensionPath: "<sdk>" };
2016
- }) ?? []),
2028
+ }),
2017
2029
  ];
2018
2030
  // `wrapToolWithMetaNotice` runs the centralized large-output → artifact spill.
2019
2031
  // Built-in tools get it in `createTools`; extension, SDK-custom, image-gen,
@@ -2291,7 +2303,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2291
2303
 
2292
2304
  // Custom tools and extension-registered tools are always included regardless of toolNames filter
2293
2305
  const alwaysInclude: string[] = [
2294
- ...(options.customTools?.map(t => (isCustomTool(t) ? t.name : t.name)) ?? []),
2306
+ ...sdkCustomTools.map(t => (isCustomTool(t) ? t.name : t.name)),
2295
2307
  ...registeredTools.filter(t => !t.definition.defaultInactive).map(t => t.definition.name),
2296
2308
  ];
2297
2309
  for (const name of alwaysInclude) {
@@ -2493,6 +2505,11 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2493
2505
  ...streamOptions,
2494
2506
  openrouterVariant: streamOptions?.openrouterVariant ?? openrouterVariant,
2495
2507
  antigravityEndpointMode: streamOptions?.antigravityEndpointMode ?? antigravityEndpointMode,
2508
+ loopGuard: {
2509
+ enabled: settings.get("model.loopGuard.enabled"),
2510
+ checkAssistantContent: settings.get("model.loopGuard.checkAssistantContent"),
2511
+ ...streamOptions?.loopGuard,
2512
+ },
2496
2513
  });
2497
2514
  },
2498
2515
  cursorExecHandlers,