praxis-agent 0.6.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 (303) hide show
  1. package/README.md +10 -1
  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 +44 -3
  19. package/dist/cli/interactive.js +1431 -189
  20. package/dist/cli/tui/claude-style.d.ts +41 -3
  21. package/dist/cli/tui/claude-style.js +227 -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/hook-settings.d.ts +33 -0
  31. package/dist/cli/tui/hook-settings.js +200 -0
  32. package/dist/cli/tui/keybindings.js +0 -1
  33. package/dist/cli/tui/mcp-panel-controller.d.ts +32 -0
  34. package/dist/cli/tui/mcp-panel-controller.js +80 -0
  35. package/dist/cli/tui/mcp-panel-projector.d.ts +79 -0
  36. package/dist/cli/tui/mcp-panel-projector.js +181 -0
  37. package/dist/cli/tui/mcp-panel.d.ts +8 -0
  38. package/dist/cli/tui/mcp-panel.js +99 -0
  39. package/dist/cli/tui/recently-denied.d.ts +15 -0
  40. package/dist/cli/tui/recently-denied.js +19 -0
  41. package/dist/cli/tui/runtime-interactions.d.ts +17 -0
  42. package/dist/cli/tui/runtime-interactions.js +100 -0
  43. package/dist/cli/tui/runtime-settings.d.ts +40 -0
  44. package/dist/cli/tui/runtime-settings.js +84 -0
  45. package/dist/cli/tui/slash-commands.js +15 -0
  46. package/dist/cli/tui/task-panel.d.ts +53 -0
  47. package/dist/cli/tui/task-panel.js +204 -0
  48. package/dist/cli/tui/terminal-notifications.d.ts +10 -0
  49. package/dist/cli/tui/terminal-notifications.js +48 -0
  50. package/dist/cli/tui/terminal-setup.d.ts +24 -0
  51. package/dist/cli/tui/terminal-setup.js +618 -0
  52. package/dist/cli/tui/theme-settings.d.ts +8 -0
  53. package/dist/cli/tui/theme-settings.js +132 -0
  54. package/dist/cli/tui/theme.d.ts +53 -0
  55. package/dist/cli/tui/theme.js +265 -0
  56. package/dist/cli.d.ts +12 -0
  57. package/dist/cli.js +140 -21
  58. package/dist/compatibility/claude/schema.js +2 -0
  59. package/dist/compatibility/claude/shared-resources.d.ts +2 -0
  60. package/dist/core/runtime.d.ts +12 -0
  61. package/dist/core/runtime.js +24 -0
  62. package/dist/maintenance/self-update.js +1 -1
  63. package/dist/mcp/claude-mcp-management.d.ts +6 -1
  64. package/dist/mcp/claude-mcp-management.js +191 -44
  65. package/dist/mcp/claude-mcp-oauth.js +2 -0
  66. package/dist/mcp/claude-mcp-tools.d.ts +31 -3
  67. package/dist/mcp/claude-mcp-tools.js +116 -34
  68. package/dist/permissions/claude-permission-resolver.d.ts +3 -0
  69. package/dist/permissions/claude-permission-resolver.js +42 -20
  70. package/dist/platform/claude-version.js +2 -1
  71. package/dist/plugins/claude-plugin-runtime.d.ts +1 -0
  72. package/dist/plugins/claude-plugin-runtime.js +60 -24
  73. package/dist/tools/claude-interactive-tools.d.ts +7 -0
  74. package/dist/tools/claude-interactive-tools.js +21 -8
  75. package/dist/tools/claude-task-tools.d.ts +4 -0
  76. package/dist/tools/claude-task-tools.js +7 -0
  77. package/package.json +2 -1
  78. package/dist/application/background-agent-manager.d.ts.map +0 -1
  79. package/dist/application/background-agent-manager.js.map +0 -1
  80. package/dist/application/background-bash-manager.d.ts.map +0 -1
  81. package/dist/application/background-bash-manager.js.map +0 -1
  82. package/dist/application/background-task-id.d.ts.map +0 -1
  83. package/dist/application/background-task-id.js.map +0 -1
  84. package/dist/application/claude-project-purge.d.ts.map +0 -1
  85. package/dist/application/claude-project-purge.js.map +0 -1
  86. package/dist/application/managed-worktree.d.ts.map +0 -1
  87. package/dist/application/managed-worktree.js.map +0 -1
  88. package/dist/application/model-compactor.d.ts.map +0 -1
  89. package/dist/application/model-compactor.js.map +0 -1
  90. package/dist/application/scheduled-prompt-manager.d.ts.map +0 -1
  91. package/dist/application/scheduled-prompt-manager.js.map +0 -1
  92. package/dist/application/session-service.d.ts.map +0 -1
  93. package/dist/application/session-service.js.map +0 -1
  94. package/dist/application/session-worktree.d.ts.map +0 -1
  95. package/dist/application/session-worktree.js.map +0 -1
  96. package/dist/application/subagent-service.d.ts.map +0 -1
  97. package/dist/application/subagent-service.js.map +0 -1
  98. package/dist/application/tool-use-summary.d.ts.map +0 -1
  99. package/dist/application/tool-use-summary.js.map +0 -1
  100. package/dist/application/top-level-agent-manager.d.ts.map +0 -1
  101. package/dist/application/top-level-agent-manager.js.map +0 -1
  102. package/dist/application/workflow-manager.d.ts.map +0 -1
  103. package/dist/application/workflow-manager.js.map +0 -1
  104. package/dist/application/workflow-meta.d.ts.map +0 -1
  105. package/dist/application/workflow-meta.js.map +0 -1
  106. package/dist/application/workflow-runtime.d.ts.map +0 -1
  107. package/dist/application/workflow-runtime.js.map +0 -1
  108. package/dist/application/workflow-worktree.d.ts.map +0 -1
  109. package/dist/application/workflow-worktree.js.map +0 -1
  110. package/dist/cli/agents-dashboard.d.ts.map +0 -1
  111. package/dist/cli/agents-dashboard.js.map +0 -1
  112. package/dist/cli/controls.d.ts.map +0 -1
  113. package/dist/cli/controls.js.map +0 -1
  114. package/dist/cli/debug.d.ts.map +0 -1
  115. package/dist/cli/debug.js.map +0 -1
  116. package/dist/cli/interactive.d.ts.map +0 -1
  117. package/dist/cli/interactive.js.map +0 -1
  118. package/dist/cli/protocol.d.ts.map +0 -1
  119. package/dist/cli/protocol.js.map +0 -1
  120. package/dist/cli/tui/claude-style.d.ts.map +0 -1
  121. package/dist/cli/tui/claude-style.js.map +0 -1
  122. package/dist/cli/tui/clipboard.d.ts.map +0 -1
  123. package/dist/cli/tui/clipboard.js.map +0 -1
  124. package/dist/cli/tui/composer-editor.d.ts.map +0 -1
  125. package/dist/cli/tui/composer-editor.js.map +0 -1
  126. package/dist/cli/tui/composer-images.d.ts.map +0 -1
  127. package/dist/cli/tui/composer-images.js.map +0 -1
  128. package/dist/cli/tui/conversation-export.d.ts.map +0 -1
  129. package/dist/cli/tui/conversation-export.js.map +0 -1
  130. package/dist/cli/tui/external-editor.d.ts.map +0 -1
  131. package/dist/cli/tui/external-editor.js.map +0 -1
  132. package/dist/cli/tui/file-picker.d.ts.map +0 -1
  133. package/dist/cli/tui/file-picker.js.map +0 -1
  134. package/dist/cli/tui/git-diff.d.ts.map +0 -1
  135. package/dist/cli/tui/git-diff.js.map +0 -1
  136. package/dist/cli/tui/keybindings.d.ts.map +0 -1
  137. package/dist/cli/tui/keybindings.js.map +0 -1
  138. package/dist/cli/tui/memory-files.d.ts.map +0 -1
  139. package/dist/cli/tui/memory-files.js.map +0 -1
  140. package/dist/cli/tui/permission-settings.d.ts.map +0 -1
  141. package/dist/cli/tui/permission-settings.js.map +0 -1
  142. package/dist/cli/tui/slash-commands.d.ts.map +0 -1
  143. package/dist/cli/tui/slash-commands.js.map +0 -1
  144. package/dist/cli/tui/terminal-suspend.d.ts.map +0 -1
  145. package/dist/cli/tui/terminal-suspend.js.map +0 -1
  146. package/dist/cli/tui/workspace-directories.d.ts.map +0 -1
  147. package/dist/cli/tui/workspace-directories.js.map +0 -1
  148. package/dist/cli.d.ts.map +0 -1
  149. package/dist/cli.js.map +0 -1
  150. package/dist/compatibility/claude/compaction.d.ts.map +0 -1
  151. package/dist/compatibility/claude/compaction.js.map +0 -1
  152. package/dist/compatibility/claude/context.d.ts.map +0 -1
  153. package/dist/compatibility/claude/context.js.map +0 -1
  154. package/dist/compatibility/claude/dynamic-context.d.ts.map +0 -1
  155. package/dist/compatibility/claude/dynamic-context.js.map +0 -1
  156. package/dist/compatibility/claude/file-history.d.ts.map +0 -1
  157. package/dist/compatibility/claude/file-history.js.map +0 -1
  158. package/dist/compatibility/claude/file-resources.d.ts.map +0 -1
  159. package/dist/compatibility/claude/file-resources.js.map +0 -1
  160. package/dist/compatibility/claude/fork.d.ts.map +0 -1
  161. package/dist/compatibility/claude/fork.js.map +0 -1
  162. package/dist/compatibility/claude/history.d.ts.map +0 -1
  163. package/dist/compatibility/claude/history.js.map +0 -1
  164. package/dist/compatibility/claude/ownership.d.ts.map +0 -1
  165. package/dist/compatibility/claude/ownership.js.map +0 -1
  166. package/dist/compatibility/claude/paths.d.ts.map +0 -1
  167. package/dist/compatibility/claude/paths.js.map +0 -1
  168. package/dist/compatibility/claude/pr-links.d.ts.map +0 -1
  169. package/dist/compatibility/claude/pr-links.js.map +0 -1
  170. package/dist/compatibility/claude/projection.d.ts.map +0 -1
  171. package/dist/compatibility/claude/projection.js.map +0 -1
  172. package/dist/compatibility/claude/schema.d.ts.map +0 -1
  173. package/dist/compatibility/claude/schema.js.map +0 -1
  174. package/dist/compatibility/claude/shared-resources.d.ts.map +0 -1
  175. package/dist/compatibility/claude/shared-resources.js.map +0 -1
  176. package/dist/compatibility/claude/sidechain.d.ts.map +0 -1
  177. package/dist/compatibility/claude/sidechain.js.map +0 -1
  178. package/dist/compatibility/claude/tool-links.d.ts.map +0 -1
  179. package/dist/compatibility/claude/tool-links.js.map +0 -1
  180. package/dist/compatibility/claude/translation.d.ts.map +0 -1
  181. package/dist/compatibility/claude/translation.js.map +0 -1
  182. package/dist/compatibility/claude/workflow-replay.d.ts.map +0 -1
  183. package/dist/compatibility/claude/workflow-replay.js.map +0 -1
  184. package/dist/compatibility/claude/workflow.d.ts.map +0 -1
  185. package/dist/compatibility/claude/workflow.js.map +0 -1
  186. package/dist/core/compaction.d.ts.map +0 -1
  187. package/dist/core/compaction.js.map +0 -1
  188. package/dist/core/context-budget.d.ts.map +0 -1
  189. package/dist/core/context-budget.js.map +0 -1
  190. package/dist/core/context.d.ts.map +0 -1
  191. package/dist/core/context.js.map +0 -1
  192. package/dist/core/runtime.d.ts.map +0 -1
  193. package/dist/core/runtime.js.map +0 -1
  194. package/dist/core/usage.d.ts.map +0 -1
  195. package/dist/core/usage.js.map +0 -1
  196. package/dist/extensions/claude-extension-tools.d.ts.map +0 -1
  197. package/dist/extensions/claude-extension-tools.js.map +0 -1
  198. package/dist/extensions/claude-extensions.d.ts.map +0 -1
  199. package/dist/extensions/claude-extensions.js.map +0 -1
  200. package/dist/hooks/claude-hook-tools.d.ts.map +0 -1
  201. package/dist/hooks/claude-hook-tools.js.map +0 -1
  202. package/dist/hooks/claude-hooks.d.ts.map +0 -1
  203. package/dist/hooks/claude-hooks.js.map +0 -1
  204. package/dist/maintenance/doctor.d.ts.map +0 -1
  205. package/dist/maintenance/doctor.js.map +0 -1
  206. package/dist/maintenance/self-update.d.ts.map +0 -1
  207. package/dist/maintenance/self-update.js.map +0 -1
  208. package/dist/mcp/claude-mcp-management.d.ts.map +0 -1
  209. package/dist/mcp/claude-mcp-management.js.map +0 -1
  210. package/dist/mcp/claude-mcp-oauth.d.ts.map +0 -1
  211. package/dist/mcp/claude-mcp-oauth.js.map +0 -1
  212. package/dist/mcp/claude-mcp-tools.d.ts.map +0 -1
  213. package/dist/mcp/claude-mcp-tools.js.map +0 -1
  214. package/dist/mcp/praxis-mcp-server.d.ts.map +0 -1
  215. package/dist/mcp/praxis-mcp-server.js.map +0 -1
  216. package/dist/permissions/claude-auto-classifier.d.ts.map +0 -1
  217. package/dist/permissions/claude-auto-classifier.js.map +0 -1
  218. package/dist/permissions/claude-permission-resolver.d.ts.map +0 -1
  219. package/dist/permissions/claude-permission-resolver.js.map +0 -1
  220. package/dist/persistence/claude-job-store.d.ts.map +0 -1
  221. package/dist/persistence/claude-job-store.js.map +0 -1
  222. package/dist/persistence/claude-scheduled-task-store.d.ts.map +0 -1
  223. package/dist/persistence/claude-scheduled-task-store.js.map +0 -1
  224. package/dist/persistence/claude-sidechain-store.d.ts.map +0 -1
  225. package/dist/persistence/claude-sidechain-store.js.map +0 -1
  226. package/dist/persistence/claude-task-store.d.ts.map +0 -1
  227. package/dist/persistence/claude-task-store.js.map +0 -1
  228. package/dist/persistence/claude-transcript-store.d.ts.map +0 -1
  229. package/dist/persistence/claude-transcript-store.js.map +0 -1
  230. package/dist/persistence/claude-workflow-store.d.ts.map +0 -1
  231. package/dist/persistence/claude-workflow-store.js.map +0 -1
  232. package/dist/persistence/in-memory-sidechain-store.d.ts.map +0 -1
  233. package/dist/persistence/in-memory-sidechain-store.js.map +0 -1
  234. package/dist/persistence/in-memory-transcript-store.d.ts.map +0 -1
  235. package/dist/persistence/in-memory-transcript-store.js.map +0 -1
  236. package/dist/platform/atomic-write.d.ts.map +0 -1
  237. package/dist/platform/atomic-write.js.map +0 -1
  238. package/dist/platform/bounded-process-runner.d.ts.map +0 -1
  239. package/dist/platform/bounded-process-runner.js.map +0 -1
  240. package/dist/platform/claude-version.d.ts.map +0 -1
  241. package/dist/platform/claude-version.js.map +0 -1
  242. package/dist/platform/command-shell.d.ts.map +0 -1
  243. package/dist/platform/command-shell.js.map +0 -1
  244. package/dist/platform/exclusive-file-lease.d.ts.map +0 -1
  245. package/dist/platform/exclusive-file-lease.js.map +0 -1
  246. package/dist/platform/sensitive-data.d.ts.map +0 -1
  247. package/dist/platform/sensitive-data.js.map +0 -1
  248. package/dist/platform/tmux-worktree.d.ts.map +0 -1
  249. package/dist/platform/tmux-worktree.js.map +0 -1
  250. package/dist/plugins/claude-plugin-eval-discovery.d.ts.map +0 -1
  251. package/dist/plugins/claude-plugin-eval-discovery.js.map +0 -1
  252. package/dist/plugins/claude-plugin-eval-graders.d.ts.map +0 -1
  253. package/dist/plugins/claude-plugin-eval-graders.js.map +0 -1
  254. package/dist/plugins/claude-plugin-eval-runner.d.ts.map +0 -1
  255. package/dist/plugins/claude-plugin-eval-runner.js.map +0 -1
  256. package/dist/plugins/claude-plugin-eval-schema.d.ts.map +0 -1
  257. package/dist/plugins/claude-plugin-eval-schema.js.map +0 -1
  258. package/dist/plugins/claude-plugin-eval.d.ts.map +0 -1
  259. package/dist/plugins/claude-plugin-eval.js.map +0 -1
  260. package/dist/plugins/claude-plugin-maintenance.d.ts.map +0 -1
  261. package/dist/plugins/claude-plugin-maintenance.js.map +0 -1
  262. package/dist/plugins/claude-plugin-marketplace.d.ts.map +0 -1
  263. package/dist/plugins/claude-plugin-marketplace.js.map +0 -1
  264. package/dist/plugins/claude-plugin-mcpb.d.ts.map +0 -1
  265. package/dist/plugins/claude-plugin-mcpb.js.map +0 -1
  266. package/dist/plugins/claude-plugin-runtime.d.ts.map +0 -1
  267. package/dist/plugins/claude-plugin-runtime.js.map +0 -1
  268. package/dist/providers/anthropic-compatible.d.ts.map +0 -1
  269. package/dist/providers/anthropic-compatible.js.map +0 -1
  270. package/dist/providers/environment.d.ts.map +0 -1
  271. package/dist/providers/environment.js.map +0 -1
  272. package/dist/providers/fallback-provider.d.ts.map +0 -1
  273. package/dist/providers/fallback-provider.js.map +0 -1
  274. package/dist/providers/openai-compatible.d.ts.map +0 -1
  275. package/dist/providers/openai-compatible.js.map +0 -1
  276. package/dist/tools/claude-interactive-tools.d.ts.map +0 -1
  277. package/dist/tools/claude-interactive-tools.js.map +0 -1
  278. package/dist/tools/claude-lsp-formatters.d.ts.map +0 -1
  279. package/dist/tools/claude-lsp-formatters.js.map +0 -1
  280. package/dist/tools/claude-lsp-tool.d.ts.map +0 -1
  281. package/dist/tools/claude-lsp-tool.js.map +0 -1
  282. package/dist/tools/claude-scheduled-tools.d.ts.map +0 -1
  283. package/dist/tools/claude-scheduled-tools.js.map +0 -1
  284. package/dist/tools/claude-task-tools.d.ts.map +0 -1
  285. package/dist/tools/claude-task-tools.js.map +0 -1
  286. package/dist/tools/claude-user-message.d.ts.map +0 -1
  287. package/dist/tools/claude-user-message.js.map +0 -1
  288. package/dist/tools/claude-workflow-tools.d.ts.map +0 -1
  289. package/dist/tools/claude-workflow-tools.js.map +0 -1
  290. package/dist/tools/claude-worktree-tools.d.ts.map +0 -1
  291. package/dist/tools/claude-worktree-tools.js.map +0 -1
  292. package/dist/tools/filtered-tool-registry.d.ts.map +0 -1
  293. package/dist/tools/filtered-tool-registry.js.map +0 -1
  294. package/dist/tools/glob.d.ts.map +0 -1
  295. package/dist/tools/glob.js.map +0 -1
  296. package/dist/tools/local-tools.d.ts.map +0 -1
  297. package/dist/tools/local-tools.js.map +0 -1
  298. package/dist/tools/notebook.d.ts.map +0 -1
  299. package/dist/tools/notebook.js.map +0 -1
  300. package/dist/tools/pdf.d.ts.map +0 -1
  301. package/dist/tools/pdf.js.map +0 -1
  302. package/dist/tools/web.d.ts.map +0 -1
  303. package/dist/tools/web.js.map +0 -1
@@ -0,0 +1,284 @@
1
+ import { constants } from 'node:fs';
2
+ import { mkdir, open, readdir, readFile, rm } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { setTimeout } from 'node:timers/promises';
6
+ import { writeFileAtomically } from '../../platform/atomic-write.js';
7
+ import { ExclusiveFileLease, } from '../../platform/exclusive-file-lease.js';
8
+ import { TUI_THEMES } from './theme.js';
9
+ export const CUSTOM_THEME_TOKENS = [
10
+ 'autoAccept',
11
+ 'autoAcceptShimmer',
12
+ 'background',
13
+ 'bashBorder',
14
+ 'bashMessageBackgroundColor',
15
+ 'blue_FOR_SUBAGENTS_ONLY',
16
+ 'briefLabelClaude',
17
+ 'briefLabelYou',
18
+ 'chromeYellow',
19
+ 'claude',
20
+ 'claudeBlueShimmer_FOR_SYSTEM_SPINNER',
21
+ 'claudeBlue_FOR_SYSTEM_SPINNER',
22
+ 'claudeShimmer',
23
+ 'clawd_background',
24
+ 'clawd_body',
25
+ 'cyan_FOR_SUBAGENTS_ONLY',
26
+ 'diffAdded',
27
+ 'diffAddedDimmed',
28
+ 'diffAddedWord',
29
+ 'diffRemoved',
30
+ 'diffRemovedDimmed',
31
+ 'diffRemovedWord',
32
+ 'error',
33
+ 'fastMode',
34
+ 'fastModeShimmer',
35
+ 'green_FOR_SUBAGENTS_ONLY',
36
+ 'ide',
37
+ 'inactive',
38
+ 'inactiveShimmer',
39
+ 'inverseText',
40
+ 'memoryBackgroundColor',
41
+ 'merged',
42
+ 'messageActionsBackground',
43
+ 'orange_FOR_SUBAGENTS_ONLY',
44
+ 'pink_FOR_SUBAGENTS_ONLY',
45
+ 'planMode',
46
+ 'professionalBlue',
47
+ 'promptBorder',
48
+ 'promptBorderShimmer',
49
+ 'purple_FOR_SUBAGENTS_ONLY',
50
+ 'rainbow_blue',
51
+ 'rainbow_blue_shimmer',
52
+ 'rainbow_green',
53
+ 'rainbow_green_shimmer',
54
+ 'rainbow_indigo',
55
+ 'rainbow_indigo_shimmer',
56
+ 'rainbow_orange',
57
+ 'rainbow_orange_shimmer',
58
+ 'rainbow_red',
59
+ 'rainbow_red_shimmer',
60
+ 'rainbow_violet',
61
+ 'rainbow_violet_shimmer',
62
+ 'rainbow_yellow',
63
+ 'rainbow_yellow_shimmer',
64
+ 'rate_limit_empty',
65
+ 'rate_limit_fill',
66
+ 'red_FOR_SUBAGENTS_ONLY',
67
+ 'remember',
68
+ 'selectionBg',
69
+ 'success',
70
+ 'subtle',
71
+ 'suggestion',
72
+ 'text',
73
+ 'userMessageBackground',
74
+ 'userMessageBackgroundHover',
75
+ 'warning',
76
+ 'warningShimmer',
77
+ 'yellow_FOR_SUBAGENTS_ONLY',
78
+ ];
79
+ const MAX_THEME_FILE_BYTES = 256 * 1024;
80
+ const CUSTOM_NAME = /^[A-Za-z][A-Za-z0-9 _-]{0,63}$/u;
81
+ const CUSTOM_SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
82
+ const HEX = /^#[0-9a-f]{6}$/iu;
83
+ const RGB = /^rgb\(\s*(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\s*,\s*(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\s*,\s*(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\s*\)$/iu;
84
+ const ANSI256 = /^ansi256\((?:[0-9]|[1-9]\d|1\d\d|2[0-4]\d)\)$/u;
85
+ const ANSI = /^ansi:[A-Za-z][A-Za-z0-9]*$/u;
86
+ function configRootPath() {
87
+ return process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), '.claude');
88
+ }
89
+ export function customThemeDirectory(configRoot = configRootPath()) {
90
+ return join(configRoot, 'themes');
91
+ }
92
+ function slugify(name) {
93
+ return name
94
+ .trim()
95
+ .toLowerCase()
96
+ .replace(/[^a-z0-9]+/gu, '-')
97
+ .replace(/^-+|-+$/gu, '');
98
+ }
99
+ export function validateCustomThemeName(name) {
100
+ const normalized = name.trim();
101
+ if (!CUSTOM_NAME.test(normalized)) {
102
+ throw new Error('Theme name must start with a letter and contain only letters, numbers, spaces, hyphens, or underscores (1–64 characters).');
103
+ }
104
+ const slug = slugify(normalized);
105
+ if (!CUSTOM_SLUG.test(slug))
106
+ throw new Error('Theme name must contain at least one ASCII letter or number.');
107
+ return slug;
108
+ }
109
+ function validateColor(value) {
110
+ const normalized = value.trim();
111
+ if (!HEX.test(normalized) &&
112
+ !RGB.test(normalized) &&
113
+ !ANSI256.test(normalized) &&
114
+ !ANSI.test(normalized)) {
115
+ throw new Error(`Invalid theme color ${JSON.stringify(value)}. Use rgb(r,g,b), #rrggbb, ansi256(n), or ansi:name.`);
116
+ }
117
+ return normalized;
118
+ }
119
+ function parseTheme(value, slug) {
120
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
121
+ throw new Error(`Invalid custom theme file: ${slug}.json`);
122
+ const record = value;
123
+ if (typeof record.name !== 'string' || !CUSTOM_NAME.test(record.name))
124
+ throw new Error(`Invalid custom theme name: ${slug}.json`);
125
+ if (!TUI_THEMES.includes(record.base) ||
126
+ record.base === 'auto')
127
+ throw new Error(`Invalid custom theme base: ${slug}.json`);
128
+ if (typeof record.overrides !== 'object' ||
129
+ record.overrides === null ||
130
+ Array.isArray(record.overrides))
131
+ throw new Error(`Invalid custom theme overrides: ${slug}.json`);
132
+ const overrides = {};
133
+ for (const [token, color] of Object.entries(record.overrides)) {
134
+ if (!CUSTOM_THEME_TOKENS.includes(token))
135
+ throw new Error(`Unknown custom theme token ${JSON.stringify(token)}.`);
136
+ if (typeof color !== 'string')
137
+ throw new Error(`Theme token ${token} must be a color string.`);
138
+ overrides[token] = validateColor(color);
139
+ }
140
+ const expectedSlug = slugify(record.name);
141
+ if (expectedSlug !== slug)
142
+ throw new Error(`Custom theme filename must match its name: ${slug}.json`);
143
+ return {
144
+ name: record.name,
145
+ slug,
146
+ base: record.base,
147
+ overrides,
148
+ };
149
+ }
150
+ async function readThemeFile(path, slug) {
151
+ const handle = await open(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
152
+ try {
153
+ const info = await handle.stat();
154
+ if (info.size > MAX_THEME_FILE_BYTES)
155
+ throw new Error(`Custom theme exceeds ${MAX_THEME_FILE_BYTES} bytes: ${path}`);
156
+ return parseTheme(JSON.parse(await handle.readFile('utf8')), slug);
157
+ }
158
+ catch (error) {
159
+ if (error instanceof SyntaxError)
160
+ throw new Error(`Invalid JSON: ${path}`, { cause: error });
161
+ throw error;
162
+ }
163
+ finally {
164
+ await handle.close();
165
+ }
166
+ }
167
+ async function acquireThemeLease(directory) {
168
+ const lease = new ExclusiveFileLease(join(directory, '.praxis-themes.lock'));
169
+ for (let attempt = 0; attempt < 400; attempt += 1) {
170
+ const handle = await lease.tryAcquire();
171
+ if (handle)
172
+ return handle;
173
+ await setTimeout(5);
174
+ }
175
+ throw new Error(`Custom theme write lock timed out: ${directory}`);
176
+ }
177
+ export async function loadTuiCustomThemes(configRoot = configRootPath()) {
178
+ const directory = customThemeDirectory(configRoot);
179
+ let entries;
180
+ try {
181
+ entries = await readdir(directory, { withFileTypes: true });
182
+ }
183
+ catch (error) {
184
+ if (error.code === 'ENOENT')
185
+ return [];
186
+ throw error;
187
+ }
188
+ const themes = [];
189
+ for (const entry of entries) {
190
+ if (!entry.isFile() || !entry.name.endsWith('.json'))
191
+ continue;
192
+ const slug = entry.name.slice(0, -'.json'.length);
193
+ if (!CUSTOM_SLUG.test(slug))
194
+ throw new Error(`Invalid custom theme filename: ${entry.name}`);
195
+ themes.push(await readThemeFile(join(directory, entry.name), slug));
196
+ }
197
+ return themes.sort((left, right) => left.name.localeCompare(right.name));
198
+ }
199
+ function serializedTheme(theme) {
200
+ return `${JSON.stringify({ name: theme.name, base: theme.base, overrides: theme.overrides }, null, 2)}\n`;
201
+ }
202
+ export async function createTuiCustomTheme({ name, base, configRoot = configRootPath(), }) {
203
+ const slug = validateCustomThemeName(name);
204
+ if (!TUI_THEMES.includes(base) ||
205
+ base === 'auto')
206
+ throw new Error(`Invalid custom theme base: ${base}`);
207
+ const directory = customThemeDirectory(configRoot);
208
+ await mkdir(directory, { recursive: true });
209
+ const handle = await acquireThemeLease(directory);
210
+ try {
211
+ const path = join(directory, `${slug}.json`);
212
+ try {
213
+ await readFile(path, 'utf8');
214
+ throw new Error(`A custom theme named ${JSON.stringify(name.trim())} already exists.`);
215
+ }
216
+ catch (error) {
217
+ if (error.code !== 'ENOENT')
218
+ throw error;
219
+ }
220
+ const theme = {
221
+ name: name.trim(),
222
+ slug,
223
+ base,
224
+ overrides: {},
225
+ };
226
+ const committed = await writeFileAtomically(path, serializedTheme(theme), {
227
+ mode: 0o600,
228
+ beforeCommit: async () => {
229
+ try {
230
+ await readFile(path, 'utf8');
231
+ return false;
232
+ }
233
+ catch (error) {
234
+ if (error.code === 'ENOENT')
235
+ return true;
236
+ throw error;
237
+ }
238
+ },
239
+ });
240
+ if (!committed)
241
+ throw new Error(`A custom theme named ${JSON.stringify(name.trim())} already exists.`);
242
+ return theme;
243
+ }
244
+ finally {
245
+ await handle.release();
246
+ }
247
+ }
248
+ export async function updateTuiCustomTheme(theme, token, value, configRoot = configRootPath()) {
249
+ const color = value === undefined ? undefined : validateColor(value);
250
+ const directory = customThemeDirectory(configRoot);
251
+ await mkdir(directory, { recursive: true });
252
+ const handle = await acquireThemeLease(directory);
253
+ try {
254
+ const path = join(directory, `${theme.slug}.json`);
255
+ const current = await readThemeFile(path, theme.slug);
256
+ const overrides = { ...current.overrides };
257
+ if (color === undefined)
258
+ delete overrides[token];
259
+ else
260
+ overrides[token] = color;
261
+ const next = { ...current, overrides };
262
+ if (!(await writeFileAtomically(path, serializedTheme(next))))
263
+ throw new Error(`Unable to update custom theme: ${path}`);
264
+ return next;
265
+ }
266
+ finally {
267
+ await handle.release();
268
+ }
269
+ }
270
+ export async function deleteTuiCustomTheme(theme, configRoot = configRootPath()) {
271
+ const directory = customThemeDirectory(configRoot);
272
+ const handle = await acquireThemeLease(directory);
273
+ try {
274
+ await rm(join(directory, `${theme.slug}.json`), { force: false });
275
+ }
276
+ catch (error) {
277
+ if (error.code !== 'ENOENT')
278
+ throw error;
279
+ }
280
+ finally {
281
+ await handle.release();
282
+ }
283
+ }
284
+ //# sourceMappingURL=custom-themes.js.map
@@ -11,7 +11,9 @@ export type TuiMentionEntry = ({
11
11
  } & TuiFileEntry) | ({
12
12
  kind: 'agent';
13
13
  } & TuiAgentEntry);
14
- export declare function loadTuiFileEntries(cwd: string): Promise<readonly TuiFileEntry[]>;
14
+ export declare function loadTuiFileEntries(cwd: string, options?: {
15
+ respectGitignore?: boolean;
16
+ }): Promise<readonly TuiFileEntry[]>;
15
17
  export declare function filterTuiFileEntries(entries: readonly TuiFileEntry[], query: string): readonly TuiFileEntry[];
16
18
  export declare function filterTuiMentionEntries(files: readonly TuiFileEntry[], agents: readonly TuiAgentEntry[], query: string): readonly TuiMentionEntry[];
17
19
  export declare function fileReferenceAtCursor(input: string, cursor: number): {
@@ -1,10 +1,16 @@
1
1
  import { execFile } from 'node:child_process';
2
2
  import { promisify } from 'node:util';
3
3
  const execFileAsync = promisify(execFile);
4
- export async function loadTuiFileEntries(cwd) {
4
+ export async function loadTuiFileEntries(cwd, options = {}) {
5
5
  let stdout;
6
6
  try {
7
- const result = await execFileAsync('rg', ['--files', '--hidden', '--glob', '!.git/**'], {
7
+ const result = await execFileAsync('rg', [
8
+ '--files',
9
+ '--hidden',
10
+ ...(options.respectGitignore === false ? ['--no-ignore'] : []),
11
+ '--glob',
12
+ '!.git/**',
13
+ ], {
8
14
  cwd,
9
15
  encoding: 'utf8',
10
16
  maxBuffer: 4 * 1024 * 1024,
@@ -0,0 +1,33 @@
1
+ import type { ClaudeJsonResource } from '../../compatibility/claude/shared-resources.js';
2
+ export interface TuiHookEventDefinition {
3
+ name: string;
4
+ description: string;
5
+ detail: readonly string[];
6
+ }
7
+ export interface TuiHookEntry {
8
+ type: string;
9
+ label: string;
10
+ scopeLabel: string;
11
+ path: string;
12
+ }
13
+ export interface TuiHookMatcher {
14
+ matcher: string;
15
+ scope: string;
16
+ scopeLabel: string;
17
+ hooks: readonly TuiHookEntry[];
18
+ }
19
+ export interface TuiHookEvent extends TuiHookEventDefinition {
20
+ matchers: readonly TuiHookMatcher[];
21
+ }
22
+ export interface TuiHookConfiguration {
23
+ events: readonly TuiHookEvent[];
24
+ hookCount: number;
25
+ }
26
+ export declare const TUI_HOOK_MENU: {
27
+ readonly title: "Hooks";
28
+ readonly readOnlyNotice: "This menu is read-only. To add or modify hooks, edit settings.json directly or ask Claude.";
29
+ readonly visibleRows: 5;
30
+ };
31
+ export declare const TUI_HOOK_EVENTS: readonly TuiHookEventDefinition[];
32
+ export declare function projectTuiHooks(settings: readonly ClaudeJsonResource[]): TuiHookConfiguration;
33
+ //# sourceMappingURL=hook-settings.d.ts.map
@@ -0,0 +1,200 @@
1
+ export const TUI_HOOK_MENU = {
2
+ title: 'Hooks',
3
+ readOnlyNotice: 'This menu is read-only. To add or modify hooks, edit settings.json directly or ask Claude.',
4
+ visibleRows: 5,
5
+ };
6
+ export const TUI_HOOK_EVENTS = [
7
+ {
8
+ name: 'PreToolUse',
9
+ description: 'Before tool execution',
10
+ detail: [
11
+ 'Input to command is JSON of tool call arguments.',
12
+ 'Exit code 0 - stdout/stderr not shown',
13
+ 'Exit code 2 - show stderr to model and block tool call',
14
+ 'Other exit codes - show stderr to user only but continue with tool call',
15
+ ],
16
+ },
17
+ {
18
+ name: 'PostToolUse',
19
+ description: 'After tool execution',
20
+ detail: [
21
+ 'Input to command is JSON with fields "inputs" (tool call arguments) and "response" (tool call response).',
22
+ 'Exit code 0 - stdout shown in transcript mode (ctrl+o)',
23
+ 'Exit code 2 - show stderr to model immediately',
24
+ 'Other exit code - show stderr to user only',
25
+ ],
26
+ },
27
+ {
28
+ name: 'PostToolUseFailure',
29
+ description: 'After tool execution fails',
30
+ detail: [],
31
+ },
32
+ {
33
+ name: 'PostToolBatch',
34
+ description: 'After a batch of tool calls resolves',
35
+ detail: [],
36
+ },
37
+ {
38
+ name: 'PermissionDenied',
39
+ description: 'After auto mode classifier denies a tool call',
40
+ detail: [],
41
+ },
42
+ {
43
+ name: 'Notification',
44
+ description: 'When notifications are sent',
45
+ detail: [
46
+ 'Input to command is JSON with notification message and type.',
47
+ 'Exit code 0 - stdout/stderr not shown',
48
+ 'Other exit codes - show stderr to user only',
49
+ ],
50
+ },
51
+ {
52
+ name: 'UserPromptSubmit',
53
+ description: 'When the user submits a prompt',
54
+ detail: [
55
+ 'Input to command is JSON with original user prompt text.',
56
+ 'Exit code 0 - stdout shown to Claude',
57
+ 'Exit code 2 - block processing, erase original prompt, and show stderr to user only',
58
+ 'Other exit codes - show stderr to user only',
59
+ ],
60
+ },
61
+ {
62
+ name: 'UserPromptExpansion',
63
+ description: 'After a user-typed slash command expands into a prompt',
64
+ detail: [],
65
+ },
66
+ {
67
+ name: 'SessionStart',
68
+ description: 'When a new session is started',
69
+ detail: [],
70
+ },
71
+ {
72
+ name: 'Stop',
73
+ description: 'Right before Claude concludes its response',
74
+ detail: [],
75
+ },
76
+ {
77
+ name: 'StopFailure',
78
+ description: 'When the turn ends due to an API error',
79
+ detail: [],
80
+ },
81
+ {
82
+ name: 'SubagentStart',
83
+ description: 'When a subagent (Agent tool call) is started',
84
+ detail: [],
85
+ },
86
+ {
87
+ name: 'SubagentStop',
88
+ description: 'Right before a subagent (Agent tool call) concludes its response',
89
+ detail: [],
90
+ },
91
+ {
92
+ name: 'PreCompact',
93
+ description: 'Before conversation compaction',
94
+ detail: [],
95
+ },
96
+ {
97
+ name: 'PostCompact',
98
+ description: 'After conversation compaction',
99
+ detail: [],
100
+ },
101
+ {
102
+ name: 'SessionEnd',
103
+ description: 'When a session is ending',
104
+ detail: [],
105
+ },
106
+ {
107
+ name: 'PermissionRequest',
108
+ description: 'When a permission dialog is displayed',
109
+ detail: [],
110
+ },
111
+ ];
112
+ function isRecord(value) {
113
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
114
+ }
115
+ function scope(resource) {
116
+ if (resource.plugin)
117
+ return {
118
+ short: 'Plugin',
119
+ long: `Plugin Hooks (${resource.pluginSource ?? resource.pluginName ?? 'plugin'})`,
120
+ };
121
+ if (resource.scope === 'project')
122
+ return { short: 'Project', long: 'Project Settings' };
123
+ if (resource.scope === 'local')
124
+ return { short: 'Local', long: 'Local Settings' };
125
+ return { short: 'User', long: 'User Settings' };
126
+ }
127
+ function hookLabel(hook, type) {
128
+ const statusMessage = hook.statusMessage;
129
+ if (typeof statusMessage === 'string' && statusMessage.length > 0)
130
+ return statusMessage;
131
+ const field = type === 'command' ? 'command' : type === 'http' ? 'url' : 'prompt';
132
+ const label = hook[field];
133
+ if (typeof label === 'string' && label.length > 0)
134
+ return label;
135
+ return type;
136
+ }
137
+ const HOOK_SCOPE_ORDER = {
138
+ Local: 0,
139
+ Project: 1,
140
+ User: 2,
141
+ Plugin: 3,
142
+ };
143
+ export function projectTuiHooks(settings) {
144
+ let hookCount = 0;
145
+ const events = TUI_HOOK_EVENTS.map((definition) => {
146
+ const matchers = [];
147
+ for (const resource of settings) {
148
+ if (!isRecord(resource.value) || !isRecord(resource.value.hooks))
149
+ continue;
150
+ const configured = resource.value.hooks[definition.name];
151
+ if (!Array.isArray(configured))
152
+ continue;
153
+ for (const group of configured) {
154
+ if (!isRecord(group) || !Array.isArray(group.hooks))
155
+ continue;
156
+ const labels = scope(resource);
157
+ const hooks = group.hooks.flatMap((hook) => {
158
+ if (!isRecord(hook))
159
+ return [];
160
+ const type = typeof hook.type === 'string' && hook.type.length > 0
161
+ ? hook.type
162
+ : 'command';
163
+ hookCount += 1;
164
+ return [
165
+ {
166
+ type,
167
+ label: hookLabel(hook, type),
168
+ scopeLabel: labels.long,
169
+ path: resource.path,
170
+ },
171
+ ];
172
+ });
173
+ if (hooks.length === 0)
174
+ continue;
175
+ matchers.push({
176
+ matcher: typeof group.matcher === 'string' && group.matcher.length > 0
177
+ ? group.matcher
178
+ : '(all)',
179
+ scope: labels.short,
180
+ scopeLabel: labels.long,
181
+ hooks,
182
+ });
183
+ }
184
+ }
185
+ matchers.sort((left, right) => {
186
+ const scopeOrder = (HOOK_SCOPE_ORDER[left.scope] ?? Number.MAX_SAFE_INTEGER) -
187
+ (HOOK_SCOPE_ORDER[right.scope] ?? Number.MAX_SAFE_INTEGER);
188
+ if (scopeOrder !== 0)
189
+ return scopeOrder;
190
+ if (left.matcher === '(all)' && right.matcher !== '(all)')
191
+ return -1;
192
+ if (right.matcher === '(all)' && left.matcher !== '(all)')
193
+ return 1;
194
+ return left.matcher.localeCompare(right.matcher);
195
+ });
196
+ return { ...definition, matchers };
197
+ });
198
+ return { events, hookCount };
199
+ }
200
+ //# sourceMappingURL=hook-settings.js.map
@@ -143,7 +143,6 @@ const CLAUDE_2_1_208_KEYBINDINGS = {
143
143
  context: 'ThemePicker',
144
144
  bindings: {
145
145
  'ctrl+t': 'theme:toggleSyntaxHighlighting',
146
- 'ctrl+e': 'theme:editCustom',
147
146
  },
148
147
  },
149
148
  {
@@ -0,0 +1,32 @@
1
+ import type { ClaudeMcpManagement } from '../../mcp/claude-mcp-management.js';
2
+ import type { ClaudeMcpRuntime } from '../../mcp/claude-mcp-tools.js';
3
+ import { type TuiMcpPanelInput, type TuiMcpPanelCommand, type TuiMcpPanelModel, type TuiMcpPanelState } from './mcp-panel-projector.js';
4
+ export type TuiMcpRuntimeController = ClaudeMcpRuntime;
5
+ export interface TuiMcpSessionCommands {
6
+ mcpInspect(): ReturnType<ClaudeMcpRuntime['inspect']>;
7
+ mcpReconnect(name: string): ReturnType<ClaudeMcpRuntime['reconnect']>;
8
+ mcpAuthenticate(name: string): ReturnType<ClaudeMcpRuntime['authenticate']>;
9
+ mcpReload(): ReturnType<ClaudeMcpRuntime['reload']>;
10
+ mcpTools(name: string): ReturnType<ClaudeMcpRuntime['tools']>;
11
+ }
12
+ export declare function mcpRuntimeFromSession(commands: TuiMcpSessionCommands): TuiMcpRuntimeController;
13
+ export interface TuiMcpPanelDispatchResult {
14
+ model: TuiMcpPanelModel;
15
+ state: TuiMcpPanelState;
16
+ closed: boolean;
17
+ error?: string;
18
+ }
19
+ export declare class McpPanelController {
20
+ private readonly cwd;
21
+ private readonly management;
22
+ private readonly runtime;
23
+ constructor(options: {
24
+ cwd: string;
25
+ management: Pick<ClaudeMcpManagement, 'list' | 'disabled' | 'setEnabled'>;
26
+ runtime: ClaudeMcpRuntime;
27
+ });
28
+ open(): Promise<TuiMcpPanelModel>;
29
+ execute(command: TuiMcpPanelCommand): Promise<TuiMcpPanelModel | null>;
30
+ dispatch(model: TuiMcpPanelModel, state: TuiMcpPanelState, input: TuiMcpPanelInput, onOperation?: (command: TuiMcpPanelCommand) => void): Promise<TuiMcpPanelDispatchResult>;
31
+ }
32
+ //# sourceMappingURL=mcp-panel-controller.d.ts.map
@@ -0,0 +1,80 @@
1
+ import { projectTuiMcpPanel, reduceTuiMcpPanelState, } from './mcp-panel-projector.js';
2
+ export function mcpRuntimeFromSession(commands) {
3
+ return {
4
+ inspect: () => commands.mcpInspect(),
5
+ reconnect: (name) => commands.mcpReconnect(name),
6
+ authenticate: (name) => commands.mcpAuthenticate(name),
7
+ reload: () => commands.mcpReload(),
8
+ tools: (name) => commands.mcpTools(name),
9
+ };
10
+ }
11
+ export class McpPanelController {
12
+ cwd;
13
+ management;
14
+ runtime;
15
+ constructor(options) {
16
+ this.cwd = options.cwd;
17
+ this.management = options.management;
18
+ this.runtime = options.runtime;
19
+ }
20
+ async open() {
21
+ const [records, disabledNames, runtime] = await Promise.all([
22
+ this.management.list(),
23
+ this.management.disabled(),
24
+ this.runtime.inspect(),
25
+ ]);
26
+ return projectTuiMcpPanel({
27
+ cwd: this.cwd,
28
+ records,
29
+ disabledNames,
30
+ runtime,
31
+ });
32
+ }
33
+ async execute(command) {
34
+ if (command.type === 'close')
35
+ return null;
36
+ if (command.type === 'reconnect') {
37
+ await this.runtime.reconnect(command.name);
38
+ return this.open();
39
+ }
40
+ if (command.type === 'authenticate') {
41
+ await this.runtime.authenticate(command.name);
42
+ return this.open();
43
+ }
44
+ if (command.type === 'set-enabled') {
45
+ await this.management.setEnabled(command.name, command.scope, command.enabled);
46
+ await this.runtime.reload();
47
+ return this.open();
48
+ }
49
+ const tools = await this.runtime.tools(command.name);
50
+ const model = await this.open();
51
+ return {
52
+ ...model,
53
+ servers: model.servers.map((server) => server.name === command.name ? { ...server, tools } : server),
54
+ };
55
+ }
56
+ async dispatch(model, state, input, onOperation) {
57
+ const transition = reduceTuiMcpPanelState(model, state, input);
58
+ if (!transition.command) {
59
+ return { model, state: transition.state, closed: false };
60
+ }
61
+ onOperation?.(transition.command);
62
+ try {
63
+ const next = await this.execute(transition.command);
64
+ return {
65
+ model: next ?? model,
66
+ state: transition.state,
67
+ closed: next === null,
68
+ };
69
+ }
70
+ catch (error) {
71
+ return {
72
+ model,
73
+ state,
74
+ closed: false,
75
+ error: error instanceof Error ? error.message : String(error),
76
+ };
77
+ }
78
+ }
79
+ }
80
+ //# sourceMappingURL=mcp-panel-controller.js.map