claude-mux 0.7.0 → 0.7.1

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 (115) hide show
  1. package/README.md +4 -2
  2. package/dist/cli.d.ts +1 -1
  3. package/dist/cli.js +1 -1
  4. package/dist/utils/version.d.ts +1 -1
  5. package/dist/utils/version.js +1 -1
  6. package/dist/web/client/_app/immutable/chunks/{DU91Ml7U.js → BGcEgn7w.js} +1 -1
  7. package/{web/.svelte-kit/output/client/_app/immutable/chunks/DmdO6ygw.js → dist/web/client/_app/immutable/chunks/By6CYjmE.js} +1 -1
  8. package/dist/web/client/_app/immutable/chunks/{HKNo9LID.js → CR5jMWGV.js} +1 -1
  9. package/{web/.svelte-kit/output/client/_app/immutable/entry/app.CGIBnoln.js → dist/web/client/_app/immutable/entry/app.DmtnygN7.js} +2 -2
  10. package/dist/web/client/_app/immutable/entry/start.fYmelGlC.js +1 -0
  11. package/dist/web/client/_app/immutable/nodes/{0.CqlJ9a31.js → 0.DGDAdwT5.js} +1 -1
  12. package/dist/web/client/_app/immutable/nodes/{1.BQUZh2-w.js → 1.Cg8dWgUN.js} +1 -1
  13. package/dist/web/client/_app/immutable/nodes/{2.CCV1YdgF.js → 2.DItUEo3e.js} +1 -1
  14. package/dist/web/client/_app/immutable/nodes/{3.D9tDCdq8.js → 3.dHui0twF.js} +1 -1
  15. package/dist/web/client/_app/immutable/nodes/{4.BqPyNkFA.js → 4.CiEHP0cr.js} +1 -1
  16. package/dist/web/client/_app/version.json +1 -1
  17. package/dist/web/server/chunks/{0-BHWsmCJv.js → 0-BmRg-l2z.js} +5 -5
  18. package/dist/web/server/chunks/{0-BHWsmCJv.js.map → 0-BmRg-l2z.js.map} +1 -1
  19. package/dist/web/server/chunks/{1-YRx6A8Tm.js → 1-CPgO8U7d.js} +3 -3
  20. package/dist/web/server/chunks/{1-YRx6A8Tm.js.map → 1-CPgO8U7d.js.map} +1 -1
  21. package/dist/web/server/chunks/{2-eC6JuGAo.js → 2--ZO5fZp_.js} +5 -5
  22. package/dist/web/server/chunks/{2-eC6JuGAo.js.map → 2--ZO5fZp_.js.map} +1 -1
  23. package/dist/web/server/chunks/{3-Bk-wV20p.js → 3-7HqSep9c.js} +3 -3
  24. package/dist/web/server/chunks/{3-Bk-wV20p.js.map → 3-7HqSep9c.js.map} +1 -1
  25. package/dist/web/server/chunks/{4-nteBgDrW.js → 4-C1PCdmY0.js} +4 -4
  26. package/dist/web/server/chunks/{4-nteBgDrW.js.map → 4-C1PCdmY0.js.map} +1 -1
  27. package/dist/web/server/index.js +1 -1
  28. package/dist/web/server/index.js.map +1 -1
  29. package/dist/web/server/manifest.js +10 -10
  30. package/dist/web/server/manifest.js.map +1 -1
  31. package/docs/release-checklist.md +8 -34
  32. package/docs/removing-hooks.md +14 -14
  33. package/package.json +1 -1
  34. package/src/cli.ts +1 -1
  35. package/src/utils/version.ts +1 -1
  36. package/web/.svelte-kit/adapter-bun/chunks/internal.js +1 -1
  37. package/web/.svelte-kit/adapter-bun/manifest-full.js +1 -1
  38. package/web/.svelte-kit/adapter-bun/manifest.js +1 -1
  39. package/web/.svelte-kit/adapter-bun/nodes/0.js +1 -1
  40. package/web/.svelte-kit/adapter-bun/nodes/1.js +1 -1
  41. package/web/.svelte-kit/adapter-bun/nodes/2.js +1 -1
  42. package/web/.svelte-kit/adapter-bun/nodes/3.js +1 -1
  43. package/web/.svelte-kit/adapter-bun/nodes/4.js +1 -1
  44. package/web/.svelte-kit/adapter-node/.vite/manifest.json +200 -15
  45. package/web/.svelte-kit/adapter-node/_app/immutable/assets/AllSessionsPanel.BKhqOrbV.css +1 -0
  46. package/web/.svelte-kit/adapter-node/_app/immutable/assets/_layout.WptSHSUl.css +1 -0
  47. package/web/.svelte-kit/adapter-node/_app/immutable/assets/_page.DldLgTc-.css +1 -0
  48. package/web/.svelte-kit/adapter-node/_app/immutable/assets/_page.DoNWy7tW.css +1 -0
  49. package/web/.svelte-kit/adapter-node/chunks/AllSessionsPanel.svelte_svelte_type_style_lang.js +49 -0
  50. package/web/.svelte-kit/adapter-node/chunks/alert-dialog-description.js +2670 -0
  51. package/web/.svelte-kit/adapter-node/chunks/auth.js +59 -0
  52. package/web/.svelte-kit/adapter-node/chunks/button.js +82 -0
  53. package/web/.svelte-kit/adapter-node/chunks/client.js +29 -0
  54. package/web/.svelte-kit/adapter-node/chunks/context.js +28 -16
  55. package/web/.svelte-kit/adapter-node/chunks/events.js +121 -0
  56. package/web/.svelte-kit/adapter-node/chunks/index.js +1 -1
  57. package/web/.svelte-kit/adapter-node/chunks/index2.js +186 -68
  58. package/web/.svelte-kit/adapter-node/chunks/internal.js +5 -90
  59. package/web/.svelte-kit/adapter-node/chunks/pane.js +82 -0
  60. package/web/.svelte-kit/adapter-node/chunks/sessions-json.js +16 -1
  61. package/web/.svelte-kit/adapter-node/chunks/sessions.svelte.js +174 -12
  62. package/web/.svelte-kit/adapter-node/chunks/ws-handlers.js +782 -0
  63. package/web/.svelte-kit/adapter-node/entries/endpoints/api/auth/login/_server.ts.js +22 -0
  64. package/web/.svelte-kit/adapter-node/entries/endpoints/api/auth/logout/_server.ts.js +9 -0
  65. package/web/.svelte-kit/adapter-node/entries/endpoints/api/beads/_server.ts.js +22 -0
  66. package/web/.svelte-kit/adapter-node/entries/endpoints/api/chrome/_server.ts.js +30 -0
  67. package/web/.svelte-kit/adapter-node/entries/endpoints/api/files/image/_server.ts.js +53 -0
  68. package/web/.svelte-kit/adapter-node/entries/endpoints/api/sessions/_id_/kill/_server.ts.js +12 -6
  69. package/web/.svelte-kit/adapter-node/entries/endpoints/api/sessions/_id_/restart/_server.ts.js +40 -0
  70. package/web/.svelte-kit/adapter-node/entries/endpoints/api/sessions/_id_/screenshots/_server.ts.js +28 -0
  71. package/web/.svelte-kit/adapter-node/entries/endpoints/api/sessions/_id_/send/_server.ts.js +11 -4
  72. package/web/.svelte-kit/adapter-node/entries/endpoints/api/sessions/_server.ts.js +1 -78
  73. package/web/.svelte-kit/adapter-node/entries/endpoints/api/sessions/_target_/output/_server.ts.js +2 -2
  74. package/web/.svelte-kit/adapter-node/entries/endpoints/api/tmux/panes/_server.ts.js +21 -0
  75. package/web/.svelte-kit/adapter-node/entries/fallbacks/error.svelte.js +1 -18
  76. package/web/.svelte-kit/adapter-node/entries/hooks.server.js +105 -0
  77. package/web/.svelte-kit/adapter-node/entries/pages/_layout.svelte.js +493 -6
  78. package/web/.svelte-kit/adapter-node/entries/pages/_page.svelte.js +3024 -54
  79. package/web/.svelte-kit/adapter-node/entries/pages/login/_page.server.ts.js +15 -0
  80. package/web/.svelte-kit/adapter-node/entries/pages/login/_page.svelte.js +37 -0
  81. package/web/.svelte-kit/adapter-node/entries/pages/session/_target_/_page.svelte.js +623 -46
  82. package/web/.svelte-kit/adapter-node/manifest-full.js +67 -3
  83. package/web/.svelte-kit/adapter-node/manifest.js +67 -3
  84. package/web/.svelte-kit/adapter-node/nodes/0.js +2 -2
  85. package/web/.svelte-kit/adapter-node/nodes/1.js +1 -1
  86. package/web/.svelte-kit/adapter-node/nodes/2.js +2 -2
  87. package/web/.svelte-kit/adapter-node/nodes/3.js +6 -4
  88. package/web/.svelte-kit/adapter-node/nodes/4.js +8 -0
  89. package/web/.svelte-kit/ambient.d.ts +28 -2
  90. package/web/.svelte-kit/generated/server/internal.js +1 -1
  91. package/web/.svelte-kit/output/client/.vite/manifest.json +44 -44
  92. package/web/.svelte-kit/output/client/_app/immutable/chunks/{DU91Ml7U.js → BGcEgn7w.js} +1 -1
  93. package/{dist/web/client/_app/immutable/chunks/DmdO6ygw.js → web/.svelte-kit/output/client/_app/immutable/chunks/By6CYjmE.js} +1 -1
  94. package/web/.svelte-kit/output/client/_app/immutable/chunks/{HKNo9LID.js → CR5jMWGV.js} +1 -1
  95. package/{dist/web/client/_app/immutable/entry/app.CGIBnoln.js → web/.svelte-kit/output/client/_app/immutable/entry/app.DmtnygN7.js} +2 -2
  96. package/web/.svelte-kit/output/client/_app/immutable/entry/start.fYmelGlC.js +1 -0
  97. package/web/.svelte-kit/output/client/_app/immutable/nodes/{0.CqlJ9a31.js → 0.DGDAdwT5.js} +1 -1
  98. package/web/.svelte-kit/output/client/_app/immutable/nodes/{1.BQUZh2-w.js → 1.Cg8dWgUN.js} +1 -1
  99. package/web/.svelte-kit/output/client/_app/immutable/nodes/{2.CCV1YdgF.js → 2.DItUEo3e.js} +1 -1
  100. package/web/.svelte-kit/output/client/_app/immutable/nodes/{3.D9tDCdq8.js → 3.dHui0twF.js} +1 -1
  101. package/web/.svelte-kit/output/client/_app/immutable/nodes/{4.BqPyNkFA.js → 4.CiEHP0cr.js} +1 -1
  102. package/web/.svelte-kit/output/client/_app/version.json +1 -1
  103. package/web/.svelte-kit/output/server/chunks/internal.js +1 -1
  104. package/web/.svelte-kit/output/server/manifest-full.js +1 -1
  105. package/web/.svelte-kit/output/server/manifest.js +1 -1
  106. package/web/.svelte-kit/output/server/nodes/0.js +1 -1
  107. package/web/.svelte-kit/output/server/nodes/1.js +1 -1
  108. package/web/.svelte-kit/output/server/nodes/2.js +1 -1
  109. package/web/.svelte-kit/output/server/nodes/3.js +1 -1
  110. package/web/.svelte-kit/output/server/nodes/4.js +1 -1
  111. package/dist/web/client/_app/immutable/entry/start.CJk8zB1j.js +0 -1
  112. package/web/.svelte-kit/adapter-node/_app/immutable/assets/_layout.4NiX29PU.css +0 -1
  113. package/web/.svelte-kit/adapter-node/_app/immutable/assets/_page.BEMzYUGV.css +0 -1
  114. package/web/.svelte-kit/adapter-node/_app/immutable/assets/_page.DOJn7TG7.css +0 -1
  115. package/web/.svelte-kit/output/client/_app/immutable/entry/start.CJk8zB1j.js +0 -1
@@ -1,73 +1,650 @@
1
- import { a3 as store_get, Z as head, a1 as attr_style, a2 as stringify, $ as attr, a4 as unsubscribe_stores } from "../../../../chunks/index2.js";
2
- import { g as getContext, e as escape_html } from "../../../../chunks/context.js";
1
+ import { a5 as derived, Z as attr_class, a1 as ensure_array_like, $ as stringify, a2 as store_get, a3 as unsubscribe_stores, a4 as head, _ as attr_style, a0 as attr } from "../../../../chunks/index2.js";
2
+ import { R as ReliableWebSocket, s as sessionStore, o as onDestroy, p as page, a as stateColor } from "../../../../chunks/sessions.svelte.js";
3
+ import { g as goto } from "../../../../chunks/client.js";
3
4
  import "clsx";
4
- import "@sveltejs/kit/internal";
5
- import "../../../../chunks/exports.js";
6
- import "../../../../chunks/utils.js";
7
- import "@sveltejs/kit/internal/server";
8
- import "../../../../chunks/state.svelte.js";
9
- import { s as sessionStore, o as onDestroy, a as stateColor } from "../../../../chunks/sessions.svelte.js";
10
- const getStores = () => {
11
- const stores$1 = getContext("__svelte__");
12
- return {
13
- /** @type {typeof page} */
14
- page: {
15
- subscribe: stores$1.page.subscribe
16
- },
17
- /** @type {typeof navigating} */
18
- navigating: {
19
- subscribe: stores$1.navigating.subscribe
20
- },
21
- /** @type {typeof updated} */
22
- updated: stores$1.updated
23
- };
5
+ import { B as Button } from "../../../../chunks/button.js";
6
+ import { A as Alert_dialog, x as Alert_dialog_content, y as Alert_dialog_header, z as Alert_dialog_title, B as Alert_dialog_description, G as Alert_dialog_footer, H as Alert_dialog_cancel, I as Alert_dialog_action } from "../../../../chunks/alert-dialog-description.js";
7
+ import { e as escape_html } from "../../../../chunks/context.js";
8
+ function html(value) {
9
+ var html2 = String(value ?? "");
10
+ var open = "<!---->";
11
+ return open + html2 + "<!---->";
12
+ }
13
+ const PATTERNS = {
14
+ // User prompt starts with ❯ (Unicode chevron only - ASCII > is used for selection indicators)
15
+ userPrompt: /^❯\s/,
16
+ // Claude response starts with ● (filled circle) followed by actual text
17
+ claudeResponse: /^●\s+\S/,
18
+ // Working indicator: just ● alone or with whitespace (no content after)
19
+ workingIndicator: /^●\s*$/,
20
+ // Tool result starts with ⎿ (with optional leading whitespace)
21
+ toolResult: /^(\s*)⎿/,
22
+ // Indented content (2+ spaces at start) - continues tool results
23
+ indentedContent: /^(\s{2,}|\t)/,
24
+ // Separator is 5+ dashes
25
+ separator: /^─{5,}/,
26
+ // Tool call: ● ToolName(...) or ● tool-name (...)
27
+ toolCall: /^●\s+([\w-]+)\s*\(/,
28
+ // MCP tool call: ● mcp-server - tool_name (MCP)
29
+ mcpToolCall: /^●\s+([\w-]+)\s+-\s+([\w_]+)\s+\(MCP\)/,
30
+ // Braille spinner characters
31
+ spinner: /[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⠐⠂⠄]/,
32
+ // Status hints
33
+ statusHint: /(Esc to interrupt|ctrl\+c to interrupt|Esc to cancel|to cycle\))/i,
34
+ // Progress bar or status line at bottom
35
+ progressBar: /^\s*[\w-]+\s+\[.*\]\s+\w+@/
24
36
  };
25
- const page = {
26
- subscribe(fn) {
27
- const store = getStores().page;
28
- return store.subscribe(fn);
37
+ function classifyLine(line, previousType) {
38
+ if (PATTERNS.separator.test(line)) return "separator";
39
+ if (PATTERNS.mcpToolCall.test(line)) return "tool-call";
40
+ if (PATTERNS.toolCall.test(line)) return "tool-call";
41
+ if (PATTERNS.workingIndicator.test(line)) return "spinner";
42
+ if (PATTERNS.userPrompt.test(line)) return "user-prompt";
43
+ if (PATTERNS.claudeResponse.test(line)) return "claude-response";
44
+ if (PATTERNS.toolResult.test(line)) return "tool-result";
45
+ if (previousType === "tool-call" && PATTERNS.indentedContent.test(line)) {
46
+ return "tool-call";
47
+ }
48
+ if (previousType === "tool-result" && PATTERNS.indentedContent.test(line)) {
49
+ return "tool-result";
50
+ }
51
+ if (PATTERNS.statusHint.test(line) || PATTERNS.progressBar.test(line)) return "status";
52
+ if (PATTERNS.spinner.test(line) && line.length < 100) return "spinner";
53
+ return "plain";
54
+ }
55
+ function extractToolName(line) {
56
+ const mcpMatch = line.match(PATTERNS.mcpToolCall);
57
+ if (mcpMatch) {
58
+ return `${mcpMatch[1]}:${mcpMatch[2]}`;
59
+ }
60
+ const match = line.match(PATTERNS.toolCall);
61
+ if (match) {
62
+ return match[1];
63
+ }
64
+ return void 0;
65
+ }
66
+ function isNewToolCall(line) {
67
+ return PATTERNS.toolCall.test(line) || PATTERNS.mcpToolCall.test(line);
68
+ }
69
+ const TRANSITIONS = {
70
+ "user-prompt": {
71
+ "plain": false,
72
+ // Multi-line user input continues
73
+ "spinner": false
74
+ // Spinners during input don't break
75
+ },
76
+ "claude-response": {
77
+ "plain": false,
78
+ // Response text continues
79
+ "spinner": false
80
+ // Spinners during response don't break
81
+ },
82
+ "tool-call": {
83
+ "tool-call": false,
84
+ // Continuation lines (handled specially for new tool calls)
85
+ "tool-result": false,
86
+ // Results follow tool calls
87
+ "spinner": false
88
+ // Spinners during execution don't break
89
+ },
90
+ "tool-result": {
91
+ "tool-result": false,
92
+ // Multiple result lines continue
93
+ "spinner": false
94
+ // Spinners during results don't break
95
+ },
96
+ "separator": {
97
+ // Separators always break - no continues
98
+ },
99
+ "status": {
100
+ "status": false
101
+ // Status lines group together
102
+ },
103
+ "spinner": {
104
+ "spinner": false
105
+ // Multiple spinner frames group together
106
+ },
107
+ "plain": {
108
+ "plain": false
109
+ // Plain content groups together
29
110
  }
30
111
  };
31
- class TerminalStore {
112
+ function shouldStartNewBlock(current, newType, line) {
113
+ if (!current) return true;
114
+ if (newType === "separator" || newType === "user-prompt") {
115
+ return true;
116
+ }
117
+ if (newType === "tool-call" && isNewToolCall(line)) {
118
+ return true;
119
+ }
120
+ const transition = TRANSITIONS[current.type]?.[newType];
121
+ if (transition !== void 0) {
122
+ return transition;
123
+ }
124
+ return current.type !== newType;
125
+ }
126
+ function parseTerminalOutput(output) {
127
+ if (!output || output.trim() === "") {
128
+ return [];
129
+ }
130
+ const lines = output.split("\n");
131
+ const blocks = [];
132
+ let currentBlock = null;
133
+ let blockIdCounter = 0;
134
+ for (const line of lines) {
135
+ if (line.trim() === "") {
136
+ continue;
137
+ }
138
+ const previousType = currentBlock?.type ?? null;
139
+ const blockType = classifyLine(line, previousType);
140
+ if (shouldStartNewBlock(currentBlock, blockType, line)) {
141
+ if (currentBlock && currentBlock.content.trim()) {
142
+ blocks.push(currentBlock);
143
+ }
144
+ currentBlock = {
145
+ id: ++blockIdCounter,
146
+ type: blockType,
147
+ content: line
148
+ };
149
+ if (blockType === "tool-call") {
150
+ const toolName = extractToolName(line);
151
+ if (toolName) {
152
+ currentBlock.metadata = { toolName };
153
+ }
154
+ }
155
+ } else if (currentBlock) {
156
+ currentBlock.content += "\n" + line;
157
+ }
158
+ }
159
+ if (currentBlock && currentBlock.content.trim()) {
160
+ blocks.push(currentBlock);
161
+ }
162
+ return blocks;
163
+ }
164
+ function getBlockStats(blocks) {
165
+ return {
166
+ userPrompts: blocks.filter((b) => b.type === "user-prompt").length,
167
+ claudeResponses: blocks.filter((b) => b.type === "claude-response").length,
168
+ toolCalls: blocks.filter((b) => b.type === "tool-call").length,
169
+ hasActiveSpinner: blocks.some((b) => b.type === "spinner")
170
+ };
171
+ }
172
+ class TerminalStore extends ReliableWebSocket {
32
173
  output = "";
33
- connected = false;
34
- ws = null;
35
- reconnectTimer = null;
174
+ #parsedBlocks = derived(() => parseTerminalOutput(this.output));
175
+ get parsedBlocks() {
176
+ return this.#parsedBlocks();
177
+ }
178
+ set parsedBlocks($$value) {
179
+ return this.#parsedBlocks($$value);
180
+ }
181
+ #stats = derived(() => getBlockStats(this.parsedBlocks));
182
+ get stats() {
183
+ return this.#stats();
184
+ }
185
+ set stats($$value) {
186
+ return this.#stats($$value);
187
+ }
36
188
  target = null;
189
+ resizeTimer = null;
190
+ lastSentSize = null;
191
+ getWsUrl() {
192
+ const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
193
+ const encodedTarget = encodeURIComponent(this.target);
194
+ return `${protocol}//${window.location.host}/api/sessions/${encodedTarget}/stream`;
195
+ }
196
+ getLogPrefix() {
197
+ return "[terminal]";
198
+ }
199
+ shouldReconnect() {
200
+ return this.target !== null;
201
+ }
202
+ handleMessage(event) {
203
+ const data = JSON.parse(event.data);
204
+ if (data.output !== void 0) {
205
+ this.output = data.output;
206
+ }
207
+ }
37
208
  connect(target) {
38
209
  return;
39
210
  }
40
211
  disconnect() {
41
- this.target = null;
42
- this.ws?.close();
43
- this.ws = null;
44
- if (this.reconnectTimer) {
45
- clearTimeout(this.reconnectTimer);
46
- this.reconnectTimer = null;
212
+ if (this.resizeTimer) {
213
+ clearTimeout(this.resizeTimer);
214
+ this.resizeTimer = null;
47
215
  }
216
+ this.lastSentSize = null;
217
+ this.target = null;
218
+ this.doDisconnect();
219
+ }
220
+ sendResize(cols, rows) {
221
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
222
+ if (this.lastSentSize?.cols === cols && this.lastSentSize?.rows === rows) return;
223
+ if (this.resizeTimer) clearTimeout(this.resizeTimer);
224
+ this.resizeTimer = setTimeout(
225
+ () => {
226
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
227
+ this.ws.send(JSON.stringify({ type: "resize", cols, rows }));
228
+ this.lastSentSize = { cols, rows };
229
+ }
230
+ this.resizeTimer = null;
231
+ },
232
+ 150
233
+ );
48
234
  }
49
235
  }
50
236
  const terminalStore = new TerminalStore();
237
+ const defaults = { terminalTheming: true };
238
+ function loadPreferences() {
239
+ return defaults;
240
+ }
241
+ function savePreferences(prefs) {
242
+ return;
243
+ }
244
+ class PreferencesStore {
245
+ prefs = loadPreferences();
246
+ get terminalTheming() {
247
+ return this.prefs.terminalTheming;
248
+ }
249
+ set terminalTheming(value) {
250
+ this.prefs.terminalTheming = value;
251
+ savePreferences(this.prefs);
252
+ }
253
+ toggle(key) {
254
+ if (typeof this.prefs[key] === "boolean") {
255
+ this.prefs[key] = !this.prefs[key];
256
+ savePreferences(this.prefs);
257
+ }
258
+ }
259
+ }
260
+ const preferences = new PreferencesStore();
261
+ function TerminalRenderer($$renderer, $$props) {
262
+ $$renderer.component(($$renderer2) => {
263
+ const { blocks, class: className = "" } = $$props;
264
+ const typeStyles = {
265
+ "user-prompt": "terminal-user-prompt",
266
+ "claude-response": "terminal-claude-response",
267
+ "tool-call": "terminal-tool-call",
268
+ "tool-result": "terminal-tool-result",
269
+ separator: "terminal-separator",
270
+ status: "terminal-status",
271
+ spinner: "terminal-spinner",
272
+ plain: "terminal-plain"
273
+ };
274
+ const toolColors = {
275
+ // File operations
276
+ "Read": "tool-read",
277
+ "Write": "tool-write",
278
+ "Edit": "tool-edit",
279
+ "Update": "tool-edit",
280
+ "NotebookEdit": "tool-edit",
281
+ "Glob": "tool-search",
282
+ "Grep": "tool-search",
283
+ "Search": "tool-search",
284
+ // Execution
285
+ "Bash": "tool-bash",
286
+ "Task": "tool-task",
287
+ // Web operations
288
+ "WebFetch": "tool-web",
289
+ "WebSearch": "tool-web",
290
+ // Todo
291
+ "TodoWrite": "tool-todo",
292
+ // Browser/MCP
293
+ "chrome-devtools": "tool-browser",
294
+ "mcp": "tool-browser"
295
+ };
296
+ function getToolClass(toolName) {
297
+ if (!toolName) return "tool-default";
298
+ if (toolColors[toolName]) return toolColors[toolName];
299
+ for (const [key, value] of Object.entries(toolColors)) {
300
+ if (toolName.toLowerCase().includes(key.toLowerCase())) return value;
301
+ }
302
+ return "tool-default";
303
+ }
304
+ function processDiffContent(content) {
305
+ return content.split("\n").map((line) => {
306
+ if (/^\s*\d+\s*\+/.test(line)) {
307
+ return `<span class="diff-add">${escapeHtml(line)}</span>`;
308
+ }
309
+ if (/^\s*\d+\s*-/.test(line)) {
310
+ return `<span class="diff-remove">${escapeHtml(line)}</span>`;
311
+ }
312
+ return escapeHtml(line);
313
+ }).join("\n");
314
+ }
315
+ function escapeHtml(text) {
316
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
317
+ }
318
+ $$renderer2.push(`<pre${attr_class(`terminal-renderer ${stringify(className)}`, "svelte-k7hba9")}><!--[-->`);
319
+ const each_array = ensure_array_like(blocks);
320
+ for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
321
+ let block = each_array[$$index];
322
+ $$renderer2.push(`<span${attr_class(`terminal-block ${stringify(typeStyles[block.type] || "terminal-plain")} ${stringify(block.type === "tool-call" ? getToolClass(block.metadata?.toolName) : "")}`, "svelte-k7hba9")}>`);
323
+ if (block.type === "tool-call" && block.metadata?.toolName) {
324
+ $$renderer2.push("<!--[-->");
325
+ $$renderer2.push(`<span${attr_class(`tool-badge ${stringify(getToolClass(block.metadata.toolName))}`, "svelte-k7hba9")}>${escape_html(block.metadata.toolName)}</span>`);
326
+ } else {
327
+ $$renderer2.push("<!--[!-->");
328
+ }
329
+ $$renderer2.push(`<!--]-->`);
330
+ if (block.type === "tool-result") {
331
+ $$renderer2.push("<!--[-->");
332
+ $$renderer2.push(`${html(processDiffContent(block.content))}`);
333
+ } else {
334
+ $$renderer2.push("<!--[!-->");
335
+ $$renderer2.push(`${escape_html(block.content)}`);
336
+ }
337
+ $$renderer2.push(`<!--]--></span>
338
+ `);
339
+ }
340
+ $$renderer2.push(`<!--]--></pre>`);
341
+ });
342
+ }
51
343
  function _page($$renderer, $$props) {
52
344
  $$renderer.component(($$renderer2) => {
53
345
  var $$store_subs;
54
- const target = decodeURIComponent(store_get($$store_subs ??= {}, "$page", page).params.target);
346
+ const target = store_get($$store_subs ??= {}, "$page", page).params.target ? decodeURIComponent(store_get($$store_subs ??= {}, "$page", page).params.target) : null;
55
347
  const currentSession = sessionStore.sessions.find((s) => s.tmux_target === target || s.id === target);
56
348
  let textInput = "";
349
+ let showConfirmKill = false;
350
+ let showCopied = false;
351
+ function calculateTerminalSize() {
352
+ return null;
353
+ }
354
+ function handleResize() {
355
+ const size = calculateTerminalSize();
356
+ if (size) terminalStore.sendResize(size.cols, size.rows);
357
+ }
57
358
  onDestroy(() => {
58
359
  terminalStore.disconnect();
59
- sessionStore.disconnect();
60
360
  });
61
- head("15bjeev", $$renderer2, ($$renderer3) => {
62
- $$renderer3.title(($$renderer4) => {
63
- $$renderer4.push(`<title>${escape_html(target)}</title>`);
361
+ async function sendKeys(keys) {
362
+ await fetch(`/api/sessions/${encodeURIComponent(target)}/send`, {
363
+ method: "POST",
364
+ headers: { "Content-Type": "application/json" },
365
+ body: JSON.stringify({ keys })
64
366
  });
65
- });
66
- $$renderer2.push(`<div class="container svelte-15bjeev"><header class="header svelte-15bjeev"><a href="/" class="back svelte-15bjeev"><iconify-icon icon="mdi:arrow-left"></iconify-icon></a> <div class="title-row svelte-15bjeev"><span class="state svelte-15bjeev"${attr_style(`background: ${stringify(stateColor(currentSession?.state || "idle"))}`)}></span> <span class="target svelte-15bjeev">${escape_html(currentSession?.pane_title || target)}</span></div> <div class="header-actions svelte-15bjeev"><button title="Copy tmux attach command" class="svelte-15bjeev"><iconify-icon icon="mdi:content-copy"></iconify-icon></button> <button title="Stop (Esc)" class="svelte-15bjeev"><iconify-icon icon="mdi:stop"></iconify-icon></button> <button class="danger svelte-15bjeev" title="Kill Session"><iconify-icon icon="mdi:power"></iconify-icon></button></div></header> <pre class="output svelte-15bjeev">${escape_html(terminalStore.output)}</pre> <div class="toolbar svelte-15bjeev"><button class="svelte-15bjeev"><iconify-icon icon="mdi:arrow-up"></iconify-icon></button> <button class="svelte-15bjeev"><iconify-icon icon="mdi:arrow-down"></iconify-icon></button> <button class="svelte-15bjeev">Space</button> <button class="svelte-15bjeev">Tab</button> <button class="svelte-15bjeev"><iconify-icon icon="mdi:keyboard-return"></iconify-icon></button> <button class="svelte-15bjeev">Clear</button> <button class="danger svelte-15bjeev">Ctrl-C</button></div> <form class="input-row svelte-15bjeev"><input type="text"${attr("value", textInput)} placeholder="Type a message..." class="svelte-15bjeev"/> <button type="submit" class="svelte-15bjeev"><iconify-icon icon="mdi:send"></iconify-icon></button></form></div> `);
67
- {
68
- $$renderer2.push("<!--[!-->");
69
367
  }
70
- $$renderer2.push(`<!--]-->`);
368
+ async function killSession() {
369
+ if (!currentSession) return;
370
+ await fetch(`/api/sessions/${encodeURIComponent(currentSession.id)}/kill`, {
371
+ method: "POST",
372
+ headers: { "Content-Type": "application/json" },
373
+ body: JSON.stringify({
374
+ pid: currentSession.pid,
375
+ tmux_target: currentSession.tmux_target
376
+ })
377
+ });
378
+ showConfirmKill = false;
379
+ goto();
380
+ }
381
+ function copyTmuxCmd() {
382
+ if (!target) return;
383
+ const cmd = `tmux attach -t "${target.split(":")[0]}"`;
384
+ if (navigator.clipboard?.writeText) {
385
+ navigator.clipboard.writeText(cmd);
386
+ } else {
387
+ const textarea = document.createElement("textarea");
388
+ textarea.value = cmd;
389
+ textarea.style.position = "fixed";
390
+ textarea.style.opacity = "0";
391
+ document.body.appendChild(textarea);
392
+ textarea.select();
393
+ document.execCommand("copy");
394
+ document.body.removeChild(textarea);
395
+ }
396
+ showCopied = true;
397
+ setTimeout(
398
+ () => {
399
+ showCopied = false;
400
+ },
401
+ 2e3
402
+ );
403
+ }
404
+ let $$settled = true;
405
+ let $$inner_renderer;
406
+ function $$render_inner($$renderer3) {
407
+ head("15bjeev", $$renderer3, ($$renderer4) => {
408
+ $$renderer4.title(($$renderer5) => {
409
+ $$renderer5.push(`<title>${escape_html(currentSession?.pane_title || target || "Session")}</title>`);
410
+ });
411
+ $$renderer4.push(`<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/> <link rel="preconnect" href="https://fonts.googleapis.com"/> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous"/> <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&amp;display=swap" rel="stylesheet"/>`);
412
+ });
413
+ $$renderer3.push(`<div class="session-container svelte-15bjeev"><header class="header svelte-15bjeev"><div class="title-row svelte-15bjeev"><span class="state svelte-15bjeev"${attr_style(`background: ${stringify(stateColor(currentSession?.state || "idle"))}`)}></span> <div class="title-info svelte-15bjeev"><span class="target svelte-15bjeev">${escape_html(currentSession?.pane_title || target)}</span> <span class="status svelte-15bjeev">${escape_html(currentSession?.current_action || currentSession?.state || "idle")}</span></div></div> <div class="header-actions svelte-15bjeev">`);
414
+ Button($$renderer3, {
415
+ variant: "secondary",
416
+ size: "toolbar",
417
+ onclick: copyTmuxCmd,
418
+ title: "Copy tmux attach command",
419
+ class: showCopied ? "bg-green-800 text-green-300" : "",
420
+ children: ($$renderer4) => {
421
+ $$renderer4.push(`<iconify-icon${attr("icon", showCopied ? "mdi:check" : "mdi:content-copy")}></iconify-icon> <span>${escape_html(showCopied ? "Copied!" : "Tmux")}</span>`);
422
+ },
423
+ $$slots: { default: true }
424
+ });
425
+ $$renderer3.push(`<!----> `);
426
+ Button($$renderer3, {
427
+ variant: "secondary",
428
+ size: "toolbar",
429
+ onclick: handleResize,
430
+ title: "Resize tmux pane to fit viewport",
431
+ children: ($$renderer4) => {
432
+ $$renderer4.push(`<iconify-icon icon="mdi:fit-to-screen"></iconify-icon> <span>Fit</span>`);
433
+ },
434
+ $$slots: { default: true }
435
+ });
436
+ $$renderer3.push(`<!----> `);
437
+ Button($$renderer3, {
438
+ variant: preferences.terminalTheming ? "secondary" : "ghost",
439
+ size: "toolbar",
440
+ onclick: () => preferences.toggle("terminalTheming"),
441
+ title: "Toggle syntax highlighting",
442
+ children: ($$renderer4) => {
443
+ $$renderer4.push(`<iconify-icon${attr("icon", preferences.terminalTheming ? "mdi:palette" : "mdi:palette-outline")}></iconify-icon> <span>Theme</span>`);
444
+ },
445
+ $$slots: { default: true }
446
+ });
447
+ $$renderer3.push(`<!----> `);
448
+ Button($$renderer3, {
449
+ variant: "ghost-destructive",
450
+ size: "toolbar",
451
+ onclick: () => showConfirmKill = true,
452
+ title: "Kill Session",
453
+ children: ($$renderer4) => {
454
+ $$renderer4.push(`<iconify-icon icon="mdi:power"></iconify-icon> <span>Kill</span>`);
455
+ },
456
+ $$slots: { default: true }
457
+ });
458
+ $$renderer3.push(`<!----></div></header> <div class="output svelte-15bjeev">`);
459
+ if (preferences.terminalTheming) {
460
+ $$renderer3.push("<!--[-->");
461
+ TerminalRenderer($$renderer3, { blocks: terminalStore.parsedBlocks });
462
+ } else {
463
+ $$renderer3.push("<!--[!-->");
464
+ $$renderer3.push(`<pre class="raw-output svelte-15bjeev">${escape_html(terminalStore.output)}</pre>`);
465
+ }
466
+ $$renderer3.push(`<!--]--></div> <div class="toolbar svelte-15bjeev">`);
467
+ Button($$renderer3, {
468
+ variant: "secondary",
469
+ size: "toolbar",
470
+ class: "flex-1",
471
+ onclick: () => sendKeys("Up"),
472
+ children: ($$renderer4) => {
473
+ $$renderer4.push(`<iconify-icon icon="mdi:arrow-up"></iconify-icon> <span>Up</span>`);
474
+ },
475
+ $$slots: { default: true }
476
+ });
477
+ $$renderer3.push(`<!----> `);
478
+ Button($$renderer3, {
479
+ variant: "secondary",
480
+ size: "toolbar",
481
+ class: "flex-1",
482
+ onclick: () => sendKeys("Down"),
483
+ children: ($$renderer4) => {
484
+ $$renderer4.push(`<iconify-icon icon="mdi:arrow-down"></iconify-icon> <span>Down</span>`);
485
+ },
486
+ $$slots: { default: true }
487
+ });
488
+ $$renderer3.push(`<!----> `);
489
+ Button($$renderer3, {
490
+ variant: "secondary",
491
+ size: "toolbar",
492
+ class: "flex-1",
493
+ onclick: () => sendKeys("Space"),
494
+ children: ($$renderer4) => {
495
+ $$renderer4.push(`<iconify-icon icon="mdi:keyboard-space"></iconify-icon> <span>Space</span>`);
496
+ },
497
+ $$slots: { default: true }
498
+ });
499
+ $$renderer3.push(`<!----> `);
500
+ Button($$renderer3, {
501
+ variant: "secondary",
502
+ size: "toolbar",
503
+ class: "flex-1",
504
+ onclick: () => sendKeys("Tab"),
505
+ children: ($$renderer4) => {
506
+ $$renderer4.push(`<iconify-icon icon="mdi:keyboard-tab"></iconify-icon> <span>Tab</span>`);
507
+ },
508
+ $$slots: { default: true }
509
+ });
510
+ $$renderer3.push(`<!----> `);
511
+ Button($$renderer3, {
512
+ variant: "secondary",
513
+ size: "toolbar",
514
+ class: "flex-1",
515
+ onclick: () => sendKeys("C-l"),
516
+ children: ($$renderer4) => {
517
+ $$renderer4.push(`<iconify-icon icon="mdi:eraser"></iconify-icon> <span>Ctrl-L</span>`);
518
+ },
519
+ $$slots: { default: true }
520
+ });
521
+ $$renderer3.push(`<!----> `);
522
+ Button($$renderer3, {
523
+ variant: "secondary",
524
+ size: "toolbar",
525
+ class: "flex-1",
526
+ onclick: async () => {
527
+ await fetch(`/api/sessions/${encodeURIComponent(target)}/send`, {
528
+ method: "POST",
529
+ headers: { "Content-Type": "application/json" },
530
+ body: JSON.stringify({ text: "/clear" })
531
+ });
532
+ },
533
+ children: ($$renderer4) => {
534
+ $$renderer4.push(`<iconify-icon icon="mdi:broom"></iconify-icon> <span>/clear</span>`);
535
+ },
536
+ $$slots: { default: true }
537
+ });
538
+ $$renderer3.push(`<!----> `);
539
+ Button($$renderer3, {
540
+ variant: "secondary",
541
+ size: "toolbar",
542
+ class: "flex-1",
543
+ onclick: () => sendKeys("Escape"),
544
+ children: ($$renderer4) => {
545
+ $$renderer4.push(`<iconify-icon icon="mdi:stop"></iconify-icon> <span>Esc</span>`);
546
+ },
547
+ $$slots: { default: true }
548
+ });
549
+ $$renderer3.push(`<!----> `);
550
+ Button($$renderer3, {
551
+ variant: "ghost-destructive",
552
+ size: "toolbar",
553
+ class: "flex-1",
554
+ onclick: () => sendKeys("C-c"),
555
+ children: ($$renderer4) => {
556
+ $$renderer4.push(`<iconify-icon icon="mdi:cancel"></iconify-icon> <span>Ctrl-C</span>`);
557
+ },
558
+ $$slots: { default: true }
559
+ });
560
+ $$renderer3.push(`<!----></div> <form class="input-row svelte-15bjeev"><textarea placeholder="Type a message..."${attr("rows", 1)} class="svelte-15bjeev">`);
561
+ const $$body = escape_html(textInput);
562
+ if ($$body) {
563
+ $$renderer3.push(`${$$body}`);
564
+ }
565
+ $$renderer3.push(`</textarea> `);
566
+ Button($$renderer3, {
567
+ type: "submit",
568
+ variant: "success",
569
+ class: "min-w-[52px] min-h-[48px] text-lg",
570
+ children: ($$renderer4) => {
571
+ $$renderer4.push(`<iconify-icon icon="mdi:send"></iconify-icon>`);
572
+ },
573
+ $$slots: { default: true }
574
+ });
575
+ $$renderer3.push(`<!----></form></div> <!---->`);
576
+ Alert_dialog?.($$renderer3, {
577
+ get open() {
578
+ return showConfirmKill;
579
+ },
580
+ set open($$value) {
581
+ showConfirmKill = $$value;
582
+ $$settled = false;
583
+ },
584
+ children: ($$renderer4) => {
585
+ $$renderer4.push(`<!---->`);
586
+ Alert_dialog_content?.($$renderer4, {
587
+ children: ($$renderer5) => {
588
+ $$renderer5.push(`<!---->`);
589
+ Alert_dialog_header?.($$renderer5, {
590
+ children: ($$renderer6) => {
591
+ $$renderer6.push(`<!---->`);
592
+ Alert_dialog_title?.($$renderer6, {
593
+ children: ($$renderer7) => {
594
+ $$renderer7.push(`<!---->Kill this session?`);
595
+ },
596
+ $$slots: { default: true }
597
+ });
598
+ $$renderer6.push(`<!----> <!---->`);
599
+ Alert_dialog_description?.($$renderer6, {
600
+ children: ($$renderer7) => {
601
+ $$renderer7.push(`<!---->This will terminate the Claude process.`);
602
+ },
603
+ $$slots: { default: true }
604
+ });
605
+ $$renderer6.push(`<!---->`);
606
+ },
607
+ $$slots: { default: true }
608
+ });
609
+ $$renderer5.push(`<!----> <!---->`);
610
+ Alert_dialog_footer?.($$renderer5, {
611
+ children: ($$renderer6) => {
612
+ $$renderer6.push(`<!---->`);
613
+ Alert_dialog_cancel?.($$renderer6, {
614
+ children: ($$renderer7) => {
615
+ $$renderer7.push(`<!---->Cancel`);
616
+ },
617
+ $$slots: { default: true }
618
+ });
619
+ $$renderer6.push(`<!----> <!---->`);
620
+ Alert_dialog_action?.($$renderer6, {
621
+ onclick: killSession,
622
+ class: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
623
+ children: ($$renderer7) => {
624
+ $$renderer7.push(`<!---->Kill`);
625
+ },
626
+ $$slots: { default: true }
627
+ });
628
+ $$renderer6.push(`<!---->`);
629
+ },
630
+ $$slots: { default: true }
631
+ });
632
+ $$renderer5.push(`<!---->`);
633
+ },
634
+ $$slots: { default: true }
635
+ });
636
+ $$renderer4.push(`<!---->`);
637
+ },
638
+ $$slots: { default: true }
639
+ });
640
+ $$renderer3.push(`<!---->`);
641
+ }
642
+ do {
643
+ $$settled = true;
644
+ $$inner_renderer = $$renderer2.copy();
645
+ $$render_inner($$inner_renderer);
646
+ } while (!$$settled);
647
+ $$renderer2.subsume($$inner_renderer);
71
648
  if ($$store_subs) unsubscribe_stores($$store_subs);
72
649
  });
73
650
  }