@dsh-tom/dsh-css 0.2.10 → 0.3.2

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/README.md CHANGED
@@ -22,7 +22,7 @@ npm publish --access public --registry=https://registry.npmjs.org/
22
22
  打开 **插件 → 添加插件 → 安装第三方插件**,在“包名或地址”输入:
23
23
 
24
24
  ```text
25
- D:\product\dsh-css\dsh-tom-dsh-css-0.2.10.tgz
25
+ D:\product\dsh-css\dsh-tom-dsh-css-0.3.2.tgz
26
26
  ```
27
27
 
28
28
  安装并启用,然后完全退出并重新打开 dsh。
@@ -32,7 +32,7 @@ D:\product\dsh-css\dsh-tom-dsh-css-0.2.10.tgz
32
32
  包发布到 npmjs 后,先卸载已安装的旧版,再打开 **插件 → 添加插件 → 安装第三方插件**,输入:
33
33
 
34
34
  ```text
35
- @dsh-tom/dsh-css@0.2.10
35
+ @dsh-tom/dsh-css@0.3.2
36
36
  ```
37
37
 
38
38
  选择 **安装源 → npm 官方源**,安装并启用,然后完全退出并重新打开 dsh。
package/dist/client.js CHANGED
@@ -29,7 +29,7 @@ __export(client_exports, {
29
29
  inject: () => inject2
30
30
  });
31
31
  module.exports = __toCommonJS(client_exports);
32
- var import_react8 = require("react");
32
+ var import_react9 = require("react");
33
33
 
34
34
  // theme.css
35
35
  var theme_default = `.dsh-css-unread-dot {
@@ -1083,24 +1083,37 @@ function replacePercent(value, percent) {
1083
1083
  function registerCacheHitPrecision(ctx) {
1084
1084
  const slot = "conversation.composer.dock";
1085
1085
  ctx.slots.inject(slot, () => {
1086
- const original = ctx.slots.entries(slot).find((entry) => entry.options.id === "usage");
1087
- if (!original) return;
1088
- const renderUsage = original.component.type;
1089
- function UsagePill(props) {
1090
- const element = renderUsage(props);
1091
- const usage = props.useProjection("tokenUsage");
1092
- if (!usage) return element;
1093
- const input2 = usage.uncachedInputTokens + usage.cacheReadTokens + usage.cacheWriteTokens;
1094
- if (input2 === 0) return element;
1095
- return replacePercent(element, (usage.cacheReadTokens / input2 * 100).toFixed(2));
1096
- }
1097
- return ctx.slots.register({
1098
- ...original.options,
1099
- name: slot,
1100
- priority: (original.options.priority ?? 0) - 1,
1101
- locale: original.locale,
1102
- inject: original.inject
1103
- }, UsagePill);
1086
+ let original;
1087
+ let dispose;
1088
+ const sync = () => {
1089
+ if (original && ctx.slots.entries(slot).includes(original)) return;
1090
+ dispose?.();
1091
+ dispose = void 0;
1092
+ original = ctx.slots.entries(slot).find((entry) => entry.options.id === "usage");
1093
+ if (!original) return;
1094
+ const renderUsage = original.component.type;
1095
+ function UsagePill(props) {
1096
+ const element = renderUsage(props);
1097
+ const usage = props.useProjection("tokenUsage");
1098
+ if (!usage) return element;
1099
+ const input2 = usage.uncachedInputTokens + usage.cacheReadTokens + usage.cacheWriteTokens;
1100
+ if (input2 === 0) return element;
1101
+ return replacePercent(element, (usage.cacheReadTokens / input2 * 100).toFixed(2));
1102
+ }
1103
+ dispose = ctx.slots.register({
1104
+ ...original.options,
1105
+ name: slot,
1106
+ priority: (original.options.priority ?? 0) - 1,
1107
+ locale: original.locale,
1108
+ inject: original.inject
1109
+ }, UsagePill);
1110
+ };
1111
+ const unsubscribe = ctx.slots.subscribe(slot, sync);
1112
+ sync();
1113
+ return () => {
1114
+ unsubscribe();
1115
+ dispose?.();
1116
+ };
1104
1117
  });
1105
1118
  }
1106
1119
 
@@ -1306,8 +1319,48 @@ function registerUnread(ctx) {
1306
1319
  }, UnreadIndicator));
1307
1320
  }
1308
1321
 
1322
+ // src/rea/client.js
1323
+ var import_react5 = require("react");
1324
+ function ReaIcon(props) {
1325
+ return (0, import_react5.createElement)(
1326
+ "svg",
1327
+ {
1328
+ width: 16,
1329
+ height: 16,
1330
+ viewBox: "0 0 24 24",
1331
+ fill: "none",
1332
+ stroke: "currentColor",
1333
+ strokeWidth: 1.65,
1334
+ strokeLinecap: "round",
1335
+ strokeLinejoin: "round",
1336
+ "aria-hidden": true,
1337
+ ...props
1338
+ },
1339
+ (0, import_react5.createElement)("path", { d: "M6 3v2m4-2v2M3 8h2m-2 4h2m3 5v2M14 5H7a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2M8 8h4v3H8z" }),
1340
+ (0, import_react5.createElement)("circle", { cx: 15, cy: 15, r: 5 }),
1341
+ (0, import_react5.createElement)("path", { d: "m19 19 3 3" })
1342
+ );
1343
+ }
1344
+ function registerReaIcon(ctx) {
1345
+ ctx.effect(() => {
1346
+ const commands = ctx.commandUi;
1347
+ const original = commands.candidates;
1348
+ const descriptor = Object.getOwnPropertyDescriptor(commands, "candidates");
1349
+ const candidates = async function(...args) {
1350
+ const rows = await original.apply(this, args);
1351
+ return rows.map((row) => row.name === "rea" ? { ...row, icon: ReaIcon } : row);
1352
+ };
1353
+ commands.candidates = candidates;
1354
+ return () => {
1355
+ if (Object.getOwnPropertyDescriptor(commands, "candidates")?.value !== candidates) return;
1356
+ if (descriptor) Object.defineProperty(commands, "candidates", descriptor);
1357
+ else delete commands.candidates;
1358
+ };
1359
+ });
1360
+ }
1361
+
1309
1362
  // src/cost/client.js
1310
- var import_react7 = require("react");
1363
+ var import_react8 = require("react");
1311
1364
 
1312
1365
  // src/cost/pricing.js
1313
1366
  var PROJECTION_KEY = "dshTomCost";
@@ -1345,7 +1398,7 @@ function formatMoney(units) {
1345
1398
  }
1346
1399
 
1347
1400
  // src/cost/panel.js
1348
- var import_react5 = require("react");
1401
+ var import_react6 = require("react");
1349
1402
  var import_react_dom = require("react-dom");
1350
1403
 
1351
1404
  // src/cost/panel-styles.js
@@ -1421,8 +1474,8 @@ function costRows(totals, daily, day = beijingDay()) {
1421
1474
  ];
1422
1475
  }
1423
1476
  function useBeijingDay() {
1424
- const [day, setDay] = (0, import_react5.useState)(beijingDay);
1425
- (0, import_react5.useEffect)(() => {
1477
+ const [day, setDay] = (0, import_react6.useState)(beijingDay);
1478
+ (0, import_react6.useEffect)(() => {
1426
1479
  let timer;
1427
1480
  const refresh = () => {
1428
1481
  const current = beijingDay();
@@ -1436,7 +1489,7 @@ function useBeijingDay() {
1436
1489
  return day;
1437
1490
  }
1438
1491
  function CostIcon() {
1439
- return (0, import_react5.createElement)(
1492
+ return (0, import_react6.createElement)(
1440
1493
  "svg",
1441
1494
  {
1442
1495
  viewBox: "0 0 24 24",
@@ -1449,18 +1502,18 @@ function CostIcon() {
1449
1502
  strokeLinejoin: "round",
1450
1503
  "aria-hidden": true
1451
1504
  },
1452
- (0, import_react5.createElement)("circle", { cx: 12, cy: 12, r: 9 }),
1453
- (0, import_react5.createElement)("path", { d: "m8.5 7.5 3.5 4 3.5-4M8.5 12h7M8.5 15h7M12 11.5V18" })
1505
+ (0, import_react6.createElement)("circle", { cx: 12, cy: 12, r: 9 }),
1506
+ (0, import_react6.createElement)("path", { d: "m8.5 7.5 3.5 4 3.5-4M8.5 12h7M8.5 15h7M12 11.5V18" })
1454
1507
  );
1455
1508
  }
1456
1509
  function CostPanel({ totals, daily, balance }) {
1457
1510
  const day = useBeijingDay();
1458
1511
  const rows = costRows(totals, daily, day);
1459
- const [open2, setOpen] = (0, import_react5.useState)(false);
1460
- const anchor2 = (0, import_react5.useRef)(null);
1461
- const panel = (0, import_react5.useRef)(null);
1462
- const dialogId = (0, import_react5.useId)();
1463
- (0, import_react5.useLayoutEffect)(() => {
1512
+ const [open2, setOpen] = (0, import_react6.useState)(false);
1513
+ const anchor2 = (0, import_react6.useRef)(null);
1514
+ const panel = (0, import_react6.useRef)(null);
1515
+ const dialogId = (0, import_react6.useId)();
1516
+ (0, import_react6.useLayoutEffect)(() => {
1464
1517
  if (!open2) return;
1465
1518
  const element = panel.current;
1466
1519
  const document2 = element.ownerDocument;
@@ -1499,11 +1552,11 @@ function CostPanel({ totals, daily, balance }) {
1499
1552
  document2.removeEventListener("keydown", dismissEscape);
1500
1553
  };
1501
1554
  }, [open2]);
1502
- return (0, import_react5.createElement)(
1555
+ return (0, import_react6.createElement)(
1503
1556
  "span",
1504
1557
  { className: "dsh-tom-cost-anchor", "data-composer-stat": "cost" },
1505
- (0, import_react5.createElement)("style", { "data-dsh-tom-cost-styles": "" }, panelStyles),
1506
- (0, import_react5.createElement)("button", {
1558
+ (0, import_react6.createElement)("style", { "data-dsh-tom-cost-styles": "" }, panelStyles),
1559
+ (0, import_react6.createElement)("button", {
1507
1560
  ref: anchor2,
1508
1561
  type: "button",
1509
1562
  className: "dsh-tom-cost-pill",
@@ -1513,8 +1566,8 @@ function CostPanel({ totals, daily, balance }) {
1513
1566
  "aria-controls": open2 ? dialogId : void 0,
1514
1567
  "aria-label": `\u4F1A\u8BDD\u7D2F\u8BA1\u8D39\u7528 ${rows[1][1]}`,
1515
1568
  onClick: () => setOpen(!open2)
1516
- }, (0, import_react5.createElement)(CostIcon), (0, import_react5.createElement)("span", { className: "dsh-tom-cost-label" }, rows[1][1])),
1517
- open2 && (0, import_react_dom.createPortal)((0, import_react5.createElement)(
1569
+ }, (0, import_react6.createElement)(CostIcon), (0, import_react6.createElement)("span", { className: "dsh-tom-cost-label" }, rows[1][1])),
1570
+ open2 && (0, import_react_dom.createPortal)((0, import_react6.createElement)(
1518
1571
  "div",
1519
1572
  {
1520
1573
  ref: panel,
@@ -1524,11 +1577,11 @@ function CostPanel({ totals, daily, balance }) {
1524
1577
  className: "dsh-tom-cost-panel",
1525
1578
  style: { visibility: "hidden", left: 0, top: 0 }
1526
1579
  },
1527
- (0, import_react5.createElement)("div", { className: "dsh-tom-cost-title" }, (0, import_react5.createElement)(CostIcon), "\u8D39\u7528\u660E\u7EC6"),
1528
- (0, import_react5.createElement)("div", { className: "dsh-tom-cost-rule", "aria-hidden": true }),
1529
- (0, import_react5.createElement)("dl", { className: "dsh-tom-cost-details" }, rows.flatMap(([label, value]) => [
1530
- (0, import_react5.createElement)("dt", { key: label }, label),
1531
- (0, import_react5.createElement)("dd", { key: `${label}-value` }, value)
1580
+ (0, import_react6.createElement)("div", { className: "dsh-tom-cost-title" }, (0, import_react6.createElement)(CostIcon), "\u8D39\u7528\u660E\u7EC6"),
1581
+ (0, import_react6.createElement)("div", { className: "dsh-tom-cost-rule", "aria-hidden": true }),
1582
+ (0, import_react6.createElement)("dl", { className: "dsh-tom-cost-details" }, rows.flatMap(([label, value]) => [
1583
+ (0, import_react6.createElement)("dt", { key: label }, label),
1584
+ (0, import_react6.createElement)("dd", { key: `${label}-value` }, value)
1532
1585
  ]))
1533
1586
  ), anchor2.current.ownerDocument.body)
1534
1587
  );
@@ -21475,7 +21528,7 @@ function createBalanceStore(readBalance) {
21475
21528
  }
21476
21529
 
21477
21530
  // src/cost/settings.js
21478
- var import_react6 = require("react");
21531
+ var import_react7 = require("react");
21479
21532
 
21480
21533
  // src/cost/settings-styles.js
21481
21534
  var settingsStyles = `
@@ -21531,62 +21584,62 @@ function usageSummary(row) {
21531
21584
  function CostSettings({ useCostReport }) {
21532
21585
  const report = useCostReport((value2) => value2);
21533
21586
  const day = useBeijingDay();
21534
- const [hideZero, setHideZero] = (0, import_react6.useState)(true);
21587
+ const [hideZero, setHideZero] = (0, import_react7.useState)(true);
21535
21588
  const value = report.status === "ready" && report.value.day === day ? report.value : void 0;
21536
21589
  const status = report.status === "error" ? "\u8BFB\u53D6\u5931\u8D25" : "\u52A0\u8F7D\u4E2D\u2026";
21537
21590
  const rows = value ? visibleHistory(value.history, hideZero) : [];
21538
21591
  const summaries = [["today", "\u4ECA\u65E5\u8D39\u7528"], ["week", "\u672C\u5468\u8D39\u7528"], ["month", "\u672C\u6708\u8D39\u7528"]];
21539
- return (0, import_react6.createElement)(
21592
+ return (0, import_react7.createElement)(
21540
21593
  "section",
21541
21594
  { className: "dsh-tom-cost-settings", "aria-label": "\u8D39\u7528" },
21542
- (0, import_react6.createElement)("style", null, settingsStyles),
21543
- (0, import_react6.createElement)("div", { className: "dsh-tom-cost-cards" }, summaries.map(([key, label]) => {
21595
+ (0, import_react7.createElement)("style", null, settingsStyles),
21596
+ (0, import_react7.createElement)("div", { className: "dsh-tom-cost-cards" }, summaries.map(([key, label]) => {
21544
21597
  const row = value?.[key];
21545
- return (0, import_react6.createElement)(
21598
+ return (0, import_react7.createElement)(
21546
21599
  "div",
21547
21600
  { key, className: "dsh-tom-cost-card" },
21548
- (0, import_react6.createElement)("div", { className: "dsh-tom-cost-card-label" }, label),
21549
- (0, import_react6.createElement)("div", { className: "dsh-tom-cost-amount" }, row ? costValue(row.totals, row.failedSessions) : status),
21550
- (0, import_react6.createElement)("div", { className: "dsh-tom-cost-usage" }, usageSummary(row))
21601
+ (0, import_react7.createElement)("div", { className: "dsh-tom-cost-card-label" }, label),
21602
+ (0, import_react7.createElement)("div", { className: "dsh-tom-cost-amount" }, row ? costValue(row.totals, row.failedSessions) : status),
21603
+ (0, import_react7.createElement)("div", { className: "dsh-tom-cost-usage" }, usageSummary(row))
21551
21604
  );
21552
21605
  })),
21553
- (0, import_react6.createElement)(
21606
+ (0, import_react7.createElement)(
21554
21607
  "div",
21555
21608
  { className: "dsh-tom-cost-history-heading" },
21556
- (0, import_react6.createElement)("h3", null, "\u5386\u53F2\u8BB0\u5F55", (0, import_react6.createElement)("span", null, "\u6700\u8FD1 30 \u5929")),
21557
- (0, import_react6.createElement)(
21609
+ (0, import_react7.createElement)("h3", null, "\u5386\u53F2\u8BB0\u5F55", (0, import_react7.createElement)("span", null, "\u6700\u8FD1 30 \u5929")),
21610
+ (0, import_react7.createElement)(
21558
21611
  "label",
21559
21612
  { className: "dsh-tom-cost-filter" },
21560
- (0, import_react6.createElement)("input", { type: "checkbox", checked: hideZero, onChange: (event) => setHideZero(event.target.checked) }),
21613
+ (0, import_react7.createElement)("input", { type: "checkbox", checked: hideZero, onChange: (event) => setHideZero(event.target.checked) }),
21561
21614
  "\u8FC7\u6EE4\u96F6\u8D39\u7528\u65E5\u671F"
21562
21615
  )
21563
21616
  ),
21564
- (0, import_react6.createElement)(
21617
+ (0, import_react7.createElement)(
21565
21618
  "div",
21566
21619
  { className: "dsh-tom-cost-table-wrap", tabIndex: 0, role: "region", "aria-label": "\u6BCF\u65E5\u8D39\u7528\u5386\u53F2\u8BB0\u5F55" },
21567
- (0, import_react6.createElement)(
21620
+ (0, import_react7.createElement)(
21568
21621
  "table",
21569
21622
  { className: "dsh-tom-cost-table" },
21570
- (0, import_react6.createElement)("thead", null, (0, import_react6.createElement)("tr", null, ["\u65E5\u671F", "\u8C03\u7528", "\u8F93\u5165 tok", "\u7F13\u5B58 tok", "\u8F93\u51FA tok", "\u8D39\u7528"].map((label) => (0, import_react6.createElement)("th", { key: label, scope: "col" }, label)))),
21571
- (0, import_react6.createElement)("tbody", null, value && rows.length ? rows.map((row) => {
21623
+ (0, import_react7.createElement)("thead", null, (0, import_react7.createElement)("tr", null, ["\u65E5\u671F", "\u8C03\u7528", "\u8F93\u5165 tok", "\u7F13\u5B58 tok", "\u8F93\u51FA tok", "\u8D39\u7528"].map((label) => (0, import_react7.createElement)("th", { key: label, scope: "col" }, label)))),
21624
+ (0, import_react7.createElement)("tbody", null, value && rows.length ? rows.map((row) => {
21572
21625
  const totals = row.totals;
21573
21626
  const unavailable = row.failedSessions > 0 && calls(totals) === 0;
21574
- return (0, import_react6.createElement)(
21627
+ return (0, import_react7.createElement)(
21575
21628
  "tr",
21576
21629
  { key: row.day },
21577
- (0, import_react6.createElement)("td", null, row.day),
21578
- (0, import_react6.createElement)("td", null, unavailable ? "\u2014" : calls(totals).toLocaleString("zh-CN")),
21579
- ...["inputTokens", "cacheTokens", "outputTokens"].map((key) => (0, import_react6.createElement)("td", {
21630
+ (0, import_react7.createElement)("td", null, row.day),
21631
+ (0, import_react7.createElement)("td", null, unavailable ? "\u2014" : calls(totals).toLocaleString("zh-CN")),
21632
+ ...["inputTokens", "cacheTokens", "outputTokens"].map((key) => (0, import_react7.createElement)("td", {
21580
21633
  key,
21581
21634
  title: unavailable ? void 0 : totals[key].toLocaleString("zh-CN")
21582
21635
  }, unavailable ? "\u2014" : formatTokens(totals[key]))),
21583
- (0, import_react6.createElement)("td", null, costValue(totals, row.failedSessions))
21636
+ (0, import_react7.createElement)("td", null, costValue(totals, row.failedSessions))
21584
21637
  );
21585
- }) : (0, import_react6.createElement)("tr", null, (0, import_react6.createElement)("td", { colSpan: 6, className: "dsh-tom-cost-empty", role: "status" }, value ? "\u6700\u8FD1 30 \u5929\u6682\u65E0\u975E\u96F6\u8D39\u7528\u8BB0\u5F55" : status)))
21638
+ }) : (0, import_react7.createElement)("tr", null, (0, import_react7.createElement)("td", { colSpan: 6, className: "dsh-tom-cost-empty", role: "status" }, value ? "\u6700\u8FD1 30 \u5929\u6682\u65E0\u975E\u96F6\u8D39\u7528\u8BB0\u5F55" : status)))
21586
21639
  )
21587
21640
  ),
21588
- (0, import_react6.createElement)("p", { className: "dsh-tom-cost-note" }, "\u5317\u4EAC\u65F6\u95F4 \xB7 \u672C\u5468\u4ECE\u5468\u4E00\u5F00\u59CB \xB7 \u8D39\u7528\u6309\u672C\u673A\u4F1A\u8BDD\u8BB0\u5F55\u4F30\u7B97"),
21589
- value && value.history.some(incomplete) && (0, import_react6.createElement)(
21641
+ (0, import_react7.createElement)("p", { className: "dsh-tom-cost-note" }, "\u5317\u4EAC\u65F6\u95F4 \xB7 \u672C\u5468\u4ECE\u5468\u4E00\u5F00\u59CB \xB7 \u8D39\u7528\u6309\u672C\u673A\u4F1A\u8BDD\u8BB0\u5F55\u4F30\u7B97"),
21642
+ value && value.history.some(incomplete) && (0, import_react7.createElement)(
21590
21643
  "p",
21591
21644
  { className: "dsh-tom-cost-note", role: "status" },
21592
21645
  "\u90E8\u5206\u8BB0\u5F55\u65E0\u6CD5\u8BFB\u53D6\u6216\u8BA1\u4EF7\uFF0C\u76F8\u5173\u91D1\u989D\u53EF\u80FD\u4E0D\u5B8C\u6574\u3002"
@@ -21600,7 +21653,7 @@ function CostMount({ useProjection, useDailyCost, useAccountBalance, sessionId }
21600
21653
  const totals = useProjection(PROJECTION_KEY);
21601
21654
  const daily = useDailyCost((value) => value);
21602
21655
  const balance = useAccountBalance((value) => value);
21603
- return (0, import_react7.createElement)(CostPanel, { key: sessionId, totals, daily, balance });
21656
+ return (0, import_react8.createElement)(CostPanel, { key: sessionId, totals, daily, balance });
21604
21657
  }
21605
21658
  async function apply(ctx) {
21606
21659
  await ctx.remote.$mount(dailyRemote);
@@ -21630,16 +21683,16 @@ async function apply(ctx) {
21630
21683
  }
21631
21684
 
21632
21685
  // src/client.js
21633
- var inject2 = [.../* @__PURE__ */ new Set(["slots", "sessions", "workspaces", "layout", "uiWorkspace", ...inject])];
21686
+ var inject2 = [.../* @__PURE__ */ new Set(["slots", "sessions", "workspaces", "layout", "uiWorkspace", "commandUi", ...inject])];
21634
21687
  function ProjectHover({ sessionId, useWorkspaces, useSessions }) {
21635
21688
  const workspace = useWorkspaces((state) => state.items.find((item) => item.sessionIds.includes(sessionId)));
21636
21689
  const cwd = useSessions((state) => state.byId[sessionId]?.cwd);
21637
21690
  const path = workspace?.path || cwd;
21638
21691
  const name = workspace?.title || path?.split(/[\\/]/).filter(Boolean).at(-1) || path || "\u672A\u5F52\u5C5E\u9879\u76EE";
21639
- return (0, import_react8.createElement)(
21692
+ return (0, import_react9.createElement)(
21640
21693
  "div",
21641
21694
  { className: "dsh-css-project", title: path },
21642
- (0, import_react8.createElement)("svg", {
21695
+ (0, import_react9.createElement)("svg", {
21643
21696
  width: 14,
21644
21697
  height: 14,
21645
21698
  viewBox: "0 0 24 24",
@@ -21648,8 +21701,8 @@ function ProjectHover({ sessionId, useWorkspaces, useSessions }) {
21648
21701
  strokeWidth: 1.7,
21649
21702
  strokeLinejoin: "round",
21650
21703
  "aria-hidden": true
21651
- }, (0, import_react8.createElement)("path", { d: "M3 7V5a2 2 0 0 1 2-2h5l2 3h7a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7Zm0 2h18" })),
21652
- (0, import_react8.createElement)("span", null, name)
21704
+ }, (0, import_react9.createElement)("path", { d: "M3 7V5a2 2 0 0 1 2-2h5l2 3h7a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7Zm0 2h18" })),
21705
+ (0, import_react9.createElement)("span", null, name)
21653
21706
  );
21654
21707
  }
21655
21708
  function applySidebarWidth(layout) {
@@ -21728,6 +21781,7 @@ async function apply2(ctx) {
21728
21781
  registerDateGroups(ctx);
21729
21782
  registerProjects(ctx);
21730
21783
  registerUnread(ctx);
21784
+ registerReaIcon(ctx);
21731
21785
  ctx.slots.inject("sidebar.session.row.hover", () => ctx.slots.register({
21732
21786
  name: "sidebar.session.row.hover",
21733
21787
  id: "dsh-css-project",
package/dist/index.js CHANGED
@@ -20083,11 +20083,167 @@ function registerProgressUpdates(ctx) {
20083
20083
  });
20084
20084
  }
20085
20085
 
20086
+ // src/rea/index.js
20087
+ import { interpolate } from "@deepseek-ai/cordis-plugin-loader";
20088
+ import { createScope, scopeOf } from "@deepseek-ai/dsh-scope";
20089
+ import { createUserMessage } from "@deepseek-ai/dsh-llm";
20090
+ import * as mcpClient from "@deepseek-ai/dsh-mcp-client";
20091
+
20092
+ // src/rea/projection.js
20093
+ var REA_STATE = "dshTomRea";
20094
+ var reaProjection = {
20095
+ key: REA_STATE,
20096
+ stateVersion: 2,
20097
+ stateSchema: external_exports.object({ started: external_exports.boolean(), enabled: external_exports.boolean(), pending: external_exports.string().nullable() }),
20098
+ init: () => ({ started: false, enabled: false, pending: null }),
20099
+ apply(state, event) {
20100
+ if (event.type === "command/run") {
20101
+ if (event.data.name === "rea") {
20102
+ return state.started || state.enabled ? state : { ...state, pending: event.data.commandId };
20103
+ }
20104
+ return state.started ? state : { ...state, started: true };
20105
+ }
20106
+ if (event.type === "command/done" && event.data.commandId === state.pending) {
20107
+ return { ...state, enabled: event.data.kind === "success", pending: null };
20108
+ }
20109
+ if (event.type === "step/start" || event.type === "user/message" && event.data.source.kind === "user") {
20110
+ return state.started ? state : { ...state, started: true };
20111
+ }
20112
+ return state;
20113
+ }
20114
+ };
20115
+
20116
+ // src/rea/index.js
20117
+ var MCP_PLUGIN = "@deepseek-ai/dsh-mcp-client";
20118
+ function findReaEntries(loader) {
20119
+ return [...loader.entries()].filter((entry) => entry.options?.name === MCP_PLUGIN && entry.options.config?.serverName === "rea" && scopeOf(entry.ctx) === void 0);
20120
+ }
20121
+ function registerRea(ctx) {
20122
+ ctx.sessionProjections.register(reaProjection);
20123
+ const connections = /* @__PURE__ */ new Map();
20124
+ let source;
20125
+ let unregister;
20126
+ let disposed = false;
20127
+ let scheduled = false;
20128
+ let pending = Promise.resolve();
20129
+ const stateOf = (agent) => ctx.sessionProjections.stateOf(agent.session, REA_STATE);
20130
+ async function disconnect(agent) {
20131
+ const connection = connections.get(agent);
20132
+ if (!connection) return;
20133
+ connections.delete(agent);
20134
+ await connection.scope.dispose();
20135
+ }
20136
+ function connect(agent) {
20137
+ const existing = connections.get(agent);
20138
+ if (existing) return existing.ready;
20139
+ if (!source) throw new Error("\u672A\u68C0\u6D4B\u5230 REA MCP \u914D\u7F6E\uFF0C\u8BF7\u5148\u5728 DSH \u4E2D\u5B89\u88C5\u5E76\u914D\u7F6E REA\u3002");
20140
+ const scope = createScope(ctx, agent);
20141
+ const connection = { scope, ready: void 0 };
20142
+ connections.set(agent, connection);
20143
+ connection.ready = (async () => {
20144
+ try {
20145
+ const config2 = interpolate(source.ctx, source.options.config);
20146
+ const fiber = scope.ctx.plugin(mcpClient, { ...config2, failOnStartupError: true });
20147
+ await fiber;
20148
+ } catch (error62) {
20149
+ if (connections.get(agent) === connection) connections.delete(agent);
20150
+ await scope.dispose();
20151
+ throw error62;
20152
+ }
20153
+ })();
20154
+ return connection.ready;
20155
+ }
20156
+ async function execute({ agent, rawInput, attachments, signal }) {
20157
+ await pending;
20158
+ signal.throwIfAborted();
20159
+ const state = stateOf(agent);
20160
+ if (!state.enabled && (state.started || agent.status !== "idle" || agent.inbox.nextTurn.length || agent.inbox.nextStep.length)) {
20161
+ return { kind: "error", text: "\u8BF7\u65B0\u5EFA\u4F1A\u8BDD\uFF0C\u5E76\u4EE5 /rea \u6216 /rea \u4EFB\u52A1\u5185\u5BB9 \u5F00\u59CB\uFF1B\u666E\u901A\u4F1A\u8BDD\u4E0D\u4F1A\u4E2D\u9014\u52A0\u8F7D REA\u3002" };
20162
+ }
20163
+ const alreadyConnected = connections.has(agent);
20164
+ const cancel = () => {
20165
+ if (!alreadyConnected) void disconnect(agent).catch((error62) => ctx.logger.warn(error62));
20166
+ };
20167
+ signal.addEventListener("abort", cancel, { once: true });
20168
+ try {
20169
+ await connect(agent);
20170
+ signal.throwIfAborted();
20171
+ const text = rawInput.trim();
20172
+ if (text || attachments.length) agent.followup(createUserMessage({
20173
+ content: [...attachments, ...text ? [{ type: "text", text }] : []],
20174
+ source: { kind: "user" }
20175
+ }));
20176
+ return { kind: "success", text: "REA \u5DF2\u4E3A\u5F53\u524D\u4F1A\u8BDD\u542F\u7528\uFF0C\u540E\u7EED\u6D88\u606F\u65E0\u9700\u518D\u52A0 /rea\u3002" };
20177
+ } finally {
20178
+ signal.removeEventListener("abort", cancel);
20179
+ }
20180
+ }
20181
+ async function refresh() {
20182
+ if (disposed) return;
20183
+ const entries = findReaEntries(ctx.loader);
20184
+ source = entries.length === 1 ? entries[0] : void 0;
20185
+ if (!source) {
20186
+ unregister?.();
20187
+ unregister = void 0;
20188
+ await Promise.all([...connections.keys()].map(disconnect));
20189
+ if (entries.length > 1) ctx.logger.warn("\u68C0\u6D4B\u5230\u591A\u6761\u5168\u5C40 REA MCP \u914D\u7F6E\uFF0C\u8BF7\u4FDD\u7559\u4E00\u6761\u540E\u518D\u542F\u7528 /rea\u3002");
20190
+ return;
20191
+ }
20192
+ if (!source.disabled) {
20193
+ const fiber = source.fiber;
20194
+ await source.update({ disabled: true });
20195
+ while (fiber?.inertia) await fiber.inertia;
20196
+ }
20197
+ if (disposed) return;
20198
+ unregister ??= ctx.commands.register({
20199
+ definitionId: "@dsh-tom/dsh-css/rea",
20200
+ name: "rea",
20201
+ description: "\u5728\u65B0\u4F1A\u8BDD\u4E2D\u6309\u9700\u542F\u7528\u5DF2\u5B89\u88C5\u7684 REA \u9006\u5411\u5DE5\u5177",
20202
+ input: { hint: "[\u4EFB\u52A1\u5185\u5BB9]", attachments: true },
20203
+ handler: execute
20204
+ });
20205
+ for (const agent of ctx.agents.list()) if (stateOf(agent).enabled) await connect(agent);
20206
+ }
20207
+ function scheduleRefresh() {
20208
+ if (disposed || scheduled) return;
20209
+ scheduled = true;
20210
+ queueMicrotask(() => {
20211
+ scheduled = false;
20212
+ if (disposed) return;
20213
+ pending = pending.then(refresh).catch((error62) => ctx.logger.warn("REA \u6309\u9700\u52A0\u8F7D\u914D\u7F6E\u5931\u8D25\uFF1A%s", error62.message));
20214
+ });
20215
+ }
20216
+ ctx.on("loader/entry-init", scheduleRefresh, { global: true });
20217
+ ctx.on("loader/partial-dispose", scheduleRefresh, { global: true });
20218
+ ctx.on("internal/plugin", (fiber) => {
20219
+ if (fiber.entry?.options.name === MCP_PLUGIN && scopeOf(fiber.ctx) === void 0) scheduleRefresh();
20220
+ }, { global: true });
20221
+ ctx.on("agent/created", async ({ agent }) => {
20222
+ await Promise.resolve();
20223
+ await pending;
20224
+ if (stateOf(agent).enabled) await connect(agent);
20225
+ });
20226
+ ctx.on("agent/disposed", ({ agent }) => disconnect(agent));
20227
+ ctx.effect(() => async () => {
20228
+ disposed = true;
20229
+ unregister?.();
20230
+ await Promise.all([...connections.keys()].map(disconnect));
20231
+ });
20232
+ scheduleRefresh();
20233
+ return { settle: async () => {
20234
+ await Promise.resolve();
20235
+ await pending;
20236
+ } };
20237
+ }
20238
+
20086
20239
  // index.js
20087
20240
  var name = "dsh-css";
20088
20241
  function apply2(ctx) {
20089
20242
  apply(ctx);
20090
20243
  ctx.inject(["systemPrompt"], registerProgressUpdates);
20244
+ ctx.inject(["commands", "tools", "loader", "agents", "sessionProjections"], (reaCtx) => {
20245
+ registerRea(reaCtx);
20246
+ });
20091
20247
  }
20092
20248
  export {
20093
20249
  apply2 as apply,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-tom/dsh-css",
3
- "version": "0.2.10",
3
+ "version": "0.3.2",
4
4
  "description": "为 DeepSeek Harness 调整深色界面,增加项目管理、费用统计和任务进展播报。",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -35,6 +35,7 @@
35
35
  "@deepseek-ai/dsh-client-locale",
36
36
  "@deepseek-ai/dsh-client-ui-settings-general",
37
37
  "@deepseek-ai/dsh-client-ui-chat",
38
+ "@deepseek-ai/dsh-client-ui-commands",
38
39
  "@deepseek-ai/dsh-client-ui-session",
39
40
  "@deepseek-ai/dsh-client-ui-conversation"
40
41
  ]
@@ -49,9 +50,25 @@
49
50
  "license": "MIT",
50
51
  "peerDependencies": {
51
52
  "@deepseek-ai/cordis": "~4.0.5",
53
+ "@deepseek-ai/cordis-plugin-loader": "~1.0.6",
54
+ "@deepseek-ai/dsh-llm": "0.2.1-rc.2",
55
+ "@deepseek-ai/dsh-mcp-client": "0.2.1-rc.2",
56
+ "@deepseek-ai/dsh-scope": "0.2.1-rc.2",
52
57
  "@deepseek-ai/dsh-typert-protocol": "0.2.1-rc.2"
53
58
  },
54
59
  "peerDependenciesMeta": {
60
+ "@deepseek-ai/cordis-plugin-loader": {
61
+ "optional": true
62
+ },
63
+ "@deepseek-ai/dsh-llm": {
64
+ "optional": true
65
+ },
66
+ "@deepseek-ai/dsh-mcp-client": {
67
+ "optional": true
68
+ },
69
+ "@deepseek-ai/dsh-scope": {
70
+ "optional": true
71
+ },
55
72
  "@deepseek-ai/cordis": {
56
73
  "optional": true
57
74
  },
@@ -61,11 +78,16 @@
61
78
  },
62
79
  "devDependencies": {
63
80
  "@deepseek-ai/cordis": "4.0.5",
81
+ "@deepseek-ai/cordis-plugin-loader": "1.0.6",
82
+ "@deepseek-ai/dsh-agent-loop": "0.2.1-rc.2",
64
83
  "@deepseek-ai/dsh-api-gateway": "0.2.1-rc.2",
65
- "@deepseek-ai/dsh-typert-registry": "0.2.1-rc.2",
66
- "@deepseek-ai/dsh-typert-protocol": "0.2.1-rc.2",
84
+ "@deepseek-ai/dsh-commands": "0.2.1-rc.2",
85
+ "@deepseek-ai/dsh-mcp-client": "0.2.1-rc.2",
67
86
  "@deepseek-ai/dsh-session-projection": "0.2.1-rc.2",
68
87
  "@deepseek-ai/dsh-system-prompt": "0.2.1-rc.2",
88
+ "@deepseek-ai/dsh-tools": "0.2.1-rc.2",
89
+ "@deepseek-ai/dsh-typert-protocol": "0.2.1-rc.2",
90
+ "@deepseek-ai/dsh-typert-registry": "0.2.1-rc.2",
69
91
  "esbuild": "0.28.2",
70
92
  "jsdom": "^27.0.0",
71
93
  "react": "18.3.1",