@morlay/ui-conversation-manager 0.1.11-alpha.0 → 0.1.11-alpha.3

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  「对话管理」全局面板页(**浏览器半**):`sidebar.panellist` 的 nav 行 + `main` keyed 面板(与官方
4
4
  ui-plugin-manager 同一种注册方式)。一层 Tabs 在**会话**与**统计**之间切换:会话视图做全量会话的搜索、分页与
5
- 归档 / 取消归档 / 导出 / 删除(确认弹窗),并带导入为新会话与孤儿数据 GC;统计视图给出全部对话的 token 用量。
5
+ 归档 / 取消归档 / 导出 / 删除(确认弹窗),并带导入为新会话与整理数据(孤儿回收 + 统计重算);统计视图给出全部对话的 token 用量。
6
6
 
7
7
  ## 用法
8
8
 
@@ -17,7 +17,7 @@ host 面,只读既有服务与路由:
17
17
  | 导出 | `POST /api/morlay/v1/session/export`(`@morlay/session-rdb`,直接下载 zip) |
18
18
  | 删除 | `POST /api/morlay/v1/session/delete`(`@morlay/session-rdb`,仅已归档行可用) |
19
19
  | 导入为新会话 | `POST /api/morlay/v1/session/import`(`@morlay/session-rdb`,不带 `sessionId` = 新建会话) |
20
- | 清理孤儿数据 | `POST /api/morlay/v1/session/gc`(停 agent → 回收孤儿 subagent 会话 → 回收孤儿事件行 → VACUUM;执行期间阻塞界面) |
20
+ | 整理数据 | `POST /api/morlay/v1/session/organize`(停 agent → 回收孤儿 subagent 会话与孤儿事件行 → 重算全部会话的统计(用量与活动计数)→ VACUUM;执行期间阻塞界面) |
21
21
  | 用量统计 | `POST /api/morlay/v1/session/usage`(`@morlay/session-rdb` 读专用用量表聚合;进入统计视图时拉一次,维度切换本地折叠,范围切换重新请求) |
22
22
 
23
23
  归档 / 取消归档 / 删除 / 导入 / GC 成功后重拉会话行;host 拒绝(未归档 / 正在使用 / 不存在)时按错误码给出可读
package/dist/client.cjs CHANGED
@@ -38,7 +38,7 @@ window.__ModuleLoader__.load({
38
38
  const SESSION_DELETE_PATH = "/api/morlay/v1/session/delete";
39
39
  const SESSION_IMPORT_PATH = "/api/morlay/v1/session/import";
40
40
  const SESSION_EXPORT_PATH = "/api/morlay/v1/session/export";
41
- const SESSION_GC_PATH = "/api/morlay/v1/session/gc";
41
+ const SESSION_ORGANIZE_PATH = "/api/morlay/v1/session/organize";
42
42
  const SESSION_USAGE_PATH = "/api/morlay/v1/session/usage";
43
43
  const SESSION_ROWS_PATH = "/api/morlay/v1/session/rows";
44
44
  var ConversationManagerRequestError = class extends Error {
@@ -88,7 +88,7 @@ window.__ModuleLoader__.load({
88
88
  remove: (sessionId) => this.remove(sessionId),
89
89
  exportZip: (sessionId) => this.exportZip(sessionId),
90
90
  importZip: (file) => this.importZip(file),
91
- collectGarbage: () => this.collectGarbage(),
91
+ organizeData: () => this.organizeData(),
92
92
  loadUsage: (range) => this.loadUsage(range)
93
93
  };
94
94
  }
@@ -128,12 +128,13 @@ window.__ModuleLoader__.load({
128
128
  await this.ports.refresh();
129
129
  return value["sessionId"];
130
130
  }
131
- async collectGarbage() {
132
- const value = await postJson(SESSION_GC_PATH, {});
131
+ async organizeData() {
132
+ const value = await postJson(SESSION_ORGANIZE_PATH, {});
133
133
  await this.ports.refresh();
134
134
  return {
135
135
  orphanSessions: typeof value["orphanSessions"] === "number" ? value["orphanSessions"] : 0,
136
136
  orphanEvents: typeof value["orphanEvents"] === "number" ? value["orphanEvents"] : 0,
137
+ rebuiltSessions: typeof value["rebuiltSessions"] === "number" ? value["rebuiltSessions"] : 0,
137
138
  stoppedAgents: typeof value["stoppedAgents"] === "number" ? value["stoppedAgents"] : 0
138
139
  };
139
140
  }
@@ -1599,25 +1600,25 @@ window.__ModuleLoader__.load({
1599
1600
  document.head.appendChild(tag);
1600
1601
  }
1601
1602
  var schema_form_module_css_default = {
1602
- "editorRoot": "oZhWGq_editorRoot",
1603
- "lineNumber": "oZhWGq_lineNumber",
1604
- "lineFold": "oZhWGq_lineFold",
1605
- "lineActions": "oZhWGq_lineActions",
1606
- "hoverActions": "oZhWGq_hoverActions",
1607
- "lineToken": "oZhWGq_lineToken",
1608
- "valueSlot": "oZhWGq_valueSlot",
1609
- "addWrap": "oZhWGq_addWrap",
1610
- "lineBody": "oZhWGq_lineBody",
1611
- "hint": "oZhWGq_hint",
1612
1603
  "lineInvalid": "oZhWGq_lineInvalid",
1613
- "valueTrigger": "oZhWGq_valueTrigger",
1604
+ "compactTextField": "oZhWGq_compactTextField",
1605
+ "valueSlot": "oZhWGq_valueSlot",
1606
+ "compactInput": "oZhWGq_compactInput",
1607
+ "editorRoot": "oZhWGq_editorRoot",
1614
1608
  "lineRow": "oZhWGq_lineRow",
1615
1609
  "lineValue": "oZhWGq_lineValue",
1616
- "compactInput": "oZhWGq_compactInput",
1617
- "compactTextField": "oZhWGq_compactTextField",
1610
+ "lineKey": "oZhWGq_lineKey",
1618
1611
  "lineFoldSpacer": "oZhWGq_lineFoldSpacer",
1612
+ "lineActions": "oZhWGq_lineActions",
1613
+ "addWrap": "oZhWGq_addWrap",
1614
+ "hint": "oZhWGq_hint",
1619
1615
  "lineComment": "oZhWGq_lineComment",
1620
- "lineKey": "oZhWGq_lineKey"
1616
+ "lineToken": "oZhWGq_lineToken",
1617
+ "valueTrigger": "oZhWGq_valueTrigger",
1618
+ "lineBody": "oZhWGq_lineBody",
1619
+ "lineNumber": "oZhWGq_lineNumber",
1620
+ "hoverActions": "oZhWGq_hoverActions",
1621
+ "lineFold": "oZhWGq_lineFold"
1621
1622
  };
1622
1623
  // ../../client/dsh-client-ui-primitives/src/client/schema-form/TruncatedTooltip.tsx
1623
1624
  function TruncatedTooltip({ label, children }) {
@@ -2601,55 +2602,55 @@ window.__ModuleLoader__.load({
2601
2602
  document.head.appendChild(tag);
2602
2603
  }
2603
2604
  var layout_module_css_default = {
2604
- "toneDanger": "uxI0LG_toneDanger",
2605
- "padCard": "uxI0LG_padCard",
2606
- "fixed": "uxI0LG_fixed",
2607
- "padRow": "uxI0LG_padRow",
2608
- "plain": "uxI0LG_plain",
2605
+ "padPage": "uxI0LG_padPage",
2609
2606
  "gapWide": "uxI0LG_gapWide",
2610
- "row": "uxI0LG_row",
2611
- "justifyBetween": "uxI0LG_justifyBetween",
2612
- "tabular": "uxI0LG_tabular",
2613
- "fill": "uxI0LG_fill",
2614
- "alignCenter": "uxI0LG_alignCenter",
2615
- "toneTertiary": "uxI0LG_toneTertiary",
2616
- "sizeLg": "uxI0LG_sizeLg",
2617
- "padBody": "uxI0LG_padBody",
2618
- "truncate": "uxI0LG_truncate",
2619
- "justifyCenter": "uxI0LG_justifyCenter",
2620
- "padNone": "uxI0LG_padNone",
2621
- "gap0": "uxI0LG_gap0",
2622
- "gap2": "uxI0LG_gap2",
2623
- "alignStart": "uxI0LG_alignStart",
2624
- "scroll": "uxI0LG_scroll",
2607
+ "tonePrimary": "uxI0LG_tonePrimary",
2625
2608
  "gap4": "uxI0LG_gap4",
2626
- "sizeMd": "uxI0LG_sizeMd",
2627
- "padBlocking": "uxI0LG_padBlocking",
2628
- "mono": "uxI0LG_mono",
2629
- "alignEnd": "uxI0LG_alignEnd",
2630
- "gap8": "uxI0LG_gap8",
2631
- "gap14": "uxI0LG_gap14",
2632
- "text": "uxI0LG_text",
2633
- "gap16": "uxI0LG_gap16",
2609
+ "sizeXs": "uxI0LG_sizeXs",
2634
2610
  "strong": "uxI0LG_strong",
2635
- "boxed": "uxI0LG_boxed",
2636
- "weightMedium": "uxI0LG_weightMedium",
2637
- "stack": "uxI0LG_stack",
2638
- "gap6": "uxI0LG_gap6",
2639
- "narrow": "uxI0LG_narrow",
2640
2611
  "wrap": "uxI0LG_wrap",
2612
+ "truncate": "uxI0LG_truncate",
2613
+ "sizeMd": "uxI0LG_sizeMd",
2614
+ "toneSecondary": "uxI0LG_toneSecondary",
2641
2615
  "wSearch": "uxI0LG_wSearch",
2616
+ "push": "uxI0LG_push",
2617
+ "text": "uxI0LG_text",
2618
+ "stack": "uxI0LG_stack",
2619
+ "boxed": "uxI0LG_boxed",
2620
+ "padCard": "uxI0LG_padCard",
2621
+ "grow": "uxI0LG_grow",
2622
+ "justifyBetween": "uxI0LG_justifyBetween",
2623
+ "padBlocking": "uxI0LG_padBlocking",
2624
+ "gap16": "uxI0LG_gap16",
2625
+ "gap8": "uxI0LG_gap8",
2626
+ "padRow": "uxI0LG_padRow",
2642
2627
  "sizeSm": "uxI0LG_sizeSm",
2628
+ "row": "uxI0LG_row",
2643
2629
  "sizeBase": "uxI0LG_sizeBase",
2644
- "sizeXs": "uxI0LG_sizeXs",
2645
2630
  "gap12": "uxI0LG_gap12",
2646
- "push": "uxI0LG_push",
2647
- "toneSecondary": "uxI0LG_toneSecondary",
2631
+ "toneTertiary": "uxI0LG_toneTertiary",
2632
+ "fill": "uxI0LG_fill",
2633
+ "scroll": "uxI0LG_scroll",
2648
2634
  "gap10": "uxI0LG_gap10",
2649
- "grow": "uxI0LG_grow",
2650
- "padPage": "uxI0LG_padPage",
2635
+ "gap14": "uxI0LG_gap14",
2636
+ "justifyCenter": "uxI0LG_justifyCenter",
2637
+ "plain": "uxI0LG_plain",
2638
+ "gap6": "uxI0LG_gap6",
2639
+ "padNone": "uxI0LG_padNone",
2640
+ "alignEnd": "uxI0LG_alignEnd",
2651
2641
  "justifyEnd": "uxI0LG_justifyEnd",
2652
- "tonePrimary": "uxI0LG_tonePrimary"
2642
+ "padBody": "uxI0LG_padBody",
2643
+ "gap2": "uxI0LG_gap2",
2644
+ "sizeLg": "uxI0LG_sizeLg",
2645
+ "weightMedium": "uxI0LG_weightMedium",
2646
+ "mono": "uxI0LG_mono",
2647
+ "tabular": "uxI0LG_tabular",
2648
+ "alignCenter": "uxI0LG_alignCenter",
2649
+ "toneDanger": "uxI0LG_toneDanger",
2650
+ "gap0": "uxI0LG_gap0",
2651
+ "fixed": "uxI0LG_fixed",
2652
+ "narrow": "uxI0LG_narrow",
2653
+ "alignStart": "uxI0LG_alignStart"
2653
2654
  };
2654
2655
  // ../../client/dsh-client-ui-primitives/src/client/layout/scales.ts
2655
2656
  function gapClass(css, gap) {
@@ -2727,15 +2728,15 @@ window.__ModuleLoader__.load({
2727
2728
  document.head.appendChild(tag);
2728
2729
  }
2729
2730
  var SettingsFieldRow_module_css_default = {
2730
- "invalid": "_0Kpzea_invalid",
2731
2731
  "inline": "_0Kpzea_inline",
2732
- "badge": "_0Kpzea_badge",
2733
- "text": "_0Kpzea_text",
2732
+ "row": "_0Kpzea_row",
2734
2733
  "label": "_0Kpzea_label",
2735
- "body": "_0Kpzea_body",
2736
2734
  "reset": "_0Kpzea_reset",
2737
- "row": "_0Kpzea_row",
2738
- "hint": "_0Kpzea_hint"
2735
+ "invalid": "_0Kpzea_invalid",
2736
+ "hint": "_0Kpzea_hint",
2737
+ "badge": "_0Kpzea_badge",
2738
+ "body": "_0Kpzea_body",
2739
+ "text": "_0Kpzea_text"
2739
2740
  };
2740
2741
  // ../../client/dsh-client-ui-primitives/src/client/settings-form/SettingsFieldRow.tsx
2741
2742
  function SettingsFieldRow({ label, hint, layout = "stack", divider = false, overriddenLabel, resetLabel, onReset, invalid, children, className, ...rest }) {
@@ -2822,8 +2823,8 @@ window.__ModuleLoader__.load({
2822
2823
  document.head.appendChild(tag);
2823
2824
  }
2824
2825
  var Button_module_css_default = {
2825
- "label": "SBA8ka_label",
2826
- "danger": "SBA8ka_danger"
2826
+ "danger": "SBA8ka_danger",
2827
+ "label": "SBA8ka_label"
2827
2828
  };
2828
2829
  // ../../client/dsh-client-ui-primitives/src/client/controls/Button.tsx
2829
2830
  const Button$1 = (0, react.forwardRef)(function Button({ className, tone, ...rest }, ref) {
@@ -2845,8 +2846,8 @@ window.__ModuleLoader__.load({
2845
2846
  document.head.appendChild(tag);
2846
2847
  }
2847
2848
  var DisclosureRow_module_css_default = {
2848
- "content": "BDL1HG_content",
2849
- "contentLayout": "BDL1HG_contentLayout"
2849
+ "contentLayout": "BDL1HG_contentLayout",
2850
+ "content": "BDL1HG_content"
2850
2851
  };
2851
2852
  // ../../client/dsh-client-ui-primitives/src/client/controls/DisclosureRow.tsx
2852
2853
  function DisclosureRow(props) {
@@ -2868,9 +2869,9 @@ window.__ModuleLoader__.load({
2868
2869
  }
2869
2870
  var SeatButton_module_css_default = {
2870
2871
  "icon": "io5HbW_icon",
2871
- "expanded": "io5HbW_expanded",
2872
2872
  "label": "io5HbW_label",
2873
2873
  "chevron": "io5HbW_chevron",
2874
+ "expanded": "io5HbW_expanded",
2874
2875
  "seat": "io5HbW_seat"
2875
2876
  };
2876
2877
  // ../../client/dsh-client-ui-primitives/src/client/controls/SeatButton.tsx
@@ -2992,16 +2993,16 @@ window.__ModuleLoader__.load({
2992
2993
  document.head.appendChild(tag);
2993
2994
  }
2994
2995
  var ModelRouteList_module_css_default = {
2995
- "list": "aGmQkW_list",
2996
- "error": "aGmQkW_error",
2997
- "id": "aGmQkW_id",
2998
2996
  "group": "aGmQkW_group",
2997
+ "notice": "aGmQkW_notice",
2998
+ "id": "aGmQkW_id",
2999
+ "error": "aGmQkW_error",
3000
+ "text": "aGmQkW_text",
2999
3001
  "provider": "aGmQkW_provider",
3000
- "picked": "aGmQkW_picked",
3001
- "name": "aGmQkW_name",
3002
3002
  "item": "aGmQkW_item",
3003
- "text": "aGmQkW_text",
3004
- "notice": "aGmQkW_notice"
3003
+ "name": "aGmQkW_name",
3004
+ "list": "aGmQkW_list",
3005
+ "picked": "aGmQkW_picked"
3005
3006
  };
3006
3007
  // ../../client/dsh-client-ui-primitives/src/client/controls/ModelRouteList.tsx
3007
3008
  function ModelRouteList({ label, candidates, selectedKey, disabled = false, status, loadingLabel, errorLabel, emptyLabel, onSelect }) {
@@ -3104,10 +3105,10 @@ window.__ModuleLoader__.load({
3104
3105
  document.head.appendChild(tag);
3105
3106
  }
3106
3107
  var SearchSelect_module_css_default = {
3107
- "empty": "pNIIcq_empty",
3108
3108
  "searchInput": "pNIIcq_searchInput",
3109
3109
  "trigger": "pNIIcq_trigger",
3110
- "searchRow": "pNIIcq_searchRow"
3110
+ "searchRow": "pNIIcq_searchRow",
3111
+ "empty": "pNIIcq_empty"
3111
3112
  };
3112
3113
  // ../../client/dsh-client-ui-primitives/src/client/controls/SearchSelect.tsx
3113
3114
  function SearchSelect({ label, value, emptyLabel, options, disabled = false, searchLabel, noMatchLabel, onSelect }) {
@@ -3217,13 +3218,13 @@ window.__ModuleLoader__.load({
3217
3218
  document.head.appendChild(tag);
3218
3219
  }
3219
3220
  var TagInput_module_css_default = {
3220
- "anchor": "_0uSpIq_anchor",
3221
- "box": "_0uSpIq_box",
3221
+ "row": "_0uSpIq_row",
3222
3222
  "input": "_0uSpIq_input",
3223
- "chip": "_0uSpIq_chip",
3223
+ "chipRemove": "_0uSpIq_chipRemove",
3224
+ "anchor": "_0uSpIq_anchor",
3224
3225
  "empty": "_0uSpIq_empty",
3225
- "row": "_0uSpIq_row",
3226
- "chipRemove": "_0uSpIq_chipRemove"
3226
+ "box": "_0uSpIq_box",
3227
+ "chip": "_0uSpIq_chip"
3227
3228
  };
3228
3229
  // ../../client/dsh-client-ui-primitives/src/client/controls/TagInput.tsx
3229
3230
  function TagInput({ value, onChange, options, placeholder, label, disabled = false, noMatchLabel = "", removeLabel }) {
@@ -18050,24 +18051,24 @@ window.__ModuleLoader__.load({
18050
18051
  document.head.appendChild(tag);
18051
18052
  }
18052
18053
  var ConversationManagerPage_module_css_default = {
18054
+ "pageContent": "hENcOW_pageContent",
18055
+ "headingActions": "hENcOW_headingActions",
18056
+ "statusBody": "hENcOW_statusBody",
18053
18057
  "statusText": "hENcOW_statusText",
18054
- "list": "hENcOW_list",
18055
18058
  "listStatus": "hENcOW_listStatus",
18056
- "listPane": "hENcOW_listPane",
18057
- "statusBody": "hENcOW_statusBody",
18058
- "searchField": "hENcOW_searchField",
18059
- "headingActions": "hENcOW_headingActions",
18060
- "pageHeading": "hENcOW_pageHeading",
18061
- "filterTab": "hENcOW_filterTab",
18062
- "filterTabActive": "hENcOW_filterTabActive",
18063
- "pageContent": "hENcOW_pageContent",
18064
- "statusFailure": "hENcOW_statusFailure",
18065
- "filterTabs": "hENcOW_filterTabs",
18059
+ "list": "hENcOW_list",
18066
18060
  "page": "hENcOW_page",
18067
- "status": "hENcOW_status",
18068
18061
  "pageScroll": "hENcOW_pageScroll",
18062
+ "filterTabs": "hENcOW_filterTabs",
18063
+ "pageHeading": "hENcOW_pageHeading",
18064
+ "status": "hENcOW_status",
18065
+ "filterTabActive": "hENcOW_filterTabActive",
18069
18066
  "searchClear": "hENcOW_searchClear",
18070
- "filters": "hENcOW_filters"
18067
+ "statusFailure": "hENcOW_statusFailure",
18068
+ "filters": "hENcOW_filters",
18069
+ "searchField": "hENcOW_searchField",
18070
+ "listPane": "hENcOW_listPane",
18071
+ "filterTab": "hENcOW_filterTab"
18071
18072
  };
18072
18073
  // src/client/format.ts
18073
18074
  function trim(value) {
@@ -18133,7 +18134,7 @@ window.__ModuleLoader__.load({
18133
18134
  })
18134
18135
  });
18135
18136
  }
18136
- function ConversationManagerPage({ t, listRows, archive, unarchive, remove, exportZip, importZip, collectGarbage, loadUsage }) {
18137
+ function ConversationManagerPage({ t, listRows, archive, unarchive, remove, exportZip, importZip, organizeData, loadUsage }) {
18137
18138
  const [rowsPage, setRowsPage] = (0, react.useState)(null);
18138
18139
  const [rowsFailure, setRowsFailure] = (0, react.useState)(null);
18139
18140
  const [query, setQuery] = (0, react.useState)("");
@@ -18148,7 +18149,7 @@ window.__ModuleLoader__.load({
18148
18149
  const [usageLoading, setUsageLoading] = (0, react.useState)(false);
18149
18150
  const [usageError, setUsageError] = (0, react.useState)(null);
18150
18151
  const [confirming, setConfirming] = (0, react.useState)(null);
18151
- const [gcPhase, setGcPhase] = (0, react.useState)("idle");
18152
+ const [organizePhase, setOrganizePhase] = (0, react.useState)("idle");
18152
18153
  const [importing, setImporting] = (0, react.useState)(false);
18153
18154
  const [notice, setNotice] = (0, react.useState)(null);
18154
18155
  const [failure, setFailure] = (0, react.useState)(null);
@@ -18205,19 +18206,20 @@ window.__ModuleLoader__.load({
18205
18206
  setFailure(failureText(error, t));
18206
18207
  });
18207
18208
  };
18208
- const startGc = () => {
18209
- setGcPhase("running");
18209
+ const startOrganize = () => {
18210
+ setOrganizePhase("running");
18210
18211
  setFailure(null);
18211
18212
  setNotice(null);
18212
- collectGarbage().then((result) => {
18213
- setGcPhase("idle");
18214
- setNotice(t("gc.done", {
18213
+ organizeData().then((result) => {
18214
+ setOrganizePhase("idle");
18215
+ setNotice(t("organize.done", {
18215
18216
  sessions: result.orphanSessions,
18216
- events: result.orphanEvents
18217
+ events: result.orphanEvents,
18218
+ rebuilt: result.rebuiltSessions
18217
18219
  }));
18218
18220
  reloadRows();
18219
18221
  }, (error) => {
18220
- setGcPhase("idle");
18222
+ setOrganizePhase("idle");
18221
18223
  setFailure(failureText(error, t));
18222
18224
  });
18223
18225
  };
@@ -18292,14 +18294,14 @@ window.__ModuleLoader__.load({
18292
18294
  variant: "outline",
18293
18295
  size: "sm",
18294
18296
  "data-action": "gc",
18295
- disabled: gcPhase !== "idle",
18296
- "aria-label": t("gc.button"),
18297
+ disabled: organizePhase !== "idle",
18298
+ "aria-label": t("organize.button"),
18297
18299
  onClick: () => {
18298
18300
  setFailure(null);
18299
18301
  setNotice(null);
18300
- setGcPhase("confirm");
18302
+ setOrganizePhase("confirm");
18301
18303
  },
18302
- children: t("gc.button")
18304
+ children: t("organize.button")
18303
18305
  })]
18304
18306
  })]
18305
18307
  }),
@@ -18584,38 +18586,38 @@ window.__ModuleLoader__.load({
18584
18586
  })] })
18585
18587
  }),
18586
18588
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(client_exports.Modal, {
18587
- open: gcPhase === "confirm",
18589
+ open: organizePhase === "confirm",
18588
18590
  onClose: () => {
18589
- setGcPhase("idle");
18591
+ setOrganizePhase("idle");
18590
18592
  },
18591
- title: t("gc.title"),
18593
+ title: t("organize.title"),
18592
18594
  closeLabel: t("close"),
18593
- description: t("gc.description"),
18595
+ description: t("organize.description"),
18594
18596
  footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button$1, {
18595
18597
  variant: "ghost",
18596
18598
  onClick: () => {
18597
- setGcPhase("idle");
18599
+ setOrganizePhase("idle");
18598
18600
  },
18599
- children: t("gc.cancel")
18601
+ children: t("organize.cancel")
18600
18602
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button$1, {
18601
18603
  variant: "primary",
18602
- onClick: startGc,
18603
- children: t("gc.confirm")
18604
+ onClick: startOrganize,
18605
+ children: t("organize.confirm")
18604
18606
  })] })
18605
18607
  }),
18606
18608
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(client_exports.Modal, {
18607
- open: gcPhase === "running",
18609
+ open: organizePhase === "running",
18608
18610
  onClose: () => {},
18609
18611
  headless: true,
18610
- title: t("gc.title"),
18612
+ title: t("organize.title"),
18611
18613
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Stack, {
18612
18614
  align: "center",
18613
18615
  gap: 14,
18614
18616
  pad: "blocking",
18615
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spinner, { label: t("gc.running") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Text, {
18617
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spinner, { label: t("organize.running") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Text, {
18616
18618
  as: "p",
18617
18619
  size: "md",
18618
- children: t("gc.running")
18620
+ children: t("organize.running")
18619
18621
  })]
18620
18622
  })
18621
18623
  })
@@ -18969,13 +18971,13 @@ window.__ModuleLoader__.load({
18969
18971
  "page.previous": "上一页",
18970
18972
  "page.next": "下一页",
18971
18973
  "page.label": "第 {page} / {total} 页",
18972
- "gc.button": "清理孤儿数据",
18973
- "gc.title": "清理孤儿数据",
18974
- "gc.description": "会先停止所有运行中的 Agent,期间界面不可操作;随后回收孤儿 subagent 会话与孤儿数据,并执行 VACUUM。",
18975
- "gc.confirm": "开始清理",
18976
- "gc.cancel": "取消",
18977
- "gc.running": "正在清理,请稍候…",
18978
- "gc.done": "已回收 {sessions} 条孤儿会话、{events} 行孤儿数据。",
18974
+ "organize.button": "整理数据",
18975
+ "organize.title": "整理数据",
18976
+ "organize.description": "会先停止所有运行中的 Agent,期间界面不可操作;随后回收孤儿 subagent 会话与孤儿数据,重算全部会话的统计数据(token 用量与活动计数),最后执行 VACUUM。",
18977
+ "organize.confirm": "开始整理",
18978
+ "organize.cancel": "取消",
18979
+ "organize.running": "正在整理,请稍候…",
18980
+ "organize.done": "已回收 {sessions} 条孤儿会话、{events} 行孤儿数据,并重算 {rebuilt} 个会话的统计数据。",
18979
18981
  import: "导入对话",
18980
18982
  importing: "导入中…",
18981
18983
  imported: "已导入为新会话。",
@@ -19048,13 +19050,13 @@ window.__ModuleLoader__.load({
19048
19050
  "page.previous": "Previous",
19049
19051
  "page.next": "Next",
19050
19052
  "page.label": "Page {page} / {total}",
19051
- "gc.button": "Clean orphan data",
19052
- "gc.title": "Clean orphan data",
19053
- "gc.description": "Stops every running Agent first — the UI is blocked meanwhile — then reclaims orphan subagent sessions and orphan rows, and runs VACUUM.",
19054
- "gc.confirm": "Start",
19055
- "gc.cancel": "Cancel",
19056
- "gc.running": "Cleaning, please wait…",
19057
- "gc.done": "Reclaimed {sessions} orphan sessions and {events} orphan rows.",
19053
+ "organize.button": "Organize data",
19054
+ "organize.title": "Organize data",
19055
+ "organize.description": "Stops every running Agent first — the UI is blocked meanwhile — then reclaims orphan subagent sessions and orphan rows, recomputes usage and activity statistics for all sessions, and runs VACUUM.",
19056
+ "organize.confirm": "Start",
19057
+ "organize.cancel": "Cancel",
19058
+ "organize.running": "Organizing, please wait…",
19059
+ "organize.done": "Reclaimed {sessions} orphan sessions and {events} orphan rows; recomputed statistics for {rebuilt} sessions.",
19058
19060
  import: "Import conversation",
19059
19061
  importing: "Importing…",
19060
19062
  imported: "Imported as a new session.",
package/dist/client.d.cts CHANGED
@@ -56,13 +56,13 @@ declare const zh: {
56
56
  "page.previous": string;
57
57
  "page.next": string;
58
58
  "page.label": string;
59
- "gc.button": string;
60
- "gc.title": string;
61
- "gc.description": string;
62
- "gc.confirm": string;
63
- "gc.cancel": string;
64
- "gc.running": string;
65
- "gc.done": string;
59
+ "organize.button": string;
60
+ "organize.title": string;
61
+ "organize.description": string;
62
+ "organize.confirm": string;
63
+ "organize.cancel": string;
64
+ "organize.running": string;
65
+ "organize.done": string;
66
66
  import: string;
67
67
  importing: string;
68
68
  imported: string;
@@ -148,9 +148,10 @@ interface ConversationManagerPorts {
148
148
  unarchiveSession(sessionId: SessionId): Promise<void>;
149
149
  refresh(): Promise<void>;
150
150
  }
151
- interface ConversationManagerGcResult {
151
+ interface ConversationManagerOrganizeResult {
152
152
  orphanSessions: number;
153
153
  orphanEvents: number;
154
+ rebuiltSessions: number;
154
155
  stoppedAgents: number;
155
156
  }
156
157
  interface ConversationManagerFace {
@@ -160,7 +161,7 @@ interface ConversationManagerFace {
160
161
  remove: (sessionId: SessionId) => Promise<void>;
161
162
  exportZip: (sessionId: SessionId) => Promise<void>;
162
163
  importZip: (file: File) => Promise<SessionId>;
163
- collectGarbage: () => Promise<ConversationManagerGcResult>;
164
+ organizeData: () => Promise<ConversationManagerOrganizeResult>;
164
165
  loadUsage: (range: UsageRangeKey) => Promise<SessionUsageReport>;
165
166
  }
166
167
  export declare class ConversationManagerRequestError extends Error {
@@ -175,7 +176,7 @@ export declare class ConversationManagerController {
175
176
  private remove;
176
177
  private exportZip;
177
178
  private importZip;
178
- private collectGarbage;
179
+ private organizeData;
179
180
  private loadUsage;
180
181
  }
181
182
  type ConversationManagerIconProps = PropsRuntime<"sidebar.panellist">;
package/dist/client.d.mts CHANGED
@@ -56,13 +56,13 @@ declare const zh: {
56
56
  "page.previous": string;
57
57
  "page.next": string;
58
58
  "page.label": string;
59
- "gc.button": string;
60
- "gc.title": string;
61
- "gc.description": string;
62
- "gc.confirm": string;
63
- "gc.cancel": string;
64
- "gc.running": string;
65
- "gc.done": string;
59
+ "organize.button": string;
60
+ "organize.title": string;
61
+ "organize.description": string;
62
+ "organize.confirm": string;
63
+ "organize.cancel": string;
64
+ "organize.running": string;
65
+ "organize.done": string;
66
66
  import: string;
67
67
  importing: string;
68
68
  imported: string;
@@ -148,9 +148,10 @@ interface ConversationManagerPorts {
148
148
  unarchiveSession(sessionId: SessionId): Promise<void>;
149
149
  refresh(): Promise<void>;
150
150
  }
151
- interface ConversationManagerGcResult {
151
+ interface ConversationManagerOrganizeResult {
152
152
  orphanSessions: number;
153
153
  orphanEvents: number;
154
+ rebuiltSessions: number;
154
155
  stoppedAgents: number;
155
156
  }
156
157
  interface ConversationManagerFace {
@@ -160,7 +161,7 @@ interface ConversationManagerFace {
160
161
  remove: (sessionId: SessionId) => Promise<void>;
161
162
  exportZip: (sessionId: SessionId) => Promise<void>;
162
163
  importZip: (file: File) => Promise<SessionId>;
163
- collectGarbage: () => Promise<ConversationManagerGcResult>;
164
+ organizeData: () => Promise<ConversationManagerOrganizeResult>;
164
165
  loadUsage: (range: UsageRangeKey) => Promise<SessionUsageReport>;
165
166
  }
166
167
  export declare class ConversationManagerRequestError extends Error {
@@ -175,7 +176,7 @@ export declare class ConversationManagerController {
175
176
  private remove;
176
177
  private exportZip;
177
178
  private importZip;
178
- private collectGarbage;
179
+ private organizeData;
179
180
  private loadUsage;
180
181
  }
181
182
  type ConversationManagerIconProps = PropsRuntime<"sidebar.panellist">;
package/dist/client.mjs CHANGED
@@ -6,7 +6,7 @@ import { IconArchiveOutlineRegular } from "@deepseek-ai/dsh-client-ui-primitives
6
6
  const SESSION_DELETE_PATH = "/api/morlay/v1/session/delete";
7
7
  const SESSION_IMPORT_PATH = "/api/morlay/v1/session/import";
8
8
  const SESSION_EXPORT_PATH = "/api/morlay/v1/session/export";
9
- const SESSION_GC_PATH = "/api/morlay/v1/session/gc";
9
+ const SESSION_ORGANIZE_PATH = "/api/morlay/v1/session/organize";
10
10
  const SESSION_USAGE_PATH = "/api/morlay/v1/session/usage";
11
11
  const SESSION_ROWS_PATH = "/api/morlay/v1/session/rows";
12
12
  var ConversationManagerRequestError = class extends Error {
@@ -56,7 +56,7 @@ var ConversationManagerController = class {
56
56
  remove: (sessionId) => this.remove(sessionId),
57
57
  exportZip: (sessionId) => this.exportZip(sessionId),
58
58
  importZip: (file) => this.importZip(file),
59
- collectGarbage: () => this.collectGarbage(),
59
+ organizeData: () => this.organizeData(),
60
60
  loadUsage: (range) => this.loadUsage(range)
61
61
  };
62
62
  }
@@ -96,12 +96,13 @@ var ConversationManagerController = class {
96
96
  await this.ports.refresh();
97
97
  return value["sessionId"];
98
98
  }
99
- async collectGarbage() {
100
- const value = await postJson(SESSION_GC_PATH, {});
99
+ async organizeData() {
100
+ const value = await postJson(SESSION_ORGANIZE_PATH, {});
101
101
  await this.ports.refresh();
102
102
  return {
103
103
  orphanSessions: typeof value["orphanSessions"] === "number" ? value["orphanSessions"] : 0,
104
104
  orphanEvents: typeof value["orphanEvents"] === "number" ? value["orphanEvents"] : 0,
105
+ rebuiltSessions: typeof value["rebuiltSessions"] === "number" ? value["rebuiltSessions"] : 0,
105
106
  stoppedAgents: typeof value["stoppedAgents"] === "number" ? value["stoppedAgents"] : 0
106
107
  };
107
108
  }
@@ -138,24 +139,24 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
138
139
  document.head.appendChild(tag);
139
140
  }
140
141
  var ConversationManagerPage_module_css_default = {
141
- "filterTab": "hENcOW_filterTab",
142
- "list": "hENcOW_list",
143
- "statusBody": "hENcOW_statusBody",
144
- "statusText": "hENcOW_statusText",
145
- "statusFailure": "hENcOW_statusFailure",
146
- "pageScroll": "hENcOW_pageScroll",
142
+ "filterTabActive": "hENcOW_filterTabActive",
143
+ "pageHeading": "hENcOW_pageHeading",
147
144
  "status": "hENcOW_status",
148
- "searchClear": "hENcOW_searchClear",
149
- "headingActions": "hENcOW_headingActions",
150
- "searchField": "hENcOW_searchField",
145
+ "listStatus": "hENcOW_listStatus",
151
146
  "filters": "hENcOW_filters",
147
+ "filterTabs": "hENcOW_filterTabs",
148
+ "searchField": "hENcOW_searchField",
149
+ "list": "hENcOW_list",
150
+ "filterTab": "hENcOW_filterTab",
151
+ "searchClear": "hENcOW_searchClear",
152
152
  "page": "hENcOW_page",
153
- "listPane": "hENcOW_listPane",
153
+ "pageScroll": "hENcOW_pageScroll",
154
+ "headingActions": "hENcOW_headingActions",
155
+ "statusBody": "hENcOW_statusBody",
156
+ "statusText": "hENcOW_statusText",
154
157
  "pageContent": "hENcOW_pageContent",
155
- "filterTabs": "hENcOW_filterTabs",
156
- "pageHeading": "hENcOW_pageHeading",
157
- "filterTabActive": "hENcOW_filterTabActive",
158
- "listStatus": "hENcOW_listStatus"
158
+ "statusFailure": "hENcOW_statusFailure",
159
+ "listPane": "hENcOW_listPane"
159
160
  };
160
161
  // src/client/format.ts
161
162
  function trim(value) {
@@ -221,7 +222,7 @@ function PageStatus({ t, status, text, spinner = false, failure = false }) {
221
222
  })
222
223
  });
223
224
  }
224
- function ConversationManagerPage({ t, listRows, archive, unarchive, remove, exportZip, importZip, collectGarbage, loadUsage }) {
225
+ function ConversationManagerPage({ t, listRows, archive, unarchive, remove, exportZip, importZip, organizeData, loadUsage }) {
225
226
  const [rowsPage, setRowsPage] = useState(null);
226
227
  const [rowsFailure, setRowsFailure] = useState(null);
227
228
  const [query, setQuery] = useState("");
@@ -236,7 +237,7 @@ function ConversationManagerPage({ t, listRows, archive, unarchive, remove, expo
236
237
  const [usageLoading, setUsageLoading] = useState(false);
237
238
  const [usageError, setUsageError] = useState(null);
238
239
  const [confirming, setConfirming] = useState(null);
239
- const [gcPhase, setGcPhase] = useState("idle");
240
+ const [organizePhase, setOrganizePhase] = useState("idle");
240
241
  const [importing, setImporting] = useState(false);
241
242
  const [notice, setNotice] = useState(null);
242
243
  const [failure, setFailure] = useState(null);
@@ -293,19 +294,20 @@ function ConversationManagerPage({ t, listRows, archive, unarchive, remove, expo
293
294
  setFailure(failureText(error, t));
294
295
  });
295
296
  };
296
- const startGc = () => {
297
- setGcPhase("running");
297
+ const startOrganize = () => {
298
+ setOrganizePhase("running");
298
299
  setFailure(null);
299
300
  setNotice(null);
300
- collectGarbage().then((result) => {
301
- setGcPhase("idle");
302
- setNotice(t("gc.done", {
301
+ organizeData().then((result) => {
302
+ setOrganizePhase("idle");
303
+ setNotice(t("organize.done", {
303
304
  sessions: result.orphanSessions,
304
- events: result.orphanEvents
305
+ events: result.orphanEvents,
306
+ rebuilt: result.rebuiltSessions
305
307
  }));
306
308
  reloadRows();
307
309
  }, (error) => {
308
- setGcPhase("idle");
310
+ setOrganizePhase("idle");
309
311
  setFailure(failureText(error, t));
310
312
  });
311
313
  };
@@ -380,14 +382,14 @@ function ConversationManagerPage({ t, listRows, archive, unarchive, remove, expo
380
382
  variant: "outline",
381
383
  size: "sm",
382
384
  "data-action": "gc",
383
- disabled: gcPhase !== "idle",
384
- "aria-label": t("gc.button"),
385
+ disabled: organizePhase !== "idle",
386
+ "aria-label": t("organize.button"),
385
387
  onClick: () => {
386
388
  setFailure(null);
387
389
  setNotice(null);
388
- setGcPhase("confirm");
390
+ setOrganizePhase("confirm");
389
391
  },
390
- children: t("gc.button")
392
+ children: t("organize.button")
391
393
  })]
392
394
  })]
393
395
  }),
@@ -672,38 +674,38 @@ function ConversationManagerPage({ t, listRows, archive, unarchive, remove, expo
672
674
  })] })
673
675
  }),
674
676
  /* @__PURE__ */ jsx(Modal, {
675
- open: gcPhase === "confirm",
677
+ open: organizePhase === "confirm",
676
678
  onClose: () => {
677
- setGcPhase("idle");
679
+ setOrganizePhase("idle");
678
680
  },
679
- title: t("gc.title"),
681
+ title: t("organize.title"),
680
682
  closeLabel: t("close"),
681
- description: t("gc.description"),
683
+ description: t("organize.description"),
682
684
  footer: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Button, {
683
685
  variant: "ghost",
684
686
  onClick: () => {
685
- setGcPhase("idle");
687
+ setOrganizePhase("idle");
686
688
  },
687
- children: t("gc.cancel")
689
+ children: t("organize.cancel")
688
690
  }), /* @__PURE__ */ jsx(Button, {
689
691
  variant: "primary",
690
- onClick: startGc,
691
- children: t("gc.confirm")
692
+ onClick: startOrganize,
693
+ children: t("organize.confirm")
692
694
  })] })
693
695
  }),
694
696
  /* @__PURE__ */ jsx(Modal, {
695
- open: gcPhase === "running",
697
+ open: organizePhase === "running",
696
698
  onClose: () => {},
697
699
  headless: true,
698
- title: t("gc.title"),
700
+ title: t("organize.title"),
699
701
  children: /* @__PURE__ */ jsxs(Stack, {
700
702
  align: "center",
701
703
  gap: 14,
702
704
  pad: "blocking",
703
- children: [/* @__PURE__ */ jsx(Spinner, { label: t("gc.running") }), /* @__PURE__ */ jsx(Text, {
705
+ children: [/* @__PURE__ */ jsx(Spinner, { label: t("organize.running") }), /* @__PURE__ */ jsx(Text, {
704
706
  as: "p",
705
707
  size: "md",
706
- children: t("gc.running")
708
+ children: t("organize.running")
707
709
  })]
708
710
  })
709
711
  })
@@ -1057,13 +1059,13 @@ const zh = {
1057
1059
  "page.previous": "上一页",
1058
1060
  "page.next": "下一页",
1059
1061
  "page.label": "第 {page} / {total} 页",
1060
- "gc.button": "清理孤儿数据",
1061
- "gc.title": "清理孤儿数据",
1062
- "gc.description": "会先停止所有运行中的 Agent,期间界面不可操作;随后回收孤儿 subagent 会话与孤儿数据,并执行 VACUUM。",
1063
- "gc.confirm": "开始清理",
1064
- "gc.cancel": "取消",
1065
- "gc.running": "正在清理,请稍候…",
1066
- "gc.done": "已回收 {sessions} 条孤儿会话、{events} 行孤儿数据。",
1062
+ "organize.button": "整理数据",
1063
+ "organize.title": "整理数据",
1064
+ "organize.description": "会先停止所有运行中的 Agent,期间界面不可操作;随后回收孤儿 subagent 会话与孤儿数据,重算全部会话的统计数据(token 用量与活动计数),最后执行 VACUUM。",
1065
+ "organize.confirm": "开始整理",
1066
+ "organize.cancel": "取消",
1067
+ "organize.running": "正在整理,请稍候…",
1068
+ "organize.done": "已回收 {sessions} 条孤儿会话、{events} 行孤儿数据,并重算 {rebuilt} 个会话的统计数据。",
1067
1069
  import: "导入对话",
1068
1070
  importing: "导入中…",
1069
1071
  imported: "已导入为新会话。",
@@ -1136,13 +1138,13 @@ const en = {
1136
1138
  "page.previous": "Previous",
1137
1139
  "page.next": "Next",
1138
1140
  "page.label": "Page {page} / {total}",
1139
- "gc.button": "Clean orphan data",
1140
- "gc.title": "Clean orphan data",
1141
- "gc.description": "Stops every running Agent first — the UI is blocked meanwhile — then reclaims orphan subagent sessions and orphan rows, and runs VACUUM.",
1142
- "gc.confirm": "Start",
1143
- "gc.cancel": "Cancel",
1144
- "gc.running": "Cleaning, please wait…",
1145
- "gc.done": "Reclaimed {sessions} orphan sessions and {events} orphan rows.",
1141
+ "organize.button": "Organize data",
1142
+ "organize.title": "Organize data",
1143
+ "organize.description": "Stops every running Agent first — the UI is blocked meanwhile — then reclaims orphan subagent sessions and orphan rows, recomputes usage and activity statistics for all sessions, and runs VACUUM.",
1144
+ "organize.confirm": "Start",
1145
+ "organize.cancel": "Cancel",
1146
+ "organize.running": "Organizing, please wait…",
1147
+ "organize.done": "Reclaimed {sessions} orphan sessions and {events} orphan rows; recomputed statistics for {rebuilt} sessions.",
1146
1148
  import: "Import conversation",
1147
1149
  importing: "Importing…",
1148
1150
  imported: "Imported as a new session.",
package/locale/en.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "Conversation Manager",
4
- "description": "Full-page conversation management panel (browser half): two tab levels over sessions and usage — search, paging, archive / unarchive / export / delete, import as a new session and orphan-data GC in the session view, token usage across all conversations in the usage view."
4
+ "description": "Full-page conversation management panel (browser half): two tab levels over sessions and usage — search, paging, archive / unarchive / export / delete, import as a new session and data organization (orphan reclaim + statistics rebuild) in the session view, token usage across all conversations in the usage view."
5
5
  }
6
6
  }
package/locale/zh.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "meta": {
3
3
  "title": "对话管理页",
4
- "description": "「对话管理」全局面板页(浏览器半):会话与统计两层 Tabs——会话视图给出全量会话(含已归档)的搜索、分页、归档 / 取消归档 / 导出 / 删除、导入为新会话与孤儿数据 GC,统计视图给出全部对话的 token 用量。"
4
+ "description": "「对话管理」全局面板页(浏览器半):会话与统计两层 Tabs——会话视图给出全量会话(含已归档)的搜索、分页、归档 / 取消归档 / 导出 / 删除、导入为新会话与整理数据(孤儿回收 + 统计重算),统计视图给出全部对话的 token 用量。"
5
5
  }
6
6
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@morlay/ui-conversation-manager",
3
- "version": "0.1.11-alpha.0",
4
- "description": "「对话管理」全局面板页(浏览器半):会话与统计两层 Tabs——会话视图给出全量会话(含已归档)的搜索、分页、归档 / 取消归档 / 导出 / 删除、导入为新会话与孤儿数据 GC,统计视图给出全部对话的 token 用量。",
3
+ "version": "0.1.11-alpha.3",
4
+ "description": "「对话管理」全局面板页(浏览器半):会话与统计两层 Tabs——会话视图给出全量会话(含已归档)的搜索、分页、归档 / 取消归档 / 导出 / 删除、导入为新会话与整理数据(孤儿回收 + 统计重算),统计视图给出全部对话的 token 用量。",
5
5
  "keywords": [
6
6
  "archived-sessions",
7
7
  "conversation-manager",
@@ -36,7 +36,7 @@
36
36
  "./locale/*.json": "./locale/*.json"
37
37
  },
38
38
  "dependencies": {
39
- "@morlay/dsh-client-ui-primitives": "0.0.14-alpha.0"
39
+ "@morlay/dsh-client-ui-primitives": "0.0.14-alpha.3"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@testing-library/react": "^16.1.0",
@@ -45,21 +45,21 @@
45
45
  "react-dom": "^18.2.0"
46
46
  },
47
47
  "peerDependencies": {
48
- "@deepseek-ai/cordis": "^4.0.6-alpha.1",
49
- "@deepseek-ai/dsh-api-session-controller": "^0.2.2-alpha.2",
50
- "@deepseek-ai/dsh-client-locale": "^0.2.2-alpha.2",
51
- "@deepseek-ai/dsh-client-ui-layout": "^0.2.2-alpha.2",
52
- "@deepseek-ai/dsh-client-ui-primitives": "^0.2.2-alpha.2",
53
- "@deepseek-ai/dsh-client-ui-renderer": "^0.2.2-alpha.2",
54
- "@deepseek-ai/dsh-client-ui-session": "^0.2.2-alpha.2",
55
- "@deepseek-ai/dsh-client-ui-sidebar": "^0.2.2-alpha.2",
56
- "@deepseek-ai/dsh-client-ui-slots": "^0.2.2-alpha.2",
57
- "@deepseek-ai/dsh-client-ui-workspace": "^0.2.2-alpha.2",
58
- "@deepseek-ai/dsh-session": "^0.2.2-alpha.2",
48
+ "@deepseek-ai/cordis": "^4.0.6-alpha.2",
49
+ "@deepseek-ai/dsh-api-session-controller": "^0.2.2-alpha.3",
50
+ "@deepseek-ai/dsh-client-locale": "^0.2.2-alpha.3",
51
+ "@deepseek-ai/dsh-client-ui-layout": "^0.2.2-alpha.3",
52
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.2.2-alpha.3",
53
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.2.2-alpha.3",
54
+ "@deepseek-ai/dsh-client-ui-session": "^0.2.2-alpha.3",
55
+ "@deepseek-ai/dsh-client-ui-sidebar": "^0.2.2-alpha.3",
56
+ "@deepseek-ai/dsh-client-ui-slots": "^0.2.2-alpha.3",
57
+ "@deepseek-ai/dsh-client-ui-workspace": "^0.2.2-alpha.3",
58
+ "@deepseek-ai/dsh-session": "^0.2.2-alpha.3",
59
59
  "react": "^18.2.0"
60
60
  },
61
61
  "engines": {
62
- "dsh": ">= 0.2.2-alpha.2 < 0.2.3"
62
+ "dsh": ">= 0.2.2-alpha.3 < 0.2.3"
63
63
  },
64
64
  "dsh": {
65
65
  "client": {
@@ -1,4 +1,4 @@
1
- // 「对话管理」页面:已归档会话的搜索、取消归档、导出、删除,以及导入为新会话与孤儿数据 GC。
1
+ // 「对话管理」页面:已归档会话的搜索、取消归档、导出、删除,以及导入为新会话与整理数据(孤儿回收 + 统计重算)。
2
2
  // 数据面:会话行读**我们自己的**列表路由(注入面 listRows,含归档;搜索 / 子代理过滤 / 分页都在后端),
3
3
  // 动作面只读注入面。
4
4
  // 形态:页面框架与上游一级页面同款(960px 居中列 + 标题行 + 过滤 chip 行 + 搜索行,见
@@ -45,8 +45,8 @@ export type ConversationManagerPageProps = PropsRuntime<"main"> &
45
45
 
46
46
  type Translate = ConversationManagerPageProps["t"];
47
47
 
48
- // GC 的三段状态:确认 → 运行(阻塞界面)→ 收尾。
49
- type GcPhase = "idle" | "confirm" | "running";
48
+ // 整理数据的三段状态:确认 → 运行(阻塞界面)→ 收尾。
49
+ type OrganizePhase = "idle" | "confirm" | "running";
50
50
 
51
51
  interface ConversationRow {
52
52
  id: SessionId;
@@ -146,7 +146,7 @@ export function ConversationManagerPage({
146
146
  remove,
147
147
  exportZip,
148
148
  importZip,
149
- collectGarbage,
149
+ organizeData,
150
150
  loadUsage,
151
151
  }: ConversationManagerPageProps): ReactNode {
152
152
  // 数据面是**我们自己的**列表路由(完整语料,含归档):官方 `session/list` 按部署策略排除归档,
@@ -165,7 +165,7 @@ export function ConversationManagerPage({
165
165
  const [usageLoading, setUsageLoading] = useState(false);
166
166
  const [usageError, setUsageError] = useState<string | null>(null);
167
167
  const [confirming, setConfirming] = useState<ConversationRow | null>(null);
168
- const [gcPhase, setGcPhase] = useState<GcPhase>("idle");
168
+ const [organizePhase, setOrganizePhase] = useState<OrganizePhase>("idle");
169
169
  const [importing, setImporting] = useState(false);
170
170
  const [notice, setNotice] = useState<string | null>(null);
171
171
  const [failure, setFailure] = useState<string | null>(null);
@@ -236,18 +236,24 @@ export function ConversationManagerPage({
236
236
  );
237
237
  };
238
238
 
239
- const startGc = (): void => {
240
- setGcPhase("running");
239
+ const startOrganize = (): void => {
240
+ setOrganizePhase("running");
241
241
  setFailure(null);
242
242
  setNotice(null);
243
- void collectGarbage().then(
243
+ void organizeData().then(
244
244
  (result) => {
245
- setGcPhase("idle");
246
- setNotice(t("gc.done", { sessions: result.orphanSessions, events: result.orphanEvents }));
245
+ setOrganizePhase("idle");
246
+ setNotice(
247
+ t("organize.done", {
248
+ sessions: result.orphanSessions,
249
+ events: result.orphanEvents,
250
+ rebuilt: result.rebuiltSessions,
251
+ }),
252
+ );
247
253
  void reloadRows();
248
254
  },
249
255
  (error: unknown) => {
250
- setGcPhase("idle");
256
+ setOrganizePhase("idle");
251
257
  setFailure(failureText(error, t));
252
258
  },
253
259
  );
@@ -324,15 +330,15 @@ export function ConversationManagerPage({
324
330
  variant="outline"
325
331
  size="sm"
326
332
  data-action="gc"
327
- disabled={gcPhase !== "idle"}
328
- aria-label={t("gc.button")}
333
+ disabled={organizePhase !== "idle"}
334
+ aria-label={t("organize.button")}
329
335
  onClick={() => {
330
336
  setFailure(null);
331
337
  setNotice(null);
332
- setGcPhase("confirm");
338
+ setOrganizePhase("confirm");
333
339
  }}
334
340
  >
335
- {t("gc.button")}
341
+ {t("organize.button")}
336
342
  </Button>
337
343
  </div>
338
344
  </div>
@@ -619,35 +625,35 @@ export function ConversationManagerPage({
619
625
  }
620
626
  />
621
627
  <Modal
622
- open={gcPhase === "confirm"}
628
+ open={organizePhase === "confirm"}
623
629
  onClose={() => {
624
- setGcPhase("idle");
630
+ setOrganizePhase("idle");
625
631
  }}
626
- title={t("gc.title")}
632
+ title={t("organize.title")}
627
633
  closeLabel={t("close")}
628
- description={t("gc.description")}
634
+ description={t("organize.description")}
629
635
  footer={
630
636
  <>
631
637
  <Button
632
638
  variant="ghost"
633
639
  onClick={() => {
634
- setGcPhase("idle");
640
+ setOrganizePhase("idle");
635
641
  }}
636
642
  >
637
- {t("gc.cancel")}
643
+ {t("organize.cancel")}
638
644
  </Button>
639
- <Button variant="primary" onClick={startGc}>
640
- {t("gc.confirm")}
645
+ <Button variant="primary" onClick={startOrganize}>
646
+ {t("organize.confirm")}
641
647
  </Button>
642
648
  </>
643
649
  }
644
650
  />
645
651
  {/* 运行期不给关闭手段:没有关闭按钮,mask 与 Escape 都只走空 onClose。 */}
646
- <Modal open={gcPhase === "running"} onClose={() => {}} headless title={t("gc.title")}>
652
+ <Modal open={organizePhase === "running"} onClose={() => {}} headless title={t("organize.title")}>
647
653
  <Stack align="center" gap={14} pad="blocking">
648
- <Spinner label={t("gc.running")} />
654
+ <Spinner label={t("organize.running")} />
649
655
  <Text as="p" size="md">
650
- {t("gc.running")}
656
+ {t("organize.running")}
651
657
  </Text>
652
658
  </Stack>
653
659
  </Modal>
@@ -4,7 +4,7 @@ import type { SessionId } from "@deepseek-ai/dsh-session";
4
4
  export const SESSION_DELETE_PATH = "/api/morlay/v1/session/delete";
5
5
  export const SESSION_IMPORT_PATH = "/api/morlay/v1/session/import";
6
6
  export const SESSION_EXPORT_PATH = "/api/morlay/v1/session/export";
7
- export const SESSION_GC_PATH = "/api/morlay/v1/session/gc";
7
+ export const SESSION_ORGANIZE_PATH = "/api/morlay/v1/session/organize";
8
8
  export const SESSION_USAGE_PATH = "/api/morlay/v1/session/usage";
9
9
 
10
10
  // 管理面的会话行(**完整语料,含归档**):我们自己的路由,与官方 `session/list` 分开——那条按部署策略
@@ -98,10 +98,12 @@ export interface ConversationManagerPorts {
98
98
  refresh(): Promise<void>;
99
99
  }
100
100
 
101
- // GC 一次执行的回报。
102
- export interface ConversationManagerGcResult {
101
+ // 一次「整理数据」的回报。
102
+ export interface ConversationManagerOrganizeResult {
103
103
  orphanSessions: number;
104
104
  orphanEvents: number;
105
+ // 统计表全量重算涉及的会话数。
106
+ rebuiltSessions: number;
105
107
  stoppedAgents: number;
106
108
  }
107
109
 
@@ -114,7 +116,7 @@ export interface ConversationManagerFace {
114
116
  remove: (sessionId: SessionId) => Promise<void>;
115
117
  exportZip: (sessionId: SessionId) => Promise<void>;
116
118
  importZip: (file: File) => Promise<SessionId>;
117
- collectGarbage: () => Promise<ConversationManagerGcResult>;
119
+ organizeData: () => Promise<ConversationManagerOrganizeResult>;
118
120
  loadUsage: (range: UsageRangeKey) => Promise<SessionUsageReport>;
119
121
  }
120
122
 
@@ -175,7 +177,7 @@ export class ConversationManagerController {
175
177
  remove: (sessionId) => this.remove(sessionId),
176
178
  exportZip: (sessionId) => this.exportZip(sessionId),
177
179
  importZip: (file) => this.importZip(file),
178
- collectGarbage: () => this.collectGarbage(),
180
+ organizeData: () => this.organizeData(),
179
181
  loadUsage: (range) => this.loadUsage(range),
180
182
  };
181
183
  }
@@ -228,12 +230,13 @@ export class ConversationManagerController {
228
230
  return value["sessionId"] as SessionId;
229
231
  }
230
232
 
231
- private async collectGarbage(): Promise<ConversationManagerGcResult> {
232
- const value = await postJson(SESSION_GC_PATH, {});
233
+ private async organizeData(): Promise<ConversationManagerOrganizeResult> {
234
+ const value = await postJson(SESSION_ORGANIZE_PATH, {});
233
235
  await this.ports.refresh();
234
236
  return {
235
237
  orphanSessions: typeof value["orphanSessions"] === "number" ? value["orphanSessions"] : 0,
236
238
  orphanEvents: typeof value["orphanEvents"] === "number" ? value["orphanEvents"] : 0,
239
+ rebuiltSessions: typeof value["rebuiltSessions"] === "number" ? value["rebuiltSessions"] : 0,
237
240
  stoppedAgents: typeof value["stoppedAgents"] === "number" ? value["stoppedAgents"] : 0,
238
241
  };
239
242
  }
@@ -54,14 +54,15 @@ export const zh = {
54
54
  "page.previous": "上一页",
55
55
  "page.next": "下一页",
56
56
  "page.label": "第 {page} / {total} 页",
57
- "gc.button": "清理孤儿数据",
58
- "gc.title": "清理孤儿数据",
59
- "gc.description":
60
- "会先停止所有运行中的 Agent,期间界面不可操作;随后回收孤儿 subagent 会话与孤儿数据,并执行 VACUUM。",
61
- "gc.confirm": "开始清理",
62
- "gc.cancel": "取消",
63
- "gc.running": "正在清理,请稍候…",
64
- "gc.done": "已回收 {sessions} 条孤儿会话、{events} 行孤儿数据。",
57
+ "organize.button": "整理数据",
58
+ "organize.title": "整理数据",
59
+ "organize.description":
60
+ "会先停止所有运行中的 Agent,期间界面不可操作;随后回收孤儿 subagent 会话与孤儿数据,重算全部会话的统计数据(token 用量与活动计数),最后执行 VACUUM。",
61
+ "organize.confirm": "开始整理",
62
+ "organize.cancel": "取消",
63
+ "organize.running": "正在整理,请稍候…",
64
+ "organize.done":
65
+ "已回收 {sessions} 条孤儿会话、{events} 行孤儿数据,并重算 {rebuilt} 个会话的统计数据。",
65
66
  import: "导入对话",
66
67
  importing: "导入中…",
67
68
  imported: "已导入为新会话。",
@@ -139,14 +140,15 @@ export const en = {
139
140
  "page.previous": "Previous",
140
141
  "page.next": "Next",
141
142
  "page.label": "Page {page} / {total}",
142
- "gc.button": "Clean orphan data",
143
- "gc.title": "Clean orphan data",
144
- "gc.description":
145
- "Stops every running Agent first — the UI is blocked meanwhile — then reclaims orphan subagent sessions and orphan rows, and runs VACUUM.",
146
- "gc.confirm": "Start",
147
- "gc.cancel": "Cancel",
148
- "gc.running": "Cleaning, please wait…",
149
- "gc.done": "Reclaimed {sessions} orphan sessions and {events} orphan rows.",
143
+ "organize.button": "Organize data",
144
+ "organize.title": "Organize data",
145
+ "organize.description":
146
+ "Stops every running Agent first — the UI is blocked meanwhile — then reclaims orphan subagent sessions and orphan rows, recomputes usage and activity statistics for all sessions, and runs VACUUM.",
147
+ "organize.confirm": "Start",
148
+ "organize.cancel": "Cancel",
149
+ "organize.running": "Organizing, please wait…",
150
+ "organize.done":
151
+ "Reclaimed {sessions} orphan sessions and {events} orphan rows; recomputed statistics for {rebuilt} sessions.",
150
152
  import: "Import conversation",
151
153
  importing: "Importing…",
152
154
  imported: "Imported as a new session.",