dsh-more 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.js +398 -61
- package/dist/index.js +98 -29
- package/dist/types/generated/patch-catalog.d.ts +1 -1
- package/dist/types/patches/conversation-markdown-export/client/menu.d.ts +5 -0
- package/dist/types/patches/projectless-tasks/client/adapter.d.ts +3 -1
- package/dist/types/patches/projectless-tasks/client/draft.d.ts +17 -3
- package/dist/types/patches/projectless-tasks/client/group-menu.d.ts +2 -0
- package/dist/types/patches/projectless-tasks/client/groups.d.ts +21 -0
- package/dist/types/patches/projectless-tasks/groups.d.ts +6 -0
- package/dist/types/patches/projectless-tasks/host/groups.d.ts +9 -0
- package/dsh.plugin.json +1 -1
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -25,7 +25,7 @@ __export(index_exports, {
|
|
|
25
25
|
inject: () => inject
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(index_exports);
|
|
28
|
-
var
|
|
28
|
+
var import_react12 = require("react");
|
|
29
29
|
var import_react_dom = require("react-dom");
|
|
30
30
|
|
|
31
31
|
// src/generated/patch-catalog.ts
|
|
@@ -36,7 +36,7 @@ var PATCH_CATALOG = [
|
|
|
36
36
|
{ "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
37
|
{ "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" },
|
|
38
38
|
{ "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
|
-
{ "id": "projectless-tasks", "name": "\u72EC\u7ACB\u4EFB\u52A1", "description": "\u5728\u5DE5\u4F5C\u533A\u4E0B\u62C9\u6846\
|
|
39
|
+
{ "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
40
|
];
|
|
41
41
|
var DEFAULT_PATCH_SETTINGS = {
|
|
42
42
|
"message-edit": true,
|
|
@@ -678,10 +678,83 @@ function markdownFilename(title, sessionId) {
|
|
|
678
678
|
return `${safeStem(title) || fallback}.md`;
|
|
679
679
|
}
|
|
680
680
|
|
|
681
|
+
// src/patches/conversation-markdown-export/client/menu.ts
|
|
682
|
+
var MENU_ITEM_ATTRIBUTE = "data-dshmore-markdown-export";
|
|
683
|
+
var MORE_BUTTON_SELECTOR = 'button[class*="_moreButton"][aria-haspopup="menu"]';
|
|
684
|
+
function installMarkdownExportMenu(fallback, options) {
|
|
685
|
+
const header = fallback.closest("header");
|
|
686
|
+
if (header === null) return () => {
|
|
687
|
+
};
|
|
688
|
+
let item = null;
|
|
689
|
+
let source = null;
|
|
690
|
+
let frame = null;
|
|
691
|
+
const removeItem = () => {
|
|
692
|
+
item?.remove();
|
|
693
|
+
item = null;
|
|
694
|
+
source = null;
|
|
695
|
+
};
|
|
696
|
+
const sync = () => {
|
|
697
|
+
frame = null;
|
|
698
|
+
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"]');
|
|
701
|
+
const text = download?.textContent?.trim();
|
|
702
|
+
if (download === void 0 || download === null || !["\u4E0B\u8F7D Session \u65E5\u5FD7", "Download session log"].includes(text ?? "")) {
|
|
703
|
+
removeItem();
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
if (source === download && item?.isConnected === true) return;
|
|
707
|
+
removeItem();
|
|
708
|
+
const wrapper = download.parentElement;
|
|
709
|
+
if (wrapper === null || wrapper.getAttribute("role") === "menu") return;
|
|
710
|
+
const clone = wrapper.cloneNode(true);
|
|
711
|
+
if (!(clone instanceof HTMLElement)) return;
|
|
712
|
+
const button = clone.querySelector('button[role="menuitem"]');
|
|
713
|
+
if (button === null) return;
|
|
714
|
+
const label = options.busy ? "\u6B63\u5728\u5BFC\u51FA\u2026" : "\u5BFC\u51FA Markdown";
|
|
715
|
+
const walker = document.createTreeWalker(button, NodeFilter.SHOW_TEXT);
|
|
716
|
+
for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {
|
|
717
|
+
if (node.nodeValue?.trim() === text) node.nodeValue = label;
|
|
718
|
+
}
|
|
719
|
+
clone.setAttribute(MENU_ITEM_ATTRIBUTE, "");
|
|
720
|
+
button.disabled = options.busy;
|
|
721
|
+
button.setAttribute("aria-busy", String(options.busy));
|
|
722
|
+
button.setAttribute("aria-label", "\u5BFC\u51FA\u5B8C\u6574\u804A\u5929\u8BB0\u5F55\u4E3A Markdown");
|
|
723
|
+
button.addEventListener("click", (event) => {
|
|
724
|
+
event.preventDefault();
|
|
725
|
+
event.stopPropagation();
|
|
726
|
+
if (options.busy) return;
|
|
727
|
+
options.download();
|
|
728
|
+
if (trigger?.getAttribute("aria-expanded") === "true") trigger.click();
|
|
729
|
+
});
|
|
730
|
+
source = download;
|
|
731
|
+
item = clone;
|
|
732
|
+
wrapper.after(clone);
|
|
733
|
+
};
|
|
734
|
+
sync();
|
|
735
|
+
const observer = new MutationObserver(() => {
|
|
736
|
+
frame ??= window.requestAnimationFrame(sync);
|
|
737
|
+
});
|
|
738
|
+
observer.observe(header, {
|
|
739
|
+
childList: true,
|
|
740
|
+
subtree: true,
|
|
741
|
+
attributes: true,
|
|
742
|
+
attributeFilter: ["aria-label", "aria-expanded"],
|
|
743
|
+
characterData: true
|
|
744
|
+
});
|
|
745
|
+
return () => {
|
|
746
|
+
observer.disconnect();
|
|
747
|
+
if (frame !== null) window.cancelAnimationFrame(frame);
|
|
748
|
+
removeItem();
|
|
749
|
+
fallback.hidden = false;
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
|
|
681
753
|
// src/patches/conversation-markdown-export/client/index.tsx
|
|
682
754
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
683
755
|
var exportStyles = `
|
|
684
756
|
.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
|
+
.dshmore-markdown-export-button[hidden] { display: none; }
|
|
685
758
|
.dshmore-markdown-export-button:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }
|
|
686
759
|
.dshmore-markdown-export-button:disabled { color: var(--dsw-alias-label-dimmed); cursor: wait; }
|
|
687
760
|
.dshmore-markdown-export-button > span, .dshmore-markdown-export-button > svg { flex: none; }
|
|
@@ -705,15 +778,23 @@ function ConversationMarkdownExportButton(props) {
|
|
|
705
778
|
const title = props.useSessions((state) => state.byId[props.sessionId]?.displayTitle ?? String(props.sessionId));
|
|
706
779
|
const [busy, setBusy] = (0, import_react4.useState)(false);
|
|
707
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);
|
|
708
783
|
const generation = (0, import_react4.useRef)(0);
|
|
709
784
|
const activeSession = (0, import_react4.useRef)(null);
|
|
710
785
|
activeSession.current = enabled ? String(props.sessionId) : null;
|
|
711
786
|
(0, import_react4.useEffect)(() => {
|
|
712
787
|
generation.current += 1;
|
|
788
|
+
inFlight.current = false;
|
|
713
789
|
setBusy(false);
|
|
714
790
|
setError(null);
|
|
791
|
+
return () => {
|
|
792
|
+
generation.current += 1;
|
|
793
|
+
};
|
|
715
794
|
}, [enabled, props.sessionId]);
|
|
716
795
|
const download = async () => {
|
|
796
|
+
if (inFlight.current) return;
|
|
797
|
+
inFlight.current = true;
|
|
717
798
|
const requestSessionId = String(props.sessionId);
|
|
718
799
|
const requestGeneration = ++generation.current;
|
|
719
800
|
setBusy(true);
|
|
@@ -729,15 +810,25 @@ function ConversationMarkdownExportButton(props) {
|
|
|
729
810
|
} catch (caught) {
|
|
730
811
|
if (generation.current === requestGeneration && activeSession.current === requestSessionId) setError(apiErrorText(caught));
|
|
731
812
|
} finally {
|
|
732
|
-
if (generation.current === requestGeneration && activeSession.current === requestSessionId)
|
|
813
|
+
if (generation.current === requestGeneration && activeSession.current === requestSessionId) {
|
|
814
|
+
inFlight.current = false;
|
|
815
|
+
setBusy(false);
|
|
816
|
+
}
|
|
733
817
|
}
|
|
734
818
|
};
|
|
819
|
+
(0, import_react4.useEffect)(() => {
|
|
820
|
+
if (!enabled || button.current === null) return;
|
|
821
|
+
return installMarkdownExportMenu(button.current, { busy, download: () => {
|
|
822
|
+
void download();
|
|
823
|
+
} });
|
|
824
|
+
}, [enabled, props.sessionId, title, busy]);
|
|
735
825
|
if (!enabled) return null;
|
|
736
826
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
737
827
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: exportStyles }),
|
|
738
828
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
739
829
|
"button",
|
|
740
830
|
{
|
|
831
|
+
ref: button,
|
|
741
832
|
type: "button",
|
|
742
833
|
className: "dshmore-markdown-export-button",
|
|
743
834
|
disabled: busy,
|
|
@@ -1293,19 +1384,29 @@ function createTaskStarter(sessions) {
|
|
|
1293
1384
|
}
|
|
1294
1385
|
|
|
1295
1386
|
// src/patches/projectless-tasks/client/draft.ts
|
|
1296
|
-
function transferDraft(source, target) {
|
|
1387
|
+
function transferDraft(source, target, rebind) {
|
|
1297
1388
|
const from = source.state.getSnapshot();
|
|
1298
1389
|
const to = target.state.getSnapshot();
|
|
1299
1390
|
if (from.phase !== "plain" || to.phase !== "plain") throw new Error("\u8F93\u5165\u6B63\u5728\u5904\u7406\u4E2D\uFF0C\u8BF7\u7A0D\u540E\u5207\u6362\u4EFB\u52A1\u76EE\u5F55\u3002");
|
|
1300
1391
|
if (from.draft !== "" && to.draft !== "" && from.draft !== to.draft) {
|
|
1301
1392
|
throw new Error("\u76EE\u6807\u4EFB\u52A1\u5DF2\u6709\u5176\u4ED6\u8349\u7A3F\uFF0C\u672C\u6B21\u5207\u6362\u5DF2\u505C\u6B62\uFF0C\u539F\u8349\u7A3F\u5DF2\u4FDD\u7559\u3002");
|
|
1302
1393
|
}
|
|
1303
|
-
|
|
1394
|
+
const ids = from.attachmentIds ?? from.imageIds;
|
|
1395
|
+
const add = from.attachmentIds === void 0 ? target.addImages : target.addAttachments;
|
|
1396
|
+
const remove = from.attachmentIds === void 0 ? source.removeImage : source.removeAttachment;
|
|
1397
|
+
if (!Array.isArray(ids) || typeof add !== "function" || typeof remove !== "function") {
|
|
1398
|
+
throw new Error("\u5F53\u524D DSH \u7248\u672C\u7684\u8349\u7A3F\u63A5\u53E3\u4E0D\u517C\u5BB9\uFF0C\u539F\u8349\u7A3F\u5DF2\u4FDD\u7559\u3002");
|
|
1399
|
+
}
|
|
1400
|
+
if (ids.length > 0 && !add.call(target, [...ids])) {
|
|
1304
1401
|
throw new Error("\u6682\u65F6\u65E0\u6CD5\u8F6C\u79FB\u56FE\u7247\uFF0C\u539F\u8349\u7A3F\u5DF2\u4FDD\u7559\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
|
|
1305
1402
|
}
|
|
1403
|
+
if (ids.length > 0 && from.attachmentIds !== void 0) {
|
|
1404
|
+
if (rebind === void 0) throw new Error("\u65E0\u6CD5\u8F6C\u79FB\u9644\u4EF6\u5F52\u5C5E\uFF0C\u539F\u8349\u7A3F\u5DF2\u4FDD\u7559\u3002");
|
|
1405
|
+
rebind(ids);
|
|
1406
|
+
}
|
|
1306
1407
|
if (from.draft !== "") target.setDraft(from.draft);
|
|
1307
1408
|
if (from.draft !== "") source.setDraft("");
|
|
1308
|
-
|
|
1409
|
+
ids.forEach((id) => remove.call(source, id));
|
|
1309
1410
|
}
|
|
1310
1411
|
function transferBeforeOpen(ctx, sourceId, targetId) {
|
|
1311
1412
|
const value = ctx.sessions;
|
|
@@ -1320,7 +1421,12 @@ function transferBeforeOpen(ctx, sourceId, targetId) {
|
|
|
1320
1421
|
const source = sessions.scope(sourceId);
|
|
1321
1422
|
const target = sessions.scope(targetId);
|
|
1322
1423
|
if (source === void 0 || target === void 0) throw new Error("\u4EFB\u52A1\u5C1A\u672A\u51C6\u5907\u597D\uFF0C\u539F\u8349\u7A3F\u5DF2\u4FDD\u7559\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
|
|
1323
|
-
|
|
1424
|
+
const conversation = ctx.conversation;
|
|
1425
|
+
transferDraft(
|
|
1426
|
+
conversation.input.for(source),
|
|
1427
|
+
conversation.input.for(target),
|
|
1428
|
+
typeof conversation.rebindDraftFiles === "function" ? (ids) => conversation.rebindDraftFiles(targetId, ids) : void 0
|
|
1429
|
+
);
|
|
1324
1430
|
return true;
|
|
1325
1431
|
}
|
|
1326
1432
|
|
|
@@ -1455,7 +1561,12 @@ function unlockComposer(owner, independent, block) {
|
|
|
1455
1561
|
const { disabled: _disabled, onRequestWorkspace: _request, workspacePickerOpen: _picker, placeholder: _placeholder, ...rest } = owner;
|
|
1456
1562
|
return { ...rest, ...block === void 0 ? {} : { blocked: block, placeholder: block.reason } };
|
|
1457
1563
|
}
|
|
1458
|
-
|
|
1564
|
+
var CONVERSATION_SLOTS = ["conversation", "main.conversation"];
|
|
1565
|
+
function conversationSlot(name) {
|
|
1566
|
+
return name;
|
|
1567
|
+
}
|
|
1568
|
+
function installConversationAdapter(ctx, activation, name = "conversation") {
|
|
1569
|
+
const slot = conversationSlot(name);
|
|
1459
1570
|
const wrapped = /* @__PURE__ */ new Map();
|
|
1460
1571
|
let live = true;
|
|
1461
1572
|
const listeners = /* @__PURE__ */ new Set();
|
|
@@ -1466,7 +1577,7 @@ function installConversationAdapter(ctx, activation) {
|
|
|
1466
1577
|
};
|
|
1467
1578
|
};
|
|
1468
1579
|
const sync = () => {
|
|
1469
|
-
for (const entry of ctx.slots.entries(
|
|
1580
|
+
for (const entry of ctx.slots.entries(slot)) {
|
|
1470
1581
|
let ProjectlessConversation2 = function(props) {
|
|
1471
1582
|
const active = (0, import_react8.useSyncExternalStore)(subscribeLifetime, () => live);
|
|
1472
1583
|
const settings = (0, import_react8.useSyncExternalStore)(activation.subscribe, activation.getSnapshot);
|
|
@@ -1499,14 +1610,14 @@ function installConversationAdapter(ctx, activation) {
|
|
|
1499
1610
|
if (starter.current === operation) setBusy(false);
|
|
1500
1611
|
});
|
|
1501
1612
|
};
|
|
1502
|
-
const renderSlot = (
|
|
1503
|
-
if (
|
|
1613
|
+
const renderSlot = (name2, owner, options) => {
|
|
1614
|
+
if (name2 === "conversation.composer.bar" && isComposerOwner(owner)) {
|
|
1504
1615
|
return props.renderSlot("conversation.composer.bar", unlockComposer(owner, independent, block), options);
|
|
1505
1616
|
}
|
|
1506
|
-
if (enabled &&
|
|
1617
|
+
if (enabled && name2 === "conversation.hero.workspace" && isWorkspaceOwner(owner)) {
|
|
1507
1618
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(WorkspaceChoice, { owner, state: { independent, busy, chooseIndependent }, error, children: props.renderSlot("conversation.hero.workspace", owner, options) });
|
|
1508
1619
|
}
|
|
1509
|
-
return props.renderSlot(
|
|
1620
|
+
return props.renderSlot(name2, owner, options);
|
|
1510
1621
|
};
|
|
1511
1622
|
return (0, import_react8.createElement)(original, { ...props, renderSlot });
|
|
1512
1623
|
};
|
|
@@ -1517,10 +1628,10 @@ function installConversationAdapter(ctx, activation) {
|
|
|
1517
1628
|
entry.component = ProjectlessConversation2;
|
|
1518
1629
|
}
|
|
1519
1630
|
};
|
|
1520
|
-
const unsubscribe = ctx.slots.subscribe(
|
|
1631
|
+
const unsubscribe = ctx.slots.subscribe(slot, sync);
|
|
1521
1632
|
sync();
|
|
1522
|
-
const priorities = ctx.slots.entries(
|
|
1523
|
-
const fallback = ctx.slots.register({ name:
|
|
1633
|
+
const priorities = ctx.slots.entries(slot).map((entry) => entry.options.priority ?? 0);
|
|
1634
|
+
const fallback = ctx.slots.register({ name: slot, priority: Math.max(0, ...priorities) + 1 }, () => null);
|
|
1524
1635
|
return () => {
|
|
1525
1636
|
live = false;
|
|
1526
1637
|
listeners.forEach((listener) => listener());
|
|
@@ -1647,13 +1758,239 @@ function installNewSessionNavigation(ctx, activation) {
|
|
|
1647
1758
|
});
|
|
1648
1759
|
}
|
|
1649
1760
|
|
|
1761
|
+
// src/patches/projectless-tasks/client/groups.tsx
|
|
1762
|
+
var import_react9 = require("react");
|
|
1763
|
+
var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
1764
|
+
|
|
1765
|
+
// src/patches/projectless-tasks/groups.ts
|
|
1766
|
+
var SESSION_GROUPS_NAMESPACE = "dsh-more-session-groups";
|
|
1767
|
+
var EMPTY_GROUPS = { assignments: {} };
|
|
1768
|
+
function decodeSessionGroups(value) {
|
|
1769
|
+
if (typeof value !== "object" || value === null || !("assignments" in value)) return void 0;
|
|
1770
|
+
const assignments = value.assignments;
|
|
1771
|
+
if (typeof assignments !== "object" || assignments === null || Array.isArray(assignments) || !Object.values(assignments).every((id) => typeof id === "string")) return void 0;
|
|
1772
|
+
return { assignments };
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
// src/patches/projectless-tasks/client/group-menu.ts
|
|
1776
|
+
var ATTRIBUTE = "data-dshmore-session-move";
|
|
1777
|
+
function installMoveMenu(onMove) {
|
|
1778
|
+
const items = /* @__PURE__ */ new Map();
|
|
1779
|
+
let frame;
|
|
1780
|
+
const sync = () => {
|
|
1781
|
+
frame = void 0;
|
|
1782
|
+
for (const [source, item] of items) {
|
|
1783
|
+
if (!source.isConnected || !item.isConnected) {
|
|
1784
|
+
item.remove();
|
|
1785
|
+
items.delete(source);
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
for (const source of document.querySelectorAll('button[role="menuitem"]')) {
|
|
1789
|
+
const text = source.textContent?.trim();
|
|
1790
|
+
if (text !== "\u5F52\u6863\u4F1A\u8BDD" && text !== "Archive session" || items.has(source)) continue;
|
|
1791
|
+
if (document.querySelector('[class*="_sessionRow"][class*="_menuOpen"]') === null) continue;
|
|
1792
|
+
const wrapper = source.parentElement;
|
|
1793
|
+
if (wrapper === null) continue;
|
|
1794
|
+
const item = wrapper.cloneNode(true);
|
|
1795
|
+
const button = item.querySelector('button[role="menuitem"]');
|
|
1796
|
+
if (button === null) continue;
|
|
1797
|
+
const label = text === "\u5F52\u6863\u4F1A\u8BDD" ? "\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A\u2026" : "Move to workspace\u2026";
|
|
1798
|
+
const walker = document.createTreeWalker(button, NodeFilter.SHOW_TEXT);
|
|
1799
|
+
for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {
|
|
1800
|
+
if (node.nodeValue?.trim() === text) node.nodeValue = node.nodeValue.replace(text, label);
|
|
1801
|
+
}
|
|
1802
|
+
item.setAttribute(ATTRIBUTE, "");
|
|
1803
|
+
button.setAttribute("aria-label", label);
|
|
1804
|
+
button.addEventListener("click", (event) => {
|
|
1805
|
+
event.preventDefault();
|
|
1806
|
+
event.stopImmediatePropagation();
|
|
1807
|
+
onMove(source);
|
|
1808
|
+
});
|
|
1809
|
+
items.set(source, item);
|
|
1810
|
+
wrapper.before(item);
|
|
1811
|
+
}
|
|
1812
|
+
};
|
|
1813
|
+
const observer = new MutationObserver(() => {
|
|
1814
|
+
frame ??= requestAnimationFrame(sync);
|
|
1815
|
+
});
|
|
1816
|
+
sync();
|
|
1817
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
1818
|
+
return () => {
|
|
1819
|
+
observer.disconnect();
|
|
1820
|
+
if (frame !== void 0) cancelAnimationFrame(frame);
|
|
1821
|
+
items.forEach((item) => item.remove());
|
|
1822
|
+
items.clear();
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
// src/patches/projectless-tasks/client/groups.tsx
|
|
1827
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1828
|
+
function projectSessionGroups(workspaces, sessions, groups) {
|
|
1829
|
+
const owned = new Set(workspaces.items.flatMap((item) => item.sessionIds));
|
|
1830
|
+
const items = workspaces.items.map((workspace) => {
|
|
1831
|
+
const added = Object.entries(groups.assignments).flatMap(([id, target]) => target === workspace.workspaceId && !owned.has(id) && sessions.byId[id]?.origin !== "subagent" && sessions.byId[id] !== void 0 ? [id] : []);
|
|
1832
|
+
return added.length === 0 ? workspace : { ...workspace, sessionIds: [...added, ...workspace.sessionIds] };
|
|
1833
|
+
});
|
|
1834
|
+
return items.every((item, index) => item === workspaces.items[index]) ? workspaces : { ...workspaces, items };
|
|
1835
|
+
}
|
|
1836
|
+
var SIDEBAR_SLOT = "sidebar.workspaces";
|
|
1837
|
+
var ALWAYS_LIVE = { subscribe: () => () => {
|
|
1838
|
+
}, getSnapshot: () => true };
|
|
1839
|
+
function extendGroupedSidebar(original, activation, source, lifetime = ALWAYS_LIVE) {
|
|
1840
|
+
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);
|
|
1844
|
+
const native = props.useWorkspaces((value) => value);
|
|
1845
|
+
const sessions = props.useSessions((value) => value);
|
|
1846
|
+
const active = (0, import_react9.useSyncExternalStore)(lifetime.subscribe, lifetime.getSnapshot);
|
|
1847
|
+
const enabled = active && settings[PROJECTLESS_TASKS_PATCH_ID];
|
|
1848
|
+
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)(() => {
|
|
1858
|
+
live.current = true;
|
|
1859
|
+
return () => {
|
|
1860
|
+
live.current = false;
|
|
1861
|
+
};
|
|
1862
|
+
}, []);
|
|
1863
|
+
(0, import_react9.useEffect)(() => {
|
|
1864
|
+
if (!enabled) {
|
|
1865
|
+
setPending(void 0);
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
return installMoveMenu((archive) => {
|
|
1869
|
+
intent.current = true;
|
|
1870
|
+
try {
|
|
1871
|
+
archive.click();
|
|
1872
|
+
} finally {
|
|
1873
|
+
intent.current = false;
|
|
1874
|
+
}
|
|
1875
|
+
});
|
|
1876
|
+
}, [enabled]);
|
|
1877
|
+
const archiveSession = (id) => {
|
|
1878
|
+
if (!intent.current) return props.archiveSession(id);
|
|
1879
|
+
intent.current = false;
|
|
1880
|
+
setPending(id);
|
|
1881
|
+
setDestination(groups.assignments[id] ?? "");
|
|
1882
|
+
setError(void 0);
|
|
1883
|
+
return Promise.resolve();
|
|
1884
|
+
};
|
|
1885
|
+
const useWorkspaces = (select) => select(display);
|
|
1886
|
+
const close = () => {
|
|
1887
|
+
if (!inFlight.current) setPending(void 0);
|
|
1888
|
+
};
|
|
1889
|
+
const move = async () => {
|
|
1890
|
+
if (pending === void 0 || inFlight.current) return;
|
|
1891
|
+
inFlight.current = true;
|
|
1892
|
+
setBusy(true);
|
|
1893
|
+
setError(void 0);
|
|
1894
|
+
try {
|
|
1895
|
+
await callPatchApi(PROJECTLESS_TASKS_PATCH_ID, "move", { sessionId: pending, workspaceId: destination || null });
|
|
1896
|
+
if (live.current) setPending(void 0);
|
|
1897
|
+
} catch (reason) {
|
|
1898
|
+
if (live.current) setError(apiErrorText(reason));
|
|
1899
|
+
} finally {
|
|
1900
|
+
inFlight.current = false;
|
|
1901
|
+
if (live.current) setBusy(false);
|
|
1902
|
+
}
|
|
1903
|
+
};
|
|
1904
|
+
const groupedNatively = pending !== void 0 && native.items.some((item) => item.sessionIds.includes(pending));
|
|
1905
|
+
const subagent = pending !== void 0 && sessions.byId[pending]?.origin === "subagent";
|
|
1906
|
+
const selectedMissing = destination !== "" && !native.items.some((item) => item.workspaceId === destination);
|
|
1907
|
+
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)(
|
|
1911
|
+
import_dsh_client_ui_primitives6.Modal,
|
|
1912
|
+
{
|
|
1913
|
+
open: pending !== void 0,
|
|
1914
|
+
onClose: close,
|
|
1915
|
+
title: "\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A",
|
|
1916
|
+
closeLabel: "\u5173\u95ED",
|
|
1917
|
+
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" })
|
|
1921
|
+
] }),
|
|
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: [
|
|
1925
|
+
"\u76EE\u6807\u5DE5\u4F5C\u533A",
|
|
1926
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1927
|
+
"select",
|
|
1928
|
+
{
|
|
1929
|
+
"aria-label": "\u76EE\u6807\u5DE5\u4F5C\u533A",
|
|
1930
|
+
value: destination,
|
|
1931
|
+
disabled: busy || unavailable !== void 0 && !selectedMissing,
|
|
1932
|
+
onChange: (event) => setDestination(event.target.value),
|
|
1933
|
+
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
|
+
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))
|
|
1937
|
+
]
|
|
1938
|
+
}
|
|
1939
|
+
)
|
|
1940
|
+
] }),
|
|
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 })
|
|
1942
|
+
] })
|
|
1943
|
+
}
|
|
1944
|
+
)
|
|
1945
|
+
] });
|
|
1946
|
+
};
|
|
1947
|
+
}
|
|
1948
|
+
function installSessionGrouping(ctx, activation) {
|
|
1949
|
+
const source = ctx.settingsScope.bind({ namespace: SESSION_GROUPS_NAMESPACE, decode: decodeSessionGroups });
|
|
1950
|
+
ctx.slots.inject(SIDEBAR_SLOT, () => {
|
|
1951
|
+
let live = true;
|
|
1952
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
1953
|
+
const lifetime = { getSnapshot: () => live, subscribe: (fn) => {
|
|
1954
|
+
listeners.add(fn);
|
|
1955
|
+
return () => {
|
|
1956
|
+
listeners.delete(fn);
|
|
1957
|
+
};
|
|
1958
|
+
} };
|
|
1959
|
+
const wrapped = /* @__PURE__ */ new Map();
|
|
1960
|
+
const sync = () => {
|
|
1961
|
+
for (const entry of ctx.slots.entries(SIDEBAR_SLOT)) {
|
|
1962
|
+
if (wrapped.has(entry) || entry.children?.["sidebar.workspaces.directoryFlow"] === void 0 || typeof entry.component !== "function") continue;
|
|
1963
|
+
const original = entry.component;
|
|
1964
|
+
const component = extendGroupedSidebar(original, activation, source, lifetime);
|
|
1965
|
+
wrapped.set(entry, { original, component });
|
|
1966
|
+
entry.component = component;
|
|
1967
|
+
}
|
|
1968
|
+
};
|
|
1969
|
+
const unsubscribe = ctx.slots.subscribe(SIDEBAR_SLOT, sync);
|
|
1970
|
+
sync();
|
|
1971
|
+
const priorities = ctx.slots.entries(SIDEBAR_SLOT).map((entry) => entry.options.priority ?? 0);
|
|
1972
|
+
const fallback = ctx.slots.register({ name: SIDEBAR_SLOT, priority: Math.max(0, ...priorities) + 1 }, () => null);
|
|
1973
|
+
return () => {
|
|
1974
|
+
live = false;
|
|
1975
|
+
listeners.forEach((listener) => listener());
|
|
1976
|
+
unsubscribe();
|
|
1977
|
+
for (const [entry, patch] of wrapped) if (entry.component === patch.component) entry.component = patch.original;
|
|
1978
|
+
wrapped.clear();
|
|
1979
|
+
fallback();
|
|
1980
|
+
};
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1650
1984
|
// src/patches/projectless-tasks/client/index.tsx
|
|
1651
1985
|
var clientPatch5 = {
|
|
1652
1986
|
id: PROJECTLESS_TASKS_PATCH_ID,
|
|
1653
1987
|
install: (ctx, activation) => {
|
|
1988
|
+
installSessionGrouping(ctx, activation);
|
|
1654
1989
|
ctx.inject(["conversation", "uiWorkspace"], (scope) => {
|
|
1655
1990
|
scope.effect(() => installNewSessionNavigation(scope, activation));
|
|
1656
|
-
|
|
1991
|
+
for (const name of CONVERSATION_SLOTS) {
|
|
1992
|
+
scope.slots.inject(conversationSlot(name), () => installConversationAdapter(scope, activation, name));
|
|
1993
|
+
}
|
|
1657
1994
|
scope.slots.inject("conversation.hero.workspace", () => installPickerAdapter(scope));
|
|
1658
1995
|
});
|
|
1659
1996
|
}
|
|
@@ -1684,19 +2021,19 @@ var ClientPatchActivation = class {
|
|
|
1684
2021
|
};
|
|
1685
2022
|
|
|
1686
2023
|
// src/kernel/client/config-card.tsx
|
|
1687
|
-
var
|
|
1688
|
-
var
|
|
1689
|
-
var
|
|
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");
|
|
1690
2027
|
function PatchConfigCard({ activation, initiallyOpen = false }) {
|
|
1691
|
-
const scope = (0,
|
|
2028
|
+
const scope = (0, import_react10.useSyncExternalStore)(
|
|
1692
2029
|
activation.subscribe,
|
|
1693
2030
|
activation.getSettingsSnapshot,
|
|
1694
2031
|
activation.getSettingsSnapshot
|
|
1695
2032
|
);
|
|
1696
2033
|
const settings = activation.getSnapshot();
|
|
1697
|
-
const [open, setOpen] = (0,
|
|
1698
|
-
const [busy, setBusy] = (0,
|
|
1699
|
-
const [error, setError] = (0,
|
|
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);
|
|
1700
2037
|
if (scope.status === "unavailable") return null;
|
|
1701
2038
|
const update = async (id, enabled) => {
|
|
1702
2039
|
setBusy((current) => /* @__PURE__ */ new Set([...current, id]));
|
|
@@ -1713,9 +2050,9 @@ function PatchConfigCard({ activation, initiallyOpen = false }) {
|
|
|
1713
2050
|
});
|
|
1714
2051
|
}
|
|
1715
2052
|
};
|
|
1716
|
-
return /* @__PURE__ */ (0,
|
|
1717
|
-
/* @__PURE__ */ (0,
|
|
1718
|
-
/* @__PURE__ */ (0,
|
|
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)(
|
|
1719
2056
|
"button",
|
|
1720
2057
|
{
|
|
1721
2058
|
type: "button",
|
|
@@ -1726,23 +2063,23 @@ function PatchConfigCard({ activation, initiallyOpen = false }) {
|
|
|
1726
2063
|
setOpen((current) => !current);
|
|
1727
2064
|
},
|
|
1728
2065
|
children: [
|
|
1729
|
-
/* @__PURE__ */ (0,
|
|
1730
|
-
/* @__PURE__ */ (0,
|
|
1731
|
-
/* @__PURE__ */ (0,
|
|
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" })
|
|
1732
2069
|
] }),
|
|
1733
|
-
/* @__PURE__ */ (0,
|
|
2070
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_dsh_client_ui_primitives7.IconChevronDownOutline14, { className: `dshmore-config-chevron${open ? " dshmore-config-chevron-open" : ""}` })
|
|
1734
2071
|
]
|
|
1735
2072
|
}
|
|
1736
2073
|
),
|
|
1737
|
-
open && /* @__PURE__ */ (0,
|
|
1738
|
-
/* @__PURE__ */ (0,
|
|
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) => {
|
|
1739
2076
|
const waiting = busy.has(patch.id);
|
|
1740
|
-
return /* @__PURE__ */ (0,
|
|
1741
|
-
/* @__PURE__ */ (0,
|
|
1742
|
-
/* @__PURE__ */ (0,
|
|
1743
|
-
/* @__PURE__ */ (0,
|
|
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 })
|
|
1744
2081
|
] }),
|
|
1745
|
-
/* @__PURE__ */ (0,
|
|
2082
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1746
2083
|
"input",
|
|
1747
2084
|
{
|
|
1748
2085
|
type: "checkbox",
|
|
@@ -1757,9 +2094,9 @@ function PatchConfigCard({ activation, initiallyOpen = false }) {
|
|
|
1757
2094
|
)
|
|
1758
2095
|
] }, patch.id);
|
|
1759
2096
|
}) }),
|
|
1760
|
-
scope.status === "loading" && /* @__PURE__ */ (0,
|
|
1761
|
-
scope.status === "ready" && !scope.writable && /* @__PURE__ */ (0,
|
|
1762
|
-
error !== null && /* @__PURE__ */ (0,
|
|
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 })
|
|
1763
2100
|
] })
|
|
1764
2101
|
] });
|
|
1765
2102
|
}
|
|
@@ -1768,14 +2105,14 @@ function installPatchConfigCard(ctx, activation) {
|
|
|
1768
2105
|
name: "settings.plugin.item",
|
|
1769
2106
|
key: PATCH_SETTINGS_NAMESPACE,
|
|
1770
2107
|
priority: 90
|
|
1771
|
-
}, (props) => /* @__PURE__ */ (0,
|
|
2108
|
+
}, (props) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PatchConfigCard, { ...props, activation })));
|
|
1772
2109
|
}
|
|
1773
2110
|
|
|
1774
2111
|
// src/kernel/message-visibility.ts
|
|
1775
2112
|
var MESSAGE_VISIBILITY_PROJECTION_KEY = "dshMoreMessageDelete";
|
|
1776
2113
|
|
|
1777
2114
|
// src/platform/dsh/client/message-targets.tsx
|
|
1778
|
-
var
|
|
2115
|
+
var import_react11 = require("react");
|
|
1779
2116
|
|
|
1780
2117
|
// src/platform/dsh/client/message-content.ts
|
|
1781
2118
|
function contentText(content) {
|
|
@@ -1913,17 +2250,17 @@ function trajectorySourceSeq(row) {
|
|
|
1913
2250
|
return Number.isSafeInteger(seq) && seq >= 0 ? seq : void 0;
|
|
1914
2251
|
}
|
|
1915
2252
|
function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = true) {
|
|
1916
|
-
const selector = (0,
|
|
2253
|
+
const selector = (0, import_react11.useMemo)(() => createMessageSurfaceSelector(active), [active, props.sessionId]);
|
|
1917
2254
|
const surface = props.useChat(selector);
|
|
1918
|
-
const surfaceRef = (0,
|
|
1919
|
-
const hiddenSeqsRef = (0,
|
|
1920
|
-
const hiddenTrajectoryKeysRef = (0,
|
|
2255
|
+
const surfaceRef = (0, import_react11.useRef)(surface);
|
|
2256
|
+
const hiddenSeqsRef = (0, import_react11.useRef)(hiddenSeqs);
|
|
2257
|
+
const hiddenTrajectoryKeysRef = (0, import_react11.useRef)(hiddenTrajectoryKeys);
|
|
1921
2258
|
surfaceRef.current = surface;
|
|
1922
2259
|
hiddenSeqsRef.current = hiddenSeqs;
|
|
1923
2260
|
hiddenTrajectoryKeysRef.current = hiddenTrajectoryKeys;
|
|
1924
|
-
const [targets, setTargets] = (0,
|
|
1925
|
-
const requestFullScanRef = (0,
|
|
1926
|
-
(0,
|
|
2261
|
+
const [targets, setTargets] = (0, import_react11.useState)([]);
|
|
2262
|
+
const requestFullScanRef = (0, import_react11.useRef)(null);
|
|
2263
|
+
(0, import_react11.useLayoutEffect)(() => {
|
|
1927
2264
|
if (!active) {
|
|
1928
2265
|
setTargets((current) => current.length === 0 ? current : []);
|
|
1929
2266
|
return;
|
|
@@ -2047,21 +2384,21 @@ function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = tru
|
|
|
2047
2384
|
for (const host of document.querySelectorAll("[data-dshmore-message-actions]")) host.remove();
|
|
2048
2385
|
};
|
|
2049
2386
|
}, [active, props.sessionId]);
|
|
2050
|
-
(0,
|
|
2387
|
+
(0, import_react11.useLayoutEffect)(() => {
|
|
2051
2388
|
requestFullScanRef.current?.();
|
|
2052
2389
|
}, [surface, hiddenSeqs, hiddenTrajectoryKeys]);
|
|
2053
2390
|
return targets;
|
|
2054
2391
|
}
|
|
2055
2392
|
|
|
2056
2393
|
// src/client/index.tsx
|
|
2057
|
-
var
|
|
2394
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2058
2395
|
var inject = ["slots", "sessions", "workspaces", "settingsScope"];
|
|
2059
2396
|
function MessageActionPatchController({ patch, props, targets, enabled }) {
|
|
2060
2397
|
const actions = patch.useActions(props, enabled);
|
|
2061
2398
|
const style = { "--dshmore-action-order": patch.order };
|
|
2062
|
-
return /* @__PURE__ */ (0,
|
|
2399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2063
2400
|
enabled && targets.map((target) => (0, import_react_dom.createPortal)(
|
|
2064
|
-
/* @__PURE__ */ (0,
|
|
2401
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "dshmore-action-contribution", style, children: actions.renderAction(target) }),
|
|
2065
2402
|
target.host,
|
|
2066
2403
|
`${patch.id}:${target.key}`
|
|
2067
2404
|
)),
|
|
@@ -2069,15 +2406,15 @@ function MessageActionPatchController({ patch, props, targets, enabled }) {
|
|
|
2069
2406
|
] });
|
|
2070
2407
|
}
|
|
2071
2408
|
function MessageActionsController(props) {
|
|
2072
|
-
const settings = (0,
|
|
2409
|
+
const settings = (0, import_react12.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot);
|
|
2073
2410
|
const projected = props.useProjection(MESSAGE_VISIBILITY_PROJECTION_KEY);
|
|
2074
|
-
const hiddenSeqs = (0,
|
|
2075
|
-
const hiddenTrajectoryKeys = (0,
|
|
2411
|
+
const hiddenSeqs = (0, import_react12.useMemo)(() => new Set(projected?.deletedSeqs ?? []), [projected]);
|
|
2412
|
+
const hiddenTrajectoryKeys = (0, import_react12.useMemo)(() => new Set(projected?.hiddenTrajectoryKeys ?? []), [projected]);
|
|
2076
2413
|
const messageActionsEnabled = MESSAGE_ACTION_PATCHES.some((patch) => settings[patch.id]);
|
|
2077
2414
|
const targets = useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, messageActionsEnabled);
|
|
2078
|
-
return /* @__PURE__ */ (0,
|
|
2079
|
-
/* @__PURE__ */ (0,
|
|
2080
|
-
MESSAGE_ACTION_PATCHES.map((patch) => /* @__PURE__ */ (0,
|
|
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)(
|
|
2081
2418
|
MessageActionPatchController,
|
|
2082
2419
|
{
|
|
2083
2420
|
patch,
|
|
@@ -2100,7 +2437,7 @@ function apply(ctx) {
|
|
|
2100
2437
|
name: "conversation.session.header.utilities",
|
|
2101
2438
|
id: `${PLUGIN_NAME}-message-actions`,
|
|
2102
2439
|
order: 90
|
|
2103
|
-
}, (props) => /* @__PURE__ */ (0,
|
|
2440
|
+
}, (props) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MessageActionsController, { ...props, ctx, activation })));
|
|
2104
2441
|
for (const patch of CLIENT_PATCHES) patch.install(ctx, activation);
|
|
2105
2442
|
}
|
|
2106
2443
|
return module.exports; } });
|
package/dist/index.js
CHANGED
|
@@ -519,10 +519,11 @@ function buildCleanSeed(source, selection) {
|
|
|
519
519
|
}
|
|
520
520
|
if (event.type === "assistant/message") {
|
|
521
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,
|
|
522
525
|
turn,
|
|
523
|
-
step
|
|
524
|
-
message: event.data.message,
|
|
525
|
-
...event.data.usage === void 0 ? {} : { usage: event.data.usage }
|
|
526
|
+
step
|
|
526
527
|
}, { surfaceOp: "append" });
|
|
527
528
|
assistantSeen = true;
|
|
528
529
|
for (const call of event.data.message.content) {
|
|
@@ -664,15 +665,13 @@ var SESSION_DELETE_PATCH_ID = "session-delete";
|
|
|
664
665
|
// src/patches/session-delete/host/live-session-handles.ts
|
|
665
666
|
var TRACKER = /* @__PURE__ */ Symbol.for("dsh-more.session-delete.live-session-handles");
|
|
666
667
|
function trackedHandle(tracker, handle) {
|
|
667
|
-
let
|
|
668
|
+
let disposal;
|
|
668
669
|
const wrapped = {
|
|
669
670
|
agent: handle.agent,
|
|
670
|
-
dispose: async () => {
|
|
671
|
-
if (disposed) return;
|
|
672
|
-
disposed = true;
|
|
673
|
-
if (tracker.handles.get(handle.agent.id) === wrapped) tracker.handles.delete(handle.agent.id);
|
|
671
|
+
dispose: () => disposal ??= Promise.resolve().then(async () => {
|
|
674
672
|
await handle.dispose();
|
|
675
|
-
|
|
673
|
+
if (tracker.handles.get(handle.agent.id) === wrapped) tracker.handles.delete(handle.agent.id);
|
|
674
|
+
})
|
|
676
675
|
};
|
|
677
676
|
tracker.handles.set(handle.agent.id, wrapped);
|
|
678
677
|
return wrapped;
|
|
@@ -682,26 +681,37 @@ function installLiveSessionHandleTracker(ctx) {
|
|
|
682
681
|
const existing = registry[TRACKER];
|
|
683
682
|
if (existing !== void 0) {
|
|
684
683
|
existing.references += 1;
|
|
685
|
-
return ()
|
|
686
|
-
existing.references -= 1;
|
|
687
|
-
};
|
|
684
|
+
return releaseTracker(registry, existing);
|
|
688
685
|
}
|
|
689
686
|
const originalCreate = registry.create;
|
|
690
687
|
const originalResume = registry.resume;
|
|
691
688
|
const tracker = { handles: /* @__PURE__ */ new Map() };
|
|
692
689
|
tracker.originalCreate = originalCreate;
|
|
693
690
|
tracker.originalResume = originalResume;
|
|
691
|
+
tracker.createDescriptor = Object.getOwnPropertyDescriptor(registry, "create");
|
|
692
|
+
tracker.resumeDescriptor = Object.getOwnPropertyDescriptor(registry, "resume");
|
|
694
693
|
tracker.wrappedCreate = async (options) => trackedHandle(tracker, await originalCreate.call(registry, options));
|
|
695
694
|
tracker.wrappedResume = async (options) => trackedHandle(tracker, await originalResume.call(registry, options));
|
|
696
695
|
tracker.references = 1;
|
|
697
696
|
registry[TRACKER] = tracker;
|
|
698
697
|
registry.create = tracker.wrappedCreate;
|
|
699
698
|
registry.resume = tracker.wrappedResume;
|
|
699
|
+
return releaseTracker(registry, tracker);
|
|
700
|
+
}
|
|
701
|
+
function releaseTracker(registry, tracker) {
|
|
702
|
+
let released = false;
|
|
700
703
|
return () => {
|
|
704
|
+
if (released) return;
|
|
705
|
+
released = true;
|
|
701
706
|
tracker.references -= 1;
|
|
702
707
|
if (tracker.references > 0 || registry[TRACKER] !== tracker) return;
|
|
703
|
-
|
|
704
|
-
|
|
708
|
+
const restore = (key, installed, descriptor) => {
|
|
709
|
+
if (Object.getOwnPropertyDescriptor(registry, key)?.value !== installed) return;
|
|
710
|
+
if (descriptor === void 0) Reflect.deleteProperty(registry, key);
|
|
711
|
+
else Object.defineProperty(registry, key, descriptor);
|
|
712
|
+
};
|
|
713
|
+
restore("create", tracker.wrappedCreate, tracker.createDescriptor);
|
|
714
|
+
restore("resume", tracker.wrappedResume, tracker.resumeDescriptor);
|
|
705
715
|
delete registry[TRACKER];
|
|
706
716
|
};
|
|
707
717
|
}
|
|
@@ -725,12 +735,16 @@ function detachInternal(registry, sessionId, label) {
|
|
|
725
735
|
async function unloadLiveSession(ctx, sessionId) {
|
|
726
736
|
const agent = ctx.agents.get(sessionId);
|
|
727
737
|
const session = ctx.sessions.get(sessionId);
|
|
738
|
+
const handle = getLiveSessionHandle(ctx, sessionId);
|
|
739
|
+
const ownsWriter = "open" in ctx.sessionPersistence && typeof ctx.sessionPersistence.open === "function";
|
|
740
|
+
if (session !== void 0 && ownsWriter && handle === void 0) {
|
|
741
|
+
throw new DshMoreError("session-not-live", "\u65E0\u6CD5\u5B89\u5168\u5378\u8F7D\u8FD9\u6761\u5DF2\u52A0\u8F7D\u7684\u4F1A\u8BDD\uFF0C\u8BF7\u91CD\u542F DSH \u540E\u518D\u5220\u9664\u3002", 409);
|
|
742
|
+
}
|
|
728
743
|
if (agent !== void 0) {
|
|
729
744
|
agent.cancel({ kind: "disposed" });
|
|
730
745
|
await agent.whenIdle();
|
|
731
746
|
}
|
|
732
747
|
if (session !== void 0) await ctx.sessions.flush(session);
|
|
733
|
-
const handle = getLiveSessionHandle(ctx, sessionId);
|
|
734
748
|
if (handle !== void 0) {
|
|
735
749
|
await handle.dispose();
|
|
736
750
|
} else {
|
|
@@ -753,7 +767,8 @@ function sessionDirectoryFromLocation(locationPath) {
|
|
|
753
767
|
throw new DshMoreError("internal", "\u5F53\u524D\u6301\u4E45\u5316\u540E\u7AEF\u6CA1\u6709\u8FD4\u56DE\u7EDD\u5BF9\u4F1A\u8BDD\u8DEF\u5F84\u3002", 409);
|
|
754
768
|
}
|
|
755
769
|
const artifact = basename(locationPath);
|
|
756
|
-
|
|
770
|
+
const match = /^session(?:\.v([1-9][0-9]*))?\.jsonl(?:\.zstd)?$/.exec(artifact);
|
|
771
|
+
if (match === null || match[1] !== void 0 && !Number.isSafeInteger(Number(match[1]))) {
|
|
757
772
|
throw new DshMoreError("internal", "\u6301\u4E45\u5316\u540E\u7AEF\u8FD4\u56DE\u4E86\u672A\u77E5\u7684\u4F1A\u8BDD\u6587\u4EF6\u5E03\u5C40\u3002", 500);
|
|
758
773
|
}
|
|
759
774
|
const sessionDir = dirname(locationPath);
|
|
@@ -765,9 +780,10 @@ function sessionDirectoryFromLocation(locationPath) {
|
|
|
765
780
|
async function deleteSessionPermanently(ctx, rawSessionId) {
|
|
766
781
|
const sessionId = SessionId6(rawSessionId);
|
|
767
782
|
const live = ctx.sessions.get(sessionId);
|
|
768
|
-
const
|
|
783
|
+
const stored = await ctx.sessionPersistence.list();
|
|
784
|
+
const header2 = stored.map((candidate) => "header" in candidate ? candidate.header : candidate).find((candidate) => candidate.id === sessionId) ?? live?.header;
|
|
769
785
|
if (header2 === void 0) throw new DshMoreError("not-found", "\u4F1A\u8BDD\u8BB0\u5F55\u4E0D\u5B58\u5728\u3002", 404);
|
|
770
|
-
const location = ctx.sessionPersistence.locate(header2);
|
|
786
|
+
const location = typeof ctx.sessionPersistence.locate === "function" ? ctx.sessionPersistence.locate(header2) : void 0;
|
|
771
787
|
if (location === void 0) {
|
|
772
788
|
throw new DshMoreError("internal", "\u5F53\u524D\u6301\u4E45\u5316\u540E\u7AEF\u4E0D\u652F\u6301\u9010\u4F1A\u8BDD\u7269\u7406\u5220\u9664\u3002", 409);
|
|
773
789
|
}
|
|
@@ -776,7 +792,10 @@ async function deleteSessionPermanently(ctx, rawSessionId) {
|
|
|
776
792
|
}
|
|
777
793
|
const sessionDir = sessionDirectoryFromLocation(location.path);
|
|
778
794
|
await unloadLiveSession(ctx, sessionId);
|
|
779
|
-
const info = await stat(sessionDir).catch(() =>
|
|
795
|
+
const info = await stat(sessionDir).catch((error) => {
|
|
796
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") return void 0;
|
|
797
|
+
throw error;
|
|
798
|
+
});
|
|
780
799
|
if (info !== void 0) {
|
|
781
800
|
if (!info.isDirectory()) throw new DshMoreError("internal", "\u4F1A\u8BDD\u6301\u4E45\u5316\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55\u3002", 500);
|
|
782
801
|
await rm(sessionDir, { recursive: true, force: false });
|
|
@@ -1435,6 +1454,48 @@ import { join } from "node:path";
|
|
|
1435
1454
|
var PROJECTLESS_TASKS_PATCH_ID = "projectless-tasks";
|
|
1436
1455
|
var TASK_ID_PATTERN = /^task-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
1437
1456
|
|
|
1457
|
+
// src/patches/projectless-tasks/groups.ts
|
|
1458
|
+
var SESSION_GROUPS_NAMESPACE = "dsh-more-session-groups";
|
|
1459
|
+
var EMPTY_GROUPS = { assignments: {} };
|
|
1460
|
+
function decodeSessionGroups(value) {
|
|
1461
|
+
if (typeof value !== "object" || value === null || !("assignments" in value)) return void 0;
|
|
1462
|
+
const assignments = value.assignments;
|
|
1463
|
+
if (typeof assignments !== "object" || assignments === null || Array.isArray(assignments) || !Object.values(assignments).every((id) => typeof id === "string")) return void 0;
|
|
1464
|
+
return { assignments };
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
// src/patches/projectless-tasks/host/groups.ts
|
|
1468
|
+
import z2 from "@deepseek-ai/schemastery";
|
|
1469
|
+
import { SessionId as SessionId7 } from "@deepseek-ai/dsh-session";
|
|
1470
|
+
import { WorkspaceId } from "@deepseek-ai/dsh-workspace";
|
|
1471
|
+
var SessionGroupsSchema = z2.object({ assignments: z2.dict(z2.string()).default({}) });
|
|
1472
|
+
async function moveSessionGroup(ctx, payload) {
|
|
1473
|
+
const sessionId = SessionId7(requireString(payload, "sessionId"));
|
|
1474
|
+
if (typeof payload !== "object" || payload === null || !("workspaceId" in payload) || !(payload.workspaceId === null || typeof payload.workspaceId === "string" && payload.workspaceId.length > 0)) {
|
|
1475
|
+
throw new DshMoreError("bad-request", "\u8BF7\u9009\u62E9\u76EE\u6807\u5DE5\u4F5C\u533A\u3002");
|
|
1476
|
+
}
|
|
1477
|
+
const workspaceId = payload.workspaceId;
|
|
1478
|
+
if (!ctx.settings.writable) throw new DshMoreError("forbidden", "\u5F53\u524D\u914D\u7F6E\u4E3A\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u79FB\u52A8\u4F1A\u8BDD\u3002", 403);
|
|
1479
|
+
if (workspaceId !== null && ctx.workspaceRegistry.get(WorkspaceId(workspaceId)) === void 0) {
|
|
1480
|
+
throw new DshMoreError("not-found", "\u76EE\u6807\u5DE5\u4F5C\u533A\u5DF2\u4E0D\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u3002", 404);
|
|
1481
|
+
}
|
|
1482
|
+
const storedHeaders = async () => {
|
|
1483
|
+
const stored = await ctx.sessionPersistence.list();
|
|
1484
|
+
return stored.map((item) => "header" in item ? item.header : item);
|
|
1485
|
+
};
|
|
1486
|
+
const header2 = ctx.sessions.get(sessionId)?.header ?? (await storedHeaders()).find((item) => item.id === sessionId);
|
|
1487
|
+
if (header2 === void 0) throw new DshMoreError("not-found", "\u8BE5\u4F1A\u8BDD\u5DF2\u4E0D\u5B58\u5728\u3002", 404);
|
|
1488
|
+
if (header2.origin === "subagent") throw new DshMoreError("bad-request", "\u5B50\u4F1A\u8BDD\u8DDF\u968F\u4E3B\u4F1A\u8BDD\u5F52\u7EC4\uFF0C\u8BF7\u79FB\u52A8\u4E3B\u4F1A\u8BDD\u3002");
|
|
1489
|
+
if (ctx.workspaceRegistry.list().some((workspace) => workspace.sessionIds.includes(sessionId))) {
|
|
1490
|
+
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");
|
|
1491
|
+
}
|
|
1492
|
+
const current = decodeSessionGroups(ctx.settings.get(SESSION_GROUPS_NAMESPACE)) ?? EMPTY_GROUPS;
|
|
1493
|
+
const result = { sessionId, workspaceId };
|
|
1494
|
+
if ((current.assignments[sessionId] ?? null) === workspaceId) return result;
|
|
1495
|
+
await ctx.settings.mutate(SESSION_GROUPS_NAMESPACE, [workspaceId === null ? { op: "unset", path: ["assignments", sessionId] } : { op: "set", path: ["assignments", sessionId], value: workspaceId }]);
|
|
1496
|
+
return result;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1438
1499
|
// src/patches/projectless-tasks/host/index.ts
|
|
1439
1500
|
function prepareTask(payload, homeDirectory = homedir()) {
|
|
1440
1501
|
if (typeof payload !== "object" || payload === null || Array.isArray(payload) || !("sessionId" in payload) || typeof payload.sessionId !== "string" || !TASK_ID_PATTERN.test(payload.sessionId) || Object.keys(payload).length !== 1) {
|
|
@@ -1444,7 +1505,15 @@ function prepareTask(payload, homeDirectory = homedir()) {
|
|
|
1444
1505
|
}
|
|
1445
1506
|
var hostPatch7 = {
|
|
1446
1507
|
id: PROJECTLESS_TASKS_PATCH_ID,
|
|
1447
|
-
|
|
1508
|
+
setup: (ctx) => {
|
|
1509
|
+
const fiber = ctx.inject(["settings"], (scope) => {
|
|
1510
|
+
scope.settings.register(SESSION_GROUPS_NAMESPACE, SessionGroupsSchema);
|
|
1511
|
+
});
|
|
1512
|
+
return () => {
|
|
1513
|
+
void fiber.dispose();
|
|
1514
|
+
};
|
|
1515
|
+
},
|
|
1516
|
+
routes: ({ ctx }) => ({ prepare: (payload) => prepareTask(payload), move: (payload) => moveSessionGroup(ctx, payload) })
|
|
1448
1517
|
};
|
|
1449
1518
|
|
|
1450
1519
|
// src/generated/host-registry.ts
|
|
@@ -1495,15 +1564,15 @@ var HostPatchActivation = class {
|
|
|
1495
1564
|
};
|
|
1496
1565
|
|
|
1497
1566
|
// src/generated/host-settings-schema.ts
|
|
1498
|
-
import
|
|
1499
|
-
var PatchSettingsSchema =
|
|
1500
|
-
"message-edit":
|
|
1501
|
-
"message-delete":
|
|
1502
|
-
"session-delete":
|
|
1503
|
-
"conversation-markdown-export":
|
|
1504
|
-
"model-capabilities":
|
|
1505
|
-
"session-auto-title":
|
|
1506
|
-
"projectless-tasks":
|
|
1567
|
+
import z3 from "@deepseek-ai/schemastery";
|
|
1568
|
+
var PatchSettingsSchema = z3.object({
|
|
1569
|
+
"message-edit": z3.boolean().default(true),
|
|
1570
|
+
"message-delete": z3.boolean().default(true),
|
|
1571
|
+
"session-delete": z3.boolean().default(true),
|
|
1572
|
+
"conversation-markdown-export": z3.boolean().default(true),
|
|
1573
|
+
"model-capabilities": z3.boolean().default(true),
|
|
1574
|
+
"session-auto-title": z3.boolean().default(true),
|
|
1575
|
+
"projectless-tasks": z3.boolean().default(true)
|
|
1507
1576
|
});
|
|
1508
1577
|
|
|
1509
1578
|
// src/kernel/host/settings.ts
|
|
@@ -43,7 +43,7 @@ export declare const PATCH_CATALOG: readonly [{
|
|
|
43
43
|
}, {
|
|
44
44
|
readonly id: "projectless-tasks";
|
|
45
45
|
readonly name: "独立任务";
|
|
46
|
-
readonly description: "
|
|
46
|
+
readonly description: "在工作区下拉框创建独立任务并保留草稿,也可将未分组会话移入工作区列表";
|
|
47
47
|
readonly defaultEnabled: true;
|
|
48
48
|
readonly order: 700;
|
|
49
49
|
readonly clientKind: "standalone";
|
|
@@ -12,4 +12,6 @@ export declare function unlockComposer(owner: ComposerBarOwnerProps, independent
|
|
|
12
12
|
* A dormant fallback registration invalidates the public slot subscription
|
|
13
13
|
* on install/uninstall, including an already mounted Web client.
|
|
14
14
|
*/
|
|
15
|
-
export declare
|
|
15
|
+
export declare const CONVERSATION_SLOTS: readonly ["conversation", "main.conversation"];
|
|
16
|
+
export declare function conversationSlot(name: typeof CONVERSATION_SLOTS[number]): 'conversation';
|
|
17
|
+
export declare function installConversationAdapter(ctx: Context, activation: PatchActivationSource, name?: typeof CONVERSATION_SLOTS[number]): () => void;
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
-
import type {
|
|
2
|
+
import type { DraftAttachmentId } from '@deepseek-ai/dsh-client-ui-conversation/client';
|
|
3
3
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
4
|
-
|
|
4
|
+
interface Draft {
|
|
5
|
+
state: {
|
|
6
|
+
getSnapshot(): {
|
|
7
|
+
phase: string;
|
|
8
|
+
draft: string;
|
|
9
|
+
imageIds?: readonly DraftAttachmentId[];
|
|
10
|
+
attachmentIds?: readonly DraftAttachmentId[];
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
setDraft(text: string): void;
|
|
14
|
+
addImages?(ids: DraftAttachmentId[]): boolean;
|
|
15
|
+
removeImage?(id: DraftAttachmentId): unknown;
|
|
16
|
+
addAttachments?(ids: readonly DraftAttachmentId[]): boolean;
|
|
17
|
+
removeAttachment?(id: DraftAttachmentId): unknown;
|
|
18
|
+
}
|
|
5
19
|
/** Move only after all target admission checks pass; never overwrite another draft. */
|
|
6
|
-
export declare function transferDraft(source: Draft, target: Draft): void;
|
|
20
|
+
export declare function transferDraft(source: Draft, target: Draft, rebind?: (ids: readonly DraftAttachmentId[]) => void): void;
|
|
7
21
|
/** Validate the Client-only service methods where Cordis Host types overlap. */
|
|
8
22
|
export declare function transferBeforeOpen(ctx: Context, sourceId: SessionId | undefined, targetId: SessionId): boolean;
|
|
9
23
|
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ComponentType } from 'react';
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
4
|
+
import type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
5
|
+
import type { WorkspaceSnapshot } from '@deepseek-ai/dsh-api-workspace-controller/client';
|
|
6
|
+
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
7
|
+
import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
8
|
+
import type { PatchActivationSource } from '../../../kernel/client/activation.js';
|
|
9
|
+
import { type SessionGroups } from '../groups.js';
|
|
10
|
+
/** Only the sidebar receives grouping metadata; execution and workspace selection use native cwd. */
|
|
11
|
+
export declare function projectSessionGroups(workspaces: WorkspaceSnapshot, sessions: SessionListState, groups: SessionGroups): WorkspaceSnapshot;
|
|
12
|
+
type SidebarProps = PropsRuntime<'sidebar'> & {
|
|
13
|
+
archiveSession(id: SessionId): Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
interface Lifetime {
|
|
16
|
+
subscribe(listener: () => void): () => void;
|
|
17
|
+
getSnapshot(): boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function extendGroupedSidebar(original: ComponentType<SidebarProps>, activation: PatchActivationSource, source: SettingsScope<SessionGroups>, lifetime?: Lifetime): ComponentType<SidebarProps>;
|
|
20
|
+
export declare function installSessionGrouping(ctx: Context, activation: PatchActivationSource): void;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const SESSION_GROUPS_NAMESPACE = "dsh-more-session-groups";
|
|
2
|
+
export interface SessionGroups {
|
|
3
|
+
assignments: Record<string, string>;
|
|
4
|
+
}
|
|
5
|
+
export declare const EMPTY_GROUPS: SessionGroups;
|
|
6
|
+
export declare function decodeSessionGroups(value: unknown): SessionGroups | undefined;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import z from '@deepseek-ai/schemastery';
|
|
3
|
+
import { type SessionGroups } from '../groups.js';
|
|
4
|
+
export declare const SessionGroupsSchema: z<SessionGroups>;
|
|
5
|
+
/** Persist presentation membership only. Immutable cwd and native accounts stay authoritative. */
|
|
6
|
+
export declare function moveSessionGroup(ctx: Context, payload: unknown): Promise<{
|
|
7
|
+
sessionId: string;
|
|
8
|
+
workspaceId: string | null;
|
|
9
|
+
}>;
|
package/dsh.plugin.json
CHANGED