dsh-more 0.0.8 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cordis.patch.yml CHANGED
@@ -1,4 +1,6 @@
1
1
  # Installed automatically as a DSH bundle layer.
2
2
  - insert:
3
+ - id: dsh-more-session-groups
4
+ name: dsh-more/session-groups
3
5
  - id: dsh-more
4
6
  name: dsh-more
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_react13 = require("react");
29
39
  var import_react_dom = require("react-dom");
30
40
 
31
41
  // src/generated/patch-catalog.ts
@@ -60,9 +70,26 @@ function decodePatchSettings(value) {
60
70
  }
61
71
 
62
72
  // src/patches/message-edit/client/index.tsx
63
- var import_react = require("react");
73
+ var import_react2 = require("react");
64
74
  var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
65
75
 
76
+ // src/platform/dsh/client/icons.tsx
77
+ var import_react = require("react");
78
+ var primitives = __toESM(require("@deepseek-ai/dsh-client-ui-primitives"), 1);
79
+ function compatibleIcon(current, legacy) {
80
+ return function CompatibleIcon(props) {
81
+ const name = Object.hasOwn(primitives, current) ? current : legacy;
82
+ const icon = Reflect.get(primitives, name);
83
+ if (typeof icon !== "function") throw new TypeError(`DSH icon is unavailable: ${current}`);
84
+ return (0, import_react.createElement)(icon, props);
85
+ };
86
+ }
87
+ var IconEditOutline16 = compatibleIcon("IconEditOutlineRegular", "IconEditOutline16");
88
+ var IconTrashOutline16 = compatibleIcon("IconTrashOutlineRegular", "IconTrashOutline16");
89
+ var IconDownloadOutline16 = compatibleIcon("IconDownloadOutlineRegular", "IconDownloadOutline16");
90
+ var IconWarningOutline16 = compatibleIcon("IconWarningOutlineRegular", "IconWarningOutline16");
91
+ var IconChevronDownOutline14 = compatibleIcon("IconChevronDownOutlineRegular", "IconChevronDownOutline14");
92
+
66
93
  // src/platform/dsh/identity.ts
67
94
  var PLUGIN_NAME = "dsh-more";
68
95
  var PLUGIN_API_PREFIX = `/${PLUGIN_NAME}/api`;
@@ -220,11 +247,11 @@ var api = {
220
247
  commit: (payload) => callPatchApi(MESSAGE_EDIT_PATCH_ID, "commit", payload)
221
248
  };
222
249
  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)(() => {
250
+ const [target, setTarget] = (0, import_react2.useState)(null);
251
+ const [text, setText] = (0, import_react2.useState)("");
252
+ const [busy, setBusy] = (0, import_react2.useState)(false);
253
+ const [error, setError] = (0, import_react2.useState)(null);
254
+ (0, import_react2.useEffect)(() => {
228
255
  if (enabled) return;
229
256
  setTarget(null);
230
257
  setError(null);
@@ -269,7 +296,7 @@ function useMessageActions(props, enabled) {
269
296
  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
297
  event.stopPropagation();
271
298
  open(candidate);
272
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconEditOutline16, { size: 16 }) }) }) : null,
299
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconEditOutline16, { size: 16 }) }) }) : null,
273
300
  overlay: enabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
274
301
  import_dsh_client_ui_primitives.Modal,
275
302
  {
@@ -306,7 +333,7 @@ function useMessageActions(props, enabled) {
306
333
  }
307
334
 
308
335
  // src/patches/message-delete/client/index.tsx
309
- var import_react2 = require("react");
336
+ var import_react3 = require("react");
310
337
  var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
311
338
 
312
339
  // src/patches/message-delete/shared.ts
@@ -319,17 +346,17 @@ var api2 = {
319
346
  commit: (payload) => callPatchApi(MESSAGE_DELETE_PATCH_ID, "commit", payload)
320
347
  };
321
348
  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)(() => {
349
+ const [target, setTarget] = (0, import_react3.useState)(null);
350
+ const [preview, setPreview] = (0, import_react3.useState)(null);
351
+ const [busy, setBusy] = (0, import_react3.useState)(false);
352
+ const [error, setError] = (0, import_react3.useState)(null);
353
+ (0, import_react3.useEffect)(() => {
327
354
  if (enabled) return;
328
355
  setTarget(null);
329
356
  setPreview(null);
330
357
  setError(null);
331
358
  }, [enabled]);
332
- const open = (0, import_react2.useCallback)(async (next) => {
359
+ const open = (0, import_react3.useCallback)(async (next) => {
333
360
  setTarget(next);
334
361
  setPreview(null);
335
362
  setError(null);
@@ -376,7 +403,7 @@ function useMessageActions2(props, enabled) {
376
403
  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
404
  event.stopPropagation();
378
405
  void open(candidate);
379
- }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.IconTrashOutline16, { size: 16 }) }) }) : null,
406
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconTrashOutline16, { size: 16 }) }) }) : null,
380
407
  overlay: enabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
381
408
  import_dsh_client_ui_primitives2.Modal,
382
409
  {
@@ -404,7 +431,7 @@ function useMessageActions2(props, enabled) {
404
431
  }
405
432
 
406
433
  // src/patches/session-delete/client/index.tsx
407
- var import_react3 = require("react");
434
+ var import_react4 = require("react");
408
435
  var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
409
436
 
410
437
  // src/platform/dsh/client/styles.ts
@@ -546,14 +573,14 @@ function installSessionDeleteMenuItems(onDelete) {
546
573
  };
547
574
  }
548
575
  function SessionDeleteController(props) {
549
- const settings = (0, import_react3.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
576
+ const settings = (0, import_react4.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
550
577
  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)(() => {
578
+ const [pending, setPending] = (0, import_react4.useState)(null);
579
+ const pendingRef = (0, import_react4.useRef)(null);
580
+ const deleteIntentRef = (0, import_react4.useRef)(false);
581
+ const [busy, setBusy] = (0, import_react4.useState)(false);
582
+ const [error, setError] = (0, import_react4.useState)(null);
583
+ (0, import_react4.useEffect)(() => {
557
584
  if (!enabled) return;
558
585
  const workspaces = props.ctx.workspaces;
559
586
  const sessions = props.ctx.sessions;
@@ -642,7 +669,7 @@ function SessionDeleteController(props) {
642
669
  children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dshmore-dialog-body", children: [
643
670
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dshmore-message-preview", children: title }),
644
671
  /* @__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 }),
672
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconWarningOutline16, { size: 16 }),
646
673
  " \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
674
  ] }),
648
675
  error !== null && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dshmore-error", children: error })
@@ -663,7 +690,7 @@ var clientPatch = {
663
690
  };
664
691
 
665
692
  // src/patches/conversation-markdown-export/client/index.tsx
666
- var import_react4 = require("react");
693
+ var import_react5 = require("react");
667
694
  var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
668
695
 
669
696
  // src/patches/conversation-markdown-export/shared.ts
@@ -773,17 +800,17 @@ function saveMarkdown(filename, markdown) {
773
800
  }, 0);
774
801
  }
775
802
  function ConversationMarkdownExportButton(props) {
776
- const settings = (0, import_react4.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
803
+ const settings = (0, import_react5.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
777
804
  const enabled = settings[CONVERSATION_MARKDOWN_EXPORT_PATCH_ID];
778
805
  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);
806
+ const [busy, setBusy] = (0, import_react5.useState)(false);
807
+ const [error, setError] = (0, import_react5.useState)(null);
808
+ const button = (0, import_react5.useRef)(null);
809
+ const inFlight = (0, import_react5.useRef)(false);
810
+ const generation = (0, import_react5.useRef)(0);
811
+ const activeSession = (0, import_react5.useRef)(null);
785
812
  activeSession.current = enabled ? String(props.sessionId) : null;
786
- (0, import_react4.useEffect)(() => {
813
+ (0, import_react5.useEffect)(() => {
787
814
  generation.current += 1;
788
815
  inFlight.current = false;
789
816
  setBusy(false);
@@ -816,7 +843,7 @@ function ConversationMarkdownExportButton(props) {
816
843
  }
817
844
  }
818
845
  };
819
- (0, import_react4.useEffect)(() => {
846
+ (0, import_react5.useEffect)(() => {
820
847
  if (!enabled || button.current === null) return;
821
848
  return installMarkdownExportMenu(button.current, { busy, download: () => {
822
849
  void download();
@@ -839,7 +866,7 @@ function ConversationMarkdownExportButton(props) {
839
866
  },
840
867
  children: [
841
868
  /* @__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 })
869
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(IconDownloadOutline16, { size: 12 })
843
870
  ]
844
871
  }
845
872
  ),
@@ -868,7 +895,7 @@ var clientPatch2 = {
868
895
  };
869
896
 
870
897
  // src/patches/model-capabilities/client/index.tsx
871
- var import_react6 = require("react");
898
+ var import_react7 = require("react");
872
899
 
873
900
  // src/patches/model-capabilities/shared.ts
874
901
  var MODEL_CAPABILITIES_PATCH_ID = "model-capabilities";
@@ -910,8 +937,47 @@ async function readCapabilities() {
910
937
  return decodeSnapshot(await callPatchApi(MODEL_CAPABILITIES_PATCH_ID, "read", {}));
911
938
  }
912
939
 
940
+ // src/platform/dsh/client/settings.ts
941
+ function isConfigForm(value) {
942
+ return typeof value === "object" && value !== null && ["getSnapshot", "subscribe", "set", "unset", "mutate"].every((key) => typeof Reflect.get(value, key) === "function");
943
+ }
944
+ function bindSettings(ctx, spec) {
945
+ const service = typeof ctx.get === "function" ? ctx.get("configForms") : void 0;
946
+ if (typeof service !== "object" || service === null) return ctx.settingsScope.bind(spec);
947
+ const get = Reflect.get(service, "get");
948
+ const form = typeof get === "function" ? get.call(service, spec.namespace) : void 0;
949
+ if (!isConfigForm(form)) throw new TypeError("DSH configuration form API is unavailable");
950
+ let previous;
951
+ let snapshot;
952
+ let accepted;
953
+ const write = async (operation) => {
954
+ if (!await operation) throw new Error("\u4FDD\u5B58\u672A\u88AB\u63A5\u53D7\uFF0C\u8BF7\u5237\u65B0\u914D\u7F6E\u540E\u91CD\u8BD5\u3002");
955
+ };
956
+ return {
957
+ getSnapshot: () => {
958
+ const current = form.getSnapshot();
959
+ if (current === previous && snapshot !== void 0) return snapshot;
960
+ const decoded = spec.decode === void 0 ? current.value : spec.decode(current.value);
961
+ if (decoded !== void 0) accepted = decoded;
962
+ previous = current;
963
+ snapshot = { ...current, value: accepted };
964
+ return snapshot;
965
+ },
966
+ subscribe: (listener) => form.subscribe(listener),
967
+ set: (...args) => write(form.set(...args)),
968
+ unset: (...args) => write(form.unset(...args)),
969
+ mutate: (...args) => write(form.mutate(...args))
970
+ };
971
+ }
972
+ function withSettings(ctx, install2) {
973
+ ctx.inject(["configForms"], install2);
974
+ ctx.inject(["settingsScope"], (scope) => {
975
+ if (scope.get("configForms") === void 0) install2(scope);
976
+ });
977
+ }
978
+
913
979
  // src/patches/model-capabilities/client/editor.tsx
914
- var import_react5 = require("react");
980
+ var import_react6 = require("react");
915
981
  var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
916
982
  var import_jsx_runtime5 = require("react/jsx-runtime");
917
983
  var LEVEL_LABELS = {
@@ -1050,20 +1116,20 @@ function CapabilitiesEditorBody({ draft, setDraft, disabled, api: api3 }) {
1050
1116
  ] });
1051
1117
  }
1052
1118
  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)(() => {
1119
+ const [snapshot, setSnapshot] = (0, import_react6.useState)(null);
1120
+ const [draft, setDraft] = (0, import_react6.useState)(null);
1121
+ const [error, setError] = (0, import_react6.useState)(null);
1122
+ const [busy, setBusy] = (0, import_react6.useState)(false);
1123
+ const [attempt, setAttempt] = (0, import_react6.useState)(0);
1124
+ const saving = (0, import_react6.useRef)(false);
1125
+ const mounted = (0, import_react6.useRef)(false);
1126
+ (0, import_react6.useEffect)(() => {
1061
1127
  mounted.current = true;
1062
1128
  return () => {
1063
1129
  mounted.current = false;
1064
1130
  };
1065
1131
  }, []);
1066
- (0, import_react5.useEffect)(() => {
1132
+ (0, import_react6.useEffect)(() => {
1067
1133
  let cancelled = false;
1068
1134
  setError(null);
1069
1135
  void readCapabilities().then((next) => {
@@ -1214,15 +1280,15 @@ var capabilitiesStyles = `
1214
1280
  var import_jsx_runtime6 = require("react/jsx-runtime");
1215
1281
  var BUTTON_ATTR = "data-dshmore-model-capabilities";
1216
1282
  function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1217
- const settings = (0, import_react6.useSyncExternalStore)(activation.subscribe, activation.getSnapshot, activation.getSnapshot);
1283
+ const settings = (0, import_react7.useSyncExternalStore)(activation.subscribe, activation.getSnapshot, activation.getSnapshot);
1218
1284
  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);
1285
+ const scopeSnapshot = (0, import_react7.useSyncExternalStore)(scope.subscribe, scope.getSnapshot, scope.getSnapshot);
1286
+ const deepseekSnapshot = (0, import_react7.useSyncExternalStore)(deepseekScope.subscribe, deepseekScope.getSnapshot, deepseekScope.getSnapshot);
1287
+ const [editing, setEditing] = (0, import_react7.useState)(null);
1288
+ const [data, setData] = (0, import_react7.useState)(null);
1289
+ const dataRef = (0, import_react7.useRef)(data);
1224
1290
  dataRef.current = data;
1225
- (0, import_react6.useEffect)(() => {
1291
+ (0, import_react7.useEffect)(() => {
1226
1292
  let cancelled = false;
1227
1293
  if (!enabled) {
1228
1294
  setEditing(null);
@@ -1238,7 +1304,7 @@ function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1238
1304
  cancelled = true;
1239
1305
  };
1240
1306
  }, [enabled, scopeSnapshot, deepseekSnapshot]);
1241
- const syncButtons = (0, import_react6.useCallback)(() => {
1307
+ const syncButtons = (0, import_react7.useCallback)(() => {
1242
1308
  if (!enabled) return;
1243
1309
  const active = /* @__PURE__ */ new Set();
1244
1310
  for (const entry of findModelEntries()) {
@@ -1270,7 +1336,7 @@ function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1270
1336
  if (button.parentElement === null || !active.has(button.parentElement)) button.remove();
1271
1337
  });
1272
1338
  }, [enabled]);
1273
- (0, import_react6.useEffect)(() => {
1339
+ (0, import_react7.useEffect)(() => {
1274
1340
  if (!enabled) return;
1275
1341
  let frame = null;
1276
1342
  const schedule = () => {
@@ -1293,7 +1359,7 @@ function ModelsPageCapabilitiesPortal({ scope, deepseekScope, activation }) {
1293
1359
  document.querySelectorAll(`[${BUTTON_ATTR}]`).forEach((element) => element.remove());
1294
1360
  };
1295
1361
  }, [enabled, syncButtons]);
1296
- (0, import_react6.useEffect)(() => {
1362
+ (0, import_react7.useEffect)(() => {
1297
1363
  if (enabled) syncButtons();
1298
1364
  }, [enabled, syncButtons, data]);
1299
1365
  if (!enabled) return null;
@@ -1316,7 +1382,7 @@ var clientPatch3 = {
1316
1382
  id: MODEL_CAPABILITIES_PATCH_ID,
1317
1383
  install: (ctx, activation) => {
1318
1384
  const bindScope = (namespace) => {
1319
- const scope = ctx.settingsScope.bind({ namespace });
1385
+ const scope = bindSettings(ctx, { namespace });
1320
1386
  return {
1321
1387
  getSnapshot: scope.getSnapshot.bind(scope),
1322
1388
  subscribe: scope.subscribe.bind(scope),
@@ -1349,7 +1415,7 @@ var clientPatch4 = {
1349
1415
  var PROJECTLESS_TASKS_PATCH_ID = "projectless-tasks";
1350
1416
 
1351
1417
  // src/patches/projectless-tasks/client/adapter.tsx
1352
- var import_react8 = require("react");
1418
+ var import_react9 = require("react");
1353
1419
 
1354
1420
  // src/patches/projectless-tasks/client/create-task.ts
1355
1421
  function createTaskStarter(sessions) {
@@ -1431,7 +1497,7 @@ function transferBeforeOpen(ctx, sourceId, targetId) {
1431
1497
  }
1432
1498
 
1433
1499
  // src/patches/projectless-tasks/client/picker.tsx
1434
- var import_react7 = require("react");
1500
+ var import_react8 = require("react");
1435
1501
  var import_jsx_runtime7 = require("react/jsx-runtime");
1436
1502
  var INDEPENDENT_CHOICE_ID = "::dsh-more-independent-task";
1437
1503
  var INDEPENDENT_CHOICE = {
@@ -1442,7 +1508,7 @@ var INDEPENDENT_CHOICE = {
1442
1508
  createdAt: "",
1443
1509
  updatedAt: ""
1444
1510
  };
1445
- var ChoiceContext = (0, import_react7.createContext)(void 0);
1511
+ var ChoiceContext = (0, import_react8.createContext)(void 0);
1446
1512
  function withIndependentChoice(snapshot) {
1447
1513
  return { ...snapshot, items: [INDEPENDENT_CHOICE, ...snapshot.items] };
1448
1514
  }
@@ -1463,7 +1529,7 @@ function labelIndependentChip(anchor) {
1463
1529
  };
1464
1530
  }
1465
1531
  function WorkspaceChoice({ owner, state, error, children }) {
1466
- (0, import_react7.useLayoutEffect)(() => {
1532
+ (0, import_react8.useLayoutEffect)(() => {
1467
1533
  const anchor = owner.anchorRef?.current;
1468
1534
  if (!state.independent || owner.selectedId !== void 0 || anchor === void 0 || anchor === null) return;
1469
1535
  return labelIndependentChip(anchor);
@@ -1499,11 +1565,11 @@ function WorkspaceChoice({ owner, state, error, children }) {
1499
1565
  }
1500
1566
  function extendWorkspacePicker(original) {
1501
1567
  return function ProjectlessPicker(props) {
1502
- const choice = (0, import_react7.useContext)(ChoiceContext);
1568
+ const choice = (0, import_react8.useContext)(ChoiceContext);
1503
1569
  const snapshot = props.useWorkspaces((value) => value);
1504
- const display = (0, import_react7.useMemo)(() => choice === void 0 ? snapshot : withIndependentChoice(snapshot), [snapshot, choice === void 0]);
1570
+ const display = (0, import_react8.useMemo)(() => choice === void 0 ? snapshot : withIndependentChoice(snapshot), [snapshot, choice === void 0]);
1505
1571
  const useWorkspaces = (select) => select(display);
1506
- return (0, import_react7.createElement)(original, {
1572
+ return (0, import_react8.createElement)(original, {
1507
1573
  ...props,
1508
1574
  useWorkspaces,
1509
1575
  open: props.open && !choice?.busy,
@@ -1579,17 +1645,17 @@ function installConversationAdapter(ctx, activation, name = "main.conversation")
1579
1645
  const sync = () => {
1580
1646
  for (const entry of ctx.slots.entries(slot)) {
1581
1647
  let ProjectlessConversation2 = function(props) {
1582
- const active = (0, import_react8.useSyncExternalStore)(subscribeLifetime, () => live);
1583
- const settings = (0, import_react8.useSyncExternalStore)(activation.subscribe, activation.getSnapshot);
1648
+ const active = (0, import_react9.useSyncExternalStore)(subscribeLifetime, () => live);
1649
+ const settings = (0, import_react9.useSyncExternalStore)(activation.subscribe, activation.getSnapshot);
1584
1650
  const workspace = props.useWorkspaces((snapshot) => snapshot);
1585
1651
  const cwd = props.useSessions((snapshot) => props.sessionId === void 0 ? void 0 : snapshot.byId[props.sessionId]?.cwd);
1586
1652
  const session = props.useSession((snapshot) => snapshot);
1587
1653
  const block = props.useComposerBlock((value) => value);
1588
1654
  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)(() => {
1655
+ const starter = (0, import_react9.useRef)();
1656
+ const [busy, setBusy] = (0, import_react9.useState)(false);
1657
+ const [error, setError] = (0, import_react9.useState)();
1658
+ (0, import_react9.useEffect)(() => {
1593
1659
  if (!enabled) return;
1594
1660
  setBusy(false);
1595
1661
  setError(void 0);
@@ -1619,7 +1685,7 @@ function installConversationAdapter(ctx, activation, name = "main.conversation")
1619
1685
  }
1620
1686
  return props.renderSlot(name2, owner, options);
1621
1687
  };
1622
- return (0, import_react8.createElement)(original, { ...props, renderSlot });
1688
+ return (0, import_react9.createElement)(original, { ...props, renderSlot });
1623
1689
  };
1624
1690
  var ProjectlessConversation = ProjectlessConversation2;
1625
1691
  if (wrapped.has(entry) || entry.children?.["conversation.composer.bar"] === void 0 || typeof entry.component !== "function") continue;
@@ -1759,7 +1825,7 @@ function installNewSessionNavigation(ctx, activation) {
1759
1825
  }
1760
1826
 
1761
1827
  // src/patches/projectless-tasks/client/groups.tsx
1762
- var import_react9 = require("react");
1828
+ var import_react10 = require("react");
1763
1829
  var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
1764
1830
 
1765
1831
  // src/patches/projectless-tasks/groups.ts
@@ -1838,29 +1904,29 @@ var ALWAYS_LIVE = { subscribe: () => () => {
1838
1904
  }, getSnapshot: () => true };
1839
1905
  function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LIVE) {
1840
1906
  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);
1907
+ const settings = (0, import_react10.useSyncExternalStore)(activation.subscribe, activation.getSnapshot);
1908
+ const binding = (0, import_react10.useMemo)(() => ({ subscribe: (listener) => source.subscribe(listener), getSnapshot: () => source.getSnapshot() }), []);
1909
+ const saved = (0, import_react10.useSyncExternalStore)(binding.subscribe, binding.getSnapshot);
1844
1910
  const native = props.useWorkspaces((value) => value);
1845
1911
  const sessions = props.useSessions((value) => value);
1846
- const active = (0, import_react9.useSyncExternalStore)(lifetime.subscribe, lifetime.getSnapshot);
1912
+ const active = (0, import_react10.useSyncExternalStore)(lifetime.subscribe, lifetime.getSnapshot);
1847
1913
  const enabled = active && settings[PROJECTLESS_TASKS_PATCH_ID];
1848
1914
  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)(() => {
1915
+ const display = (0, import_react10.useMemo)(() => enabled ? projectSessionGroups(native, sessions, groups) : native, [enabled, native, sessions, groups]);
1916
+ const [pending, setPending] = (0, import_react10.useState)();
1917
+ const [destination, setDestination] = (0, import_react10.useState)("");
1918
+ const [busy, setBusy] = (0, import_react10.useState)(false);
1919
+ const [error, setError] = (0, import_react10.useState)();
1920
+ const intent = (0, import_react10.useRef)(false);
1921
+ const inFlight = (0, import_react10.useRef)(false);
1922
+ const live = (0, import_react10.useRef)(true);
1923
+ (0, import_react10.useEffect)(() => {
1858
1924
  live.current = true;
1859
1925
  return () => {
1860
1926
  live.current = false;
1861
1927
  };
1862
1928
  }, []);
1863
- (0, import_react9.useEffect)(() => {
1929
+ (0, import_react10.useEffect)(() => {
1864
1930
  if (!enabled) {
1865
1931
  setPending(void 0);
1866
1932
  return;
@@ -1906,7 +1972,7 @@ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LI
1906
1972
  const selectedMissing = destination !== "" && !native.items.some((item) => item.workspaceId === destination);
1907
1973
  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
1974
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1909
- (0, import_react9.createElement)(original, { ...props, useWorkspaces, archiveSession }),
1975
+ (0, import_react10.createElement)(original, { ...props, useWorkspaces, archiveSession }),
1910
1976
  enabled && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1911
1977
  import_dsh_client_ui_primitives6.Modal,
1912
1978
  {
@@ -1946,7 +2012,7 @@ function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LI
1946
2012
  };
1947
2013
  }
1948
2014
  function installSessionGrouping(ctx, activation) {
1949
- const source = ctx.settingsScope.bind({ namespace: SESSION_GROUPS_NAMESPACE, decode: decodeSessionGroups });
2015
+ const source = bindSettings(ctx, { namespace: SESSION_GROUPS_NAMESPACE, decode: decodeSessionGroups });
1950
2016
  ctx.slots.inject(SIDEBAR_SLOT, () => {
1951
2017
  let live = true;
1952
2018
  const listeners = /* @__PURE__ */ new Set();
@@ -2021,19 +2087,18 @@ var ClientPatchActivation = class {
2021
2087
  };
2022
2088
 
2023
2089
  // 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");
2090
+ var import_react11 = require("react");
2026
2091
  var import_jsx_runtime10 = require("react/jsx-runtime");
2027
2092
  function PatchConfigCard({ activation, initiallyOpen = false }) {
2028
- const scope = (0, import_react10.useSyncExternalStore)(
2093
+ const scope = (0, import_react11.useSyncExternalStore)(
2029
2094
  activation.subscribe,
2030
2095
  activation.getSettingsSnapshot,
2031
2096
  activation.getSettingsSnapshot
2032
2097
  );
2033
2098
  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);
2099
+ const [open, setOpen] = (0, import_react11.useState)(initiallyOpen);
2100
+ const [busy, setBusy] = (0, import_react11.useState)(/* @__PURE__ */ new Set());
2101
+ const [error, setError] = (0, import_react11.useState)(null);
2037
2102
  if (scope.status === "unavailable") return null;
2038
2103
  const update = async (id, enabled) => {
2039
2104
  setBusy((current) => /* @__PURE__ */ new Set([...current, id]));
@@ -2067,7 +2132,7 @@ function PatchConfigCard({ activation, initiallyOpen = false }) {
2067
2132
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { children: "DSH More" }),
2068
2133
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "\u52A8\u6001\u5F00\u542F\u6216\u5173\u95ED\u72EC\u7ACB\u8865\u4E01\uFF0C\u9ED8\u8BA4\u5168\u90E8\u5F00\u542F\u3002" })
2069
2134
  ] }),
2070
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_dsh_client_ui_primitives7.IconChevronDownOutline14, { className: `dshmore-config-chevron${open ? " dshmore-config-chevron-open" : ""}` })
2135
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconChevronDownOutline14, { size: 14, className: `dshmore-config-chevron${open ? " dshmore-config-chevron-open" : ""}` })
2071
2136
  ]
2072
2137
  }
2073
2138
  ),
@@ -2101,18 +2166,27 @@ function PatchConfigCard({ activation, initiallyOpen = false }) {
2101
2166
  ] });
2102
2167
  }
2103
2168
  function installPatchConfigCard(ctx, activation) {
2169
+ if (ctx.get("configForms") !== void 0) {
2170
+ ctx.slots.inject("settings.section", () => ctx.slots.register({
2171
+ name: "settings.section",
2172
+ id: PATCH_SETTINGS_NAMESPACE,
2173
+ order: 90,
2174
+ label: "DSH More"
2175
+ }, () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("ul", { style: { listStyle: "none", padding: 0, margin: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PatchConfigCard, { activation, initiallyOpen: true }) })));
2176
+ return;
2177
+ }
2104
2178
  ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
2105
2179
  name: "settings.plugin.item",
2106
2180
  key: PATCH_SETTINGS_NAMESPACE,
2107
2181
  priority: 90
2108
- }, (props) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PatchConfigCard, { ...props, activation })));
2182
+ }, () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PatchConfigCard, { activation })));
2109
2183
  }
2110
2184
 
2111
2185
  // src/kernel/message-visibility.ts
2112
2186
  var MESSAGE_VISIBILITY_PROJECTION_KEY = "dshMoreMessageDelete";
2113
2187
 
2114
2188
  // src/platform/dsh/client/message-targets.tsx
2115
- var import_react11 = require("react");
2189
+ var import_react12 = require("react");
2116
2190
 
2117
2191
  // src/platform/dsh/client/message-content.ts
2118
2192
  function contentText(content) {
@@ -2250,17 +2324,17 @@ function trajectorySourceSeq(row) {
2250
2324
  return Number.isSafeInteger(seq) && seq >= 0 ? seq : void 0;
2251
2325
  }
2252
2326
  function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = true) {
2253
- const selector = (0, import_react11.useMemo)(() => createMessageSurfaceSelector(active), [active, props.sessionId]);
2327
+ const selector = (0, import_react12.useMemo)(() => createMessageSurfaceSelector(active), [active, props.sessionId]);
2254
2328
  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);
2329
+ const surfaceRef = (0, import_react12.useRef)(surface);
2330
+ const hiddenSeqsRef = (0, import_react12.useRef)(hiddenSeqs);
2331
+ const hiddenTrajectoryKeysRef = (0, import_react12.useRef)(hiddenTrajectoryKeys);
2258
2332
  surfaceRef.current = surface;
2259
2333
  hiddenSeqsRef.current = hiddenSeqs;
2260
2334
  hiddenTrajectoryKeysRef.current = hiddenTrajectoryKeys;
2261
- const [targets, setTargets] = (0, import_react11.useState)([]);
2262
- const requestFullScanRef = (0, import_react11.useRef)(null);
2263
- (0, import_react11.useLayoutEffect)(() => {
2335
+ const [targets, setTargets] = (0, import_react12.useState)([]);
2336
+ const requestFullScanRef = (0, import_react12.useRef)(null);
2337
+ (0, import_react12.useLayoutEffect)(() => {
2264
2338
  if (!active) {
2265
2339
  setTargets((current) => current.length === 0 ? current : []);
2266
2340
  return;
@@ -2384,7 +2458,7 @@ function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = tru
2384
2458
  for (const host of document.querySelectorAll("[data-dshmore-message-actions]")) host.remove();
2385
2459
  };
2386
2460
  }, [active, props.sessionId]);
2387
- (0, import_react11.useLayoutEffect)(() => {
2461
+ (0, import_react12.useLayoutEffect)(() => {
2388
2462
  requestFullScanRef.current?.();
2389
2463
  }, [surface, hiddenSeqs, hiddenTrajectoryKeys]);
2390
2464
  return targets;
@@ -2392,7 +2466,7 @@ function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = tru
2392
2466
 
2393
2467
  // src/client/index.tsx
2394
2468
  var import_jsx_runtime11 = require("react/jsx-runtime");
2395
- var inject = ["slots", "sessions", "workspaces", "settingsScope"];
2469
+ var inject = ["slots", "sessions", "workspaces"];
2396
2470
  function MessageActionPatchController({ patch, props, targets, enabled }) {
2397
2471
  const actions = patch.useActions(props, enabled);
2398
2472
  const style = { "--dshmore-action-order": patch.order };
@@ -2406,10 +2480,10 @@ function MessageActionPatchController({ patch, props, targets, enabled }) {
2406
2480
  ] });
2407
2481
  }
2408
2482
  function MessageActionsController(props) {
2409
- const settings = (0, import_react12.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
2483
+ const settings = (0, import_react13.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
2410
2484
  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]);
2485
+ const hiddenSeqs = (0, import_react13.useMemo)(() => new Set(projected?.deletedSeqs ?? []), [projected]);
2486
+ const hiddenTrajectoryKeys = (0, import_react13.useMemo)(() => new Set(projected?.hiddenTrajectoryKeys ?? []), [projected]);
2413
2487
  const messageActionsEnabled = MESSAGE_ACTION_PATCHES.some((patch) => settings[patch.id]);
2414
2488
  const targets = useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, messageActionsEnabled);
2415
2489
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
@@ -2427,7 +2501,10 @@ function MessageActionsController(props) {
2427
2501
  ] });
2428
2502
  }
2429
2503
  function apply(ctx) {
2430
- const scope = ctx.settingsScope.bind({
2504
+ withSettings(ctx, install);
2505
+ }
2506
+ function install(ctx) {
2507
+ const scope = bindSettings(ctx, {
2431
2508
  namespace: PATCH_SETTINGS_NAMESPACE,
2432
2509
  decode: decodePatchSettings
2433
2510
  });
package/dist/index.js CHANGED
@@ -282,9 +282,13 @@ async function createEditedContinuation(ctx, sourceAgent, cut, editedText, child
282
282
  agentOptions: {
283
283
  ...(request?.provider ?? sourceAgent.options.provider) === void 0 ? {} : { provider: request?.provider ?? sourceAgent.options.provider },
284
284
  ...(request?.model ?? sourceAgent.options.model) === void 0 ? {} : { model: request?.model ?? sourceAgent.options.model },
285
- ...sourceAgent.options.maxTokens === void 0 ? {} : { maxTokens: sourceAgent.options.maxTokens }
285
+ ...sourceAgent.options.maxTokens === void 0 ? {} : { maxTokens: sourceAgent.options.maxTokens },
286
+ ...(request?.reasoningEffort ?? sourceAgent.options.reasoningEffort) === void 0 ? {} : {
287
+ reasoningEffort: request?.reasoningEffort ?? sourceAgent.options.reasoningEffort
288
+ }
286
289
  },
287
- setup: (agentCtx) => {
290
+ setup: (agentCtx, agent) => {
291
+ agent.inbox.clear();
288
292
  roster?.composeFrom(agentCtx, sourceAgent.ctx);
289
293
  releaseRuntimeContextReplay = replaySeedRuntimeContext(agentCtx, seed);
290
294
  }
@@ -475,7 +479,21 @@ function recordedDeletionSeqs(events) {
475
479
  function buildCleanSeed(source, selection) {
476
480
  const deleted = recordedDeletionSeqs(source.snapshotEvents());
477
481
  for (const seq of selection.shadowedSeqs) deleted.add(seq);
478
- const survivors = source.surface.nodes.filter((seq) => !deleted.has(seq)).map((seq) => source.eventAt(seq)).filter((event) => event !== void 0 && source.deriveEventMessage(event) !== null);
482
+ const survivors = /* @__PURE__ */ new Map();
483
+ for (const seq of source.surface.nodes) {
484
+ if (deleted.has(seq)) continue;
485
+ const event = source.eventAt(seq);
486
+ if (event === void 0 || source.deriveEventMessage(event) === null) continue;
487
+ let anchor = event;
488
+ while (anchor.surfaceOp !== void 0 && anchor.surfaceOp !== "append") {
489
+ const previous = source.eventAt(anchor.surfaceOp.startSeq);
490
+ if (previous === void 0 || previous.seq >= anchor.seq) break;
491
+ anchor = previous;
492
+ }
493
+ const at = survivors.get(anchor.seq) ?? [];
494
+ at.push(event);
495
+ survivors.set(anchor.seq, at);
496
+ }
479
497
  const rebuilt = Session.create(SessionId4(`session-rebuild-${randomUUID3()}`));
480
498
  let turn = 0;
481
499
  let step = 0;
@@ -483,6 +501,8 @@ function buildCleanSeed(source, selection) {
483
501
  let stepOpen = false;
484
502
  let assistantSeen = false;
485
503
  const loggedCalls = /* @__PURE__ */ new Set();
504
+ const userSeqs = /* @__PURE__ */ new Map();
505
+ let sourceTurnOpen = false;
486
506
  const closeStep = () => {
487
507
  if (!stepOpen) return;
488
508
  rebuilt.append("step/end", { turn, step });
@@ -509,40 +529,87 @@ function buildCleanSeed(source, selection) {
509
529
  stepOpen = true;
510
530
  }
511
531
  };
512
- for (const event of survivors) {
513
- if (event.type === "user/message" && event.data.source.kind === "user" && turnOpen) closeTurn();
514
- if (event.type === "assistant/message" && assistantSeen) closeStep();
515
- openStep();
516
- if (event.type === "user/message") {
517
- rebuilt.append("user/message", event.data, { surfaceOp: "append" });
532
+ for (const entry of source.snapshotEvents()) {
533
+ if ([
534
+ "permission/preset",
535
+ "sandbox/mode",
536
+ "approval/policy",
537
+ "subagent/model-selection-policy",
538
+ "model/selection",
539
+ "request/header",
540
+ "request/context",
541
+ "agent-preset/selected"
542
+ ].includes(entry.type)) {
543
+ rebuilt.append(entry.type, entry.data);
518
544
  continue;
519
545
  }
520
- if (event.type === "assistant/message") {
521
- rebuilt.append("assistant/message", {
522
- // Keep the durable stream and settlement metadata required by DSH 0.1.5.
523
- // Only the reconstructed turn/step coordinates belong to the new log.
524
- ...event.data,
525
- turn,
526
- step
527
- }, { surfaceOp: "append" });
528
- assistantSeen = true;
529
- for (const call of event.data.message.content) {
530
- if (call.type !== "tool-call") continue;
531
- rebuilt.append("tool/call", { turn, step, callId: call.id, name: call.name, arguments: call.arguments });
532
- loggedCalls.add(call.id);
533
- }
546
+ if (entry.type === "turn/start") {
547
+ closeTurn();
548
+ sourceTurnOpen = true;
534
549
  continue;
535
550
  }
536
- if (event.type === "tool/result") {
537
- const callId = event.data.message.source.callId;
538
- if (!loggedCalls.has(callId)) {
539
- rebuilt.append("tool/call", { turn, step, callId: event.data.message.source.callId, name: "restored-tool", arguments: "{}" });
540
- loggedCalls.add(callId);
551
+ if (entry.type === "turn/end") {
552
+ closeTurn();
553
+ sourceTurnOpen = false;
554
+ continue;
555
+ }
556
+ if (entry.type === "step/end") {
557
+ closeStep();
558
+ continue;
559
+ }
560
+ for (const event of survivors.get(entry.seq) ?? []) {
561
+ if (event.type === "user/message" && !sourceTurnOpen && event.data.source.kind !== "user") {
562
+ rebuilt.append("user/message", event.data, { surfaceOp: "append" });
563
+ continue;
564
+ }
565
+ if (event.type === "assistant/message" && assistantSeen) closeStep();
566
+ openStep();
567
+ if (event.type === "system/message") {
568
+ rebuilt.append("system/message", { ...event.data, turn, step }, { surfaceOp: "append" });
569
+ continue;
570
+ }
571
+ if (event.type === "user/message") {
572
+ const appended = rebuilt.append("user/message", event.data, { surfaceOp: "append" });
573
+ if (event.data.source.kind === "user") userSeqs.set(event.seq, appended.seq);
574
+ continue;
575
+ }
576
+ if (event.type === "assistant/message") {
577
+ rebuilt.append("assistant/message", {
578
+ // Keep the durable stream and settlement metadata required by DSH 0.1.5.
579
+ // Only the reconstructed turn/step coordinates belong to the new log.
580
+ ...event.data,
581
+ turn,
582
+ step
583
+ }, { surfaceOp: "append" });
584
+ assistantSeen = true;
585
+ for (const call of event.data.message.content) {
586
+ if (call.type !== "tool-call") continue;
587
+ rebuilt.append("tool/call", { turn, step, callId: call.id, name: call.name, arguments: call.arguments });
588
+ loggedCalls.add(call.id);
589
+ }
590
+ continue;
591
+ }
592
+ if (event.type === "tool/result") {
593
+ const callId = event.data.message.source.callId;
594
+ if (!loggedCalls.has(callId)) {
595
+ rebuilt.append("tool/call", { turn, step, callId: event.data.message.source.callId, name: "restored-tool", arguments: "{}" });
596
+ loggedCalls.add(callId);
597
+ }
598
+ rebuilt.append("tool/result", { turn, step, message: event.data.message, ...event.data.error === void 0 ? {} : { error: event.data.error }, ...event.data.meta === void 0 ? {} : { meta: event.data.meta } }, { surfaceOp: "append" });
541
599
  }
542
- rebuilt.append("tool/result", { turn, step, message: event.data.message, ...event.data.error === void 0 ? {} : { error: event.data.error }, ...event.data.meta === void 0 ? {} : { meta: event.data.meta } }, { surfaceOp: "append" });
543
600
  }
544
601
  }
545
602
  closeTurn();
603
+ const title = source.snapshotEvents().findLast((event) => event.type === "session/title");
604
+ if (title?.type === "session/title") {
605
+ const messageSeqs = title.data.messageSeqs.flatMap((seq) => {
606
+ const mapped = userSeqs.get(seq);
607
+ return mapped === void 0 ? [] : [mapped];
608
+ });
609
+ if (title.data.source.kind === "user" || messageSeqs.length > 0) {
610
+ rebuilt.append("session/title", { ...title.data, messageSeqs });
611
+ }
612
+ }
546
613
  return rebuilt.snapshotEvents();
547
614
  }
548
615
  async function createDeletedContinuation(ctx, sourceAgent, selection, childId = SessionId4(`session-${randomUUID3()}`)) {
@@ -578,7 +645,10 @@ async function createDeletedContinuation(ctx, sourceAgent, selection, childId =
578
645
  agentOptions: {
579
646
  ...provider === void 0 ? {} : { provider },
580
647
  ...model === void 0 ? {} : { model },
581
- ...sourceAgent.options.maxTokens === void 0 ? {} : { maxTokens: sourceAgent.options.maxTokens }
648
+ ...sourceAgent.options.maxTokens === void 0 ? {} : { maxTokens: sourceAgent.options.maxTokens },
649
+ ...(request?.reasoningEffort ?? sourceAgent.options.reasoningEffort) === void 0 ? {} : {
650
+ reasoningEffort: request?.reasoningEffort ?? sourceAgent.options.reasoningEffort
651
+ }
582
652
  },
583
653
  setup: (agentCtx) => {
584
654
  roster?.composeFrom(agentCtx, sourceAgent.ctx);
@@ -1073,6 +1143,21 @@ function validateCapabilities(raw) {
1073
1143
  };
1074
1144
  }
1075
1145
 
1146
+ // src/platform/dsh/host/settings.ts
1147
+ function liveSetting(schema2) {
1148
+ const volatile = Reflect.get(schema2, "volatile");
1149
+ return typeof volatile === "function" ? volatile.call(schema2) : schema2;
1150
+ }
1151
+ function settingValue(value) {
1152
+ if (typeof value !== "object" || value === null) return value;
1153
+ const get = Reflect.get(value, "get");
1154
+ return typeof get === "function" ? get.call(value) : value;
1155
+ }
1156
+ function readSettings(ctx, namespace) {
1157
+ if (typeof ctx.settings.get === "function") return ctx.settings.get(namespace);
1158
+ return ctx.settings.describe().find((entry) => entry.ns === namespace)?.value;
1159
+ }
1160
+
1076
1161
  // src/patches/model-capabilities/host/deepseek.ts
1077
1162
  function record(value) {
1078
1163
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
@@ -1087,7 +1172,7 @@ function validateDeepSeekEfforts(efforts) {
1087
1172
  }
1088
1173
  function ruleFor(ctx, provider, modelId) {
1089
1174
  if (provider !== DEEPSEEK_PROVIDER) return void 0;
1090
- const profile = record(ctx.settings.get(LLM_DEEPSEEK_SETTINGS_NAMESPACE));
1175
+ const profile = record(readSettings(ctx, LLM_DEEPSEEK_SETTINGS_NAMESPACE));
1091
1176
  const models = Array.isArray(profile.models) ? profile.models : [];
1092
1177
  const model = record(models.find((item) => record(item).id === modelId));
1093
1178
  if (model.reasoningEfforts === void 0) return void 0;
@@ -1493,7 +1578,7 @@ async function moveSessionGroup(ctx, payload) {
1493
1578
  if (ctx.workspaceRegistry.list().some((workspace) => workspace.sessionIds.includes(sessionId))) {
1494
1579
  throw new DshMoreError("bad-request", "\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");
1495
1580
  }
1496
- const current = decodeSessionGroups(ctx.settings.get(SESSION_GROUPS_NAMESPACE)) ?? EMPTY_GROUPS;
1581
+ const current = decodeSessionGroups(readSettings(ctx, SESSION_GROUPS_NAMESPACE)) ?? EMPTY_GROUPS;
1497
1582
  const result = { sessionId, workspaceId };
1498
1583
  if ((current.assignments[sessionId] ?? null) === workspaceId) return result;
1499
1584
  await ctx.settings.mutate(SESSION_GROUPS_NAMESPACE, [workspaceId === null ? { op: "unset", path: ["assignments", sessionId] } : { op: "set", path: ["assignments", sessionId], value: workspaceId }]);
@@ -1511,7 +1596,9 @@ var hostPatch7 = {
1511
1596
  id: PROJECTLESS_TASKS_PATCH_ID,
1512
1597
  setup: (ctx) => {
1513
1598
  const fiber = ctx.inject(["settings"], (scope) => {
1514
- scope.settings.register(SESSION_GROUPS_NAMESPACE, SessionGroupsSchema);
1599
+ if (typeof scope.settings.register === "function") {
1600
+ scope.settings.register(SESSION_GROUPS_NAMESPACE, SessionGroupsSchema);
1601
+ }
1515
1602
  });
1516
1603
  return () => {
1517
1604
  void fiber.dispose();
@@ -1524,6 +1611,15 @@ var hostPatch7 = {
1524
1611
  var HOST_PATCHES = [hostPatch, hostPatch2, hostPatch3, hostPatch4, hostPatch5, hostPatch6, hostPatch7];
1525
1612
 
1526
1613
  // src/generated/patch-catalog.ts
1614
+ var PATCH_CATALOG = [
1615
+ { "id": "message-edit", "name": "\u7F16\u8F91\u5E76\u91CD\u65B0\u5F00\u59CB", "description": "\u7F16\u8F91\u7528\u6237\u6D88\u606F\u5E76\u4E22\u5F03\u8BE5\u6D88\u606F\u4E4B\u540E\u7684\u5386\u53F2", "defaultEnabled": true, "order": 100, "clientKind": "message-action" },
1616
+ { "id": "message-delete", "name": "\u5355\u6761\u6D88\u606F\u5220\u9664", "description": "\u5220\u9664\u6307\u5B9A\u6D88\u606F\u5E76\u4FDD\u7559\u524D\u540E\u5386\u53F2\u8BB0\u5F55", "defaultEnabled": true, "order": 200, "clientKind": "message-action" },
1617
+ { "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" },
1618
+ { "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" },
1619
+ { "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" },
1620
+ { "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" },
1621
+ { "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" }
1622
+ ];
1527
1623
  var DEFAULT_PATCH_SETTINGS = {
1528
1624
  "message-edit": true,
1529
1625
  "message-delete": true,
@@ -1533,6 +1629,17 @@ var DEFAULT_PATCH_SETTINGS = {
1533
1629
  "session-auto-title": true,
1534
1630
  "projectless-tasks": true
1535
1631
  };
1632
+ function decodePatchSettings(value) {
1633
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
1634
+ const candidate = value;
1635
+ const decoded = { ...DEFAULT_PATCH_SETTINGS };
1636
+ for (const patch of PATCH_CATALOG) {
1637
+ const enabled = candidate[patch.id];
1638
+ if (enabled !== void 0 && typeof enabled !== "boolean") return void 0;
1639
+ if (typeof enabled === "boolean") decoded[patch.id] = enabled;
1640
+ }
1641
+ return decoded;
1642
+ }
1536
1643
 
1537
1644
  // src/kernel/host/activation.ts
1538
1645
  var NOOP = () => void 0;
@@ -1567,6 +1674,9 @@ var HostPatchActivation = class {
1567
1674
  }
1568
1675
  };
1569
1676
 
1677
+ // src/kernel/host/settings.ts
1678
+ import z4 from "@deepseek-ai/schemastery";
1679
+
1570
1680
  // src/generated/host-settings-schema.ts
1571
1681
  import z3 from "@deepseek-ai/schemastery";
1572
1682
  var PatchSettingsSchema = z3.object({
@@ -1581,7 +1691,21 @@ var PatchSettingsSchema = z3.object({
1581
1691
 
1582
1692
  // src/kernel/host/settings.ts
1583
1693
  var PATCH_SETTINGS_NAMESPACE2 = PATCH_SETTINGS_NAMESPACE;
1584
- function installPatchSettings(ctx, activation) {
1694
+ var PatchConfig = z4.object(Object.fromEntries(
1695
+ Object.entries(PatchSettingsSchema.dict ?? {}).map(([key, schema2]) => [key, liveSetting(schema2)])
1696
+ ));
1697
+ function installPatchSettings(ctx, activation, config = DEFAULT_PATCH_SETTINGS) {
1698
+ if (typeof ctx.settings.installSection !== "function") {
1699
+ const refresh = () => {
1700
+ const values = typeof config === "object" && config !== null ? Object.fromEntries(Object.entries(config).map(([key, value]) => [key, settingValue(value)])) : config;
1701
+ const settings = decodePatchSettings(values);
1702
+ if (settings === void 0) throw new TypeError("Invalid DSH More patch configuration");
1703
+ activation.apply(settings);
1704
+ };
1705
+ ctx.on("loader/volatile-update", refresh);
1706
+ refresh();
1707
+ return;
1708
+ }
1585
1709
  let source = () => DEFAULT_PATCH_SETTINGS;
1586
1710
  ctx.settings.installSection(ctx, PATCH_SETTINGS_NAMESPACE2, PatchSettingsSchema, DEFAULT_PATCH_SETTINGS, {
1587
1711
  setSource: (next) => {
@@ -1700,13 +1824,14 @@ var inject = [
1700
1824
  "agentPresets",
1701
1825
  "settings"
1702
1826
  ];
1703
- function apply(ctx) {
1827
+ function apply(ctx, config) {
1704
1828
  const activation = new HostPatchActivation(ctx, HOST_PATCHES);
1705
1829
  ctx.effect(() => () => activation.dispose(), `${PLUGIN_NAME}: patch activation`);
1706
- installPatchSettings(ctx, activation);
1830
+ installPatchSettings(ctx, activation, config);
1707
1831
  registerPatchApi(ctx, HOST_PATCHES, randomBytes(32), (patchId) => activation.isEnabled(patchId));
1708
1832
  }
1709
1833
  export {
1834
+ PatchConfig as Config,
1710
1835
  apply,
1711
1836
  inject,
1712
1837
  name
@@ -0,0 +1,17 @@
1
+ // src/patches/projectless-tasks/host/settings.ts
2
+ import z from "@deepseek-ai/schemastery";
3
+
4
+ // src/platform/dsh/host/settings.ts
5
+ function liveSetting(schema) {
6
+ const volatile = Reflect.get(schema, "volatile");
7
+ return typeof volatile === "function" ? volatile.call(schema) : schema;
8
+ }
9
+
10
+ // src/patches/projectless-tasks/host/settings.ts
11
+ var Config = z.object({ assignments: liveSetting(z.dict(z.string()).default({})) });
12
+ function apply() {
13
+ }
14
+ export {
15
+ Config,
16
+ apply
17
+ };
@@ -1,4 +1,5 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
+ export { PatchConfig as Config } from './kernel/host/settings.js';
2
3
  export declare const name = "dsh-more";
3
4
  export declare const inject: string[];
4
- export declare function apply(ctx: Context): void;
5
+ export declare function apply(ctx: Context, config?: unknown): void;
@@ -1,9 +1,7 @@
1
1
  import type { Context as ClientContext } from '@deepseek-ai/cordis';
2
- import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
3
2
  export type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client';
4
3
  import type { PatchActivationSource } from './activation.js';
5
- type CardProps = PropsRuntime<'settings.plugin.item'>;
6
- export interface PatchConfigCardProps extends CardProps {
4
+ export interface PatchConfigCardProps {
7
5
  activation: PatchActivationSource;
8
6
  initiallyOpen?: boolean;
9
7
  }
@@ -1,5 +1,11 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
+ import z from '@deepseek-ai/schemastery';
2
3
  import type { HostPatchActivation } from './activation.js';
3
4
  export declare const PATCH_SETTINGS_NAMESPACE = "dsh-more";
5
+ export declare const PatchConfig: z<Schemastery.ObjectS<{
6
+ [k: string]: z<any>;
7
+ }>, Schemastery.ObjectT<{
8
+ [k: string]: z<any>;
9
+ }>>;
4
10
  /** Bind persisted DSH settings to live Host patch activation. */
5
- export declare function installPatchSettings(ctx: Context, activation: HostPatchActivation): void;
11
+ export declare function installPatchSettings(ctx: Context, activation: HostPatchActivation, config?: unknown): void;
@@ -0,0 +1,6 @@
1
+ import z from '@deepseek-ai/schemastery';
2
+ import type { SessionGroups } from '../groups.js';
3
+ /** Keep the existing grouping namespace independently addressable by SettingsForms. */
4
+ export declare const Config: z<SessionGroups>;
5
+ /** The settings form owns this entry; grouping consumers subscribe to its descriptor. */
6
+ export declare function apply(): void;
@@ -0,0 +1,7 @@
1
+ import { type ComponentType } from 'react';
2
+ import * as primitives from '@deepseek-ai/dsh-client-ui-primitives';
3
+ export declare const IconEditOutline16: ComponentType<primitives.IconProps>;
4
+ export declare const IconTrashOutline16: ComponentType<primitives.IconProps>;
5
+ export declare const IconDownloadOutline16: ComponentType<primitives.IconProps>;
6
+ export declare const IconWarningOutline16: ComponentType<primitives.IconProps>;
7
+ export declare const IconChevronDownOutline14: ComponentType<primitives.IconProps>;
@@ -0,0 +1,6 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import type { SettingsScope, SettingsScopeSpec } from '@deepseek-ai/dsh-client-ui-settings/client';
3
+ /** Keep feature consumers stable across the settingsScope -> configForms service rename. */
4
+ export declare function bindSettings<T>(ctx: Context, spec: SettingsScopeSpec<T>): SettingsScope<T>;
5
+ /** Each supported DSH release provides one of these settings services. */
6
+ export declare function withSettings(ctx: Context, install: (scope: Context) => void): void;
@@ -0,0 +1,13 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import type z from '@deepseek-ai/schemastery';
3
+ declare module '@deepseek-ai/cordis' {
4
+ interface Events {
5
+ 'loader/volatile-update'(paths: readonly (readonly string[])[]): void;
6
+ }
7
+ }
8
+ /** DSH 0.1.7 projects volatile Config fields; older hosts use registered sections. */
9
+ export declare function liveSetting<T>(schema: z<T>): z<T>;
10
+ /** New Config fields are stable references whose current value is read with get(). */
11
+ export declare function settingValue(value: unknown): unknown;
12
+ /** Read the public descriptor projection when the legacy settings store is absent. */
13
+ export declare function readSettings(ctx: Context, namespace: string): unknown;
package/dsh.plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-more",
3
3
  "description": "Practical patches for missing DSH Web context and history controls",
4
- "version": "0.0.8",
4
+ "version": "0.1.0",
5
5
  "entry": {
6
6
  "name": "dsh-more",
7
7
  "inject": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-more",
3
- "version": "0.0.8",
3
+ "version": "0.1.0",
4
4
  "description": "Practical patches for missing DeepSeek Harness Web context and history controls.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -37,6 +37,10 @@
37
37
  "types": "./dist/types/client/index.d.ts",
38
38
  "default": "./dist/client.js"
39
39
  },
40
+ "./session-groups": {
41
+ "types": "./dist/types/patches/projectless-tasks/host/settings.d.ts",
42
+ "default": "./dist/session-groups.js"
43
+ },
40
44
  "./package.json": "./package.json"
41
45
  },
42
46
  "files": [