dsh-more 0.0.9 → 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.
Files changed (32) hide show
  1. package/CONTRIBUTING.md +13 -0
  2. package/README.md +4 -2
  3. package/README.zh-CN.md +5 -2
  4. package/cordis.patch.yml +2 -0
  5. package/dist/client.js +783 -311
  6. package/dist/index.js +323 -14
  7. package/dist/session-groups.js +17 -0
  8. package/dist/types/generated/host-settings-schema.d.ts +2 -0
  9. package/dist/types/generated/patch-catalog.d.ts +8 -0
  10. package/dist/types/index.d.ts +2 -1
  11. package/dist/types/kernel/client/config-card.d.ts +1 -3
  12. package/dist/types/kernel/host/activation.d.ts +1 -0
  13. package/dist/types/kernel/host/patch.d.ts +2 -0
  14. package/dist/types/kernel/host/settings.d.ts +7 -1
  15. package/dist/types/patches/fast-mode/client/index.d.ts +19 -0
  16. package/dist/types/patches/fast-mode/client/styles.d.ts +1 -0
  17. package/dist/types/patches/fast-mode/host/index.d.ts +26 -0
  18. package/dist/types/patches/fast-mode/shared.d.ts +17 -0
  19. package/dist/types/patches/projectless-tasks/client/adapter.d.ts +2 -3
  20. package/dist/types/patches/projectless-tasks/client/create-task.d.ts +2 -2
  21. package/dist/types/patches/projectless-tasks/client/groups.d.ts +1 -1
  22. package/dist/types/patches/projectless-tasks/client/new-session.d.ts +2 -1
  23. package/dist/types/patches/projectless-tasks/host/settings.d.ts +6 -0
  24. package/dist/types/platform/dsh/client/icons.d.ts +7 -0
  25. package/dist/types/platform/dsh/client/runtime.d.ts +17 -2
  26. package/dist/types/platform/dsh/client/session-menu.d.ts +10 -0
  27. package/dist/types/platform/dsh/client/settings.d.ts +6 -0
  28. package/dist/types/platform/dsh/host/settings.d.ts +13 -0
  29. package/dist/types/platform/dsh/identity.d.ts +1 -1
  30. package/docs/desktop-compatibility.md +76 -0
  31. package/dsh.plugin.json +1 -1
  32. package/package.json +33 -27
package/dist/client.js CHANGED
@@ -1,8 +1,10 @@
1
1
  window.__ModuleLoader__.load({ id: "dsh-more", factory: (require) => { var module = { exports: {} }; var exports = module.exports;
2
2
  "use strict";
3
+ var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
6
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
9
  var __export = (target, all) => {
8
10
  for (var name in all)
@@ -16,6 +18,14 @@ var __copyProps = (to, from, except, desc) => {
16
18
  }
17
19
  return to;
18
20
  };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
19
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
30
 
21
31
  // src/client/index.tsx
@@ -25,7 +35,7 @@ __export(index_exports, {
25
35
  inject: () => inject
26
36
  });
27
37
  module.exports = __toCommonJS(index_exports);
28
- var import_react12 = require("react");
38
+ var import_react15 = require("react");
29
39
  var import_react_dom = require("react-dom");
30
40
 
31
41
  // src/generated/patch-catalog.ts
@@ -35,6 +45,7 @@ var PATCH_CATALOG = [
35
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" },
36
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" },
37
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" },
38
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" },
39
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" }
40
51
  ];
@@ -44,6 +55,7 @@ var DEFAULT_PATCH_SETTINGS = {
44
55
  "session-delete": true,
45
56
  "conversation-markdown-export": true,
46
57
  "model-capabilities": true,
58
+ "fast-mode": true,
47
59
  "session-auto-title": true,
48
60
  "projectless-tasks": true
49
61
  };
@@ -60,12 +72,29 @@ function decodePatchSettings(value) {
60
72
  }
61
73
 
62
74
  // src/patches/message-edit/client/index.tsx
63
- var import_react = require("react");
75
+ var import_react2 = require("react");
64
76
  var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
65
77
 
78
+ // src/platform/dsh/client/icons.tsx
79
+ var import_react = require("react");
80
+ var primitives = __toESM(require("@deepseek-ai/dsh-client-ui-primitives"), 1);
81
+ function compatibleIcon(current, legacy) {
82
+ return function CompatibleIcon(props) {
83
+ const name = Object.hasOwn(primitives, current) ? current : legacy;
84
+ const icon = Reflect.get(primitives, name);
85
+ if (typeof icon !== "function") throw new TypeError(`DSH icon is unavailable: ${current}`);
86
+ return (0, import_react.createElement)(icon, props);
87
+ };
88
+ }
89
+ var IconEditOutline16 = compatibleIcon("IconEditOutlineRegular", "IconEditOutline16");
90
+ var IconTrashOutline16 = compatibleIcon("IconTrashOutlineRegular", "IconTrashOutline16");
91
+ var IconDownloadOutline16 = compatibleIcon("IconDownloadOutlineRegular", "IconDownloadOutline16");
92
+ var IconWarningOutline16 = compatibleIcon("IconWarningOutlineRegular", "IconWarningOutline16");
93
+ var IconChevronDownOutline14 = compatibleIcon("IconChevronDownOutlineRegular", "IconChevronDownOutline14");
94
+
66
95
  // src/platform/dsh/identity.ts
67
96
  var PLUGIN_NAME = "dsh-more";
68
- var PLUGIN_API_PREFIX = `/${PLUGIN_NAME}/api`;
97
+ var PLUGIN_API_PREFIX = `/api/${PLUGIN_NAME}`;
69
98
  var PLUGIN_MUTATION_HEADER = "x-dsh-more";
70
99
  var PATCH_SETTINGS_NAMESPACE = PLUGIN_NAME;
71
100
 
@@ -81,7 +110,9 @@ var DshMoreApiError = class extends Error {
81
110
  async function requestPatch(patchId, action, payload) {
82
111
  let response;
83
112
  try {
84
- 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), {
85
116
  method: "POST",
86
117
  headers: {
87
118
  "content-type": "application/json",
@@ -119,6 +150,39 @@ function apiErrorText(error) {
119
150
  return String(error);
120
151
  }
121
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
+
122
186
  // src/platform/dsh/client/session-sync.ts
123
187
  var INCREMENTAL_SYNC_GRACE_MS = 180;
124
188
  function openSessionWithoutGap(sessions, sessionId) {
@@ -196,7 +260,7 @@ async function settleSessionRemoval(sessions, workspaces, sessionId) {
196
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");
197
261
  }
198
262
  function adjacentVisibleSession(sessions, workspaces, deletingSessionId) {
199
- if (sessions.current !== deletingSessionId) return void 0;
263
+ if (currentSessionId(sessions) !== deletingSessionId) return void 0;
200
264
  const archived = new Set(workspaces.archivedSessionIds);
201
265
  const deletingIndex = sessions.ids.indexOf(deletingSessionId);
202
266
  for (let index = deletingIndex + 1; index < sessions.ids.length; index += 1) {
@@ -220,11 +284,11 @@ var api = {
220
284
  commit: (payload) => callPatchApi(MESSAGE_EDIT_PATCH_ID, "commit", payload)
221
285
  };
222
286
  function useMessageActions(props, enabled) {
223
- const [target, setTarget] = (0, import_react.useState)(null);
224
- const [text, setText] = (0, import_react.useState)("");
225
- const [busy, setBusy] = (0, import_react.useState)(false);
226
- const [error, setError] = (0, import_react.useState)(null);
227
- (0, import_react.useEffect)(() => {
287
+ const [target, setTarget] = (0, import_react2.useState)(null);
288
+ const [text, setText] = (0, import_react2.useState)("");
289
+ const [busy, setBusy] = (0, import_react2.useState)(false);
290
+ const [error, setError] = (0, import_react2.useState)(null);
291
+ (0, import_react2.useEffect)(() => {
228
292
  if (enabled) return;
229
293
  setTarget(null);
230
294
  setError(null);
@@ -238,7 +302,7 @@ function useMessageActions(props, enabled) {
238
302
  if (target === null) return;
239
303
  setBusy(true);
240
304
  setError(null);
241
- const sessions = props.ctx.sessions;
305
+ const sessions = clientSessions(props.ctx);
242
306
  let handoff;
243
307
  try {
244
308
  const preview = await api.preview({ sessionId: props.sessionId, targetSeq: target.seq, text });
@@ -259,7 +323,7 @@ function useMessageActions(props, enabled) {
259
323
  const sessionList = sessions.list.getSnapshot();
260
324
  const sourceAvailable = sessionList.byId[sourceId] !== void 0;
261
325
  const sourceArchived = props.ctx.workspaces.list.getSnapshot().archivedSessionIds.includes(sourceId);
262
- if (sourceAvailable && !sourceArchived && sessionList.current !== sourceId) openSessionWithoutGap(sessions, sourceId);
326
+ if (sourceAvailable && !sourceArchived && currentSessionId(sessionList) !== sourceId) openSessionWithoutGap(sessions, sourceId);
263
327
  setError(apiErrorText(caught));
264
328
  } finally {
265
329
  setBusy(false);
@@ -269,7 +333,7 @@ function useMessageActions(props, enabled) {
269
333
  renderAction: (candidate) => enabled && candidate.kind === "user" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tooltip, { label: "\u7F16\u8F91\u5E76\u4ECE\u8FD9\u91CC\u91CD\u65B0\u5F00\u59CB", side: "bottom", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "dshmore-inline-button", "aria-label": "\u7F16\u8F91\u5E76\u4ECE\u8FD9\u91CC\u91CD\u65B0\u5F00\u59CB", onClick: (event) => {
270
334
  event.stopPropagation();
271
335
  open(candidate);
272
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconEditOutline16, { size: 16 }) }) }) : null,
336
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconEditOutline16, { size: 16 }) }) }) : null,
273
337
  overlay: enabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
274
338
  import_dsh_client_ui_primitives.Modal,
275
339
  {
@@ -306,7 +370,7 @@ function useMessageActions(props, enabled) {
306
370
  }
307
371
 
308
372
  // src/patches/message-delete/client/index.tsx
309
- var import_react2 = require("react");
373
+ var import_react3 = require("react");
310
374
  var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
311
375
 
312
376
  // src/patches/message-delete/shared.ts
@@ -319,17 +383,17 @@ var api2 = {
319
383
  commit: (payload) => callPatchApi(MESSAGE_DELETE_PATCH_ID, "commit", payload)
320
384
  };
321
385
  function useMessageActions2(props, enabled) {
322
- const [target, setTarget] = (0, import_react2.useState)(null);
323
- const [preview, setPreview] = (0, import_react2.useState)(null);
324
- const [busy, setBusy] = (0, import_react2.useState)(false);
325
- const [error, setError] = (0, import_react2.useState)(null);
326
- (0, import_react2.useEffect)(() => {
386
+ const [target, setTarget] = (0, import_react3.useState)(null);
387
+ const [preview, setPreview] = (0, import_react3.useState)(null);
388
+ const [busy, setBusy] = (0, import_react3.useState)(false);
389
+ const [error, setError] = (0, import_react3.useState)(null);
390
+ (0, import_react3.useEffect)(() => {
327
391
  if (enabled) return;
328
392
  setTarget(null);
329
393
  setPreview(null);
330
394
  setError(null);
331
395
  }, [enabled]);
332
- const open = (0, import_react2.useCallback)(async (next) => {
396
+ const open = (0, import_react3.useCallback)(async (next) => {
333
397
  setTarget(next);
334
398
  setPreview(null);
335
399
  setError(null);
@@ -346,7 +410,7 @@ function useMessageActions2(props, enabled) {
346
410
  if (target === null || preview === null) return;
347
411
  setBusy(true);
348
412
  setError(null);
349
- const sessions = props.ctx.sessions;
413
+ const sessions = clientSessions(props.ctx);
350
414
  const continuationSessionId = preview.continuationSessionId;
351
415
  const handoff = followSessionHandoff(sessions, continuationSessionId);
352
416
  try {
@@ -365,7 +429,7 @@ function useMessageActions2(props, enabled) {
365
429
  const sessionList = sessions.list.getSnapshot();
366
430
  const sourceAvailable = sessionList.byId[sourceId] !== void 0;
367
431
  const sourceArchived = props.ctx.workspaces.list.getSnapshot().archivedSessionIds.includes(sourceId);
368
- if (sourceAvailable && !sourceArchived && sessionList.current !== sourceId) openSessionWithoutGap(sessions, sourceId);
432
+ if (sourceAvailable && !sourceArchived && currentSessionId(sessionList) !== sourceId) openSessionWithoutGap(sessions, sourceId);
369
433
  setPreview(null);
370
434
  setError(apiErrorText(caught));
371
435
  } finally {
@@ -376,7 +440,7 @@ function useMessageActions2(props, enabled) {
376
440
  renderAction: (candidate) => enabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Tooltip, { label: "\u5220\u9664\u8FD9\u6761\u6D88\u606F", side: "bottom", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dshmore-inline-button", "aria-label": "\u5220\u9664\u8FD9\u6761\u6D88\u606F", onClick: (event) => {
377
441
  event.stopPropagation();
378
442
  void open(candidate);
379
- }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.IconTrashOutline16, { size: 16 }) }) }) : null,
443
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconTrashOutline16, { size: 16 }) }) }) : null,
380
444
  overlay: enabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
381
445
  import_dsh_client_ui_primitives2.Modal,
382
446
  {
@@ -404,7 +468,7 @@ function useMessageActions2(props, enabled) {
404
468
  }
405
469
 
406
470
  // src/patches/session-delete/client/index.tsx
407
- var import_react3 = require("react");
471
+ var import_react5 = require("react");
408
472
  var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
409
473
 
410
474
  // src/platform/dsh/client/styles.ts
@@ -447,11 +511,39 @@ var styles = `
447
511
  @media (prefers-reduced-motion: no-preference) { .dshmore-config-chevron { transition: transform .16s; } }
448
512
  `;
449
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
+
450
542
  // src/patches/session-delete/shared.ts
451
543
  var SESSION_DELETE_PATCH_ID = "session-delete";
452
544
 
453
545
  // src/patches/session-delete/client/index.tsx
454
- var import_jsx_runtime3 = require("react/jsx-runtime");
546
+ var import_jsx_runtime4 = require("react/jsx-runtime");
455
547
  var DELETE_MENU_ATTRIBUTE = "data-dshmore-session-delete";
456
548
  var DELETE_SOURCE_ATTRIBUTE = "data-dshmore-session-delete-source";
457
549
  var sessionDeleteStyles = `
@@ -546,32 +638,48 @@ function installSessionDeleteMenuItems(onDelete) {
546
638
  };
547
639
  }
548
640
  function SessionDeleteController(props) {
549
- const settings = (0, import_react3.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
641
+ const settings = (0, import_react5.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
550
642
  const enabled = settings[SESSION_DELETE_PATCH_ID];
551
- const [pending, setPending] = (0, import_react3.useState)(null);
552
- const pendingRef = (0, import_react3.useRef)(null);
553
- const deleteIntentRef = (0, import_react3.useRef)(false);
554
- const [busy, setBusy] = (0, import_react3.useState)(false);
555
- const [error, setError] = (0, import_react3.useState)(null);
556
- (0, import_react3.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)(() => {
557
649
  if (!enabled) return;
558
650
  const workspaces = props.ctx.workspaces;
559
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
+ };
560
676
  const mutable = workspaces;
561
677
  const original = mutable.archiveSession;
562
678
  mutable.archiveSession = (sessionId) => {
563
679
  if (!deleteIntentRef.current) return original.call(mutable, sessionId);
564
680
  deleteIntentRef.current = false;
565
681
  return new Promise((resolve) => {
566
- const request = {
567
- sessionId,
568
- title: sessions.list.getSnapshot().byId[sessionId]?.displayTitle ?? String(sessionId),
569
- resolve
570
- };
571
- pendingRef.current?.resolve();
572
- pendingRef.current = request;
573
- setError(null);
574
- setPending(request);
682
+ requestDelete(sessionId, resolve);
575
683
  });
576
684
  };
577
685
  const removeDeleteItems = installSessionDeleteMenuItems((archiveButton) => {
@@ -600,15 +708,15 @@ function SessionDeleteController(props) {
600
708
  if (pending === null) return;
601
709
  setBusy(true);
602
710
  setError(null);
603
- const sessions = props.ctx.sessions;
711
+ const sessions = clientSessions(props.ctx);
604
712
  const workspaces = props.ctx.workspaces;
605
713
  const fallbackSessionId = adjacentVisibleSession(
606
714
  sessions.list.getSnapshot(),
607
715
  workspaces.list.getSnapshot(),
608
716
  pending.sessionId
609
717
  );
610
- if (fallbackSessionId !== void 0) openSessionWithoutGap(sessions, fallbackSessionId);
611
718
  try {
719
+ if (fallbackSessionId !== void 0) openSessionWithoutGap(sessions, fallbackSessionId);
612
720
  await callPatchApi(SESSION_DELETE_PATCH_ID, "commit", {
613
721
  sessionId: pending.sessionId,
614
722
  confirmSessionId: pending.sessionId
@@ -618,6 +726,8 @@ function SessionDeleteController(props) {
618
726
  pendingRef.current = null;
619
727
  setPending(null);
620
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);
621
731
  setError(apiErrorText(caught));
622
732
  } finally {
623
733
  setBusy(false);
@@ -625,9 +735,9 @@ function SessionDeleteController(props) {
625
735
  };
626
736
  const title = pending?.title ?? "";
627
737
  if (!enabled) return null;
628
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
629
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: styles + sessionDeleteStyles }),
630
- /* @__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)(
631
741
  import_dsh_client_ui_primitives3.Modal,
632
742
  {
633
743
  open: pending !== null,
@@ -635,17 +745,17 @@ function SessionDeleteController(props) {
635
745
  title: "\u6C38\u4E45\u5220\u9664\u4F1A\u8BDD\uFF1F",
636
746
  closeLabel: "\u5173\u95ED",
637
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",
638
- footer: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
639
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", disabled: busy, onClick: close, children: "\u53D6\u6D88" }),
640
- /* @__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" })
641
751
  ] }),
642
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dshmore-dialog-body", children: [
643
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dshmore-message-preview", children: title }),
644
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dshmore-danger", children: [
645
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.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 }),
646
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"
647
757
  ] }),
648
- 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 })
649
759
  ] })
650
760
  }
651
761
  )
@@ -658,12 +768,12 @@ var clientPatch = {
658
768
  name: "shell.overlay",
659
769
  id: `${PLUGIN_NAME}-${SESSION_DELETE_PATCH_ID}`,
660
770
  order: 90
661
- }, (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SessionDeleteController, { ...props, ctx, activation })));
771
+ }, (props) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SessionDeleteController, { ...props, ctx, activation })));
662
772
  }
663
773
  };
664
774
 
665
775
  // src/patches/conversation-markdown-export/client/index.tsx
666
- var import_react4 = require("react");
776
+ var import_react6 = require("react");
667
777
  var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
668
778
 
669
779
  // src/patches/conversation-markdown-export/shared.ts
@@ -680,7 +790,7 @@ function markdownFilename(title, sessionId) {
680
790
 
681
791
  // src/patches/conversation-markdown-export/client/menu.ts
682
792
  var MENU_ITEM_ATTRIBUTE = "data-dshmore-markdown-export";
683
- var MORE_BUTTON_SELECTOR = 'button[class*="_moreButton"][aria-haspopup="menu"]';
793
+ var MORE_BUTTON_SELECTOR = 'button[aria-haspopup="menu"]';
684
794
  function installMarkdownExportMenu(fallback, options) {
685
795
  const header = fallback.closest("header");
686
796
  if (header === null) return () => {
@@ -696,14 +806,18 @@ function installMarkdownExportMenu(fallback, options) {
696
806
  const sync = () => {
697
807
  frame = null;
698
808
  const trigger = Array.from(header.querySelectorAll(MORE_BUTTON_SELECTOR)).find((button2) => ["\u66F4\u591A\u64CD\u4F5C", "More actions"].includes(button2.getAttribute("aria-label") ?? ""));
699
- fallback.hidden = trigger !== void 0;
700
- 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;
701
812
  const text = download?.textContent?.trim();
702
813
  if (download === void 0 || download === null || !["\u4E0B\u8F7D Session \u65E5\u5FD7", "Download session log"].includes(text ?? "")) {
703
814
  removeItem();
704
815
  return;
705
816
  }
706
- if (source === download && item?.isConnected === true) return;
817
+ if (source === download && item?.isConnected === true) {
818
+ fallback.hidden = true;
819
+ return;
820
+ }
707
821
  removeItem();
708
822
  const wrapper = download.parentElement;
709
823
  if (wrapper === null || wrapper.getAttribute("role") === "menu") return;
@@ -730,6 +844,7 @@ function installMarkdownExportMenu(fallback, options) {
730
844
  source = download;
731
845
  item = clone;
732
846
  wrapper.after(clone);
847
+ fallback.hidden = true;
733
848
  };
734
849
  sync();
735
850
  const observer = new MutationObserver(() => {
@@ -751,7 +866,7 @@ function installMarkdownExportMenu(fallback, options) {
751
866
  }
752
867
 
753
868
  // src/patches/conversation-markdown-export/client/index.tsx
754
- var import_jsx_runtime4 = require("react/jsx-runtime");
869
+ var import_jsx_runtime5 = require("react/jsx-runtime");
755
870
  var exportStyles = `
756
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; }
757
872
  .dshmore-markdown-export-button[hidden] { display: none; }
@@ -773,17 +888,17 @@ function saveMarkdown(filename, markdown) {
773
888
  }, 0);
774
889
  }
775
890
  function ConversationMarkdownExportButton(props) {
776
- const settings = (0, import_react4.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
891
+ const settings = (0, import_react6.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
777
892
  const enabled = settings[CONVERSATION_MARKDOWN_EXPORT_PATCH_ID];
778
893
  const title = props.useSessions((state) => state.byId[props.sessionId]?.displayTitle ?? String(props.sessionId));
779
- const [busy, setBusy] = (0, import_react4.useState)(false);
780
- const [error, setError] = (0, import_react4.useState)(null);
781
- const button = (0, import_react4.useRef)(null);
782
- const inFlight = (0, import_react4.useRef)(false);
783
- const generation = (0, import_react4.useRef)(0);
784
- const activeSession = (0, import_react4.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);
785
900
  activeSession.current = enabled ? String(props.sessionId) : null;
786
- (0, import_react4.useEffect)(() => {
901
+ (0, import_react6.useEffect)(() => {
787
902
  generation.current += 1;
788
903
  inFlight.current = false;
789
904
  setBusy(false);
@@ -816,16 +931,16 @@ function ConversationMarkdownExportButton(props) {
816
931
  }
817
932
  }
818
933
  };
819
- (0, import_react4.useEffect)(() => {
934
+ (0, import_react6.useEffect)(() => {
820
935
  if (!enabled || button.current === null) return;
821
936
  return installMarkdownExportMenu(button.current, { busy, download: () => {
822
937
  void download();
823
938
  } });
824
939
  }, [enabled, props.sessionId, title, busy]);
825
940
  if (!enabled) return null;
826
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
827
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: exportStyles }),
828
- /* @__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)(
829
944
  "button",
830
945
  {
831
946
  ref: button,
@@ -838,12 +953,12 @@ function ConversationMarkdownExportButton(props) {
838
953
  void download();
839
954
  },
840
955
  children: [
841
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: busy ? "\u6B63\u5728\u5BFC\u51FA\u2026" : "\u5BFC\u51FA Markdown" }),
842
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.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 })
843
958
  ]
844
959
  }
845
960
  ),
846
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
961
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
847
962
  import_dsh_client_ui_primitives4.Modal,
848
963
  {
849
964
  open: error !== null,
@@ -851,7 +966,7 @@ function ConversationMarkdownExportButton(props) {
851
966
  title: "\u65E0\u6CD5\u5BFC\u51FA\u804A\u5929\u8BB0\u5F55",
852
967
  closeLabel: "\u5173\u95ED",
853
968
  description: error ?? "",
854
- 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" })
855
970
  }
856
971
  )
857
972
  ] });
@@ -863,12 +978,12 @@ var clientPatch2 = {
863
978
  name: "conversation.session.header.utilities",
864
979
  id: `${PLUGIN_NAME}-${CONVERSATION_MARKDOWN_EXPORT_PATCH_ID}`,
865
980
  order: 100
866
- }, (props) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ConversationMarkdownExportButton, { ...props, activation })));
981
+ }, (props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ConversationMarkdownExportButton, { ...props, activation })));
867
982
  }
868
983
  };
869
984
 
870
985
  // src/patches/model-capabilities/client/index.tsx
871
- var import_react6 = require("react");
986
+ var import_react8 = require("react");
872
987
 
873
988
  // src/patches/model-capabilities/shared.ts
874
989
  var MODEL_CAPABILITIES_PATCH_ID = "model-capabilities";
@@ -910,10 +1025,49 @@ async function readCapabilities() {
910
1025
  return decodeSnapshot(await callPatchApi(MODEL_CAPABILITIES_PATCH_ID, "read", {}));
911
1026
  }
912
1027
 
1028
+ // src/platform/dsh/client/settings.ts
1029
+ function isConfigForm(value) {
1030
+ return typeof value === "object" && value !== null && ["getSnapshot", "subscribe", "set", "unset", "mutate"].every((key) => typeof Reflect.get(value, key) === "function");
1031
+ }
1032
+ function bindSettings(ctx, spec) {
1033
+ const service = typeof ctx.get === "function" ? ctx.get("configForms") : void 0;
1034
+ if (typeof service !== "object" || service === null) return ctx.settingsScope.bind(spec);
1035
+ const get = Reflect.get(service, "get");
1036
+ const form = typeof get === "function" ? get.call(service, spec.namespace) : void 0;
1037
+ if (!isConfigForm(form)) throw new TypeError("DSH configuration form API is unavailable");
1038
+ let previous;
1039
+ let snapshot;
1040
+ let accepted;
1041
+ const write = async (operation) => {
1042
+ if (!await operation) throw new Error("\u4FDD\u5B58\u672A\u88AB\u63A5\u53D7\uFF0C\u8BF7\u5237\u65B0\u914D\u7F6E\u540E\u91CD\u8BD5\u3002");
1043
+ };
1044
+ return {
1045
+ getSnapshot: () => {
1046
+ const current = form.getSnapshot();
1047
+ if (current === previous && snapshot !== void 0) return snapshot;
1048
+ const decoded = spec.decode === void 0 ? current.value : spec.decode(current.value);
1049
+ if (decoded !== void 0) accepted = decoded;
1050
+ previous = current;
1051
+ snapshot = { ...current, value: accepted };
1052
+ return snapshot;
1053
+ },
1054
+ subscribe: (listener) => form.subscribe(listener),
1055
+ set: (...args) => write(form.set(...args)),
1056
+ unset: (...args) => write(form.unset(...args)),
1057
+ mutate: (...args) => write(form.mutate(...args))
1058
+ };
1059
+ }
1060
+ function withSettings(ctx, install2) {
1061
+ ctx.inject(["configForms"], install2);
1062
+ ctx.inject(["settingsScope"], (scope) => {
1063
+ if (scope.get("configForms") === void 0) install2(scope);
1064
+ });
1065
+ }
1066
+
913
1067
  // src/patches/model-capabilities/client/editor.tsx
914
- var import_react5 = require("react");
1068
+ var import_react7 = require("react");
915
1069
  var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
916
- var import_jsx_runtime5 = require("react/jsx-runtime");
1070
+ var import_jsx_runtime6 = require("react/jsx-runtime");
917
1071
  var LEVEL_LABELS = {
918
1072
  off: "\u4E0D\u601D\u8003",
919
1073
  minimal: "\u6781\u7B80",
@@ -967,49 +1121,49 @@ function summaryLabel(capabilities) {
967
1121
  return `${vision} \xB7 ${thinking}`;
968
1122
  }
969
1123
  function CapabilitiesEditorBody({ draft, setDraft, disabled, api: api3 }) {
970
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dshmore-capabilities-fields", children: [
971
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "dshmore-capabilities-field", children: [
972
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u8BC6\u56FE\u80FD\u529B" }),
973
- /* @__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) => {
974
1128
  const vision = event.currentTarget.value;
975
1129
  setDraft((current) => ({ ...current, vision }));
976
1130
  }, children: [
977
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "default", children: "\u6CBF\u7528\u9ED8\u8BA4" }),
978
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "yes", children: "\u652F\u6301\u8BC6\u56FE" }),
979
- /* @__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" })
980
1134
  ] })
981
1135
  ] }),
982
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "dshmore-capabilities-field", children: [
983
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u601D\u8003\u7C7B\u578B" }),
984
- /* @__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) => {
985
1139
  const thinking = event.currentTarget.value;
986
1140
  setDraft((current) => ({ ...current, thinking }));
987
1141
  }, children: [
988
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "default", children: "\u6CBF\u7528\u9ED8\u8BA4" }),
989
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "disabled", children: "\u4E0D\u652F\u6301\u601D\u8003" }),
990
- /* @__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" })
991
1145
  ] })
992
1146
  ] }),
993
- draft.thinking === "custom" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("fieldset", { className: "dshmore-capabilities-levels", disabled, children: [
994
- /* @__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" }),
995
1149
  (api3 === "deepseek-native" ? DEEPSEEK_THINKING_LEVELS : THINKING_LEVELS).map((level) => {
996
1150
  const entry = draft.levels[level];
997
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dshmore-capabilities-level", children: [
998
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { children: [
999
- /* @__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) => {
1000
1154
  const enabled = event.currentTarget.checked;
1001
1155
  setDraft((current) => ({ ...current, levels: {
1002
1156
  ...current.levels,
1003
1157
  [level]: { wire: level === "off" ? "" : level, ...current.levels[level], enabled }
1004
1158
  } }));
1005
1159
  } }),
1006
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
1160
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
1007
1161
  LEVEL_LABELS[level],
1008
1162
  " ",
1009
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("small", { children: level })
1163
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("small", { children: level })
1010
1164
  ] })
1011
1165
  ] }),
1012
- entry?.enabled && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1166
+ entry?.enabled && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1013
1167
  "input",
1014
1168
  {
1015
1169
  type: "text",
@@ -1029,41 +1183,41 @@ function CapabilitiesEditorBody({ draft, setDraft, disabled, api: api3 }) {
1029
1183
  ] }, level);
1030
1184
  })
1031
1185
  ] }),
1032
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("details", { className: "dshmore-capabilities-advanced", children: [
1033
- /* @__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: [
1034
1188
  "\u601D\u8003\u53C2\u6570\u683C\u5F0F",
1035
1189
  draft.thinkingFormat === "default" ? "" : ` \xB7 ${draft.thinkingFormat}`
1036
1190
  ] }),
1037
- api3 === null || api3 === "openai-completions" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "dshmore-capabilities-field", children: [
1038
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u63A5\u53E3\u63A5\u53D7\u7684\u683C\u5F0F" }),
1039
- /* @__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) => {
1040
1194
  const thinkingFormat = event.currentTarget.value;
1041
1195
  setDraft((current) => ({ ...current, thinkingFormat }));
1042
1196
  }, children: [
1043
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "default", children: "\u6CBF\u7528\u9ED8\u8BA4\uFF08\u63D0\u4F9B\u65B9 / \u81EA\u52A8\u8BC6\u522B\uFF09" }),
1044
- 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))
1045
1199
  ] }),
1046
- /* @__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" })
1047
- ] }) : /* @__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" })
1048
1202
  ] }),
1049
- /* @__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" })
1050
1204
  ] });
1051
1205
  }
1052
1206
  function CapabilitiesEditorModal({ provider, modelId, namespace, onClose, onSaved }) {
1053
- const [snapshot, setSnapshot] = (0, import_react5.useState)(null);
1054
- const [draft, setDraft] = (0, import_react5.useState)(null);
1055
- const [error, setError] = (0, import_react5.useState)(null);
1056
- const [busy, setBusy] = (0, import_react5.useState)(false);
1057
- const [attempt, setAttempt] = (0, import_react5.useState)(0);
1058
- const saving = (0, import_react5.useRef)(false);
1059
- const mounted = (0, import_react5.useRef)(false);
1060
- (0, import_react5.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)(() => {
1061
1215
  mounted.current = true;
1062
1216
  return () => {
1063
1217
  mounted.current = false;
1064
1218
  };
1065
1219
  }, []);
1066
- (0, import_react5.useEffect)(() => {
1220
+ (0, import_react7.useEffect)(() => {
1067
1221
  let cancelled = false;
1068
1222
  setError(null);
1069
1223
  void readCapabilities().then((next) => {
@@ -1114,7 +1268,7 @@ function CapabilitiesEditorModal({ provider, modelId, namespace, onClose, onSave
1114
1268
  if (mounted.current) setBusy(false);
1115
1269
  }
1116
1270
  };
1117
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1271
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1118
1272
  import_dsh_client_ui_primitives5.Modal,
1119
1273
  {
1120
1274
  open: true,
@@ -1124,9 +1278,9 @@ function CapabilitiesEditorModal({ provider, modelId, namespace, onClose, onSave
1124
1278
  title: `\u6A21\u578B\u80FD\u529B \xB7 ${modelId}`,
1125
1279
  closeLabel: "\u5173\u95ED",
1126
1280
  description: `\u63D0\u4F9B\u65B9 ${provider}`,
1127
- footer: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1128
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", disabled: busy, onClick: onClose, children: "\u53D6\u6D88" }),
1129
- /* @__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)(
1130
1284
  import_dsh_client_ui_primitives5.Button,
1131
1285
  {
1132
1286
  variant: "primary",
@@ -1138,10 +1292,10 @@ function CapabilitiesEditorModal({ provider, modelId, namespace, onClose, onSave
1138
1292
  }
1139
1293
  )
1140
1294
  ] }),
1141
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dshmore-capabilities-dialog", children: [
1142
- 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" }),
1143
- 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" }),
1144
- 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)(
1145
1299
  CapabilitiesEditorBody,
1146
1300
  {
1147
1301
  draft,
@@ -1152,9 +1306,9 @@ function CapabilitiesEditorModal({ provider, modelId, namespace, onClose, onSave
1152
1306
  api: row.api
1153
1307
  }
1154
1308
  ),
1155
- snapshot !== null && !snapshot.writable && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "dshmore-capabilities-note", children: "\u5F53\u524D\u914D\u7F6E\u4E3A\u53EA\u8BFB\u3002" }),
1156
- error !== null && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { role: "alert", className: "dshmore-capabilities-error", children: error }),
1157
- 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: () => {
1158
1312
  setAttempt((value) => value + 1);
1159
1313
  }, children: "\u91CD\u8BD5" })
1160
1314
  ] })
@@ -1211,18 +1365,18 @@ var capabilitiesStyles = `
1211
1365
  `;
1212
1366
 
1213
1367
  // src/patches/model-capabilities/client/index.tsx
1214
- var import_jsx_runtime6 = require("react/jsx-runtime");
1368
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1215
1369
  var BUTTON_ATTR = "data-dshmore-model-capabilities";
1216
1370
  function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1217
- const settings = (0, import_react6.useSyncExternalStore)(activation.subscribe, activation.getSnapshot, activation.getSnapshot);
1371
+ const settings = (0, import_react8.useSyncExternalStore)(activation.subscribe, activation.getSnapshot, activation.getSnapshot);
1218
1372
  const enabled = settings[MODEL_CAPABILITIES_PATCH_ID];
1219
- const scopeSnapshot = (0, import_react6.useSyncExternalStore)(scope.subscribe, scope.getSnapshot, scope.getSnapshot);
1220
- const deepseekSnapshot = (0, import_react6.useSyncExternalStore)(deepseekScope.subscribe, deepseekScope.getSnapshot, deepseekScope.getSnapshot);
1221
- const [editing, setEditing] = (0, import_react6.useState)(null);
1222
- const [data, setData] = (0, import_react6.useState)(null);
1223
- const dataRef = (0, import_react6.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);
1224
1378
  dataRef.current = data;
1225
- (0, import_react6.useEffect)(() => {
1379
+ (0, import_react8.useEffect)(() => {
1226
1380
  let cancelled = false;
1227
1381
  if (!enabled) {
1228
1382
  setEditing(null);
@@ -1238,7 +1392,7 @@ function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1238
1392
  cancelled = true;
1239
1393
  };
1240
1394
  }, [enabled, scopeSnapshot, deepseekSnapshot]);
1241
- const syncButtons = (0, import_react6.useCallback)(() => {
1395
+ const syncButtons = (0, import_react8.useCallback)(() => {
1242
1396
  if (!enabled) return;
1243
1397
  const active = /* @__PURE__ */ new Set();
1244
1398
  for (const entry of findModelEntries()) {
@@ -1270,7 +1424,7 @@ function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1270
1424
  if (button.parentElement === null || !active.has(button.parentElement)) button.remove();
1271
1425
  });
1272
1426
  }, [enabled]);
1273
- (0, import_react6.useEffect)(() => {
1427
+ (0, import_react8.useEffect)(() => {
1274
1428
  if (!enabled) return;
1275
1429
  let frame = null;
1276
1430
  const schedule = () => {
@@ -1293,13 +1447,13 @@ function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1293
1447
  document.querySelectorAll(`[${BUTTON_ATTR}]`).forEach((element) => element.remove());
1294
1448
  };
1295
1449
  }, [enabled, syncButtons]);
1296
- (0, import_react6.useEffect)(() => {
1450
+ (0, import_react8.useEffect)(() => {
1297
1451
  if (enabled) syncButtons();
1298
1452
  }, [enabled, syncButtons, data]);
1299
1453
  if (!enabled) return null;
1300
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1301
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: capabilitiesStyles }),
1302
- 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)(
1303
1457
  CapabilitiesEditorModal,
1304
1458
  {
1305
1459
  ...editing,
@@ -1316,7 +1470,7 @@ var clientPatch3 = {
1316
1470
  id: MODEL_CAPABILITIES_PATCH_ID,
1317
1471
  install: (ctx, activation) => {
1318
1472
  const bindScope = (namespace) => {
1319
- const scope = ctx.settingsScope.bind({ namespace });
1473
+ const scope = bindSettings(ctx, { namespace });
1320
1474
  return {
1321
1475
  getSnapshot: scope.getSnapshot.bind(scope),
1322
1476
  subscribe: scope.subscribe.bind(scope),
@@ -1331,7 +1485,253 @@ var clientPatch3 = {
1331
1485
  name: "shell.overlay",
1332
1486
  id: `${PLUGIN_NAME}-${MODEL_CAPABILITIES_PATCH_ID}`,
1333
1487
  order: 90
1334
- }, () => /* @__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
+ }
1335
1735
  }
1336
1736
  };
1337
1737
 
@@ -1339,7 +1739,7 @@ var clientPatch3 = {
1339
1739
  var SESSION_AUTO_TITLE_PATCH_ID = "session-auto-title";
1340
1740
 
1341
1741
  // src/patches/session-auto-title/client/index.ts
1342
- var clientPatch4 = {
1742
+ var clientPatch5 = {
1343
1743
  id: SESSION_AUTO_TITLE_PATCH_ID,
1344
1744
  install: () => {
1345
1745
  }
@@ -1349,13 +1749,14 @@ var clientPatch4 = {
1349
1749
  var PROJECTLESS_TASKS_PATCH_ID = "projectless-tasks";
1350
1750
 
1351
1751
  // src/patches/projectless-tasks/client/adapter.tsx
1352
- var import_react8 = require("react");
1752
+ var import_react11 = require("react");
1353
1753
 
1354
1754
  // src/patches/projectless-tasks/client/create-task.ts
1355
1755
  function createTaskStarter(sessions) {
1356
1756
  let pendingId;
1357
1757
  let flight;
1358
1758
  let disposed = false;
1759
+ let reference;
1359
1760
  return {
1360
1761
  start(beforeOpen) {
1361
1762
  if (disposed) return Promise.reject(new Error("\u72EC\u7ACB\u4EFB\u52A1\u8865\u4E01\u5DF2\u5173\u95ED\u3002"));
@@ -1370,8 +1771,21 @@ function createTaskStarter(sessions) {
1370
1771
  if (disposed) return;
1371
1772
  const id = await sessions.create({ sessionId, cwd: location.cwd });
1372
1773
  if (id !== sessionId) throw new Error("\u521B\u5EFA\u7ED3\u679C\u4E0E\u72EC\u7ACB\u4EFB\u52A1\u6807\u8BC6\u4E0D\u4E00\u81F4\u3002");
1373
- if (!disposed && beforeOpen?.(id) !== false) sessions.open(id);
1374
- 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
+ }
1375
1789
  })().finally(() => {
1376
1790
  flight = void 0;
1377
1791
  });
@@ -1379,6 +1793,8 @@ function createTaskStarter(sessions) {
1379
1793
  },
1380
1794
  dispose() {
1381
1795
  disposed = true;
1796
+ reference?.release();
1797
+ reference = void 0;
1382
1798
  }
1383
1799
  };
1384
1800
  }
@@ -1415,7 +1831,7 @@ function transferBeforeOpen(ctx, sourceId, targetId) {
1415
1831
  }
1416
1832
  const sessions = value;
1417
1833
  const list = sessions.list.getSnapshot();
1418
- if (list.current !== sourceId) return false;
1834
+ if (currentSessionId(list) !== sourceId) return false;
1419
1835
  if (sourceId === void 0 || sourceId === targetId) return true;
1420
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");
1421
1837
  const source = sessions.scope(sourceId);
@@ -1431,8 +1847,8 @@ function transferBeforeOpen(ctx, sourceId, targetId) {
1431
1847
  }
1432
1848
 
1433
1849
  // src/patches/projectless-tasks/client/picker.tsx
1434
- var import_react7 = require("react");
1435
- var import_jsx_runtime7 = require("react/jsx-runtime");
1850
+ var import_react10 = require("react");
1851
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1436
1852
  var INDEPENDENT_CHOICE_ID = "::dsh-more-independent-task";
1437
1853
  var INDEPENDENT_CHOICE = {
1438
1854
  workspaceId: INDEPENDENT_CHOICE_ID,
@@ -1442,7 +1858,7 @@ var INDEPENDENT_CHOICE = {
1442
1858
  createdAt: "",
1443
1859
  updatedAt: ""
1444
1860
  };
1445
- var ChoiceContext = (0, import_react7.createContext)(void 0);
1861
+ var ChoiceContext = (0, import_react10.createContext)(void 0);
1446
1862
  function withIndependentChoice(snapshot) {
1447
1863
  return { ...snapshot, items: [INDEPENDENT_CHOICE, ...snapshot.items] };
1448
1864
  }
@@ -1463,7 +1879,7 @@ function labelIndependentChip(anchor) {
1463
1879
  };
1464
1880
  }
1465
1881
  function WorkspaceChoice({ owner, state, error, children }) {
1466
- (0, import_react7.useLayoutEffect)(() => {
1882
+ (0, import_react10.useLayoutEffect)(() => {
1467
1883
  const anchor = owner.anchorRef?.current;
1468
1884
  if (!state.independent || owner.selectedId !== void 0 || anchor === void 0 || anchor === null) return;
1469
1885
  return labelIndependentChip(anchor);
@@ -1472,9 +1888,9 @@ function WorkspaceChoice({ owner, state, error, children }) {
1472
1888
  owner.onClose();
1473
1889
  state.chooseIndependent();
1474
1890
  };
1475
- 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: [
1476
1892
  children,
1477
- owner.selectedId !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1893
+ owner.selectedId !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1478
1894
  "button",
1479
1895
  {
1480
1896
  type: "button",
@@ -1486,9 +1902,9 @@ function WorkspaceChoice({ owner, state, error, children }) {
1486
1902
  children: "\xD7"
1487
1903
  }
1488
1904
  ),
1489
- state.busy && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dshmore-workspace-status", role: "status", children: "\u5207\u6362\u4E2D\u2026" }),
1490
- error !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dshmore-workspace-error", role: "alert", children: error }),
1491
- /* @__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: `
1492
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; }
1493
1909
  .dshmore-workspace-clear:hover { color:var(--dsw-alias-label-primary); background:var(--dsw-alias-interactive-bg-hover); }
1494
1910
  .dshmore-workspace-clear:disabled { opacity:.45; cursor:wait; }
@@ -1499,11 +1915,11 @@ function WorkspaceChoice({ owner, state, error, children }) {
1499
1915
  }
1500
1916
  function extendWorkspacePicker(original) {
1501
1917
  return function ProjectlessPicker(props) {
1502
- const choice = (0, import_react7.useContext)(ChoiceContext);
1918
+ const choice = (0, import_react10.useContext)(ChoiceContext);
1503
1919
  const snapshot = props.useWorkspaces((value) => value);
1504
- const display = (0, import_react7.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]);
1505
1921
  const useWorkspaces = (select) => select(display);
1506
- return (0, import_react7.createElement)(original, {
1922
+ return (0, import_react10.createElement)(original, {
1507
1923
  ...props,
1508
1924
  useWorkspaces,
1509
1925
  open: props.open && !choice?.busy,
@@ -1542,20 +1958,13 @@ function installPickerAdapter(ctx) {
1542
1958
  }
1543
1959
 
1544
1960
  // src/patches/projectless-tasks/client/adapter.tsx
1545
- var import_jsx_runtime8 = require("react/jsx-runtime");
1961
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1546
1962
  function isComposerOwner(owner) {
1547
1963
  return "variant" in owner && (owner.variant === "hero" || owner.variant === "composer");
1548
1964
  }
1549
1965
  function isWorkspaceOwner(owner) {
1550
1966
  return "open" in owner && typeof owner.open === "boolean" && "onPick" in owner && typeof owner.onPick === "function" && "onClose" in owner && typeof owner.onClose === "function";
1551
1967
  }
1552
- function clientSessionActions(ctx) {
1553
- const sessions = ctx.sessions;
1554
- if (typeof sessions !== "object" || sessions === null || !("create" in sessions) || !("open" in sessions) || typeof sessions.create !== "function" || typeof sessions.open !== "function") {
1555
- throw new Error("\u5F53\u524D DSH \u7248\u672C\u4E0D\u652F\u6301\u72EC\u7ACB\u4EFB\u52A1\uFF0C\u8BF7\u68C0\u67E5\u4F1A\u8BDD\u63A5\u53E3\u3002");
1556
- }
1557
- return sessions;
1558
- }
1559
1968
  function unlockComposer(owner, independent, block) {
1560
1969
  if (!independent || owner.disabled !== true || owner.onRequestWorkspace === void 0) return owner;
1561
1970
  const { disabled: _disabled, onRequestWorkspace: _request, workspacePickerOpen: _picker, placeholder: _placeholder, ...rest } = owner;
@@ -1578,54 +1987,11 @@ function installConversationAdapter(ctx, activation, name = "main.conversation")
1578
1987
  };
1579
1988
  const sync = () => {
1580
1989
  for (const entry of ctx.slots.entries(slot)) {
1581
- let ProjectlessConversation2 = function(props) {
1582
- const active = (0, import_react8.useSyncExternalStore)(subscribeLifetime, () => live);
1583
- const settings = (0, import_react8.useSyncExternalStore)(activation.subscribe, activation.getSnapshot);
1584
- const workspace = props.useWorkspaces((snapshot) => snapshot);
1585
- const cwd = props.useSessions((snapshot) => props.sessionId === void 0 ? void 0 : snapshot.byId[props.sessionId]?.cwd);
1586
- const session = props.useSession((snapshot) => snapshot);
1587
- const block = props.useComposerBlock((value) => value);
1588
- const enabled = active && settings[PROJECTLESS_TASKS_PATCH_ID];
1589
- const starter = (0, import_react8.useRef)();
1590
- const [busy, setBusy] = (0, import_react8.useState)(false);
1591
- const [error, setError] = (0, import_react8.useState)();
1592
- (0, import_react8.useEffect)(() => {
1593
- if (!enabled) return;
1594
- setBusy(false);
1595
- setError(void 0);
1596
- return () => {
1597
- starter.current?.dispose();
1598
- starter.current = void 0;
1599
- };
1600
- }, [enabled]);
1601
- 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));
1602
- const chooseIndependent = () => {
1603
- if (!enabled || busy || independent) return;
1604
- const operation = starter.current ??= createTaskStarter(clientSessionActions(ctx));
1605
- setBusy(true);
1606
- setError(void 0);
1607
- void operation.start((id) => transferBeforeOpen(ctx, props.sessionId, id)).catch((reason) => {
1608
- if (starter.current === operation) setError(apiErrorText(reason));
1609
- }).finally(() => {
1610
- if (starter.current === operation) setBusy(false);
1611
- });
1612
- };
1613
- const renderSlot = (name2, owner, options) => {
1614
- if (name2 === "conversation.composer.bar" && isComposerOwner(owner)) {
1615
- return props.renderSlot("conversation.composer.bar", unlockComposer(owner, independent, block), options);
1616
- }
1617
- if (enabled && name2 === "conversation.hero.workspace" && isWorkspaceOwner(owner)) {
1618
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(WorkspaceChoice, { owner, state: { independent, busy, chooseIndependent }, error, children: props.renderSlot("conversation.hero.workspace", owner, options) });
1619
- }
1620
- return props.renderSlot(name2, owner, options);
1621
- };
1622
- return (0, import_react8.createElement)(original, { ...props, renderSlot });
1623
- };
1624
- var ProjectlessConversation = ProjectlessConversation2;
1625
1990
  if (wrapped.has(entry) || entry.children?.["conversation.composer.bar"] === void 0 || typeof entry.component !== "function") continue;
1626
1991
  const original = entry.component;
1627
- wrapped.set(entry, { original, component: ProjectlessConversation2 });
1628
- entry.component = ProjectlessConversation2;
1992
+ const ProjectlessConversation = wrapConversation(ctx, activation, original, subscribeLifetime, () => live);
1993
+ wrapped.set(entry, { original, component: ProjectlessConversation });
1994
+ entry.component = ProjectlessConversation;
1629
1995
  }
1630
1996
  };
1631
1997
  const unsubscribe = ctx.slots.subscribe(slot, sync);
@@ -1643,14 +2009,95 @@ function installConversationAdapter(ctx, activation, name = "main.conversation")
1643
2009
  fallback();
1644
2010
  };
1645
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
+ }
1646
2092
 
1647
2093
  // src/patches/projectless-tasks/client/new-session.ts
1648
2094
  function newSessionTarget(list, workspaces, explicit) {
1649
2095
  if (explicit !== void 0) return { kind: "workspace", workspaceId: explicit };
1650
- if (list.current === void 0) return { kind: "native" };
2096
+ const current = currentSessionId(list);
2097
+ if (current === void 0) return { kind: "native" };
1651
2098
  if (list.phase !== "ready" || workspaces.phase !== "ready") return { kind: "pending" };
1652
2099
  const visited = /* @__PURE__ */ new Set();
1653
- let id = list.current;
2100
+ let id = current;
1654
2101
  while (id !== void 0 && !visited.has(id)) {
1655
2102
  visited.add(id);
1656
2103
  const workspace = workspaces.items.find((item) => item.sessionIds.includes(id));
@@ -1661,7 +2108,7 @@ function newSessionTarget(list, workspaces, explicit) {
1661
2108
  id = summary.parentId;
1662
2109
  continue;
1663
2110
  }
1664
- 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" };
1665
2112
  }
1666
2113
  return { kind: "pending" };
1667
2114
  }
@@ -1694,7 +2141,8 @@ function bindNewSessionNavigation({ navigation, sessions, workspaces, activation
1694
2141
  }
1695
2142
  if (target.kind === "pending") {
1696
2143
  cancel();
1697
- 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"));
1698
2146
  return;
1699
2147
  }
1700
2148
  if (attempt?.sourceId !== target.sourceId) {
@@ -1708,7 +2156,7 @@ function bindNewSessionNavigation({ navigation, sessions, workspaces, activation
1708
2156
  const destination = newSessionTarget(sessions.list.getSnapshot(), workspaces.list.getSnapshot());
1709
2157
  return destination.kind === "independent" && destination.sourceId === current.sourceId;
1710
2158
  }).catch((error) => {
1711
- if (active && attempt === current && sessions.list.getSnapshot().current === current.sourceId) {
2159
+ if (active && attempt === current && currentSessionId(sessions.list.getSnapshot()) === current.sourceId) {
1712
2160
  reportError(current.sourceId, error);
1713
2161
  }
1714
2162
  }).finally(() => {
@@ -1740,17 +2188,17 @@ function bindNewSessionNavigation({ navigation, sessions, workspaces, activation
1740
2188
  function installNewSessionNavigation(ctx, activation) {
1741
2189
  const navigation = ctx.get("uiWorkspace");
1742
2190
  const sessions = ctx.sessions;
1743
- 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") {
1744
2192
  throw new Error("\u5F53\u524D DSH \u7248\u672C\u4E0D\u652F\u6301\u8DDF\u968F\u4F1A\u8BDD\u6765\u6E90\u65B0\u5EFA\u4EFB\u52A1\u3002");
1745
2193
  }
1746
- const clientSessions = sessions;
2194
+ const clientSessions2 = sessions;
1747
2195
  return bindNewSessionNavigation({
1748
2196
  navigation,
1749
- sessions: clientSessions,
2197
+ sessions: { ...clientSessionActions(ctx), list: clientSessions2.list },
1750
2198
  workspaces: ctx.workspaces,
1751
2199
  activation,
1752
2200
  reportError: (sourceId, error) => {
1753
- const scope = clientSessions.scope(sourceId);
2201
+ const scope = clientSessions2.scope(sourceId);
1754
2202
  const message = `\u65B0\u5EFA\u4F1A\u8BDD\u5931\u8D25\uFF1A${apiErrorText(error)}`;
1755
2203
  if (scope !== void 0) ctx.conversation.input.for(scope).notify("error", message);
1756
2204
  else ctx.logger.warn(message);
@@ -1759,7 +2207,7 @@ function installNewSessionNavigation(ctx, activation) {
1759
2207
  }
1760
2208
 
1761
2209
  // src/patches/projectless-tasks/client/groups.tsx
1762
- var import_react9 = require("react");
2210
+ var import_react12 = require("react");
1763
2211
  var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
1764
2212
 
1765
2213
  // src/patches/projectless-tasks/groups.ts
@@ -1824,7 +2272,7 @@ function installMoveMenu(onMove) {
1824
2272
  }
1825
2273
 
1826
2274
  // src/patches/projectless-tasks/client/groups.tsx
1827
- var import_jsx_runtime9 = require("react/jsx-runtime");
2275
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1828
2276
  function projectSessionGroups(workspaces, sessions, groups) {
1829
2277
  const owned = new Set(workspaces.items.flatMap((item) => item.sessionIds));
1830
2278
  const items = workspaces.items.map((workspace) => {
@@ -1836,35 +2284,49 @@ function projectSessionGroups(workspaces, sessions, groups) {
1836
2284
  var SIDEBAR_SLOT = "sidebar.workspaces";
1837
2285
  var ALWAYS_LIVE = { subscribe: () => () => {
1838
2286
  }, getSnapshot: () => true };
1839
- function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LIVE) {
2287
+ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LIVE, ctx) {
1840
2288
  return function GroupedSidebar(props) {
1841
- const settings = (0, import_react9.useSyncExternalStore)(activation.subscribe, activation.getSnapshot);
1842
- const binding = (0, import_react9.useMemo)(() => ({ subscribe: (listener) => source.subscribe(listener), getSnapshot: () => source.getSnapshot() }), []);
1843
- const saved = (0, import_react9.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);
1844
2292
  const native = props.useWorkspaces((value) => value);
1845
2293
  const sessions = props.useSessions((value) => value);
1846
- const active = (0, import_react9.useSyncExternalStore)(lifetime.subscribe, lifetime.getSnapshot);
2294
+ const active = (0, import_react12.useSyncExternalStore)(lifetime.subscribe, lifetime.getSnapshot);
1847
2295
  const enabled = active && settings[PROJECTLESS_TASKS_PATCH_ID];
1848
2296
  const groups = saved.value ?? EMPTY_GROUPS;
1849
- const display = (0, import_react9.useMemo)(() => enabled ? projectSessionGroups(native, sessions, groups) : native, [enabled, native, sessions, groups]);
1850
- const [pending, setPending] = (0, import_react9.useState)();
1851
- const [destination, setDestination] = (0, import_react9.useState)("");
1852
- const [busy, setBusy] = (0, import_react9.useState)(false);
1853
- const [error, setError] = (0, import_react9.useState)();
1854
- const intent = (0, import_react9.useRef)(false);
1855
- const inFlight = (0, import_react9.useRef)(false);
1856
- const live = (0, import_react9.useRef)(true);
1857
- (0, import_react9.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)(() => {
1858
2313
  live.current = true;
1859
2314
  return () => {
1860
2315
  live.current = false;
1861
2316
  };
1862
2317
  }, []);
1863
- (0, import_react9.useEffect)(() => {
2318
+ (0, import_react12.useEffect)(() => {
1864
2319
  if (!enabled) {
1865
2320
  setPending(void 0);
1866
2321
  return;
1867
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;
1868
2330
  return installMoveMenu((archive) => {
1869
2331
  intent.current = true;
1870
2332
  try {
@@ -1877,9 +2339,7 @@ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LI
1877
2339
  const archiveSession = (id) => {
1878
2340
  if (!intent.current) return props.archiveSession(id);
1879
2341
  intent.current = false;
1880
- setPending(id);
1881
- setDestination(groups.assignments[id] ?? "");
1882
- setError(void 0);
2342
+ requestMove(id);
1883
2343
  return Promise.resolve();
1884
2344
  };
1885
2345
  const useWorkspaces = (select) => select(display);
@@ -1905,9 +2365,9 @@ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LI
1905
2365
  const subagent = pending !== void 0 && sessions.byId[pending]?.origin === "subagent";
1906
2366
  const selectedMissing = destination !== "" && !native.items.some((item) => item.workspaceId === destination);
1907
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;
1908
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1909
- (0, import_react9.createElement)(original, { ...props, useWorkspaces, archiveSession }),
1910
- 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)(
1911
2371
  import_dsh_client_ui_primitives6.Modal,
1912
2372
  {
1913
2373
  open: pending !== void 0,
@@ -1915,15 +2375,15 @@ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LI
1915
2375
  title: "\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A",
1916
2376
  closeLabel: "\u5173\u95ED",
1917
2377
  description: "\u4FDD\u7559\u4F1A\u8BDD\u5386\u53F2\u548C\u539F\u5DE5\u4F5C\u76EE\u5F55\uFF0C\u4EC5\u8C03\u6574\u5217\u8868\u5F52\u5C5E\u3002",
1918
- footer: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1919
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_dsh_client_ui_primitives6.Button, { variant: "ghost", disabled: busy, onClick: close, children: "\u53D6\u6D88" }),
1920
- /* @__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" })
1921
2381
  ] }),
1922
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "grid", gap: 12 }, children: [
1923
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { children: pending === void 0 ? "" : sessions.byId[pending]?.displayTitle ?? pending }),
1924
- /* @__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: [
1925
2385
  "\u76EE\u6807\u5DE5\u4F5C\u533A",
1926
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2386
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1927
2387
  "select",
1928
2388
  {
1929
2389
  "aria-label": "\u76EE\u6807\u5DE5\u4F5C\u533A",
@@ -1932,13 +2392,13 @@ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LI
1932
2392
  onChange: (event) => setDestination(event.target.value),
1933
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)" },
1934
2394
  children: [
1935
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: "", children: "\u672A\u5206\u7EC4" }),
1936
- 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))
1937
2397
  ]
1938
2398
  }
1939
2399
  )
1940
2400
  ] }),
1941
- (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 })
1942
2402
  ] })
1943
2403
  }
1944
2404
  )
@@ -1946,7 +2406,7 @@ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LI
1946
2406
  };
1947
2407
  }
1948
2408
  function installSessionGrouping(ctx, activation) {
1949
- const source = ctx.settingsScope.bind({ namespace: SESSION_GROUPS_NAMESPACE, decode: decodeSessionGroups });
2409
+ const source = bindSettings(ctx, { namespace: SESSION_GROUPS_NAMESPACE, decode: decodeSessionGroups });
1950
2410
  ctx.slots.inject(SIDEBAR_SLOT, () => {
1951
2411
  let live = true;
1952
2412
  const listeners = /* @__PURE__ */ new Set();
@@ -1961,7 +2421,7 @@ function installSessionGrouping(ctx, activation) {
1961
2421
  for (const entry of ctx.slots.entries(SIDEBAR_SLOT)) {
1962
2422
  if (wrapped.has(entry) || entry.children?.["sidebar.workspaces.directoryFlow"] === void 0 || typeof entry.component !== "function") continue;
1963
2423
  const original = entry.component;
1964
- const component = extendGroupedSidebar(original, activation, source, lifetime);
2424
+ const component = extendGroupedSidebar(original, activation, source, lifetime, ctx);
1965
2425
  wrapped.set(entry, { original, component });
1966
2426
  entry.component = component;
1967
2427
  }
@@ -1982,12 +2442,13 @@ function installSessionGrouping(ctx, activation) {
1982
2442
  }
1983
2443
 
1984
2444
  // src/patches/projectless-tasks/client/index.tsx
1985
- var clientPatch5 = {
2445
+ var clientPatch6 = {
1986
2446
  id: PROJECTLESS_TASKS_PATCH_ID,
1987
2447
  install: (ctx, activation) => {
1988
2448
  installSessionGrouping(ctx, activation);
1989
2449
  ctx.inject(["conversation", "uiWorkspace"], (scope) => {
1990
2450
  scope.effect(() => installNewSessionNavigation(scope, activation));
2451
+ scope.effect(() => installConversationFactoryAdapter(scope, activation));
1991
2452
  for (const name of CONVERSATION_SLOTS) {
1992
2453
  scope.slots.inject(conversationSlot(name), () => installConversationAdapter(scope, activation, name));
1993
2454
  }
@@ -1998,7 +2459,7 @@ var clientPatch5 = {
1998
2459
 
1999
2460
  // src/generated/client-registry.ts
2000
2461
  var MESSAGE_ACTION_PATCHES = [{ id: "message-edit", order: 100, useActions: useMessageActions }, { id: "message-delete", order: 200, useActions: useMessageActions2 }];
2001
- var CLIENT_PATCHES = [clientPatch, clientPatch2, clientPatch3, clientPatch4, clientPatch5];
2462
+ var CLIENT_PATCHES = [clientPatch, clientPatch2, clientPatch3, clientPatch4, clientPatch5, clientPatch6];
2002
2463
 
2003
2464
  // src/kernel/client/activation.ts
2004
2465
  var ClientPatchActivation = class {
@@ -2021,19 +2482,18 @@ var ClientPatchActivation = class {
2021
2482
  };
2022
2483
 
2023
2484
  // src/kernel/client/config-card.tsx
2024
- var import_react10 = require("react");
2025
- var import_dsh_client_ui_primitives7 = require("@deepseek-ai/dsh-client-ui-primitives");
2026
- var import_jsx_runtime10 = require("react/jsx-runtime");
2485
+ var import_react13 = require("react");
2486
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2027
2487
  function PatchConfigCard({ activation, initiallyOpen = false }) {
2028
- const scope = (0, import_react10.useSyncExternalStore)(
2488
+ const scope = (0, import_react13.useSyncExternalStore)(
2029
2489
  activation.subscribe,
2030
2490
  activation.getSettingsSnapshot,
2031
2491
  activation.getSettingsSnapshot
2032
2492
  );
2033
2493
  const settings = activation.getSnapshot();
2034
- const [open, setOpen] = (0, import_react10.useState)(initiallyOpen);
2035
- const [busy, setBusy] = (0, import_react10.useState)(/* @__PURE__ */ new Set());
2036
- const [error, setError] = (0, import_react10.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);
2037
2497
  if (scope.status === "unavailable") return null;
2038
2498
  const update = async (id, enabled) => {
2039
2499
  setBusy((current) => /* @__PURE__ */ new Set([...current, id]));
@@ -2050,9 +2510,9 @@ function PatchConfigCard({ activation, initiallyOpen = false }) {
2050
2510
  });
2051
2511
  }
2052
2512
  };
2053
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("li", { className: `dshmore-config-card${open ? " dshmore-config-card-open" : ""}`, children: [
2054
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("style", { children: styles }),
2055
- /* @__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)(
2056
2516
  "button",
2057
2517
  {
2058
2518
  type: "button",
@@ -2063,23 +2523,23 @@ function PatchConfigCard({ activation, initiallyOpen = false }) {
2063
2523
  setOpen((current) => !current);
2064
2524
  },
2065
2525
  children: [
2066
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "dshmore-config-heading-copy", children: [
2067
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { children: "DSH More" }),
2068
- /* @__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" })
2069
2529
  ] }),
2070
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_dsh_client_ui_primitives7.IconChevronDownOutline14, { 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" : ""}` })
2071
2531
  ]
2072
2532
  }
2073
2533
  ),
2074
- open && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dshmore-config-body", children: [
2075
- /* @__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) => {
2076
2536
  const waiting = busy.has(patch.id);
2077
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "dshmore-config-row", children: [
2078
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "dshmore-config-copy", children: [
2079
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { children: patch.name }),
2080
- /* @__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 })
2081
2541
  ] }),
2082
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2542
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2083
2543
  "input",
2084
2544
  {
2085
2545
  type: "checkbox",
@@ -2094,25 +2554,34 @@ function PatchConfigCard({ activation, initiallyOpen = false }) {
2094
2554
  )
2095
2555
  ] }, patch.id);
2096
2556
  }) }),
2097
- scope.status === "loading" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "dshmore-config-note", children: "\u6B63\u5728\u8BFB\u53D6\u63D2\u4EF6\u914D\u7F6E\u2026" }),
2098
- 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" }),
2099
- 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 })
2100
2560
  ] })
2101
2561
  ] });
2102
2562
  }
2103
2563
  function installPatchConfigCard(ctx, activation) {
2564
+ if (ctx.get("configForms") !== void 0) {
2565
+ ctx.slots.inject("settings.section", () => ctx.slots.register({
2566
+ name: "settings.section",
2567
+ id: PATCH_SETTINGS_NAMESPACE,
2568
+ order: 90,
2569
+ label: "DSH More"
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 }) })));
2571
+ return;
2572
+ }
2104
2573
  ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
2105
2574
  name: "settings.plugin.item",
2106
2575
  key: PATCH_SETTINGS_NAMESPACE,
2107
2576
  priority: 90
2108
- }, (props) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PatchConfigCard, { ...props, activation })));
2577
+ }, () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PatchConfigCard, { activation })));
2109
2578
  }
2110
2579
 
2111
2580
  // src/kernel/message-visibility.ts
2112
2581
  var MESSAGE_VISIBILITY_PROJECTION_KEY = "dshMoreMessageDelete";
2113
2582
 
2114
2583
  // src/platform/dsh/client/message-targets.tsx
2115
- var import_react11 = require("react");
2584
+ var import_react14 = require("react");
2116
2585
 
2117
2586
  // src/platform/dsh/client/message-content.ts
2118
2587
  function contentText(content) {
@@ -2250,17 +2719,17 @@ function trajectorySourceSeq(row) {
2250
2719
  return Number.isSafeInteger(seq) && seq >= 0 ? seq : void 0;
2251
2720
  }
2252
2721
  function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = true) {
2253
- const selector = (0, import_react11.useMemo)(() => createMessageSurfaceSelector(active), [active, props.sessionId]);
2722
+ const selector = (0, import_react14.useMemo)(() => createMessageSurfaceSelector(active), [active, props.sessionId]);
2254
2723
  const surface = props.useChat(selector);
2255
- const surfaceRef = (0, import_react11.useRef)(surface);
2256
- const hiddenSeqsRef = (0, import_react11.useRef)(hiddenSeqs);
2257
- const hiddenTrajectoryKeysRef = (0, import_react11.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);
2258
2727
  surfaceRef.current = surface;
2259
2728
  hiddenSeqsRef.current = hiddenSeqs;
2260
2729
  hiddenTrajectoryKeysRef.current = hiddenTrajectoryKeys;
2261
- const [targets, setTargets] = (0, import_react11.useState)([]);
2262
- const requestFullScanRef = (0, import_react11.useRef)(null);
2263
- (0, import_react11.useLayoutEffect)(() => {
2730
+ const [targets, setTargets] = (0, import_react14.useState)([]);
2731
+ const requestFullScanRef = (0, import_react14.useRef)(null);
2732
+ (0, import_react14.useLayoutEffect)(() => {
2264
2733
  if (!active) {
2265
2734
  setTargets((current) => current.length === 0 ? current : []);
2266
2735
  return;
@@ -2384,21 +2853,21 @@ function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = tru
2384
2853
  for (const host of document.querySelectorAll("[data-dshmore-message-actions]")) host.remove();
2385
2854
  };
2386
2855
  }, [active, props.sessionId]);
2387
- (0, import_react11.useLayoutEffect)(() => {
2856
+ (0, import_react14.useLayoutEffect)(() => {
2388
2857
  requestFullScanRef.current?.();
2389
2858
  }, [surface, hiddenSeqs, hiddenTrajectoryKeys]);
2390
2859
  return targets;
2391
2860
  }
2392
2861
 
2393
2862
  // src/client/index.tsx
2394
- var import_jsx_runtime11 = require("react/jsx-runtime");
2395
- var inject = ["slots", "sessions", "workspaces", "settingsScope"];
2863
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2864
+ var inject = ["slots", "sessions", "workspaces"];
2396
2865
  function MessageActionPatchController({ patch, props, targets, enabled }) {
2397
2866
  const actions = patch.useActions(props, enabled);
2398
2867
  const style = { "--dshmore-action-order": patch.order };
2399
- 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: [
2400
2869
  enabled && targets.map((target) => (0, import_react_dom.createPortal)(
2401
- /* @__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) }),
2402
2871
  target.host,
2403
2872
  `${patch.id}:${target.key}`
2404
2873
  )),
@@ -2406,15 +2875,15 @@ function MessageActionPatchController({ patch, props, targets, enabled }) {
2406
2875
  ] });
2407
2876
  }
2408
2877
  function MessageActionsController(props) {
2409
- const settings = (0, import_react12.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
2878
+ const settings = (0, import_react15.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
2410
2879
  const projected = props.useProjection(MESSAGE_VISIBILITY_PROJECTION_KEY);
2411
- const hiddenSeqs = (0, import_react12.useMemo)(() => new Set(projected?.deletedSeqs ?? []), [projected]);
2412
- const hiddenTrajectoryKeys = (0, import_react12.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]);
2413
2882
  const messageActionsEnabled = MESSAGE_ACTION_PATCHES.some((patch) => settings[patch.id]);
2414
2883
  const targets = useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, messageActionsEnabled);
2415
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2416
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("style", { children: styles }),
2417
- 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)(
2418
2887
  MessageActionPatchController,
2419
2888
  {
2420
2889
  patch,
@@ -2427,7 +2896,10 @@ function MessageActionsController(props) {
2427
2896
  ] });
2428
2897
  }
2429
2898
  function apply(ctx) {
2430
- const scope = ctx.settingsScope.bind({
2899
+ withSettings(ctx, install);
2900
+ }
2901
+ function install(ctx) {
2902
+ const scope = bindSettings(ctx, {
2431
2903
  namespace: PATCH_SETTINGS_NAMESPACE,
2432
2904
  decode: decodePatchSettings
2433
2905
  });
@@ -2437,7 +2909,7 @@ function apply(ctx) {
2437
2909
  name: "conversation.session.header.utilities",
2438
2910
  id: `${PLUGIN_NAME}-message-actions`,
2439
2911
  order: 90
2440
- }, (props) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MessageActionsController, { ...props, ctx, activation })));
2912
+ }, (props) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MessageActionsController, { ...props, ctx, activation })));
2441
2913
  for (const patch of CLIENT_PATCHES) patch.install(ctx, activation);
2442
2914
  }
2443
2915
  return module.exports; } });