@oh-my-pi/pi-coding-agent 0.1.0

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 (337) hide show
  1. package/CHANGELOG.md +1629 -0
  2. package/README.md +1041 -0
  3. package/docs/compaction.md +403 -0
  4. package/docs/config-usage.md +113 -0
  5. package/docs/custom-tools.md +541 -0
  6. package/docs/extension-loading.md +1004 -0
  7. package/docs/hooks.md +867 -0
  8. package/docs/rpc.md +1040 -0
  9. package/docs/sdk.md +994 -0
  10. package/docs/session-tree-plan.md +441 -0
  11. package/docs/session.md +240 -0
  12. package/docs/skills.md +290 -0
  13. package/docs/theme.md +670 -0
  14. package/docs/tree.md +197 -0
  15. package/docs/tui.md +341 -0
  16. package/examples/README.md +21 -0
  17. package/examples/custom-tools/README.md +124 -0
  18. package/examples/custom-tools/hello/index.ts +20 -0
  19. package/examples/custom-tools/question/index.ts +84 -0
  20. package/examples/custom-tools/subagent/README.md +172 -0
  21. package/examples/custom-tools/subagent/agents/planner.md +37 -0
  22. package/examples/custom-tools/subagent/agents/scout.md +50 -0
  23. package/examples/custom-tools/subagent/agents/worker.md +24 -0
  24. package/examples/custom-tools/subagent/agents.ts +156 -0
  25. package/examples/custom-tools/subagent/commands/implement-and-review.md +10 -0
  26. package/examples/custom-tools/subagent/commands/implement.md +10 -0
  27. package/examples/custom-tools/subagent/commands/scout-and-plan.md +9 -0
  28. package/examples/custom-tools/subagent/index.ts +1002 -0
  29. package/examples/custom-tools/todo/index.ts +212 -0
  30. package/examples/hooks/README.md +56 -0
  31. package/examples/hooks/auto-commit-on-exit.ts +49 -0
  32. package/examples/hooks/confirm-destructive.ts +59 -0
  33. package/examples/hooks/custom-compaction.ts +116 -0
  34. package/examples/hooks/dirty-repo-guard.ts +52 -0
  35. package/examples/hooks/file-trigger.ts +41 -0
  36. package/examples/hooks/git-checkpoint.ts +53 -0
  37. package/examples/hooks/handoff.ts +150 -0
  38. package/examples/hooks/permission-gate.ts +34 -0
  39. package/examples/hooks/protected-paths.ts +30 -0
  40. package/examples/hooks/qna.ts +119 -0
  41. package/examples/hooks/snake.ts +343 -0
  42. package/examples/hooks/status-line.ts +40 -0
  43. package/examples/sdk/01-minimal.ts +22 -0
  44. package/examples/sdk/02-custom-model.ts +49 -0
  45. package/examples/sdk/03-custom-prompt.ts +44 -0
  46. package/examples/sdk/04-skills.ts +44 -0
  47. package/examples/sdk/05-tools.ts +90 -0
  48. package/examples/sdk/06-hooks.ts +61 -0
  49. package/examples/sdk/07-context-files.ts +36 -0
  50. package/examples/sdk/08-slash-commands.ts +42 -0
  51. package/examples/sdk/09-api-keys-and-oauth.ts +55 -0
  52. package/examples/sdk/10-settings.ts +38 -0
  53. package/examples/sdk/11-sessions.ts +48 -0
  54. package/examples/sdk/12-full-control.ts +95 -0
  55. package/examples/sdk/README.md +154 -0
  56. package/package.json +89 -0
  57. package/src/bun-imports.d.ts +16 -0
  58. package/src/capability/context-file.ts +40 -0
  59. package/src/capability/extension.ts +48 -0
  60. package/src/capability/hook.ts +40 -0
  61. package/src/capability/index.ts +616 -0
  62. package/src/capability/instruction.ts +37 -0
  63. package/src/capability/mcp.ts +52 -0
  64. package/src/capability/prompt.ts +35 -0
  65. package/src/capability/rule.ts +56 -0
  66. package/src/capability/settings.ts +35 -0
  67. package/src/capability/skill.ts +49 -0
  68. package/src/capability/slash-command.ts +40 -0
  69. package/src/capability/system-prompt.ts +35 -0
  70. package/src/capability/tool.ts +38 -0
  71. package/src/capability/types.ts +166 -0
  72. package/src/cli/args.ts +259 -0
  73. package/src/cli/file-processor.ts +121 -0
  74. package/src/cli/list-models.ts +104 -0
  75. package/src/cli/plugin-cli.ts +661 -0
  76. package/src/cli/session-picker.ts +41 -0
  77. package/src/cli/update-cli.ts +274 -0
  78. package/src/cli.ts +10 -0
  79. package/src/config.ts +391 -0
  80. package/src/core/agent-session.ts +2178 -0
  81. package/src/core/auth-storage.ts +258 -0
  82. package/src/core/bash-executor.ts +197 -0
  83. package/src/core/compaction/branch-summarization.ts +315 -0
  84. package/src/core/compaction/compaction.ts +664 -0
  85. package/src/core/compaction/index.ts +7 -0
  86. package/src/core/compaction/utils.ts +153 -0
  87. package/src/core/custom-commands/bundled/review/index.ts +156 -0
  88. package/src/core/custom-commands/index.ts +15 -0
  89. package/src/core/custom-commands/loader.ts +226 -0
  90. package/src/core/custom-commands/types.ts +112 -0
  91. package/src/core/custom-tools/index.ts +22 -0
  92. package/src/core/custom-tools/loader.ts +248 -0
  93. package/src/core/custom-tools/types.ts +185 -0
  94. package/src/core/custom-tools/wrapper.ts +29 -0
  95. package/src/core/exec.ts +139 -0
  96. package/src/core/export-html/index.ts +159 -0
  97. package/src/core/export-html/template.css +774 -0
  98. package/src/core/export-html/template.generated.ts +2 -0
  99. package/src/core/export-html/template.html +45 -0
  100. package/src/core/export-html/template.js +1185 -0
  101. package/src/core/export-html/template.macro.ts +24 -0
  102. package/src/core/file-mentions.ts +54 -0
  103. package/src/core/hooks/index.ts +16 -0
  104. package/src/core/hooks/loader.ts +288 -0
  105. package/src/core/hooks/runner.ts +434 -0
  106. package/src/core/hooks/tool-wrapper.ts +98 -0
  107. package/src/core/hooks/types.ts +770 -0
  108. package/src/core/index.ts +53 -0
  109. package/src/core/logger.ts +112 -0
  110. package/src/core/mcp/client.ts +185 -0
  111. package/src/core/mcp/config.ts +248 -0
  112. package/src/core/mcp/index.ts +45 -0
  113. package/src/core/mcp/loader.ts +99 -0
  114. package/src/core/mcp/manager.ts +235 -0
  115. package/src/core/mcp/tool-bridge.ts +156 -0
  116. package/src/core/mcp/transports/http.ts +316 -0
  117. package/src/core/mcp/transports/index.ts +6 -0
  118. package/src/core/mcp/transports/stdio.ts +252 -0
  119. package/src/core/mcp/types.ts +228 -0
  120. package/src/core/messages.ts +211 -0
  121. package/src/core/model-registry.ts +334 -0
  122. package/src/core/model-resolver.ts +494 -0
  123. package/src/core/plugins/doctor.ts +67 -0
  124. package/src/core/plugins/index.ts +38 -0
  125. package/src/core/plugins/installer.ts +189 -0
  126. package/src/core/plugins/loader.ts +339 -0
  127. package/src/core/plugins/manager.ts +672 -0
  128. package/src/core/plugins/parser.ts +105 -0
  129. package/src/core/plugins/paths.ts +37 -0
  130. package/src/core/plugins/types.ts +190 -0
  131. package/src/core/sdk.ts +900 -0
  132. package/src/core/session-manager.ts +1837 -0
  133. package/src/core/settings-manager.ts +860 -0
  134. package/src/core/skills.ts +352 -0
  135. package/src/core/slash-commands.ts +132 -0
  136. package/src/core/system-prompt.ts +442 -0
  137. package/src/core/timings.ts +25 -0
  138. package/src/core/title-generator.ts +110 -0
  139. package/src/core/tools/ask.ts +193 -0
  140. package/src/core/tools/bash-interceptor.ts +120 -0
  141. package/src/core/tools/bash.ts +91 -0
  142. package/src/core/tools/context.ts +32 -0
  143. package/src/core/tools/edit-diff.ts +487 -0
  144. package/src/core/tools/edit.ts +140 -0
  145. package/src/core/tools/exa/company.ts +59 -0
  146. package/src/core/tools/exa/index.ts +63 -0
  147. package/src/core/tools/exa/linkedin.ts +59 -0
  148. package/src/core/tools/exa/mcp-client.ts +368 -0
  149. package/src/core/tools/exa/render.ts +200 -0
  150. package/src/core/tools/exa/researcher.ts +90 -0
  151. package/src/core/tools/exa/search.ts +338 -0
  152. package/src/core/tools/exa/types.ts +167 -0
  153. package/src/core/tools/exa/websets.ts +248 -0
  154. package/src/core/tools/find.ts +244 -0
  155. package/src/core/tools/grep.ts +584 -0
  156. package/src/core/tools/index.ts +283 -0
  157. package/src/core/tools/ls.ts +142 -0
  158. package/src/core/tools/lsp/client.ts +767 -0
  159. package/src/core/tools/lsp/clients/biome-client.ts +207 -0
  160. package/src/core/tools/lsp/clients/index.ts +49 -0
  161. package/src/core/tools/lsp/clients/lsp-linter-client.ts +98 -0
  162. package/src/core/tools/lsp/config.ts +845 -0
  163. package/src/core/tools/lsp/edits.ts +110 -0
  164. package/src/core/tools/lsp/index.ts +1364 -0
  165. package/src/core/tools/lsp/render.ts +560 -0
  166. package/src/core/tools/lsp/rust-analyzer.ts +145 -0
  167. package/src/core/tools/lsp/types.ts +495 -0
  168. package/src/core/tools/lsp/utils.ts +526 -0
  169. package/src/core/tools/notebook.ts +182 -0
  170. package/src/core/tools/output.ts +198 -0
  171. package/src/core/tools/path-utils.ts +61 -0
  172. package/src/core/tools/read.ts +507 -0
  173. package/src/core/tools/renderers.ts +820 -0
  174. package/src/core/tools/review.ts +275 -0
  175. package/src/core/tools/rulebook.ts +124 -0
  176. package/src/core/tools/task/agents.ts +158 -0
  177. package/src/core/tools/task/artifacts.ts +114 -0
  178. package/src/core/tools/task/commands.ts +157 -0
  179. package/src/core/tools/task/discovery.ts +217 -0
  180. package/src/core/tools/task/executor.ts +531 -0
  181. package/src/core/tools/task/index.ts +548 -0
  182. package/src/core/tools/task/model-resolver.ts +176 -0
  183. package/src/core/tools/task/parallel.ts +38 -0
  184. package/src/core/tools/task/render.ts +502 -0
  185. package/src/core/tools/task/subprocess-tool-registry.ts +89 -0
  186. package/src/core/tools/task/types.ts +142 -0
  187. package/src/core/tools/truncate.ts +265 -0
  188. package/src/core/tools/web-fetch.ts +2511 -0
  189. package/src/core/tools/web-search/auth.ts +199 -0
  190. package/src/core/tools/web-search/index.ts +583 -0
  191. package/src/core/tools/web-search/providers/anthropic.ts +198 -0
  192. package/src/core/tools/web-search/providers/exa.ts +196 -0
  193. package/src/core/tools/web-search/providers/perplexity.ts +195 -0
  194. package/src/core/tools/web-search/render.ts +372 -0
  195. package/src/core/tools/web-search/types.ts +180 -0
  196. package/src/core/tools/write.ts +63 -0
  197. package/src/core/ttsr.ts +211 -0
  198. package/src/core/utils.ts +187 -0
  199. package/src/discovery/agents-md.ts +75 -0
  200. package/src/discovery/builtin.ts +647 -0
  201. package/src/discovery/claude.ts +623 -0
  202. package/src/discovery/cline.ts +104 -0
  203. package/src/discovery/codex.ts +571 -0
  204. package/src/discovery/cursor.ts +266 -0
  205. package/src/discovery/gemini.ts +368 -0
  206. package/src/discovery/github.ts +120 -0
  207. package/src/discovery/helpers.test.ts +127 -0
  208. package/src/discovery/helpers.ts +249 -0
  209. package/src/discovery/index.ts +84 -0
  210. package/src/discovery/mcp-json.ts +127 -0
  211. package/src/discovery/vscode.ts +99 -0
  212. package/src/discovery/windsurf.ts +219 -0
  213. package/src/index.ts +192 -0
  214. package/src/main.ts +507 -0
  215. package/src/migrations.ts +156 -0
  216. package/src/modes/cleanup.ts +23 -0
  217. package/src/modes/index.ts +48 -0
  218. package/src/modes/interactive/components/armin.ts +382 -0
  219. package/src/modes/interactive/components/assistant-message.ts +86 -0
  220. package/src/modes/interactive/components/bash-execution.ts +199 -0
  221. package/src/modes/interactive/components/bordered-loader.ts +41 -0
  222. package/src/modes/interactive/components/branch-summary-message.ts +42 -0
  223. package/src/modes/interactive/components/compaction-summary-message.ts +45 -0
  224. package/src/modes/interactive/components/custom-editor.ts +122 -0
  225. package/src/modes/interactive/components/diff.ts +147 -0
  226. package/src/modes/interactive/components/dynamic-border.ts +25 -0
  227. package/src/modes/interactive/components/extensions/extension-dashboard.ts +296 -0
  228. package/src/modes/interactive/components/extensions/extension-list.ts +479 -0
  229. package/src/modes/interactive/components/extensions/index.ts +9 -0
  230. package/src/modes/interactive/components/extensions/inspector-panel.ts +313 -0
  231. package/src/modes/interactive/components/extensions/state-manager.ts +558 -0
  232. package/src/modes/interactive/components/extensions/types.ts +191 -0
  233. package/src/modes/interactive/components/hook-editor.ts +117 -0
  234. package/src/modes/interactive/components/hook-input.ts +64 -0
  235. package/src/modes/interactive/components/hook-message.ts +96 -0
  236. package/src/modes/interactive/components/hook-selector.ts +91 -0
  237. package/src/modes/interactive/components/model-selector.ts +560 -0
  238. package/src/modes/interactive/components/oauth-selector.ts +136 -0
  239. package/src/modes/interactive/components/plugin-settings.ts +481 -0
  240. package/src/modes/interactive/components/queue-mode-selector.ts +56 -0
  241. package/src/modes/interactive/components/session-selector.ts +220 -0
  242. package/src/modes/interactive/components/settings-defs.ts +597 -0
  243. package/src/modes/interactive/components/settings-selector.ts +545 -0
  244. package/src/modes/interactive/components/show-images-selector.ts +45 -0
  245. package/src/modes/interactive/components/status-line/index.ts +4 -0
  246. package/src/modes/interactive/components/status-line/presets.ts +94 -0
  247. package/src/modes/interactive/components/status-line/segments.ts +350 -0
  248. package/src/modes/interactive/components/status-line/separators.ts +55 -0
  249. package/src/modes/interactive/components/status-line/types.ts +81 -0
  250. package/src/modes/interactive/components/status-line-segment-editor.ts +357 -0
  251. package/src/modes/interactive/components/status-line.ts +384 -0
  252. package/src/modes/interactive/components/theme-selector.ts +62 -0
  253. package/src/modes/interactive/components/thinking-selector.ts +64 -0
  254. package/src/modes/interactive/components/tool-execution.ts +946 -0
  255. package/src/modes/interactive/components/tree-selector.ts +877 -0
  256. package/src/modes/interactive/components/ttsr-notification.ts +82 -0
  257. package/src/modes/interactive/components/user-message-selector.ts +159 -0
  258. package/src/modes/interactive/components/user-message.ts +18 -0
  259. package/src/modes/interactive/components/visual-truncate.ts +50 -0
  260. package/src/modes/interactive/components/welcome.ts +228 -0
  261. package/src/modes/interactive/interactive-mode.ts +2669 -0
  262. package/src/modes/interactive/theme/dark.json +102 -0
  263. package/src/modes/interactive/theme/defaults/dark-arctic.json +111 -0
  264. package/src/modes/interactive/theme/defaults/dark-catppuccin.json +106 -0
  265. package/src/modes/interactive/theme/defaults/dark-cyberpunk.json +109 -0
  266. package/src/modes/interactive/theme/defaults/dark-dracula.json +105 -0
  267. package/src/modes/interactive/theme/defaults/dark-forest.json +103 -0
  268. package/src/modes/interactive/theme/defaults/dark-github.json +112 -0
  269. package/src/modes/interactive/theme/defaults/dark-gruvbox.json +119 -0
  270. package/src/modes/interactive/theme/defaults/dark-monochrome.json +101 -0
  271. package/src/modes/interactive/theme/defaults/dark-monokai.json +105 -0
  272. package/src/modes/interactive/theme/defaults/dark-nord.json +104 -0
  273. package/src/modes/interactive/theme/defaults/dark-ocean.json +108 -0
  274. package/src/modes/interactive/theme/defaults/dark-one.json +107 -0
  275. package/src/modes/interactive/theme/defaults/dark-retro.json +99 -0
  276. package/src/modes/interactive/theme/defaults/dark-rose-pine.json +95 -0
  277. package/src/modes/interactive/theme/defaults/dark-solarized.json +96 -0
  278. package/src/modes/interactive/theme/defaults/dark-sunset.json +106 -0
  279. package/src/modes/interactive/theme/defaults/dark-synthwave.json +102 -0
  280. package/src/modes/interactive/theme/defaults/dark-tokyo-night.json +108 -0
  281. package/src/modes/interactive/theme/defaults/index.ts +67 -0
  282. package/src/modes/interactive/theme/defaults/light-arctic.json +106 -0
  283. package/src/modes/interactive/theme/defaults/light-catppuccin.json +105 -0
  284. package/src/modes/interactive/theme/defaults/light-cyberpunk.json +103 -0
  285. package/src/modes/interactive/theme/defaults/light-forest.json +107 -0
  286. package/src/modes/interactive/theme/defaults/light-github.json +114 -0
  287. package/src/modes/interactive/theme/defaults/light-gruvbox.json +115 -0
  288. package/src/modes/interactive/theme/defaults/light-monochrome.json +100 -0
  289. package/src/modes/interactive/theme/defaults/light-ocean.json +106 -0
  290. package/src/modes/interactive/theme/defaults/light-one.json +105 -0
  291. package/src/modes/interactive/theme/defaults/light-retro.json +105 -0
  292. package/src/modes/interactive/theme/defaults/light-solarized.json +101 -0
  293. package/src/modes/interactive/theme/defaults/light-sunset.json +106 -0
  294. package/src/modes/interactive/theme/defaults/light-synthwave.json +105 -0
  295. package/src/modes/interactive/theme/defaults/light-tokyo-night.json +118 -0
  296. package/src/modes/interactive/theme/light.json +99 -0
  297. package/src/modes/interactive/theme/theme-schema.json +424 -0
  298. package/src/modes/interactive/theme/theme.ts +2211 -0
  299. package/src/modes/print-mode.ts +163 -0
  300. package/src/modes/rpc/rpc-client.ts +527 -0
  301. package/src/modes/rpc/rpc-mode.ts +494 -0
  302. package/src/modes/rpc/rpc-types.ts +203 -0
  303. package/src/prompts/architect-plan.md +10 -0
  304. package/src/prompts/branch-summary-preamble.md +3 -0
  305. package/src/prompts/branch-summary.md +28 -0
  306. package/src/prompts/browser.md +71 -0
  307. package/src/prompts/compaction-summary.md +34 -0
  308. package/src/prompts/compaction-turn-prefix.md +16 -0
  309. package/src/prompts/compaction-update-summary.md +41 -0
  310. package/src/prompts/explore.md +82 -0
  311. package/src/prompts/implement-with-critic.md +11 -0
  312. package/src/prompts/implement.md +11 -0
  313. package/src/prompts/init.md +30 -0
  314. package/src/prompts/plan.md +54 -0
  315. package/src/prompts/reviewer.md +81 -0
  316. package/src/prompts/summarization-system.md +3 -0
  317. package/src/prompts/system-prompt.md +27 -0
  318. package/src/prompts/task.md +56 -0
  319. package/src/prompts/title-system.md +8 -0
  320. package/src/prompts/tools/ask.md +24 -0
  321. package/src/prompts/tools/bash.md +23 -0
  322. package/src/prompts/tools/edit.md +9 -0
  323. package/src/prompts/tools/find.md +6 -0
  324. package/src/prompts/tools/grep.md +12 -0
  325. package/src/prompts/tools/lsp.md +14 -0
  326. package/src/prompts/tools/output.md +23 -0
  327. package/src/prompts/tools/read.md +25 -0
  328. package/src/prompts/tools/web-fetch.md +8 -0
  329. package/src/prompts/tools/web-search.md +10 -0
  330. package/src/prompts/tools/write.md +10 -0
  331. package/src/utils/changelog.ts +99 -0
  332. package/src/utils/clipboard.ts +265 -0
  333. package/src/utils/fuzzy.ts +108 -0
  334. package/src/utils/mime.ts +30 -0
  335. package/src/utils/shell-snapshot.ts +218 -0
  336. package/src/utils/shell.ts +364 -0
  337. package/src/utils/tools-manager.ts +265 -0
@@ -0,0 +1,597 @@
1
+ /**
2
+ * Declarative settings definitions.
3
+ *
4
+ * Each setting is defined once here and the UI is generated automatically.
5
+ * To add a new setting:
6
+ * 1. Add it to SettingsManager (getter/setter)
7
+ * 2. Add the definition here
8
+ * 3. Add the handler in interactive-mode.ts settingsHandlers
9
+ */
10
+
11
+ import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
12
+ import { getCapabilities } from "@oh-my-pi/pi-tui";
13
+ import type {
14
+ SettingsManager,
15
+ StatusLinePreset,
16
+ StatusLineSeparatorStyle,
17
+ SymbolPreset,
18
+ } from "../../../core/settings-manager";
19
+ import { getPreset } from "./status-line/presets";
20
+
21
+ // Setting value types
22
+ export type SettingValue = boolean | string;
23
+
24
+ // Base definition for all settings
25
+ interface BaseSettingDef {
26
+ id: string;
27
+ label: string;
28
+ description: string;
29
+ tab: string;
30
+ }
31
+
32
+ // Boolean toggle setting
33
+ export interface BooleanSettingDef extends BaseSettingDef {
34
+ type: "boolean";
35
+ get: (sm: SettingsManager) => boolean;
36
+ set: (sm: SettingsManager, value: boolean) => void;
37
+ /** If provided, setting is only shown when this returns true */
38
+ condition?: () => boolean;
39
+ }
40
+
41
+ // Enum setting (inline toggle between values)
42
+ export interface EnumSettingDef extends BaseSettingDef {
43
+ type: "enum";
44
+ values: readonly string[];
45
+ get: (sm: SettingsManager) => string;
46
+ set: (sm: SettingsManager, value: string) => void;
47
+ }
48
+
49
+ // Submenu setting (opens a selection list)
50
+ export interface SubmenuSettingDef extends BaseSettingDef {
51
+ type: "submenu";
52
+ get: (sm: SettingsManager) => string;
53
+ set: (sm: SettingsManager, value: string) => void;
54
+ /** Get available options dynamically */
55
+ getOptions: (sm: SettingsManager) => Array<{ value: string; label: string; description?: string }>;
56
+ /** Called when selection changes (for preview) */
57
+ onPreview?: (value: string) => void;
58
+ /** Called when submenu is cancelled (to restore preview) */
59
+ onPreviewCancel?: (originalValue: string) => void;
60
+ }
61
+
62
+ export type SettingDef = BooleanSettingDef | EnumSettingDef | SubmenuSettingDef;
63
+
64
+ const THINKING_DESCRIPTIONS: Record<ThinkingLevel, string> = {
65
+ off: "No reasoning",
66
+ minimal: "Very brief reasoning (~1k tokens)",
67
+ low: "Light reasoning (~2k tokens)",
68
+ medium: "Moderate reasoning (~8k tokens)",
69
+ high: "Deep reasoning (~16k tokens)",
70
+ xhigh: "Maximum reasoning (~32k tokens)",
71
+ };
72
+
73
+ /**
74
+ * All settings definitions.
75
+ * Order determines display order within each tab.
76
+ */
77
+ export const SETTINGS_DEFS: SettingDef[] = [
78
+ // Config tab
79
+ {
80
+ id: "autoCompact",
81
+ tab: "config",
82
+ type: "boolean",
83
+ label: "Auto-compact",
84
+ description: "Automatically compact context when it gets too large",
85
+ get: (sm) => sm.getCompactionEnabled(),
86
+ set: (sm, v) => sm.setCompactionEnabled(v), // Also handled in session
87
+ },
88
+ {
89
+ id: "showImages",
90
+ tab: "config",
91
+ type: "boolean",
92
+ label: "Show images",
93
+ description: "Render images inline in terminal",
94
+ get: (sm) => sm.getShowImages(),
95
+ set: (sm, v) => sm.setShowImages(v),
96
+ condition: () => !!getCapabilities().images,
97
+ },
98
+ {
99
+ id: "queueMode",
100
+ tab: "config",
101
+ type: "enum",
102
+ label: "Queue mode",
103
+ description: "How to process queued messages while agent is working",
104
+ values: ["one-at-a-time", "all"],
105
+ get: (sm) => sm.getQueueMode(),
106
+ set: (sm, v) => sm.setQueueMode(v as "all" | "one-at-a-time"), // Also handled in session
107
+ },
108
+ {
109
+ id: "interruptMode",
110
+ tab: "config",
111
+ type: "enum",
112
+ label: "Interrupt mode",
113
+ description: "When to process queued messages: immediately (interrupt tools) or wait for turn to complete",
114
+ values: ["immediate", "wait"],
115
+ get: (sm) => sm.getInterruptMode(),
116
+ set: (sm, v) => sm.setInterruptMode(v as "immediate" | "wait"), // Also handled in session
117
+ },
118
+ {
119
+ id: "hideThinking",
120
+ tab: "config",
121
+ type: "boolean",
122
+ label: "Hide thinking",
123
+ description: "Hide thinking blocks in assistant responses",
124
+ get: (sm) => sm.getHideThinkingBlock(),
125
+ set: (sm, v) => sm.setHideThinkingBlock(v),
126
+ },
127
+ {
128
+ id: "collapseChangelog",
129
+ tab: "config",
130
+ type: "boolean",
131
+ label: "Collapse changelog",
132
+ description: "Show condensed changelog after updates",
133
+ get: (sm) => sm.getCollapseChangelog(),
134
+ set: (sm, v) => sm.setCollapseChangelog(v),
135
+ },
136
+ {
137
+ id: "bashInterceptor",
138
+ tab: "config",
139
+ type: "boolean",
140
+ label: "Bash interceptor",
141
+ description: "Block shell commands that have dedicated tools (grep, cat, etc.)",
142
+ get: (sm) => sm.getBashInterceptorEnabled(),
143
+ set: (sm, v) => sm.setBashInterceptorEnabled(v),
144
+ },
145
+ {
146
+ id: "mcpProjectConfig",
147
+ tab: "config",
148
+ type: "boolean",
149
+ label: "MCP project config",
150
+ description: "Load .mcp.json/mcp.json from project root",
151
+ get: (sm) => sm.getMCPProjectConfigEnabled(),
152
+ set: (sm, v) => sm.setMCPProjectConfigEnabled(v),
153
+ },
154
+ {
155
+ id: "editFuzzyMatch",
156
+ tab: "config",
157
+ type: "boolean",
158
+ label: "Edit fuzzy match",
159
+ description: "Accept high-confidence fuzzy matches for whitespace/indentation differences",
160
+ get: (sm) => sm.getEditFuzzyMatch(),
161
+ set: (sm, v) => sm.setEditFuzzyMatch(v),
162
+ },
163
+ {
164
+ id: "ttsrEnabled",
165
+ tab: "config",
166
+ type: "boolean",
167
+ label: "TTSR enabled",
168
+ description: "Time Traveling Stream Rules: interrupt agent when output matches rule patterns",
169
+ get: (sm) => sm.getTtsrEnabled(),
170
+ set: (sm, v) => sm.setTtsrEnabled(v),
171
+ },
172
+ {
173
+ id: "ttsrContextMode",
174
+ tab: "config",
175
+ type: "enum",
176
+ label: "TTSR context mode",
177
+ description: "What to do with partial output when TTSR triggers",
178
+ values: ["discard", "keep"],
179
+ get: (sm) => sm.getTtsrContextMode(),
180
+ set: (sm, v) => sm.setTtsrContextMode(v as "keep" | "discard"),
181
+ },
182
+ {
183
+ id: "ttsrRepeatMode",
184
+ tab: "config",
185
+ type: "enum",
186
+ label: "TTSR repeat mode",
187
+ description: "How rules can repeat: once per session or after a message gap",
188
+ values: ["once", "after-gap"],
189
+ get: (sm) => sm.getTtsrRepeatMode(),
190
+ set: (sm, v) => sm.setTtsrRepeatMode(v as "once" | "after-gap"),
191
+ },
192
+ {
193
+ id: "thinkingLevel",
194
+ tab: "config",
195
+ type: "submenu",
196
+ label: "Thinking level",
197
+ description: "Reasoning depth for thinking-capable models",
198
+ get: (sm) => sm.getDefaultThinkingLevel() ?? "off",
199
+ set: (sm, v) => sm.setDefaultThinkingLevel(v as ThinkingLevel), // Also handled in session
200
+ getOptions: () =>
201
+ (["off", "minimal", "low", "medium", "high", "xhigh"] as ThinkingLevel[]).map((level) => ({
202
+ value: level,
203
+ label: level,
204
+ description: THINKING_DESCRIPTIONS[level],
205
+ })),
206
+ },
207
+ {
208
+ id: "theme",
209
+ tab: "config",
210
+ type: "submenu",
211
+ label: "Theme",
212
+ description: "Color theme for the interface",
213
+ get: (sm) => sm.getTheme() ?? "dark",
214
+ set: (sm, v) => sm.setTheme(v),
215
+ getOptions: () => [], // Filled dynamically from context
216
+ },
217
+ {
218
+ id: "symbolPreset",
219
+ tab: "config",
220
+ type: "submenu",
221
+ label: "Symbol preset",
222
+ description: "Icon/symbol style (overrides theme default)",
223
+ get: (sm) => sm.getSymbolPreset() ?? "unicode",
224
+ set: (sm, v) => sm.setSymbolPreset(v as SymbolPreset),
225
+ getOptions: () => [
226
+ { value: "unicode", label: "Unicode", description: "Standard Unicode symbols (default)" },
227
+ { value: "nerd", label: "Nerd Font", description: "Nerd Font icons (requires Nerd Font)" },
228
+ { value: "ascii", label: "ASCII", description: "ASCII-only characters (maximum compatibility)" },
229
+ ],
230
+ },
231
+
232
+ // LSP tab
233
+ {
234
+ id: "lspFormatOnWrite",
235
+ tab: "lsp",
236
+ type: "boolean",
237
+ label: "Format on write",
238
+ description: "Automatically format code files using LSP after writing",
239
+ get: (sm) => sm.getLspFormatOnWrite(),
240
+ set: (sm, v) => sm.setLspFormatOnWrite(v),
241
+ },
242
+ {
243
+ id: "lspDiagnosticsOnWrite",
244
+ tab: "lsp",
245
+ type: "boolean",
246
+ label: "Diagnostics on write",
247
+ description: "Return LSP diagnostics (errors/warnings) after writing code files",
248
+ get: (sm) => sm.getLspDiagnosticsOnWrite(),
249
+ set: (sm, v) => sm.setLspDiagnosticsOnWrite(v),
250
+ },
251
+ {
252
+ id: "lspDiagnosticsOnEdit",
253
+ tab: "lsp",
254
+ type: "boolean",
255
+ label: "Diagnostics on edit",
256
+ description: "Return LSP diagnostics (errors/warnings) after editing code files",
257
+ get: (sm) => sm.getLspDiagnosticsOnEdit(),
258
+ set: (sm, v) => sm.setLspDiagnosticsOnEdit(v),
259
+ },
260
+
261
+ // Exa tab
262
+ {
263
+ id: "exaEnabled",
264
+ tab: "exa",
265
+ type: "boolean",
266
+ label: "Exa enabled",
267
+ description: "Master toggle for all Exa search tools",
268
+ get: (sm) => sm.getExaSettings().enabled,
269
+ set: (sm, v) => sm.setExaEnabled(v),
270
+ },
271
+ {
272
+ id: "exaSearch",
273
+ tab: "exa",
274
+ type: "boolean",
275
+ label: "Exa search",
276
+ description: "Basic search, deep search, code search, crawl",
277
+ get: (sm) => sm.getExaSettings().enableSearch,
278
+ set: (sm, v) => sm.setExaSearchEnabled(v),
279
+ },
280
+ {
281
+ id: "exaLinkedin",
282
+ tab: "exa",
283
+ type: "boolean",
284
+ label: "Exa LinkedIn",
285
+ description: "Search LinkedIn for people and companies",
286
+ get: (sm) => sm.getExaSettings().enableLinkedin,
287
+ set: (sm, v) => sm.setExaLinkedinEnabled(v),
288
+ },
289
+ {
290
+ id: "exaCompany",
291
+ tab: "exa",
292
+ type: "boolean",
293
+ label: "Exa company",
294
+ description: "Comprehensive company research tool",
295
+ get: (sm) => sm.getExaSettings().enableCompany,
296
+ set: (sm, v) => sm.setExaCompanyEnabled(v),
297
+ },
298
+ {
299
+ id: "exaResearcher",
300
+ tab: "exa",
301
+ type: "boolean",
302
+ label: "Exa researcher",
303
+ description: "AI-powered deep research tasks",
304
+ get: (sm) => sm.getExaSettings().enableResearcher,
305
+ set: (sm, v) => sm.setExaResearcherEnabled(v),
306
+ },
307
+ {
308
+ id: "exaWebsets",
309
+ tab: "exa",
310
+ type: "boolean",
311
+ label: "Exa websets",
312
+ description: "Webset management and enrichment tools",
313
+ get: (sm) => sm.getExaSettings().enableWebsets,
314
+ set: (sm, v) => sm.setExaWebsetsEnabled(v),
315
+ },
316
+
317
+ // Status Line tab
318
+ {
319
+ id: "statusLinePreset",
320
+ tab: "status",
321
+ type: "submenu",
322
+ label: "Preset",
323
+ description: "Pre-built status line configurations",
324
+ get: (sm) => sm.getStatusLinePreset(),
325
+ set: (sm, v) => sm.setStatusLinePreset(v as StatusLinePreset),
326
+ getOptions: () => [
327
+ { value: "default", label: "Default", description: "Model, path, git, context, tokens, cost" },
328
+ { value: "minimal", label: "Minimal", description: "Path and git only" },
329
+ { value: "compact", label: "Compact", description: "Model, git, cost, context" },
330
+ { value: "full", label: "Full", description: "All segments including time" },
331
+ { value: "nerd", label: "Nerd", description: "Maximum info with Nerd Font icons" },
332
+ { value: "ascii", label: "ASCII", description: "No special characters" },
333
+ { value: "custom", label: "Custom", description: "User-defined segments" },
334
+ ],
335
+ },
336
+ {
337
+ id: "statusLineSeparator",
338
+ tab: "status",
339
+ type: "submenu",
340
+ label: "Separator style",
341
+ description: "Style of separators between segments",
342
+ get: (sm) => {
343
+ const settings = sm.getStatusLineSettings();
344
+ if (settings.separator) return settings.separator;
345
+ return getPreset(sm.getStatusLinePreset()).separator;
346
+ },
347
+ set: (sm, v) => sm.setStatusLineSeparator(v as StatusLineSeparatorStyle),
348
+ getOptions: () => [
349
+ { value: "powerline", label: "Powerline", description: "Solid arrows (requires Nerd Font)" },
350
+ { value: "powerline-thin", label: "Thin chevron", description: "Thin arrows (requires Nerd Font)" },
351
+ { value: "slash", label: "Slash", description: "Forward slashes" },
352
+ { value: "pipe", label: "Pipe", description: "Vertical pipes" },
353
+ { value: "block", label: "Block", description: "Solid blocks" },
354
+ { value: "none", label: "None", description: "Space only" },
355
+ { value: "ascii", label: "ASCII", description: "Greater-than signs" },
356
+ ],
357
+ },
358
+ {
359
+ id: "statusLineShowHooks",
360
+ tab: "status",
361
+ type: "boolean",
362
+ label: "Show hook status",
363
+ description: "Display hook status messages below status line",
364
+ get: (sm) => sm.getStatusLineShowHookStatus(),
365
+ set: (sm, v) => sm.setStatusLineShowHookStatus(v),
366
+ },
367
+ {
368
+ id: "statusLineSegments",
369
+ tab: "status",
370
+ type: "submenu",
371
+ label: "Configure segments",
372
+ description: "Choose and arrange status line segments",
373
+ get: () => "configure...",
374
+ set: () => {}, // Handled specially
375
+ getOptions: () => [{ value: "open", label: "Open segment editor..." }],
376
+ },
377
+ {
378
+ id: "statusLineModelThinking",
379
+ tab: "status",
380
+ type: "enum",
381
+ label: "Model thinking level",
382
+ description: "Show thinking level in the model segment",
383
+ values: ["default", "on", "off"],
384
+ get: (sm) => {
385
+ const value = sm.getStatusLineSegmentOptions().model?.showThinkingLevel;
386
+ if (value === undefined) return "default";
387
+ return value ? "on" : "off";
388
+ },
389
+ set: (sm, v) => {
390
+ if (v === "default") {
391
+ sm.clearStatusLineSegmentOption("model", "showThinkingLevel");
392
+ } else {
393
+ sm.setStatusLineSegmentOption("model", "showThinkingLevel", v === "on");
394
+ }
395
+ },
396
+ },
397
+ {
398
+ id: "statusLinePathAbbreviate",
399
+ tab: "status",
400
+ type: "enum",
401
+ label: "Path abbreviate",
402
+ description: "Use ~ and strip home prefix in path segment",
403
+ values: ["default", "on", "off"],
404
+ get: (sm) => {
405
+ const value = sm.getStatusLineSegmentOptions().path?.abbreviate;
406
+ if (value === undefined) return "default";
407
+ return value ? "on" : "off";
408
+ },
409
+ set: (sm, v) => {
410
+ if (v === "default") {
411
+ sm.clearStatusLineSegmentOption("path", "abbreviate");
412
+ } else {
413
+ sm.setStatusLineSegmentOption("path", "abbreviate", v === "on");
414
+ }
415
+ },
416
+ },
417
+ {
418
+ id: "statusLinePathMaxLength",
419
+ tab: "status",
420
+ type: "submenu",
421
+ label: "Path max length",
422
+ description: "Maximum length for displayed path",
423
+ get: (sm) => {
424
+ const value = sm.getStatusLineSegmentOptions().path?.maxLength;
425
+ return typeof value === "number" ? String(value) : "default";
426
+ },
427
+ set: (sm, v) => {
428
+ if (v === "default") {
429
+ sm.clearStatusLineSegmentOption("path", "maxLength");
430
+ } else {
431
+ sm.setStatusLineSegmentOption("path", "maxLength", Number.parseInt(v, 10));
432
+ }
433
+ },
434
+ getOptions: () => [
435
+ { value: "default", label: "Preset default" },
436
+ { value: "20", label: "20" },
437
+ { value: "30", label: "30" },
438
+ { value: "40", label: "40" },
439
+ { value: "50", label: "50" },
440
+ { value: "60", label: "60" },
441
+ { value: "80", label: "80" },
442
+ ],
443
+ },
444
+ {
445
+ id: "statusLinePathStripWorkPrefix",
446
+ tab: "status",
447
+ type: "enum",
448
+ label: "Path strip /work",
449
+ description: "Strip /work prefix in path segment",
450
+ values: ["default", "on", "off"],
451
+ get: (sm) => {
452
+ const value = sm.getStatusLineSegmentOptions().path?.stripWorkPrefix;
453
+ if (value === undefined) return "default";
454
+ return value ? "on" : "off";
455
+ },
456
+ set: (sm, v) => {
457
+ if (v === "default") {
458
+ sm.clearStatusLineSegmentOption("path", "stripWorkPrefix");
459
+ } else {
460
+ sm.setStatusLineSegmentOption("path", "stripWorkPrefix", v === "on");
461
+ }
462
+ },
463
+ },
464
+ {
465
+ id: "statusLineGitShowBranch",
466
+ tab: "status",
467
+ type: "enum",
468
+ label: "Git show branch",
469
+ description: "Show branch name in git segment",
470
+ values: ["default", "on", "off"],
471
+ get: (sm) => {
472
+ const value = sm.getStatusLineSegmentOptions().git?.showBranch;
473
+ if (value === undefined) return "default";
474
+ return value ? "on" : "off";
475
+ },
476
+ set: (sm, v) => {
477
+ if (v === "default") {
478
+ sm.clearStatusLineSegmentOption("git", "showBranch");
479
+ } else {
480
+ sm.setStatusLineSegmentOption("git", "showBranch", v === "on");
481
+ }
482
+ },
483
+ },
484
+ {
485
+ id: "statusLineGitShowStaged",
486
+ tab: "status",
487
+ type: "enum",
488
+ label: "Git show staged",
489
+ description: "Show staged file count in git segment",
490
+ values: ["default", "on", "off"],
491
+ get: (sm) => {
492
+ const value = sm.getStatusLineSegmentOptions().git?.showStaged;
493
+ if (value === undefined) return "default";
494
+ return value ? "on" : "off";
495
+ },
496
+ set: (sm, v) => {
497
+ if (v === "default") {
498
+ sm.clearStatusLineSegmentOption("git", "showStaged");
499
+ } else {
500
+ sm.setStatusLineSegmentOption("git", "showStaged", v === "on");
501
+ }
502
+ },
503
+ },
504
+ {
505
+ id: "statusLineGitShowUnstaged",
506
+ tab: "status",
507
+ type: "enum",
508
+ label: "Git show unstaged",
509
+ description: "Show unstaged file count in git segment",
510
+ values: ["default", "on", "off"],
511
+ get: (sm) => {
512
+ const value = sm.getStatusLineSegmentOptions().git?.showUnstaged;
513
+ if (value === undefined) return "default";
514
+ return value ? "on" : "off";
515
+ },
516
+ set: (sm, v) => {
517
+ if (v === "default") {
518
+ sm.clearStatusLineSegmentOption("git", "showUnstaged");
519
+ } else {
520
+ sm.setStatusLineSegmentOption("git", "showUnstaged", v === "on");
521
+ }
522
+ },
523
+ },
524
+ {
525
+ id: "statusLineGitShowUntracked",
526
+ tab: "status",
527
+ type: "enum",
528
+ label: "Git show untracked",
529
+ description: "Show untracked file count in git segment",
530
+ values: ["default", "on", "off"],
531
+ get: (sm) => {
532
+ const value = sm.getStatusLineSegmentOptions().git?.showUntracked;
533
+ if (value === undefined) return "default";
534
+ return value ? "on" : "off";
535
+ },
536
+ set: (sm, v) => {
537
+ if (v === "default") {
538
+ sm.clearStatusLineSegmentOption("git", "showUntracked");
539
+ } else {
540
+ sm.setStatusLineSegmentOption("git", "showUntracked", v === "on");
541
+ }
542
+ },
543
+ },
544
+ {
545
+ id: "statusLineTimeFormat",
546
+ tab: "status",
547
+ type: "enum",
548
+ label: "Time format",
549
+ description: "Clock segment time format",
550
+ values: ["default", "12h", "24h"],
551
+ get: (sm) => sm.getStatusLineSegmentOptions().time?.format ?? "default",
552
+ set: (sm, v) => {
553
+ if (v === "default") {
554
+ sm.clearStatusLineSegmentOption("time", "format");
555
+ } else {
556
+ sm.setStatusLineSegmentOption("time", "format", v);
557
+ }
558
+ },
559
+ },
560
+ {
561
+ id: "statusLineTimeShowSeconds",
562
+ tab: "status",
563
+ type: "enum",
564
+ label: "Time show seconds",
565
+ description: "Include seconds in clock segment",
566
+ values: ["default", "on", "off"],
567
+ get: (sm) => {
568
+ const value = sm.getStatusLineSegmentOptions().time?.showSeconds;
569
+ if (value === undefined) return "default";
570
+ return value ? "on" : "off";
571
+ },
572
+ set: (sm, v) => {
573
+ if (v === "default") {
574
+ sm.clearStatusLineSegmentOption("time", "showSeconds");
575
+ } else {
576
+ sm.setStatusLineSegmentOption("time", "showSeconds", v === "on");
577
+ }
578
+ },
579
+ },
580
+ ];
581
+
582
+ /**
583
+ * All settings. Discovery settings have been moved to /extensions dashboard.
584
+ */
585
+ function getAllSettings(): SettingDef[] {
586
+ return SETTINGS_DEFS;
587
+ }
588
+
589
+ /** Get settings for a specific tab */
590
+ export function getSettingsForTab(tab: string): SettingDef[] {
591
+ return getAllSettings().filter((def) => def.tab === tab);
592
+ }
593
+
594
+ /** Get a setting definition by id */
595
+ export function getSettingDef(id: string): SettingDef | undefined {
596
+ return getAllSettings().find((def) => def.id === id);
597
+ }