claude-mux 0.26.2 → 0.26.4

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 (157) hide show
  1. package/dist/server/ws-handlers.d.ts.map +1 -1
  2. package/dist/server/ws-handlers.js +37 -6
  3. package/dist/server/ws-handlers.js.map +1 -1
  4. package/dist/tmux/pane.d.ts +13 -3
  5. package/dist/tmux/pane.d.ts.map +1 -1
  6. package/dist/tmux/pane.js +113 -36
  7. package/dist/tmux/pane.js.map +1 -1
  8. package/dist/transcript/context-peek.d.ts +18 -0
  9. package/dist/transcript/context-peek.d.ts.map +1 -1
  10. package/dist/transcript/context-peek.js +59 -12
  11. package/dist/transcript/context-peek.js.map +1 -1
  12. package/dist/types/ws-messages.d.ts +6 -0
  13. package/dist/types/ws-messages.d.ts.map +1 -1
  14. package/dist/types/ws-messages.js +2 -0
  15. package/dist/types/ws-messages.js.map +1 -1
  16. package/dist/utils/version.d.ts +1 -1
  17. package/dist/utils/version.js +1 -1
  18. package/dist/web/client/_app/immutable/assets/0.CiLJk_Xe.css +1 -0
  19. package/{web/.svelte-kit/adapter-bun/_app/immutable/assets/_page.XJ3XhAQU.css → dist/web/client/_app/immutable/assets/3.DIECCPxi.css} +1 -1
  20. package/dist/web/client/_app/immutable/chunks/Bjgls5C2.js +2 -0
  21. package/{web/.svelte-kit/output/client/_app/immutable/chunks/Cotx9uI_.js → dist/web/client/_app/immutable/chunks/C8V5fK-3.js} +1 -1
  22. package/dist/web/client/_app/immutable/chunks/DnC9WjQh.js +57 -0
  23. package/dist/web/client/_app/immutable/chunks/MhGpinwS.js +1 -0
  24. package/dist/web/client/_app/immutable/chunks/cJslalWy.js +1 -0
  25. package/dist/web/client/_app/immutable/entry/{app.DXHW0aPL.js → app.tijMyuHe.js} +2 -2
  26. package/dist/web/client/_app/immutable/entry/start.BjUUmuae.js +1 -0
  27. package/dist/web/client/_app/immutable/nodes/{0.DAnv2asW.js → 0.Dh-WcEW1.js} +1 -1
  28. package/dist/web/client/_app/immutable/nodes/{1.CU8f4oNB.js → 1.haoM4e9N.js} +1 -1
  29. package/dist/web/client/_app/immutable/nodes/{2.BYpvCgtu.js → 2.DtC9KdX8.js} +1 -1
  30. package/dist/web/client/_app/immutable/nodes/3.FZTTKJCk.js +168 -0
  31. package/dist/web/client/_app/version.json +1 -1
  32. package/dist/web/server/chunks/{0-C-AAPmon.js → 0-Cw5iP0WY.js} +9 -9
  33. package/dist/web/server/chunks/{0-C-AAPmon.js.map → 0-Cw5iP0WY.js.map} +1 -1
  34. package/dist/web/server/chunks/{1-T_dogl8W.js → 1-CR_g4jt5.js} +3 -3
  35. package/dist/web/server/chunks/{1-T_dogl8W.js.map → 1-CR_g4jt5.js.map} +1 -1
  36. package/dist/web/server/chunks/{2-FlchE_4u.js → 2-Cy0TJi3N.js} +7 -7
  37. package/dist/web/server/chunks/{2-FlchE_4u.js.map → 2-Cy0TJi3N.js.map} +1 -1
  38. package/dist/web/server/chunks/{3-U2bTntXU.js → 3-D9Ui86YT.js} +7 -7
  39. package/dist/web/server/chunks/{3-U2bTntXU.js.map → 3-D9Ui86YT.js.map} +1 -1
  40. package/dist/web/server/chunks/{_layout.svelte-Ddn9Wu-V.js → _layout.svelte-DZ2sqwz3.js} +4 -4
  41. package/dist/web/server/chunks/{_layout.svelte-Ddn9Wu-V.js.map → _layout.svelte-DZ2sqwz3.js.map} +1 -1
  42. package/dist/web/server/chunks/{_page.svelte-_F3qltju.js → _page.svelte--yq9E8Jb.js} +2 -2
  43. package/dist/web/server/chunks/{_page.svelte-_F3qltju.js.map → _page.svelte--yq9E8Jb.js.map} +1 -1
  44. package/dist/web/server/chunks/{_server.ts-CNU4yPZZ.js → _server.ts-BCCIAioG.js} +4 -2
  45. package/dist/web/server/chunks/_server.ts-BCCIAioG.js.map +1 -0
  46. package/dist/web/server/chunks/{_server.ts-CtsPyICr.js → _server.ts-BMZtxwLP.js} +2 -2
  47. package/dist/web/server/chunks/{_server.ts-CtsPyICr.js.map → _server.ts-BMZtxwLP.js.map} +1 -1
  48. package/dist/web/server/chunks/{_server.ts-BBrtrcEt.js → _server.ts-CONr9rjv.js} +2 -2
  49. package/dist/web/server/chunks/{_server.ts-BBrtrcEt.js.map → _server.ts-CONr9rjv.js.map} +1 -1
  50. package/dist/web/server/chunks/{_server.ts-fnuGtMqr.js → _server.ts-CSKVHlMn.js} +3 -3
  51. package/dist/web/server/chunks/{_server.ts-fnuGtMqr.js.map → _server.ts-CSKVHlMn.js.map} +1 -1
  52. package/dist/web/server/chunks/{_server.ts-Df32fD_Q.js → _server.ts-D1PwUVXn.js} +2 -2
  53. package/dist/web/server/chunks/{_server.ts-Df32fD_Q.js.map → _server.ts-D1PwUVXn.js.map} +1 -1
  54. package/dist/web/server/chunks/{_server.ts-C00ejke7.js → _server.ts-D4xa8gs1.js} +2 -2
  55. package/dist/web/server/chunks/{_server.ts-C00ejke7.js.map → _server.ts-D4xa8gs1.js.map} +1 -1
  56. package/dist/web/server/chunks/{_server.ts-C6MJsvPN.js → _server.ts-DxjUBscT.js} +3 -3
  57. package/dist/web/server/chunks/{_server.ts-C6MJsvPN.js.map → _server.ts-DxjUBscT.js.map} +1 -1
  58. package/dist/web/server/chunks/{button-C1GVS_oY.js → button-BxVvCjdl.js} +24 -4
  59. package/dist/web/server/chunks/{button-C1GVS_oY.js.map → button-BxVvCjdl.js.map} +1 -1
  60. package/dist/web/server/chunks/{hooks.server-DG_lyHkY.js → hooks.server-B8dJh24b.js} +3 -3
  61. package/dist/web/server/chunks/{hooks.server-DG_lyHkY.js.map → hooks.server-B8dJh24b.js.map} +1 -1
  62. package/dist/web/server/chunks/{ws-handlers-BQ2RtlNl.js → ws-handlers-fSFiSfwn.js} +150 -43
  63. package/dist/web/server/chunks/ws-handlers-fSFiSfwn.js.map +1 -0
  64. package/dist/web/server/chunks/{ws-managers-DLQiiQnX.js → ws-managers-Cv1gfcBO.js} +2 -2
  65. package/dist/web/server/chunks/{ws-managers-DLQiiQnX.js.map → ws-managers-Cv1gfcBO.js.map} +1 -1
  66. package/dist/web/server/index.js +2 -2
  67. package/dist/web/server/index.js.map +1 -1
  68. package/dist/web/server/manifest.js +17 -17
  69. package/dist/web/server/manifest.js.map +1 -1
  70. package/package.json +1 -1
  71. package/src/server/ws-handlers.ts +35 -6
  72. package/src/tmux/pane.ts +124 -33
  73. package/src/transcript/context-peek.ts +71 -13
  74. package/src/types/ws-messages.ts +2 -0
  75. package/src/utils/version.ts +1 -1
  76. package/tests/tmux/activity-line.test.ts +47 -0
  77. package/tests/tmux/prompt-options.test.ts +49 -4
  78. package/tests/transcript/title-peek.test.ts +54 -0
  79. package/web/.svelte-kit/adapter-bun/.vite/manifest.json +4 -8
  80. package/web/.svelte-kit/adapter-bun/_app/immutable/assets/_layout.6tlxP3iE.css +1 -0
  81. package/{dist/web/client/_app/immutable/assets/3.XJ3XhAQU.css → web/.svelte-kit/adapter-bun/_app/immutable/assets/_page.DIECCPxi.css} +1 -1
  82. package/web/.svelte-kit/adapter-bun/chunks/button.js +24 -1
  83. package/web/.svelte-kit/adapter-bun/chunks/internal2.js +1 -1
  84. package/web/.svelte-kit/adapter-bun/chunks/ws-handlers.js +137 -40
  85. package/web/.svelte-kit/adapter-bun/chunks/ws-managers.js +1 -1
  86. package/web/.svelte-kit/adapter-bun/entries/endpoints/api/projects/new-session/_server.ts.js +3 -1
  87. package/web/.svelte-kit/adapter-bun/entries/endpoints/api/sessions/_server.ts.js +1 -1
  88. package/web/.svelte-kit/adapter-bun/entries/endpoints/api/settings/_server.ts.js +1 -1
  89. package/web/.svelte-kit/adapter-bun/entries/pages/_layout.svelte.js +2 -2
  90. package/web/.svelte-kit/adapter-bun/entries/pages/session/_target_/_page.svelte.js +2 -1
  91. package/web/.svelte-kit/adapter-bun/manifest-full.js +1 -1
  92. package/web/.svelte-kit/adapter-bun/manifest.js +1 -1
  93. package/web/.svelte-kit/adapter-bun/nodes/0.js +2 -2
  94. package/web/.svelte-kit/adapter-bun/nodes/1.js +1 -1
  95. package/web/.svelte-kit/adapter-bun/nodes/2.js +1 -1
  96. package/web/.svelte-kit/adapter-bun/nodes/3.js +2 -2
  97. package/web/.svelte-kit/generated/server/internal.js +1 -1
  98. package/web/.svelte-kit/output/client/.vite/manifest.json +59 -59
  99. package/web/.svelte-kit/output/client/_app/immutable/assets/0.CiLJk_Xe.css +1 -0
  100. package/web/.svelte-kit/output/client/_app/immutable/assets/{3.XJ3XhAQU.css → 3.DIECCPxi.css} +1 -1
  101. package/web/.svelte-kit/output/client/_app/immutable/chunks/Bjgls5C2.js +2 -0
  102. package/{dist/web/client/_app/immutable/chunks/Cotx9uI_.js → web/.svelte-kit/output/client/_app/immutable/chunks/C8V5fK-3.js} +1 -1
  103. package/web/.svelte-kit/output/client/_app/immutable/chunks/DnC9WjQh.js +57 -0
  104. package/web/.svelte-kit/output/client/_app/immutable/chunks/MhGpinwS.js +1 -0
  105. package/web/.svelte-kit/output/client/_app/immutable/chunks/cJslalWy.js +1 -0
  106. package/web/.svelte-kit/output/client/_app/immutable/entry/{app.DXHW0aPL.js → app.tijMyuHe.js} +2 -2
  107. package/web/.svelte-kit/output/client/_app/immutable/entry/start.BjUUmuae.js +1 -0
  108. package/web/.svelte-kit/output/client/_app/immutable/nodes/{0.DAnv2asW.js → 0.Dh-WcEW1.js} +1 -1
  109. package/web/.svelte-kit/output/client/_app/immutable/nodes/{1.CU8f4oNB.js → 1.haoM4e9N.js} +1 -1
  110. package/web/.svelte-kit/output/client/_app/immutable/nodes/{2.BYpvCgtu.js → 2.DtC9KdX8.js} +1 -1
  111. package/web/.svelte-kit/output/client/_app/immutable/nodes/3.FZTTKJCk.js +168 -0
  112. package/web/.svelte-kit/output/client/_app/version.json +1 -1
  113. package/web/.svelte-kit/output/server/.vite/manifest.json +4 -8
  114. package/web/.svelte-kit/output/server/_app/immutable/assets/_layout.6tlxP3iE.css +1 -0
  115. package/web/.svelte-kit/output/server/_app/immutable/assets/{_page.XJ3XhAQU.css → _page.DIECCPxi.css} +1 -1
  116. package/web/.svelte-kit/output/server/chunks/button.js +24 -1
  117. package/web/.svelte-kit/output/server/chunks/internal2.js +1 -1
  118. package/web/.svelte-kit/output/server/chunks/ws-handlers.js +137 -40
  119. package/web/.svelte-kit/output/server/chunks/ws-managers.js +1 -1
  120. package/web/.svelte-kit/output/server/entries/endpoints/api/projects/new-session/_server.ts.js +3 -1
  121. package/web/.svelte-kit/output/server/entries/endpoints/api/sessions/_server.ts.js +1 -1
  122. package/web/.svelte-kit/output/server/entries/endpoints/api/settings/_server.ts.js +1 -1
  123. package/web/.svelte-kit/output/server/entries/pages/_layout.svelte.js +2 -2
  124. package/web/.svelte-kit/output/server/entries/pages/session/_target_/_page.svelte.js +2 -1
  125. package/web/.svelte-kit/output/server/manifest-full.js +1 -1
  126. package/web/.svelte-kit/output/server/manifest.js +1 -1
  127. package/web/.svelte-kit/output/server/nodes/0.js +2 -2
  128. package/web/.svelte-kit/output/server/nodes/1.js +1 -1
  129. package/web/.svelte-kit/output/server/nodes/2.js +1 -1
  130. package/web/.svelte-kit/output/server/nodes/3.js +2 -2
  131. package/web/src/lib/actions/longPress.ts +52 -6
  132. package/web/src/lib/components/AllSessionsPanel.svelte +12 -3
  133. package/web/src/lib/stores/websocket-base.svelte.ts +24 -1
  134. package/web/src/routes/api/projects/new-session/+server.ts +3 -0
  135. package/web/src/routes/session/[target]/+page.svelte +60 -12
  136. package/dist/web/client/_app/immutable/assets/0.DwaaTdPO.css +0 -1
  137. package/dist/web/client/_app/immutable/chunks/1pIWnoD_.js +0 -1
  138. package/dist/web/client/_app/immutable/chunks/DfoR1zCV.js +0 -1
  139. package/dist/web/client/_app/immutable/chunks/DmEI2TOa.js +0 -57
  140. package/dist/web/client/_app/immutable/chunks/DtVU-s3j.js +0 -2
  141. package/dist/web/client/_app/immutable/entry/start.CchjowOg.js +0 -1
  142. package/dist/web/client/_app/immutable/nodes/3.DuMzeRg3.js +0 -168
  143. package/dist/web/server/chunks/_server.ts-CNU4yPZZ.js.map +0 -1
  144. package/dist/web/server/chunks/geometry-CUMMOI9q.js +0 -46
  145. package/dist/web/server/chunks/geometry-CUMMOI9q.js.map +0 -1
  146. package/dist/web/server/chunks/ws-handlers-BQ2RtlNl.js.map +0 -1
  147. package/web/.svelte-kit/adapter-bun/_app/immutable/assets/_layout.Bpy37C6o.css +0 -1
  148. package/web/.svelte-kit/adapter-bun/chunks/geometry.js +0 -32
  149. package/web/.svelte-kit/output/client/_app/immutable/assets/0.DwaaTdPO.css +0 -1
  150. package/web/.svelte-kit/output/client/_app/immutable/chunks/1pIWnoD_.js +0 -1
  151. package/web/.svelte-kit/output/client/_app/immutable/chunks/DfoR1zCV.js +0 -1
  152. package/web/.svelte-kit/output/client/_app/immutable/chunks/DmEI2TOa.js +0 -57
  153. package/web/.svelte-kit/output/client/_app/immutable/chunks/DtVU-s3j.js +0 -2
  154. package/web/.svelte-kit/output/client/_app/immutable/entry/start.CchjowOg.js +0 -1
  155. package/web/.svelte-kit/output/client/_app/immutable/nodes/3.DuMzeRg3.js +0 -168
  156. package/web/.svelte-kit/output/server/_app/immutable/assets/_layout.Bpy37C6o.css +0 -1
  157. package/web/.svelte-kit/output/server/chunks/geometry.js +0 -32
@@ -23,14 +23,14 @@ const manifest = (() => {
23
23
  },
24
24
  _: {
25
25
  client: {
26
- start: "_app/immutable/entry/start.CchjowOg.js",
27
- app: "_app/immutable/entry/app.DXHW0aPL.js",
26
+ start: "_app/immutable/entry/start.BjUUmuae.js",
27
+ app: "_app/immutable/entry/app.tijMyuHe.js",
28
28
  imports: [
29
- "_app/immutable/entry/start.CchjowOg.js",
30
- "_app/immutable/chunks/DtVU-s3j.js",
29
+ "_app/immutable/entry/start.BjUUmuae.js",
30
+ "_app/immutable/chunks/Bjgls5C2.js",
31
31
  "_app/immutable/chunks/RhyL4cOo.js",
32
- "_app/immutable/chunks/DfoR1zCV.js",
33
- "_app/immutable/entry/app.DXHW0aPL.js",
32
+ "_app/immutable/chunks/cJslalWy.js",
33
+ "_app/immutable/entry/app.tijMyuHe.js",
34
34
  "_app/immutable/chunks/RhyL4cOo.js",
35
35
  "_app/immutable/chunks/BuvGONG-.js",
36
36
  "_app/immutable/chunks/ukOf9Kzz.js",
@@ -41,10 +41,10 @@ const manifest = (() => {
41
41
  uses_env_dynamic_public: false
42
42
  },
43
43
  nodes: [
44
- __memo(() => import("./chunks/0-C-AAPmon.js")),
45
- __memo(() => import("./chunks/1-T_dogl8W.js")),
46
- __memo(() => import("./chunks/2-FlchE_4u.js")),
47
- __memo(() => import("./chunks/3-U2bTntXU.js")),
44
+ __memo(() => import("./chunks/0-Cw5iP0WY.js")),
45
+ __memo(() => import("./chunks/1-CR_g4jt5.js")),
46
+ __memo(() => import("./chunks/2-Cy0TJi3N.js")),
47
+ __memo(() => import("./chunks/3-D9Ui86YT.js")),
48
48
  __memo(() => import("./chunks/4-DWNV8gkw.js"))
49
49
  ],
50
50
  remotes: {},
@@ -100,14 +100,14 @@ const manifest = (() => {
100
100
  pattern: /^\/api\/projects\/?$/,
101
101
  params: [],
102
102
  page: null,
103
- endpoint: __memo(() => import("./chunks/_server.ts-fnuGtMqr.js"))
103
+ endpoint: __memo(() => import("./chunks/_server.ts-CSKVHlMn.js"))
104
104
  },
105
105
  {
106
106
  id: "/api/projects/new-session",
107
107
  pattern: /^\/api\/projects\/new-session\/?$/,
108
108
  params: [],
109
109
  page: null,
110
- endpoint: __memo(() => import("./chunks/_server.ts-CNU4yPZZ.js"))
110
+ endpoint: __memo(() => import("./chunks/_server.ts-BCCIAioG.js"))
111
111
  },
112
112
  {
113
113
  id: "/api/servers/discover",
@@ -121,7 +121,7 @@ const manifest = (() => {
121
121
  pattern: /^\/api\/sessions\/?$/,
122
122
  params: [],
123
123
  page: null,
124
- endpoint: __memo(() => import("./chunks/_server.ts-Df32fD_Q.js"))
124
+ endpoint: __memo(() => import("./chunks/_server.ts-D1PwUVXn.js"))
125
125
  },
126
126
  {
127
127
  id: "/api/sessions/[id]",
@@ -157,7 +157,7 @@ const manifest = (() => {
157
157
  "chained": false
158
158
  }],
159
159
  page: null,
160
- endpoint: __memo(() => import("./chunks/_server.ts-BBrtrcEt.js"))
160
+ endpoint: __memo(() => import("./chunks/_server.ts-CONr9rjv.js"))
161
161
  },
162
162
  {
163
163
  id: "/api/sessions/[target]/output",
@@ -205,7 +205,7 @@ const manifest = (() => {
205
205
  "chained": false
206
206
  }],
207
207
  page: null,
208
- endpoint: __memo(() => import("./chunks/_server.ts-C00ejke7.js"))
208
+ endpoint: __memo(() => import("./chunks/_server.ts-D4xa8gs1.js"))
209
209
  },
210
210
  {
211
211
  id: "/api/sessions/[id]/restart",
@@ -217,7 +217,7 @@ const manifest = (() => {
217
217
  "chained": false
218
218
  }],
219
219
  page: null,
220
- endpoint: __memo(() => import("./chunks/_server.ts-CtsPyICr.js"))
220
+ endpoint: __memo(() => import("./chunks/_server.ts-BMZtxwLP.js"))
221
221
  },
222
222
  {
223
223
  id: "/api/sessions/[id]/screenshots",
@@ -260,7 +260,7 @@ const manifest = (() => {
260
260
  pattern: /^\/api\/settings\/?$/,
261
261
  params: [],
262
262
  page: null,
263
- endpoint: __memo(() => import("./chunks/_server.ts-C6MJsvPN.js"))
263
+ endpoint: __memo(() => import("./chunks/_server.ts-DxjUBscT.js"))
264
264
  },
265
265
  {
266
266
  id: "/api/tmux/panes",
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","names":[],"sources":["../../../web/.svelte-kit/adapter-bun/manifest.js"],"sourcesContent":["export const manifest = (() => {\nfunction __memo(fn) {\n\tlet value;\n\treturn () => value ??= (value = fn());\n}\n\nreturn {\n\tappDir: \"_app\",\n\tappPath: \"_app\",\n\tassets: new Set([\"apple-touch-icon.png\",\"favicon.svg\",\"icon-192.png\",\"icon-512.png\",\"manifest.webmanifest\",\"robots.txt\"]),\n\tmimeTypes: {\".png\":\"image/png\",\".svg\":\"image/svg+xml\",\".webmanifest\":\"application/manifest+json\",\".txt\":\"text/plain\"},\n\t_: {\n\t\tclient: {start:\"_app/immutable/entry/start.CchjowOg.js\",app:\"_app/immutable/entry/app.DXHW0aPL.js\",imports:[\"_app/immutable/entry/start.CchjowOg.js\",\"_app/immutable/chunks/DtVU-s3j.js\",\"_app/immutable/chunks/RhyL4cOo.js\",\"_app/immutable/chunks/DfoR1zCV.js\",\"_app/immutable/entry/app.DXHW0aPL.js\",\"_app/immutable/chunks/RhyL4cOo.js\",\"_app/immutable/chunks/BuvGONG-.js\",\"_app/immutable/chunks/ukOf9Kzz.js\",\"_app/immutable/chunks/CjMoR7Dp.js\"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},\n\t\tnodes: [\n\t\t\t__memo(() => import('./nodes/0.js')),\n\t\t\t__memo(() => import('./nodes/1.js')),\n\t\t\t__memo(() => import('./nodes/2.js')),\n\t\t\t__memo(() => import('./nodes/3.js')),\n\t\t\t__memo(() => import('./nodes/4.js'))\n\t\t],\n\t\tremotes: {\n\t\t\t\n\t\t},\n\t\troutes: [\n\t\t\t{\n\t\t\t\tid: \"/\",\n\t\t\t\tpattern: /^\\/$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 2 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/browse\",\n\t\t\t\tpattern: /^\\/api\\/browse\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/browse/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/chrome\",\n\t\t\t\tpattern: /^\\/api\\/chrome\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/chrome/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/commands\",\n\t\t\t\tpattern: /^\\/api\\/commands\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/commands/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/files/image\",\n\t\t\t\tpattern: /^\\/api\\/files\\/image\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/files/image/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/health\",\n\t\t\t\tpattern: /^\\/api\\/health\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/health/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/projects\",\n\t\t\t\tpattern: /^\\/api\\/projects\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/projects/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/projects/new-session\",\n\t\t\t\tpattern: /^\\/api\\/projects\\/new-session\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/projects/new-session/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/servers/discover\",\n\t\t\t\tpattern: /^\\/api\\/servers\\/discover\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/servers/discover/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/attach\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/attach\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/attach/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/kill\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/kill\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/kill/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[target]/output\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/output\\/?$/,\n\t\t\t\tparams: [{\"name\":\"target\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_target_/output/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/queue\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/queue\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/queue/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/rc\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/rc\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/rc/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/rename\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/rename\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/rename/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/restart\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/restart\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/restart/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/screenshots\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/screenshots\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/screenshots/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/send\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/send\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/send/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/voice\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/voice\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/voice/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/settings\",\n\t\t\t\tpattern: /^\\/api\\/settings\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/settings/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/tmux/panes\",\n\t\t\t\tpattern: /^\\/api\\/tmux\\/panes\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/tmux/panes/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/usage\",\n\t\t\t\tpattern: /^\\/api\\/usage\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/usage/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/usage/all\",\n\t\t\t\tpattern: /^\\/api\\/usage\\/all\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/usage/all/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/usage/quota\",\n\t\t\t\tpattern: /^\\/api\\/usage\\/quota\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/usage/quota/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/downloads/[file]\",\n\t\t\t\tpattern: /^\\/downloads\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"file\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/downloads/_file_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/session/[target]\",\n\t\t\t\tpattern: /^\\/session\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"target\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 3 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/usage\",\n\t\t\t\tpattern: /^\\/usage\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 4 },\n\t\t\t\tendpoint: null\n\t\t\t}\n\t\t],\n\t\tprerendered_routes: new Set([]),\n\t\tmatchers: async () => {\n\t\t\t\n\t\t\treturn { };\n\t\t},\n\t\tserver_assets: {}\n\t}\n}\n})();\n\nexport const prerendered = new Set([]);\n\nexport const base = \"\";"],"mappings":";AAAA,MAAa,kBAAkB;CAC/B,SAAS,OAAO,IAAI;EACnB,IAAI;EACJ,aAAa,UAAW,QAAQ,GAAG;CACpC;CAEA,OAAO;EACN,QAAQ;EACR,SAAS;EACT,wBAAQ,IAAI,IAAI;GAAC;GAAuB;GAAc;GAAe;GAAe;GAAuB;EAAY,CAAC;EACxH,WAAW;GAAC,QAAO;GAAY,QAAO;GAAgB,gBAAe;GAA4B,QAAO;EAAY;EACpH,GAAG;GACF,QAAQ;IAAC,OAAM;IAAyC,KAAI;IAAuC,SAAQ;KAAC;KAAyC;KAAoC;KAAoC;KAAoC;KAAuC;KAAoC;KAAoC;KAAoC;IAAmC;IAAE,aAAY,CAAC;IAAE,OAAM,CAAC;IAAE,yBAAwB;GAAK;GAC9e,OAAO;IACN,aAAa,OAAO,yBAAe;IACnC,aAAa,OAAO,yBAAe;IACnC,aAAa,OAAO,yBAAe;IACnC,aAAa,OAAO,yBAAe;IACnC,aAAa,OAAO,yBAAe;GACpC;GACA,SAAS,CAET;GACA,QAAQ;IACP;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;MAAE,SAAS,CAAC,CAAE;MAAG,QAAQ,CAAC,CAAE;MAAG,MAAM;KAAE;KAC7C,UAAU;IACX;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAA+C;IAC9E;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAA+C;IAC9E;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAAiD;IAChF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAAoD;IACnF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAA+C;IAC9E;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAAiD;IAChF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAA6D;IAC5F;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAAyD;IACxF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAAiD;IAChF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAK,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACpE,MAAM;KACN,UAAU,aAAa,OAAO,kCAAsD;IACrF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAK,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACpE,MAAM;KACN,UAAU,aAAa,OAAO,kCAA6D;IAC5F;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAK,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACpE,MAAM;KACN,UAAU,aAAa,OAAO,kCAA2D;IAC1F;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAS,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACxE,MAAM;KACN,UAAU,aAAa,OAAO,kCAAiE;IAChG;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAK,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACpE,MAAM;KACN,UAAU,aAAa,OAAO,kCAA4D;IAC3F;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAK,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACpE,MAAM;KACN,UAAU,aAAa,OAAO,kCAAyD;IACxF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAK,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACpE,MAAM;KACN,UAAU,aAAa,OAAO,kCAA6D;IAC5F;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAK,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACpE,MAAM;KACN,UAAU,aAAa,OAAO,kCAA8D;IAC7F;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAK,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACpE,MAAM;KACN,UAAU,aAAa,OAAO,kCAAkE;IACjG;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAK,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACpE,MAAM;KACN,UAAU,aAAa,OAAO,kCAA2D;IAC1F;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAK,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACpE,MAAM;KACN,UAAU,aAAa,OAAO,kCAA4D;IAC3F;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAAiD;IAChF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAAmD;IAClF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAA8C;IAC7E;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAAkD;IACjF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;KACN,UAAU,aAAa,OAAO,kCAAoD;IACnF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAO,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACtE,MAAM;KACN,UAAU,aAAa,OAAO,kCAAqD;IACpF;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;MAAC,QAAO;MAAS,YAAW;MAAM,QAAO;MAAM,WAAU;KAAK,CAAC;KACxE,MAAM;MAAE,SAAS,CAAC,CAAE;MAAG,QAAQ,CAAC,CAAE;MAAG,MAAM;KAAE;KAC7C,UAAU;IACX;IACA;KACC,IAAI;KACJ,SAAS;KACT,QAAQ,CAAC;KACT,MAAM;MAAE,SAAS,CAAC,CAAE;MAAG,QAAQ,CAAC,CAAE;MAAG,MAAM;KAAE;KAC7C,UAAU;IACX;GACD;GACA,oCAAoB,IAAI,IAAI,CAAC,CAAC;GAC9B,UAAU,YAAY;IAErB,OAAO,CAAG;GACX;GACA,eAAe,CAAC;EACjB;CACD;AACA,EAAA,CAAG;AAEH,MAAa,8BAAc,IAAI,IAAI,CAAC,CAAC;AAErC,MAAa,OAAO"}
1
+ {"version":3,"file":"manifest.js","names":[],"sources":["../../../web/.svelte-kit/adapter-bun/manifest.js"],"sourcesContent":["export const manifest = (() => {\nfunction __memo(fn) {\n\tlet value;\n\treturn () => value ??= (value = fn());\n}\n\nreturn {\n\tappDir: \"_app\",\n\tappPath: \"_app\",\n\tassets: new Set([\"apple-touch-icon.png\",\"favicon.svg\",\"icon-192.png\",\"icon-512.png\",\"manifest.webmanifest\",\"robots.txt\"]),\n\tmimeTypes: {\".png\":\"image/png\",\".svg\":\"image/svg+xml\",\".webmanifest\":\"application/manifest+json\",\".txt\":\"text/plain\"},\n\t_: {\n\t\tclient: {start:\"_app/immutable/entry/start.BjUUmuae.js\",app:\"_app/immutable/entry/app.tijMyuHe.js\",imports:[\"_app/immutable/entry/start.BjUUmuae.js\",\"_app/immutable/chunks/Bjgls5C2.js\",\"_app/immutable/chunks/RhyL4cOo.js\",\"_app/immutable/chunks/cJslalWy.js\",\"_app/immutable/entry/app.tijMyuHe.js\",\"_app/immutable/chunks/RhyL4cOo.js\",\"_app/immutable/chunks/BuvGONG-.js\",\"_app/immutable/chunks/ukOf9Kzz.js\",\"_app/immutable/chunks/CjMoR7Dp.js\"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},\n\t\tnodes: [\n\t\t\t__memo(() => import('./nodes/0.js')),\n\t\t\t__memo(() => import('./nodes/1.js')),\n\t\t\t__memo(() => import('./nodes/2.js')),\n\t\t\t__memo(() => import('./nodes/3.js')),\n\t\t\t__memo(() => import('./nodes/4.js'))\n\t\t],\n\t\tremotes: {\n\t\t\t\n\t\t},\n\t\troutes: [\n\t\t\t{\n\t\t\t\tid: \"/\",\n\t\t\t\tpattern: /^\\/$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 2 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/browse\",\n\t\t\t\tpattern: /^\\/api\\/browse\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/browse/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/chrome\",\n\t\t\t\tpattern: /^\\/api\\/chrome\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/chrome/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/commands\",\n\t\t\t\tpattern: /^\\/api\\/commands\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/commands/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/files/image\",\n\t\t\t\tpattern: /^\\/api\\/files\\/image\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/files/image/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/health\",\n\t\t\t\tpattern: /^\\/api\\/health\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/health/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/projects\",\n\t\t\t\tpattern: /^\\/api\\/projects\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/projects/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/projects/new-session\",\n\t\t\t\tpattern: /^\\/api\\/projects\\/new-session\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/projects/new-session/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/servers/discover\",\n\t\t\t\tpattern: /^\\/api\\/servers\\/discover\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/servers/discover/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/attach\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/attach\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/attach/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/kill\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/kill\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/kill/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[target]/output\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/output\\/?$/,\n\t\t\t\tparams: [{\"name\":\"target\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_target_/output/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/queue\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/queue\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/queue/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/rc\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/rc\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/rc/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/rename\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/rename\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/rename/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/restart\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/restart\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/restart/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/screenshots\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/screenshots\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/screenshots/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/send\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/send\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/send/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[id]/voice\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/voice\\/?$/,\n\t\t\t\tparams: [{\"name\":\"id\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_id_/voice/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/settings\",\n\t\t\t\tpattern: /^\\/api\\/settings\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/settings/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/tmux/panes\",\n\t\t\t\tpattern: /^\\/api\\/tmux\\/panes\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/tmux/panes/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/usage\",\n\t\t\t\tpattern: /^\\/api\\/usage\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/usage/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/usage/all\",\n\t\t\t\tpattern: /^\\/api\\/usage\\/all\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/usage/all/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/usage/quota\",\n\t\t\t\tpattern: /^\\/api\\/usage\\/quota\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/usage/quota/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/downloads/[file]\",\n\t\t\t\tpattern: /^\\/downloads\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"file\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/downloads/_file_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/session/[target]\",\n\t\t\t\tpattern: /^\\/session\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"target\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 3 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/usage\",\n\t\t\t\tpattern: /^\\/usage\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 4 },\n\t\t\t\tendpoint: null\n\t\t\t}\n\t\t],\n\t\tprerendered_routes: new Set([]),\n\t\tmatchers: async () => {\n\t\t\t\n\t\t\treturn { };\n\t\t},\n\t\tserver_assets: {}\n\t}\n}\n})();\n\nexport const prerendered = new Set([]);\n\nexport const base = \"\";"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mux",
3
- "version": "0.26.2",
3
+ "version": "0.26.4",
4
4
  "description": "Real-time web dashboard for monitoring and controlling multiple Claude Code sessions",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",
@@ -10,17 +10,17 @@
10
10
 
11
11
  import { execFileSync } from 'child_process';
12
12
  import { readFileSync } from 'fs';
13
- import { getAllSessions, getSession, updateSession, readLinks, cleanupStaleSessions, type Session } from '../db/index.js';
13
+ import { getAllSessions, getSession, updateSession, readLinks, cleanupStaleSessions, sanitizeDisplayName, type Session } from '../db/index.js';
14
14
  import { type ContextUsage } from '../transcript/context.js';
15
15
  import { TranscriptBuilder, type TranscriptEntry } from '../transcript/parser.js';
16
16
  import { subagentPayload, type SubagentPayload } from '../transcript/subagent.js';
17
17
  import { isDictated } from './dictation-marks.js';
18
18
  import { JsonlTailer, listSubagents, resolveTranscriptPath, type SubagentMeta } from '../transcript/tailer.js';
19
- import { getAllPaneTitles, detectRemoteControlUrl, capturePaneContentAsync, isPaneShowingSpinner, isPaneShowingIdlePrompt, detectRecentInterruption, readPromptBox, readQueuedMessages, readPromptOptions, stripAnsi, sendKeyAsync } from '../tmux/pane.js';
19
+ import { getAllPaneTitles, detectRemoteControlUrl, capturePaneContentAsync, readActivityLine, isPaneShowingIdlePrompt, detectRecentInterruption, readPromptBox, readQueuedMessages, readPromptOptions, stripAnsi, sendKeyAsync } from '../tmux/pane.js';
20
20
  import type { PromptChoice } from '../tmux/pane.js';
21
21
  import { wantsWidening, widenDetachedWindow } from '../tmux/geometry.js';
22
22
  import { getSavedProjects, saveProjects } from '../db/projects-json.js';
23
- import { peekContextPercent } from '../transcript/context-peek.js';
23
+ import { peekContextPercent, peekTranscriptTitle } from '../transcript/context-peek.js';
24
24
 
25
25
  /**
26
26
  * What the session poll reads off the pane itself and rides the broadcast —
@@ -253,9 +253,11 @@ async function captureAndSyncSessions(): Promise<{
253
253
  } else {
254
254
  idleLookTicks.delete(session.id);
255
255
  }
256
- // If hook says idle but pane shows a spinner (e.g. compaction), override to busy
257
- if (session.state === 'idle' && isPaneShowingSpinner(content)) {
258
- apply(session, { state: 'busy', current_action: 'Compacting...' });
256
+ // The hooks say idle but the pane is spinning: compaction, which fires
257
+ // no hook. The spinner's own words are the action.
258
+ if (session.state === 'idle') {
259
+ const activity = readActivityLine(content);
260
+ if (activity) apply(session, { state: 'busy', current_action: activity });
259
261
  }
260
262
  })
261
263
  );
@@ -283,6 +285,31 @@ const rcSeen = new Set<string>();
283
285
  /** False on the first poll, which only primes `rcSeen` with what already runs. */
284
286
  let rcPrimed = false;
285
287
 
288
+ /**
289
+ * The transcript title each session was last seen to carry, so a name is
290
+ * applied when Claude Code changes it and not on every tick that it differs.
291
+ */
292
+ const transcriptTitleSeen = new Map<string, string>();
293
+
294
+ /**
295
+ * A `/rename` typed inside Claude Code goes through none of the hooks — slash
296
+ * commands never reach UserPromptSubmit — so the only trace is the
297
+ * `custom-title` record in the transcript. Mirror a change there into
298
+ * `display_name`. The other direction (renamed from the dashboard) sends the
299
+ * same `/rename` into the pane, so the record it produces already matches
300
+ * and nothing is written twice.
301
+ */
302
+ function syncTranscriptTitle(s: Session): void {
303
+ if ((s.agent ?? 'claude') !== 'claude') return;
304
+ const title = peekTranscriptTitle(s);
305
+ if (title === undefined || transcriptTitleSeen.get(s.id) === title) return;
306
+ transcriptTitleSeen.set(s.id, title);
307
+ const name = sanitizeDisplayName(title);
308
+ if (name === (s.display_name ?? null)) return;
309
+ updateSession(s.id, { display_name: name });
310
+ s.display_name = name;
311
+ }
312
+
286
313
  export async function getEnrichedSessionsAsync(): Promise<(Session & LivePaneFields)[]> {
287
314
  const [{ captures, rawCaptures, sessions }, paneTitles] = await Promise.all([
288
315
  captureAndSyncSessions(),
@@ -318,6 +345,8 @@ export async function getEnrichedSessionsAsync(): Promise<(Session & LivePaneFie
318
345
  }
319
346
  rcPrimed = true;
320
347
 
348
+ for (const s of sessions) syncTranscriptTitle(s);
349
+
321
350
  // Scan for Remote Control URLs in pane content (detect new URLs and clear stale ones)
322
351
  for (const s of sessions) {
323
352
  if (!s.tmux_target) continue;
package/src/tmux/pane.ts CHANGED
@@ -103,15 +103,40 @@ export async function capturePaneContentAsync(target: string, withColor = false)
103
103
  }
104
104
 
105
105
  /**
106
- * Check if the pane shows a spinner (e.g. during compaction).
107
- * Claude Code uses braille spinner characters (U+2800–U+28FF) in the status area.
108
- * Checks the bottom few lines of the pane where the spinner would appear.
106
+ * Claude Code's activity line: a spinner glyph, then what it is doing, ending
107
+ * in "…" — "✻ Julienning… (1m 39s", "⠋ Compacting conversation…". Older
108
+ * builds spin a braille glyph, newer ones the star family; the finished form
109
+ * ("✻ Baked for 33s · done") has no "…" and is not one.
110
+ *
111
+ * Only this shape counts as work. A braille or star glyph elsewhere in the
112
+ * pane — a CLI's own progress bar left in tool output, a bullet in Claude's
113
+ * answer — is not a spinner, and reading it as one held sessions at busy after
114
+ * they had stopped.
115
+ */
116
+ const ACTIVITY_LINE = /^\s*[⠀-⣿✻✢✳✶✽·]\s+(\S[^…]*…)/;
117
+
118
+ /** Lines from the foot of the pane that a spinner can sit in: above the prompt box and its footer. */
119
+ const ACTIVITY_WINDOW = 12;
120
+
121
+ /**
122
+ * What the spinner at the foot of the pane says Claude Code is doing, without
123
+ * the glyph — "Compacting conversation…" — or null when no spinner is drawn.
124
+ */
125
+ export function readActivityLine(content: string): string | null {
126
+ if (!content) return null;
127
+ for (const line of content.split("\n").slice(-ACTIVITY_WINDOW)) {
128
+ const m = ACTIVITY_LINE.exec(line);
129
+ if (m) return m[1].trim();
130
+ }
131
+ return null;
132
+ }
133
+
134
+ /**
135
+ * Whether the pane shows a spinner while the hooks say idle — compaction,
136
+ * which fires no hook, is the usual case.
109
137
  */
110
138
  export function isPaneShowingSpinner(content: string): boolean {
111
- if (!content) return false;
112
- const bottomLines = content.split('\n').slice(-5).join('');
113
- // Braille spinner characters: ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏ etc. (U+2800-U+28FF)
114
- return /[\u2800-\u28FF]/.test(bottomLines);
139
+ return readActivityLine(content) !== null;
115
140
  }
116
141
 
117
142
  /**
@@ -122,13 +147,12 @@ export function isPaneShowingSpinner(content: string): boolean {
122
147
  */
123
148
  export function isPaneShowingIdlePrompt(content: string): boolean {
124
149
  if (!content) return false;
125
- const bottom = content.split("\n").slice(-12);
150
+ const bottom = content.split("\n").slice(-ACTIVITY_WINDOW);
126
151
  const joined = bottom.join("\n");
127
152
  // Any active-work or dialog indicator vetoes idle.
128
- if (/[⠀-⣿]/.test(joined)) return false; // braille spinner
153
+ if (readActivityLine(content) !== null) return false;
129
154
  if (/esc to interrupt|esc to cancel|ctrl\+c to interrupt/i.test(joined)) return false;
130
- // Activity status line: spinner glyph + word ending in "…", e.g. "✻ Julienning… (1m 39s"
131
- // (the finished form "✻ Baked for 33s · done" has no "…" and passes).
155
+ // A status line drawn with some other glyph: "⎿ Running hook…".
132
156
  if (bottom.some((line) => /^\s*[^\w\s❯│>]\s+\S+…/.test(line))) return false;
133
157
  if (/Do you want|❯\s+\d+\./.test(joined)) return false;
134
158
  // The ready input prompt must actually be visible.
@@ -451,12 +475,20 @@ export function checkForInterruption(tmuxTarget: string): { state: 'idle'; curre
451
475
  /** Max options carried to the UI; a longer list is truncated. */
452
476
  const MAX_PROMPT_OPTIONS = 10;
453
477
 
454
- /** Max characters kept per option label. */
455
- const MAX_OPTION_CHARS = 120;
478
+ /**
479
+ * Longest text kept per option label, description or question. A bound on
480
+ * the broadcast, not a display choice: the dialog's words are read in full,
481
+ * wrapped lines and all, because a question cut mid-sentence cannot be
482
+ * answered from the dashboard.
483
+ */
484
+ const MAX_OPTION_CHARS = 4000;
456
485
 
457
486
  /** How far up from the last content line an option run may start. */
458
487
  const OPTION_RUN_WINDOW = 24;
459
488
 
489
+ /** How many pane lines a question may take above its first row. */
490
+ const QUESTION_LINES = 12;
491
+
460
492
  /**
461
493
  * How far above the last content line the run may end. A dialog puts its
462
494
  * options at the foot, under at most a closing border and a hint.
@@ -477,6 +509,12 @@ export type PromptOption = {
477
509
  checked?: boolean;
478
510
  /** Claude Code's own highlight — the row carrying the `❯` marker. */
479
511
  selected: boolean;
512
+ /**
513
+ * The row is the question's free-text answer. Highlighting it is what opens
514
+ * it for typing, and Enter on it while it is empty declines the question —
515
+ * so it is picked with the arrows alone, never with Enter.
516
+ */
517
+ text?: true;
480
518
  };
481
519
 
482
520
  /** A numbered question waiting in the pane. */
@@ -580,6 +618,9 @@ const BOX_ROW = /^[┌┐└┘├┤─━│╭╮╰╯]/;
580
618
  /** A multi-select row carries its own state in a checkbox. */
581
619
  const CHECKBOX = /^\[([ xX✔✓])\]\s*/;
582
620
 
621
+ /** The free-text row of a question, as Claude Code labels it while empty. */
622
+ const TEXT_ROW = /^Type something\.?$/i;
623
+
583
624
  /** How far past its row a description may be indented and still be one. */
584
625
  const HINT_INDENT_SPAN = 8;
585
626
 
@@ -595,11 +636,42 @@ function bodyOf(line: string): { indent: number; text: string } {
595
636
  return { indent: body.length - text.length, text };
596
637
  }
597
638
 
598
- /** Keep a dialog's own words, but not a paragraph of them. */
639
+ /** Keep a dialog's own words, up to the bound on the broadcast. */
599
640
  function clampOption(text: string): string {
600
641
  return text.length > MAX_OPTION_CHARS ? text.slice(0, MAX_OPTION_CHARS) + "…" : text;
601
642
  }
602
643
 
644
+ /**
645
+ * Below this share of a paragraph's widest line, a line ended early: it is a
646
+ * title or the end of a sentence, and what follows starts a new line. At or
647
+ * above it the terminal wrapped it, and what follows is the same sentence.
648
+ */
649
+ const WRAPPED_LINE_SHARE = 0.6;
650
+
651
+ /**
652
+ * Shorter than this, a line was not wrapped by the terminal whatever its
653
+ * neighbours measure: panes are wider, and a dialog's short lines are its own
654
+ * — a title, a review's answers, the line that asks.
655
+ */
656
+ const MIN_WRAPPED_COLS = 60;
657
+
658
+ /**
659
+ * Join the lines of a paragraph the way the terminal broke them. A line the
660
+ * terminal wrapped continues on the next with a space; a line that ended
661
+ * early — the model picker's title over its description — keeps its break,
662
+ * which the dashboard renders as one.
663
+ */
664
+ function joinParagraph(lines: string[]): string {
665
+ const widest = Math.max(...lines.map((line) => line.length));
666
+ let out = lines[0] ?? "";
667
+ for (let i = 1; i < lines.length; i++) {
668
+ const prev = lines[i - 1].length;
669
+ const wrapped = prev >= MIN_WRAPPED_COLS && prev >= widest * WRAPPED_LINE_SHARE;
670
+ out += (wrapped ? " " : "\n") + lines[i];
671
+ }
672
+ return out;
673
+ }
674
+
603
675
  /**
604
676
  * Read the numbered options of a permission or question dialog.
605
677
  *
@@ -724,26 +796,37 @@ export function readPromptOptions(content: string, mode: ReadPromptOptionsMode =
724
796
  // description of anything; the rows before it stop at the next row.
725
797
  const stop = last ? (declared ? lastContent : lastContent + 1) : rows[k + 1].i;
726
798
  const noting = last && declared;
727
- let hint: string | undefined;
799
+ // A description wraps over as many lines as it needs, every one at the
800
+ // indent of the first; the paragraph ends at a blank line, a rule, or a
801
+ // line indented differently — the dialog's own note under the last row.
802
+ const hintLines: string[] = [];
803
+ let hintIndent = -1;
804
+ let hintOpen = false;
728
805
  // A rule closes the run, and the description search with it.
729
806
  let ruled = false;
730
807
  for (let i = row.i + 1; i < stop; i++) {
731
808
  const { indent, text } = at(i);
732
809
  if (OPTION_RULE.test(text)) {
810
+ hintOpen = false;
733
811
  if (!noting) break;
734
812
  ruled = true;
735
813
  continue;
736
814
  }
737
- if (!text || BOX_ROW.test(text)) continue;
815
+ if (!text || BOX_ROW.test(text)) {
816
+ if (!text) hintOpen = false;
817
+ continue;
818
+ }
738
819
  const bare = text.replace(PREVIEW_COLUMN, "").trimEnd();
739
820
  if (!bare) continue;
740
821
  const under =
741
822
  !ruled && indent >= row.indent && indent <= row.indent + HINT_INDENT_SPAN;
742
- if (!under || hint !== undefined) {
823
+ const continues = hintOpen && indent === hintIndent;
824
+ if (!under || (hintLines.length > 0 && !continues)) {
743
825
  // Not this row's description. Under the last row of a declared dialog
744
826
  // that makes it a note the dialog is printing for itself — unless a
745
827
  // rule has already closed the run, past which only the dialog's own
746
828
  // unnumbered rows ("Chat about this") are drawn.
829
+ hintOpen = false;
747
830
  if (noting && !ruled) notes.push(clampOption(bare));
748
831
  continue;
749
832
  }
@@ -751,8 +834,12 @@ export function readPromptOptions(content: string, mode: ReadPromptOptionsMode =
751
834
  label = `${label} ${bare}`;
752
835
  continue;
753
836
  }
754
- hint = clampOption(bare);
837
+ hintLines.push(bare);
838
+ hintIndent = indent;
839
+ hintOpen = true;
755
840
  }
841
+ let hint: string | undefined =
842
+ hintLines.length > 0 ? clampOption(joinParagraph(hintLines)) : undefined;
756
843
 
757
844
  // The model picker writes the description on the row itself, after a run
758
845
  // of spaces; a question never does, and a preview row's spaces were the
@@ -765,35 +852,39 @@ export function readPromptOptions(content: string, mode: ReadPromptOptionsMode =
765
852
  }
766
853
  }
767
854
 
768
- return {
855
+ const option: PromptOption = {
769
856
  n: row.n,
770
857
  label: clampOption(label),
771
858
  hint,
772
859
  checked: box ? box[1] !== " " : undefined,
773
860
  selected: row.selected,
774
861
  };
862
+ if (TEXT_ROW.test(option.label)) option.text = true;
863
+ return option;
775
864
  });
776
865
 
777
- // The question is in the paragraph directly above the run: the line that
778
- // asks it when one does, else the paragraph's first line, which is the
779
- // title a dialog such as the model picker leads with. The paragraph ends at
780
- // a blank line, a rule, or the tab strip a question draws over itself.
781
- let question: string | null = null;
782
- let top: string | null = null;
783
- for (let i = rows[0].i - 1; i >= 0 && i >= rows[0].i - 4; i--) {
866
+ // The question is the paragraph directly above the run, whole: a long one
867
+ // wraps over several pane lines, and the model picker leads with a title
868
+ // over a description. The paragraph ends at a blank line, a rule, or the
869
+ // tab strip a question draws over itself.
870
+ const paragraph: string[] = [];
871
+ for (let i = rows[0].i - 1; i >= 0 && i >= rows[0].i - QUESTION_LINES; i--) {
784
872
  const { text } = at(i);
785
873
  if (/^[─━╌┄┈╭╮╰╯]+$/.test(text) || TAB_STRIP.test(text)) break;
786
874
  if (!text) {
787
- if (top !== null) break;
875
+ if (paragraph.length > 0) break;
788
876
  continue;
789
877
  }
790
- top = text;
791
- if (text.endsWith("?")) {
792
- question = clampOption(text);
793
- break;
794
- }
878
+ paragraph.unshift(text);
879
+ }
880
+ // A paragraph that ends by asking — a multi-select's review, which lists
881
+ // the answers first — is the line that asks; any other is carried whole.
882
+ let question: string | null = null;
883
+ if (paragraph.length > 0) {
884
+ const joined = joinParagraph(paragraph);
885
+ const asking = joined.split("\n").pop()!;
886
+ question = clampOption(asking.endsWith("?") ? asking : joined);
795
887
  }
796
- if (question === null && top !== null) question = clampOption(top);
797
888
 
798
889
  const choice: NonNullable<PromptChoice> = { question, options };
799
890
  if (multi) choice.multi = true;
@@ -32,6 +32,8 @@ interface FileMemo {
32
32
  mtimeMs: number;
33
33
  size: number;
34
34
  usage: ContextUsage | null;
35
+ /** The last `custom-title` record; undefined until one has been seen. */
36
+ title: string | undefined;
35
37
  }
36
38
 
37
39
  const paths = new Map<string, PathMemo>();
@@ -59,10 +61,10 @@ function transcriptPathFor(session: { id: string; cwd: string; transcript_path?:
59
61
  return path;
60
62
  }
61
63
 
62
- /** Scan the tail of the file backwards for the last assistant line with usage. */
63
- function readLastUsage(path: string, size: number): ContextUsage | null {
64
+ /** The last TAIL_BYTES of the file, as lines; the first is usually cut mid-record. */
65
+ function readTailLines(path: string, size: number): string[] {
64
66
  const length = Math.min(size, TAIL_BYTES);
65
- if (length === 0) return null;
67
+ if (length === 0) return [];
66
68
  const buffer = Buffer.alloc(length);
67
69
  const fd = openSync(path, "r");
68
70
  try {
@@ -70,7 +72,11 @@ function readLastUsage(path: string, size: number): ContextUsage | null {
70
72
  } finally {
71
73
  closeSync(fd);
72
74
  }
73
- const lines = buffer.toString("utf-8").split("\n");
75
+ return buffer.toString("utf-8").split("\n");
76
+ }
77
+
78
+ /** Scan the tail backwards for the last assistant line with usage. */
79
+ function lastUsage(lines: string[]): ContextUsage | null {
74
80
  for (let i = lines.length - 1; i >= 0; i--) {
75
81
  const line = lines[i];
76
82
  // Cheap reject before parsing: most lines are tool results and user turns.
@@ -89,14 +95,33 @@ function readLastUsage(path: string, size: number): ContextUsage | null {
89
95
  }
90
96
 
91
97
  /**
92
- * The session's context usage as of its latest reply, or null when there is
93
- * no transcript yet or no reply in it.
98
+ * Scan the tail backwards for the last `custom-title` record — what Claude
99
+ * Code writes when the session is renamed with `/rename`, and keeps
100
+ * re-appending afterwards, so it is rarely far from the end. Undefined when
101
+ * the window holds none.
94
102
  */
95
- export function peekContextUsage(session: {
103
+ export function lastCustomTitle(lines: string[]): string | undefined {
104
+ for (let i = lines.length - 1; i >= 0; i--) {
105
+ const line = lines[i];
106
+ if (!line.includes('"custom-title"')) continue;
107
+ try {
108
+ const record = asRecord(JSON.parse(line));
109
+ if (record?.type !== "custom-title") continue;
110
+ const title = record.customTitle;
111
+ return typeof title === "string" ? title : "";
112
+ } catch {
113
+ // Cut record at the head of the window.
114
+ }
115
+ }
116
+ return undefined;
117
+ }
118
+
119
+ /** Stat the transcript and, when it has changed, re-read its tail. */
120
+ function fileMemoFor(session: {
96
121
  id: string;
97
122
  cwd: string;
98
123
  transcript_path?: string | null;
99
- }): ContextUsage | null {
124
+ }): FileMemo | null {
100
125
  const path = transcriptPathFor(session);
101
126
  if (!path) return null;
102
127
  let stat: { mtimeMs: number; size: number };
@@ -108,12 +133,45 @@ export function peekContextUsage(session: {
108
133
  return null;
109
134
  }
110
135
  const memo = files.get(path);
111
- if (memo && memo.mtimeMs === stat.mtimeMs && memo.size === stat.size) return memo.usage;
136
+ if (memo && memo.mtimeMs === stat.mtimeMs && memo.size === stat.size) return memo;
137
+ const lines = readTailLines(path, stat.size);
112
138
  // A tail with no assistant line in it (a burst of tool results) keeps the
113
- // last usage seen rather than blanking the gauge until the next reply.
114
- const usage = readLastUsage(path, stat.size) ?? memo?.usage ?? null;
115
- files.set(path, { mtimeMs: stat.mtimeMs, size: stat.size, usage });
116
- return usage;
139
+ // last usage seen rather than blanking the gauge until the next reply;
140
+ // the title likewise outlives a window without its record.
141
+ const next: FileMemo = {
142
+ mtimeMs: stat.mtimeMs,
143
+ size: stat.size,
144
+ usage: lastUsage(lines) ?? memo?.usage ?? null,
145
+ title: lastCustomTitle(lines) ?? memo?.title,
146
+ };
147
+ files.set(path, next);
148
+ return next;
149
+ }
150
+
151
+ /**
152
+ * The title the session was given inside Claude Code (`/rename`), read off
153
+ * the same tail as the context gauge. Undefined when there is no transcript
154
+ * yet or it has never been renamed; the empty string when the name was
155
+ * cleared.
156
+ */
157
+ export function peekTranscriptTitle(session: {
158
+ id: string;
159
+ cwd: string;
160
+ transcript_path?: string | null;
161
+ }): string | undefined {
162
+ return fileMemoFor(session)?.title;
163
+ }
164
+
165
+ /**
166
+ * The session's context usage as of its latest reply, or null when there is
167
+ * no transcript yet or no reply in it.
168
+ */
169
+ export function peekContextUsage(session: {
170
+ id: string;
171
+ cwd: string;
172
+ transcript_path?: string | null;
173
+ }): ContextUsage | null {
174
+ return fileMemoFor(session)?.usage ?? null;
117
175
  }
118
176
 
119
177
  /** The same, as the percentage the sidebar draws; null when unknown. */