@michengai/dsh-codex-ui 0.2.103 → 0.2.104

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/CHANGELOG.md CHANGED
@@ -4,6 +4,37 @@
4
4
 
5
5
  This changelog records recent releases of DSH Codex UI and its one-click installer. Earlier changes remain available in the [Git history](https://github.com/MichengAI/dsh-codex-ui/commits/main).
6
6
 
7
+ ## 0.2.104 — 2026-09-06
8
+
9
+ Companion release: `@michengai/dsh-codex-suite-installer@0.1.21`.
10
+
11
+ ### Added
12
+
13
+ - Moved Up/Down input history from BTW into Codex UI, with workspace persistence, legacy history import, and guards for drafts, IME, and candidate menus.
14
+ - Added BTW at the end of the first-party About list with existing install and update actions; shortened the archive label to "Archived conversations".
15
+
16
+ ### Fixed
17
+
18
+ - Capture only live appended messages after mounting, preventing duplicate history when opening, reloading, or replacing conversation windows. Messages sent while unmounted are not backfilled.
19
+ - Preserve the history cursor during synchronous draft writes for consecutive Up/Down navigation, and resume live collection after window revision resets.
20
+ - Declare the official input-trigger peer dependency and add contracts for the BTW package, display order, and localized names.
21
+
22
+ ### Validation
23
+
24
+ - Type checking, 96 tests, the build, and 31 assertion scripts passed. Actual DSH interaction acceptance remains pending user testing after local installation.
25
+
26
+ ## suite-installer-v0.1.21 — 2026-09-06
27
+
28
+ ### Dependencies
29
+
30
+ - Pin Codex UI to `0.2.104`, including input history, About-page updates, and their fixes.
31
+ - Update Skills Manager, Agency Agents, and Automation to `0.1.40`, `0.1.32`, and `0.1.31`, respectively; keep Archive Manager at `0.1.30` and IM Connect at `0.1.34`.
32
+ - Continue installing exact member versions with `--save-exact` for reproducible installations.
33
+
34
+ ### Release
35
+
36
+ - Extract GitHub Release notes from both CHANGELOG files, with Chinese first and English second.
37
+
7
38
  ## 0.2.103 — 2026-09-04
8
39
 
9
40
  Companion release: `@michengai/dsh-codex-suite-installer@0.1.20`.
@@ -4,6 +4,37 @@
4
4
 
5
5
  本日志记录 DSH Codex UI 及其一键安装器的最近发布;更早的变更可查看 [Git 提交历史](https://github.com/MichengAI/dsh-codex-ui/commits/main)。
6
6
 
7
+ ## 0.2.104 — 2026-09-06
8
+
9
+ 配套版本:`@michengai/dsh-codex-suite-installer@0.1.21`。
10
+
11
+ ### 新增
12
+
13
+ - 将上下键输入历史从 BTW 迁入 Codex UI,按工作区持久化、支持旧历史导入,并保护草稿、输入法和候选菜单。
14
+ - 在关于页的自研插件末尾加入 BTW 旁问,复用安装更新入口;将“归档会话管理”简化为“归档会话”。
15
+
16
+ ### 修复
17
+
18
+ - 仅采集挂载后的实时追加消息,避免打开、重载或替换会话窗口时重复写入历史;未挂载期间的消息不补录。
19
+ - 保护自身同步回写期间的历史游标,支持连续上下键;窗口版本归零后恢复实时采集。
20
+ - 补齐官方 input-trigger 的 peer 依赖声明,并增加 BTW 包名、显示顺序和中英文名称契约。
21
+
22
+ ### 验证
23
+
24
+ - 类型检查、96 项测试、构建和 31 组断言通过;真实 DSH 交互验收仍由用户在本地安装后执行。
25
+
26
+ ## suite-installer-v0.1.21 — 2026-09-06
27
+
28
+ ### 依赖
29
+
30
+ - 将 Codex UI 钉定到 `0.2.104`,包含输入历史与关于页改动及其修复。
31
+ - 将 Skills Manager、Agency Agents 和 Automation 分别更新到 `0.1.40`、`0.1.32` 和 `0.1.31`;Archive Manager 保持 `0.1.30`,IM Connect 保持 `0.1.34`。
32
+ - 安装器继续使用精确版本及 `--save-exact`,确保安装可复现。
33
+
34
+ ### 发布
35
+
36
+ - GitHub Release 说明改为从中英文 CHANGELOG 提取,中文在前、英文在后。
37
+
7
38
  ## 0.2.103 — 2026-09-04
8
39
 
9
40
  配套版本:`@michengai/dsh-codex-suite-installer@0.1.20`。
package/README.md CHANGED
@@ -27,6 +27,8 @@
27
27
  - List workspaces and conversations with expand/collapse, drag reorder, project pinning, unread dots, and running-state indicators.
28
28
  - Add project and conversation menus for rename, pin, unread, archive, fork, open folder, copy, and delete.
29
29
  - Restyle the conversation column and composer card, and add a compact turn navigator on the current session.
30
+ - Recall submitted text with Up/Down from an empty composer, with workspace isolation and guards for drafts, IME, and candidate menus. BTW is not required.
31
+ - Capture ordinary messages only from live events while the input extension is mounted. Opening or reloading conversations and loading older messages do not backfill history; input sent while the extension is unmounted is not imported.
30
32
  - Show companion-plugin status in **Settings → About**, and install the missing pieces from npm.
31
33
 
32
34
  ## Screenshots
package/README.zh-CN.md CHANGED
@@ -27,10 +27,15 @@
27
27
  - 工作区与会话支持展开折叠、拖拽排序、项目置顶、未读圆点和运行状态。
28
28
  - 项目和会话菜单支持重命名、置顶、未读、归档、派生、打开目录、复制和删除。
29
29
  - 调整会话列与输入卡片视觉,并为当前会话提供紧凑轮次导航。
30
+ - 空输入框按上下键召回已提交文本,按工作区隔离并保护草稿、输入法和候选菜单;无需安装 BTW。
30
31
  - 在「设置 → 关于」展示配套插件状态,并可从 npm 安装缺失项。
31
32
 
32
33
  ## 界面预览
33
34
 
35
+ 输入历史保存在浏览器 `michengai.codex-ui.input-history.v1`,每工作区最多 200 条、最多 20 个工作区,总序列化长度最多 100 万字符。首次使用可导入旧 BTW 历史,保留旧键用于回退;关闭浏览器存储时使用内存。BTW 插件现在只负责旁问气泡。
36
+
37
+ 普通消息仅从输入扩展挂载后的实时追加事件采集;打开、重载会话和加载旧消息不会回填历史,扩展未挂载期间的输入也不补录。
38
+
34
39
  浅色主题:Codex 风格侧栏、工作区会话树和会话列。
35
40
 
36
41
  ![浅色主题会话页](assets/screenshots/conversation-light.png)
package/lib/client.js CHANGED
@@ -5952,6 +5952,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
5952
5952
  id: "schedule",
5953
5953
  packageName: "@michengai/dsh-automation"
5954
5954
  },
5955
+ {
5956
+ id: "btw",
5957
+ packageName: "@michengai/dsh-btw"
5958
+ },
5955
5959
  {
5956
5960
  id: "market",
5957
5961
  packageName: "dshmarket"
@@ -6482,6 +6486,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
6482
6486
  /** 本插件独占的界面文案命名空间。 */
6483
6487
  const NS = "michengai.codexUi";
6484
6488
  const zh = {
6489
+ "input.historyHint": "↑↓ 翻历史",
6485
6490
  "sidebar.label": "DSH 导航",
6486
6491
  "sidebar.expand": "展开侧边栏",
6487
6492
  "sidebar.collapse": "收缩侧边栏",
@@ -6628,7 +6633,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
6628
6633
  "about.feature.conversation": "保留原生消息、工具调用、输入、权限和模型选择,仅调整容器视觉",
6629
6634
  "about.feature.navigator": "当前会话提供轮次缩略导航,可快速跳转至每一次用户提问",
6630
6635
  "about.dependencies": "配套管理插件",
6631
- "about.dependenciesDescription": "每个配套插件都可单独安装和更新,也可一键安装缺失项并更新旧版本。可分别检查 Codex UI、专家、技能、归档、IM、定时任务和第三方插件市场。",
6636
+ "about.dependenciesDescription": "每个配套插件都可单独安装和更新,也可一键安装缺失项并更新旧版本。可分别检查 Codex UI、专家、技能、归档、IM、定时任务、BTW 和第三方插件市场。",
6632
6637
  "about.loading": "正在读取依赖安装状态…",
6633
6638
  "about.statusFailed": "暂时无法读取依赖安装状态。",
6634
6639
  "about.refreshFailed": "依赖状态刷新失败,当前显示上次成功读取的结果。",
@@ -6662,9 +6667,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
6662
6667
  "about.dependency.ui": "Codex UI",
6663
6668
  "about.dependency.experts": "专家管理",
6664
6669
  "about.dependency.skills": "技能管理",
6665
- "about.dependency.archive": "归档会话管理",
6670
+ "about.dependency.archive": "归档会话",
6666
6671
  "about.dependency.im": "IM助理",
6667
6672
  "about.dependency.schedule": "定时任务",
6673
+ "about.dependency.btw": "BTW 旁问",
6668
6674
  "about.dependency.market": "插件市场",
6669
6675
  "turns.label": "当前会话轮次导航",
6670
6676
  "turns.untitled": "未命名提问",
@@ -6681,6 +6687,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
6681
6687
  "meta.locale": "zh-CN"
6682
6688
  };
6683
6689
  const en = {
6690
+ "input.historyHint": "↑↓ History",
6684
6691
  "sidebar.label": "DSH navigation",
6685
6692
  "sidebar.expand": "Expand sidebar",
6686
6693
  "sidebar.collapse": "Collapse sidebar",
@@ -6827,7 +6834,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
6827
6834
  "about.feature.conversation": "Keeps native messages, tool calls, composer, permissions, and model selection while refining the container visuals",
6828
6835
  "about.feature.navigator": "Navigate directly to each user prompt with the current conversation turn navigator",
6829
6836
  "about.dependencies": "Companion management plugins",
6830
- "about.dependenciesDescription": "Install or update each companion separately, or install missing plugins and update old versions in one action. Check Codex UI, expert, skill, archive, IM, scheduled-task, and marketplace plugins on their own.",
6837
+ "about.dependenciesDescription": "Install or update each companion separately, or install missing plugins and update old versions in one action. Check Codex UI, expert, skill, archive, IM, scheduled-task, BTW, and marketplace plugins on their own.",
6831
6838
  "about.loading": "Loading dependency status…",
6832
6839
  "about.statusFailed": "Dependency status is temporarily unavailable.",
6833
6840
  "about.refreshFailed": "Dependency status refresh failed. Showing the last successful result.",
@@ -6861,9 +6868,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
6861
6868
  "about.dependency.ui": "Codex UI",
6862
6869
  "about.dependency.experts": "Expert management",
6863
6870
  "about.dependency.skills": "Skill management",
6864
- "about.dependency.archive": "Archived conversation management",
6871
+ "about.dependency.archive": "Archived conversations",
6865
6872
  "about.dependency.im": "IM Assistant",
6866
6873
  "about.dependency.schedule": "Scheduled tasks",
6874
+ "about.dependency.btw": "BTW",
6867
6875
  "about.dependency.market": "Plugin Market",
6868
6876
  "turns.label": "Conversation turn navigation",
6869
6877
  "turns.untitled": "Untitled prompt",
@@ -7463,6 +7471,273 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
7463
7471
  });
7464
7472
  }
7465
7473
  //#endregion
7474
+ //#region src/client/input-history.ts
7475
+ const HISTORY_KEY = "michengai.codex-ui.input-history.v1";
7476
+ const LEGACY_HISTORY_KEY = "michengai.btw.history.v1";
7477
+ const MAX_STORAGE_LENGTH = 1e6;
7478
+ /** 只保存已发送文本;浏览器存储失败时仍保留本次内存历史。 */
7479
+ var InputHistory = class {
7480
+ storage;
7481
+ limit;
7482
+ warn;
7483
+ scopes = /* @__PURE__ */ new Map();
7484
+ constructor(storage, limit = 200, warn = console.warn) {
7485
+ this.storage = storage;
7486
+ this.limit = limit;
7487
+ this.warn = warn;
7488
+ try {
7489
+ const current = storage?.getItem(HISTORY_KEY);
7490
+ const raw = current ?? storage?.getItem(LEGACY_HISTORY_KEY);
7491
+ if (!raw) return;
7492
+ if (raw.length > MAX_STORAGE_LENGTH) throw new Error("历史数据过大");
7493
+ const data = JSON.parse(raw);
7494
+ if (typeof data !== "object" || data === null || Array.isArray(data)) throw new Error("历史格式无效");
7495
+ for (const [key, value] of Object.entries(data).slice(-20)) if (Array.isArray(value)) this.scopes.set(key, value.filter((item) => typeof item === "string" && item.length <= 8e3).slice(-limit));
7496
+ if (current === null || current === void 0) storage?.setItem(HISTORY_KEY, JSON.stringify(Object.fromEntries(this.scopes)));
7497
+ } catch {
7498
+ warn("输入历史读取失败,本次使用内存历史。");
7499
+ }
7500
+ }
7501
+ list(scope) {
7502
+ return this.scopes.get(scope) ?? [];
7503
+ }
7504
+ add(scope, text) {
7505
+ if (!text.trim() || text.length > 8e3) return;
7506
+ const previous = this.scopes.get(scope) ?? [];
7507
+ if (previous.at(-1) === text) return;
7508
+ this.scopes.delete(scope);
7509
+ this.scopes.set(scope, [...previous, text].slice(-this.limit));
7510
+ while (this.scopes.size > 20) this.scopes.delete(this.scopes.keys().next().value);
7511
+ let serialized = JSON.stringify(Object.fromEntries(this.scopes));
7512
+ while (serialized.length > MAX_STORAGE_LENGTH && this.scopes.size) {
7513
+ const oldest = this.scopes.keys().next().value;
7514
+ const entries = this.scopes.get(oldest);
7515
+ entries.shift();
7516
+ if (!entries.length) this.scopes.delete(oldest);
7517
+ serialized = JSON.stringify(Object.fromEntries(this.scopes));
7518
+ }
7519
+ try {
7520
+ this.storage?.setItem(HISTORY_KEY, serialized);
7521
+ } catch {
7522
+ this.warn("输入历史无法保存到浏览器,本次仍可使用。");
7523
+ }
7524
+ }
7525
+ };
7526
+ /** 从空输入进入,编辑历史即退出,避免覆盖用户的新草稿。 */
7527
+ var HistoryCursor = class {
7528
+ index;
7529
+ original = "";
7530
+ displayed = "";
7531
+ entries = [];
7532
+ reset() {
7533
+ this.index = void 0;
7534
+ this.entries = [];
7535
+ }
7536
+ move(direction, draft, entries) {
7537
+ if (this.index !== void 0 && draft !== this.displayed) this.reset();
7538
+ if (this.index === void 0) {
7539
+ if (direction !== -1 || draft !== "" || entries.length === 0) return void 0;
7540
+ this.original = draft;
7541
+ this.entries = [...entries];
7542
+ this.index = this.entries.length;
7543
+ }
7544
+ this.index = Math.max(0, Math.min(this.entries.length, this.index + direction));
7545
+ if (this.index === this.entries.length) {
7546
+ const restored = this.original;
7547
+ this.reset();
7548
+ return restored;
7549
+ }
7550
+ this.displayed = this.entries[this.index] ?? "";
7551
+ return this.displayed;
7552
+ }
7553
+ };
7554
+ //#endregion
7555
+ //#region src/client/input-history-keyboard.ts
7556
+ /** 只处理当前输入框的历史按键,保持 IME、菜单和富内容的原有行为。 */
7557
+ function bindHistoryKeys(editor, adapter) {
7558
+ const cursor = new HistoryCursor();
7559
+ let composing = false;
7560
+ let writingHistory = false;
7561
+ const begin = () => {
7562
+ composing = true;
7563
+ };
7564
+ const end = () => {
7565
+ composing = false;
7566
+ };
7567
+ const changed = () => {
7568
+ if (!writingHistory) cursor.reset();
7569
+ };
7570
+ const keydown = (event) => {
7571
+ if (event.target !== editor && !editor.contains(event.target)) return;
7572
+ if (event.defaultPrevented || composing || event.isComposing || event.keyCode === 229 || event.ctrlKey || event.metaKey || event.altKey || event.shiftKey || adapter.blocked()) return;
7573
+ if (event.key !== "ArrowUp" && event.key !== "ArrowDown") return;
7574
+ const draft = adapter.draft();
7575
+ if (draft !== "" && !atHistoryBoundary(editor)) return;
7576
+ const next = cursor.move(event.key === "ArrowUp" ? -1 : 1, draft, adapter.entries());
7577
+ if (next === void 0) return;
7578
+ event.preventDefault();
7579
+ event.stopImmediatePropagation();
7580
+ writingHistory = true;
7581
+ try {
7582
+ adapter.setDraft(next);
7583
+ } finally {
7584
+ writingHistory = false;
7585
+ }
7586
+ };
7587
+ editor.addEventListener("compositionstart", begin);
7588
+ editor.addEventListener("compositionend", end);
7589
+ editor.addEventListener("input", changed);
7590
+ editor.addEventListener("keydown", keydown, true);
7591
+ return () => {
7592
+ editor.removeEventListener("compositionstart", begin);
7593
+ editor.removeEventListener("compositionend", end);
7594
+ editor.removeEventListener("input", changed);
7595
+ editor.removeEventListener("keydown", keydown, true);
7596
+ };
7597
+ }
7598
+ /** 召回文本中间或存在选区时,保留宿主编辑器的垂直光标移动。 */
7599
+ function atHistoryBoundary(editor) {
7600
+ if (editor instanceof HTMLTextAreaElement) return editor.selectionStart === editor.selectionEnd && (editor.selectionStart === 0 || editor.selectionEnd === editor.value.length);
7601
+ const selection = editor.ownerDocument.getSelection();
7602
+ if (!selection?.isCollapsed || !selection.rangeCount || !editor.contains(selection.anchorNode)) return false;
7603
+ const caret = selection.getRangeAt(0);
7604
+ const before = editor.ownerDocument.createRange();
7605
+ before.selectNodeContents(editor);
7606
+ before.setEnd(caret.startContainer, caret.startOffset);
7607
+ const after = editor.ownerDocument.createRange();
7608
+ after.selectNodeContents(editor);
7609
+ after.setStart(caret.endContainer, caret.endOffset);
7610
+ return before.toString() === "" || after.toString() === "";
7611
+ }
7612
+ /** 从本 slot 向上寻找唯一输入框,避免绑定侧栏、搜索或其他会话。 */
7613
+ function findComposer(anchor) {
7614
+ let parent = anchor.parentElement;
7615
+ while (parent && parent !== document.body) {
7616
+ const editors = parent.querySelectorAll("textarea:not([disabled]), [data-lexical-editor=\"true\"][contenteditable=\"true\"]");
7617
+ if (editors.length === 1) return editors[0];
7618
+ if (editors.length > 1) return void 0;
7619
+ parent = parent.parentElement;
7620
+ }
7621
+ }
7622
+ //#endregion
7623
+ //#region src/client/InputHistoryDock.tsx
7624
+ function InputHistoryHint({ t }) {
7625
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: `
7626
+ [data-composer-card] [data-input-scroll]{container:dcu-composer-input / inline-size}
7627
+ [data-composer-card] [data-composer-placeholder]{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
7628
+ [data-composer-card] [data-composer-placeholder]::after{
7629
+ content:${JSON.stringify(t("input.historyHint"))};
7630
+ color:var(--dsw-alias-label-caption);font-size:12px;line-height:18px;
7631
+ white-space:nowrap;flex:0 0 auto;margin-right:8px;
7632
+ }
7633
+ @container dcu-composer-input (max-width:560px){
7634
+ [data-composer-card] [data-composer-placeholder]::after{display:none}
7635
+ }
7636
+ @media(max-width:640px){
7637
+ [data-composer-card] [data-composer-placeholder]::after{display:none}
7638
+ }
7639
+ ` });
7640
+ }
7641
+ /** 隐形输入扩展:使用宿主状态和编辑动作,不替换编辑器或创建旁问界面。 */
7642
+ function InputHistoryDock({ ctx, sessionId, history, seen }) {
7643
+ const anchor = (0, react.useRef)(null);
7644
+ (0, react.useEffect)(() => {
7645
+ const binding = ctx.sessions.binding(sessionId);
7646
+ if (binding === void 0) return;
7647
+ const scope = ctx.sessions.list.getSnapshot().byId[sessionId]?.cwd ?? sessionId;
7648
+ const input = ctx.conversation.input.for(binding.ctx);
7649
+ const menu = ctx.inputTriggers.sessionOf(binding.ctx).menu;
7650
+ seen.set(binding, binding.eventSource.getSnapshot().revision);
7651
+ const collect = () => {
7652
+ const snapshot = binding.eventSource.getSnapshot();
7653
+ if (snapshot.change.kind !== "replace" && snapshot.revision <= (seen.get(binding) ?? -1)) return;
7654
+ seen.set(binding, snapshot.revision);
7655
+ if (snapshot.change.kind !== "append") return;
7656
+ for (const entry of snapshot.change.entries) {
7657
+ if (entry.event.type !== "user/message" || entry.event.data.source?.kind !== "user") continue;
7658
+ const text = entry.event.data.content.filter((block) => block.type === "text").map((block) => block.text).join("");
7659
+ history.add(scope, text);
7660
+ }
7661
+ };
7662
+ const offEvents = binding.eventSource.subscribe(collect);
7663
+ let previous = input.state.getSnapshot();
7664
+ const offInput = input.state.subscribe(() => {
7665
+ const next = input.state.getSnapshot();
7666
+ if (previous.phase === "submitting" && next.phase === "plain" && next.draft === "" && previous.imageIds.length === 0 && previous.occurrences.length === 0) history.add(scope, previous.draft);
7667
+ previous = next;
7668
+ });
7669
+ let editor;
7670
+ let offKeys = () => {};
7671
+ const connect = () => {
7672
+ const next = anchor.current === null ? void 0 : findComposer(anchor.current);
7673
+ if (next === editor) return;
7674
+ offKeys();
7675
+ editor = next;
7676
+ if (editor === void 0) return;
7677
+ offKeys = bindHistoryKeys(editor, {
7678
+ draft: () => input.state.getSnapshot().draft,
7679
+ entries: () => history.list(scope),
7680
+ setDraft: (text) => input.setDraft(text),
7681
+ blocked: () => {
7682
+ const state = input.state.getSnapshot();
7683
+ return state.phase === "adjudicating" || state.phase === "submitting" || state.imageIds.length > 0 || state.occurrences.length > 0 || menu.getSnapshot().open;
7684
+ }
7685
+ });
7686
+ };
7687
+ connect();
7688
+ const parent = anchor.current?.parentElement?.parentElement;
7689
+ const observer = new MutationObserver(connect);
7690
+ if (parent !== null && parent !== void 0) observer.observe(parent, {
7691
+ childList: true,
7692
+ subtree: true
7693
+ });
7694
+ return () => {
7695
+ observer.disconnect();
7696
+ offKeys();
7697
+ offInput();
7698
+ offEvents();
7699
+ };
7700
+ }, [
7701
+ ctx,
7702
+ sessionId,
7703
+ history,
7704
+ seen
7705
+ ]);
7706
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7707
+ ref: anchor,
7708
+ hidden: true
7709
+ });
7710
+ }
7711
+ function registerInputHistory(ctx) {
7712
+ let storage;
7713
+ try {
7714
+ storage = window.localStorage;
7715
+ } catch {
7716
+ console.warn("[michengai-codex-ui] 浏览器存储不可用,使用内存输入历史。");
7717
+ }
7718
+ const history = new InputHistory(storage);
7719
+ const seen = /* @__PURE__ */ new WeakMap();
7720
+ function Dock(props) {
7721
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InputHistoryDock, {
7722
+ ctx,
7723
+ sessionId: props.session.sessionId,
7724
+ history,
7725
+ seen
7726
+ });
7727
+ }
7728
+ ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
7729
+ name: "conversation.input.dock",
7730
+ id: "codex-ui-input-history",
7731
+ order: -100
7732
+ }, Dock));
7733
+ ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
7734
+ name: "conversation.input.dock",
7735
+ id: "codex-ui-input-history-hint",
7736
+ order: -100,
7737
+ locale: NS
7738
+ }, InputHistoryHint));
7739
+ }
7740
+ //#endregion
7466
7741
  //#region src/client/index.ts
7467
7742
  const inject = [
7468
7743
  "slots",
@@ -7471,6 +7746,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
7471
7746
  "layout",
7472
7747
  "locale",
7473
7748
  "connection",
7749
+ "inputTriggers",
7474
7750
  "conversation"
7475
7751
  ];
7476
7752
  function hasDeleteSession(value) {
@@ -7504,6 +7780,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
7504
7780
  en
7505
7781
  }), "michengai-codex-ui: dictionaries");
7506
7782
  const t = ctx.locale.bind(NS);
7783
+ registerInputHistory(ctx);
7507
7784
  const connection = ctx.get("connection");
7508
7785
  const openPath = (path) => openPathInHost(connection, path);
7509
7786
  ctx.effect(() => observeSlimSidebar(), "michengai-codex-ui: slim sidebar");
package/lib/index.mjs CHANGED
@@ -44,6 +44,10 @@ const MANAGED_DEPENDENCIES = [
44
44
  id: "schedule",
45
45
  packageName: "@michengai/dsh-automation"
46
46
  },
47
+ {
48
+ id: "btw",
49
+ packageName: "@michengai/dsh-btw"
50
+ },
47
51
  {
48
52
  id: "market",
49
53
  packageName: "dshmarket"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-codex-ui",
3
- "version": "0.2.103",
3
+ "version": "0.2.104",
4
4
  "description": "以 Codex 风格重构 DSH Web 侧栏的独立客户端插件",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -49,6 +49,7 @@
49
49
  "@deepseek-ai/dsh-client-ui-layout",
50
50
  "@deepseek-ai/dsh-client-locale",
51
51
  "@deepseek-ai/dsh-client-ui-conversation",
52
+ "@deepseek-ai/dsh-client-ui-input-trigger",
52
53
  "@deepseek-ai/dsh-client-ui-workspace",
53
54
  "@deepseek-ai/dsh-client-ui-settings-general"
54
55
  ],
@@ -65,6 +66,7 @@
65
66
  "@deepseek-ai/dsh-client-locale": ">=0.1.0-rc.5 <0.2.0",
66
67
  "@deepseek-ai/dsh-client-runtime": ">=0.1.0-rc.5 <0.2.0",
67
68
  "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.0-rc.5 <0.2.0",
69
+ "@deepseek-ai/dsh-client-ui-input-trigger": ">=0.1.0-rc.5 <0.2.0",
68
70
  "@deepseek-ai/dsh-client-ui-layout": ">=0.1.0-rc.5 <0.2.0",
69
71
  "@deepseek-ai/dsh-client-ui-primitives": ">=0.1.0-rc.5 <0.2.0",
70
72
  "@deepseek-ai/dsh-client-ui-settings": ">=0.1.0-rc.5 <0.2.0",
@@ -96,6 +98,7 @@
96
98
  "@deepseek-ai/dsh-client-test-runtime": "0.1.2-rc.1",
97
99
  "@deepseek-ai/dsh-client-ui-chat": "0.1.2-rc.1",
98
100
  "@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1",
101
+ "@deepseek-ai/dsh-client-ui-input-trigger": "0.1.2-rc.1",
99
102
  "@deepseek-ai/dsh-client-ui-layout": "0.1.2-rc.1",
100
103
  "@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1",
101
104
  "@deepseek-ai/dsh-client-ui-renderer": "0.1.2-rc.1",