praxis-agent 0.7.0 → 0.8.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 (301) hide show
  1. package/README.md +8 -0
  2. package/dist/application/background-agent-manager.d.ts +5 -0
  3. package/dist/application/background-agent-manager.js +21 -0
  4. package/dist/application/background-bash-manager.d.ts +14 -0
  5. package/dist/application/background-bash-manager.js +42 -4
  6. package/dist/application/background-task-runtime.d.ts +34 -0
  7. package/dist/application/background-task-runtime.js +59 -0
  8. package/dist/application/session-service.d.ts +21 -1
  9. package/dist/application/session-service.js +188 -17
  10. package/dist/application/session-worktree.d.ts +1 -0
  11. package/dist/application/session-worktree.js +13 -2
  12. package/dist/application/subagent-service.d.ts +3 -0
  13. package/dist/application/subagent-service.js +6 -0
  14. package/dist/application/workflow-manager.d.ts +70 -2
  15. package/dist/application/workflow-manager.js +21 -4
  16. package/dist/cli/agents-dashboard.d.ts +9 -0
  17. package/dist/cli/agents-dashboard.js +16 -5
  18. package/dist/cli/interactive.d.ts +41 -3
  19. package/dist/cli/interactive.js +1281 -183
  20. package/dist/cli/tui/claude-style.d.ts +31 -3
  21. package/dist/cli/tui/claude-style.js +165 -54
  22. package/dist/cli/tui/config-dashboard.d.ts +63 -0
  23. package/dist/cli/tui/config-dashboard.js +150 -0
  24. package/dist/cli/tui/config-settings.d.ts +32 -0
  25. package/dist/cli/tui/config-settings.js +276 -0
  26. package/dist/cli/tui/custom-themes.d.ts +21 -0
  27. package/dist/cli/tui/custom-themes.js +284 -0
  28. package/dist/cli/tui/file-picker.d.ts +3 -1
  29. package/dist/cli/tui/file-picker.js +8 -2
  30. package/dist/cli/tui/keybindings.js +0 -1
  31. package/dist/cli/tui/mcp-panel-controller.d.ts +32 -0
  32. package/dist/cli/tui/mcp-panel-controller.js +80 -0
  33. package/dist/cli/tui/mcp-panel-projector.d.ts +79 -0
  34. package/dist/cli/tui/mcp-panel-projector.js +181 -0
  35. package/dist/cli/tui/mcp-panel.d.ts +8 -0
  36. package/dist/cli/tui/mcp-panel.js +99 -0
  37. package/dist/cli/tui/recently-denied.d.ts +15 -0
  38. package/dist/cli/tui/recently-denied.js +19 -0
  39. package/dist/cli/tui/runtime-interactions.d.ts +17 -0
  40. package/dist/cli/tui/runtime-interactions.js +100 -0
  41. package/dist/cli/tui/runtime-settings.d.ts +40 -0
  42. package/dist/cli/tui/runtime-settings.js +84 -0
  43. package/dist/cli/tui/slash-commands.js +10 -0
  44. package/dist/cli/tui/task-panel.d.ts +53 -0
  45. package/dist/cli/tui/task-panel.js +204 -0
  46. package/dist/cli/tui/terminal-notifications.d.ts +10 -0
  47. package/dist/cli/tui/terminal-notifications.js +48 -0
  48. package/dist/cli/tui/terminal-setup.d.ts +24 -0
  49. package/dist/cli/tui/terminal-setup.js +618 -0
  50. package/dist/cli/tui/theme-settings.d.ts +8 -0
  51. package/dist/cli/tui/theme-settings.js +132 -0
  52. package/dist/cli/tui/theme.d.ts +53 -0
  53. package/dist/cli/tui/theme.js +265 -0
  54. package/dist/cli.d.ts +9 -0
  55. package/dist/cli.js +97 -17
  56. package/dist/compatibility/claude/schema.js +2 -0
  57. package/dist/core/runtime.d.ts +12 -0
  58. package/dist/core/runtime.js +24 -0
  59. package/dist/maintenance/self-update.js +1 -1
  60. package/dist/mcp/claude-mcp-management.d.ts +6 -1
  61. package/dist/mcp/claude-mcp-management.js +191 -44
  62. package/dist/mcp/claude-mcp-oauth.js +2 -0
  63. package/dist/mcp/claude-mcp-tools.d.ts +31 -3
  64. package/dist/mcp/claude-mcp-tools.js +116 -34
  65. package/dist/permissions/claude-permission-resolver.d.ts +3 -0
  66. package/dist/permissions/claude-permission-resolver.js +42 -20
  67. package/dist/platform/claude-version.js +2 -1
  68. package/dist/plugins/claude-plugin-runtime.js +11 -3
  69. package/dist/tools/claude-interactive-tools.d.ts +7 -0
  70. package/dist/tools/claude-interactive-tools.js +21 -8
  71. package/dist/tools/claude-task-tools.d.ts +4 -0
  72. package/dist/tools/claude-task-tools.js +7 -0
  73. package/package.json +2 -1
  74. package/dist/application/background-agent-manager.d.ts.map +0 -1
  75. package/dist/application/background-agent-manager.js.map +0 -1
  76. package/dist/application/background-bash-manager.d.ts.map +0 -1
  77. package/dist/application/background-bash-manager.js.map +0 -1
  78. package/dist/application/background-task-id.d.ts.map +0 -1
  79. package/dist/application/background-task-id.js.map +0 -1
  80. package/dist/application/claude-project-purge.d.ts.map +0 -1
  81. package/dist/application/claude-project-purge.js.map +0 -1
  82. package/dist/application/managed-worktree.d.ts.map +0 -1
  83. package/dist/application/managed-worktree.js.map +0 -1
  84. package/dist/application/model-compactor.d.ts.map +0 -1
  85. package/dist/application/model-compactor.js.map +0 -1
  86. package/dist/application/scheduled-prompt-manager.d.ts.map +0 -1
  87. package/dist/application/scheduled-prompt-manager.js.map +0 -1
  88. package/dist/application/session-service.d.ts.map +0 -1
  89. package/dist/application/session-service.js.map +0 -1
  90. package/dist/application/session-worktree.d.ts.map +0 -1
  91. package/dist/application/session-worktree.js.map +0 -1
  92. package/dist/application/subagent-service.d.ts.map +0 -1
  93. package/dist/application/subagent-service.js.map +0 -1
  94. package/dist/application/tool-use-summary.d.ts.map +0 -1
  95. package/dist/application/tool-use-summary.js.map +0 -1
  96. package/dist/application/top-level-agent-manager.d.ts.map +0 -1
  97. package/dist/application/top-level-agent-manager.js.map +0 -1
  98. package/dist/application/workflow-manager.d.ts.map +0 -1
  99. package/dist/application/workflow-manager.js.map +0 -1
  100. package/dist/application/workflow-meta.d.ts.map +0 -1
  101. package/dist/application/workflow-meta.js.map +0 -1
  102. package/dist/application/workflow-runtime.d.ts.map +0 -1
  103. package/dist/application/workflow-runtime.js.map +0 -1
  104. package/dist/application/workflow-worktree.d.ts.map +0 -1
  105. package/dist/application/workflow-worktree.js.map +0 -1
  106. package/dist/cli/agents-dashboard.d.ts.map +0 -1
  107. package/dist/cli/agents-dashboard.js.map +0 -1
  108. package/dist/cli/controls.d.ts.map +0 -1
  109. package/dist/cli/controls.js.map +0 -1
  110. package/dist/cli/debug.d.ts.map +0 -1
  111. package/dist/cli/debug.js.map +0 -1
  112. package/dist/cli/interactive.d.ts.map +0 -1
  113. package/dist/cli/interactive.js.map +0 -1
  114. package/dist/cli/protocol.d.ts.map +0 -1
  115. package/dist/cli/protocol.js.map +0 -1
  116. package/dist/cli/tui/claude-style.d.ts.map +0 -1
  117. package/dist/cli/tui/claude-style.js.map +0 -1
  118. package/dist/cli/tui/clipboard.d.ts.map +0 -1
  119. package/dist/cli/tui/clipboard.js.map +0 -1
  120. package/dist/cli/tui/composer-editor.d.ts.map +0 -1
  121. package/dist/cli/tui/composer-editor.js.map +0 -1
  122. package/dist/cli/tui/composer-images.d.ts.map +0 -1
  123. package/dist/cli/tui/composer-images.js.map +0 -1
  124. package/dist/cli/tui/conversation-export.d.ts.map +0 -1
  125. package/dist/cli/tui/conversation-export.js.map +0 -1
  126. package/dist/cli/tui/external-editor.d.ts.map +0 -1
  127. package/dist/cli/tui/external-editor.js.map +0 -1
  128. package/dist/cli/tui/file-picker.d.ts.map +0 -1
  129. package/dist/cli/tui/file-picker.js.map +0 -1
  130. package/dist/cli/tui/git-diff.d.ts.map +0 -1
  131. package/dist/cli/tui/git-diff.js.map +0 -1
  132. package/dist/cli/tui/hook-settings.d.ts.map +0 -1
  133. package/dist/cli/tui/hook-settings.js.map +0 -1
  134. package/dist/cli/tui/keybindings.d.ts.map +0 -1
  135. package/dist/cli/tui/keybindings.js.map +0 -1
  136. package/dist/cli/tui/memory-files.d.ts.map +0 -1
  137. package/dist/cli/tui/memory-files.js.map +0 -1
  138. package/dist/cli/tui/permission-settings.d.ts.map +0 -1
  139. package/dist/cli/tui/permission-settings.js.map +0 -1
  140. package/dist/cli/tui/slash-commands.d.ts.map +0 -1
  141. package/dist/cli/tui/slash-commands.js.map +0 -1
  142. package/dist/cli/tui/terminal-suspend.d.ts.map +0 -1
  143. package/dist/cli/tui/terminal-suspend.js.map +0 -1
  144. package/dist/cli/tui/workspace-directories.d.ts.map +0 -1
  145. package/dist/cli/tui/workspace-directories.js.map +0 -1
  146. package/dist/cli.d.ts.map +0 -1
  147. package/dist/cli.js.map +0 -1
  148. package/dist/compatibility/claude/compaction.d.ts.map +0 -1
  149. package/dist/compatibility/claude/compaction.js.map +0 -1
  150. package/dist/compatibility/claude/context.d.ts.map +0 -1
  151. package/dist/compatibility/claude/context.js.map +0 -1
  152. package/dist/compatibility/claude/dynamic-context.d.ts.map +0 -1
  153. package/dist/compatibility/claude/dynamic-context.js.map +0 -1
  154. package/dist/compatibility/claude/file-history.d.ts.map +0 -1
  155. package/dist/compatibility/claude/file-history.js.map +0 -1
  156. package/dist/compatibility/claude/file-resources.d.ts.map +0 -1
  157. package/dist/compatibility/claude/file-resources.js.map +0 -1
  158. package/dist/compatibility/claude/fork.d.ts.map +0 -1
  159. package/dist/compatibility/claude/fork.js.map +0 -1
  160. package/dist/compatibility/claude/history.d.ts.map +0 -1
  161. package/dist/compatibility/claude/history.js.map +0 -1
  162. package/dist/compatibility/claude/ownership.d.ts.map +0 -1
  163. package/dist/compatibility/claude/ownership.js.map +0 -1
  164. package/dist/compatibility/claude/paths.d.ts.map +0 -1
  165. package/dist/compatibility/claude/paths.js.map +0 -1
  166. package/dist/compatibility/claude/pr-links.d.ts.map +0 -1
  167. package/dist/compatibility/claude/pr-links.js.map +0 -1
  168. package/dist/compatibility/claude/projection.d.ts.map +0 -1
  169. package/dist/compatibility/claude/projection.js.map +0 -1
  170. package/dist/compatibility/claude/schema.d.ts.map +0 -1
  171. package/dist/compatibility/claude/schema.js.map +0 -1
  172. package/dist/compatibility/claude/shared-resources.d.ts.map +0 -1
  173. package/dist/compatibility/claude/shared-resources.js.map +0 -1
  174. package/dist/compatibility/claude/sidechain.d.ts.map +0 -1
  175. package/dist/compatibility/claude/sidechain.js.map +0 -1
  176. package/dist/compatibility/claude/tool-links.d.ts.map +0 -1
  177. package/dist/compatibility/claude/tool-links.js.map +0 -1
  178. package/dist/compatibility/claude/translation.d.ts.map +0 -1
  179. package/dist/compatibility/claude/translation.js.map +0 -1
  180. package/dist/compatibility/claude/workflow-replay.d.ts.map +0 -1
  181. package/dist/compatibility/claude/workflow-replay.js.map +0 -1
  182. package/dist/compatibility/claude/workflow.d.ts.map +0 -1
  183. package/dist/compatibility/claude/workflow.js.map +0 -1
  184. package/dist/core/compaction.d.ts.map +0 -1
  185. package/dist/core/compaction.js.map +0 -1
  186. package/dist/core/context-budget.d.ts.map +0 -1
  187. package/dist/core/context-budget.js.map +0 -1
  188. package/dist/core/context.d.ts.map +0 -1
  189. package/dist/core/context.js.map +0 -1
  190. package/dist/core/runtime.d.ts.map +0 -1
  191. package/dist/core/runtime.js.map +0 -1
  192. package/dist/core/usage.d.ts.map +0 -1
  193. package/dist/core/usage.js.map +0 -1
  194. package/dist/extensions/claude-extension-tools.d.ts.map +0 -1
  195. package/dist/extensions/claude-extension-tools.js.map +0 -1
  196. package/dist/extensions/claude-extensions.d.ts.map +0 -1
  197. package/dist/extensions/claude-extensions.js.map +0 -1
  198. package/dist/hooks/claude-hook-tools.d.ts.map +0 -1
  199. package/dist/hooks/claude-hook-tools.js.map +0 -1
  200. package/dist/hooks/claude-hooks.d.ts.map +0 -1
  201. package/dist/hooks/claude-hooks.js.map +0 -1
  202. package/dist/maintenance/doctor.d.ts.map +0 -1
  203. package/dist/maintenance/doctor.js.map +0 -1
  204. package/dist/maintenance/self-update.d.ts.map +0 -1
  205. package/dist/maintenance/self-update.js.map +0 -1
  206. package/dist/mcp/claude-mcp-management.d.ts.map +0 -1
  207. package/dist/mcp/claude-mcp-management.js.map +0 -1
  208. package/dist/mcp/claude-mcp-oauth.d.ts.map +0 -1
  209. package/dist/mcp/claude-mcp-oauth.js.map +0 -1
  210. package/dist/mcp/claude-mcp-tools.d.ts.map +0 -1
  211. package/dist/mcp/claude-mcp-tools.js.map +0 -1
  212. package/dist/mcp/praxis-mcp-server.d.ts.map +0 -1
  213. package/dist/mcp/praxis-mcp-server.js.map +0 -1
  214. package/dist/permissions/claude-auto-classifier.d.ts.map +0 -1
  215. package/dist/permissions/claude-auto-classifier.js.map +0 -1
  216. package/dist/permissions/claude-permission-resolver.d.ts.map +0 -1
  217. package/dist/permissions/claude-permission-resolver.js.map +0 -1
  218. package/dist/persistence/claude-job-store.d.ts.map +0 -1
  219. package/dist/persistence/claude-job-store.js.map +0 -1
  220. package/dist/persistence/claude-scheduled-task-store.d.ts.map +0 -1
  221. package/dist/persistence/claude-scheduled-task-store.js.map +0 -1
  222. package/dist/persistence/claude-sidechain-store.d.ts.map +0 -1
  223. package/dist/persistence/claude-sidechain-store.js.map +0 -1
  224. package/dist/persistence/claude-task-store.d.ts.map +0 -1
  225. package/dist/persistence/claude-task-store.js.map +0 -1
  226. package/dist/persistence/claude-transcript-store.d.ts.map +0 -1
  227. package/dist/persistence/claude-transcript-store.js.map +0 -1
  228. package/dist/persistence/claude-workflow-store.d.ts.map +0 -1
  229. package/dist/persistence/claude-workflow-store.js.map +0 -1
  230. package/dist/persistence/in-memory-sidechain-store.d.ts.map +0 -1
  231. package/dist/persistence/in-memory-sidechain-store.js.map +0 -1
  232. package/dist/persistence/in-memory-transcript-store.d.ts.map +0 -1
  233. package/dist/persistence/in-memory-transcript-store.js.map +0 -1
  234. package/dist/platform/atomic-write.d.ts.map +0 -1
  235. package/dist/platform/atomic-write.js.map +0 -1
  236. package/dist/platform/bounded-process-runner.d.ts.map +0 -1
  237. package/dist/platform/bounded-process-runner.js.map +0 -1
  238. package/dist/platform/claude-version.d.ts.map +0 -1
  239. package/dist/platform/claude-version.js.map +0 -1
  240. package/dist/platform/command-shell.d.ts.map +0 -1
  241. package/dist/platform/command-shell.js.map +0 -1
  242. package/dist/platform/exclusive-file-lease.d.ts.map +0 -1
  243. package/dist/platform/exclusive-file-lease.js.map +0 -1
  244. package/dist/platform/sensitive-data.d.ts.map +0 -1
  245. package/dist/platform/sensitive-data.js.map +0 -1
  246. package/dist/platform/tmux-worktree.d.ts.map +0 -1
  247. package/dist/platform/tmux-worktree.js.map +0 -1
  248. package/dist/plugins/claude-plugin-eval-discovery.d.ts.map +0 -1
  249. package/dist/plugins/claude-plugin-eval-discovery.js.map +0 -1
  250. package/dist/plugins/claude-plugin-eval-graders.d.ts.map +0 -1
  251. package/dist/plugins/claude-plugin-eval-graders.js.map +0 -1
  252. package/dist/plugins/claude-plugin-eval-runner.d.ts.map +0 -1
  253. package/dist/plugins/claude-plugin-eval-runner.js.map +0 -1
  254. package/dist/plugins/claude-plugin-eval-schema.d.ts.map +0 -1
  255. package/dist/plugins/claude-plugin-eval-schema.js.map +0 -1
  256. package/dist/plugins/claude-plugin-eval.d.ts.map +0 -1
  257. package/dist/plugins/claude-plugin-eval.js.map +0 -1
  258. package/dist/plugins/claude-plugin-maintenance.d.ts.map +0 -1
  259. package/dist/plugins/claude-plugin-maintenance.js.map +0 -1
  260. package/dist/plugins/claude-plugin-marketplace.d.ts.map +0 -1
  261. package/dist/plugins/claude-plugin-marketplace.js.map +0 -1
  262. package/dist/plugins/claude-plugin-mcpb.d.ts.map +0 -1
  263. package/dist/plugins/claude-plugin-mcpb.js.map +0 -1
  264. package/dist/plugins/claude-plugin-runtime.d.ts.map +0 -1
  265. package/dist/plugins/claude-plugin-runtime.js.map +0 -1
  266. package/dist/providers/anthropic-compatible.d.ts.map +0 -1
  267. package/dist/providers/anthropic-compatible.js.map +0 -1
  268. package/dist/providers/environment.d.ts.map +0 -1
  269. package/dist/providers/environment.js.map +0 -1
  270. package/dist/providers/fallback-provider.d.ts.map +0 -1
  271. package/dist/providers/fallback-provider.js.map +0 -1
  272. package/dist/providers/openai-compatible.d.ts.map +0 -1
  273. package/dist/providers/openai-compatible.js.map +0 -1
  274. package/dist/tools/claude-interactive-tools.d.ts.map +0 -1
  275. package/dist/tools/claude-interactive-tools.js.map +0 -1
  276. package/dist/tools/claude-lsp-formatters.d.ts.map +0 -1
  277. package/dist/tools/claude-lsp-formatters.js.map +0 -1
  278. package/dist/tools/claude-lsp-tool.d.ts.map +0 -1
  279. package/dist/tools/claude-lsp-tool.js.map +0 -1
  280. package/dist/tools/claude-scheduled-tools.d.ts.map +0 -1
  281. package/dist/tools/claude-scheduled-tools.js.map +0 -1
  282. package/dist/tools/claude-task-tools.d.ts.map +0 -1
  283. package/dist/tools/claude-task-tools.js.map +0 -1
  284. package/dist/tools/claude-user-message.d.ts.map +0 -1
  285. package/dist/tools/claude-user-message.js.map +0 -1
  286. package/dist/tools/claude-workflow-tools.d.ts.map +0 -1
  287. package/dist/tools/claude-workflow-tools.js.map +0 -1
  288. package/dist/tools/claude-worktree-tools.d.ts.map +0 -1
  289. package/dist/tools/claude-worktree-tools.js.map +0 -1
  290. package/dist/tools/filtered-tool-registry.d.ts.map +0 -1
  291. package/dist/tools/filtered-tool-registry.js.map +0 -1
  292. package/dist/tools/glob.d.ts.map +0 -1
  293. package/dist/tools/glob.js.map +0 -1
  294. package/dist/tools/local-tools.d.ts.map +0 -1
  295. package/dist/tools/local-tools.js.map +0 -1
  296. package/dist/tools/notebook.d.ts.map +0 -1
  297. package/dist/tools/notebook.js.map +0 -1
  298. package/dist/tools/pdf.d.ts.map +0 -1
  299. package/dist/tools/pdf.js.map +0 -1
  300. package/dist/tools/web.d.ts.map +0 -1
  301. package/dist/tools/web.js.map +0 -1
@@ -4,7 +4,10 @@ import { type TuiDiffSnapshot } from './git-diff.js';
4
4
  import { type TuiHookConfiguration } from './hook-settings.js';
5
5
  import type { TuiMemoryFileEntry } from './memory-files.js';
6
6
  import type { TuiPermissionRule } from './permission-settings.js';
7
+ import type { RecentlyDeniedAction } from './recently-denied.js';
8
+ import type { CustomThemeToken, TuiCustomTheme } from './custom-themes.js';
7
9
  import type { TuiSlashCommand } from './slash-commands.js';
10
+ import { type TuiTheme } from './theme.js';
8
11
  export interface TuiDisplayMetadata {
9
12
  version: string;
10
13
  cwd: string;
@@ -88,12 +91,13 @@ export declare function DiffDashboard({ snapshots, sourceIndex, selectedIndex, v
88
91
  width: number;
89
92
  screenReader: boolean;
90
93
  }): import("react").JSX.Element;
91
- export declare function PermissionDashboard({ tabIndex, selectedIndex, query, rules, recentDenied, workspaceDirectories, width, screenReader, }: {
94
+ export declare function PermissionDashboard({ tabIndex, selectedIndex, query, rules, recentDenied, retryingDeniedId, workspaceDirectories, width, screenReader, }: {
92
95
  tabIndex: number;
93
96
  selectedIndex: number;
94
97
  query: string;
95
98
  rules: readonly TuiPermissionRule[];
96
- recentDenied: readonly string[];
99
+ recentDenied: readonly RecentlyDeniedAction[];
100
+ retryingDeniedId?: string | null;
97
101
  workspaceDirectories: readonly {
98
102
  path: string;
99
103
  original: boolean;
@@ -101,6 +105,25 @@ export declare function PermissionDashboard({ tabIndex, selectedIndex, query, ru
101
105
  width: number;
102
106
  screenReader: boolean;
103
107
  }): import("react").JSX.Element;
108
+ export declare function ThemePicker({ currentTheme, selectedIndex, syntaxHighlightingDisabled, customThemes, allowCustomThemes, width, screenReader, }: {
109
+ currentTheme: TuiTheme | `custom:${string}`;
110
+ selectedIndex: number;
111
+ syntaxHighlightingDisabled: boolean;
112
+ customThemes?: readonly TuiCustomTheme[];
113
+ allowCustomThemes?: boolean;
114
+ width: number;
115
+ screenReader: boolean;
116
+ }): import("react").JSX.Element;
117
+ export declare function CustomThemeEditor({ theme, token, value, tokens, selectedIndex, query, width, screenReader, }: {
118
+ theme: TuiCustomTheme;
119
+ token?: CustomThemeToken;
120
+ value: string;
121
+ tokens?: readonly CustomThemeToken[];
122
+ selectedIndex?: number;
123
+ query?: string;
124
+ width: number;
125
+ screenReader: boolean;
126
+ }): import("react").JSX.Element;
104
127
  export declare function StatusDashboard({ tabIndex, version, sessionId, display, usage, costUsd, turnCount, toolCount, commandCount, detailedTranscript, width, screenReader, }: {
105
128
  tabIndex: number;
106
129
  version: string;
@@ -209,7 +232,7 @@ export declare function SelectionMenu({ title, description, options, selectedInd
209
232
  export declare function ExternalEditorWait({ screenReader, }: {
210
233
  screenReader: boolean;
211
234
  }): import("react").JSX.Element;
212
- export declare function Composer({ input, cursor, busy, clipboardBusy, status, display, usage, costUsd, width, screenReader, hasThinking, thinkingExpanded, shortcutsVisible, shellMode, footerMessage, }: {
235
+ export declare function Composer({ input, cursor, busy, clipboardBusy, status, display, usage, costUsd, width, screenReader, hasThinking, thinkingExpanded, shortcutsVisible, shellMode, footerMessage, reduceMotion, progressBar, turnDuration, editorMode, prStatus, }: {
213
236
  input: string;
214
237
  cursor?: number;
215
238
  busy: boolean;
@@ -228,6 +251,11 @@ export declare function Composer({ input, cursor, busy, clipboardBusy, status, d
228
251
  text: string;
229
252
  isError: boolean;
230
253
  };
254
+ reduceMotion?: boolean;
255
+ progressBar?: boolean;
256
+ turnDuration?: string;
257
+ editorMode?: 'normal' | 'vim';
258
+ prStatus?: string;
231
259
  }): import("react").JSX.Element;
232
260
  export declare function DialogFrame({ title, children, screenReader, }: {
233
261
  title: string;
@@ -4,8 +4,7 @@ import { Box, Text, useStdout } from 'ink';
4
4
  import { composerEditorSegments } from './composer-editor.js';
5
5
  import { visiblePatchLines } from './git-diff.js';
6
6
  import { TUI_HOOK_MENU } from './hook-settings.js';
7
- const BRAND = '#D97757';
8
- const ACCENT = '#B8A1FF';
7
+ import { tuiPalette, tuiSyntaxStyle, useTuiPalette, } from './theme.js';
9
8
  const SPINNER = ['✳', '✢', '✣', '✤', '✥'];
10
9
  export function useTerminalWidth(override) {
11
10
  const { stdout } = useStdout();
@@ -45,31 +44,39 @@ function permissionLabel(mode) {
45
44
  return 'permissions default';
46
45
  }
47
46
  }
47
+ function selectionPrefix(selected, screenReader) {
48
+ if (selected)
49
+ return screenReader ? 'Selected: ' : '❯ ';
50
+ return screenReader ? '' : ' ';
51
+ }
48
52
  export function WelcomePanel({ display, width, }) {
53
+ const palette = useTuiPalette();
49
54
  const panelWidth = Math.min(100, Math.max(32, width));
50
55
  const wide = panelWidth >= 68;
51
- return (_jsxs(Box, { borderStyle: "round", borderColor: "gray", flexDirection: "column", width: panelWidth, paddingX: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: BRAND, bold: true, children: "Praxis" }), _jsxs(Text, { children: [" Code v", display.version, " "] }), _jsx(Text, { dimColor: true, children: '─'.repeat(Math.max(1, panelWidth - 24)) })] }), _jsxs(Box, { flexDirection: wide ? 'row' : 'column', marginTop: 1, children: [_jsxs(Box, { alignItems: wide ? 'center' : undefined, flexDirection: "column", width: wide ? '50%' : '100%', children: [_jsx(Text, { bold: true, children: "Welcome back!" }), _jsx(Text, { color: BRAND, bold: true, children: "\u2590\u259B\u2588\u2588\u2588\u259C\u258C" }), _jsx(Text, { color: BRAND, children: "\u259D\u259C\u2588\u2588\u2588\u2588\u2588\u259B\u2598" }), _jsx(Text, { color: BRAND, children: " \u2598\u2598 \u259D\u259D" }), _jsxs(Text, { children: [display.model ?? 'provider default', display.effort ? (_jsxs(Text, { dimColor: true, children: [" \u00B7 ", display.effort, " effort"] })) : null] }), _jsx(Text, { dimColor: true, children: compactPath(display.cwd) })] }), _jsxs(Box, { flexDirection: "column", width: wide ? '50%' : '100%', marginTop: wide ? 0 : 1, children: [_jsx(Text, { bold: true, children: "Tips for getting started" }), _jsx(Text, { children: "Run /help for commands" }), _jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }), _jsx(Text, { bold: true, children: "Shared with Claude Code" }), _jsx(Text, { children: "Sessions, memory, skills" })] })] })] }));
56
+ return (_jsxs(Box, { borderStyle: "round", borderColor: palette.muted, flexDirection: "column", width: panelWidth, paddingX: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: palette.brand, bold: true, children: "Praxis" }), _jsxs(Text, { children: [" Code v", display.version, " "] }), _jsx(Text, { dimColor: true, children: '─'.repeat(Math.max(1, panelWidth - 24)) })] }), _jsxs(Box, { flexDirection: wide ? 'row' : 'column', marginTop: 1, children: [_jsxs(Box, { alignItems: wide ? 'center' : undefined, flexDirection: "column", width: wide ? '50%' : '100%', children: [_jsx(Text, { bold: true, children: "Welcome back!" }), _jsx(Text, { color: palette.brand, bold: true, children: "\u2590\u259B\u2588\u2588\u2588\u259C\u258C" }), _jsx(Text, { color: palette.brand, children: "\u259D\u259C\u2588\u2588\u2588\u2588\u2588\u259B\u2598" }), _jsx(Text, { color: palette.brand, children: " \u2598\u2598 \u259D\u259D" }), _jsxs(Text, { children: [display.model ?? 'provider default', display.effort ? (_jsxs(Text, { dimColor: true, children: [" \u00B7 ", display.effort, " effort"] })) : null] }), _jsx(Text, { dimColor: true, children: compactPath(display.cwd) })] }), _jsxs(Box, { flexDirection: "column", width: wide ? '50%' : '100%', marginTop: wide ? 0 : 1, children: [_jsx(Text, { bold: true, children: "Tips for getting started" }), _jsx(Text, { children: "Run /help for commands" }), _jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }), _jsx(Text, { bold: true, children: "Shared with Claude Code" }), _jsx(Text, { children: "Sessions, memory, skills" })] })] })] }));
52
57
  }
53
58
  function InlineText({ text }) {
59
+ const palette = useTuiPalette();
54
60
  const tokens = text.split(/(`[^`]+`|\*\*[^*]+\*\*|\[[^\]]+\]\([^)]+\))/u);
55
61
  return (_jsx(Text, { children: tokens.map((token, index) => {
56
62
  if (token.startsWith('`') && token.endsWith('`'))
57
- return (_jsx(Text, { color: "cyan", children: token.slice(1, -1) }, index));
63
+ return (_jsx(Text, { color: palette.info, children: token.slice(1, -1) }, index));
58
64
  if (token.startsWith('**') && token.endsWith('**'))
59
65
  return (_jsx(Text, { bold: true, children: token.slice(2, -2) }, index));
60
66
  const link = /^\[([^\]]+)\]\(([^)]+)\)$/u.exec(token);
61
67
  if (link)
62
- return (_jsx(Text, { color: "blue", underline: true, children: link[1] }, index));
68
+ return (_jsx(Text, { color: palette.link, underline: true, children: link[1] }, index));
63
69
  return token;
64
70
  }) }));
65
71
  }
66
72
  function MarkdownLine({ line }) {
73
+ const palette = useTuiPalette();
67
74
  if (line.startsWith('### '))
68
75
  return (_jsx(Text, { bold: true, children: _jsx(InlineText, { text: line.slice(4) }) }));
69
76
  if (line.startsWith('## '))
70
- return (_jsx(Text, { bold: true, color: ACCENT, children: _jsx(InlineText, { text: line.slice(3) }) }));
77
+ return (_jsx(Text, { bold: true, color: palette.accent, children: _jsx(InlineText, { text: line.slice(3) }) }));
71
78
  if (line.startsWith('# '))
72
- return (_jsx(Text, { bold: true, color: BRAND, children: _jsx(InlineText, { text: line.slice(2) }) }));
79
+ return (_jsx(Text, { bold: true, color: palette.brand, children: _jsx(InlineText, { text: line.slice(2) }) }));
73
80
  if (/^[-*] /u.test(line))
74
81
  return (_jsxs(Text, { children: [' • ', _jsx(InlineText, { text: line.slice(2) })] }));
75
82
  if (/^\d+\. /u.test(line))
@@ -78,14 +85,51 @@ function MarkdownLine({ line }) {
78
85
  return (_jsxs(Text, { dimColor: true, children: ['│ ', _jsx(InlineText, { text: line.slice(2) })] }));
79
86
  return line ? _jsx(InlineText, { text: line }) : _jsx(Text, { children: " " });
80
87
  }
81
- function ToolResultText({ text }) {
82
- return (_jsx(Box, { flexDirection: "column", children: text.split('\n').map((line, index) => (_jsx(Text, { ...(line.startsWith('+') && !line.startsWith('+++')
83
- ? { color: 'green' }
84
- : line.startsWith('-') && !line.startsWith('---')
85
- ? { color: 'red' }
86
- : line.startsWith('@@')
87
- ? { color: 'cyan' }
88
- : { dimColor: true }), children: line || ' ' }, index))) }));
88
+ const CODE_KEYWORDS = new Set([
89
+ 'async',
90
+ 'await',
91
+ 'class',
92
+ 'const',
93
+ 'else',
94
+ 'export',
95
+ 'false',
96
+ 'from',
97
+ 'function',
98
+ 'if',
99
+ 'import',
100
+ 'let',
101
+ 'new',
102
+ 'null',
103
+ 'return',
104
+ 'true',
105
+ 'undefined',
106
+ 'var',
107
+ ]);
108
+ const CODE_TOKEN_PATTERN = /("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\b(?:async|await|class|const|else|export|false|from|function|if|import|let|new|null|return|true|undefined|var)\b|\b[A-Za-z_$][\w$]*(?=\s*\())/gu;
109
+ function SyntaxCodeLine({ text, prefix = '', change, }) {
110
+ const palette = useTuiPalette();
111
+ if (palette.syntaxHighlightingDisabled) {
112
+ return (_jsxs(Text, { children: [prefix, text || ' '] }));
113
+ }
114
+ const lineStyle = tuiSyntaxStyle(palette, 'text', change);
115
+ return (_jsxs(Text, { children: [prefix, _jsx(Text, { ...lineStyle, children: text.split(CODE_TOKEN_PATTERN).map((token, index) => {
116
+ const kind = token.startsWith('"') || token.startsWith("'")
117
+ ? 'string'
118
+ : CODE_KEYWORDS.has(token)
119
+ ? 'keyword'
120
+ : /^[A-Za-z_$][\w$]*$/u.test(token)
121
+ ? 'identifier'
122
+ : 'text';
123
+ if (kind === 'text')
124
+ return token;
125
+ return (_jsx(Text, { ...tuiSyntaxStyle(palette, kind), children: token }, index));
126
+ }) })] }));
127
+ }
128
+ function ToolResultText({ text, prefix = '', }) {
129
+ const palette = useTuiPalette();
130
+ return (_jsx(Box, { flexDirection: "column", children: text.split('\n').map((line, index) => line.startsWith('+') && !line.startsWith('+++') ? (_jsx(SyntaxCodeLine, { prefix: index === 0 ? prefix : prefix ? ' ' : '', text: line, change: "added" }, index)) : line.startsWith('-') && !line.startsWith('---') ? (_jsx(SyntaxCodeLine, { prefix: index === 0 ? prefix : prefix ? ' ' : '', text: line, change: "removed" }, index)) : (_jsxs(Text, { ...(line.startsWith('@@')
131
+ ? { color: palette.info }
132
+ : { dimColor: true }), children: [index === 0 ? prefix : prefix ? ' ' : '', line || ' '] }, index))) }));
89
133
  }
90
134
  function inputString(call, key) {
91
135
  const value = call.input[key];
@@ -107,6 +151,7 @@ function toolHeading(call) {
107
151
  return call.name;
108
152
  }
109
153
  function ToolTranscriptEntry({ call, detail, result, detailed, }) {
154
+ const palette = useTuiPalette();
110
155
  const displayResult = call.name === 'Read' &&
111
156
  result?.text.startsWith('Wasted call — file unchanged since your last Read')
112
157
  ? 'Unchanged since last read'
@@ -117,17 +162,20 @@ function ToolTranscriptEntry({ call, detail, result, detailed, }) {
117
162
  }
118
163
  const visible = detailed ? resultLines : resultLines.slice(0, 3);
119
164
  const hidden = resultLines.length - visible.length;
165
+ const resultIsDiff = resultLines.some((line) => line.startsWith('+') && !line.startsWith('+++')) &&
166
+ resultLines.some((line) => line.startsWith('-') && !line.startsWith('---'));
120
167
  const errorText = displayResult.length > 500
121
168
  ? `${displayResult.slice(0, 497)}...`
122
169
  : displayResult;
123
170
  const oldLines = contentLines(inputString(call, 'old_string'));
124
171
  const newLines = contentLines(inputString(call, 'new_string'));
125
- return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { children: [_jsx(Text, { color: ACCENT, children: "\u23FA" }), " ", _jsx(Text, { bold: true, children: toolHeading(call) })] }), !['Bash', 'Read', 'Edit'].includes(call.name) && detail ? (_jsxs(Text, { dimColor: true, children: [" ", detail] })) : null, result ? (_jsx(Box, { marginLeft: 2, flexDirection: "column", children: result.isError ? (_jsxs(Text, { color: "red", children: ["\u23BF Error: ", errorText] })) : call.name === 'Edit' ? (_jsxs(_Fragment, { children: [_jsxs(Text, { dimColor: true, children: ["\u23BF Added ", newLines.length, " line", newLines.length === 1 ? '' : 's', ", removed ", oldLines.length, " line", oldLines.length === 1 ? '' : 's'] }), oldLines.map((line, index) => (_jsxs(Text, { color: "red", children: [' ', index + 1, " -", line] }, `old-${index}`))), newLines.map((line, index) => (_jsxs(Text, { color: "green", children: [' ', index + 1, " +", line] }, `new-${index}`)))] })) : (_jsxs(_Fragment, { children: [visible.map((line, index) => (_jsxs(Text, { dimColor: true, children: [index === 0 ? '⎿ ' : ' ', line || ' '] }, index))), hidden > 0 ? (_jsxs(Text, { dimColor: true, children: [' ', "\u2026 +", hidden, " lines (ctrl+o to expand)"] })) : null] })) })) : null] }));
172
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { children: [_jsx(Text, { color: palette.accent, children: "\u23FA" }), ' ', _jsx(Text, { bold: true, children: toolHeading(call) })] }), !['Bash', 'Read', 'Edit'].includes(call.name) && detail ? (_jsxs(Text, { dimColor: true, children: [" ", detail] })) : null, result ? (_jsx(Box, { marginLeft: 2, flexDirection: "column", children: result.isError ? (_jsxs(Text, { color: palette.error, children: ["\u23BF Error: ", errorText] })) : call.name === 'Edit' ? (_jsxs(_Fragment, { children: [_jsxs(Text, { dimColor: true, children: ["\u23BF Added ", newLines.length, " line", newLines.length === 1 ? '' : 's', ", removed ", oldLines.length, " line", oldLines.length === 1 ? '' : 's'] }), oldLines.map((line, index) => (_jsx(SyntaxCodeLine, { prefix: ` ${index + 1} -`, text: line, change: "removed" }, `old-${index}`))), newLines.map((line, index) => (_jsx(SyntaxCodeLine, { prefix: ` ${index + 1} +`, text: line, change: "added" }, `new-${index}`)))] })) : resultIsDiff ? (_jsx(ToolResultText, { text: visible.join('\n'), prefix: "\u23BF " })) : (_jsxs(_Fragment, { children: [visible.map((line, index) => (_jsxs(Text, { dimColor: true, children: [index === 0 ? '⎿ ' : ' ', line || ' '] }, index))), hidden > 0 ? (_jsxs(Text, { dimColor: true, children: [' ', "\u2026 +", hidden, " lines (ctrl+o to expand)"] })) : null] })) })) : null] }));
126
173
  }
127
174
  function ThinkingBlock({ text, active, expanded, screenReader, }) {
175
+ const palette = useTuiPalette();
128
176
  const summary = text.replace(/\s+/gu, ' ').trim();
129
177
  const showFull = screenReader || active || expanded;
130
- return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { ...(!screenReader ? { color: ACCENT } : {}), dimColor: !screenReader, italic: !screenReader, children: [screenReader ? 'Thinking:' : '✻ ', active ? 'Thinking…' : 'Thought for a moment', !showFull && summary ? ` · ${summary.slice(0, 160)}` : ''] }), showFull && text ? (_jsx(Box, { marginLeft: screenReader ? 0 : 2, flexDirection: "column", children: _jsx(MarkdownText, { text: text }) })) : !screenReader && summary.length > 160 ? (_jsx(Text, { dimColor: true, children: " ctrl+o to expand thinking" })) : null] }));
178
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { ...(!screenReader ? { color: palette.accent } : {}), dimColor: !screenReader, italic: !screenReader, children: [screenReader ? 'Thinking:' : '✻ ', active ? 'Thinking…' : 'Thought for a moment', !showFull && summary ? ` · ${summary.slice(0, 160)}` : ''] }), showFull && text ? (_jsx(Box, { marginLeft: screenReader ? 0 : 2, flexDirection: "column", children: _jsx(MarkdownText, { text: text }) })) : !screenReader && summary.length > 160 ? (_jsx(Text, { dimColor: true, children: " ctrl+o to expand thinking" })) : null] }));
131
179
  }
132
180
  function ContextUsageBlock({ usedTokens, contextWindowTokens, skills, screenReader, }) {
133
181
  const totalTokens = Math.max(1, contextWindowTokens);
@@ -151,10 +199,11 @@ export function MarkdownText({ text }) {
151
199
  code = !code;
152
200
  return (_jsx(Text, { dimColor: true, children: code ? `╭─ ${line.slice(3) || 'code'}` : '╰─' }, index));
153
201
  }
154
- return code ? (_jsxs(Text, { color: "cyan", children: ["\u2502 ", line] }, index)) : (_jsx(MarkdownLine, { line: line }, index));
202
+ return code ? (_jsx(SyntaxCodeLine, { prefix: "\u2502 ", text: line }, index)) : (_jsx(MarkdownLine, { line: line }, index));
155
203
  }) }));
156
204
  }
157
205
  export function Transcript({ items, activeText, activeThinking = '', thinkingExpanded = false, detailedTranscript = false, screenReader, }) {
206
+ const palette = useTuiPalette();
158
207
  const detailed = thinkingExpanded || detailedTranscript;
159
208
  const results = new Map(items
160
209
  .filter((item) => item.kind === 'tool-result')
@@ -213,16 +262,16 @@ export function Transcript({ items, activeText, activeThinking = '', thinkingExp
213
262
  if (groupedReadTools.has(index))
214
263
  return null;
215
264
  if (item.kind === 'user') {
216
- return (_jsxs(Box, { marginTop: index === 0 ? 0 : 1, children: [_jsx(Text, { color: BRAND, bold: true, children: screenReader ? 'You: ' : '❯ ' }), _jsx(Text, { bold: true, children: item.text })] }, index));
265
+ return (_jsxs(Box, { marginTop: index === 0 ? 0 : 1, children: [_jsx(Text, { color: palette.brand, bold: true, children: screenReader ? 'You: ' : '❯ ' }), _jsx(Text, { bold: true, children: item.text })] }, index));
217
266
  }
218
267
  if (item.kind === 'assistant') {
219
- return (_jsxs(Box, { marginTop: 1, children: [screenReader ? _jsx(Text, { children: "Praxis:" }) : null, !screenReader ? _jsx(Text, { color: ACCENT, children: "\u23FA " }) : null, _jsx(MarkdownText, { text: item.text })] }, index));
268
+ return (_jsxs(Box, { marginTop: 1, children: [screenReader ? _jsx(Text, { children: "Praxis:" }) : null, !screenReader ? _jsx(Text, { color: palette.accent, children: "\u23FA " }) : null, _jsx(MarkdownText, { text: item.text })] }, index));
220
269
  }
221
270
  if (item.kind === 'thinking') {
222
271
  return (_jsx(ThinkingBlock, { text: item.text, active: false, expanded: detailed, screenReader: screenReader }, index));
223
272
  }
224
273
  if (item.kind === 'compact') {
225
- return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: ACCENT, italic: true, children: screenReader
274
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: palette.accent, italic: true, children: screenReader
226
275
  ? 'Conversation compacted'
227
276
  : '✻ Conversation compacted (ctrl+o for history)' }), detailed ? (_jsx(Box, { marginLeft: screenReader ? 0 : 2, children: _jsx(MarkdownText, { text: item.summary }) })) : null] }, index));
228
277
  }
@@ -237,7 +286,7 @@ export function Transcript({ items, activeText, activeThinking = '', thinkingExp
237
286
  if (pairedResults.has(item.callId))
238
287
  return null;
239
288
  const text = item.text.length > 500 ? `${item.text.slice(0, 497)}...` : item.text;
240
- return (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsx(Text, { color: item.isError ? 'red' : 'gray', children: item.isError ? '└ Error' : '└ Result' }), item.isError ? (_jsx(Text, { color: "red", children: text })) : (_jsx(ToolResultText, { text: text }))] }, index));
289
+ return (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsx(Text, { color: item.isError ? palette.error : palette.muted, children: item.isError ? '└ Error' : '└ Result' }), item.isError ? (_jsx(Text, { color: palette.error, children: text })) : (_jsx(ToolResultText, { text: text }))] }, index));
241
290
  }
242
291
  if (item.kind === 'shell') {
243
292
  const result = shellResults.get(item.callId);
@@ -253,21 +302,22 @@ export function Transcript({ items, activeText, activeThinking = '', thinkingExp
253
302
  const lines = contentLines(output);
254
303
  const visible = detailed || screenReader ? lines : lines.slice(0, 3);
255
304
  const hidden = lines.length - visible.length;
256
- return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { children: _jsxs(Text, { bold: true, children: [screenReader ? 'Shell command: ' : '! ', item.command] }) }), result ? (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [lines.length === 0 ? (_jsx(Text, { dimColor: true, children: "\u23BF " })) : (visible.map((line, lineIndex) => (_jsxs(Text, { ...(result.isError ? { color: 'red' } : {}), dimColor: !result.isError, children: [lineIndex === 0 ? '⎿ ' : ' ', line || ' '] }, lineIndex)))), hidden > 0 ? (_jsxs(Text, { dimColor: true, children: [' ', "\u2026 +", hidden, " lines (ctrl+o to expand)"] })) : null] })) : null] }, index));
305
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { children: _jsxs(Text, { bold: true, children: [screenReader ? 'Shell command: ' : '! ', item.command] }) }), result ? (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [lines.length === 0 ? (_jsx(Text, { dimColor: true, children: "\u23BF " })) : (visible.map((line, lineIndex) => (_jsxs(Text, { ...(result.isError ? { color: palette.error } : {}), dimColor: !result.isError, children: [lineIndex === 0 ? '⎿ ' : ' ', line || ' '] }, lineIndex)))), hidden > 0 ? (_jsxs(Text, { dimColor: true, children: [' ', "\u2026 +", hidden, " lines (ctrl+o to expand)"] })) : null] })) : null] }, index));
257
306
  }
258
307
  if (item.kind === 'shell-result') {
259
308
  if (pairedShellResults.has(item.callId))
260
309
  return null;
261
310
  const output = [item.stdout, item.stderr].filter(Boolean).join('\n');
262
- return (_jsxs(Text, { ...(item.isError ? { color: 'red' } : {}), children: ["\u23BF ", output] }, index));
311
+ return (_jsxs(Text, { ...(item.isError ? { color: palette.error } : {}), children: ["\u23BF ", output] }, index));
263
312
  }
264
313
  if (item.kind === 'local-result') {
265
314
  return (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { dimColor: true, children: ["\u23BF ", item.text] }) }, index));
266
315
  }
267
- return (_jsxs(Text, { ...(item.kind === 'warning' ? { color: 'red' } : {}), dimColor: item.kind === 'notice', children: [item.kind === 'warning' ? '⚠ ' : '· ', item.text] }, index));
268
- }), activeThinking ? (_jsx(ThinkingBlock, { text: activeThinking, active: true, expanded: detailed, screenReader: screenReader })) : activeText ? (_jsxs(Box, { marginTop: 1, children: [screenReader ? (_jsx(Text, { children: "Praxis: " })) : (_jsx(Text, { color: ACCENT, children: "\u2733 " })), _jsx(MarkdownText, { text: activeText })] })) : null] }));
316
+ return (_jsxs(Text, { ...(item.kind === 'warning' ? { color: palette.error } : {}), dimColor: item.kind === 'notice', children: [item.kind === 'warning' ? '⚠ ' : '· ', item.text] }, index));
317
+ }), activeThinking ? (_jsx(ThinkingBlock, { text: activeThinking, active: true, expanded: detailed, screenReader: screenReader })) : activeText ? (_jsxs(Box, { marginTop: 1, children: [screenReader ? (_jsx(Text, { children: "Praxis: " })) : (_jsx(Text, { color: palette.accent, children: "\u2733 " })), _jsx(MarkdownText, { text: activeText })] })) : null] }));
269
318
  }
270
319
  export function DiffDashboard({ snapshots, sourceIndex, selectedIndex, viewingFile, scrollOffset, width, screenReader, }) {
320
+ const palette = useTuiPalette();
271
321
  const source = snapshots[sourceIndex];
272
322
  const snapshot = source?.snapshot ?? { files: [], additions: 0, deletions: 0 };
273
323
  const selected = snapshot.files[selectedIndex];
@@ -275,15 +325,11 @@ export function DiffDashboard({ snapshots, sourceIndex, selectedIndex, viewingFi
275
325
  const line = '─'.repeat(panelWidth);
276
326
  if (viewingFile && selected) {
277
327
  const lines = visiblePatchLines(selected.patch).slice(scrollOffset, scrollOffset + 18);
278
- return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsx(Text, { bold: true, children: " Uncommitted changes (git diff HEAD)" }), _jsxs(Text, { children: [' ', snapshots.map((item, index) => (_jsxs(Text, { inverse: index === sourceIndex, children: [' ', item.label, ' '] }, item.label)))] }), _jsx(Text, { children: " " }), _jsxs(Text, { bold: true, children: [" ", selected.path] }), _jsxs(Text, { dimColor: true, children: [" ", '─'.repeat(Math.max(1, panelWidth - 4))] }), lines.map((patchLine, index) => (_jsxs(Text, { ...(patchLine.startsWith('+')
279
- ? { color: 'green' }
280
- : patchLine.startsWith('-')
281
- ? { color: 'red' }
282
- : { dimColor: true }), children: [' ', patchLine] }, `${scrollOffset}-${index}`))), _jsx(Text, { dimColor: true, children: " \u2191/\u2193 to scroll \u00B7 Esc to back" })] }));
328
+ return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsx(Text, { bold: true, children: " Uncommitted changes (git diff HEAD)" }), _jsxs(Text, { children: [' ', snapshots.map((item, index) => (_jsxs(Text, { inverse: !screenReader && index === sourceIndex, children: [screenReader && index === sourceIndex ? 'Current source: ' : ' ', item.label, ' '] }, item.label)))] }), _jsx(Text, { children: " " }), _jsxs(Text, { bold: true, children: [" ", selected.path] }), !screenReader ? (_jsxs(Text, { dimColor: true, children: [" ", '─'.repeat(Math.max(1, panelWidth - 4))] })) : null, lines.map((patchLine, index) => patchLine.startsWith('+') && !patchLine.startsWith('+++') ? (_jsx(SyntaxCodeLine, { prefix: " ", text: patchLine, change: "added" }, `${scrollOffset}-${index}`)) : patchLine.startsWith('-') && !patchLine.startsWith('---') ? (_jsx(SyntaxCodeLine, { prefix: " ", text: patchLine, change: "removed" }, `${scrollOffset}-${index}`)) : (_jsxs(Text, { dimColor: true, children: [' ', patchLine] }, `${scrollOffset}-${index}`))), _jsx(Text, { dimColor: true, children: " \u2191/\u2193 to scroll \u00B7 Esc to back" })] }));
283
329
  }
284
- return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsx(Text, { bold: true, children: " Uncommitted changes (git diff HEAD)" }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [' ', snapshots.map((item, index) => (_jsxs(Text, { inverse: index === sourceIndex, children: [' ', item.label, ' '] }, item.label)))] }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [' ', snapshot.files.length, " file", snapshot.files.length === 1 ? '' : 's', ' ', "changed ", _jsxs(Text, { color: "green", children: ["+", snapshot.additions] }), ' ', _jsxs(Text, { color: "red", children: ["-", snapshot.deletions] })] }), _jsx(Text, { children: " " }), snapshot.files.length === 0 ? (_jsx(Text, { dimColor: true, children: " No uncommitted changes." })) : (snapshot.files.map((file, index) => (_jsxs(Text, { inverse: index === selectedIndex, children: [index === selectedIndex ? '❯ ' : ' ', file.path, " ", _jsxs(Text, { color: "green", children: ["+", file.additions] }), ' ', _jsxs(Text, { color: "red", children: ["-", file.deletions] })] }, file.path)))), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "\u2190/\u2192 to switch source \u00B7 \u2191/\u2193 to select \u00B7 Enter to view \u00B7 Esc to close" })] }));
330
+ return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsx(Text, { bold: true, children: " Uncommitted changes (git diff HEAD)" }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [' ', snapshots.map((item, index) => (_jsxs(Text, { inverse: !screenReader && index === sourceIndex, children: [screenReader && index === sourceIndex ? 'Current source: ' : ' ', item.label, ' '] }, item.label)))] }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [' ', snapshot.files.length, " file", snapshot.files.length === 1 ? '' : 's', ' ', "changed ", _jsxs(Text, { color: palette.success, children: ["+", snapshot.additions] }), ' ', _jsxs(Text, { color: palette.error, children: ["-", snapshot.deletions] })] }), _jsx(Text, { children: " " }), snapshot.files.length === 0 ? (_jsx(Text, { dimColor: true, children: " No uncommitted changes." })) : (snapshot.files.map((file, index) => (_jsxs(Text, { inverse: !screenReader && index === selectedIndex, children: [selectionPrefix(index === selectedIndex, screenReader), file.path, ' ', _jsxs(Text, { ...(!screenReader ? { color: palette.success } : {}), children: ["+", file.additions] }), ' ', _jsxs(Text, { ...(!screenReader ? { color: palette.error } : {}), children: ["-", file.deletions] })] }, file.path)))), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "\u2190/\u2192 to switch source \u00B7 \u2191/\u2193 to select \u00B7 Enter to view \u00B7 Esc to close" })] }));
285
331
  }
286
- export function PermissionDashboard({ tabIndex, selectedIndex, query, rules, recentDenied, workspaceDirectories, width, screenReader, }) {
332
+ export function PermissionDashboard({ tabIndex, selectedIndex, query, rules, recentDenied, retryingDeniedId, workspaceDirectories, width, screenReader, }) {
287
333
  const tabs = ['Recently denied', 'Allow', 'Ask', 'Deny', 'Workspace'];
288
334
  const behavior = ['allow', 'ask', 'deny'][tabIndex - 1];
289
335
  const normalizedQuery = query.trim().toLowerCase();
@@ -293,13 +339,13 @@ export function PermissionDashboard({ tabIndex, selectedIndex, query, rules, rec
293
339
  rule.rule.toLowerCase().includes(normalizedQuery) ||
294
340
  rule.scope.includes(normalizedQuery)))
295
341
  : [];
296
- const rows = tabIndex === 0 ? recentDenied : matchingRules.map((rule) => rule.rule);
342
+ const rows = matchingRules.map((rule) => rule.rule);
297
343
  const originalWorkspace = workspaceDirectories.find((directory) => directory.original);
298
344
  const additionalWorkspaces = workspaceDirectories.filter((directory) => !directory.original);
299
345
  const description = tabIndex === 0
300
346
  ? recentDenied.length === 0
301
347
  ? 'No recent denials. Commands denied by the auto mode classifier will appear here.'
302
- : 'Commands denied by the auto mode classifier appear here.'
348
+ : 'Commands recently denied by the auto mode classifier.'
303
349
  : tabIndex === 1
304
350
  ? "Praxis Code won't ask before using allowed tools."
305
351
  : tabIndex === 2
@@ -307,9 +353,60 @@ export function PermissionDashboard({ tabIndex, selectedIndex, query, rules, rec
307
353
  : tabIndex === 3
308
354
  ? 'Praxis Code will reject requests to use denied tools.'
309
355
  : 'Praxis Code can read files in the workspace, and make edits when auto-accept edits is on.';
310
- return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? (_jsx(Text, { dimColor: true, children: '─'.repeat(Math.min(100, width)) })) : null, _jsx(Text, { bold: true, children: " Permissions" }), _jsxs(Text, { children: [' ', tabs.map((tab, index) => (_jsxs(Text, { inverse: index === tabIndex, children: [' ', tab, ' '] }, tab)))] }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [" ", description] }), tabIndex >= 1 && tabIndex <= 3 ? (_jsx(Box, { borderStyle: screenReader ? undefined : 'round', paddingX: 1, marginY: 1, children: _jsxs(Text, { ...(query ? {} : { dimColor: true }), children: ["\u2315 ", query || 'Search…'] }) })) : (_jsx(Text, { children: " " })), tabIndex >= 1 && tabIndex <= 3 ? (['Add a new rule…', ...rows].map((row, index) => (_jsxs(Text, { inverse: index === selectedIndex, children: [index === selectedIndex ? '❯ ' : ' ', index + 1, ". ", row] }, `${index}-${row}`)))) : tabIndex === 4 ? (_jsxs(_Fragment, { children: [originalWorkspace ? (_jsxs(Text, { children: [' - ', originalWorkspace.path, " (Original working directory)"] })) : null, additionalWorkspaces.map((directory, index) => (_jsxs(Text, { inverse: selectedIndex === index, children: [selectedIndex === index ? '❯ ' : ' ', index + 1, ". ", directory.path] }, directory.path))), _jsxs(Text, { inverse: selectedIndex === additionalWorkspaces.length, children: [selectedIndex === additionalWorkspaces.length ? '❯ ' : ' ', additionalWorkspaces.length + 1, ". Add directory\u2026"] })] })) : rows.length > 0 ? (rows.map((row, index) => (_jsxs(Text, { inverse: index === selectedIndex, children: [index === selectedIndex ? '❯ ' : ' ', index + 1, ". ", row] }, `${index}-${row}`)))) : null, _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: selectedIndex >= 0
311
- ? '↑/↓ navigate · Enter to select · ←/→ to switch · Esc to cancel'
312
- : '←/→ to switch · ↓ to select · Esc to cancel' })] }));
356
+ return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? (_jsx(Text, { dimColor: true, children: '─'.repeat(Math.min(100, width)) })) : null, _jsx(Text, { bold: true, children: " Permissions" }), _jsxs(Text, { children: [' ', tabs.map((tab, index) => (_jsxs(Text, { inverse: !screenReader && index === tabIndex, children: [screenReader && index === tabIndex ? 'Current tab: ' : ' ', tab, ' '] }, tab)))] }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [" ", description] }), tabIndex >= 1 && tabIndex <= 3 ? (_jsx(Box, { borderStyle: screenReader ? undefined : 'round', paddingX: 1, marginY: 1, children: _jsxs(Text, { ...(query ? {} : { dimColor: true }), children: [screenReader ? 'Search: ' : '⌕ ', query || 'Search…'] }) })) : (_jsx(Text, { children: " " })), tabIndex >= 1 && tabIndex <= 3 ? (['Add a new rule…', ...rows].map((row, index) => (_jsxs(Text, { inverse: !screenReader && index === selectedIndex, children: [selectionPrefix(index === selectedIndex, screenReader), index + 1, ". ", row] }, `${index}-${row}`)))) : tabIndex === 0 ? (recentDenied.map((action, index) => (_jsxs(Text, { inverse: !screenReader && index === selectedIndex, children: [selectionPrefix(index === selectedIndex, screenReader), index + 1, ". ", action.id === retryingDeniedId ? '✔' : '✘', ' ', action.display, action.id === retryingDeniedId ? ' (retry)' : '', action.reason ? ` ${action.reason}` : ''] }, action.id)))) : tabIndex === 4 ? (_jsxs(_Fragment, { children: [originalWorkspace ? (_jsxs(Text, { children: [' - ', originalWorkspace.path, " (Original working directory)"] })) : null, additionalWorkspaces.map((directory, index) => (_jsxs(Text, { inverse: !screenReader && selectedIndex === index, children: [selectionPrefix(selectedIndex === index, screenReader), index + 1, ". ", directory.path] }, directory.path))), _jsxs(Text, { inverse: !screenReader && selectedIndex === additionalWorkspaces.length, children: [selectionPrefix(selectedIndex === additionalWorkspaces.length, screenReader), additionalWorkspaces.length + 1, ". Add directory\u2026"] })] })) : rows.length > 0 ? (rows.map((row, index) => (_jsxs(Text, { inverse: !screenReader && index === selectedIndex, children: [selectionPrefix(index === selectedIndex, screenReader), index + 1, ". ", row] }, `${index}-${row}`)))) : null, _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: tabIndex === 0 && recentDenied.length > 0
357
+ ? 'Enter to approve · r to retry · ↑/↓ to navigate · Esc to cancel'
358
+ : selectedIndex >= 0
359
+ ? '↑/↓ navigate · Enter to select · ←/→ to switch · Esc to cancel'
360
+ : '←/→ to switch · ↓ to select · Esc to cancel' })] }));
361
+ }
362
+ const THEME_OPTIONS = [
363
+ { theme: 'auto', label: 'Auto (match terminal)' },
364
+ { theme: 'dark', label: 'Dark mode' },
365
+ { theme: 'light', label: 'Light mode' },
366
+ { theme: 'dark-daltonized', label: 'Dark mode (colorblind-friendly)' },
367
+ { theme: 'light-daltonized', label: 'Light mode (colorblind-friendly)' },
368
+ { theme: 'dark-ansi', label: 'Dark mode (ANSI colors only)' },
369
+ { theme: 'light-ansi', label: 'Light mode (ANSI colors only)' },
370
+ ];
371
+ export function ThemePicker({ currentTheme, selectedIndex, syntaxHighlightingDisabled, customThemes = [], allowCustomThemes = true, width, screenReader, }) {
372
+ const options = [
373
+ ...THEME_OPTIONS.map((option) => ({ ...option, customTheme: undefined })),
374
+ ...customThemes.map((theme) => ({
375
+ theme: `custom:${theme.slug}`,
376
+ label: `${theme.name} (custom)`,
377
+ customTheme: theme,
378
+ })),
379
+ ...(allowCustomThemes
380
+ ? [{ theme: '__new__', label: 'New custom theme…' }]
381
+ : []),
382
+ ];
383
+ const selected = options[selectedIndex];
384
+ const selectedCustomTheme = selected && 'customTheme' in selected ? selected.customTheme : undefined;
385
+ const previewTheme = selected?.theme.startsWith('custom:') && selectedCustomTheme
386
+ ? selectedCustomTheme.base
387
+ : selected?.theme === '__new__'
388
+ ? 'dark'
389
+ : (selected?.theme ??
390
+ (currentTheme.startsWith('custom:') ? 'dark' : currentTheme));
391
+ const preview = tuiPalette(previewTheme, syntaxHighlightingDisabled, process.env, selectedCustomTheme);
392
+ const syntax = preview.syntax;
393
+ const syntaxColor = (color) => syntaxHighlightingDisabled ? {} : { color };
394
+ return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? _jsx(Text, { children: '▔'.repeat(Math.min(100, width)) }) : null, _jsx(Text, { bold: true, children: " Theme" }), _jsx(Text, { children: " " }), _jsx(Text, { children: " Choose the text style that looks best with your terminal" }), _jsx(Text, { children: " " }), options.map((option, index) => screenReader ? (_jsxs(Text, { children: [index + 1, ". ", option.label, option.theme === currentTheme ? ' (current)' : '', index === selectedIndex ? ' (focused)' : ''] }, option.theme)) : (_jsxs(Text, { inverse: index === selectedIndex, children: [index === selectedIndex ? ' ❯ ' : ' ', index + 1, ". ", option.label, option.theme === currentTheme ? ' ✔' : ''] }, option.theme))), _jsx(Text, { children: " " }), screenReader ? (_jsxs(Text, { children: ["Selected: ", options[selectedIndex]?.label] })) : null, !screenReader ? (_jsxs(_Fragment, { children: [_jsxs(Text, { dimColor: true, children: [' ', '╌'.repeat(Math.max(1, Math.min(96, width - 3)))] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: " 1 " }), _jsx(Text, { ...syntaxColor(syntax.keyword), children: "function" }), _jsx(Text, { ...syntaxColor(syntax.text), children: " " }), _jsx(Text, { ...syntaxColor(syntax.identifier), children: "greet" }), _jsxs(Text, { ...syntaxColor(syntax.text), children: ["() ", '{'] })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: " 2 - " }), _jsx(Text, { ...syntaxColor(syntax.text), ...(syntaxHighlightingDisabled || !syntax.removedBackground
395
+ ? {}
396
+ : { backgroundColor: syntax.removedBackground }), children: ' console.log("Hello, World!"); ' })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: " 2 + " }), _jsxs(Text, { ...syntaxColor(syntax.text), ...(syntaxHighlightingDisabled || !syntax.addedBackground
397
+ ? {}
398
+ : { backgroundColor: syntax.addedBackground }), children: [' console.', _jsx(Text, { ...syntaxColor(syntax.identifier), children: "log" }), '(', _jsx(Text, { ...syntaxColor(syntax.string), children: "\"Hello, " }), _jsx(Text, { ...(syntaxHighlightingDisabled || !syntax.addedHighlight
399
+ ? {}
400
+ : { backgroundColor: syntax.addedHighlight }), children: "Praxis" }), _jsx(Text, { ...syntaxColor(syntax.string), children: "!\"" }), '); '] })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: " 3 " }), _jsx(Text, { ...syntaxColor(syntax.text), children: '}' })] }), _jsxs(Text, { dimColor: true, children: [' ', '╌'.repeat(Math.max(1, Math.min(96, width - 3)))] })] })) : null, _jsxs(Text, { dimColor: true, children: [' ', selected?.theme === '__new__'
401
+ ? 'Enter to create a custom theme'
402
+ : syntaxHighlightingDisabled
403
+ ? 'Syntax highlighting disabled (ctrl+t to enable)'
404
+ : `Syntax theme: ${preview.syntaxTheme} (ctrl+t to disable)`] }), _jsx(Text, { dimColor: true, children: " Enter to select \u00B7 Esc to cancel" })] }));
405
+ }
406
+ export function CustomThemeEditor({ theme, token, value, tokens = [], selectedIndex = 0, query = '', width, screenReader, }) {
407
+ return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [_jsx(Text, { bold: true, children: theme.name }), token ? (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsxs(Text, { children: ["\u2588\u2588 ", token] }), _jsxs(Text, { dimColor: true, children: ["preset: ", value || '(not customized)'] }), _jsx(Text, { children: " " }), _jsxs(Text, { children: ["Value: ", value] }), _jsx(Text, { dimColor: true, children: "Accepts rgb(r,g,b), #rrggbb, ansi256(n), or ansi:name" }), _jsx(Text, { dimColor: true, children: "Enter to save \u00B7 Esc to cancel" })] })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { dimColor: true, children: ["\u2315 ", query || 'Filter color tokens…'] }), tokens
408
+ .slice(selectedIndex, selectedIndex + 8)
409
+ .map((entry, index) => (_jsxs(Text, { inverse: index === 0, children: [index === 0 ? '❯ ' : ' ', "\u2588\u2588 ", entry, theme.overrides[entry] === undefined ? '' : ' (custom)'] }, entry))), _jsx(Text, { dimColor: true, children: "\u2191/\u2193 to nav \u00B7 Enter to edit \u00B7 Tab to reset \u00B7 Esc to done" })] })), screenReader ? _jsx(Text, { children: "Editing custom theme token" }) : null] }));
313
410
  }
314
411
  export function StatusDashboard({ tabIndex, version, sessionId, display, usage, costUsd, turnCount, toolCount, commandCount, detailedTranscript, width, screenReader, }) {
315
412
  const tabs = ['Settings', 'Status', 'Config', 'Usage', 'Stats'];
@@ -364,8 +461,9 @@ export function ListDashboard({ title, rows, emptyText, selectedIndex, width, sc
364
461
  return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? (_jsx(Text, { dimColor: true, children: '─'.repeat(Math.min(100, width)) })) : null, _jsxs(Text, { bold: true, children: [" ", title] }), _jsx(Text, { children: " " }), rows.length === 0 ? (_jsxs(Text, { dimColor: true, children: [" ", emptyText] })) : (rows.map((row, index) => (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { inverse: index === selectedIndex, children: [index === selectedIndex ? '❯ ' : ' ', row.label] }), row.description ? _jsxs(Text, { dimColor: true, children: [" ", row.description] }) : null] }, `${index}-${row.label}`)))), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "\u2191/\u2193 to select \u00B7 Esc to close" })] }));
365
462
  }
366
463
  export function MemoryDashboard({ autoMemoryEnabled, entries, selectedIndex, openedIndex, loading = false, width, screenReader, }) {
464
+ const palette = useTuiPalette();
367
465
  const panelWidth = Math.min(100, width);
368
- return (_jsxs(Box, { flexDirection: "column", width: panelWidth, children: [!screenReader ? (_jsx(Text, { color: "cyan", children: '─'.repeat(panelWidth) })) : null, _jsx(Text, { bold: true, children: " Memory" }), _jsx(Text, { children: " " }), loading ? (_jsx(Text, { dimColor: true, children: " \u2736 Loading memory files\u2026" })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { children: [" Auto-memory: ", autoMemoryEnabled ? 'on' : 'off'] }), _jsx(Text, { children: " " }), entries.map((entry, index) => (_jsxs(Box, { children: [_jsx(Box, { width: Math.max(24, Math.min(52, panelWidth - 28)), children: _jsxs(Text, { inverse: index === selectedIndex, children: [index === selectedIndex ? '❯ ' : ' ', index + 1, ". ", entry.label, openedIndex === index ? ' ✔' : ''] }) }), entry.annotation ? (_jsx(Text, { dimColor: true, children: entry.annotation })) : null] }, `${entry.kind}-${entry.path}`)))] })), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: " Learn more: https://code.claude.com/docs/en/memory" }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, italic: true, children: "Enter to confirm \u00B7 Esc to cancel" })] }));
466
+ return (_jsxs(Box, { flexDirection: "column", width: panelWidth, children: [!screenReader ? (_jsx(Text, { color: palette.accent, children: '─'.repeat(panelWidth) })) : null, _jsx(Text, { bold: true, children: " Memory" }), _jsx(Text, { children: " " }), loading ? (_jsx(Text, { dimColor: true, children: " \u2736 Loading memory files\u2026" })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { children: [" Auto-memory: ", autoMemoryEnabled ? 'on' : 'off'] }), _jsx(Text, { children: " " }), entries.map((entry, index) => (_jsxs(Box, { children: [_jsx(Box, { width: Math.max(24, Math.min(52, panelWidth - 28)), children: _jsxs(Text, { inverse: index === selectedIndex, children: [index === selectedIndex ? '❯ ' : ' ', index + 1, ". ", entry.label, openedIndex === index ? ' ✔' : ''] }) }), entry.annotation ? (_jsx(Text, { dimColor: true, children: entry.annotation })) : null] }, `${entry.kind}-${entry.path}`)))] })), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: " Learn more: https://code.claude.com/docs/en/memory" }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, italic: true, children: "Enter to confirm \u00B7 Esc to cancel" })] }));
369
467
  }
370
468
  function selectedWindow(length, selectedIndex, size) {
371
469
  return Math.max(0, Math.min(selectedIndex - Math.floor(size / 2), Math.max(0, length - size)));
@@ -429,6 +527,7 @@ export function HookDashboard({ configuration, depth, eventIndex, matcherIndex,
429
527
  : 'Enter to confirm · Esc to cancel' })] }));
430
528
  }
431
529
  export function BtwPanel({ entries, selectedIndex, scrollOffset, copied, width, screenReader, }) {
530
+ const palette = useTuiPalette();
432
531
  const selected = entries[selectedIndex];
433
532
  const lines = selected?.answer.split('\n') ?? [];
434
533
  const visibleLines = lines.slice(scrollOffset, scrollOffset + 16);
@@ -452,20 +551,22 @@ export function BtwPanel({ entries, selectedIndex, scrollOffset, copied, width,
452
551
  ].join(' · ');
453
552
  return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? (_jsx(Text, { dimColor: true, children: '─'.repeat(Math.min(100, width)) })) : null, entries.map((entry, index) => (_jsxs(Text, { dimColor: index !== selectedIndex, children: [' ', "/btw ", entry.question] }, entry.id))), _jsx(Text, { children: " " }), selected?.status === 'answering' ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [" ", ' ', "\u00B7 Answering\u2026"] }), selected.answer
454
553
  ? visibleLines.map((line, index) => (_jsxs(Text, { children: [' ', ' ', line || ' '] }, `${scrollOffset + index}-${line}`)))
455
- : null] })) : selected?.status === 'forking' ? (_jsxs(Text, { children: [" ", ' ', "\u00B7 Forking\u2026"] })) : selected?.status === 'error' ? (_jsxs(Text, { color: "red", children: [' ', ' ', selected.error ?? 'Side question failed'] })) : (visibleLines.map((line, index) => (_jsxs(Text, { children: [' ', ' ', line || ' '] }, `${scrollOffset + index}-${line}`)))), _jsx(Text, { children: " " }), _jsxs(Text, { dimColor: true, children: [" ", footer] })] }));
554
+ : null] })) : selected?.status === 'forking' ? (_jsxs(Text, { children: [" ", ' ', "\u00B7 Forking\u2026"] })) : selected?.status === 'error' ? (_jsxs(Text, { color: palette.error, children: [' ', ' ', selected.error ?? 'Side question failed'] })) : (visibleLines.map((line, index) => (_jsxs(Text, { children: [' ', ' ', line || ' '] }, `${scrollOffset + index}-${line}`)))), _jsx(Text, { children: " " }), _jsxs(Text, { dimColor: true, children: [" ", footer] })] }));
456
555
  }
457
556
  export function SessionPicker({ sessions, selectedIndex, screenReader, query = '', }) {
557
+ const palette = useTuiPalette();
458
558
  const maxVisible = 8;
459
559
  const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), sessions.length - maxVisible));
460
560
  const visible = sessions.slice(start, start + maxVisible);
461
- return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: '─'.repeat(80) }) : null, _jsx(Text, { bold: true, children: " Resume session" }), _jsx(Box, { borderStyle: screenReader ? undefined : 'round', borderColor: "gray", paddingX: screenReader ? 0 : 1, marginY: 1, children: _jsxs(Text, { ...(query ? {} : { dimColor: true }), children: ["\u2315 ", query || 'Search…'] }) }), start > 0 ? _jsxs(Text, { dimColor: true, children: [" \u2191 ", start, " earlier"] }) : null, visible.length === 0 ? _jsx(Text, { dimColor: true, children: "No sessions found." }) : null, visible.map((session, visibleIndex) => {
561
+ return (_jsxs(Box, { flexDirection: "column", children: [!screenReader ? _jsx(Text, { dimColor: true, children: '─'.repeat(80) }) : null, _jsx(Text, { bold: true, children: " Resume session" }), _jsx(Box, { borderStyle: screenReader ? undefined : 'round', borderColor: palette.muted, paddingX: screenReader ? 0 : 1, marginY: 1, children: _jsxs(Text, { ...(query ? {} : { dimColor: true }), children: ["\u2315 ", query || 'Search…'] }) }), start > 0 ? _jsxs(Text, { dimColor: true, children: [" \u2191 ", start, " earlier"] }) : null, visible.length === 0 ? _jsx(Text, { dimColor: true, children: "No sessions found." }) : null, visible.map((session, visibleIndex) => {
462
562
  const index = start + visibleIndex;
463
- return (_jsxs(Box, { children: [_jsxs(Text, { ...(index === selectedIndex ? { color: BRAND } : {}), bold: index === selectedIndex, children: [index === selectedIndex ? '❯ ' : ' ', session
563
+ return (_jsxs(Box, { children: [_jsxs(Text, { ...(index === selectedIndex ? { color: palette.brand } : {}), bold: index === selectedIndex, children: [index === selectedIndex ? '❯ ' : ' ', session
464
564
  ? (session.name ?? session.lastPrompt ?? 'Untitled')
465
565
  : 'Start a new session'] }), session ? (_jsxs(Text, { dimColor: true, children: [' ', "\u00B7 ", session.sessionId, " \u00B7 ", session.status] })) : null] }, session?.sessionId ?? 'new'));
466
566
  }), start + visible.length < sessions.length ? (_jsxs(Text, { dimColor: true, children: [" \u2193 ", sessions.length - start - visible.length, " more"] })) : null, !screenReader ? (_jsx(Text, { dimColor: true, children: "\u2191/\u2193 to navigate \u00B7 Enter to select \u00B7 Type to search \u00B7 Esc to cancel" })) : null] }));
467
567
  }
468
568
  export function CommandPalette({ commands, selectedIndex, width, screenReader, }) {
569
+ const palette = useTuiPalette();
469
570
  const maxVisible = 12;
470
571
  const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), Math.max(0, commands.length - maxVisible)));
471
572
  const visible = commands.slice(start, start + maxVisible);
@@ -475,7 +576,7 @@ export function CommandPalette({ commands, selectedIndex, width, screenReader, }
475
576
  return (_jsx(Box, { flexDirection: "column", width: Math.min(100, width), children: visible.length === 0 ? (_jsx(Text, { dimColor: true, children: "No matching commands." })) : (visible.map((command, visibleIndex) => {
476
577
  const index = start + visibleIndex;
477
578
  const selected = index === selectedIndex;
478
- return (_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { width: 30, children: _jsxs(Text, { ...(selected ? { color: BRAND, bold: true } : {}), children: ["/", command.name] }) }), _jsx(Box, { flexGrow: 1, children: _jsx(Text, { dimColor: true, children: command.description }) })] }, command.name));
579
+ return (_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { width: 30, children: _jsxs(Text, { ...(selected ? { color: palette.brand, bold: true } : {}), children: ["/", command.name] }) }), _jsx(Box, { flexGrow: 1, children: _jsx(Text, { dimColor: true, children: command.description }) })] }, command.name));
479
580
  })) }));
480
581
  }
481
582
  export function FilePicker({ entries, selectedIndex, width, screenReader, }) {
@@ -526,54 +627,63 @@ export function ShortcutHelp({ width }) {
526
627
  return (_jsx(Box, { flexDirection: "column", width: Math.min(100, width), children: SHORTCUT_ROWS.map((row, rowIndex) => wide ? (_jsx(Box, { flexDirection: "row", children: row.map((cell, cellIndex) => (_jsx(Box, { width: cellIndex === 2 ? undefined : '33%', children: _jsx(Text, { dimColor: true, children: cell }) }, cellIndex))) }, rowIndex)) : (row.filter(Boolean).map((cell, cellIndex) => (_jsx(Text, { dimColor: true, children: cell }, `${rowIndex}-${cellIndex}`))))) }));
527
628
  }
528
629
  export function HelpMenu({ tabIndex, selectedIndex, builtinCommands, customCommands, width, screenReader, }) {
630
+ const palette = useTuiPalette();
529
631
  const tabs = ['General', 'Commands', 'Custom commands'];
530
632
  const commands = tabIndex === 1 ? builtinCommands : customCommands;
531
633
  const maxVisible = 10;
532
634
  const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), Math.max(0, commands.length - maxVisible)));
533
635
  const visible = commands.slice(start, start + maxVisible);
534
636
  const line = '─'.repeat(Math.max(12, Math.min(100, width)));
535
- return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsxs(Box, { children: [_jsx(Text, { bold: true, children: " Help " }), tabs.map((tab, index) => (_jsxs(Text, { ...(index === tabIndex ? { color: BRAND, bold: true } : {}), children: [' ', tab, ' '] }, tab)))] }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: tabIndex === 0 ? (_jsxs(_Fragment, { children: [_jsx(Text, { children: "Praxis understands your codebase, makes edits with your permission, and executes commands from your terminal." }), _jsx(Text, { bold: true, children: "Shortcuts" }), _jsx(ShortcutHelp, { width: width })] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { bold: true, children: tabIndex === 1
637
+ return (_jsxs(Box, { flexDirection: "column", width: Math.min(100, width), children: [!screenReader ? _jsx(Text, { dimColor: true, children: line }) : null, _jsxs(Box, { children: [_jsx(Text, { bold: true, children: " Help " }), tabs.map((tab, index) => (_jsxs(Text, { ...(index === tabIndex
638
+ ? { color: palette.brand, bold: true }
639
+ : {}), children: [' ', tab, ' '] }, tab)))] }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: tabIndex === 0 ? (_jsxs(_Fragment, { children: [_jsx(Text, { children: "Praxis understands your codebase, makes edits with your permission, and executes commands from your terminal." }), _jsx(Text, { bold: true, children: "Shortcuts" }), _jsx(ShortcutHelp, { width: width })] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { bold: true, children: tabIndex === 1
536
640
  ? 'Browse default commands'
537
641
  : 'Browse shared commands and skills' }), visible.length === 0 ? (_jsx(Text, { dimColor: true, children: "No commands found." })) : (visible.map((command, visibleIndex) => {
538
642
  const index = start + visibleIndex;
539
643
  return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { ...(index === selectedIndex
540
- ? { color: BRAND, bold: true }
644
+ ? { color: palette.brand, bold: true }
541
645
  : {}), children: [index === selectedIndex ? '↓ ' : ' ', "/", command.name] }), _jsxs(Text, { dimColor: true, children: [" ", command.description] })] }, command.name));
542
646
  }))] })) }), _jsx(Text, { dimColor: true, children: "\u2190/\u2192 to switch \u00B7 \u2191/\u2193 to navigate \u00B7 Esc to cancel" })] }));
543
647
  }
544
648
  export function SelectionMenu({ title, description, options, selectedIndex, footer, width, screenReader, }) {
649
+ const palette = useTuiPalette();
545
650
  const maxVisible = 7;
546
651
  const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), Math.max(0, options.length - maxVisible)));
547
652
  const visible = options.slice(start, start + maxVisible);
548
- return (_jsxs(Box, { borderStyle: screenReader ? undefined : 'round', borderColor: "gray", flexDirection: "column", marginTop: 1, paddingX: screenReader ? 0 : 1, width: screenReader ? undefined : Math.min(80, width), children: [_jsx(Text, { bold: true, children: title }), description ? _jsx(Text, { dimColor: true, children: description }) : null, visible.map((option, visibleIndex) => {
653
+ const current = options.find((option) => option.selected);
654
+ return (_jsxs(Box, { borderStyle: screenReader ? undefined : 'round', borderColor: palette.muted, flexDirection: "column", marginTop: 1, paddingX: screenReader ? 0 : 1, width: screenReader ? undefined : Math.min(80, width), children: [_jsx(Text, { bold: true, children: title }), description ? _jsx(Text, { dimColor: true, children: description }) : null, screenReader && current ? _jsxs(Text, { children: ["Current: ", current.label] }) : null, visible.map((option, visibleIndex) => {
549
655
  const index = start + visibleIndex;
550
656
  const selected = index === selectedIndex;
551
- return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { ...(selected ? { color: BRAND, bold: true } : {}), children: [selected ? '❯ ' : ' ', index + 1, ". ", option.label, option.selected ? ' ✔' : ''] }), option.description ? (_jsxs(Text, { dimColor: true, children: [" ", option.description] })) : null] }, `${index}-${option.label}`));
657
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { ...(!screenReader && selected
658
+ ? { color: palette.brand, bold: true }
659
+ : {}), children: [selectionPrefix(selected, screenReader), index + 1, ". ", option.label, !screenReader && option.selected ? ' ✔' : ''] }), option.description ? (_jsxs(Text, { dimColor: true, children: [" ", option.description] })) : null] }, `${index}-${option.label}`));
552
660
  }), start > 0 || start + visible.length < options.length ? (_jsxs(Text, { dimColor: true, children: [start > 0 ? `↑ ${start} earlier` : '', start > 0 && start + visible.length < options.length ? ' · ' : '', start + visible.length < options.length
553
661
  ? `↓ ${options.length - start - visible.length} more`
554
662
  : ''] })) : null, _jsx(Text, { dimColor: true, children: footer })] }));
555
663
  }
556
664
  function ComposerInput({ input, cursor }) {
665
+ const palette = useTuiPalette();
557
666
  const { before, current, after } = composerEditorSegments({
558
667
  text: input,
559
668
  cursor,
560
669
  });
561
670
  const cursorText = current === '\n' ? '↵' : (current ?? ' ');
562
- return (_jsxs(Text, { children: [before, _jsx(Text, { color: "black", backgroundColor: ACCENT, children: cursorText }), after] }));
671
+ return (_jsxs(Text, { children: [before, _jsx(Text, { color: palette.selectionText, backgroundColor: palette.accent, children: cursorText }), after] }));
563
672
  }
564
673
  export function ExternalEditorWait({ screenReader, }) {
565
674
  if (screenReader)
566
675
  return _jsx(Text, { children: "External editor open. Save and close it to continue." });
567
676
  return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }), _jsx(Text, { children: "Save and close editor to continue..." }), _jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" })] }));
568
677
  }
569
- export function Composer({ input, cursor, busy, clipboardBusy = false, status, display, usage, costUsd, width, screenReader, hasThinking = false, thinkingExpanded = false, shortcutsVisible = false, shellMode = false, footerMessage, }) {
678
+ export function Composer({ input, cursor, busy, clipboardBusy = false, status, display, usage, costUsd, width, screenReader, hasThinking = false, thinkingExpanded = false, shortcutsVisible = false, shellMode = false, footerMessage, reduceMotion = false, progressBar = true, turnDuration, editorMode = 'normal', prStatus, }) {
679
+ const palette = useTuiPalette();
570
680
  const [spinnerIndex, setSpinnerIndex] = useState(0);
571
681
  useEffect(() => {
572
- if (!busy || screenReader)
682
+ if (!busy || screenReader || reduceMotion)
573
683
  return;
574
684
  const timer = setInterval(() => setSpinnerIndex((current) => (current + 1) % SPINNER.length), 90);
575
685
  return () => clearInterval(timer);
576
- }, [busy, screenReader]);
686
+ }, [busy, reduceMotion, screenReader]);
577
687
  if (screenReader)
578
688
  return (_jsx(Text, { children: clipboardBusy
579
689
  ? 'Pasting…'
@@ -589,13 +699,14 @@ export function Composer({ input, cursor, busy, clipboardBusy = false, status, d
589
699
  100))}%)`
590
700
  : '', usage.cacheReadInputTokens
591
701
  ? ` · ${usage.cacheReadInputTokens} cached`
592
- : '', costUsd === undefined ? '' : ` · $${costUsd.toFixed(6)}`] })) : null, _jsx(Text, { dimColor: true, children: line }), clipboardBusy ? (_jsx(Text, { children: "Pasting\u2026" })) : busy ? (_jsxs(Text, { children: [_jsx(Text, { color: ACCENT, children: SPINNER[spinnerIndex] }), " ", status, "\u2026", ' ', _jsx(Text, { dimColor: true, children: "\u00B7 esc to interrupt" })] })) : (_jsxs(Text, { children: [_jsx(Text, { ...(shellMode ? {} : { color: BRAND }), bold: true, children: shellMode ? '! ' : '❯ ' }), input ? (_jsx(ComposerInput, { cursor: cursor ?? Array.from(input).length, input: input })) : (_jsx(Text, { dimColor: true, children: shellMode
702
+ : '', costUsd === undefined ? '' : ` · $${costUsd.toFixed(6)}`] })) : null, _jsx(Text, { dimColor: true, children: line }), clipboardBusy ? (_jsx(Text, { children: "Pasting\u2026" })) : busy ? (_jsxs(Text, { children: [progressBar ? (_jsx(Text, { color: palette.accent, children: reduceMotion ? '•' : SPINNER[spinnerIndex] })) : null, ' ', status, "\u2026 ", _jsx(Text, { dimColor: true, children: "\u00B7 esc to interrupt" })] })) : (_jsxs(Text, { children: [_jsx(Text, { ...(shellMode ? {} : { color: palette.brand }), bold: true, children: shellMode ? '! ' : '❯ ' }), input ? (_jsx(ComposerInput, { cursor: cursor ?? Array.from(input).length, input: input })) : (_jsx(Text, { dimColor: true, children: shellMode
593
703
  ? 'Enter a shell command'
594
704
  : 'Try "review this project"' }))] })), _jsx(Text, { dimColor: true, children: line }), shortcutsVisible ? (_jsx(ShortcutHelp, { width: width })) : (_jsxs(Box, { width: Math.min(100, width), children: [_jsx(Text, { dimColor: true, children: shellMode ? ('! for shell mode') : (_jsxs(_Fragment, { children: ["\u23F5\u23F5 ", permissionLabel(display.permissionMode), " \u00B7", ' ', busy ? 'esc to interrupt' : '? for shortcuts', " \u00B7 \u2190 for agents", hasThinking
595
705
  ? ` · ctrl+o ${thinkingExpanded ? 'collapse' : 'expand'}`
596
- : ''] })) }), _jsx(Box, { flexGrow: 1 }), footerMessage ? (footerMessage.isError ? (_jsx(Text, { color: "red", children: footerMessage.text })) : (_jsx(Text, { dimColor: true, children: footerMessage.text }))) : display.effort ? (_jsxs(Text, { children: [_jsxs(Text, { color: ACCENT, children: ["\u25CF ", display.effort] }), _jsx(Text, { dimColor: true, children: " \u00B7 /effort" })] })) : null] }))] }));
706
+ : ''] })) }), _jsx(Box, { flexGrow: 1 }), footerMessage ? (footerMessage.isError ? (_jsx(Text, { color: palette.error, children: footerMessage.text })) : (_jsx(Text, { dimColor: true, children: footerMessage.text }))) : prStatus ? (_jsx(Text, { dimColor: true, children: prStatus })) : turnDuration ? (_jsxs(Text, { dimColor: true, children: ["Cooked for ", turnDuration] })) : display.effort ? (_jsxs(Text, { children: [_jsxs(Text, { color: palette.accent, children: ["\u25CF ", display.effort] }), _jsxs(Text, { dimColor: true, children: [' ', "\u00B7 ", editorMode === 'vim' ? 'vim' : '/effort'] })] })) : null] }))] }));
597
707
  }
598
708
  export function DialogFrame({ title, children, screenReader, }) {
599
- return (_jsxs(Box, { flexDirection: "column", borderStyle: screenReader ? undefined : 'round', borderColor: "yellow", paddingX: screenReader ? 0 : 1, marginTop: 1, children: [_jsx(Text, { color: "yellow", bold: true, children: title }), children] }));
709
+ const palette = useTuiPalette();
710
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: screenReader ? undefined : 'round', borderColor: palette.warning, paddingX: screenReader ? 0 : 1, marginTop: 1, children: [_jsx(Text, { color: palette.warning, bold: true, children: title }), children] }));
600
711
  }
601
712
  //# sourceMappingURL=claude-style.js.map