dsh-more 0.1.0 → 0.1.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.
package/dist/client.js CHANGED
@@ -35,7 +35,7 @@ __export(index_exports, {
35
35
  inject: () => inject
36
36
  });
37
37
  module.exports = __toCommonJS(index_exports);
38
- var import_react13 = require("react");
38
+ var import_react15 = require("react");
39
39
  var import_react_dom = require("react-dom");
40
40
 
41
41
  // src/generated/patch-catalog.ts
@@ -45,6 +45,7 @@ var PATCH_CATALOG = [
45
45
  { "id": "session-delete", "name": "\u6C38\u4E45\u5220\u9664\u4F1A\u8BDD", "description": "\u505C\u6B62\u76EE\u6807\u4F1A\u8BDD\u5E76\u4ECE\u78C1\u76D8\u6C38\u4E45\u5220\u9664\uFF0C\u4E0D\u5F71\u54CD\u539F\u751F\u5F52\u6863", "defaultEnabled": true, "order": 300, "clientKind": "standalone" },
46
46
  { "id": "conversation-markdown-export", "name": "\u5BFC\u51FA\u5B8C\u6574\u804A\u5929\u8BB0\u5F55", "description": "\u5C06\u5F53\u524D\u4F1A\u8BDD\u7684\u5B8C\u6574\u804A\u5929\u8BB0\u5F55\u4E0B\u8F7D\u4E3A Markdown \u6587\u4EF6", "defaultEnabled": true, "order": 400, "clientKind": "standalone" },
47
47
  { "id": "model-capabilities", "name": "\u6A21\u578B\u80FD\u529B\u914D\u7F6E", "description": "\u5728\u6A21\u578B\u914D\u7F6E\u9875\u8BBE\u7F6E\u6BCF\u4E2A\u6A21\u578B\u7684\u8BC6\u56FE\u80FD\u529B\u3001\u53EF\u9009\u601D\u8003\u7C7B\u578B\u4E0E\u601D\u8003\u53C2\u6570\u683C\u5F0F", "defaultEnabled": true, "order": 500, "clientKind": "standalone" },
48
+ { "id": "fast-mode", "name": "\u52A0\u901F", "description": "\u5728\u8F93\u5165\u6846\u548C /fast \u547D\u4EE4\u4E2D\u5F00\u5173\u52A0\u901F\u3002\u54CD\u5E94\u66F4\u5FEB\uFF0C\u4F46\u4F1A\u66F4\u5FEB\u6D88\u8017\u989D\u5EA6", "defaultEnabled": true, "order": 550, "clientKind": "standalone" },
48
49
  { "id": "session-auto-title", "name": "\u4F1A\u8BDD\u81EA\u52A8\u547D\u540D", "description": "\u65B0\u4F1A\u8BDD\u9996\u6761\u9700\u6C42\u540E\uFF0C\u4F7F\u7528\u5F53\u524D\u6A21\u578B\u751F\u6210\u300C\u7C7B\u578B \xB7 \u5177\u4F53\u4EFB\u52A1\u300D\u6807\u9898\uFF1B\u4FDD\u7559\u624B\u52A8\u547D\u540D\uFF0C\u5931\u8D25\u65F6\u4FDD\u7559\u539F\u6709\u6807\u9898", "defaultEnabled": true, "order": 600, "clientKind": "standalone" },
49
50
  { "id": "projectless-tasks", "name": "\u72EC\u7ACB\u4EFB\u52A1", "description": "\u5728\u5DE5\u4F5C\u533A\u4E0B\u62C9\u6846\u521B\u5EFA\u72EC\u7ACB\u4EFB\u52A1\u5E76\u4FDD\u7559\u8349\u7A3F\uFF0C\u4E5F\u53EF\u5C06\u672A\u5206\u7EC4\u4F1A\u8BDD\u79FB\u5165\u5DE5\u4F5C\u533A\u5217\u8868", "defaultEnabled": true, "order": 700, "clientKind": "standalone" }
50
51
  ];
@@ -54,6 +55,7 @@ var DEFAULT_PATCH_SETTINGS = {
54
55
  "session-delete": true,
55
56
  "conversation-markdown-export": true,
56
57
  "model-capabilities": true,
58
+ "fast-mode": true,
57
59
  "session-auto-title": true,
58
60
  "projectless-tasks": true
59
61
  };
@@ -92,7 +94,7 @@ var IconChevronDownOutline14 = compatibleIcon("IconChevronDownOutlineRegular", "
92
94
 
93
95
  // src/platform/dsh/identity.ts
94
96
  var PLUGIN_NAME = "dsh-more";
95
- var PLUGIN_API_PREFIX = `/${PLUGIN_NAME}/api`;
97
+ var PLUGIN_API_PREFIX = `/api/${PLUGIN_NAME}`;
96
98
  var PLUGIN_MUTATION_HEADER = "x-dsh-more";
97
99
  var PATCH_SETTINGS_NAMESPACE = PLUGIN_NAME;
98
100
 
@@ -108,7 +110,9 @@ var DshMoreApiError = class extends Error {
108
110
  async function requestPatch(patchId, action, payload) {
109
111
  let response;
110
112
  try {
111
- response = await fetch(`${PLUGIN_API_PREFIX}/${encodeURIComponent(patchId)}/${encodeURIComponent(action)}`, {
113
+ const transport = globalThis.__DSH_TRANSPORT__;
114
+ const send = transport?.fetch?.bind(transport) ?? globalThis.fetch.bind(globalThis);
115
+ response = await send(`${PLUGIN_API_PREFIX}/${encodeURIComponent(patchId)}/${encodeURIComponent(action)}`.slice(1), {
112
116
  method: "POST",
113
117
  headers: {
114
118
  "content-type": "application/json",
@@ -146,6 +150,39 @@ function apiErrorText(error) {
146
150
  return String(error);
147
151
  }
148
152
 
153
+ // src/platform/dsh/client/runtime.ts
154
+ function currentSessionId(list) {
155
+ if (list.current !== void 0) return list.current;
156
+ return Object.values(list.byId).find((row) => {
157
+ const retained = row.retainedBy;
158
+ return (retained?.mainView ?? 0) > 0;
159
+ })?.id;
160
+ }
161
+ function clientSessions(ctx) {
162
+ const sessions = ctx.sessions;
163
+ const navigation = typeof ctx.get === "function" ? ctx.get("uiWorkspace") : void 0;
164
+ let open;
165
+ if (typeof sessions.open === "function") open = (id) => sessions.open(id);
166
+ else if (typeof navigation === "object" && navigation !== null && "openSession" in navigation && typeof navigation.openSession === "function") {
167
+ const openSession = navigation.openSession;
168
+ open = (id) => openSession.call(navigation, id);
169
+ } else throw new Error("\u5F53\u524D DSH \u7248\u672C\u4E0D\u652F\u6301\u4F1A\u8BDD\u5BFC\u822A\uFF0C\u8BF7\u68C0\u67E5\u4F1A\u8BDD\u63A5\u53E3\u3002");
170
+ return { list: sessions.list, refresh: () => sessions.refresh(), open };
171
+ }
172
+ function clientSessionActions(ctx) {
173
+ const sessions = ctx.sessions;
174
+ if (typeof sessions !== "object" || sessions === null || !("create" in sessions) || typeof sessions.create !== "function") {
175
+ throw new Error("\u5F53\u524D DSH \u7248\u672C\u4E0D\u652F\u6301\u72EC\u7ACB\u4EFB\u52A1\uFF0C\u8BF7\u68C0\u67E5\u4F1A\u8BDD\u63A5\u53E3\u3002");
176
+ }
177
+ const create = sessions.create;
178
+ const actions = { create: (options) => create.call(sessions, options), open: clientSessions(ctx).open };
179
+ if ("retain" in sessions && typeof sessions.retain === "function") {
180
+ const retain = sessions.retain;
181
+ actions.retain = (id) => retain.call(sessions, id, { source: "dsh-more-draft-transfer" });
182
+ }
183
+ return actions;
184
+ }
185
+
149
186
  // src/platform/dsh/client/session-sync.ts
150
187
  var INCREMENTAL_SYNC_GRACE_MS = 180;
151
188
  function openSessionWithoutGap(sessions, sessionId) {
@@ -223,7 +260,7 @@ async function settleSessionRemoval(sessions, workspaces, sessionId) {
223
260
  if (!settled()) throw new Error("\u4F1A\u8BDD\u5DF2\u5220\u9664\uFF0C\u4F46\u5BA2\u6237\u7AEF\u5217\u8868\u5C1A\u672A\u540C\u6B65\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u9875\u9762\u3002");
224
261
  }
225
262
  function adjacentVisibleSession(sessions, workspaces, deletingSessionId) {
226
- if (sessions.current !== deletingSessionId) return void 0;
263
+ if (currentSessionId(sessions) !== deletingSessionId) return void 0;
227
264
  const archived = new Set(workspaces.archivedSessionIds);
228
265
  const deletingIndex = sessions.ids.indexOf(deletingSessionId);
229
266
  for (let index = deletingIndex + 1; index < sessions.ids.length; index += 1) {
@@ -265,7 +302,7 @@ function useMessageActions(props, enabled) {
265
302
  if (target === null) return;
266
303
  setBusy(true);
267
304
  setError(null);
268
- const sessions = props.ctx.sessions;
305
+ const sessions = clientSessions(props.ctx);
269
306
  let handoff;
270
307
  try {
271
308
  const preview = await api.preview({ sessionId: props.sessionId, targetSeq: target.seq, text });
@@ -286,7 +323,7 @@ function useMessageActions(props, enabled) {
286
323
  const sessionList = sessions.list.getSnapshot();
287
324
  const sourceAvailable = sessionList.byId[sourceId] !== void 0;
288
325
  const sourceArchived = props.ctx.workspaces.list.getSnapshot().archivedSessionIds.includes(sourceId);
289
- if (sourceAvailable && !sourceArchived && sessionList.current !== sourceId) openSessionWithoutGap(sessions, sourceId);
326
+ if (sourceAvailable && !sourceArchived && currentSessionId(sessionList) !== sourceId) openSessionWithoutGap(sessions, sourceId);
290
327
  setError(apiErrorText(caught));
291
328
  } finally {
292
329
  setBusy(false);
@@ -373,7 +410,7 @@ function useMessageActions2(props, enabled) {
373
410
  if (target === null || preview === null) return;
374
411
  setBusy(true);
375
412
  setError(null);
376
- const sessions = props.ctx.sessions;
413
+ const sessions = clientSessions(props.ctx);
377
414
  const continuationSessionId = preview.continuationSessionId;
378
415
  const handoff = followSessionHandoff(sessions, continuationSessionId);
379
416
  try {
@@ -392,7 +429,7 @@ function useMessageActions2(props, enabled) {
392
429
  const sessionList = sessions.list.getSnapshot();
393
430
  const sourceAvailable = sessionList.byId[sourceId] !== void 0;
394
431
  const sourceArchived = props.ctx.workspaces.list.getSnapshot().archivedSessionIds.includes(sourceId);
395
- if (sourceAvailable && !sourceArchived && sessionList.current !== sourceId) openSessionWithoutGap(sessions, sourceId);
432
+ if (sourceAvailable && !sourceArchived && currentSessionId(sessionList) !== sourceId) openSessionWithoutGap(sessions, sourceId);
396
433
  setPreview(null);
397
434
  setError(apiErrorText(caught));
398
435
  } finally {
@@ -431,7 +468,7 @@ function useMessageActions2(props, enabled) {
431
468
  }
432
469
 
433
470
  // src/patches/session-delete/client/index.tsx
434
- var import_react4 = require("react");
471
+ var import_react5 = require("react");
435
472
  var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
436
473
 
437
474
  // src/platform/dsh/client/styles.ts
@@ -474,11 +511,39 @@ var styles = `
474
511
  @media (prefers-reduced-motion: no-preference) { .dshmore-config-chevron { transition: transform .16s; } }
475
512
  `;
476
513
 
514
+ // src/platform/dsh/client/session-menu.tsx
515
+ var import_react4 = require("react");
516
+ var primitives2 = __toESM(require("@deepseek-ai/dsh-client-ui-primitives"), 1);
517
+ var import_jsx_runtime3 = require("react/jsx-runtime");
518
+ var SESSION_MENU_SLOT = "sidebar.workspaces.session.menu.item";
519
+ function installSessionMenuAction(ctx, options) {
520
+ const slots = ctx.slots;
521
+ if (slots.spec?.(SESSION_MENU_SLOT) === void 0) return void 0;
522
+ const item = Reflect.get(primitives2, "MenuItemButton");
523
+ if (typeof item !== "function") return void 0;
524
+ const MenuItem = item;
525
+ return ctx.slots.register({
526
+ name: SESSION_MENU_SLOT,
527
+ id: options.id,
528
+ order: options.order
529
+ }, (props) => {
530
+ if (typeof props !== "object" || props === null || !("sessionId" in props) || typeof props.sessionId !== "string" || !("useMenuOpenState" in props) || typeof props.useMenuOpenState !== "function") return null;
531
+ return (0, import_react4.createElement)(SessionMenuAction, { ...options, MenuItem, menu: props });
532
+ });
533
+ }
534
+ function SessionMenuAction({ MenuItem, menu, label, danger = false, select }) {
535
+ const [, setOpen] = menu.useMenuOpenState();
536
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MenuItem, { danger, onSelect: () => {
537
+ setOpen(false);
538
+ select(menu.sessionId);
539
+ }, children: label });
540
+ }
541
+
477
542
  // src/patches/session-delete/shared.ts
478
543
  var SESSION_DELETE_PATCH_ID = "session-delete";
479
544
 
480
545
  // src/patches/session-delete/client/index.tsx
481
- var import_jsx_runtime3 = require("react/jsx-runtime");
546
+ var import_jsx_runtime4 = require("react/jsx-runtime");
482
547
  var DELETE_MENU_ATTRIBUTE = "data-dshmore-session-delete";
483
548
  var DELETE_SOURCE_ATTRIBUTE = "data-dshmore-session-delete-source";
484
549
  var sessionDeleteStyles = `
@@ -573,32 +638,48 @@ function installSessionDeleteMenuItems(onDelete) {
573
638
  };
574
639
  }
575
640
  function SessionDeleteController(props) {
576
- const settings = (0, import_react4.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
641
+ const settings = (0, import_react5.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
577
642
  const enabled = settings[SESSION_DELETE_PATCH_ID];
578
- const [pending, setPending] = (0, import_react4.useState)(null);
579
- const pendingRef = (0, import_react4.useRef)(null);
580
- const deleteIntentRef = (0, import_react4.useRef)(false);
581
- const [busy, setBusy] = (0, import_react4.useState)(false);
582
- const [error, setError] = (0, import_react4.useState)(null);
583
- (0, import_react4.useEffect)(() => {
643
+ const [pending, setPending] = (0, import_react5.useState)(null);
644
+ const pendingRef = (0, import_react5.useRef)(null);
645
+ const deleteIntentRef = (0, import_react5.useRef)(false);
646
+ const [busy, setBusy] = (0, import_react5.useState)(false);
647
+ const [error, setError] = (0, import_react5.useState)(null);
648
+ (0, import_react5.useEffect)(() => {
584
649
  if (!enabled) return;
585
650
  const workspaces = props.ctx.workspaces;
586
651
  const sessions = props.ctx.sessions;
652
+ const requestDelete = (sessionId, resolve = () => {
653
+ }) => {
654
+ const request = {
655
+ sessionId,
656
+ title: sessions.list.getSnapshot().byId[sessionId]?.displayTitle ?? String(sessionId),
657
+ resolve
658
+ };
659
+ pendingRef.current?.resolve();
660
+ pendingRef.current = request;
661
+ setError(null);
662
+ setPending(request);
663
+ };
664
+ const removeNativeItem = installSessionMenuAction(props.ctx, {
665
+ id: `${PLUGIN_NAME}-${SESSION_DELETE_PATCH_ID}`,
666
+ label: "\u6C38\u4E45\u5220\u9664\u4F1A\u8BDD",
667
+ order: 500,
668
+ danger: true,
669
+ select: (sessionId) => requestDelete(sessionId)
670
+ });
671
+ if (removeNativeItem !== void 0) return () => {
672
+ removeNativeItem();
673
+ pendingRef.current?.resolve();
674
+ pendingRef.current = null;
675
+ };
587
676
  const mutable = workspaces;
588
677
  const original = mutable.archiveSession;
589
678
  mutable.archiveSession = (sessionId) => {
590
679
  if (!deleteIntentRef.current) return original.call(mutable, sessionId);
591
680
  deleteIntentRef.current = false;
592
681
  return new Promise((resolve) => {
593
- const request = {
594
- sessionId,
595
- title: sessions.list.getSnapshot().byId[sessionId]?.displayTitle ?? String(sessionId),
596
- resolve
597
- };
598
- pendingRef.current?.resolve();
599
- pendingRef.current = request;
600
- setError(null);
601
- setPending(request);
682
+ requestDelete(sessionId, resolve);
602
683
  });
603
684
  };
604
685
  const removeDeleteItems = installSessionDeleteMenuItems((archiveButton) => {
@@ -627,15 +708,15 @@ function SessionDeleteController(props) {
627
708
  if (pending === null) return;
628
709
  setBusy(true);
629
710
  setError(null);
630
- const sessions = props.ctx.sessions;
711
+ const sessions = clientSessions(props.ctx);
631
712
  const workspaces = props.ctx.workspaces;
632
713
  const fallbackSessionId = adjacentVisibleSession(
633
714
  sessions.list.getSnapshot(),
634
715
  workspaces.list.getSnapshot(),
635
716
  pending.sessionId
636
717
  );
637
- if (fallbackSessionId !== void 0) openSessionWithoutGap(sessions, fallbackSessionId);
638
718
  try {
719
+ if (fallbackSessionId !== void 0) openSessionWithoutGap(sessions, fallbackSessionId);
639
720
  await callPatchApi(SESSION_DELETE_PATCH_ID, "commit", {
640
721
  sessionId: pending.sessionId,
641
722
  confirmSessionId: pending.sessionId
@@ -645,6 +726,8 @@ function SessionDeleteController(props) {
645
726
  pendingRef.current = null;
646
727
  setPending(null);
647
728
  } catch (caught) {
729
+ const list = sessions.list.getSnapshot();
730
+ if (fallbackSessionId !== void 0 && currentSessionId(list) === fallbackSessionId && list.byId[pending.sessionId] !== void 0) openSessionWithoutGap(sessions, pending.sessionId);
648
731
  setError(apiErrorText(caught));
649
732
  } finally {
650
733
  setBusy(false);
@@ -652,9 +735,9 @@ function SessionDeleteController(props) {
652
735
  };
653
736
  const title = pending?.title ?? "";
654
737
  if (!enabled) return null;
655
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
656
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: styles + sessionDeleteStyles }),
657
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
738
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
739
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: styles + sessionDeleteStyles }),
740
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
658
741
  import_dsh_client_ui_primitives3.Modal,
659
742
  {
660
743
  open: pending !== null,
@@ -662,17 +745,17 @@ function SessionDeleteController(props) {
662
745
  title: "\u6C38\u4E45\u5220\u9664\u4F1A\u8BDD\uFF1F",
663
746
  closeLabel: "\u5173\u95ED",
664
747
  description: "\u4F1A\u8BDD\u4F1A\u4ECE\u5DE6\u4FA7\u5217\u8868\u548C DSH \u6301\u4E45\u5316\u76EE\u5F55\u4E2D\u6C38\u4E45\u5220\u9664\uFF0C\u4E0D\u4F1A\u5F52\u6863\uFF0C\u4E5F\u4E0D\u4F1A\u79FB\u5165\u56DE\u6536\u76EE\u5F55\u3002",
665
- footer: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
666
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", disabled: busy, onClick: close, children: "\u53D6\u6D88" }),
667
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Button, { variant: "primary", disabled: busy, onClick: () => void commit(), children: busy ? "\u6B63\u5728\u5220\u9664\u2026" : "\u6C38\u4E45\u5220\u9664" })
748
+ footer: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
749
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", disabled: busy, onClick: close, children: "\u53D6\u6D88" }),
750
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives3.Button, { variant: "primary", disabled: busy, onClick: () => void commit(), children: busy ? "\u6B63\u5728\u5220\u9664\u2026" : "\u6C38\u4E45\u5220\u9664" })
668
751
  ] }),
669
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dshmore-dialog-body", children: [
670
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dshmore-message-preview", children: title }),
671
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dshmore-danger", children: [
672
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconWarningOutline16, { size: 16 }),
752
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dshmore-dialog-body", children: [
753
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dshmore-message-preview", children: title }),
754
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dshmore-danger", children: [
755
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(IconWarningOutline16, { size: 16 }),
673
756
  " \u82E5\u4F1A\u8BDD\u6B63\u5728\u8FD0\u884C\uFF0C\u5C06\u5148\u505C\u6B62\u5F53\u524D\u4EFB\u52A1\u3002\u5220\u9664\u540E\u65E0\u6CD5\u6062\u590D\u3002"
674
757
  ] }),
675
- error !== null && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dshmore-error", children: error })
758
+ error !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dshmore-error", children: error })
676
759
  ] })
677
760
  }
678
761
  )
@@ -685,12 +768,12 @@ var clientPatch = {
685
768
  name: "shell.overlay",
686
769
  id: `${PLUGIN_NAME}-${SESSION_DELETE_PATCH_ID}`,
687
770
  order: 90
688
- }, (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SessionDeleteController, { ...props, ctx, activation })));
771
+ }, (props) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SessionDeleteController, { ...props, ctx, activation })));
689
772
  }
690
773
  };
691
774
 
692
775
  // src/patches/conversation-markdown-export/client/index.tsx
693
- var import_react5 = require("react");
776
+ var import_react6 = require("react");
694
777
  var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
695
778
 
696
779
  // src/patches/conversation-markdown-export/shared.ts
@@ -707,7 +790,7 @@ function markdownFilename(title, sessionId) {
707
790
 
708
791
  // src/patches/conversation-markdown-export/client/menu.ts
709
792
  var MENU_ITEM_ATTRIBUTE = "data-dshmore-markdown-export";
710
- var MORE_BUTTON_SELECTOR = 'button[class*="_moreButton"][aria-haspopup="menu"]';
793
+ var MORE_BUTTON_SELECTOR = 'button[aria-haspopup="menu"]';
711
794
  function installMarkdownExportMenu(fallback, options) {
712
795
  const header = fallback.closest("header");
713
796
  if (header === null) return () => {
@@ -723,14 +806,18 @@ function installMarkdownExportMenu(fallback, options) {
723
806
  const sync = () => {
724
807
  frame = null;
725
808
  const trigger = Array.from(header.querySelectorAll(MORE_BUTTON_SELECTOR)).find((button2) => ["\u66F4\u591A\u64CD\u4F5C", "More actions"].includes(button2.getAttribute("aria-label") ?? ""));
726
- fallback.hidden = trigger !== void 0;
727
- const download = trigger?.parentElement?.querySelector('button[role="menuitem"]');
809
+ const open = trigger?.getAttribute("aria-expanded") === "true";
810
+ fallback.hidden = trigger !== void 0 && !open;
811
+ const download = open ? Array.from(header.querySelectorAll('button[role="menuitem"]')).find((button2) => ["\u4E0B\u8F7D Session \u65E5\u5FD7", "Download session log"].includes(button2.textContent?.trim() ?? "")) : void 0;
728
812
  const text = download?.textContent?.trim();
729
813
  if (download === void 0 || download === null || !["\u4E0B\u8F7D Session \u65E5\u5FD7", "Download session log"].includes(text ?? "")) {
730
814
  removeItem();
731
815
  return;
732
816
  }
733
- if (source === download && item?.isConnected === true) return;
817
+ if (source === download && item?.isConnected === true) {
818
+ fallback.hidden = true;
819
+ return;
820
+ }
734
821
  removeItem();
735
822
  const wrapper = download.parentElement;
736
823
  if (wrapper === null || wrapper.getAttribute("role") === "menu") return;
@@ -757,6 +844,7 @@ function installMarkdownExportMenu(fallback, options) {
757
844
  source = download;
758
845
  item = clone;
759
846
  wrapper.after(clone);
847
+ fallback.hidden = true;
760
848
  };
761
849
  sync();
762
850
  const observer = new MutationObserver(() => {
@@ -778,7 +866,7 @@ function installMarkdownExportMenu(fallback, options) {
778
866
  }
779
867
 
780
868
  // src/patches/conversation-markdown-export/client/index.tsx
781
- var import_jsx_runtime4 = require("react/jsx-runtime");
869
+ var import_jsx_runtime5 = require("react/jsx-runtime");
782
870
  var exportStyles = `
783
871
  .dshmore-markdown-export-button { box-sizing: border-box; min-width: 128px; height: 32px; color: var(--dsw-alias-label-primary); cursor: pointer; background: transparent; border: 1px solid var(--dsw-alias-border-l2); border-radius: 18px; display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 6px 12px; font-family: var(--dsw-font-family); font-size: 13px; line-height: 20px; }
784
872
  .dshmore-markdown-export-button[hidden] { display: none; }
@@ -800,17 +888,17 @@ function saveMarkdown(filename, markdown) {
800
888
  }, 0);
801
889
  }
802
890
  function ConversationMarkdownExportButton(props) {
803
- const settings = (0, import_react5.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
891
+ const settings = (0, import_react6.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
804
892
  const enabled = settings[CONVERSATION_MARKDOWN_EXPORT_PATCH_ID];
805
893
  const title = props.useSessions((state) => state.byId[props.sessionId]?.displayTitle ?? String(props.sessionId));
806
- const [busy, setBusy] = (0, import_react5.useState)(false);
807
- const [error, setError] = (0, import_react5.useState)(null);
808
- const button = (0, import_react5.useRef)(null);
809
- const inFlight = (0, import_react5.useRef)(false);
810
- const generation = (0, import_react5.useRef)(0);
811
- const activeSession = (0, import_react5.useRef)(null);
894
+ const [busy, setBusy] = (0, import_react6.useState)(false);
895
+ const [error, setError] = (0, import_react6.useState)(null);
896
+ const button = (0, import_react6.useRef)(null);
897
+ const inFlight = (0, import_react6.useRef)(false);
898
+ const generation = (0, import_react6.useRef)(0);
899
+ const activeSession = (0, import_react6.useRef)(null);
812
900
  activeSession.current = enabled ? String(props.sessionId) : null;
813
- (0, import_react5.useEffect)(() => {
901
+ (0, import_react6.useEffect)(() => {
814
902
  generation.current += 1;
815
903
  inFlight.current = false;
816
904
  setBusy(false);
@@ -843,16 +931,16 @@ function ConversationMarkdownExportButton(props) {
843
931
  }
844
932
  }
845
933
  };
846
- (0, import_react5.useEffect)(() => {
934
+ (0, import_react6.useEffect)(() => {
847
935
  if (!enabled || button.current === null) return;
848
936
  return installMarkdownExportMenu(button.current, { busy, download: () => {
849
937
  void download();
850
938
  } });
851
939
  }, [enabled, props.sessionId, title, busy]);
852
940
  if (!enabled) return null;
853
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
854
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: exportStyles }),
855
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
941
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
942
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: exportStyles }),
943
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
856
944
  "button",
857
945
  {
858
946
  ref: button,
@@ -865,12 +953,12 @@ function ConversationMarkdownExportButton(props) {
865
953
  void download();
866
954
  },
867
955
  children: [
868
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: busy ? "\u6B63\u5728\u5BFC\u51FA\u2026" : "\u5BFC\u51FA Markdown" }),
869
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(IconDownloadOutline16, { size: 12 })
956
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: busy ? "\u6B63\u5728\u5BFC\u51FA\u2026" : "\u5BFC\u51FA Markdown" }),
957
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconDownloadOutline16, { size: 12 })
870
958
  ]
871
959
  }
872
960
  ),
873
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
961
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
874
962
  import_dsh_client_ui_primitives4.Modal,
875
963
  {
876
964
  open: error !== null,
@@ -878,7 +966,7 @@ function ConversationMarkdownExportButton(props) {
878
966
  title: "\u65E0\u6CD5\u5BFC\u51FA\u804A\u5929\u8BB0\u5F55",
879
967
  closeLabel: "\u5173\u95ED",
880
968
  description: error ?? "",
881
- footer: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.Button, { variant: "primary", onClick: () => setError(null), children: "\u5173\u95ED" })
969
+ footer: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dsh_client_ui_primitives4.Button, { variant: "primary", onClick: () => setError(null), children: "\u5173\u95ED" })
882
970
  }
883
971
  )
884
972
  ] });
@@ -890,12 +978,12 @@ var clientPatch2 = {
890
978
  name: "conversation.session.header.utilities",
891
979
  id: `${PLUGIN_NAME}-${CONVERSATION_MARKDOWN_EXPORT_PATCH_ID}`,
892
980
  order: 100
893
- }, (props) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ConversationMarkdownExportButton, { ...props, activation })));
981
+ }, (props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ConversationMarkdownExportButton, { ...props, activation })));
894
982
  }
895
983
  };
896
984
 
897
985
  // src/patches/model-capabilities/client/index.tsx
898
- var import_react7 = require("react");
986
+ var import_react8 = require("react");
899
987
 
900
988
  // src/patches/model-capabilities/shared.ts
901
989
  var MODEL_CAPABILITIES_PATCH_ID = "model-capabilities";
@@ -977,9 +1065,9 @@ function withSettings(ctx, install2) {
977
1065
  }
978
1066
 
979
1067
  // src/patches/model-capabilities/client/editor.tsx
980
- var import_react6 = require("react");
1068
+ var import_react7 = require("react");
981
1069
  var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
982
- var import_jsx_runtime5 = require("react/jsx-runtime");
1070
+ var import_jsx_runtime6 = require("react/jsx-runtime");
983
1071
  var LEVEL_LABELS = {
984
1072
  off: "\u4E0D\u601D\u8003",
985
1073
  minimal: "\u6781\u7B80",
@@ -1033,49 +1121,49 @@ function summaryLabel(capabilities) {
1033
1121
  return `${vision} \xB7 ${thinking}`;
1034
1122
  }
1035
1123
  function CapabilitiesEditorBody({ draft, setDraft, disabled, api: api3 }) {
1036
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dshmore-capabilities-fields", children: [
1037
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "dshmore-capabilities-field", children: [
1038
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u8BC6\u56FE\u80FD\u529B" }),
1039
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("select", { "aria-label": "\u8BC6\u56FE\u80FD\u529B", value: draft.vision, disabled, onChange: (event) => {
1124
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dshmore-capabilities-fields", children: [
1125
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "dshmore-capabilities-field", children: [
1126
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u8BC6\u56FE\u80FD\u529B" }),
1127
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("select", { "aria-label": "\u8BC6\u56FE\u80FD\u529B", value: draft.vision, disabled, onChange: (event) => {
1040
1128
  const vision = event.currentTarget.value;
1041
1129
  setDraft((current) => ({ ...current, vision }));
1042
1130
  }, children: [
1043
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "default", children: "\u6CBF\u7528\u9ED8\u8BA4" }),
1044
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "yes", children: "\u652F\u6301\u8BC6\u56FE" }),
1045
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "no", children: "\u4E0D\u652F\u6301\u8BC6\u56FE\uFF08\u4EC5\u6587\u5B57\uFF09" })
1131
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "default", children: "\u6CBF\u7528\u9ED8\u8BA4" }),
1132
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "yes", children: "\u652F\u6301\u8BC6\u56FE" }),
1133
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "no", children: "\u4E0D\u652F\u6301\u8BC6\u56FE\uFF08\u4EC5\u6587\u5B57\uFF09" })
1046
1134
  ] })
1047
1135
  ] }),
1048
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "dshmore-capabilities-field", children: [
1049
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u601D\u8003\u7C7B\u578B" }),
1050
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("select", { "aria-label": "\u601D\u8003\u7C7B\u578B", value: draft.thinking, disabled, onChange: (event) => {
1136
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "dshmore-capabilities-field", children: [
1137
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u601D\u8003\u7C7B\u578B" }),
1138
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("select", { "aria-label": "\u601D\u8003\u7C7B\u578B", value: draft.thinking, disabled, onChange: (event) => {
1051
1139
  const thinking = event.currentTarget.value;
1052
1140
  setDraft((current) => ({ ...current, thinking }));
1053
1141
  }, children: [
1054
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "default", children: "\u6CBF\u7528\u9ED8\u8BA4" }),
1055
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "disabled", children: "\u4E0D\u652F\u6301\u601D\u8003" }),
1056
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "custom", children: "\u81EA\u5B9A\u4E49\u53EF\u9009\u7C7B\u578B" })
1142
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "default", children: "\u6CBF\u7528\u9ED8\u8BA4" }),
1143
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "disabled", children: "\u4E0D\u652F\u6301\u601D\u8003" }),
1144
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "custom", children: "\u81EA\u5B9A\u4E49\u53EF\u9009\u7C7B\u578B" })
1057
1145
  ] })
1058
1146
  ] }),
1059
- draft.thinking === "custom" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("fieldset", { className: "dshmore-capabilities-levels", disabled, children: [
1060
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("legend", { children: "\u6A21\u578B\u652F\u6301\u7684\u601D\u8003\u7B49\u7EA7" }),
1147
+ draft.thinking === "custom" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("fieldset", { className: "dshmore-capabilities-levels", disabled, children: [
1148
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { children: "\u6A21\u578B\u652F\u6301\u7684\u601D\u8003\u7B49\u7EA7" }),
1061
1149
  (api3 === "deepseek-native" ? DEEPSEEK_THINKING_LEVELS : THINKING_LEVELS).map((level) => {
1062
1150
  const entry = draft.levels[level];
1063
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dshmore-capabilities-level", children: [
1064
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { children: [
1065
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "checkbox", checked: entry?.enabled === true, onChange: (event) => {
1151
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dshmore-capabilities-level", children: [
1152
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
1153
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { type: "checkbox", checked: entry?.enabled === true, onChange: (event) => {
1066
1154
  const enabled = event.currentTarget.checked;
1067
1155
  setDraft((current) => ({ ...current, levels: {
1068
1156
  ...current.levels,
1069
1157
  [level]: { wire: level === "off" ? "" : level, ...current.levels[level], enabled }
1070
1158
  } }));
1071
1159
  } }),
1072
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
1160
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
1073
1161
  LEVEL_LABELS[level],
1074
1162
  " ",
1075
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("small", { children: level })
1163
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("small", { children: level })
1076
1164
  ] })
1077
1165
  ] }),
1078
- entry?.enabled && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1166
+ entry?.enabled && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1079
1167
  "input",
1080
1168
  {
1081
1169
  type: "text",
@@ -1095,41 +1183,41 @@ function CapabilitiesEditorBody({ draft, setDraft, disabled, api: api3 }) {
1095
1183
  ] }, level);
1096
1184
  })
1097
1185
  ] }),
1098
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("details", { className: "dshmore-capabilities-advanced", children: [
1099
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("summary", { children: [
1186
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("details", { className: "dshmore-capabilities-advanced", children: [
1187
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("summary", { children: [
1100
1188
  "\u601D\u8003\u53C2\u6570\u683C\u5F0F",
1101
1189
  draft.thinkingFormat === "default" ? "" : ` \xB7 ${draft.thinkingFormat}`
1102
1190
  ] }),
1103
- api3 === null || api3 === "openai-completions" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "dshmore-capabilities-field", children: [
1104
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u63A5\u53E3\u63A5\u53D7\u7684\u683C\u5F0F" }),
1105
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("select", { "aria-label": "\u601D\u8003\u53C2\u6570\u683C\u5F0F", disabled, value: draft.thinkingFormat, onChange: (event) => {
1191
+ api3 === null || api3 === "openai-completions" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "dshmore-capabilities-field", children: [
1192
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u63A5\u53E3\u63A5\u53D7\u7684\u683C\u5F0F" }),
1193
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("select", { "aria-label": "\u601D\u8003\u53C2\u6570\u683C\u5F0F", disabled, value: draft.thinkingFormat, onChange: (event) => {
1106
1194
  const thinkingFormat = event.currentTarget.value;
1107
1195
  setDraft((current) => ({ ...current, thinkingFormat }));
1108
1196
  }, children: [
1109
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "default", children: "\u6CBF\u7528\u9ED8\u8BA4\uFF08\u63D0\u4F9B\u65B9 / \u81EA\u52A8\u8BC6\u522B\uFF09" }),
1110
- THINKING_FORMATS.map((format) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: format, children: format }, format))
1197
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "default", children: "\u6CBF\u7528\u9ED8\u8BA4\uFF08\u63D0\u4F9B\u65B9 / \u81EA\u52A8\u8BC6\u522B\uFF09" }),
1198
+ THINKING_FORMATS.map((format) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: format, children: format }, format))
1111
1199
  ] }),
1112
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dshmore-capabilities-note", children: "\u7528\u4E8E OpenAI \u517C\u5BB9\u63A5\u53E3\uFF1B\u6309\u63A5\u53E3\u8981\u6C42\u9009\u62E9 OpenAI\u3001DeepSeek\u3001Qwen \u7B49\u683C\u5F0F\u3002" })
1113
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "dshmore-capabilities-note", children: "\u5F53\u524D\u63A5\u53E3\u4F7F\u7528\u539F\u751F\u601D\u8003\u534F\u8BAE\uFF0C\u65E0\u9700\u914D\u7F6E\u6B64\u9879\u3002" })
1200
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dshmore-capabilities-note", children: "\u7528\u4E8E OpenAI \u517C\u5BB9\u63A5\u53E3\uFF1B\u6309\u63A5\u53E3\u8981\u6C42\u9009\u62E9 OpenAI\u3001DeepSeek\u3001Qwen \u7B49\u683C\u5F0F\u3002" })
1201
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "dshmore-capabilities-note", children: "\u5F53\u524D\u63A5\u53E3\u4F7F\u7528\u539F\u751F\u601D\u8003\u534F\u8BAE\uFF0C\u65E0\u9700\u914D\u7F6E\u6B64\u9879\u3002" })
1114
1202
  ] }),
1115
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "dshmore-capabilities-note", children: "\u6CBF\u7528\u9ED8\u8BA4\u4F1A\u79FB\u9664\u8BE5\u6A21\u578B\u7684\u5BF9\u5E94\u58F0\u660E\u3002\u8BF7\u6309\u6A21\u578B\u5B9E\u9645\u80FD\u529B\u914D\u7F6E\u3002" })
1203
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "dshmore-capabilities-note", children: "\u6CBF\u7528\u9ED8\u8BA4\u4F1A\u79FB\u9664\u8BE5\u6A21\u578B\u7684\u5BF9\u5E94\u58F0\u660E\u3002\u8BF7\u6309\u6A21\u578B\u5B9E\u9645\u80FD\u529B\u914D\u7F6E\u3002" })
1116
1204
  ] });
1117
1205
  }
1118
1206
  function CapabilitiesEditorModal({ provider, modelId, namespace, onClose, onSaved }) {
1119
- const [snapshot, setSnapshot] = (0, import_react6.useState)(null);
1120
- const [draft, setDraft] = (0, import_react6.useState)(null);
1121
- const [error, setError] = (0, import_react6.useState)(null);
1122
- const [busy, setBusy] = (0, import_react6.useState)(false);
1123
- const [attempt, setAttempt] = (0, import_react6.useState)(0);
1124
- const saving = (0, import_react6.useRef)(false);
1125
- const mounted = (0, import_react6.useRef)(false);
1126
- (0, import_react6.useEffect)(() => {
1207
+ const [snapshot, setSnapshot] = (0, import_react7.useState)(null);
1208
+ const [draft, setDraft] = (0, import_react7.useState)(null);
1209
+ const [error, setError] = (0, import_react7.useState)(null);
1210
+ const [busy, setBusy] = (0, import_react7.useState)(false);
1211
+ const [attempt, setAttempt] = (0, import_react7.useState)(0);
1212
+ const saving = (0, import_react7.useRef)(false);
1213
+ const mounted = (0, import_react7.useRef)(false);
1214
+ (0, import_react7.useEffect)(() => {
1127
1215
  mounted.current = true;
1128
1216
  return () => {
1129
1217
  mounted.current = false;
1130
1218
  };
1131
1219
  }, []);
1132
- (0, import_react6.useEffect)(() => {
1220
+ (0, import_react7.useEffect)(() => {
1133
1221
  let cancelled = false;
1134
1222
  setError(null);
1135
1223
  void readCapabilities().then((next) => {
@@ -1180,7 +1268,7 @@ function CapabilitiesEditorModal({ provider, modelId, namespace, onClose, onSave
1180
1268
  if (mounted.current) setBusy(false);
1181
1269
  }
1182
1270
  };
1183
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1271
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1184
1272
  import_dsh_client_ui_primitives5.Modal,
1185
1273
  {
1186
1274
  open: true,
@@ -1190,9 +1278,9 @@ function CapabilitiesEditorModal({ provider, modelId, namespace, onClose, onSave
1190
1278
  title: `\u6A21\u578B\u80FD\u529B \xB7 ${modelId}`,
1191
1279
  closeLabel: "\u5173\u95ED",
1192
1280
  description: `\u63D0\u4F9B\u65B9 ${provider}`,
1193
- footer: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1194
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", disabled: busy, onClick: onClose, children: "\u53D6\u6D88" }),
1195
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1281
+ footer: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1282
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", disabled: busy, onClick: onClose, children: "\u53D6\u6D88" }),
1283
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1196
1284
  import_dsh_client_ui_primitives5.Button,
1197
1285
  {
1198
1286
  variant: "primary",
@@ -1204,10 +1292,10 @@ function CapabilitiesEditorModal({ provider, modelId, namespace, onClose, onSave
1204
1292
  }
1205
1293
  )
1206
1294
  ] }),
1207
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dshmore-capabilities-dialog", children: [
1208
- snapshot === null && error === null && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "dshmore-capabilities-note", children: "\u6B63\u5728\u8BFB\u53D6\u6A21\u578B\u914D\u7F6E\u2026" }),
1209
- snapshot !== null && row === void 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "dshmore-capabilities-note", children: "\u8BF7\u5148\u4FDD\u5B58\u63D0\u4F9B\u65B9\u914D\u7F6E\uFF0C\u518D\u6253\u5F00\u8BE5\u6A21\u578B\u7684\u80FD\u529B\u8BBE\u7F6E\u3002" }),
1210
- draft !== null && row !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1295
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dshmore-capabilities-dialog", children: [
1296
+ snapshot === null && error === null && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "dshmore-capabilities-note", children: "\u6B63\u5728\u8BFB\u53D6\u6A21\u578B\u914D\u7F6E\u2026" }),
1297
+ snapshot !== null && row === void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "dshmore-capabilities-note", children: "\u8BF7\u5148\u4FDD\u5B58\u63D0\u4F9B\u65B9\u914D\u7F6E\uFF0C\u518D\u6253\u5F00\u8BE5\u6A21\u578B\u7684\u80FD\u529B\u8BBE\u7F6E\u3002" }),
1298
+ draft !== null && row !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1211
1299
  CapabilitiesEditorBody,
1212
1300
  {
1213
1301
  draft,
@@ -1218,9 +1306,9 @@ function CapabilitiesEditorModal({ provider, modelId, namespace, onClose, onSave
1218
1306
  api: row.api
1219
1307
  }
1220
1308
  ),
1221
- snapshot !== null && !snapshot.writable && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "dshmore-capabilities-note", children: "\u5F53\u524D\u914D\u7F6E\u4E3A\u53EA\u8BFB\u3002" }),
1222
- error !== null && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { role: "alert", className: "dshmore-capabilities-error", children: error }),
1223
- snapshot === null && error !== null && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", onClick: () => {
1309
+ snapshot !== null && !snapshot.writable && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "dshmore-capabilities-note", children: "\u5F53\u524D\u914D\u7F6E\u4E3A\u53EA\u8BFB\u3002" }),
1310
+ error !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { role: "alert", className: "dshmore-capabilities-error", children: error }),
1311
+ snapshot === null && error !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", onClick: () => {
1224
1312
  setAttempt((value) => value + 1);
1225
1313
  }, children: "\u91CD\u8BD5" })
1226
1314
  ] })
@@ -1277,18 +1365,18 @@ var capabilitiesStyles = `
1277
1365
  `;
1278
1366
 
1279
1367
  // src/patches/model-capabilities/client/index.tsx
1280
- var import_jsx_runtime6 = require("react/jsx-runtime");
1368
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1281
1369
  var BUTTON_ATTR = "data-dshmore-model-capabilities";
1282
1370
  function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1283
- const settings = (0, import_react7.useSyncExternalStore)(activation.subscribe, activation.getSnapshot, activation.getSnapshot);
1371
+ const settings = (0, import_react8.useSyncExternalStore)(activation.subscribe, activation.getSnapshot, activation.getSnapshot);
1284
1372
  const enabled = settings[MODEL_CAPABILITIES_PATCH_ID];
1285
- const scopeSnapshot = (0, import_react7.useSyncExternalStore)(scope.subscribe, scope.getSnapshot, scope.getSnapshot);
1286
- const deepseekSnapshot = (0, import_react7.useSyncExternalStore)(deepseekScope.subscribe, deepseekScope.getSnapshot, deepseekScope.getSnapshot);
1287
- const [editing, setEditing] = (0, import_react7.useState)(null);
1288
- const [data, setData] = (0, import_react7.useState)(null);
1289
- const dataRef = (0, import_react7.useRef)(data);
1373
+ const scopeSnapshot = (0, import_react8.useSyncExternalStore)(scope.subscribe, scope.getSnapshot, scope.getSnapshot);
1374
+ const deepseekSnapshot = (0, import_react8.useSyncExternalStore)(deepseekScope.subscribe, deepseekScope.getSnapshot, deepseekScope.getSnapshot);
1375
+ const [editing, setEditing] = (0, import_react8.useState)(null);
1376
+ const [data, setData] = (0, import_react8.useState)(null);
1377
+ const dataRef = (0, import_react8.useRef)(data);
1290
1378
  dataRef.current = data;
1291
- (0, import_react7.useEffect)(() => {
1379
+ (0, import_react8.useEffect)(() => {
1292
1380
  let cancelled = false;
1293
1381
  if (!enabled) {
1294
1382
  setEditing(null);
@@ -1304,7 +1392,7 @@ function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1304
1392
  cancelled = true;
1305
1393
  };
1306
1394
  }, [enabled, scopeSnapshot, deepseekSnapshot]);
1307
- const syncButtons = (0, import_react7.useCallback)(() => {
1395
+ const syncButtons = (0, import_react8.useCallback)(() => {
1308
1396
  if (!enabled) return;
1309
1397
  const active = /* @__PURE__ */ new Set();
1310
1398
  for (const entry of findModelEntries()) {
@@ -1336,7 +1424,7 @@ function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1336
1424
  if (button.parentElement === null || !active.has(button.parentElement)) button.remove();
1337
1425
  });
1338
1426
  }, [enabled]);
1339
- (0, import_react7.useEffect)(() => {
1427
+ (0, import_react8.useEffect)(() => {
1340
1428
  if (!enabled) return;
1341
1429
  let frame = null;
1342
1430
  const schedule = () => {
@@ -1359,13 +1447,13 @@ function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1359
1447
  document.querySelectorAll(`[${BUTTON_ATTR}]`).forEach((element) => element.remove());
1360
1448
  };
1361
1449
  }, [enabled, syncButtons]);
1362
- (0, import_react7.useEffect)(() => {
1450
+ (0, import_react8.useEffect)(() => {
1363
1451
  if (enabled) syncButtons();
1364
1452
  }, [enabled, syncButtons, data]);
1365
1453
  if (!enabled) return null;
1366
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1367
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: capabilitiesStyles }),
1368
- editing !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1454
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1455
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: capabilitiesStyles }),
1456
+ editing !== null && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1369
1457
  CapabilitiesEditorModal,
1370
1458
  {
1371
1459
  ...editing,
@@ -1397,7 +1485,253 @@ var clientPatch3 = {
1397
1485
  name: "shell.overlay",
1398
1486
  id: `${PLUGIN_NAME}-${MODEL_CAPABILITIES_PATCH_ID}`,
1399
1487
  order: 90
1400
- }, () => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ModelsPageCapabilitiesPortal, { scope: boundScope, deepseekScope, activation })));
1488
+ }, () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ModelsPageCapabilitiesPortal, { scope: boundScope, deepseekScope, activation })));
1489
+ }
1490
+ };
1491
+
1492
+ // src/patches/fast-mode/client/index.tsx
1493
+ var import_react9 = require("react");
1494
+
1495
+ // src/patches/fast-mode/shared.ts
1496
+ var FAST_MODE_PATCH_ID = "fast-mode";
1497
+
1498
+ // src/patches/fast-mode/client/styles.ts
1499
+ var fastModeStyles = `
1500
+ .dshmore-fast-btn {
1501
+ box-sizing: border-box;
1502
+ display: inline-flex;
1503
+ align-items: center;
1504
+ justify-content: center;
1505
+ gap: 5px;
1506
+ height: 28px;
1507
+ padding: 0 10px;
1508
+ font-family: var(--dsw-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);
1509
+ font-size: 12px;
1510
+ font-weight: 500;
1511
+ line-height: 1;
1512
+ border-radius: 14px;
1513
+ border: 1px solid var(--dsw-alias-border-l2, rgba(128, 128, 128, 0.3));
1514
+ background: var(--dsw-alias-interactive-bg-idle, rgba(128, 128, 128, 0.08));
1515
+ color: var(--dsw-alias-label-primary, inherit);
1516
+ cursor: pointer;
1517
+ transition: all 0.15s ease-in-out;
1518
+ user-select: none;
1519
+ white-space: nowrap;
1520
+ outline: none;
1521
+ margin-right: 6px;
1522
+ flex: none;
1523
+ }
1524
+
1525
+ .dshmore-fast-btn:hover:not(:disabled) {
1526
+ background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.18));
1527
+ border-color: var(--dsw-alias-border-l1, rgba(128, 128, 128, 0.5));
1528
+ }
1529
+
1530
+ .dshmore-fast-btn--active {
1531
+ background: rgba(245, 158, 11, 0.16) !important;
1532
+ color: #f59e0b !important;
1533
+ border-color: #f59e0b !important;
1534
+ box-shadow: 0 0 8px rgba(245, 158, 11, 0.3) !important;
1535
+ font-weight: 600;
1536
+ }
1537
+
1538
+ .dshmore-fast-btn:disabled,
1539
+ .dshmore-fast-btn--busy {
1540
+ opacity: 0.6;
1541
+ cursor: wait;
1542
+ }
1543
+
1544
+ .dshmore-fast-btn-icon {
1545
+ display: inline-flex;
1546
+ align-items: center;
1547
+ justify-content: center;
1548
+ flex: none;
1549
+ line-height: 1;
1550
+ }
1551
+
1552
+ .dshmore-fast-btn-label {
1553
+ display: inline-block;
1554
+ line-height: 1;
1555
+ }
1556
+ `;
1557
+
1558
+ // src/patches/fast-mode/client/index.tsx
1559
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1560
+ var IDLE_FAST_STATE = { active: false, busy: false };
1561
+ var FastModeClientStore = class {
1562
+ states = /* @__PURE__ */ new Map();
1563
+ listeners = /* @__PURE__ */ new Set();
1564
+ getState(sessionId) {
1565
+ const key = sessionId || "default";
1566
+ return this.states.get(key) ?? IDLE_FAST_STATE;
1567
+ }
1568
+ setState(sessionId, next) {
1569
+ const key = sessionId || "default";
1570
+ const prev = this.getState(key);
1571
+ this.states.set(key, { ...prev, ...next });
1572
+ this.notify();
1573
+ }
1574
+ subscribe = (listener) => {
1575
+ this.listeners.add(listener);
1576
+ return () => {
1577
+ this.listeners.delete(listener);
1578
+ };
1579
+ };
1580
+ notify() {
1581
+ for (const l of this.listeners) l();
1582
+ }
1583
+ };
1584
+ var fastModeClientStore = new FastModeClientStore();
1585
+ async function syncSessionFastState(sessionId) {
1586
+ if (!sessionId) return false;
1587
+ try {
1588
+ const res = await callPatchApi(FAST_MODE_PATCH_ID, "getState", { sessionId });
1589
+ fastModeClientStore.setState(sessionId, { active: res.enabled, busy: false });
1590
+ return res.enabled;
1591
+ } catch {
1592
+ return false;
1593
+ }
1594
+ }
1595
+ async function toggleFastMode(ctx, sessionId) {
1596
+ const currentId = sessionId || currentSessionId(ctx.sessions?.list?.getSnapshot());
1597
+ if (!currentId) return;
1598
+ const current = fastModeClientStore.getState(currentId);
1599
+ if (current.busy) return;
1600
+ fastModeClientStore.setState(currentId, { active: !current.active, busy: true });
1601
+ try {
1602
+ const res = await callPatchApi(FAST_MODE_PATCH_ID, "toggle", { sessionId: currentId });
1603
+ fastModeClientStore.setState(currentId, { active: res.enabled, busy: false });
1604
+ } catch (err) {
1605
+ console.error("Failed to toggle fast mode:", err);
1606
+ fastModeClientStore.setState(currentId, { active: current.active, busy: false });
1607
+ }
1608
+ }
1609
+ function FastModeButton({
1610
+ sessionId,
1611
+ activation,
1612
+ ctx
1613
+ }) {
1614
+ const settings = (0, import_react9.useSyncExternalStore)(activation.subscribe, activation.getSnapshot);
1615
+ const enabled = settings[FAST_MODE_PATCH_ID];
1616
+ const state = (0, import_react9.useSyncExternalStore)(
1617
+ fastModeClientStore.subscribe,
1618
+ () => fastModeClientStore.getState(sessionId)
1619
+ );
1620
+ (0, import_react9.useEffect)(() => {
1621
+ if (sessionId) {
1622
+ void syncSessionFastState(sessionId);
1623
+ }
1624
+ }, [sessionId]);
1625
+ if (!enabled) return null;
1626
+ const tooltip = state.active ? "\u52A0\u901F\u5DF2\u5F00\u542F\n\u54CD\u5E94\u66F4\u5FEB\uFF0C\u4E5F\u4F1A\u66F4\u5FEB\u6D88\u8017\u989D\u5EA6\n\u70B9\u51FB\u5173\u95ED\uFF0C\u6062\u590D\u6807\u51C6\u901F\u5EA6" : "\u52A0\u901F\n\u5F00\u542F\u540E\u54CD\u5E94\u66F4\u5FEB\uFF0C\u4F46\u4F1A\u66F4\u5FEB\u6D88\u8017\u989D\u5EA6\n\u70B9\u51FB\u5F00\u542F";
1627
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1628
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: fastModeStyles }),
1629
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1630
+ "button",
1631
+ {
1632
+ type: "button",
1633
+ className: `dshmore-fast-btn ${state.active ? "dshmore-fast-btn--active" : ""} ${state.busy ? "dshmore-fast-btn--busy" : ""}`,
1634
+ disabled: state.busy,
1635
+ title: tooltip,
1636
+ "aria-label": tooltip,
1637
+ onClick: (e) => {
1638
+ e.preventDefault();
1639
+ e.stopPropagation();
1640
+ void toggleFastMode(ctx, sessionId);
1641
+ },
1642
+ children: [
1643
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dshmore-fast-btn-icon", children: "\u26A1" }),
1644
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dshmore-fast-btn-label", children: state.busy ? "\u5207\u6362\u4E2D\u2026" : state.active ? "\u52A0\u901F (\u5F00)" : "\u52A0\u901F" })
1645
+ ]
1646
+ }
1647
+ )
1648
+ ] });
1649
+ }
1650
+ function FastModeInputContribution(props) {
1651
+ const currentList = props.useSessions ? props.useSessions((s) => s) : void 0;
1652
+ const derivedId = props.sessionId || (currentList ? currentSessionId(currentList) : void 0) || currentSessionId(props.ctx.sessions?.list?.getSnapshot());
1653
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1654
+ FastModeButton,
1655
+ {
1656
+ sessionId: derivedId ? String(derivedId) : void 0,
1657
+ activation: props.activation,
1658
+ ctx: props.ctx
1659
+ }
1660
+ );
1661
+ }
1662
+ function FastModeHeaderContribution(props) {
1663
+ const currentList = props.useSessions ? props.useSessions((s) => s) : void 0;
1664
+ const derivedId = props.sessionId || (currentList ? currentSessionId(currentList) : void 0) || currentSessionId(props.ctx.sessions?.list?.getSnapshot());
1665
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1666
+ FastModeButton,
1667
+ {
1668
+ sessionId: derivedId ? String(derivedId) : void 0,
1669
+ activation: props.activation,
1670
+ ctx: props.ctx
1671
+ }
1672
+ );
1673
+ }
1674
+ var clientPatch4 = {
1675
+ id: FAST_MODE_PATCH_ID,
1676
+ install: (ctx, activation) => {
1677
+ ctx.slots.inject(
1678
+ "conversation.input.right",
1679
+ () => ctx.slots.register(
1680
+ {
1681
+ name: "conversation.input.right",
1682
+ id: `${PLUGIN_NAME}-${FAST_MODE_PATCH_ID}`,
1683
+ order: 10,
1684
+ priority: 10,
1685
+ inject: (sessionId) => ({
1686
+ sessionId: sessionId ? String(sessionId) : void 0
1687
+ })
1688
+ },
1689
+ (props) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FastModeInputContribution, { ...props, ctx, activation })
1690
+ )
1691
+ );
1692
+ ctx.slots.inject(
1693
+ "conversation.session.header.utilities",
1694
+ () => ctx.slots.register(
1695
+ {
1696
+ name: "conversation.session.header.utilities",
1697
+ id: `${PLUGIN_NAME}-${FAST_MODE_PATCH_ID}-header`,
1698
+ order: 85
1699
+ },
1700
+ (props) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FastModeHeaderContribution, { ...props, ctx, activation })
1701
+ )
1702
+ );
1703
+ const registerCommand = (scope) => {
1704
+ const command = scope.commandUi ?? scope.get?.("commandUi");
1705
+ const sessions = scope.sessions ?? scope.get?.("sessions");
1706
+ if (command && typeof command.register === "function") {
1707
+ scope.effect(
1708
+ () => command.register({
1709
+ name: "fast",
1710
+ label: () => "\u52A0\u901F",
1711
+ description: () => "\u5F00\u542F\u6216\u5173\u95ED\u5F53\u524D\u4F1A\u8BDD\u7684\u52A0\u901F\u3002\u54CD\u5E94\u66F4\u5FEB\uFF0C\u4F46\u4F1A\u66F4\u5FEB\u6D88\u8017\u989D\u5EA6",
1712
+ available: (session) => sessions?.subagentAddress?.(session.sessionId) === void 0,
1713
+ ui: {
1714
+ kind: "action",
1715
+ run: (session) => {
1716
+ void toggleFastMode(ctx, String(session.sessionId));
1717
+ }
1718
+ }
1719
+ }),
1720
+ "fast-mode: /fast command"
1721
+ );
1722
+ }
1723
+ };
1724
+ if (typeof ctx.inject === "function") {
1725
+ try {
1726
+ ctx.inject(["commandUi"], (scope) => {
1727
+ registerCommand(scope);
1728
+ });
1729
+ } catch {
1730
+ registerCommand(ctx);
1731
+ }
1732
+ } else {
1733
+ registerCommand(ctx);
1734
+ }
1401
1735
  }
1402
1736
  };
1403
1737
 
@@ -1405,7 +1739,7 @@ var clientPatch3 = {
1405
1739
  var SESSION_AUTO_TITLE_PATCH_ID = "session-auto-title";
1406
1740
 
1407
1741
  // src/patches/session-auto-title/client/index.ts
1408
- var clientPatch4 = {
1742
+ var clientPatch5 = {
1409
1743
  id: SESSION_AUTO_TITLE_PATCH_ID,
1410
1744
  install: () => {
1411
1745
  }
@@ -1415,13 +1749,14 @@ var clientPatch4 = {
1415
1749
  var PROJECTLESS_TASKS_PATCH_ID = "projectless-tasks";
1416
1750
 
1417
1751
  // src/patches/projectless-tasks/client/adapter.tsx
1418
- var import_react9 = require("react");
1752
+ var import_react11 = require("react");
1419
1753
 
1420
1754
  // src/patches/projectless-tasks/client/create-task.ts
1421
1755
  function createTaskStarter(sessions) {
1422
1756
  let pendingId;
1423
1757
  let flight;
1424
1758
  let disposed = false;
1759
+ let reference;
1425
1760
  return {
1426
1761
  start(beforeOpen) {
1427
1762
  if (disposed) return Promise.reject(new Error("\u72EC\u7ACB\u4EFB\u52A1\u8865\u4E01\u5DF2\u5173\u95ED\u3002"));
@@ -1436,8 +1771,21 @@ function createTaskStarter(sessions) {
1436
1771
  if (disposed) return;
1437
1772
  const id = await sessions.create({ sessionId, cwd: location.cwd });
1438
1773
  if (id !== sessionId) throw new Error("\u521B\u5EFA\u7ED3\u679C\u4E0E\u72EC\u7ACB\u4EFB\u52A1\u6807\u8BC6\u4E0D\u4E00\u81F4\u3002");
1439
- if (!disposed && beforeOpen?.(id) !== false) sessions.open(id);
1440
- pendingId = void 0;
1774
+ if (disposed) return;
1775
+ const retained = sessions.retain?.(id);
1776
+ reference = retained;
1777
+ try {
1778
+ if (retained !== void 0) await retained.ready;
1779
+ if (!disposed && beforeOpen?.(id) !== false) sessions.open(id);
1780
+ pendingId = void 0;
1781
+ } catch (error) {
1782
+ if (!disposed) throw error;
1783
+ } finally {
1784
+ if (reference === retained) {
1785
+ retained?.release();
1786
+ reference = void 0;
1787
+ }
1788
+ }
1441
1789
  })().finally(() => {
1442
1790
  flight = void 0;
1443
1791
  });
@@ -1445,6 +1793,8 @@ function createTaskStarter(sessions) {
1445
1793
  },
1446
1794
  dispose() {
1447
1795
  disposed = true;
1796
+ reference?.release();
1797
+ reference = void 0;
1448
1798
  }
1449
1799
  };
1450
1800
  }
@@ -1481,7 +1831,7 @@ function transferBeforeOpen(ctx, sourceId, targetId) {
1481
1831
  }
1482
1832
  const sessions = value;
1483
1833
  const list = sessions.list.getSnapshot();
1484
- if (list.current !== sourceId) return false;
1834
+ if (currentSessionId(list) !== sourceId) return false;
1485
1835
  if (sourceId === void 0 || sourceId === targetId) return true;
1486
1836
  if (list.byId[sourceId]?.blank !== true) throw new Error("\u5F53\u524D\u4F1A\u8BDD\u5DF2\u5F00\u59CB\uFF0C\u8BF7\u65B0\u5EFA\u4F1A\u8BDD\u540E\u9009\u62E9\u72EC\u7ACB\u4EFB\u52A1\u3002");
1487
1837
  const source = sessions.scope(sourceId);
@@ -1497,8 +1847,8 @@ function transferBeforeOpen(ctx, sourceId, targetId) {
1497
1847
  }
1498
1848
 
1499
1849
  // src/patches/projectless-tasks/client/picker.tsx
1500
- var import_react8 = require("react");
1501
- var import_jsx_runtime7 = require("react/jsx-runtime");
1850
+ var import_react10 = require("react");
1851
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1502
1852
  var INDEPENDENT_CHOICE_ID = "::dsh-more-independent-task";
1503
1853
  var INDEPENDENT_CHOICE = {
1504
1854
  workspaceId: INDEPENDENT_CHOICE_ID,
@@ -1508,7 +1858,7 @@ var INDEPENDENT_CHOICE = {
1508
1858
  createdAt: "",
1509
1859
  updatedAt: ""
1510
1860
  };
1511
- var ChoiceContext = (0, import_react8.createContext)(void 0);
1861
+ var ChoiceContext = (0, import_react10.createContext)(void 0);
1512
1862
  function withIndependentChoice(snapshot) {
1513
1863
  return { ...snapshot, items: [INDEPENDENT_CHOICE, ...snapshot.items] };
1514
1864
  }
@@ -1529,7 +1879,7 @@ function labelIndependentChip(anchor) {
1529
1879
  };
1530
1880
  }
1531
1881
  function WorkspaceChoice({ owner, state, error, children }) {
1532
- (0, import_react8.useLayoutEffect)(() => {
1882
+ (0, import_react10.useLayoutEffect)(() => {
1533
1883
  const anchor = owner.anchorRef?.current;
1534
1884
  if (!state.independent || owner.selectedId !== void 0 || anchor === void 0 || anchor === null) return;
1535
1885
  return labelIndependentChip(anchor);
@@ -1538,9 +1888,9 @@ function WorkspaceChoice({ owner, state, error, children }) {
1538
1888
  owner.onClose();
1539
1889
  state.chooseIndependent();
1540
1890
  };
1541
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(ChoiceContext.Provider, { value: state, children: [
1891
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ChoiceContext.Provider, { value: state, children: [
1542
1892
  children,
1543
- owner.selectedId !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1893
+ owner.selectedId !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1544
1894
  "button",
1545
1895
  {
1546
1896
  type: "button",
@@ -1552,9 +1902,9 @@ function WorkspaceChoice({ owner, state, error, children }) {
1552
1902
  children: "\xD7"
1553
1903
  }
1554
1904
  ),
1555
- state.busy && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dshmore-workspace-status", role: "status", children: "\u5207\u6362\u4E2D\u2026" }),
1556
- error !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dshmore-workspace-error", role: "alert", children: error }),
1557
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
1905
+ state.busy && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "dshmore-workspace-status", role: "status", children: "\u5207\u6362\u4E2D\u2026" }),
1906
+ error !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "dshmore-workspace-error", role: "alert", children: error }),
1907
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `
1558
1908
  .dshmore-workspace-clear { display:inline-flex; align-items:center; justify-content:center; flex:none; width:22px; height:22px; margin:0 4px 0 -2px; padding:0; border:0; border-radius:50%; color:var(--dsw-alias-label-secondary); background:transparent; font:18px/1 sans-serif; cursor:pointer; }
1559
1909
  .dshmore-workspace-clear:hover { color:var(--dsw-alias-label-primary); background:var(--dsw-alias-interactive-bg-hover); }
1560
1910
  .dshmore-workspace-clear:disabled { opacity:.45; cursor:wait; }
@@ -1565,11 +1915,11 @@ function WorkspaceChoice({ owner, state, error, children }) {
1565
1915
  }
1566
1916
  function extendWorkspacePicker(original) {
1567
1917
  return function ProjectlessPicker(props) {
1568
- const choice = (0, import_react8.useContext)(ChoiceContext);
1918
+ const choice = (0, import_react10.useContext)(ChoiceContext);
1569
1919
  const snapshot = props.useWorkspaces((value) => value);
1570
- const display = (0, import_react8.useMemo)(() => choice === void 0 ? snapshot : withIndependentChoice(snapshot), [snapshot, choice === void 0]);
1920
+ const display = (0, import_react10.useMemo)(() => choice === void 0 ? snapshot : withIndependentChoice(snapshot), [snapshot, choice === void 0]);
1571
1921
  const useWorkspaces = (select) => select(display);
1572
- return (0, import_react8.createElement)(original, {
1922
+ return (0, import_react10.createElement)(original, {
1573
1923
  ...props,
1574
1924
  useWorkspaces,
1575
1925
  open: props.open && !choice?.busy,
@@ -1608,20 +1958,13 @@ function installPickerAdapter(ctx) {
1608
1958
  }
1609
1959
 
1610
1960
  // src/patches/projectless-tasks/client/adapter.tsx
1611
- var import_jsx_runtime8 = require("react/jsx-runtime");
1961
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1612
1962
  function isComposerOwner(owner) {
1613
1963
  return "variant" in owner && (owner.variant === "hero" || owner.variant === "composer");
1614
1964
  }
1615
1965
  function isWorkspaceOwner(owner) {
1616
1966
  return "open" in owner && typeof owner.open === "boolean" && "onPick" in owner && typeof owner.onPick === "function" && "onClose" in owner && typeof owner.onClose === "function";
1617
1967
  }
1618
- function clientSessionActions(ctx) {
1619
- const sessions = ctx.sessions;
1620
- if (typeof sessions !== "object" || sessions === null || !("create" in sessions) || !("open" in sessions) || typeof sessions.create !== "function" || typeof sessions.open !== "function") {
1621
- throw new Error("\u5F53\u524D DSH \u7248\u672C\u4E0D\u652F\u6301\u72EC\u7ACB\u4EFB\u52A1\uFF0C\u8BF7\u68C0\u67E5\u4F1A\u8BDD\u63A5\u53E3\u3002");
1622
- }
1623
- return sessions;
1624
- }
1625
1968
  function unlockComposer(owner, independent, block) {
1626
1969
  if (!independent || owner.disabled !== true || owner.onRequestWorkspace === void 0) return owner;
1627
1970
  const { disabled: _disabled, onRequestWorkspace: _request, workspacePickerOpen: _picker, placeholder: _placeholder, ...rest } = owner;
@@ -1644,54 +1987,11 @@ function installConversationAdapter(ctx, activation, name = "main.conversation")
1644
1987
  };
1645
1988
  const sync = () => {
1646
1989
  for (const entry of ctx.slots.entries(slot)) {
1647
- let ProjectlessConversation2 = function(props) {
1648
- const active = (0, import_react9.useSyncExternalStore)(subscribeLifetime, () => live);
1649
- const settings = (0, import_react9.useSyncExternalStore)(activation.subscribe, activation.getSnapshot);
1650
- const workspace = props.useWorkspaces((snapshot) => snapshot);
1651
- const cwd = props.useSessions((snapshot) => props.sessionId === void 0 ? void 0 : snapshot.byId[props.sessionId]?.cwd);
1652
- const session = props.useSession((snapshot) => snapshot);
1653
- const block = props.useComposerBlock((value) => value);
1654
- const enabled = active && settings[PROJECTLESS_TASKS_PATCH_ID];
1655
- const starter = (0, import_react9.useRef)();
1656
- const [busy, setBusy] = (0, import_react9.useState)(false);
1657
- const [error, setError] = (0, import_react9.useState)();
1658
- (0, import_react9.useEffect)(() => {
1659
- if (!enabled) return;
1660
- setBusy(false);
1661
- setError(void 0);
1662
- return () => {
1663
- starter.current?.dispose();
1664
- starter.current = void 0;
1665
- };
1666
- }, [enabled]);
1667
- const independent = enabled && props.sessionId !== void 0 && session?.openState === "open" && typeof cwd === "string" && cwd.length > 0 && workspace.phase === "ready" && !workspace.items.some((item) => item.sessionIds.includes(props.sessionId));
1668
- const chooseIndependent = () => {
1669
- if (!enabled || busy || independent) return;
1670
- const operation = starter.current ??= createTaskStarter(clientSessionActions(ctx));
1671
- setBusy(true);
1672
- setError(void 0);
1673
- void operation.start((id) => transferBeforeOpen(ctx, props.sessionId, id)).catch((reason) => {
1674
- if (starter.current === operation) setError(apiErrorText(reason));
1675
- }).finally(() => {
1676
- if (starter.current === operation) setBusy(false);
1677
- });
1678
- };
1679
- const renderSlot = (name2, owner, options) => {
1680
- if (name2 === "conversation.composer.bar" && isComposerOwner(owner)) {
1681
- return props.renderSlot("conversation.composer.bar", unlockComposer(owner, independent, block), options);
1682
- }
1683
- if (enabled && name2 === "conversation.hero.workspace" && isWorkspaceOwner(owner)) {
1684
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(WorkspaceChoice, { owner, state: { independent, busy, chooseIndependent }, error, children: props.renderSlot("conversation.hero.workspace", owner, options) });
1685
- }
1686
- return props.renderSlot(name2, owner, options);
1687
- };
1688
- return (0, import_react9.createElement)(original, { ...props, renderSlot });
1689
- };
1690
- var ProjectlessConversation = ProjectlessConversation2;
1691
1990
  if (wrapped.has(entry) || entry.children?.["conversation.composer.bar"] === void 0 || typeof entry.component !== "function") continue;
1692
1991
  const original = entry.component;
1693
- wrapped.set(entry, { original, component: ProjectlessConversation2 });
1694
- entry.component = ProjectlessConversation2;
1992
+ const ProjectlessConversation = wrapConversation(ctx, activation, original, subscribeLifetime, () => live);
1993
+ wrapped.set(entry, { original, component: ProjectlessConversation });
1994
+ entry.component = ProjectlessConversation;
1695
1995
  }
1696
1996
  };
1697
1997
  const unsubscribe = ctx.slots.subscribe(slot, sync);
@@ -1709,14 +2009,95 @@ function installConversationAdapter(ctx, activation, name = "main.conversation")
1709
2009
  fallback();
1710
2010
  };
1711
2011
  }
2012
+ function wrapConversation(ctx, activation, original, subscribeLifetime, isLive) {
2013
+ return function ProjectlessConversation(props) {
2014
+ const active = (0, import_react11.useSyncExternalStore)(subscribeLifetime, isLive);
2015
+ const settings = (0, import_react11.useSyncExternalStore)(activation.subscribe, activation.getSnapshot);
2016
+ const workspace = props.useWorkspaces((snapshot) => snapshot);
2017
+ const cwd = props.useSessions((snapshot) => props.sessionId === void 0 ? void 0 : snapshot.byId[props.sessionId]?.cwd);
2018
+ const session = props.useSession((snapshot) => snapshot);
2019
+ const block = props.useComposerBlock((value) => value);
2020
+ const enabled = active && settings[PROJECTLESS_TASKS_PATCH_ID];
2021
+ const starter = (0, import_react11.useRef)();
2022
+ const [busy, setBusy] = (0, import_react11.useState)(false);
2023
+ const [error, setError] = (0, import_react11.useState)();
2024
+ (0, import_react11.useEffect)(() => {
2025
+ if (!enabled) return;
2026
+ setBusy(false);
2027
+ setError(void 0);
2028
+ return () => {
2029
+ starter.current?.dispose();
2030
+ starter.current = void 0;
2031
+ };
2032
+ }, [enabled]);
2033
+ const independent = enabled && props.sessionId !== void 0 && session?.openState === "open" && typeof cwd === "string" && cwd.length > 0 && workspace.phase === "ready" && !workspace.items.some((item) => item.sessionIds.includes(props.sessionId));
2034
+ const chooseIndependent = () => {
2035
+ if (!enabled || busy || independent) return;
2036
+ const operation = starter.current ??= createTaskStarter(clientSessionActions(ctx));
2037
+ setBusy(true);
2038
+ setError(void 0);
2039
+ void operation.start((id) => transferBeforeOpen(ctx, props.sessionId, id)).catch((reason) => {
2040
+ if (starter.current === operation) setError(apiErrorText(reason));
2041
+ }).finally(() => {
2042
+ if (starter.current === operation) setBusy(false);
2043
+ });
2044
+ };
2045
+ const renderSlot = (name, owner, options) => {
2046
+ if (name === "conversation.composer.bar" && isComposerOwner(owner)) {
2047
+ return props.renderSlot("conversation.composer.bar", unlockComposer(owner, independent, block), options);
2048
+ }
2049
+ if (enabled && name === "conversation.hero.workspace" && isWorkspaceOwner(owner)) {
2050
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(WorkspaceChoice, { owner, state: { independent, busy, chooseIndependent }, error, children: props.renderSlot("conversation.hero.workspace", owner, options) });
2051
+ }
2052
+ return props.renderSlot(name, owner, options);
2053
+ };
2054
+ return (0, import_react11.createElement)(original, { ...props, renderSlot });
2055
+ };
2056
+ }
2057
+ function installConversationFactoryAdapter(ctx, activation) {
2058
+ const slots = ctx.slots;
2059
+ const candidate = typeof slots.hostFace === "function" ? slots.hostFace() : void 0;
2060
+ if (typeof candidate !== "object" || candidate === null || !("factoryOf" in candidate) || typeof candidate.factoryOf !== "function" || !("subscribeFactory" in candidate) || typeof candidate.subscribeFactory !== "function") return () => {
2061
+ };
2062
+ const registry = candidate;
2063
+ const wrapped = /* @__PURE__ */ new Map();
2064
+ let live = true;
2065
+ const listeners = /* @__PURE__ */ new Set();
2066
+ const subscribeLifetime = (listener) => {
2067
+ listeners.add(listener);
2068
+ return () => {
2069
+ listeners.delete(listener);
2070
+ };
2071
+ };
2072
+ const sync = () => {
2073
+ const definition = registry.factoryOf("conversation.content");
2074
+ if (definition === void 0 || wrapped.has(definition) || definition.children?.["conversation.composer.bar"] === void 0 || typeof definition.component !== "function") return;
2075
+ const original = definition.component;
2076
+ const component = wrapConversation(ctx, activation, original, subscribeLifetime, () => live);
2077
+ wrapped.set(definition, { original, component });
2078
+ definition.component = component;
2079
+ };
2080
+ const unsubscribe = registry.subscribeFactory("conversation.content", sync);
2081
+ sync();
2082
+ return () => {
2083
+ live = false;
2084
+ listeners.forEach((listener) => listener());
2085
+ unsubscribe();
2086
+ for (const [definition, patch] of wrapped) {
2087
+ if (definition.component === patch.component) definition.component = patch.original;
2088
+ }
2089
+ wrapped.clear();
2090
+ };
2091
+ }
1712
2092
 
1713
2093
  // src/patches/projectless-tasks/client/new-session.ts
1714
2094
  function newSessionTarget(list, workspaces, explicit) {
1715
2095
  if (explicit !== void 0) return { kind: "workspace", workspaceId: explicit };
1716
- if (list.current === void 0) return { kind: "native" };
2096
+ const current = currentSessionId(list);
2097
+ if (current === void 0) return { kind: "native" };
1717
2098
  if (list.phase !== "ready" || workspaces.phase !== "ready") return { kind: "pending" };
1718
2099
  const visited = /* @__PURE__ */ new Set();
1719
- let id = list.current;
2100
+ let id = current;
1720
2101
  while (id !== void 0 && !visited.has(id)) {
1721
2102
  visited.add(id);
1722
2103
  const workspace = workspaces.items.find((item) => item.sessionIds.includes(id));
@@ -1727,7 +2108,7 @@ function newSessionTarget(list, workspaces, explicit) {
1727
2108
  id = summary.parentId;
1728
2109
  continue;
1729
2110
  }
1730
- return typeof summary.cwd === "string" && summary.cwd.length > 0 ? { kind: "independent", sourceId: list.current } : { kind: "pending" };
2111
+ return typeof summary.cwd === "string" && summary.cwd.length > 0 ? { kind: "independent", sourceId: current } : { kind: "pending" };
1731
2112
  }
1732
2113
  return { kind: "pending" };
1733
2114
  }
@@ -1760,7 +2141,8 @@ function bindNewSessionNavigation({ navigation, sessions, workspaces, activation
1760
2141
  }
1761
2142
  if (target.kind === "pending") {
1762
2143
  cancel();
1763
- if (list.current !== void 0) reportError(list.current, new Error("\u4F1A\u8BDD\u6765\u6E90\u4ECD\u5728\u52A0\u8F7D\uFF0C\u8BF7\u7A0D\u540E\u518D\u65B0\u5EFA\u4F1A\u8BDD\u3002"));
2144
+ const current2 = currentSessionId(list);
2145
+ if (current2 !== void 0) reportError(current2, new Error("\u4F1A\u8BDD\u6765\u6E90\u4ECD\u5728\u52A0\u8F7D\uFF0C\u8BF7\u7A0D\u540E\u518D\u65B0\u5EFA\u4F1A\u8BDD\u3002"));
1764
2146
  return;
1765
2147
  }
1766
2148
  if (attempt?.sourceId !== target.sourceId) {
@@ -1774,7 +2156,7 @@ function bindNewSessionNavigation({ navigation, sessions, workspaces, activation
1774
2156
  const destination = newSessionTarget(sessions.list.getSnapshot(), workspaces.list.getSnapshot());
1775
2157
  return destination.kind === "independent" && destination.sourceId === current.sourceId;
1776
2158
  }).catch((error) => {
1777
- if (active && attempt === current && sessions.list.getSnapshot().current === current.sourceId) {
2159
+ if (active && attempt === current && currentSessionId(sessions.list.getSnapshot()) === current.sourceId) {
1778
2160
  reportError(current.sourceId, error);
1779
2161
  }
1780
2162
  }).finally(() => {
@@ -1806,17 +2188,17 @@ function bindNewSessionNavigation({ navigation, sessions, workspaces, activation
1806
2188
  function installNewSessionNavigation(ctx, activation) {
1807
2189
  const navigation = ctx.get("uiWorkspace");
1808
2190
  const sessions = ctx.sessions;
1809
- if (typeof navigation !== "object" || navigation === null || !("startSession" in navigation) || typeof navigation.startSession !== "function" || typeof sessions !== "object" || sessions === null || !("create" in sessions) || typeof sessions.create !== "function" || !("open" in sessions) || typeof sessions.open !== "function" || !("scope" in sessions) || typeof sessions.scope !== "function" || !("list" in sessions) || typeof sessions.list !== "object" || sessions.list === null || !("getSnapshot" in sessions.list) || typeof sessions.list.getSnapshot !== "function") {
2191
+ if (typeof navigation !== "object" || navigation === null || !("startSession" in navigation) || typeof navigation.startSession !== "function" || typeof sessions !== "object" || sessions === null || !("create" in sessions) || typeof sessions.create !== "function" || !("scope" in sessions) || typeof sessions.scope !== "function" || !("list" in sessions) || typeof sessions.list !== "object" || sessions.list === null || !("getSnapshot" in sessions.list) || typeof sessions.list.getSnapshot !== "function") {
1810
2192
  throw new Error("\u5F53\u524D DSH \u7248\u672C\u4E0D\u652F\u6301\u8DDF\u968F\u4F1A\u8BDD\u6765\u6E90\u65B0\u5EFA\u4EFB\u52A1\u3002");
1811
2193
  }
1812
- const clientSessions = sessions;
2194
+ const clientSessions2 = sessions;
1813
2195
  return bindNewSessionNavigation({
1814
2196
  navigation,
1815
- sessions: clientSessions,
2197
+ sessions: { ...clientSessionActions(ctx), list: clientSessions2.list },
1816
2198
  workspaces: ctx.workspaces,
1817
2199
  activation,
1818
2200
  reportError: (sourceId, error) => {
1819
- const scope = clientSessions.scope(sourceId);
2201
+ const scope = clientSessions2.scope(sourceId);
1820
2202
  const message = `\u65B0\u5EFA\u4F1A\u8BDD\u5931\u8D25\uFF1A${apiErrorText(error)}`;
1821
2203
  if (scope !== void 0) ctx.conversation.input.for(scope).notify("error", message);
1822
2204
  else ctx.logger.warn(message);
@@ -1825,7 +2207,7 @@ function installNewSessionNavigation(ctx, activation) {
1825
2207
  }
1826
2208
 
1827
2209
  // src/patches/projectless-tasks/client/groups.tsx
1828
- var import_react10 = require("react");
2210
+ var import_react12 = require("react");
1829
2211
  var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
1830
2212
 
1831
2213
  // src/patches/projectless-tasks/groups.ts
@@ -1890,7 +2272,7 @@ function installMoveMenu(onMove) {
1890
2272
  }
1891
2273
 
1892
2274
  // src/patches/projectless-tasks/client/groups.tsx
1893
- var import_jsx_runtime9 = require("react/jsx-runtime");
2275
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1894
2276
  function projectSessionGroups(workspaces, sessions, groups) {
1895
2277
  const owned = new Set(workspaces.items.flatMap((item) => item.sessionIds));
1896
2278
  const items = workspaces.items.map((workspace) => {
@@ -1902,35 +2284,49 @@ function projectSessionGroups(workspaces, sessions, groups) {
1902
2284
  var SIDEBAR_SLOT = "sidebar.workspaces";
1903
2285
  var ALWAYS_LIVE = { subscribe: () => () => {
1904
2286
  }, getSnapshot: () => true };
1905
- function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LIVE) {
2287
+ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LIVE, ctx) {
1906
2288
  return function GroupedSidebar(props) {
1907
- const settings = (0, import_react10.useSyncExternalStore)(activation.subscribe, activation.getSnapshot);
1908
- const binding = (0, import_react10.useMemo)(() => ({ subscribe: (listener) => source.subscribe(listener), getSnapshot: () => source.getSnapshot() }), []);
1909
- const saved = (0, import_react10.useSyncExternalStore)(binding.subscribe, binding.getSnapshot);
2289
+ const settings = (0, import_react12.useSyncExternalStore)(activation.subscribe, activation.getSnapshot);
2290
+ const binding = (0, import_react12.useMemo)(() => ({ subscribe: (listener) => source.subscribe(listener), getSnapshot: () => source.getSnapshot() }), []);
2291
+ const saved = (0, import_react12.useSyncExternalStore)(binding.subscribe, binding.getSnapshot);
1910
2292
  const native = props.useWorkspaces((value) => value);
1911
2293
  const sessions = props.useSessions((value) => value);
1912
- const active = (0, import_react10.useSyncExternalStore)(lifetime.subscribe, lifetime.getSnapshot);
2294
+ const active = (0, import_react12.useSyncExternalStore)(lifetime.subscribe, lifetime.getSnapshot);
1913
2295
  const enabled = active && settings[PROJECTLESS_TASKS_PATCH_ID];
1914
2296
  const groups = saved.value ?? EMPTY_GROUPS;
1915
- const display = (0, import_react10.useMemo)(() => enabled ? projectSessionGroups(native, sessions, groups) : native, [enabled, native, sessions, groups]);
1916
- const [pending, setPending] = (0, import_react10.useState)();
1917
- const [destination, setDestination] = (0, import_react10.useState)("");
1918
- const [busy, setBusy] = (0, import_react10.useState)(false);
1919
- const [error, setError] = (0, import_react10.useState)();
1920
- const intent = (0, import_react10.useRef)(false);
1921
- const inFlight = (0, import_react10.useRef)(false);
1922
- const live = (0, import_react10.useRef)(true);
1923
- (0, import_react10.useEffect)(() => {
2297
+ const display = (0, import_react12.useMemo)(() => enabled ? projectSessionGroups(native, sessions, groups) : native, [enabled, native, sessions, groups]);
2298
+ const [pending, setPending] = (0, import_react12.useState)();
2299
+ const [destination, setDestination] = (0, import_react12.useState)("");
2300
+ const [busy, setBusy] = (0, import_react12.useState)(false);
2301
+ const [error, setError] = (0, import_react12.useState)();
2302
+ const groupsRef = (0, import_react12.useRef)(groups);
2303
+ groupsRef.current = groups;
2304
+ const requestMove = (id) => {
2305
+ setPending(id);
2306
+ setDestination(groupsRef.current.assignments[id] ?? "");
2307
+ setError(void 0);
2308
+ };
2309
+ const intent = (0, import_react12.useRef)(false);
2310
+ const inFlight = (0, import_react12.useRef)(false);
2311
+ const live = (0, import_react12.useRef)(true);
2312
+ (0, import_react12.useEffect)(() => {
1924
2313
  live.current = true;
1925
2314
  return () => {
1926
2315
  live.current = false;
1927
2316
  };
1928
2317
  }, []);
1929
- (0, import_react10.useEffect)(() => {
2318
+ (0, import_react12.useEffect)(() => {
1930
2319
  if (!enabled) {
1931
2320
  setPending(void 0);
1932
2321
  return;
1933
2322
  }
2323
+ const removeNativeItem = ctx === void 0 ? void 0 : installSessionMenuAction(ctx, {
2324
+ id: "dsh-more-session-move",
2325
+ label: "\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A\u2026",
2326
+ order: 350,
2327
+ select: requestMove
2328
+ });
2329
+ if (removeNativeItem !== void 0) return removeNativeItem;
1934
2330
  return installMoveMenu((archive) => {
1935
2331
  intent.current = true;
1936
2332
  try {
@@ -1943,9 +2339,7 @@ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LI
1943
2339
  const archiveSession = (id) => {
1944
2340
  if (!intent.current) return props.archiveSession(id);
1945
2341
  intent.current = false;
1946
- setPending(id);
1947
- setDestination(groups.assignments[id] ?? "");
1948
- setError(void 0);
2342
+ requestMove(id);
1949
2343
  return Promise.resolve();
1950
2344
  };
1951
2345
  const useWorkspaces = (select) => select(display);
@@ -1971,9 +2365,9 @@ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LI
1971
2365
  const subagent = pending !== void 0 && sessions.byId[pending]?.origin === "subagent";
1972
2366
  const selectedMissing = destination !== "" && !native.items.some((item) => item.workspaceId === destination);
1973
2367
  const unavailable = groupedNatively ? "\u8FD9\u6761\u4F1A\u8BDD\u5DF2\u6709\u539F\u751F\u5DE5\u4F5C\u533A\uFF0C\u53EA\u652F\u6301\u79FB\u52A8\u672A\u5206\u7EC4\u6216\u624B\u52A8\u5F52\u7EC4\u7684\u4F1A\u8BDD\u3002" : subagent ? "\u5B50\u4F1A\u8BDD\u8DDF\u968F\u4E3B\u4F1A\u8BDD\u5F52\u7EC4\uFF0C\u8BF7\u79FB\u52A8\u4E3B\u4F1A\u8BDD\u3002" : saved.status !== "ready" ? "\u5F52\u7EC4\u8BBE\u7F6E\u5C1A\u672A\u5C31\u7EEA\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u91CD\u542F DSH \u540E\u53F0\u5E76\u5237\u65B0\u9875\u9762\u3002" : !saved.writable ? "\u5F53\u524D\u914D\u7F6E\u4E3A\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u79FB\u52A8\u4F1A\u8BDD\u3002" : selectedMissing ? "\u76EE\u6807\u5DE5\u4F5C\u533A\u5DF2\u4E0D\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u3002" : void 0;
1974
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1975
- (0, import_react10.createElement)(original, { ...props, useWorkspaces, archiveSession }),
1976
- enabled && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2368
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2369
+ (0, import_react12.createElement)(original, { ...props, useWorkspaces, archiveSession }),
2370
+ enabled && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1977
2371
  import_dsh_client_ui_primitives6.Modal,
1978
2372
  {
1979
2373
  open: pending !== void 0,
@@ -1981,15 +2375,15 @@ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LI
1981
2375
  title: "\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A",
1982
2376
  closeLabel: "\u5173\u95ED",
1983
2377
  description: "\u4FDD\u7559\u4F1A\u8BDD\u5386\u53F2\u548C\u539F\u5DE5\u4F5C\u76EE\u5F55\uFF0C\u4EC5\u8C03\u6574\u5217\u8868\u5F52\u5C5E\u3002",
1984
- footer: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1985
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_dsh_client_ui_primitives6.Button, { variant: "ghost", disabled: busy, onClick: close, children: "\u53D6\u6D88" }),
1986
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_dsh_client_ui_primitives6.Button, { variant: "primary", disabled: busy || unavailable !== void 0 || pending === void 0 || (groups.assignments[pending] ?? "") === destination, onClick: () => void move(), children: busy ? "\u6B63\u5728\u79FB\u52A8\u2026" : "\u79FB\u52A8" })
2378
+ footer: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2379
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_dsh_client_ui_primitives6.Button, { variant: "ghost", disabled: busy, onClick: close, children: "\u53D6\u6D88" }),
2380
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_dsh_client_ui_primitives6.Button, { variant: "primary", disabled: busy || unavailable !== void 0 || pending === void 0 || (groups.assignments[pending] ?? "") === destination, onClick: () => void move(), children: busy ? "\u6B63\u5728\u79FB\u52A8\u2026" : "\u79FB\u52A8" })
1987
2381
  ] }),
1988
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "grid", gap: 12 }, children: [
1989
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { children: pending === void 0 ? "" : sessions.byId[pending]?.displayTitle ?? pending }),
1990
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { display: "grid", gap: 8 }, children: [
2382
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "grid", gap: 12 }, children: [
2383
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { children: pending === void 0 ? "" : sessions.byId[pending]?.displayTitle ?? pending }),
2384
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { style: { display: "grid", gap: 8 }, children: [
1991
2385
  "\u76EE\u6807\u5DE5\u4F5C\u533A",
1992
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2386
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1993
2387
  "select",
1994
2388
  {
1995
2389
  "aria-label": "\u76EE\u6807\u5DE5\u4F5C\u533A",
@@ -1998,13 +2392,13 @@ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LI
1998
2392
  onChange: (event) => setDestination(event.target.value),
1999
2393
  style: { width: "100%", minHeight: 40, borderRadius: 10, padding: "8px 12px", color: "var(--dsw-alias-label-primary)", background: "var(--dsw-alias-button-elevated-fill)", border: "1px solid var(--dsw-alias-border-l4)" },
2000
2394
  children: [
2001
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: "", children: "\u672A\u5206\u7EC4" }),
2002
- native.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: item.workspaceId, children: item.title || item.path }, item.workspaceId))
2395
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "", children: "\u672A\u5206\u7EC4" }),
2396
+ native.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: item.workspaceId, children: item.title || item.path }, item.workspaceId))
2003
2397
  ]
2004
2398
  }
2005
2399
  )
2006
2400
  ] }),
2007
- (error ?? unavailable) !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "alert", style: { color: "var(--dsw-alias-state-error-primary)" }, children: error ?? unavailable })
2401
+ (error ?? unavailable) !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "alert", style: { color: "var(--dsw-alias-state-error-primary)" }, children: error ?? unavailable })
2008
2402
  ] })
2009
2403
  }
2010
2404
  )
@@ -2027,7 +2421,7 @@ function installSessionGrouping(ctx, activation) {
2027
2421
  for (const entry of ctx.slots.entries(SIDEBAR_SLOT)) {
2028
2422
  if (wrapped.has(entry) || entry.children?.["sidebar.workspaces.directoryFlow"] === void 0 || typeof entry.component !== "function") continue;
2029
2423
  const original = entry.component;
2030
- const component = extendGroupedSidebar(original, activation, source, lifetime);
2424
+ const component = extendGroupedSidebar(original, activation, source, lifetime, ctx);
2031
2425
  wrapped.set(entry, { original, component });
2032
2426
  entry.component = component;
2033
2427
  }
@@ -2048,12 +2442,13 @@ function installSessionGrouping(ctx, activation) {
2048
2442
  }
2049
2443
 
2050
2444
  // src/patches/projectless-tasks/client/index.tsx
2051
- var clientPatch5 = {
2445
+ var clientPatch6 = {
2052
2446
  id: PROJECTLESS_TASKS_PATCH_ID,
2053
2447
  install: (ctx, activation) => {
2054
2448
  installSessionGrouping(ctx, activation);
2055
2449
  ctx.inject(["conversation", "uiWorkspace"], (scope) => {
2056
2450
  scope.effect(() => installNewSessionNavigation(scope, activation));
2451
+ scope.effect(() => installConversationFactoryAdapter(scope, activation));
2057
2452
  for (const name of CONVERSATION_SLOTS) {
2058
2453
  scope.slots.inject(conversationSlot(name), () => installConversationAdapter(scope, activation, name));
2059
2454
  }
@@ -2064,7 +2459,7 @@ var clientPatch5 = {
2064
2459
 
2065
2460
  // src/generated/client-registry.ts
2066
2461
  var MESSAGE_ACTION_PATCHES = [{ id: "message-edit", order: 100, useActions: useMessageActions }, { id: "message-delete", order: 200, useActions: useMessageActions2 }];
2067
- var CLIENT_PATCHES = [clientPatch, clientPatch2, clientPatch3, clientPatch4, clientPatch5];
2462
+ var CLIENT_PATCHES = [clientPatch, clientPatch2, clientPatch3, clientPatch4, clientPatch5, clientPatch6];
2068
2463
 
2069
2464
  // src/kernel/client/activation.ts
2070
2465
  var ClientPatchActivation = class {
@@ -2087,18 +2482,18 @@ var ClientPatchActivation = class {
2087
2482
  };
2088
2483
 
2089
2484
  // src/kernel/client/config-card.tsx
2090
- var import_react11 = require("react");
2091
- var import_jsx_runtime10 = require("react/jsx-runtime");
2485
+ var import_react13 = require("react");
2486
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2092
2487
  function PatchConfigCard({ activation, initiallyOpen = false }) {
2093
- const scope = (0, import_react11.useSyncExternalStore)(
2488
+ const scope = (0, import_react13.useSyncExternalStore)(
2094
2489
  activation.subscribe,
2095
2490
  activation.getSettingsSnapshot,
2096
2491
  activation.getSettingsSnapshot
2097
2492
  );
2098
2493
  const settings = activation.getSnapshot();
2099
- const [open, setOpen] = (0, import_react11.useState)(initiallyOpen);
2100
- const [busy, setBusy] = (0, import_react11.useState)(/* @__PURE__ */ new Set());
2101
- const [error, setError] = (0, import_react11.useState)(null);
2494
+ const [open, setOpen] = (0, import_react13.useState)(initiallyOpen);
2495
+ const [busy, setBusy] = (0, import_react13.useState)(/* @__PURE__ */ new Set());
2496
+ const [error, setError] = (0, import_react13.useState)(null);
2102
2497
  if (scope.status === "unavailable") return null;
2103
2498
  const update = async (id, enabled) => {
2104
2499
  setBusy((current) => /* @__PURE__ */ new Set([...current, id]));
@@ -2115,9 +2510,9 @@ function PatchConfigCard({ activation, initiallyOpen = false }) {
2115
2510
  });
2116
2511
  }
2117
2512
  };
2118
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("li", { className: `dshmore-config-card${open ? " dshmore-config-card-open" : ""}`, children: [
2119
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("style", { children: styles }),
2120
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2513
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("li", { className: `dshmore-config-card${open ? " dshmore-config-card-open" : ""}`, children: [
2514
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("style", { children: styles }),
2515
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2121
2516
  "button",
2122
2517
  {
2123
2518
  type: "button",
@@ -2128,23 +2523,23 @@ function PatchConfigCard({ activation, initiallyOpen = false }) {
2128
2523
  setOpen((current) => !current);
2129
2524
  },
2130
2525
  children: [
2131
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "dshmore-config-heading-copy", children: [
2132
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { children: "DSH More" }),
2133
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "\u52A8\u6001\u5F00\u542F\u6216\u5173\u95ED\u72EC\u7ACB\u8865\u4E01\uFF0C\u9ED8\u8BA4\u5168\u90E8\u5F00\u542F\u3002" })
2526
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "dshmore-config-heading-copy", children: [
2527
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { children: "DSH More" }),
2528
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u52A8\u6001\u5F00\u542F\u6216\u5173\u95ED\u72EC\u7ACB\u8865\u4E01\uFF0C\u9ED8\u8BA4\u5168\u90E8\u5F00\u542F\u3002" })
2134
2529
  ] }),
2135
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconChevronDownOutline14, { size: 14, className: `dshmore-config-chevron${open ? " dshmore-config-chevron-open" : ""}` })
2530
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconChevronDownOutline14, { size: 14, className: `dshmore-config-chevron${open ? " dshmore-config-chevron-open" : ""}` })
2136
2531
  ]
2137
2532
  }
2138
2533
  ),
2139
- open && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dshmore-config-body", children: [
2140
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "dshmore-config-list", children: PATCH_CATALOG.map((patch) => {
2534
+ open && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dshmore-config-body", children: [
2535
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dshmore-config-list", children: PATCH_CATALOG.map((patch) => {
2141
2536
  const waiting = busy.has(patch.id);
2142
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "dshmore-config-row", children: [
2143
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "dshmore-config-copy", children: [
2144
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { children: patch.name }),
2145
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: patch.description })
2537
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "dshmore-config-row", children: [
2538
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "dshmore-config-copy", children: [
2539
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { children: patch.name }),
2540
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: patch.description })
2146
2541
  ] }),
2147
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2542
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2148
2543
  "input",
2149
2544
  {
2150
2545
  type: "checkbox",
@@ -2159,9 +2554,9 @@ function PatchConfigCard({ activation, initiallyOpen = false }) {
2159
2554
  )
2160
2555
  ] }, patch.id);
2161
2556
  }) }),
2162
- scope.status === "loading" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "dshmore-config-note", children: "\u6B63\u5728\u8BFB\u53D6\u63D2\u4EF6\u914D\u7F6E\u2026" }),
2163
- scope.status === "ready" && !scope.writable && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "dshmore-config-note", children: "\u5F53\u524D Settings \u5B58\u50A8\u4E3A\u53EA\u8BFB\u3002" }),
2164
- error !== null && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "dshmore-config-error", children: error })
2557
+ scope.status === "loading" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "dshmore-config-note", children: "\u6B63\u5728\u8BFB\u53D6\u63D2\u4EF6\u914D\u7F6E\u2026" }),
2558
+ scope.status === "ready" && !scope.writable && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "dshmore-config-note", children: "\u5F53\u524D Settings \u5B58\u50A8\u4E3A\u53EA\u8BFB\u3002" }),
2559
+ error !== null && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "dshmore-config-error", children: error })
2165
2560
  ] })
2166
2561
  ] });
2167
2562
  }
@@ -2172,21 +2567,21 @@ function installPatchConfigCard(ctx, activation) {
2172
2567
  id: PATCH_SETTINGS_NAMESPACE,
2173
2568
  order: 90,
2174
2569
  label: "DSH More"
2175
- }, () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("ul", { style: { listStyle: "none", padding: 0, margin: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PatchConfigCard, { activation, initiallyOpen: true }) })));
2570
+ }, () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", { style: { listStyle: "none", padding: 0, margin: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PatchConfigCard, { activation, initiallyOpen: true }) })));
2176
2571
  return;
2177
2572
  }
2178
2573
  ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
2179
2574
  name: "settings.plugin.item",
2180
2575
  key: PATCH_SETTINGS_NAMESPACE,
2181
2576
  priority: 90
2182
- }, () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PatchConfigCard, { activation })));
2577
+ }, () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PatchConfigCard, { activation })));
2183
2578
  }
2184
2579
 
2185
2580
  // src/kernel/message-visibility.ts
2186
2581
  var MESSAGE_VISIBILITY_PROJECTION_KEY = "dshMoreMessageDelete";
2187
2582
 
2188
2583
  // src/platform/dsh/client/message-targets.tsx
2189
- var import_react12 = require("react");
2584
+ var import_react14 = require("react");
2190
2585
 
2191
2586
  // src/platform/dsh/client/message-content.ts
2192
2587
  function contentText(content) {
@@ -2324,17 +2719,17 @@ function trajectorySourceSeq(row) {
2324
2719
  return Number.isSafeInteger(seq) && seq >= 0 ? seq : void 0;
2325
2720
  }
2326
2721
  function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = true) {
2327
- const selector = (0, import_react12.useMemo)(() => createMessageSurfaceSelector(active), [active, props.sessionId]);
2722
+ const selector = (0, import_react14.useMemo)(() => createMessageSurfaceSelector(active), [active, props.sessionId]);
2328
2723
  const surface = props.useChat(selector);
2329
- const surfaceRef = (0, import_react12.useRef)(surface);
2330
- const hiddenSeqsRef = (0, import_react12.useRef)(hiddenSeqs);
2331
- const hiddenTrajectoryKeysRef = (0, import_react12.useRef)(hiddenTrajectoryKeys);
2724
+ const surfaceRef = (0, import_react14.useRef)(surface);
2725
+ const hiddenSeqsRef = (0, import_react14.useRef)(hiddenSeqs);
2726
+ const hiddenTrajectoryKeysRef = (0, import_react14.useRef)(hiddenTrajectoryKeys);
2332
2727
  surfaceRef.current = surface;
2333
2728
  hiddenSeqsRef.current = hiddenSeqs;
2334
2729
  hiddenTrajectoryKeysRef.current = hiddenTrajectoryKeys;
2335
- const [targets, setTargets] = (0, import_react12.useState)([]);
2336
- const requestFullScanRef = (0, import_react12.useRef)(null);
2337
- (0, import_react12.useLayoutEffect)(() => {
2730
+ const [targets, setTargets] = (0, import_react14.useState)([]);
2731
+ const requestFullScanRef = (0, import_react14.useRef)(null);
2732
+ (0, import_react14.useLayoutEffect)(() => {
2338
2733
  if (!active) {
2339
2734
  setTargets((current) => current.length === 0 ? current : []);
2340
2735
  return;
@@ -2458,21 +2853,21 @@ function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = tru
2458
2853
  for (const host of document.querySelectorAll("[data-dshmore-message-actions]")) host.remove();
2459
2854
  };
2460
2855
  }, [active, props.sessionId]);
2461
- (0, import_react12.useLayoutEffect)(() => {
2856
+ (0, import_react14.useLayoutEffect)(() => {
2462
2857
  requestFullScanRef.current?.();
2463
2858
  }, [surface, hiddenSeqs, hiddenTrajectoryKeys]);
2464
2859
  return targets;
2465
2860
  }
2466
2861
 
2467
2862
  // src/client/index.tsx
2468
- var import_jsx_runtime11 = require("react/jsx-runtime");
2863
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2469
2864
  var inject = ["slots", "sessions", "workspaces"];
2470
2865
  function MessageActionPatchController({ patch, props, targets, enabled }) {
2471
2866
  const actions = patch.useActions(props, enabled);
2472
2867
  const style = { "--dshmore-action-order": patch.order };
2473
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2868
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
2474
2869
  enabled && targets.map((target) => (0, import_react_dom.createPortal)(
2475
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "dshmore-action-contribution", style, children: actions.renderAction(target) }),
2870
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dshmore-action-contribution", style, children: actions.renderAction(target) }),
2476
2871
  target.host,
2477
2872
  `${patch.id}:${target.key}`
2478
2873
  )),
@@ -2480,15 +2875,15 @@ function MessageActionPatchController({ patch, props, targets, enabled }) {
2480
2875
  ] });
2481
2876
  }
2482
2877
  function MessageActionsController(props) {
2483
- const settings = (0, import_react13.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
2878
+ const settings = (0, import_react15.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
2484
2879
  const projected = props.useProjection(MESSAGE_VISIBILITY_PROJECTION_KEY);
2485
- const hiddenSeqs = (0, import_react13.useMemo)(() => new Set(projected?.deletedSeqs ?? []), [projected]);
2486
- const hiddenTrajectoryKeys = (0, import_react13.useMemo)(() => new Set(projected?.hiddenTrajectoryKeys ?? []), [projected]);
2880
+ const hiddenSeqs = (0, import_react15.useMemo)(() => new Set(projected?.deletedSeqs ?? []), [projected]);
2881
+ const hiddenTrajectoryKeys = (0, import_react15.useMemo)(() => new Set(projected?.hiddenTrajectoryKeys ?? []), [projected]);
2487
2882
  const messageActionsEnabled = MESSAGE_ACTION_PATCHES.some((patch) => settings[patch.id]);
2488
2883
  const targets = useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, messageActionsEnabled);
2489
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2490
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("style", { children: styles }),
2491
- MESSAGE_ACTION_PATCHES.map((patch) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2884
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
2885
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("style", { children: styles }),
2886
+ MESSAGE_ACTION_PATCHES.map((patch) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2492
2887
  MessageActionPatchController,
2493
2888
  {
2494
2889
  patch,
@@ -2514,7 +2909,7 @@ function install(ctx) {
2514
2909
  name: "conversation.session.header.utilities",
2515
2910
  id: `${PLUGIN_NAME}-message-actions`,
2516
2911
  order: 90
2517
- }, (props) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MessageActionsController, { ...props, ctx, activation })));
2912
+ }, (props) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MessageActionsController, { ...props, ctx, activation })));
2518
2913
  for (const patch of CLIENT_PATCHES) patch.install(ctx, activation);
2519
2914
  }
2520
2915
  return module.exports; } });