dsh-data-cleaning-agent 0.9.11 → 0.9.12

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
@@ -1,3 +1,10 @@
1
+ # 0.9.12 · 2026-09-14
2
+
3
+ - Remove home subtitle and its spacing, retain native controls.
4
+ - Keep launcher naming stable and prevent duplicate launches.
5
+ - Preserve other agents’ branding and surfaces; clarify recorded progress and synchronization failures.
6
+ - Adopt DSH-UX-001 v1.5.4; 277 checks and 10 isolated browser scenarios pass.
7
+
1
8
  # Changelog
2
9
 
3
10
  本文件记录 `dsh-data-cleaning-agent` 的版本变更。格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。
package/README.en.md CHANGED
@@ -10,9 +10,9 @@ Related agents: [数据清洗补全](https://github.com/duhu2000/dsh-data-cleani
10
10
 
11
11
  > A data cleaning & completion agent plugin for DeepSeek Harness: local CSV/XLSX/JSON engine plus optional Qichacha (QCC) MCP enterprise-data enrichment. Initiated and maintained by the Qichacha (QCC) team.
12
12
  >
13
- > Current source version / 当前源码版本: **0.9.11** (stable release)
13
+ > Current source version / 当前源码版本: **0.9.12** (stable release)
14
14
 
15
- 0.9.11 uses the current cleaning Session's rendered Host phase instead of the nonexistent Session.composerPhase property. Branding appears on the real home screen and restores when leaving it.
15
+ 0.9.12 removes the home subtitle and its spacing, keeps native workspace/mode/composer controls, prevents duplicate menu launches, and scopes branding to its own home. Task records are distinguished from live model activity. The 0.9.11 Host phase and Session restoration fixes remain intact.
16
16
 
17
17
  0.9.10 observes the Host settling-to-hero transition so the database logo and product title appear even after delayed layout. Unknown structures do not trigger global headline rewriting. Rollback version: 0.9.9.
18
18
 
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  数据清洗补全智能体:面向 Excel/CSV/JSON 企业名单,提供数据清洗、表格清洗、清洗补全、去重、企业数据补全与字段补全,支持企查查 MCP 和结果导出。
10
10
 
11
11
  ```sh
12
- dsh plugin --profile web add dsh-data-cleaning-agent@0.9.11
12
+ dsh plugin --profile web add dsh-data-cleaning-agent@0.9.12
13
13
  ```
14
14
 
15
15
  请先满足下文的 DSH、连接器及侧边栏依赖要求;安装后完整停止并重启对应 Profile。
@@ -27,9 +27,9 @@ dsh plugin --profile web add dsh-data-cleaning-agent@0.9.11
27
27
 
28
28
  > 在 DeepSeek Harness 中清洗、补全、画像企业名单数据的智能体插件:本地 CSV/XLSX/JSON 引擎 + 可选企查查(Qichacha/QCC)MCP 企业数据补全,由企查查(Qichacha/QCC)团队发起并维护。
29
29
  >
30
- > 当前源码版本 / Current source version: **0.9.11**(正式版本)
30
+ > 当前源码版本 / Current source version: **0.9.12**(正式版本)
31
31
 
32
- 0.9.11 修正真实 Host 的首页状态接口:不再依赖 Session.composerPhase,按当前清洗会话所在宿主根节点的 data-phase 显示 Logo 与标题,并在离开首页时恢复。
32
+ 0.9.12 统一简洁首页:移除副标题与占位,保留原生工作区、模式和输入框。菜单名称固定并防止重复创建;品牌标题仅在所属首页生效,任务记录与模型运行状态明确区分。保留 0.9.11 的真实 Host 阶段与会话切换修复。
33
33
 
34
34
  0.9.10 补齐首页 settling → hero 阶段监听,避免首次挂载漏掉 Logo 与标题替换;兼容“探索未知之境”,未知结构不做全局标题改写。回滚版本为 0.9.9。
35
35
 
@@ -0,0 +1,9 @@
1
+ # 0.9.12 · 简洁首页与局部品牌保护
2
+
3
+ 首页移除副标题和专属留白,使用原生工作区、模式与输入框。左栏名称保持稳定,创建中禁用并阻止重复点击。品牌适配仅改写原生默认或本产品标题,停止隐藏其他产品 dock;保留 0.9.11 的真实阶段监听及晚挂载修复。
4
+
5
+ 任务区说明任务记录不代表模型实时运行;同步失败保留记录且不重复查询。
6
+
7
+ 验证:277 项检查,浅/深色 × 5 尺寸合成 Host React/Chromium 回归全部通过。未验证本轮真实四包共装、生产页面或真实计费 MCP。没有生产 Profile 修改。
8
+
9
+ 发布要求:PR CI → 合并 main → main CI → 新 annotated v0.9.12 → 既有 OIDC workflow → Registry/provenance 回读。旧版本和 Tag 不动。
@@ -0,0 +1,24 @@
1
+ # DSH-UX-001 v1.5.4 采用记录
2
+
3
+ 日期:2026-09-14。基线:0.9.11 / a0ec971db0d25d42f67f99e4328cca6f49a2bc2f。
4
+ 本轮仅本地代码与验收,不发布,不修改正式 Profile 或全局 DSH。
5
+
6
+ ## 已采用
7
+
8
+ - UX-05:首页删除 ProductHome 副标题组件、挂载与 dcAgentHomeSummary 样式;没有替代空白容器。保留原生工作区/模式/输入控件以及输入框下能力菜单,不修改 npm description/搜索文案。
9
+ - UX-45:左菜单固定“数据清洗补全”;创建中通过 disabled/aria-busy 表示,ref 门闩阻止同一渲染周期重复创建。失败仍沿用已有工作台错误状态,菜单名称不变。
10
+ - UX-46:保留 0.9.11 的真实 data-phase、openState、所有权立即重读和独立 Session namespace。只接管原生已知 Hero 标题或本插件标记;不覆盖其他产品标题,不再隐藏其他产品 dock。清理仅恢复仍为本插件标题的文字,不调用会话 rename API。
11
+ - UX-47:任务区明确展示“任务记录”,匹配/补全记录不冒充模型实时运行证明;元数据恢复/轮询失败明确为“状态同步异常”,保留最后记录且不重新查询。已有确认、取消、失败、完成状态继续来自 Host 任务数据,实际主体进度仍来自服务端计数,不伪造百分比。
12
+
13
+ ## 验证范围
14
+
15
+ - npm run check:277 项通过,包括安装包检查、正文语法与既有业务测试。
16
+ - 新增/调整断言:首页不含副标题组件或专属样式;同时点击只创建一个 Session;外产品标题和 dock 不被接管;既有 settling→hero、文本刷新、普通 Session、phase observer 清理继续回归。
17
+ - scripts/ui-layout-regression.mjs:10/10 通过,真实 React/Chromium,合成 Host DOM/API fixture,浅/深色 × 5 尺寸。验证品牌、普通会话恢复、晚挂载和无副标题;完整现有导入/映射/确认/下载测试保留。
18
+ - 浏览器 fixture 不等于完整真实 DSH 宿主。当前本轮未验证四包真实共装、用户正式页面或真实模型/QCC/OCR;正式版本仍为 0.9.11。
19
+
20
+ ## 边界
21
+
22
+ 清洗目前没有已验证的模型 running 状态接口,不新增假定宿主正在思考的状态条,也不声称掌握模型停止原因。恢复仅读取任务元数据。模型运行态由原生会话显示。
23
+
24
+ 证据:`/private/tmp/dc-unified-home-check.log`、`/private/tmp/dc-unified-home-ui-final.log` 与本工作树 `_scratch/ui-layout/results.json`。最后的未知标题保护收紧由观察器行为测试覆盖,未影响布局;其后完整 277 项检查再次通过。
package/lib/client.js CHANGED
@@ -200,14 +200,13 @@ window.__ModuleLoader__.load({
200
200
  }
201
201
  .dcAgentCapability svg { flex: 0 0 auto; }
202
202
 
203
- /* 原生 input.dock 保留轻量简介;菜单独立 Portal 到 composer 后,不重排共享 slot。 */
203
+ /* 首页无副标题或占位;菜单独立 Portal 到 composer 后,不重排共享 slot。 */
204
204
 
205
205
  .dcAgentExperience {
206
206
  width: 100%;
207
207
  box-sizing: border-box;
208
208
  }
209
209
  .dcAgentCapabilityMount { width: 100%; padding: 8px 0; flex: none; }
210
- .dcAgentHomeSummary { margin: 0 20px 8px; text-align: center; color: var(--dc-muted); font-size: 13px; line-height: 20px; }
211
210
  .dcAgentPromptBackdrop { position: fixed; inset: 0; z-index: 2000; display: grid; place-items: center; padding: 16px; box-sizing: border-box; background: rgba(8, 15, 28, .36); pointer-events: auto; }
212
211
  body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
213
212
 
@@ -2531,6 +2530,8 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2531
2530
  const { wide, useStore, actions, startSession } = props;
2532
2531
  useStore((state) => state.open);
2533
2532
  const [topMount, setTopMount] = react.useState(null);
2533
+ const [opening, setOpening] = react.useState(false);
2534
+ const openingRef = react.useRef(false);
2534
2535
 
2535
2536
  react.useEffect(() => {
2536
2537
  let disposed = false;
@@ -2559,7 +2560,12 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2559
2560
  className: 'dcAgentLauncher',
2560
2561
  'data-wide': wide,
2561
2562
  'aria-label': '数据清洗补全',
2563
+ 'aria-busy': opening,
2564
+ disabled: opening,
2562
2565
  onClick: async () => {
2566
+ if (openingRef.current) return;
2567
+ openingRef.current = true;
2568
+ setOpening(true);
2563
2569
  try {
2564
2570
  if (typeof startSession === 'function') {
2565
2571
  const sessionId = await startSession();
@@ -2568,6 +2574,9 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2568
2574
  } catch (error) {
2569
2575
  actions.setError(error instanceof Error ? error.message : String(error));
2570
2576
  console.error('[dc-agent] open failed:', error);
2577
+ } finally {
2578
+ openingRef.current = false;
2579
+ setOpening(false);
2571
2580
  }
2572
2581
  },
2573
2582
  children: h('span', { className: 'dcAgentLauncherContent' }, h(DatabaseLogo), wide ? h('span', null, '数据清洗补全') : null),
@@ -2604,11 +2613,6 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2604
2613
  authorization_required: '待连接企查查', cancelled: '已取消', parse_failed: '解析失败',
2605
2614
  };
2606
2615
 
2607
- function ProductHome() {
2608
- return h('p', { className: 'dcAgentHomeSummary' },
2609
- '导入企业名单或图片,核验主体、补全字段,并导出可追溯结果。');
2610
- }
2611
-
2612
2616
  function workflowNavigationIssue(step, task, hasData, profile, qccRun, hasLocalResult = false) {
2613
2617
  if (['upload', 'history'].includes(step)) return null;
2614
2618
  if (step === 'download' && task?.artifacts?.length) return null;
@@ -2744,8 +2748,6 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2744
2748
  const changedMarks = new Map();
2745
2749
  const changedRows = new Map();
2746
2750
  const ownedLogos = new Map();
2747
- const hiddenForeignDocks = new Map();
2748
- const composerStack = marker?.parentElement?.parentElement;
2749
2751
  // 单一会话所有权由入口 enabled 与真实宿主 data-phase=hero 共同保证,
2750
2752
  // 与 React effect 生命周期共同保证:非清洗会话不会挂载,会话切换即走 cleanup 让位。
2751
2753
  // 有界同步:每次 fix 的 DOM 变更计入校正预算,达到上限即断开观察器,杜绝与其它插件互相改写的死循环。
@@ -2763,7 +2765,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2763
2765
  ?? hero.querySelector?.('[class*="headlineText"]');
2764
2766
  const badge = spans.find((element) => element.dataset?.dcAgentHeroBadge === 'true')
2765
2767
  ?? spans.find((element) => ['预览版', 'Preview'].includes(element.textContent?.trim()));
2766
- if (title) {
2768
+ if (title && ['数据清洗补全智能体', '探索未至之境', '探索未知之境', 'Into the Unknown'].includes(title.textContent?.trim())) {
2767
2769
  if (!changedTitles.has(title)) changedTitles.set(title, title.textContent ?? '');
2768
2770
  title.dataset.dcAgentHeroTitle = 'true';
2769
2771
  if (title.textContent !== '数据清洗补全智能体') { title.textContent = '数据清洗补全智能体'; mutated = true; }
@@ -2791,28 +2793,12 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2791
2793
  }
2792
2794
  }
2793
2795
  }
2794
- if (badge) {
2796
+ if (badge && title?.dataset?.dcAgentHeroTitle === 'true') {
2795
2797
  if (!changedBadges.has(badge)) changedBadges.set(badge, badge.style?.display ?? '');
2796
2798
  badge.dataset.dcAgentHeroBadge = 'true';
2797
2799
  if (badge.style && badge.style.display !== 'none') { badge.style.display = 'none'; mutated = true; }
2798
2800
  }
2799
2801
 
2800
- const foreignSurfaces = composerStack?.querySelectorAll?.('[aria-label="尽调类型"], .qccDock') ?? [];
2801
- for (const foreignSurface of foreignSurfaces) {
2802
- let hideTarget = foreignSurface;
2803
- while (hideTarget?.parentElement
2804
- && hideTarget.parentElement !== composerStack
2805
- && hideTarget.parentElement !== marker.parentElement) {
2806
- hideTarget = hideTarget.parentElement;
2807
- }
2808
- // DSH 的 list slot 可能把多个插件放进同一个 data-slot 容器。此时只能隐藏
2809
- // 对方自己的根节点,不能隐藏共享 slot;独立 host 则隐藏其直接容器。
2810
- if ((hideTarget?.parentElement === composerStack || hideTarget?.parentElement === marker.parentElement)
2811
- && !hideTarget.contains?.(marker)) {
2812
- if (!hiddenForeignDocks.has(hideTarget)) hiddenForeignDocks.set(hideTarget, hideTarget.style?.display ?? '');
2813
- if (hideTarget.style && hideTarget.style.display !== 'none') { hideTarget.style.display = 'none'; mutated = true; }
2814
- }
2815
- }
2816
2802
  if (mutated) {
2817
2803
  corrections += 1;
2818
2804
  if (corrections >= MAX_HERO_CORRECTIONS && observer) {
@@ -2842,9 +2828,6 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2842
2828
  if (badge.style) badge.style.display = originalDisplay;
2843
2829
  delete badge.dataset.dcAgentHeroBadge;
2844
2830
  }
2845
- for (const [foreignDock, originalDisplay] of hiddenForeignDocks) {
2846
- if (foreignDock.style) foreignDock.style.display = originalDisplay;
2847
- }
2848
2831
  };
2849
2832
  }
2850
2833
 
@@ -2895,7 +2878,6 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2895
2878
  },
2896
2879
  dependencyMessage ? h('p', { className: 'dcAgentError', role: 'alert' }, dependencyMessage) : null,
2897
2880
  menuMount ? reactDom.createPortal(h(CapabilityBar, { sessionId }), menuMount) : h(CapabilityBar, { sessionId }),
2898
- hero ? h(ProductHome, { sessionId }) : null,
2899
2881
  );
2900
2882
  }
2901
2883
 
@@ -3872,7 +3854,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
3872
3854
  const taskId = workflowTaskBySession.get(key)?.id || (/^dcw-[a-zA-Z0-9-]+$/.test(saved || '') ? saved : null);
3873
3855
  if (taskId) await refreshHostedTask(actions, activeSessionId, taskId, null, false);
3874
3856
  }).catch((taskError) => {
3875
- if (!disposed) actions.setError(taskError instanceof Error ? taskError.message : String(taskError));
3857
+ if (!disposed) actions.setError(`状态同步异常:${taskError instanceof Error ? taskError.message : String(taskError)}。保留最近任务记录,未重新执行查询。`);
3876
3858
  });
3877
3859
  }
3878
3860
  return () => { disposed = true; };
@@ -3890,7 +3872,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
3890
3872
  if (!task) return;
3891
3873
  if (['matching', 'enriching'].includes(task.state)) timer = setTimeout(poll, 2000);
3892
3874
  else if (step === 'match' || step === 'enrich') actions.setStep(task.stage || step);
3893
- } catch (error) { if (!disposed) actions.setError(error.message); }
3875
+ } catch (error) { if (!disposed) actions.setError(`状态同步异常:${error.message}。保留最近任务记录,未重新执行查询。`); }
3894
3876
  };
3895
3877
  timer = setTimeout(poll, 2000);
3896
3878
  return () => { disposed = true; clearTimeout(timer); };
@@ -4831,8 +4813,9 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
4831
4813
  ) : null,
4832
4814
  h('div', { className: 'dcAgentWbBody' },
4833
4815
  cachedTask && step !== 'history' ? h('section', { className: 'dcAgentSection', 'aria-label': '当前任务进展', 'aria-live': 'polite' },
4834
- h('b', null, cachedTask.source?.type === 'image' && cachedTask.state === 'draft' ? '图片已暂存,待识别' : WORKFLOW_STATE_LABELS[cachedTask.state] || cachedTask.state),
4816
+ h('b', null, cachedTask.source?.type === 'image' && cachedTask.state === 'draft' ? '图片已暂存,待识别' : `任务记录:${WORKFLOW_STATE_LABELS[cachedTask.state] || '状态未知'}`),
4835
4817
  h('h3', null, workflowDisplayName(cachedTask)),
4818
+ ['matching', 'enriching'].includes(cachedTask.state) ? h('p', { className: 'dcAgentHint' }, '以上为最近同步的任务记录,不代表模型仍在运行。若会话已停止,请查看原会话的确认或错误提示;不要重复启动。') : null,
4836
4819
  h('details', null, h('summary', null, '任务详情'), h('p', { className: 'dcAgentHint' }, `任务编号:${cachedTask.id}`)),
4837
4820
  h('p', null, `${cachedTask.source?.type === 'image' ? '图片识别' : cachedTask.source?.type === 'text' ? '粘贴名单' : cachedTask.source ? '上传表格' : '待选择数据来源'}${cachedTask.source?.fileName ? ' · ' + cachedTask.source.fileName : ''} · ${cachedTask.source?.type === 'image' && cachedTask.state === 'draft' ? '条目数待识别' : `${cachedTask.source?.rowCount || 0} 条`} · ${cachedTask.fieldSelection?.length || 0} 个补全字段`),
4838
4821
  commandProgress?.taskId === cachedTask.id && Number.isFinite(commandProgress.totalUnique) ? h('p', null, `已处理主体 ${commandProgress.completedUnique}/${commandProgress.totalUnique}(去重后,含未匹配或失败,不代表补全成功)`) : null,
@@ -5239,7 +5222,6 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
5239
5222
  visibleCatalogFields,
5240
5223
  installCapabilityMount,
5241
5224
  PromptDialog,
5242
- ProductHome,
5243
5225
  workflowNavigationIssue,
5244
5226
  buildTaskPrompt,
5245
5227
  DatasetReview,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-data-cleaning-agent",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
4
4
  "description": "Data cleaning and data enrichment for CSV/XLSX/JSON enterprise lists in DeepSeek Harness, including spreadsheet cleaning, deduplication, profiling, optional Qichacha MCP and exports.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -21,6 +21,8 @@
21
21
  "marketing",
22
22
  "docs/USER-GUIDE.md",
23
23
  "docs/RELEASE-0.9.11.md",
24
+ "docs/RELEASE-0.9.12.md",
25
+ "docs/UNIFIED-HOME-1.5.4-ADOPTION.md",
24
26
  "docs/FIRST-CONTRIBUTION.md",
25
27
  "docs/COMPATIBILITY.md",
26
28
  "docs/UI-V1.5.0-ADOPTION.md",