@michengai/dsh-codex-ui 0.2.102 → 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 +50 -0
- package/CHANGELOG.zh-CN.md +50 -0
- package/README.md +3 -1
- package/README.zh-CN.md +5 -0
- package/lib/client.js +360 -28
- package/lib/index.mjs +4 -0
- package/package.json +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,56 @@
|
|
|
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
|
+
|
|
38
|
+
## 0.2.103 — 2026-09-04
|
|
39
|
+
|
|
40
|
+
Companion release: `@michengai/dsh-codex-suite-installer@0.1.20`.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- Limited conversation DOM processing to affected message roots during streaming updates, avoiding repeated full-document decoration scans.
|
|
45
|
+
- Corrected blank-language fallback, cyclic remote-error handling, workspace-preference response versioning, About-page refresh warnings, and connector marketplace probing compatibility.
|
|
46
|
+
- Hardened Suite Installer YAML build-policy normalization across indentation styles and rejected Windows command-expansion characters.
|
|
47
|
+
- Preserved existing third-party bundle order during Suite migration, expanded managed members at the prior Suite anchor, and rejected profiles with missing or reversed base/web prerequisites instead of silently rewriting them.
|
|
48
|
+
|
|
49
|
+
### Tests
|
|
50
|
+
|
|
51
|
+
- Added behavior coverage for cross-site dependency-route rejection, error redaction, localized refresh failures, connector probing, observer scope, cyclic errors, installer ordering, invalid bundle baselines, and Windows command quoting.
|
|
52
|
+
|
|
53
|
+
### Dependencies
|
|
54
|
+
|
|
55
|
+
- The Suite Installer release workflow will resolve Codex UI `0.2.103` and publish the companion `0.1.20` release.
|
|
56
|
+
|
|
7
57
|
## 0.2.102 — 2026-09-03
|
|
8
58
|
|
|
9
59
|
Companion release: `@michengai/dsh-codex-suite-installer@0.1.19`.
|
package/CHANGELOG.zh-CN.md
CHANGED
|
@@ -4,6 +4,56 @@
|
|
|
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
|
+
|
|
38
|
+
## 0.2.103 — 2026-09-04
|
|
39
|
+
|
|
40
|
+
配套版本:`@michengai/dsh-codex-suite-installer@0.1.20`。
|
|
41
|
+
|
|
42
|
+
### 修复
|
|
43
|
+
|
|
44
|
+
- 将流式更新期间的会话 DOM 处理限制在受影响的消息根,避免反复执行全文档装饰扫描。
|
|
45
|
+
- 修复空语言兜底、远程错误循环引用、工作区偏好响应版本、关于页刷新失败提示和连接器市场探测兼容性。
|
|
46
|
+
- 强化 Suite 安装器对不同缩进 YAML 构建策略的归一化,并拒绝 Windows 命令展开字符。
|
|
47
|
+
- Suite 迁移时保留既有第三方 bundle 顺序,在原 Suite 锚点展开受管成员;缺少或颠倒 `base/web` 前置项时明确失败,不再静默改写。
|
|
48
|
+
|
|
49
|
+
### 测试
|
|
50
|
+
|
|
51
|
+
- 新增依赖路由跨站拒绝、错误脱敏、本地化刷新失败、连接器探测、观察器范围、循环错误、安装器保序、无效 bundle 基线和 Windows 命令引用的行为覆盖。
|
|
52
|
+
|
|
53
|
+
### 依赖
|
|
54
|
+
|
|
55
|
+
- Suite Installer 发布 workflow 会解析 Codex UI `0.2.103`,并发布配套的 `0.1.20` 版本。
|
|
56
|
+
|
|
7
57
|
## 0.2.102 — 2026-09-03
|
|
8
58
|
|
|
9
59
|
配套版本:`@michengai/dsh-codex-suite-installer@0.1.19`。
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
**Rebuild the DeepSeek Harness Web sidebar, workspace tree, search, and turn navigation in a Codex-style layout**
|
|
10
10
|
|
|
11
|
-
[简体中文](README.zh-CN.md) · [Changelog](CHANGELOG.md) · [Apache-2.0](LICENSE)
|
|
11
|
+
[简体中文](README.zh-CN.md) · [项目交接](docs/00-交接入口/00-阅读导航.md) · [Changelog](CHANGELOG.md) · [Apache-2.0](LICENSE)
|
|
12
12
|
|
|
13
13
|
[](LICENSE)
|
|
14
14
|
[](https://www.npmjs.com/package/@michengai/dsh-codex-ui)
|
|
@@ -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
|

|
package/lib/client.js
CHANGED
|
@@ -1236,8 +1236,11 @@ header:has([data-dcu-inline-tabs]) [class*="headerActions"]{order:2;flex:none}
|
|
|
1236
1236
|
header [data-dcu-inline-tabs]{box-sizing:border-box;order:3;flex:none;display:flex;align-items:center;gap:0;margin:0;padding:0;height:28px;position:relative;z-index:1;overflow:hidden;border:1px solid var(--dsw-alias-border-subtle,rgba(255,255,255,.12));border-radius:8px;background:var(--dsw-alias-background-secondary,rgba(255,255,255,.025))}
|
|
1237
1237
|
header:has([data-dcu-inline-tabs]) [class*="headerUtilities"]{order:4;flex:none}
|
|
1238
1238
|
header [data-dcu-tab-slider]{position:absolute;left:0;top:0;height:26px;border-radius:7px;background:color-mix(in srgb,var(--dsw-alias-button-info-fill,#4c8dff) 18%,transparent);pointer-events:none;z-index:0;opacity:0;transform:translateX(0);width:0;transition:transform 240ms cubic-bezier(.16,1,.3,1),width 240ms cubic-bezier(.16,1,.3,1),opacity 160ms ease}
|
|
1239
|
-
/* 顶栏统一使用 34px 控件带:与宿主扩展常用的 top:3px + 28px
|
|
1240
|
-
|
|
1239
|
+
/* 顶栏统一使用 34px 控件带:与宿主扩展常用的 top:3px + 28px 图标按钮同心。
|
|
1240
|
+
better-sidebar 0.18.0 收起时会把开关组改到 14px(按官方 padding-top:12px 算),
|
|
1241
|
+
这里只在紧凑顶栏存在时扣回 3px,不搬 DOM、不跟展开/收起跳动。 */
|
|
1242
|
+
body[data-dsh-sidebar-collapsed]:has([data-dcu-inline-tabs]) [data-dsh-toggle-cluster]{top:calc(3px + env(safe-area-inset-top))}
|
|
1243
|
+
body[data-dsh-sidebar-collapsed][data-dsh-title-bar-compat]:has([data-dcu-inline-tabs]) [data-dsh-toggle-cluster]{top:calc(var(--dsh-title-bar-strip, 40px) + 3px)}
|
|
1241
1244
|
header [data-dcu-inline-tabs] [role=tab]{box-sizing:border-box;position:relative;z-index:1;height:26px;padding:3px 10px;margin:0;line-height:20px;color:var(--dsw-alias-label-tertiary);border:0;box-shadow:none;background:transparent;font-size:13px;white-space:nowrap}
|
|
1242
1245
|
header [data-dcu-inline-tabs] [role=tab][aria-selected=true],header [data-dcu-inline-tabs] [role=tab][data-state=active]{color:var(--dsw-alias-button-info-fill,#4c8dff);font-weight:500}
|
|
1243
1246
|
header [data-dcu-inline-tabs] [role=tab]+[role=tab]{border-left:1px solid var(--dsw-alias-border-subtle,rgba(255,255,255,.08))}
|
|
@@ -1372,10 +1375,28 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1372
1375
|
style.textContent = CONVERSATION_HEADER_STYLE;
|
|
1373
1376
|
doc.head.append(style);
|
|
1374
1377
|
}
|
|
1375
|
-
const
|
|
1376
|
-
function
|
|
1377
|
-
|
|
1378
|
-
|
|
1378
|
+
const CONVERSATION_BUBBLE_SELECTOR = "[data-time-hover-root],[data-dcu-user-card],[data-dcu-user-source]";
|
|
1379
|
+
function inspectConversationNode(node, impact, includeDescendants) {
|
|
1380
|
+
if (!(node instanceof Element)) return;
|
|
1381
|
+
if (node.matches("header") || node.closest("header") !== null || includeDescendants && node.querySelector("header") !== null) impact.headerChanged = true;
|
|
1382
|
+
const row = node.closest("[data-time-hover-root]");
|
|
1383
|
+
if (row !== null) {
|
|
1384
|
+
impact.bubbleRoots.add(row);
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
if (node.matches(CONVERSATION_BUBBLE_SELECTOR) || includeDescendants && node.querySelector(CONVERSATION_BUBBLE_SELECTOR) !== null) impact.bubbleRoots.add(node);
|
|
1388
|
+
}
|
|
1389
|
+
function conversationMutationImpact(records) {
|
|
1390
|
+
const impact = {
|
|
1391
|
+
headerChanged: false,
|
|
1392
|
+
bubbleRoots: /* @__PURE__ */ new Set()
|
|
1393
|
+
};
|
|
1394
|
+
for (const record of records) {
|
|
1395
|
+
inspectConversationNode(record.target, impact, false);
|
|
1396
|
+
for (const node of record.addedNodes) inspectConversationNode(node, impact, true);
|
|
1397
|
+
for (const node of record.removedNodes) if (node instanceof Element && (node.matches("header") || node.querySelector("header") !== null)) impact.headerChanged = true;
|
|
1398
|
+
}
|
|
1399
|
+
return impact;
|
|
1379
1400
|
}
|
|
1380
1401
|
/** 观察会话顶栏与用户气泡;只对相关子树变更按帧合并,流式回答不会触发全文档扫描。 */
|
|
1381
1402
|
function observeConversationHeader(doc = document) {
|
|
@@ -1384,6 +1405,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1384
1405
|
restoreOfficialUserBubbles(doc);
|
|
1385
1406
|
let applying = false;
|
|
1386
1407
|
let frame;
|
|
1408
|
+
let headerPending = true;
|
|
1409
|
+
const bubbleRoots = /* @__PURE__ */ new Set();
|
|
1387
1410
|
let watchedTabs;
|
|
1388
1411
|
let stopWatchingTabs;
|
|
1389
1412
|
const run = () => {
|
|
@@ -1391,17 +1414,22 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1391
1414
|
if (applying) return;
|
|
1392
1415
|
applying = true;
|
|
1393
1416
|
try {
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
const
|
|
1397
|
-
if (
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1417
|
+
const roots = [...bubbleRoots];
|
|
1418
|
+
bubbleRoots.clear();
|
|
1419
|
+
for (const root of roots) restoreOfficialUserBubbles(root);
|
|
1420
|
+
if (headerPending) {
|
|
1421
|
+
headerPending = false;
|
|
1422
|
+
placeConversationTabs(doc);
|
|
1423
|
+
const tabs = findConversationTablist(doc);
|
|
1424
|
+
if (tabs !== watchedTabs) {
|
|
1425
|
+
stopWatchingTabs?.();
|
|
1426
|
+
watchedTabs = tabs;
|
|
1427
|
+
stopWatchingTabs = tabs === void 0 ? void 0 : watchTabSelection(tabs);
|
|
1428
|
+
}
|
|
1429
|
+
syncTabSlider(doc);
|
|
1430
|
+
decorateConversationTitle(doc);
|
|
1431
|
+
decorateSessionLogDownload(doc);
|
|
1401
1432
|
}
|
|
1402
|
-
syncTabSlider(doc);
|
|
1403
|
-
decorateConversationTitle(doc);
|
|
1404
|
-
decorateSessionLogDownload(doc);
|
|
1405
1433
|
} finally {
|
|
1406
1434
|
applying = false;
|
|
1407
1435
|
}
|
|
@@ -1412,7 +1440,11 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1412
1440
|
};
|
|
1413
1441
|
sync();
|
|
1414
1442
|
const observer = new MutationObserver((records) => {
|
|
1415
|
-
|
|
1443
|
+
const impact = conversationMutationImpact(records);
|
|
1444
|
+
if (!impact.headerChanged && impact.bubbleRoots.size === 0) return;
|
|
1445
|
+
headerPending ||= impact.headerChanged;
|
|
1446
|
+
for (const root of impact.bubbleRoots) bubbleRoots.add(root);
|
|
1447
|
+
sync();
|
|
1416
1448
|
});
|
|
1417
1449
|
observer.observe(doc.body, {
|
|
1418
1450
|
childList: true,
|
|
@@ -1932,10 +1964,15 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1932
1964
|
}
|
|
1933
1965
|
/** DSH 明确要求跨 bundle 按结构标记识别 RemoteFailure,不能使用 instanceof。 */
|
|
1934
1966
|
function remoteFailureCode(value) {
|
|
1935
|
-
const
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1967
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1968
|
+
let current = value;
|
|
1969
|
+
while (true) {
|
|
1970
|
+
const record = objectRecord(current);
|
|
1971
|
+
if (record === void 0 || seen.has(record)) return void 0;
|
|
1972
|
+
seen.add(record);
|
|
1973
|
+
if (record.isDSHRemoteError === true && typeof record.code === "string") return record.code;
|
|
1974
|
+
current = record.rpcError;
|
|
1975
|
+
}
|
|
1939
1976
|
}
|
|
1940
1977
|
function diagnosticMessage(value) {
|
|
1941
1978
|
if (value instanceof Error) return value.message;
|
|
@@ -5915,6 +5952,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5915
5952
|
id: "schedule",
|
|
5916
5953
|
packageName: "@michengai/dsh-automation"
|
|
5917
5954
|
},
|
|
5955
|
+
{
|
|
5956
|
+
id: "btw",
|
|
5957
|
+
packageName: "@michengai/dsh-btw"
|
|
5958
|
+
},
|
|
5918
5959
|
{
|
|
5919
5960
|
id: "market",
|
|
5920
5961
|
packageName: "dshmarket"
|
|
@@ -5977,6 +6018,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5977
6018
|
const [installing, setInstalling] = (0, react.useState)();
|
|
5978
6019
|
const [progress, setProgress] = (0, react.useState)();
|
|
5979
6020
|
const [message, setMessage] = (0, react.useState)();
|
|
6021
|
+
const [refreshFailed, setRefreshFailed] = (0, react.useState)(false);
|
|
5980
6022
|
const alive = (0, react.useRef)(true);
|
|
5981
6023
|
const root = (0, react.useRef)(null);
|
|
5982
6024
|
const stateRef = (0, react.useRef)("loading");
|
|
@@ -6002,9 +6044,11 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6002
6044
|
if (!response.ok || !Array.isArray(payload.dependencies) || !payload.dependencies.every(isDependencyStatus)) throw new Error();
|
|
6003
6045
|
setDependencies(payload.dependencies);
|
|
6004
6046
|
setState("ready");
|
|
6047
|
+
setRefreshFailed(false);
|
|
6005
6048
|
} catch (error) {
|
|
6006
6049
|
if (signal?.aborted || error instanceof DOMException && error.name === "AbortError" || currentRequest !== requestId.current) return;
|
|
6007
|
-
if (stateRef.current
|
|
6050
|
+
if (stateRef.current === "ready") setRefreshFailed(true);
|
|
6051
|
+
else setState("failed");
|
|
6008
6052
|
}
|
|
6009
6053
|
}, []);
|
|
6010
6054
|
(0, react.useEffect)(() => {
|
|
@@ -6072,6 +6116,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6072
6116
|
if (!alive.current) return;
|
|
6073
6117
|
setDependencies(payload.dependencies);
|
|
6074
6118
|
setState("ready");
|
|
6119
|
+
setRefreshFailed(false);
|
|
6075
6120
|
setMessage({
|
|
6076
6121
|
error: false,
|
|
6077
6122
|
text: payload.autoReload === false ? t("about.restartManually") : t("about.restartRequired")
|
|
@@ -6099,6 +6144,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6099
6144
|
if (!alive.current) return;
|
|
6100
6145
|
setDependencies(payload.dependencies);
|
|
6101
6146
|
setState("ready");
|
|
6147
|
+
setRefreshFailed(false);
|
|
6102
6148
|
setMessage({
|
|
6103
6149
|
error: false,
|
|
6104
6150
|
text: payload.restartRequired === false ? t("about.upToDate") : payload.autoReload === false ? t("about.restartManually") : t("about.restartRequired")
|
|
@@ -6243,6 +6289,12 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6243
6289
|
})
|
|
6244
6290
|
]
|
|
6245
6291
|
}),
|
|
6292
|
+
refreshFailed && state === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6293
|
+
className: "dcu-about-message",
|
|
6294
|
+
"data-error": "true",
|
|
6295
|
+
role: "status",
|
|
6296
|
+
children: t("about.refreshFailed")
|
|
6297
|
+
}),
|
|
6246
6298
|
message !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6247
6299
|
className: "dcu-about-message",
|
|
6248
6300
|
"data-error": message.error,
|
|
@@ -6397,10 +6449,11 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6397
6449
|
(0, react.useEffect)(() => {
|
|
6398
6450
|
const controller = new AbortController();
|
|
6399
6451
|
fetch(MCP_CONNECTOR_UI, {
|
|
6400
|
-
method: "
|
|
6452
|
+
method: "GET",
|
|
6401
6453
|
cache: "no-store",
|
|
6402
6454
|
signal: controller.signal
|
|
6403
6455
|
}).then((response) => {
|
|
6456
|
+
response.body?.cancel().catch(() => {});
|
|
6404
6457
|
if (!controller.signal.aborted) setMarketAvailable(response.ok);
|
|
6405
6458
|
}).catch(() => {
|
|
6406
6459
|
if (!controller.signal.aborted) setMarketAvailable(false);
|
|
@@ -6433,6 +6486,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6433
6486
|
/** 本插件独占的界面文案命名空间。 */
|
|
6434
6487
|
const NS = "michengai.codexUi";
|
|
6435
6488
|
const zh = {
|
|
6489
|
+
"input.historyHint": "↑↓ 翻历史",
|
|
6436
6490
|
"sidebar.label": "DSH 导航",
|
|
6437
6491
|
"sidebar.expand": "展开侧边栏",
|
|
6438
6492
|
"sidebar.collapse": "收缩侧边栏",
|
|
@@ -6579,9 +6633,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6579
6633
|
"about.feature.conversation": "保留原生消息、工具调用、输入、权限和模型选择,仅调整容器视觉",
|
|
6580
6634
|
"about.feature.navigator": "当前会话提供轮次缩略导航,可快速跳转至每一次用户提问",
|
|
6581
6635
|
"about.dependencies": "配套管理插件",
|
|
6582
|
-
"about.dependenciesDescription": "每个配套插件都可单独安装和更新,也可一键安装缺失项并更新旧版本。可分别检查 Codex UI、专家、技能、归档、IM
|
|
6636
|
+
"about.dependenciesDescription": "每个配套插件都可单独安装和更新,也可一键安装缺失项并更新旧版本。可分别检查 Codex UI、专家、技能、归档、IM、定时任务、BTW 和第三方插件市场。",
|
|
6583
6637
|
"about.loading": "正在读取依赖安装状态…",
|
|
6584
6638
|
"about.statusFailed": "暂时无法读取依赖安装状态。",
|
|
6639
|
+
"about.refreshFailed": "依赖状态刷新失败,当前显示上次成功读取的结果。",
|
|
6585
6640
|
"about.installed": "已安装",
|
|
6586
6641
|
"about.missing": "未安装",
|
|
6587
6642
|
"about.updateAvailable": "可更新",
|
|
@@ -6612,9 +6667,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6612
6667
|
"about.dependency.ui": "Codex UI",
|
|
6613
6668
|
"about.dependency.experts": "专家管理",
|
|
6614
6669
|
"about.dependency.skills": "技能管理",
|
|
6615
|
-
"about.dependency.archive": "
|
|
6670
|
+
"about.dependency.archive": "归档会话",
|
|
6616
6671
|
"about.dependency.im": "IM助理",
|
|
6617
6672
|
"about.dependency.schedule": "定时任务",
|
|
6673
|
+
"about.dependency.btw": "BTW 旁问",
|
|
6618
6674
|
"about.dependency.market": "插件市场",
|
|
6619
6675
|
"turns.label": "当前会话轮次导航",
|
|
6620
6676
|
"turns.untitled": "未命名提问",
|
|
@@ -6631,6 +6687,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6631
6687
|
"meta.locale": "zh-CN"
|
|
6632
6688
|
};
|
|
6633
6689
|
const en = {
|
|
6690
|
+
"input.historyHint": "↑↓ History",
|
|
6634
6691
|
"sidebar.label": "DSH navigation",
|
|
6635
6692
|
"sidebar.expand": "Expand sidebar",
|
|
6636
6693
|
"sidebar.collapse": "Collapse sidebar",
|
|
@@ -6777,9 +6834,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6777
6834
|
"about.feature.conversation": "Keeps native messages, tool calls, composer, permissions, and model selection while refining the container visuals",
|
|
6778
6835
|
"about.feature.navigator": "Navigate directly to each user prompt with the current conversation turn navigator",
|
|
6779
6836
|
"about.dependencies": "Companion management plugins",
|
|
6780
|
-
"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.",
|
|
6781
6838
|
"about.loading": "Loading dependency status…",
|
|
6782
6839
|
"about.statusFailed": "Dependency status is temporarily unavailable.",
|
|
6840
|
+
"about.refreshFailed": "Dependency status refresh failed. Showing the last successful result.",
|
|
6783
6841
|
"about.installed": "Installed",
|
|
6784
6842
|
"about.missing": "Not installed",
|
|
6785
6843
|
"about.updateAvailable": "Update available",
|
|
@@ -6810,9 +6868,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6810
6868
|
"about.dependency.ui": "Codex UI",
|
|
6811
6869
|
"about.dependency.experts": "Expert management",
|
|
6812
6870
|
"about.dependency.skills": "Skill management",
|
|
6813
|
-
"about.dependency.archive": "Archived
|
|
6871
|
+
"about.dependency.archive": "Archived conversations",
|
|
6814
6872
|
"about.dependency.im": "IM Assistant",
|
|
6815
6873
|
"about.dependency.schedule": "Scheduled tasks",
|
|
6874
|
+
"about.dependency.btw": "BTW",
|
|
6816
6875
|
"about.dependency.market": "Plugin Market",
|
|
6817
6876
|
"turns.label": "Conversation turn navigation",
|
|
6818
6877
|
"turns.untitled": "Untitled prompt",
|
|
@@ -7024,7 +7083,11 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7024
7083
|
const apply = () => {
|
|
7025
7084
|
if (applying) return;
|
|
7026
7085
|
applying = true;
|
|
7027
|
-
const active =
|
|
7086
|
+
const active = [
|
|
7087
|
+
locale.getSnapshot?.().active,
|
|
7088
|
+
document.documentElement.lang,
|
|
7089
|
+
window.navigator.language
|
|
7090
|
+
].find((value) => typeof value === "string" && value.trim() !== "") ?? "zh";
|
|
7028
7091
|
const roots = [...pendingRoots];
|
|
7029
7092
|
pendingRoots.clear();
|
|
7030
7093
|
try {
|
|
@@ -7408,6 +7471,273 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7408
7471
|
});
|
|
7409
7472
|
}
|
|
7410
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
|
|
7411
7741
|
//#region src/client/index.ts
|
|
7412
7742
|
const inject = [
|
|
7413
7743
|
"slots",
|
|
@@ -7416,6 +7746,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7416
7746
|
"layout",
|
|
7417
7747
|
"locale",
|
|
7418
7748
|
"connection",
|
|
7749
|
+
"inputTriggers",
|
|
7419
7750
|
"conversation"
|
|
7420
7751
|
];
|
|
7421
7752
|
function hasDeleteSession(value) {
|
|
@@ -7449,6 +7780,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7449
7780
|
en
|
|
7450
7781
|
}), "michengai-codex-ui: dictionaries");
|
|
7451
7782
|
const t = ctx.locale.bind(NS);
|
|
7783
|
+
registerInputHistory(ctx);
|
|
7452
7784
|
const connection = ctx.get("connection");
|
|
7453
7785
|
const openPath = (path) => openPathInHost(connection, path);
|
|
7454
7786
|
ctx.effect(() => observeSlimSidebar(), "michengai-codex-ui: slim sidebar");
|
package/lib/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@michengai/dsh-codex-ui",
|
|
3
|
-
"version": "0.2.
|
|
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",
|