@cuongtran001/kanna 1.63.1 → 1.63.3

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 (200) hide show
  1. package/README.md +5 -9
  2. package/dist/client/assets/{BoardsPage-mVdaRV1l.js → BoardsPage-AckCuswi.js} +1 -1
  3. package/dist/client/assets/BoardsRoutePage-DzKwKy3f.js +1 -0
  4. package/dist/client/assets/ChatPage-DsaH8CTz.js +93 -0
  5. package/dist/client/assets/{CronJobRow-mZDgZOsq.js → CronJobRow-Bx9gRqKW.js} +1 -1
  6. package/dist/client/assets/{CronJobsPage-BQYTTqIG.js → CronJobsPage-v0-2X1oX.js} +1 -1
  7. package/dist/client/assets/{FilePreviewSheet-BG7x42bT.js → FilePreviewSheet-B6SDxSD0.js} +2 -2
  8. package/dist/client/assets/{FlowSurface-Dc6Pe40O.js → FlowSurface-CLC-ZFar.js} +1 -1
  9. package/dist/client/assets/{GenUIBlock-DQ1FAYV2.js → GenUIBlock-CC79Ujro.js} +2 -2
  10. package/dist/client/assets/{KannaSocketProvider-DNcmJfoW.js → KannaSocketProvider-B2sHsWP5.js} +1 -1
  11. package/dist/client/assets/{LocalProjectsPage-DTYGi4cw.js → LocalProjectsPage-DYBkcEAm.js} +1 -1
  12. package/dist/client/assets/SettingsPage-CZqMkMRW.js +9 -0
  13. package/dist/client/assets/{StackBoardsRoutePage-Rg9heAp8.js → StackBoardsRoutePage-Clviz0hX.js} +1 -1
  14. package/dist/client/assets/{ToolCallMessage-CX01LIYK.js → ToolCallMessage-BfNbWGmc.js} +1 -1
  15. package/dist/client/assets/{VChartSurface-CPViuiRJ.js → VChartSurface-CUbxyBo3.js} +1 -1
  16. package/dist/client/assets/{WorkflowsPage-CxJhZK-y.js → WorkflowsPage-rengzb97.js} +1 -1
  17. package/dist/client/assets/{WorkflowsSection-0Qt0VjIb.js → WorkflowsSection-DuXdLsMO.js} +1 -1
  18. package/dist/client/assets/{chart-renderer-DTvjgTUY.js → chart-renderer-D7ukB2wg.js} +1 -1
  19. package/dist/client/assets/{chatSounds-03e825gY.js → chatSounds-BLg2xPDZ.js} +1 -1
  20. package/dist/client/assets/chevron-left-RbFvmeyK.js +1 -0
  21. package/dist/client/assets/{clipboard.adapter-wqfdW5oW.js → clipboard.adapter-CgdNwn-1.js} +1 -1
  22. package/dist/client/assets/{columnStyle-ulMmtOxb.js → columnStyle-CMCF0ds6.js} +1 -1
  23. package/dist/client/assets/{createScopedStore-BdgPJYn5.js → createScopedStore-BrD5NHWx.js} +1 -1
  24. package/dist/client/assets/{dist-DOdGYk49.js → dist-DNSTHlSo.js} +1 -1
  25. package/dist/client/assets/editor-icons-DY4uKeEY.js +1 -0
  26. package/dist/client/assets/{ellipsis-cPOVPqFO.js → ellipsis-OHg0x_x1.js} +1 -1
  27. package/dist/client/assets/{flow-kinds-Ci7hyYYJ.js → flow-kinds-Ki2DP9nP.js} +1 -1
  28. package/dist/client/assets/{folder-O6RMSd2V.js → folder-CnWzWIG5.js} +1 -1
  29. package/dist/client/assets/{formatters-wSVyvDFZ.js → formatters-BGORekd-.js} +1 -1
  30. package/dist/client/assets/{genui-B-C_12wk.js → genui-C9i6j0XZ.js} +1 -1
  31. package/dist/client/assets/{globe-CJeLPEEK.js → globe-BjR1tyE4.js} +1 -1
  32. package/dist/client/assets/{host-0t0cdS1h.js → host-D9tJwZXl.js} +1 -1
  33. package/dist/client/assets/index-CesRxZ0X.js +26 -0
  34. package/dist/client/assets/index-CxDE9VOy.css +1 -0
  35. package/dist/client/assets/{info-CFDoDIFy.js → info-DNYekoE-.js} +1 -1
  36. package/dist/client/assets/{input-CSOou2Ke.js → input-DgW9uRZN.js} +1 -1
  37. package/dist/client/assets/{lexicalToReact-BnB8UCaU.js → lexicalToReact-CZvp9Pgz.js} +3 -3
  38. package/dist/client/assets/{log-DFhobdvS.js → log-DnEvbp3E.js} +1 -1
  39. package/dist/client/assets/{monitor-Dz3yjPhP.js → monitor-qbWfUdBG.js} +1 -1
  40. package/dist/client/assets/{pencil-Bt12fSgV.js → pencil-C965rrpd.js} +1 -1
  41. package/dist/client/assets/{pendingActionsStore-B_FYCH16.js → pendingActionsStore-CxhI19V9.js} +1 -1
  42. package/dist/client/assets/{play-BwOyLfLF.js → play-uofLR7yT.js} +1 -1
  43. package/dist/client/assets/{plus-s5_Ks732.js → plus-D4CI6rj1.js} +1 -1
  44. package/dist/client/assets/{popover-CN6KN-Pv.js → popover-Bc646hKn.js} +1 -1
  45. package/dist/client/assets/{pushClient-Fj8srGZa.js → pushClient-CxnHu9h4.js} +1 -1
  46. package/dist/client/assets/runDetached-DfQXHAaY.js +1 -0
  47. package/dist/client/assets/{segmented-control-Dgl0BpK9.js → segmented-control-CKGX29Kl.js} +1 -1
  48. package/dist/client/assets/{select-PbwoBhm-.js → select-BjeajpVt.js} +1 -1
  49. package/dist/client/assets/{settings-header-button-eDLLqJ7N.js → settings-header-button-BYvHR6Xl.js} +1 -1
  50. package/dist/client/assets/{sidebarPendingActions-BahCtzQw.js → sidebarPendingActions-xgMTnfRY.js} +1 -1
  51. package/dist/client/assets/{square-pen-B85EVyLP.js → square-pen-DmppQdTd.js} +1 -1
  52. package/dist/client/assets/{state-mark-BitecvKK.js → state-mark-C3kEL1hX.js} +1 -1
  53. package/dist/client/assets/{status-pill-BqnLSrIr.js → status-pill-Bo1Nb6HX.js} +1 -1
  54. package/dist/client/assets/{terminal-Cj5AmSMz.js → terminal-DfCF-J4p.js} +1 -1
  55. package/dist/client/assets/{timer.adapter-g84UDqc_.js → timer.adapter-C2RhP4d6.js} +1 -1
  56. package/dist/client/assets/{tools-oiti76TK.js → tools-t5T_3UBg.js} +1 -1
  57. package/dist/client/assets/{triangle-alert-DluPUJcc.js → triangle-alert-CYQhobyY.js} +1 -1
  58. package/dist/client/assets/useAppGlobalState-DUa3pkCF.js +1 -0
  59. package/dist/client/assets/useKannaState-FcieR5qb.js +5 -0
  60. package/dist/client/assets/useTheme-D9sKDPEm.js +1 -0
  61. package/dist/client/index.html +35 -35
  62. package/package.json +2 -2
  63. package/src/server/agent-coordinator-types.ts +0 -6
  64. package/src/server/agent-coordinator.ts +6 -45
  65. package/src/server/agent.compaction.test.ts +1 -13
  66. package/src/server/agent.oauth-account-info.test.ts +0 -3
  67. package/src/server/agent.oauth-release.test.ts +0 -2
  68. package/src/server/agent.oauth-rotation.test.ts +0 -9
  69. package/src/server/agent.oauth-token-share-cap.test.ts +0 -1
  70. package/src/server/agent.openrouter-model.test.ts +0 -2
  71. package/src/server/agent.openrouter-watchdog.test.ts +0 -3
  72. package/src/server/agent.sdk-workflow-register.test.ts +2 -64
  73. package/src/server/agent.test.ts +1 -319
  74. package/src/server/app-settings.test.ts +14 -17
  75. package/src/server/app-settings.ts +22 -37
  76. package/src/server/auto-continue/e2e.test.ts +0 -1
  77. package/src/server/background-task-output-registry.test.ts +1 -1
  78. package/src/server/background-task-output-registry.ts +1 -1
  79. package/src/server/claude-cancel-handler.test.ts +0 -58
  80. package/src/server/claude-cancel-handler.ts +1 -17
  81. package/src/server/claude-harness-stream.test.ts +134 -0
  82. package/src/server/{claude-pty/jsonl-path.test.ts → claude-projects-path.adapter.test.ts} +1 -19
  83. package/src/server/{claude-pty/jsonl-path.adapter.ts → claude-projects-path.adapter.ts} +0 -11
  84. package/src/server/claude-send-command.test.ts +0 -1
  85. package/src/server/claude-session-config-helpers.test.ts +1 -90
  86. package/src/server/claude-session-config-helpers.ts +1 -38
  87. package/src/server/claude-session-error-handler.test.ts +0 -1
  88. package/src/server/claude-session-lifecycle.test.ts +2 -36
  89. package/src/server/claude-session-lifecycle.ts +2 -8
  90. package/src/server/claude-session-runner.test.ts +8 -36
  91. package/src/server/claude-session-runner.ts +1 -26
  92. package/src/server/claude-session-spawner.test.ts +5 -64
  93. package/src/server/claude-session-spawner.ts +49 -115
  94. package/src/server/claude-session-start.test.ts +1 -14
  95. package/src/server/claude-session-start.ts +0 -8
  96. package/src/server/claude-session-state-queries.test.ts +1 -2
  97. package/src/server/claude-session-state.test.ts +0 -1
  98. package/src/server/claude-session-state.ts +0 -4
  99. package/src/server/claude-subagent-wiring.test.ts +2 -68
  100. package/src/server/claude-subagent-wiring.ts +3 -50
  101. package/src/server/claude-turn-starter-types.ts +0 -3
  102. package/src/server/claude-turn-starter.test.ts +0 -28
  103. package/src/server/claude-turn-starter.ts +0 -5
  104. package/src/server/event-store.test.ts +0 -2
  105. package/src/server/events.ts +1 -2
  106. package/src/server/harness-types.ts +1 -2
  107. package/src/server/import-subagent-drill.e2e.test.ts +1 -1
  108. package/src/server/imported-subagents-dir.test.ts +1 -1
  109. package/src/server/imported-subagents-dir.ts +1 -1
  110. package/src/server/kanna-mcp.test.ts +0 -75
  111. package/src/server/kanna-mcp.ts +1 -47
  112. package/src/server/server.test.ts +5 -7
  113. package/src/server/server.ts +2 -18
  114. package/src/server/subagent-orchestrator.test.ts +0 -1
  115. package/src/server/subagent-provider-run.test.ts +48 -10
  116. package/src/server/subagent-provider-run.ts +12 -3
  117. package/src/server/tool-callback.test.ts +1 -1
  118. package/src/server/ws-router-agent-ctrl.test.ts +0 -45
  119. package/src/server/ws-router-agent-ctrl.ts +1 -31
  120. package/src/server/ws-router-broadcast.ts +0 -27
  121. package/src/server/ws-router-defaults.test.ts +2 -3
  122. package/src/server/ws-router-defaults.ts +2 -3
  123. package/src/server/ws-router-envelope.ts +0 -15
  124. package/src/server/ws-router-observability.test.ts +1 -1
  125. package/src/server/ws-router-settings.test.ts +2 -2
  126. package/src/server/ws-router.test.ts +2 -2
  127. package/src/server/ws-router.ts +0 -8
  128. package/src/shared/app-settings-types.ts +9 -20
  129. package/src/shared/claude-api-error-classification.ts +1 -1
  130. package/src/shared/protocol.ts +1 -11
  131. package/dist/client/assets/BoardsRoutePage-Cz6irKOB.js +0 -1
  132. package/dist/client/assets/ChatPage-Di9Mm9dW.js +0 -93
  133. package/dist/client/assets/SettingsPage-1Ka-lzSx.js +0 -9
  134. package/dist/client/assets/chevron-left-BdNUIJTA.js +0 -1
  135. package/dist/client/assets/editor-icons-99dE-E7-.js +0 -1
  136. package/dist/client/assets/index-C-UYaDk6.css +0 -1
  137. package/dist/client/assets/index-GJyusOM5.js +0 -26
  138. package/dist/client/assets/runDetached-AJ-JDygc.js +0 -1
  139. package/dist/client/assets/useAppGlobalState-w8KX_7Yj.js +0 -1
  140. package/dist/client/assets/useKannaState-QABuA8Rf.js +0 -5
  141. package/dist/client/assets/useTheme-E3vVm1KS.js +0 -1
  142. package/src/server/agent.pty-rotation.test.ts +0 -322
  143. package/src/server/claude-pty/auth.test.ts +0 -38
  144. package/src/server/claude-pty/auth.ts +0 -17
  145. package/src/server/claude-pty/claude-session-registry.adapter.ts +0 -68
  146. package/src/server/claude-pty/claude-session-registry.test.ts +0 -149
  147. package/src/server/claude-pty/driver.test.ts +0 -1153
  148. package/src/server/claude-pty/driver.ts +0 -829
  149. package/src/server/claude-pty/env.test.ts +0 -79
  150. package/src/server/claude-pty/env.ts +0 -20
  151. package/src/server/claude-pty/jsonl-to-event.test.ts +0 -882
  152. package/src/server/claude-pty/jsonl-to-event.ts +0 -357
  153. package/src/server/claude-pty/parity-matrix.test.ts +0 -437
  154. package/src/server/claude-pty/pid-registry.adapter.ts +0 -164
  155. package/src/server/claude-pty/pid-registry.test.ts +0 -178
  156. package/src/server/claude-pty/preflight/binary-fingerprint.adapter.ts +0 -20
  157. package/src/server/claude-pty/preflight/binary-fingerprint.test.ts +0 -32
  158. package/src/server/claude-pty/pty-instance-registry.test.ts +0 -208
  159. package/src/server/claude-pty/pty-instance-registry.ts +0 -172
  160. package/src/server/claude-pty/pty-memory-sampler.adapter.test.ts +0 -103
  161. package/src/server/claude-pty/pty-memory-sampler.adapter.ts +0 -86
  162. package/src/server/claude-pty/pty-process.adapter.ts +0 -60
  163. package/src/server/claude-pty/pty-process.test.ts +0 -49
  164. package/src/server/claude-pty/resolve-binary.adapter.ts +0 -106
  165. package/src/server/claude-pty/resolve-binary.test.ts +0 -118
  166. package/src/server/claude-pty/runtime-dir.adapter.ts +0 -19
  167. package/src/server/claude-pty/sandbox/detect.adapter.ts +0 -17
  168. package/src/server/claude-pty/sandbox/detect.test.ts +0 -17
  169. package/src/server/claude-pty/sandbox/platform.test.ts +0 -35
  170. package/src/server/claude-pty/sandbox/platform.ts +0 -27
  171. package/src/server/claude-pty/sandbox/preflight-io.adapter.ts +0 -14
  172. package/src/server/claude-pty/sandbox/preflight.test.ts +0 -69
  173. package/src/server/claude-pty/sandbox/preflight.ts +0 -44
  174. package/src/server/claude-pty/sandbox/profile-linux.adapter.ts +0 -63
  175. package/src/server/claude-pty/sandbox/profile-linux.test.ts +0 -90
  176. package/src/server/claude-pty/sandbox/profile-macos.adapter.ts +0 -72
  177. package/src/server/claude-pty/sandbox/profile-macos.test.ts +0 -68
  178. package/src/server/claude-pty/sandbox/wrap.adapter.ts +0 -58
  179. package/src/server/claude-pty/sandbox/wrap.test.ts +0 -82
  180. package/src/server/claude-pty/settings-writer.adapter.ts +0 -23
  181. package/src/server/claude-pty/settings-writer.test.ts +0 -22
  182. package/src/server/claude-pty/smoke-test-io.adapter.ts +0 -28
  183. package/src/server/claude-pty/smoke-test.test.ts +0 -199
  184. package/src/server/claude-pty/smoke-test.ts +0 -182
  185. package/src/server/claude-pty/tui-control.test.ts +0 -300
  186. package/src/server/claude-pty/tui-control.ts +0 -174
  187. package/src/server/claude-pty/tui-source.adapter.test.ts +0 -374
  188. package/src/server/claude-pty/tui-source.adapter.ts +0 -294
  189. package/src/server/http-server.adapter.test.ts +0 -18
  190. package/src/server/http-server.adapter.ts +0 -39
  191. package/src/server/kanna-mcp-http.test.ts +0 -274
  192. package/src/server/kanna-mcp-http.ts +0 -194
  193. package/src/server/kanna-mcp-tools/ask-user-question.test.ts +0 -108
  194. package/src/server/kanna-mcp-tools/ask-user-question.ts +0 -55
  195. package/src/server/kanna-mcp-tools/exit-plan-mode.test.ts +0 -61
  196. package/src/server/kanna-mcp-tools/exit-plan-mode.ts +0 -49
  197. package/src/server/mcp-zod-compat.adapter.ts +0 -20
  198. package/src/shared/pty-instance.ts +0 -43
  199. /package/src/server/{claude-pty/output-ring.test.ts → output-ring.test.ts} +0 -0
  200. /package/src/server/{claude-pty/output-ring.ts → output-ring.ts} +0 -0
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- <em>Subscription-billing PTY mode, OAuth token pooling, multi-provider chat (Claude + Codex + OpenRouter), subagent orchestration, custom MCP servers, a workflow status panel, durable tool-approval protocol, in-app self-update, and more.</em>
12
+ <em>OAuth token pooling, multi-provider chat (Claude + Codex + OpenRouter), subagent orchestration, custom MCP servers, a workflow status panel, durable tool-approval protocol, in-app self-update, and more.</em>
13
13
  </p>
14
14
 
15
15
  <p align="center">
@@ -41,12 +41,11 @@ Kanna (`@cuongtran001/kanna`) is a clean web UI for the Claude Code and Codex CL
41
41
 
42
42
  **Headline features:**
43
43
 
44
- - **Subscription-billing PTY driver** (`KANNA_CLAUDE_DRIVER=pty`) — runs the `claude` CLI under a pseudo-terminal so Pro/Max plans are charged instead of API rates. Parses the on-disk transcript JSONL as the sole event source, with HarnessEvent parity with the SDK driver, a cached per-spawn smoke-test gate, and failure-mode parity.
45
44
  - **OAuth token pool** — register multiple Claude OAuth tokens; Kanna rotates across them per chat with automatic fallover on rate-limit and an explicit disabled state.
46
45
  - **Multi-provider chat** — switch between Claude, Codex (OpenAI), and OpenRouter from the composer with per-provider model + reasoning-effort controls and Codex fast mode. OpenRouter populates its model picker live from the public catalog (tool-capable models).
47
46
  - **Subagent orchestration** — first-class subagent CRUD, `@agent/` mentions, parallel runs, live activity labels, MCP progress notifications, and `mcp__kanna__delegate_subagent` so the main agent itself can delegate — including **keep-alive multi-turn** sessions (`send_subagent_message` / `close_subagent`) and **background** runs that report back as a fresh turn.
48
- - **Custom MCP servers** — register your own `stdio` / `http` / `sse` / `ws` MCP servers from Settings (with OAuth 2.1 for network transports); they merge into both drivers and their tools surface as `mcp__<name>__<tool>`.
49
- - **Workflow status panel** — read-only per-chat panel surfacing Claude Code's native Workflow tool runs (live status, drill-in progress, token totals) via disk-watch, under both drivers.
47
+ - **Custom MCP servers** — register your own `stdio` / `http` / `sse` / `ws` MCP servers from Settings (with OAuth 2.1 for network transports); they merge into every Claude session and their tools surface as `mcp__<name>__<tool>`.
48
+ - **Workflow status panel** — read-only per-chat panel surfacing Claude Code's native Workflow tool runs (live status, drill-in progress, token totals) via disk-watch.
50
49
  - **Agent self-scheduled wake** — `mcp__kanna__schedule_wakeup` lets the agent re-enter the chat to harvest long-running background work, with a runaway-loop cap.
51
50
  - **Durable tool-approval protocol** (`KANNA_MCP_TOOL_CALLBACKS=1`) — pending `AskUserQuestion` / `ExitPlanMode` / built-in shims survive server restart and replay to the client on reconnect.
52
51
  - **Cloudflare `expose_port` MCP tool** — agent-callable port exposure with always-ask or auto-expose modes, replacing bash-output sniffing.
@@ -82,8 +81,7 @@ That's it. Kanna opens in your browser at [`localhost:3210`](http://localhost:32
82
81
  - **Multi-provider support** — switch between Claude, Codex (OpenAI), and OpenRouter from the chat input, with per-provider model selection, reasoning-effort controls, and Codex fast mode
83
82
  - **OpenRouter** — set an OpenRouter API key in Settings; the model picker populates live from OpenRouter's catalog (tool-capable models), routed through its Anthropic-compatible endpoint
84
83
  - **OAuth token pool** — register multiple Claude OAuth tokens; Kanna rotates across them per chat
85
- - **Subscription-billing PTY driver** — optional `KANNA_CLAUDE_DRIVER=pty` runs the `claude` CLI under a pseudo-terminal so Pro/Max subscription billing is preserved instead of API rates
86
- - **Custom MCP servers** — register `stdio` / `http` / `sse` / `ws` MCP servers from Settings (OAuth 2.1 for network transports); merged into both drivers
84
+ - **Custom MCP servers** — register `stdio` / `http` / `sse` / `ws` MCP servers from Settings (OAuth 2.1 for network transports); merged into every Claude session
87
85
 
88
86
  **Chat & transcript**
89
87
 
@@ -163,7 +161,6 @@ flowchart LR
163
161
  WS --> RM
164
162
  Agent --> ES
165
163
  Agent -.spawn.-> SpA
166
- Agent -.spawn.-> PtyA
167
164
  ES -.fs.-> FsA
168
165
  Diff -.fs+spawn.-> SpA
169
166
  Diff -.fs.-> FsA
@@ -181,7 +178,7 @@ flowchart LR
181
178
  end
182
179
 
183
180
  subgraph External["External processes"]
184
- CC["Claude Agent SDK / claude CLI (PTY)"]
181
+ CC["Claude Agent SDK / claude CLI"]
185
182
  CX["Codex App Server"]
186
183
  FS["Local FS<br/>~/.kanna/data/, project dirs"]
187
184
  end
@@ -399,7 +396,6 @@ src/
399
396
  │ ├── ws-router.ts WebSocket routing & subscriptions
400
397
  │ ├── agent.ts AgentCoordinator (multi-provider turns)
401
398
  │ ├── codex-app-server.ts Codex App Server JSON-RPC client
402
- │ ├── claude-pty/ PTY driver (subscription billing)
403
399
  │ ├── oauth-pool/ Claude OAuth token rotation
404
400
  │ ├── provider-catalog.ts provider/model/effort normalization
405
401
  │ ├── openrouter-models.ts live OpenRouter catalog (tool-capable models)
@@ -1 +1 @@
1
- import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{t}from"./react-DiVRNtpo.js";import{t as n}from"./jsx-runtime-BdxMnOeJ.js";import{c as r,i,m as a,t as o}from"./log-DFhobdvS.js";import{a as s,c,i as l,n as u,r as d,s as f,t as p}from"./pendingActionsStore-B_FYCH16.js";import{t as m}from"./ellipsis-cPOVPqFO.js";import{t as h}from"./plus-s5_Ks732.js";import{t as g}from"./input-CSOou2Ke.js";import{n as _,r as v,t as y}from"./popover-CN6KN-Pv.js";import{o as b,r as x,s as S,t as C}from"./columnStyle-ulMmtOxb.js";var w=e(t(),1),T=[],E=r()(e=>({templates:T,templatesStatus:`loading`,openMenuId:null,picking:!1,renamingId:null,error:null,setTemplates:t=>e({templates:Array.isArray(t)?t:[],templatesStatus:`ready`}),beginTemplatesLoad:()=>e({templatesStatus:`loading`}),failTemplatesLoad:()=>e({templatesStatus:`failed`}),openMenu:t=>e({openMenuId:t}),closeMenu:()=>e({openMenuId:null}),openPicker:()=>e({picking:!0,error:null}),closePicker:()=>e({picking:!1}),startRename:t=>e({renamingId:t,picking:!1,openMenuId:null}),stopRename:()=>e({renamingId:null}),setError:t=>e({error:t})}));function D(e){return e.templates}var O=e(n(),1),k=[`board.update`,`board.duplicate`,`board.saveAsTemplate`,`board.archive`];function A(e){return l(t=>k.some(n=>t.inFlight[p(n,e)]===!0))}function j({ownerKind:e,ownerId:t,ownerName:n,socket:r,onOpenBoard:c}){let l=x(e,t),f=S(b(l)),m=E(D),g=E(e=>e.picking),_=E(e=>e.renamingId),v=E(e=>e.error),y=E(e=>e.templatesStatus),C=p(`board.create`,l),T=d(C),{openPicker:k,closePicker:A,startRename:j,stopRename:N,setError:P,setTemplates:I}=E.getState();(0,w.useEffect)(()=>r.subscribe({type:`boards`,ownerKind:e,ownerId:t},e=>{S.getState().setBoards(x(e.ownerKind,e.ownerId),e.boards)}),[e,t,r]),(0,w.useEffect)(()=>{let e=!1,t=E.getState();return t.templatesStatus!==`ready`&&t.beginTemplatesLoad(),r.command({type:`board.templates.list`}).then(t=>{e||I(t)},a(t=>{o.error(i,`board.templates.list failed`,t),e||E.getState().failTemplatesLoad()})),()=>{e=!0}},[r,I]);let L=(0,w.useCallback)(async e=>{try{return await r.command(e),P(null),!0}catch(e){return P(e instanceof Error?e.message:`That did not work.`),!1}},[r,P]),R=(0,w.useCallback)(n=>{u(C,async()=>{await L({type:`board.create`,ownerKind:e,ownerId:t,title:n?n.name:`Untitled board`,templateId:n?.id??null})&&A()})},[A,C,e,t,L]),z=(0,w.useCallback)((e,t)=>{N();let n=t.trim();n!==``&&u(p(`board.update`,e),()=>L({type:`board.update`,boardId:e,title:n}))},[L,N]),B=g||f.length===0;return(0,O.jsxs)(`div`,{className:`flex min-h-0 min-w-0 flex-1 flex-col bg-background`,children:[(0,O.jsxs)(`header`,{className:`flex items-end justify-between gap-4 border-b border-border px-6 py-4`,children:[(0,O.jsxs)(`div`,{className:`min-w-0`,children:[(0,O.jsx)(`h1`,{className:`text-lg font-medium leading-tight tracking-[-0.01em] text-foreground`,children:`Boards`}),(0,O.jsxs)(`p`,{className:`truncate text-13 text-muted-foreground`,children:[n,f.length>0?(0,O.jsxs)(`span`,{className:`tabular-nums`,children:[` · `,f.length,` boards`]}):null]})]}),f.length>0?(0,O.jsxs)(s,{size:`sm`,onClick:k,pending:T,children:[(0,O.jsx)(h,{className:`size-3.5`}),`New board`]}):null]}),v?(0,O.jsx)(`p`,{className:`border-b border-border px-6 py-2 text-13 text-destructive-text`,children:v}):null,(0,O.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto`,children:[B?(0,O.jsx)(F,{templates:m,templatesStatus:y,creating:T,firstRun:f.length===0,onPick:R,onCancel:A}):null,f.length>0?(0,O.jsx)(`ul`,{className:`px-4 py-1`,children:f.map(e=>(0,O.jsx)(M,{board:e,renaming:_===e.id,onOpen:c,onStartRename:j,onRename:z,onCancelRename:N,onCommand:L},e.id))}):null]})]})}function M({board:e,renaming:t,onOpen:n,onStartRename:r,onRename:i,onCancelRename:a,onCommand:o}){let s=A(e.id),c=(0,w.useCallback)(()=>n(e.id),[e.id,n]),l=(0,w.useCallback)(t=>{t.key===`Enter`&&i(e.id,t.currentTarget.value),t.key===`Escape`&&a()},[e.id,a,i]),u=(0,w.useCallback)(t=>i(e.id,t.currentTarget.value),[e.id,i]);return(0,O.jsxs)(`li`,{"aria-busy":s||void 0,className:`group grid grid-cols-[1fr_auto_auto] items-center gap-5 border-b border-border px-3 py-3 last:border-b-0 hover:bg-secondary`,children:[(0,O.jsx)(`div`,{className:`min-w-0`,children:t?(0,O.jsx)(g,{autoFocus:!0,defaultValue:e.title,onKeyDown:l,onBlur:u,className:`h-7 max-w-sm`,"aria-label":`Board name`}):(0,O.jsxs)(`button`,{type:`button`,onClick:c,className:`block w-full text-left`,children:[(0,O.jsx)(`span`,{className:`block truncate text-15 font-semibold tracking-[-0.005em] text-foreground`,children:e.title}),e.description?(0,O.jsx)(`span`,{className:`mt-0.5 block truncate text-13 text-muted-foreground`,children:e.description}):null]})}),(0,O.jsxs)(`div`,{className:`flex items-center gap-4 text-xs text-muted-foreground`,children:[(0,O.jsxs)(`span`,{children:[(0,O.jsx)(`b`,{className:`font-medium tabular-nums text-foreground`,children:e.columnCount}),` columns`]}),(0,O.jsxs)(`span`,{children:[(0,O.jsx)(`b`,{className:`font-medium tabular-nums text-foreground`,children:e.cardCount}),` cards`]})]}),(0,O.jsx)(N,{board:e,pending:s,onStartRename:r,onCommand:o})]})}function N({board:e,pending:t,onStartRename:n,onCommand:r}){let i=E(t=>t.openMenuId===e.id),{openMenu:a,closeMenu:o}=E.getState(),s=(0,w.useCallback)(t=>{t?a(e.id):o()},[e.id,o,a]),l=(0,w.useCallback)(()=>{o(),n(e.id)},[e.id,o,n]),d=(0,w.useCallback)(()=>{o(),u(p(`board.duplicate`,e.id),()=>r({type:`board.duplicate`,boardId:e.id,title:`${e.title} copy`}))},[e.id,e.title,o,r]),h=(0,w.useCallback)(()=>{o(),u(p(`board.saveAsTemplate`,e.id),()=>r({type:`board.saveAsTemplate`,boardId:e.id,name:e.title}))},[e.id,e.title,o,r]),g=(0,w.useCallback)(()=>{o(),u(p(`board.archive`,e.id),()=>r({type:`board.archive`,boardId:e.id}))},[e.id,o,r]);return(0,O.jsxs)(y,{open:i,onOpenChange:s,children:[(0,O.jsx)(v,{asChild:!0,children:(0,O.jsx)(`button`,{type:`button`,"aria-label":`Actions for ${e.title}`,disabled:t,"aria-busy":t||void 0,className:c(`rounded-md px-1.5 py-1 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100 data-[state=open]:opacity-100`,t&&`opacity-100`),children:t?(0,O.jsx)(f,{className:`size-4`}):(0,O.jsx)(m,{className:`size-4`})})}),(0,O.jsxs)(_,{align:`end`,className:`w-56 p-1`,children:[(0,O.jsx)(P,{onClick:l,children:`Rename`}),(0,O.jsx)(P,{onClick:d,children:`Duplicate structure`}),(0,O.jsx)(P,{onClick:h,children:`Save as template`}),(0,O.jsx)(`div`,{className:`my-1 h-px bg-border`}),(0,O.jsx)(P,{onClick:g,tone:`destructive`,children:`Archive`})]})]})}function P({onClick:e,children:t,tone:n}){return(0,O.jsx)(`button`,{type:`button`,onClick:e,className:c(`flex w-full items-center rounded-sm px-2 py-1.5 text-left text-xs font-medium hover:bg-secondary`,n===`destructive`&&`text-destructive-text`),children:t})}function F({templates:e,templatesStatus:t,creating:n,firstRun:r,onPick:i,onCancel:a}){let o=(0,w.useCallback)(()=>i(null),[i]);return(0,O.jsxs)(`div`,{className:`px-6 py-8`,children:[r?(0,O.jsxs)(O.Fragment,{children:[(0,O.jsx)(`h2`,{className:`text-15 font-semibold text-foreground`,children:`No boards yet.`}),(0,O.jsx)(`p`,{className:`mt-1 max-w-[58ch] text-sm text-muted-foreground`,children:`A board turns issues into work your agents can pick up. Start from a shape, or import an existing tracker.`})]}):(0,O.jsx)(`h2`,{className:`text-15 font-semibold text-foreground`,children:`Start from a shape`}),(0,O.jsxs)(`div`,{className:`mt-4 max-w-xl rounded-lg border border-border`,"aria-busy":n||void 0,children:[e.map(e=>(0,O.jsx)(I,{template:e,disabled:n,onPick:i},e.id)),t===`loading`?(0,O.jsxs)(`p`,{role:`status`,className:`flex items-center gap-2 px-3.5 py-2.5 text-xs text-muted-foreground`,children:[(0,O.jsx)(f,{}),`Loading templates…`]}):null,t===`failed`?(0,O.jsx)(`p`,{className:`px-3.5 py-2.5 text-xs text-muted-foreground`,children:`Couldn't load templates.`}):null,(0,O.jsx)(`button`,{type:`button`,onClick:o,disabled:n,className:`flex w-full items-center border-t border-border px-3.5 py-2.5 text-left hover:bg-secondary disabled:pointer-events-none disabled:opacity-60`,children:(0,O.jsxs)(`span`,{children:[(0,O.jsx)(`span`,{className:`block text-sm font-medium text-foreground`,children:`Empty board`}),(0,O.jsx)(`span`,{className:`block text-xs text-muted-foreground`,children:`Name your own columns`})]})})]}),n?(0,O.jsxs)(`p`,{role:`status`,className:`mt-3 flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,O.jsx)(f,{}),`Creating board…`]}):null,r?null:(0,O.jsx)(s,{variant:`ghost`,size:`sm`,className:`mt-3`,onClick:a,children:`Cancel`})]})}function I({template:e,disabled:t,onPick:n}){let r=(0,w.useCallback)(()=>n(e),[n,e]),i=e.definition.columns;return(0,O.jsxs)(`button`,{type:`button`,onClick:r,disabled:t,className:`flex w-full items-center gap-3 border-b border-border px-3.5 py-2.5 text-left last:border-b-0 hover:bg-secondary disabled:pointer-events-none disabled:opacity-60`,children:[(0,O.jsxs)(`span`,{className:`min-w-0`,children:[(0,O.jsx)(`span`,{className:`block text-sm font-medium text-foreground`,children:e.name}),(0,O.jsx)(`span`,{className:`block truncate text-xs text-muted-foreground`,children:i.map(e=>e.title).join(` · `)})]}),(0,O.jsx)(`span`,{"aria-hidden":!0,className:`ml-auto flex shrink-0 gap-1`,children:i.map((t,n)=>(0,O.jsx)(`span`,{className:c(`size-1.5 rounded-full`,t.colorToken?C[t.colorToken]:`bg-muted-icon`)},`${e.id}-${String(n)}`))})]})}export{j as t};
1
+ import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{t}from"./react-DiVRNtpo.js";import{t as n}from"./jsx-runtime-BdxMnOeJ.js";import{c as r,i,m as a,t as o}from"./log-DnEvbp3E.js";import{a as s,c,i as l,n as u,r as d,s as f,t as p}from"./pendingActionsStore-CxhI19V9.js";import{t as m}from"./ellipsis-OHg0x_x1.js";import{t as h}from"./plus-D4CI6rj1.js";import{t as g}from"./input-DgW9uRZN.js";import{n as _,r as v,t as y}from"./popover-Bc646hKn.js";import{o as b,r as x,s as S,t as C}from"./columnStyle-CMCF0ds6.js";var w=e(t(),1),T=[],E=r()(e=>({templates:T,templatesStatus:`loading`,openMenuId:null,picking:!1,renamingId:null,error:null,setTemplates:t=>e({templates:Array.isArray(t)?t:[],templatesStatus:`ready`}),beginTemplatesLoad:()=>e({templatesStatus:`loading`}),failTemplatesLoad:()=>e({templatesStatus:`failed`}),openMenu:t=>e({openMenuId:t}),closeMenu:()=>e({openMenuId:null}),openPicker:()=>e({picking:!0,error:null}),closePicker:()=>e({picking:!1}),startRename:t=>e({renamingId:t,picking:!1,openMenuId:null}),stopRename:()=>e({renamingId:null}),setError:t=>e({error:t})}));function D(e){return e.templates}var O=e(n(),1),k=[`board.update`,`board.duplicate`,`board.saveAsTemplate`,`board.archive`];function A(e){return l(t=>k.some(n=>t.inFlight[p(n,e)]===!0))}function j({ownerKind:e,ownerId:t,ownerName:n,socket:r,onOpenBoard:c}){let l=x(e,t),f=S(b(l)),m=E(D),g=E(e=>e.picking),_=E(e=>e.renamingId),v=E(e=>e.error),y=E(e=>e.templatesStatus),C=p(`board.create`,l),T=d(C),{openPicker:k,closePicker:A,startRename:j,stopRename:N,setError:P,setTemplates:I}=E.getState();(0,w.useEffect)(()=>r.subscribe({type:`boards`,ownerKind:e,ownerId:t},e=>{S.getState().setBoards(x(e.ownerKind,e.ownerId),e.boards)}),[e,t,r]),(0,w.useEffect)(()=>{let e=!1,t=E.getState();return t.templatesStatus!==`ready`&&t.beginTemplatesLoad(),r.command({type:`board.templates.list`}).then(t=>{e||I(t)},a(t=>{o.error(i,`board.templates.list failed`,t),e||E.getState().failTemplatesLoad()})),()=>{e=!0}},[r,I]);let L=(0,w.useCallback)(async e=>{try{return await r.command(e),P(null),!0}catch(e){return P(e instanceof Error?e.message:`That did not work.`),!1}},[r,P]),R=(0,w.useCallback)(n=>{u(C,async()=>{await L({type:`board.create`,ownerKind:e,ownerId:t,title:n?n.name:`Untitled board`,templateId:n?.id??null})&&A()})},[A,C,e,t,L]),z=(0,w.useCallback)((e,t)=>{N();let n=t.trim();n!==``&&u(p(`board.update`,e),()=>L({type:`board.update`,boardId:e,title:n}))},[L,N]),B=g||f.length===0;return(0,O.jsxs)(`div`,{className:`flex min-h-0 min-w-0 flex-1 flex-col bg-background`,children:[(0,O.jsxs)(`header`,{className:`flex items-end justify-between gap-4 border-b border-border px-6 py-4`,children:[(0,O.jsxs)(`div`,{className:`min-w-0`,children:[(0,O.jsx)(`h1`,{className:`text-lg font-medium leading-tight tracking-[-0.01em] text-foreground`,children:`Boards`}),(0,O.jsxs)(`p`,{className:`truncate text-13 text-muted-foreground`,children:[n,f.length>0?(0,O.jsxs)(`span`,{className:`tabular-nums`,children:[` · `,f.length,` boards`]}):null]})]}),f.length>0?(0,O.jsxs)(s,{size:`sm`,onClick:k,pending:T,children:[(0,O.jsx)(h,{className:`size-3.5`}),`New board`]}):null]}),v?(0,O.jsx)(`p`,{className:`border-b border-border px-6 py-2 text-13 text-destructive-text`,children:v}):null,(0,O.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto`,children:[B?(0,O.jsx)(F,{templates:m,templatesStatus:y,creating:T,firstRun:f.length===0,onPick:R,onCancel:A}):null,f.length>0?(0,O.jsx)(`ul`,{className:`px-4 py-1`,children:f.map(e=>(0,O.jsx)(M,{board:e,renaming:_===e.id,onOpen:c,onStartRename:j,onRename:z,onCancelRename:N,onCommand:L},e.id))}):null]})]})}function M({board:e,renaming:t,onOpen:n,onStartRename:r,onRename:i,onCancelRename:a,onCommand:o}){let s=A(e.id),c=(0,w.useCallback)(()=>n(e.id),[e.id,n]),l=(0,w.useCallback)(t=>{t.key===`Enter`&&i(e.id,t.currentTarget.value),t.key===`Escape`&&a()},[e.id,a,i]),u=(0,w.useCallback)(t=>i(e.id,t.currentTarget.value),[e.id,i]);return(0,O.jsxs)(`li`,{"aria-busy":s||void 0,className:`group grid grid-cols-[1fr_auto_auto] items-center gap-5 border-b border-border px-3 py-3 last:border-b-0 hover:bg-secondary`,children:[(0,O.jsx)(`div`,{className:`min-w-0`,children:t?(0,O.jsx)(g,{autoFocus:!0,defaultValue:e.title,onKeyDown:l,onBlur:u,className:`h-7 max-w-sm`,"aria-label":`Board name`}):(0,O.jsxs)(`button`,{type:`button`,onClick:c,className:`block w-full text-left`,children:[(0,O.jsx)(`span`,{className:`block truncate text-15 font-semibold tracking-[-0.005em] text-foreground`,children:e.title}),e.description?(0,O.jsx)(`span`,{className:`mt-0.5 block truncate text-13 text-muted-foreground`,children:e.description}):null]})}),(0,O.jsxs)(`div`,{className:`flex items-center gap-4 text-xs text-muted-foreground`,children:[(0,O.jsxs)(`span`,{children:[(0,O.jsx)(`b`,{className:`font-medium tabular-nums text-foreground`,children:e.columnCount}),` columns`]}),(0,O.jsxs)(`span`,{children:[(0,O.jsx)(`b`,{className:`font-medium tabular-nums text-foreground`,children:e.cardCount}),` cards`]})]}),(0,O.jsx)(N,{board:e,pending:s,onStartRename:r,onCommand:o})]})}function N({board:e,pending:t,onStartRename:n,onCommand:r}){let i=E(t=>t.openMenuId===e.id),{openMenu:a,closeMenu:o}=E.getState(),s=(0,w.useCallback)(t=>{t?a(e.id):o()},[e.id,o,a]),l=(0,w.useCallback)(()=>{o(),n(e.id)},[e.id,o,n]),d=(0,w.useCallback)(()=>{o(),u(p(`board.duplicate`,e.id),()=>r({type:`board.duplicate`,boardId:e.id,title:`${e.title} copy`}))},[e.id,e.title,o,r]),h=(0,w.useCallback)(()=>{o(),u(p(`board.saveAsTemplate`,e.id),()=>r({type:`board.saveAsTemplate`,boardId:e.id,name:e.title}))},[e.id,e.title,o,r]),g=(0,w.useCallback)(()=>{o(),u(p(`board.archive`,e.id),()=>r({type:`board.archive`,boardId:e.id}))},[e.id,o,r]);return(0,O.jsxs)(y,{open:i,onOpenChange:s,children:[(0,O.jsx)(v,{asChild:!0,children:(0,O.jsx)(`button`,{type:`button`,"aria-label":`Actions for ${e.title}`,disabled:t,"aria-busy":t||void 0,className:c(`rounded-md px-1.5 py-1 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100 data-[state=open]:opacity-100`,t&&`opacity-100`),children:t?(0,O.jsx)(f,{className:`size-4`}):(0,O.jsx)(m,{className:`size-4`})})}),(0,O.jsxs)(_,{align:`end`,className:`w-56 p-1`,children:[(0,O.jsx)(P,{onClick:l,children:`Rename`}),(0,O.jsx)(P,{onClick:d,children:`Duplicate structure`}),(0,O.jsx)(P,{onClick:h,children:`Save as template`}),(0,O.jsx)(`div`,{className:`my-1 h-px bg-border`}),(0,O.jsx)(P,{onClick:g,tone:`destructive`,children:`Archive`})]})]})}function P({onClick:e,children:t,tone:n}){return(0,O.jsx)(`button`,{type:`button`,onClick:e,className:c(`flex w-full items-center rounded-sm px-2 py-1.5 text-left text-xs font-medium hover:bg-secondary`,n===`destructive`&&`text-destructive-text`),children:t})}function F({templates:e,templatesStatus:t,creating:n,firstRun:r,onPick:i,onCancel:a}){let o=(0,w.useCallback)(()=>i(null),[i]);return(0,O.jsxs)(`div`,{className:`px-6 py-8`,children:[r?(0,O.jsxs)(O.Fragment,{children:[(0,O.jsx)(`h2`,{className:`text-15 font-semibold text-foreground`,children:`No boards yet.`}),(0,O.jsx)(`p`,{className:`mt-1 max-w-[58ch] text-sm text-muted-foreground`,children:`A board turns issues into work your agents can pick up. Start from a shape, or import an existing tracker.`})]}):(0,O.jsx)(`h2`,{className:`text-15 font-semibold text-foreground`,children:`Start from a shape`}),(0,O.jsxs)(`div`,{className:`mt-4 max-w-xl rounded-lg border border-border`,"aria-busy":n||void 0,children:[e.map(e=>(0,O.jsx)(I,{template:e,disabled:n,onPick:i},e.id)),t===`loading`?(0,O.jsxs)(`p`,{role:`status`,className:`flex items-center gap-2 px-3.5 py-2.5 text-xs text-muted-foreground`,children:[(0,O.jsx)(f,{}),`Loading templates…`]}):null,t===`failed`?(0,O.jsx)(`p`,{className:`px-3.5 py-2.5 text-xs text-muted-foreground`,children:`Couldn't load templates.`}):null,(0,O.jsx)(`button`,{type:`button`,onClick:o,disabled:n,className:`flex w-full items-center border-t border-border px-3.5 py-2.5 text-left hover:bg-secondary disabled:pointer-events-none disabled:opacity-60`,children:(0,O.jsxs)(`span`,{children:[(0,O.jsx)(`span`,{className:`block text-sm font-medium text-foreground`,children:`Empty board`}),(0,O.jsx)(`span`,{className:`block text-xs text-muted-foreground`,children:`Name your own columns`})]})})]}),n?(0,O.jsxs)(`p`,{role:`status`,className:`mt-3 flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,O.jsx)(f,{}),`Creating board…`]}):null,r?null:(0,O.jsx)(s,{variant:`ghost`,size:`sm`,className:`mt-3`,onClick:a,children:`Cancel`})]})}function I({template:e,disabled:t,onPick:n}){let r=(0,w.useCallback)(()=>n(e),[n,e]),i=e.definition.columns;return(0,O.jsxs)(`button`,{type:`button`,onClick:r,disabled:t,className:`flex w-full items-center gap-3 border-b border-border px-3.5 py-2.5 text-left last:border-b-0 hover:bg-secondary disabled:pointer-events-none disabled:opacity-60`,children:[(0,O.jsxs)(`span`,{className:`min-w-0`,children:[(0,O.jsx)(`span`,{className:`block text-sm font-medium text-foreground`,children:e.name}),(0,O.jsx)(`span`,{className:`block truncate text-xs text-muted-foreground`,children:i.map(e=>e.title).join(` · `)})]}),(0,O.jsx)(`span`,{"aria-hidden":!0,className:`ml-auto flex shrink-0 gap-1`,children:i.map((t,n)=>(0,O.jsx)(`span`,{className:c(`size-1.5 rounded-full`,t.colorToken?C[t.colorToken]:`bg-muted-icon`)},`${e.id}-${String(n)}`))})]})}export{j as t};
@@ -0,0 +1 @@
1
+ import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{t}from"./react-DiVRNtpo.js";import{c as n,l as r,u as i}from"./chunk-OB3PAWPO-mARpRU1A.js";import{t as a}from"./jsx-runtime-BdxMnOeJ.js";import{a as o}from"./formatters-BGORekd-.js";import{t as s}from"./BoardsPage-AckCuswi.js";var c=e(t(),1),l=e(a(),1);function u(){let e=r(),t=n(),{projectId:a=``}=i(),u=[...e.sidebarData.starredProjectGroups,...e.sidebarData.projectGroups].find(e=>e.groupKey===a),d=u?o(u.localPath):`Project`,f=(0,c.useCallback)(e=>{t(`/boards/${a}/${e}`)},[t,a]);return(0,l.jsx)(`div`,{className:`relative flex min-h-0 min-w-0 flex-1 flex-col`,children:(0,l.jsx)(s,{ownerKind:`project`,ownerId:a,ownerName:d,socket:e.socket,onOpenBoard:f})})}export{u as BoardsRoutePage};