@duckmind/dm-darwin-x64 0.32.9 → 0.33.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 (95) hide show
  1. package/dm +0 -0
  2. package/extensions/.dm-extensions.json +14 -65
  3. package/extensions/dm-9router-ext/README.md +142 -0
  4. package/extensions/dm-9router-ext/package.json +45 -0
  5. package/extensions/dm-9router-ext/src/index.ts +541 -0
  6. package/extensions/dm-9router-ext/tsconfig.json +17 -0
  7. package/extensions/dm-subagents/package-lock.json +3 -3
  8. package/extensions/dm-tasks/node_modules/.package-lock.json +3 -3
  9. package/extensions/dm-tasks/node_modules/typebox/build/type/script/mapping.d.mts +2 -2
  10. package/extensions/dm-tasks/node_modules/typebox/build/type/script/parser.d.mts +2 -2
  11. package/extensions/dm-tasks/node_modules/typebox/build/type/script/parser.mjs +2 -2
  12. package/extensions/dm-tasks/node_modules/typebox/build/type/types/number.d.mts +1 -1
  13. package/extensions/dm-tasks/node_modules/typebox/build/type/types/number.mjs +1 -1
  14. package/extensions/dm-tasks/node_modules/typebox/build/type/types/record.d.mts +1 -1
  15. package/extensions/dm-tasks/node_modules/typebox/package.json +1 -1
  16. package/extensions/dm-tasks/package-lock.json +3 -3
  17. package/package.json +1 -1
  18. package/theme/theme-alps.json +93 -0
  19. package/extensions/dm-chime/README.md +0 -11
  20. package/extensions/dm-chime/docs/protocols.md +0 -107
  21. package/extensions/dm-chime/index.ts +0 -205
  22. package/extensions/dm-chime/package.json +0 -33
  23. package/extensions/dm-phone/README.md +0 -24
  24. package/extensions/dm-phone/index.ts +0 -12
  25. package/extensions/dm-phone/node_modules/.package-lock.json +0 -29
  26. package/extensions/dm-phone/node_modules/ws/LICENSE +0 -20
  27. package/extensions/dm-phone/node_modules/ws/README.md +0 -548
  28. package/extensions/dm-phone/node_modules/ws/browser.js +0 -8
  29. package/extensions/dm-phone/node_modules/ws/index.js +0 -22
  30. package/extensions/dm-phone/node_modules/ws/lib/buffer-util.js +0 -131
  31. package/extensions/dm-phone/node_modules/ws/lib/constants.js +0 -19
  32. package/extensions/dm-phone/node_modules/ws/lib/event-target.js +0 -292
  33. package/extensions/dm-phone/node_modules/ws/lib/extension.js +0 -203
  34. package/extensions/dm-phone/node_modules/ws/lib/limiter.js +0 -55
  35. package/extensions/dm-phone/node_modules/ws/lib/permessage-deflate.js +0 -528
  36. package/extensions/dm-phone/node_modules/ws/lib/receiver.js +0 -760
  37. package/extensions/dm-phone/node_modules/ws/lib/sender.js +0 -607
  38. package/extensions/dm-phone/node_modules/ws/lib/stream.js +0 -161
  39. package/extensions/dm-phone/node_modules/ws/lib/subprotocol.js +0 -62
  40. package/extensions/dm-phone/node_modules/ws/lib/validation.js +0 -152
  41. package/extensions/dm-phone/node_modules/ws/lib/websocket-server.js +0 -562
  42. package/extensions/dm-phone/node_modules/ws/lib/websocket.js +0 -1407
  43. package/extensions/dm-phone/node_modules/ws/package.json +0 -70
  44. package/extensions/dm-phone/node_modules/ws/wrapper.mjs +0 -21
  45. package/extensions/dm-phone/package-lock.json +0 -66
  46. package/extensions/dm-phone/package.json +0 -35
  47. package/extensions/dm-phone/phone-session-pool.ts +0 -8
  48. package/extensions/dm-phone/public/app/attachments.js +0 -233
  49. package/extensions/dm-phone/public/app/autocomplete-controller.js +0 -81
  50. package/extensions/dm-phone/public/app/autocomplete.js +0 -135
  51. package/extensions/dm-phone/public/app/bindings.js +0 -178
  52. package/extensions/dm-phone/public/app/command-catalog.js +0 -76
  53. package/extensions/dm-phone/public/app/commands.js +0 -376
  54. package/extensions/dm-phone/public/app/constants.js +0 -60
  55. package/extensions/dm-phone/public/app/formatters.js +0 -131
  56. package/extensions/dm-phone/public/app/handlers.js +0 -442
  57. package/extensions/dm-phone/public/app/main.js +0 -6
  58. package/extensions/dm-phone/public/app/markdown.js +0 -105
  59. package/extensions/dm-phone/public/app/messages.js +0 -418
  60. package/extensions/dm-phone/public/app/sheet-actions.js +0 -113
  61. package/extensions/dm-phone/public/app/sheet-navigation.js +0 -19
  62. package/extensions/dm-phone/public/app/sheets-view.js +0 -287
  63. package/extensions/dm-phone/public/app/state.js +0 -95
  64. package/extensions/dm-phone/public/app/tool-rendering.js +0 -562
  65. package/extensions/dm-phone/public/app/transport.js +0 -176
  66. package/extensions/dm-phone/public/app/ui.js +0 -417
  67. package/extensions/dm-phone/public/app.js +0 -1
  68. package/extensions/dm-phone/public/icon.svg +0 -15
  69. package/extensions/dm-phone/public/index.html +0 -146
  70. package/extensions/dm-phone/public/manifest.webmanifest +0 -17
  71. package/extensions/dm-phone/public/styles.css +0 -1139
  72. package/extensions/dm-phone/public/sw.js +0 -78
  73. package/extensions/dm-phone/src/extension/duckmind-models.js +0 -264
  74. package/extensions/dm-phone/src/extension/phone-args.ts +0 -121
  75. package/extensions/dm-phone/src/extension/phone-paths.ts +0 -250
  76. package/extensions/dm-phone/src/extension/phone-quota.ts +0 -188
  77. package/extensions/dm-phone/src/extension/phone-runtime.ts +0 -154
  78. package/extensions/dm-phone/src/extension/phone-server-runtime.ts +0 -1217
  79. package/extensions/dm-phone/src/extension/phone-sessions.ts +0 -139
  80. package/extensions/dm-phone/src/extension/phone-static.ts +0 -30
  81. package/extensions/dm-phone/src/extension/phone-tailscale.ts +0 -148
  82. package/extensions/dm-phone/src/extension/phone-theme.ts +0 -85
  83. package/extensions/dm-phone/src/extension/register-phone-child-extension.ts +0 -112
  84. package/extensions/dm-phone/src/extension/register-phone-extension.ts +0 -106
  85. package/extensions/dm-phone/src/extension/types.ts +0 -73
  86. package/extensions/dm-phone/src/session-pool/parent-session-worker.ts +0 -882
  87. package/extensions/dm-phone/src/session-pool/session-pool.ts +0 -470
  88. package/extensions/dm-phone/src/session-pool/session-worker.ts +0 -739
  89. package/extensions/dm-phone/src/session-pool/types.ts +0 -111
  90. package/extensions/dm-phone/src/session-pool/utils.ts +0 -23
  91. package/extensions/dm-phone/test/duckmind-models.test.js +0 -147
  92. package/extensions/dm-thinking-timer/LICENSE +0 -21
  93. package/extensions/dm-thinking-timer/README.md +0 -7
  94. package/extensions/dm-thinking-timer/package.json +0 -20
  95. package/extensions/dm-thinking-timer/thinking-timer.ts +0 -250
@@ -1,418 +0,0 @@
1
- import { el, state } from "./state.js";
2
- import {
3
- assistantParts,
4
- contentToText,
5
- countImages,
6
- escapeAttribute,
7
- escapeHtml,
8
- formatTimestamp,
9
- toDetailString,
10
- stripTerminalControlSequences,
11
- } from "./formatters.js";
12
- import { renderMarkdownLite } from "./markdown.js";
13
- import { renderRichToolContent } from "./tool-rendering.js";
14
- import { scrollMessagesToBottom, showToast, updateJumpToLatestButton } from "./ui.js";
15
-
16
- const INLINE_USER_CUSTOM_TYPES = new Set(["phone-inline-user-message"]);
17
-
18
- function userContentDisplayText(content) {
19
- const imageCount = countImages(content);
20
- if (!Array.isArray(content)) return contentToText(content);
21
-
22
- const text = content
23
- .filter((part) => part?.type === "text")
24
- .map((part) => part.text || "")
25
- .join("")
26
- .trim();
27
-
28
- if (text) return text;
29
- if (imageCount === 1) return "[1 image attached]";
30
- if (imageCount > 1) return `[${imageCount} images attached]`;
31
- return contentToText(content);
32
- }
33
-
34
- function imageSource(part) {
35
- if (!part || part.type !== "image") return "";
36
- if (typeof part.previewUrl === "string" && part.previewUrl) return part.previewUrl;
37
- if (typeof part.url === "string" && part.url) return part.url;
38
- if (typeof part.data === "string" && part.data && typeof part.mimeType === "string" && part.mimeType) {
39
- return `data:${escapeAttribute(part.mimeType)};base64,${escapeAttribute(part.data)}`;
40
- }
41
- return "";
42
- }
43
-
44
- function renderUserContent(content, fallbackText = "") {
45
- if (!Array.isArray(content)) {
46
- return {
47
- html: renderMarkdownLite(typeof content === "string" ? content : fallbackText),
48
- renderedImages: 0,
49
- };
50
- }
51
-
52
- const blocks = [];
53
- let imageIndex = 0;
54
-
55
- for (const part of content) {
56
- if (part?.type === "text") {
57
- const text = String(part.text || "");
58
- if (text.trim()) {
59
- blocks.push(`<div class="user-message-text-block">${renderMarkdownLite(text)}</div>`);
60
- }
61
- continue;
62
- }
63
-
64
- if (part?.type !== "image") continue;
65
- const src = imageSource(part);
66
- if (!src) continue;
67
- imageIndex += 1;
68
- const alt = part.name || `Attached image ${imageIndex}`;
69
- blocks.push(`
70
- <div class="user-message-image-wrap">
71
- <img class="user-message-image" src="${src}" alt="${escapeAttribute(alt)}" loading="lazy" />
72
- </div>
73
- `);
74
- }
75
-
76
- if (!blocks.length) {
77
- return {
78
- html: renderMarkdownLite(fallbackText),
79
- renderedImages: 0,
80
- };
81
- }
82
-
83
- return {
84
- html: `<div class="user-message-inline-content">${blocks.join("")}</div>`,
85
- renderedImages: imageIndex,
86
- };
87
- }
88
-
89
- export function transformMessage(message, index) {
90
- if (!message || typeof message !== "object") return [];
91
-
92
- if (message.role === "user") {
93
- return [{
94
- id: `user-${message.timestamp || index}`,
95
- kind: "user",
96
- meta: formatTimestamp(message.timestamp),
97
- text: userContentDisplayText(message.content),
98
- rawContent: message.content,
99
- imageCount: countImages(message.content),
100
- }];
101
- }
102
-
103
- if (message.role === "assistant") {
104
- const parts = assistantParts(message.content);
105
- return [{
106
- id: `assistant-${message.timestamp || index}`,
107
- kind: "assistant",
108
- meta: [message.model, formatTimestamp(message.timestamp)].filter(Boolean).join(" · "),
109
- text: parts.text,
110
- thinking: parts.thinking,
111
- toolCalls: parts.toolCalls,
112
- details: message.usage || message.stopReason ? {
113
- usage: message.usage,
114
- stopReason: message.stopReason,
115
- } : undefined,
116
- }];
117
- }
118
-
119
- if (message.role === "toolResult") {
120
- return [{
121
- id: `tool-${message.toolCallId || message.timestamp || index}`,
122
- kind: "tool",
123
- toolCallId: message.toolCallId,
124
- toolName: message.toolName || "tool",
125
- title: message.toolName || "tool",
126
- status: message.isError ? "error" : "done",
127
- text: contentToText(message.content),
128
- rawContent: message.content,
129
- meta: formatTimestamp(message.timestamp),
130
- details: message.details,
131
- }];
132
- }
133
-
134
- if (message.role === "bashExecution") {
135
- return [{
136
- id: `bash-${message.timestamp || index}`,
137
- kind: "tool",
138
- toolName: "bash",
139
- title: `bash · ${message.command || ""}`,
140
- command: message.command || "",
141
- args: { command: message.command || "" },
142
- status: message.cancelled ? "cancelled" : "done",
143
- text: message.output || "",
144
- meta: formatTimestamp(message.timestamp),
145
- details: {
146
- exitCode: message.exitCode,
147
- truncated: message.truncated,
148
- fullOutputPath: message.fullOutputPath,
149
- },
150
- }];
151
- }
152
-
153
- if (message.role === "custom") {
154
- if (message.display === false) return [];
155
-
156
- if (INLINE_USER_CUSTOM_TYPES.has(message.customType || "")) {
157
- return [{
158
- id: `custom-user-${message.timestamp || index}`,
159
- kind: "user",
160
- meta: formatTimestamp(message.timestamp),
161
- text: userContentDisplayText(message.content),
162
- rawContent: message.content,
163
- imageCount: countImages(message.content),
164
- }];
165
- }
166
-
167
- return [{
168
- id: `custom-${message.timestamp || index}`,
169
- kind: "custom",
170
- title: message.customType || "extension",
171
- text: contentToText(message.content),
172
- meta: formatTimestamp(message.timestamp),
173
- details: message.details,
174
- imageCount: countImages(message.content),
175
- }];
176
- }
177
-
178
- if (message.role === "branchSummary") {
179
- return [{
180
- id: `branch-summary-${message.timestamp || index}`,
181
- kind: "summary",
182
- title: "Branch summary",
183
- text: message.summary || "",
184
- meta: formatTimestamp(message.timestamp),
185
- details: { fromId: message.fromId },
186
- }];
187
- }
188
-
189
- if (message.role === "compactionSummary") {
190
- return [{
191
- id: `compaction-summary-${message.timestamp || index}`,
192
- kind: "summary",
193
- title: `Compaction summary${message.tokensBefore ? ` · ${message.tokensBefore.toLocaleString()} tokens` : ""}`,
194
- text: message.summary || "",
195
- meta: formatTimestamp(message.timestamp),
196
- }];
197
- }
198
-
199
- return [];
200
- }
201
-
202
- function renderMessageMeta(item, options = {}) {
203
- const pills = [];
204
- if (item.imageCount && !options.suppressImageCount) {
205
- pills.push(`<span class="inline-pill">${item.imageCount} image${item.imageCount === 1 ? "" : "s"}</span>`);
206
- }
207
- if (item.status) pills.push(`<span class="inline-pill">${escapeHtml(item.status)}</span>`);
208
- return pills.join("");
209
- }
210
-
211
- function renderDetailSection(title, value, options = {}) {
212
- if (!value) return "";
213
-
214
- const body = options.markdown
215
- ? `<div class="detail-content detail-markdown">${renderMarkdownLite(value)}</div>`
216
- : `<pre class="detail-pre">${escapeHtml(value)}</pre>`;
217
-
218
- return `
219
- <details>
220
- <summary>${escapeHtml(title)}</summary>
221
- ${body}
222
- </details>
223
- `;
224
- }
225
-
226
- function renderAssistantDetails(item) {
227
- const sections = [];
228
- if (item.thinking) sections.push(renderDetailSection("Thinking", item.thinking, { markdown: true }));
229
-
230
- if (item.toolCalls?.length) {
231
- sections.push(renderDetailSection("Tool calls", JSON.stringify(item.toolCalls, null, 2)));
232
- }
233
-
234
- if (item.details) {
235
- sections.push(renderDetailSection("Details", toDetailString(item.details)));
236
- }
237
-
238
- return sections.join("");
239
- }
240
-
241
- function toolDetailsForSecondarySection(item) {
242
- if (!item.details) return null;
243
-
244
- if (String(item.toolName || item.title || "").trim().split(" · ")[0].toLowerCase() !== "edit") {
245
- return item.details;
246
- }
247
-
248
- const details = item.details && typeof item.details === "object" && !Array.isArray(item.details) ? item.details : null;
249
- if (!details) return item.details;
250
-
251
- const { diff, firstChangedLine, ...rest } = details;
252
- return Object.keys(rest).length ? rest : null;
253
- }
254
-
255
- function renderMessage(item) {
256
- const richTool = item.kind === "tool" ? renderRichToolContent(item) : "";
257
- const roleLabel = {
258
- assistant: "DM",
259
- custom: item.title || "Extension",
260
- summary: item.title || "Summary",
261
- system: "System",
262
- tool: richTool ? "Tool" : item.title || "Tool",
263
- user: "You",
264
- }[item.kind] || "Message";
265
-
266
- const renderedUser = item.kind === "user"
267
- ? renderUserContent(item.rawContent, item.text || "")
268
- : { html: "", renderedImages: 0 };
269
-
270
- const bodyMain = richTool || (item.kind === "tool"
271
- ? `<pre>${escapeHtml(item.text || "")}</pre>`
272
- : item.kind === "user"
273
- ? renderedUser.html
274
- : renderMarkdownLite(item.text || ""));
275
-
276
- const detailValue = item.kind === "tool" ? toolDetailsForSecondarySection(item) : item.details;
277
- const extraDetails = item.kind === "assistant"
278
- ? renderAssistantDetails(item)
279
- : detailValue
280
- ? renderDetailSection("Details", toDetailString(detailValue))
281
- : "";
282
-
283
- return `
284
- <article class="message ${item.kind}">
285
- <div class="message-header">
286
- <div class="role-badge">${escapeHtml(roleLabel)}${item.live ? " · live" : ""}</div>
287
- <div class="meta">${escapeHtml(item.meta || "")}</div>
288
- </div>
289
- <div class="message-body">
290
- ${bodyMain}
291
- ${richTool ? "" : renderMessageMeta(item, { suppressImageCount: renderedUser.renderedImages > 0 })}
292
- ${extraDetails}
293
- </div>
294
- </article>
295
- `;
296
- }
297
-
298
- function enrichToolItems(items) {
299
- const toolCalls = new Map();
300
-
301
- for (const item of items) {
302
- if (item.kind !== "assistant" || !Array.isArray(item.toolCalls)) continue;
303
- for (const toolCall of item.toolCalls) {
304
- if (!toolCall?.id) continue;
305
- toolCalls.set(toolCall.id, toolCall);
306
- }
307
- }
308
-
309
- return items.map((item) => {
310
- if (item.kind !== "tool" || item.args || !item.toolCallId) return item;
311
- const linked = toolCalls.get(item.toolCallId);
312
- if (!linked) return item;
313
- return { ...item, args: linked.arguments || {} };
314
- });
315
- }
316
-
317
- function currentItems() {
318
- const items = [...state.messages];
319
- for (const tool of state.liveTools.values()) items.push(tool);
320
- if (state.liveAssistant) items.push(state.liveAssistant);
321
- return enrichToolItems(items);
322
- }
323
-
324
- function hasLiveItems() {
325
- if (state.liveAssistant?.live) return true;
326
- for (const tool of state.liveTools.values()) {
327
- if (tool?.live) return true;
328
- }
329
- return false;
330
- }
331
-
332
- export function clearTransientState() {
333
- state.liveAssistant = null;
334
- state.liveTools.clear();
335
- }
336
-
337
- export function clearSnapshotView() {
338
- state.snapshotState = null;
339
- state.snapshotWorkerId = null;
340
- state.messages = [];
341
- clearTransientState();
342
- }
343
-
344
- export function handleAssistantEvent(event) {
345
- if (!event) return;
346
- if (!state.liveAssistant) {
347
- state.liveAssistant = {
348
- id: "assistant-live",
349
- kind: "assistant",
350
- live: true,
351
- text: "",
352
- thinking: "",
353
- toolCalls: [],
354
- meta: "Streaming…",
355
- };
356
- }
357
-
358
- if (event.type === "text_delta") state.liveAssistant.text += stripTerminalControlSequences(event.delta || "");
359
- if (event.type === "thinking_delta") state.liveAssistant.thinking += stripTerminalControlSequences(event.delta || "");
360
- if (event.type === "toolcall_end" && event.toolCall) {
361
- state.liveAssistant.toolCalls.push({ id: event.toolCall.id || "", name: event.toolCall.name || "tool", arguments: event.toolCall.arguments || {} });
362
- }
363
- if (event.type === "error") showToast(event.message || "Agent error", "error");
364
- renderMessages();
365
- }
366
-
367
- export function upsertLiveTool(toolId, value) {
368
- state.liveTools.set(toolId, value);
369
- renderMessages();
370
- }
371
-
372
- export function renderMessages({ forceScroll = false, streaming = hasLiveItems() } = {}) {
373
- const items = currentItems();
374
- if (!items.length) {
375
- el.messages.innerHTML = `
376
- <article class="message system">
377
- <div class="message-header"><div class="role-badge">Ready</div></div>
378
- <div class="message-body">
379
- <p>This phone UI now exposes much more of DM: commands, models, thinking, sessions, tree history, custom extension messages, and image upload.</p>
380
- </div>
381
- </article>
382
- `;
383
- updateJumpToLatestButton();
384
- return;
385
- }
386
-
387
- el.messages.innerHTML = items.map(renderMessage).join("");
388
- updateJumpToLatestButton();
389
- scrollMessagesToBottom({ force: forceScroll, streaming, behavior: "smooth" });
390
- }
391
-
392
- export function renderWidgets() {
393
- const widgets = [...state.widgets.entries()];
394
- if (!widgets.length && !state.footerStatus) {
395
- el.widgetStack.classList.add("hidden");
396
- el.widgetStack.innerHTML = "";
397
- return;
398
- }
399
-
400
- const cards = widgets.map(([key, lines]) => `
401
- <article class="widget-card">
402
- <h3>${escapeHtml(key)}</h3>
403
- <ul>${lines.map((line) => `<li>${escapeHtml(line)}</li>`).join("")}</ul>
404
- </article>
405
- `);
406
-
407
- if (state.footerStatus) {
408
- cards.unshift(`
409
- <article class="widget-card">
410
- <h3>Extension status</h3>
411
- <div>${escapeHtml(state.footerStatus)}</div>
412
- </article>
413
- `);
414
- }
415
-
416
- el.widgetStack.innerHTML = cards.join("");
417
- el.widgetStack.classList.remove("hidden");
418
- }
@@ -1,113 +0,0 @@
1
- import { renderCommandSuggestions } from "./autocomplete-controller.js";
2
- import {
3
- handleInsertOnlyLocalCommand,
4
- insertSlashCommand,
5
- prepareParentSessionNew,
6
- prepareSessionSelection,
7
- prepareSessionSpawn,
8
- tryHandleLocalCommand,
9
- } from "./commands.js";
10
- import { el, state } from "./state.js";
11
- import { closeSheet, openSheet } from "./sheet-navigation.js";
12
- import { refreshAll, sendRpc } from "./transport.js";
13
- import { autoResizeTextarea } from "./ui.js";
14
-
15
- export function sheetButtonActionKey(button) {
16
- return [
17
- button.getAttribute("data-sheet-action") || "",
18
- button.getAttribute("data-active-session-id") || "",
19
- button.getAttribute("data-session-path") || "",
20
- button.getAttribute("data-open-branch-entry") || "",
21
- button.getAttribute("data-fork-entry") || "",
22
- button.getAttribute("data-run-command") || "",
23
- button.getAttribute("data-run-local-command") || "",
24
- ].join("|");
25
- }
26
-
27
- export function handleSheetButtonAction(button) {
28
- const action = button.getAttribute("data-sheet-action");
29
- if (action === "refresh") return refreshSheet(), true;
30
- if (action === "new-session") return sendRpc({ type: "new_session" }), true;
31
- if (action === "compact") return sendRpc({ type: "compact" }), true;
32
- if (action === "stats") return sendRpc({ type: "get_session_stats" }), true;
33
- if (action === "models") return openSheet("models"), true;
34
- if (action === "thinking") return openSheet("thinking"), true;
35
- if (action === "commands") return openSheet("commands"), true;
36
- if (action === "sessions") return openSheet("sessions"), true;
37
- if (action === "new-parent-session") return handleNewParentSession(), true;
38
- if (action === "new-parallel-session") return handleSpawnActiveSession(), true;
39
- if (action === "tree") return openSheet("tree"), true;
40
-
41
- const thinkingLevel = button.getAttribute("data-thinking-level");
42
- if (thinkingLevel) return sendRpc({ type: "set_thinking_level", level: thinkingLevel }), true;
43
-
44
- const modelProvider = button.getAttribute("data-model-provider");
45
- const modelId = button.getAttribute("data-model-id");
46
- if (modelProvider && modelId) return sendRpc({ type: "set_model", provider: modelProvider, modelId }), true;
47
-
48
- const runLocalCommand = button.getAttribute("data-run-local-command");
49
- if (runLocalCommand) return handleRunLocalCommand(runLocalCommand), true;
50
-
51
- const runCommand = button.getAttribute("data-run-command");
52
- if (runCommand) return handleInsertRunCommand(runCommand), true;
53
-
54
- const activeSessionId = button.getAttribute("data-active-session-id");
55
- if (activeSessionId) return handleSelectActiveSession(activeSessionId), true;
56
-
57
- const sessionPath = button.getAttribute("data-session-path");
58
- if (sessionPath) return sendRpc({ type: "switch_session", sessionPath }), true;
59
-
60
- const openBranchEntry = button.getAttribute("data-open-branch-entry");
61
- if (openBranchEntry) return sendRpc({ type: "phone_open_branch_path", entryId: openBranchEntry }), true;
62
-
63
- const forkEntry = button.getAttribute("data-fork-entry");
64
- if (forkEntry) return sendRpc({ type: "fork", entryId: forkEntry }), true;
65
-
66
- return false;
67
- }
68
-
69
- function refreshSheet() {
70
- refreshAll();
71
- }
72
-
73
- function handleNewParentSession() {
74
- if (!prepareParentSessionNew()) return;
75
- closeSheet();
76
- }
77
-
78
- function handleSpawnActiveSession() {
79
- if (!prepareSessionSpawn()) return;
80
- closeSheet();
81
- }
82
-
83
- function handleRunLocalCommand(runLocalCommand) {
84
- if (handleInsertOnlyLocalCommand(runLocalCommand)) {
85
- closeSheet();
86
- return;
87
- }
88
-
89
- const result = tryHandleLocalCommand(`/${runLocalCommand}`, { hasAttachments: state.attachments.length > 0 });
90
- if (result === "handled") {
91
- el.promptInput.value = "";
92
- autoResizeTextarea();
93
- renderCommandSuggestions();
94
- }
95
- }
96
-
97
- function handleInsertRunCommand(runCommand) {
98
- const commandName = runCommand.replace(/^\//, "").trim();
99
- if (commandName) {
100
- insertSlashCommand(commandName);
101
- } else {
102
- el.promptInput.value = `${runCommand} `;
103
- autoResizeTextarea();
104
- renderCommandSuggestions();
105
- el.promptInput.focus();
106
- }
107
- closeSheet();
108
- }
109
-
110
- function handleSelectActiveSession(activeSessionId) {
111
- if (!prepareSessionSelection(activeSessionId)) return showToast("Not connected to DM.", "error");
112
- closeSheet();
113
- }
@@ -1,19 +0,0 @@
1
- import { renderSheet } from "./sheets-view.js";
2
- import { el, state } from "./state.js";
3
- import { sendRpc } from "./transport.js";
4
-
5
- export function openSheet(mode = "actions") {
6
- state.sheetMode = mode;
7
- el.sheetModal.classList.remove("hidden");
8
- renderSheet();
9
-
10
- if (mode === "actions") sendRpc({ type: "get_session_stats" });
11
- if (mode === "models") sendRpc({ type: "get_available_models" });
12
- if (mode === "commands") sendRpc({ type: "get_commands" });
13
- if (mode === "sessions") sendRpc({ type: "phone_list_sessions" });
14
- if (mode === "tree") sendRpc({ type: "phone_get_tree" });
15
- }
16
-
17
- export function closeSheet() {
18
- el.sheetModal.classList.add("hidden");
19
- }