dsh-data-cleaning-agent 0.9.9 → 0.9.11

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,17 @@
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.11] - 2026-09-13
8
+
9
+ - 修正真实 Host 首页判断:Session 并不提供 composerPhase;改为观察当前清洗会话 DOM 的真实 data-phase,确保标题替换实际启用。
10
+ - 回归夹具移除虚构 composerPhase 字段,覆盖 settling/hero/active、普通会话隔离与卸载恢复。
11
+
12
+ ## [0.9.10] - 2026-09-13
13
+
14
+ - 修复首页先挂载于 settling 阶段导致 Logo 与标题替换被跳过的问题;监听宿主阶段及文本节点变化,显示“数据清洗补全智能体”。
15
+ - 兼容“探索未知之境”文案,保留 0.9.9 同级标题分支适配;不再降级到 document.body 全局改写。
16
+ - 新增延迟 Hero 挂载、标题刷新和离开会话恢复回归;真实 DSH 页面仍需登录后验收。
17
+
7
18
  ## [0.9.9] - 2026-09-13
8
19
 
9
20
  - 原生首页标题桥接适配新版 Host 的 composer sibling slot;菜单进入数据清洗补全后稳定显示“数据清洗补全智能体”,不再回退为“探索未至之境”。
package/README.en.md CHANGED
@@ -10,7 +10,11 @@ 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.9** (stable release)
13
+ > Current source version / 当前源码版本: **0.9.11** (stable release)
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.
16
+
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.
14
18
 
15
19
  0.9.9 restores the “数据清洗补全智能体” native home title when newer Host builds place the plugin marker and Hero headline in sibling composer branches. The bridge remains reversible and isolated from other business plugins. The 0.9.8 read-only Profile history and origin Workspace/Session guarantees remain unchanged. Rollback: `dsh plugin --profile web add dsh-data-cleaning-agent@0.9.8`. Live DSH A/B verification remains a post-install user check.
16
20
 
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.9
12
+ dsh plugin --profile web add dsh-data-cleaning-agent@0.9.11
13
13
  ```
14
14
 
15
15
  请先满足下文的 DSH、连接器及侧边栏依赖要求;安装后完整停止并重启对应 Profile。
@@ -27,7 +27,11 @@ dsh plugin --profile web add dsh-data-cleaning-agent@0.9.9
27
27
 
28
28
  > 在 DeepSeek Harness 中清洗、补全、画像企业名单数据的智能体插件:本地 CSV/XLSX/JSON 引擎 + 可选企查查(Qichacha/QCC)MCP 企业数据补全,由企查查(Qichacha/QCC)团队发起并维护。
29
29
  >
30
- > 当前源码版本 / Current source version: **0.9.9**(正式版本)
30
+ > 当前源码版本 / Current source version: **0.9.11**(正式版本)
31
+
32
+ 0.9.11 修正真实 Host 的首页状态接口:不再依赖 Session.composerPhase,按当前清洗会话所在宿主根节点的 data-phase 显示 Logo 与标题,并在离开首页时恢复。
33
+
34
+ 0.9.10 补齐首页 settling → hero 阶段监听,避免首次挂载漏掉 Logo 与标题替换;兼容“探索未知之境”,未知结构不做全局标题改写。回滚版本为 0.9.9。
31
35
 
32
36
  0.9.9 修复新版 Host composer sibling slot 下的原生首页标题定位,进入数据清洗补全后稳定显示“数据清洗补全智能体”,并保持对其它业务插件的标题隔离。0.9.8 的 Profile 历史只读、来源工作区/会话校验与旧记录边界全部保留。回滚:`dsh plugin --profile web add dsh-data-cleaning-agent@0.9.8`。真实 DSH A/B 验收仍以安装后的用户验证为准,详见发布说明。
33
37
 
@@ -0,0 +1,18 @@
1
+ # 0.9.11 · Real Host home phase
2
+
3
+ The real DSH Session snapshot does not expose composerPhase. Versions 0.9.9/0.9.10
4
+ adapted the DOM rewrite but its caller never enabled it. The former React fixture
5
+ supplied that nonexistent property and masked the integration bug.
6
+
7
+ The cleaning experience now observes data-phase on its own marker's closest Host
8
+ root. It never derives the phase from input text or other Sessions. Unknown or active
9
+ roots are not treated as home. The observer disconnects on Session changes/unmount.
10
+ Hero changes retain the existing reversible logo/title behavior.
11
+
12
+ Session-scoped factories can also mount after the root ownership event. Restore
13
+ ownership from the explicit independently-created cleaning Session namespace;
14
+ never infer it from another Session, a task history selection or draft text.
15
+
16
+ Tests must omit composerPhase, cover settling/hero/active and ordinary Session cleanup.
17
+ Real logged-in DSH visual acceptance and final registry evidence are recorded in Release notes.
18
+ No paid QCC/OCR calls are needed for branding acceptance. Rollback: 0.9.10 (known title bug).
package/lib/client.js CHANGED
@@ -1530,6 +1530,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
1530
1530
  isCleaningSession(sessionId) ? sessionId : null,
1531
1531
  );
1532
1532
  react.useEffect(() => {
1533
+ setMarkedSessionId(isCleaningSession(sessionId) ? sessionId : null);
1533
1534
  const handleMarked = (event) => {
1534
1535
  const detail = event?.detail ?? {};
1535
1536
  setMarkedSessionId(detail.active === true && detail.sessionId === sessionId ? sessionId : null);
@@ -1539,7 +1540,9 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
1539
1540
  }, [sessionId]);
1540
1541
  // DSH 可能复用同一个 slot component 切换会话;状态必须绑定具体 sessionId,
1541
1542
  // 避免从清洗会话切回普通会话后仍残留业务首页与提示词入口。
1542
- return markedSessionId === sessionId && isCleaningSession(sessionId);
1543
+ // Session-scoped slot factories can mount after the root ownership event.
1544
+ // Our independently-created namespace is durable ownership, unlike a draft.
1545
+ return ownedSessionId(sessionId) || (markedSessionId === sessionId && isCleaningSession(sessionId));
1543
1546
  }
1544
1547
 
1545
1548
  /**
@@ -2722,18 +2725,19 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2722
2725
  if (!scope?.querySelectorAll) return false;
2723
2726
  const spans = [...scope.querySelectorAll('span')];
2724
2727
  return spans.some((element) => element.dataset?.dcAgentHeroTitle === 'true'
2725
- || ['探索未至之境', 'Into the Unknown'].includes(element.textContent?.trim()))
2728
+ || ['探索未至之境', '探索未知之境', 'Into the Unknown'].includes(element.textContent?.trim()))
2726
2729
  || Boolean(scope.querySelector?.('[class*="headlineText"]'));
2727
2730
  };
2728
2731
  // 新版 Host 会把 list slot 放在 composer seat 的独立分支;marker 不一定再是
2729
2732
  // data-phase=hero 的后代。沿祖先寻找同时包含原生标题的最小范围,保留旧结构兼容。
2730
- let hero = marker?.closest?.('[data-phase="hero"]') ?? null;
2733
+ // Observe the same root while Host layout transitions from settling to hero.
2734
+ let hero = marker?.closest?.('[data-phase="hero"]')
2735
+ ?? marker?.closest?.('[data-phase="settling"]') ?? null;
2731
2736
  if (!hasHeadline(hero)) {
2732
2737
  let scope = marker?.closest?.('[data-composer-seat]') ?? marker?.parentElement ?? null;
2733
- while (scope && !hasHeadline(scope)) scope = scope.parentElement;
2734
- if (scope) hero = scope;
2738
+ while (scope && scope !== document.body && scope !== document.documentElement && !hasHeadline(scope)) scope = scope.parentElement;
2739
+ if (scope && scope !== document.body && scope !== document.documentElement) hero = scope;
2735
2740
  }
2736
- if (!hero && document.body?.querySelectorAll) hero = document.body;
2737
2741
  if (!hero) return () => {};
2738
2742
  const changedTitles = new Map();
2739
2743
  const changedBadges = new Map();
@@ -2742,7 +2746,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2742
2746
  const ownedLogos = new Map();
2743
2747
  const hiddenForeignDocks = new Map();
2744
2748
  const composerStack = marker?.parentElement?.parentElement;
2745
- // 单一会话所有权由入口的 enabled 参数(useCleaningSession(sessionId) && composerPhase==='blank')
2749
+ // 单一会话所有权由入口 enabled 与真实宿主 data-phase=hero 共同保证,
2746
2750
  // 与 React effect 生命周期共同保证:非清洗会话不会挂载,会话切换即走 cleanup 让位。
2747
2751
  // 有界同步:每次 fix 的 DOM 变更计入校正预算,达到上限即断开观察器,杜绝与其它插件互相改写的死循环。
2748
2752
  const MAX_HERO_CORRECTIONS = 8;
@@ -2750,10 +2754,12 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2750
2754
  let observer = null;
2751
2755
 
2752
2756
  const fix = () => {
2757
+ if (hero.getAttribute?.('data-phase') === 'settling') return;
2758
+ if (hero.getAttribute?.('data-phase') === 'active') return;
2753
2759
  let mutated = false;
2754
2760
  const spans = [...hero.querySelectorAll('span')];
2755
2761
  const title = spans.find((element) => element.dataset?.dcAgentHeroTitle === 'true')
2756
- ?? spans.find((element) => ['探索未至之境', 'Into the Unknown'].includes(element.textContent?.trim()))
2762
+ ?? spans.find((element) => ['探索未至之境', '探索未知之境', 'Into the Unknown'].includes(element.textContent?.trim()))
2757
2763
  ?? hero.querySelector?.('[class*="headlineText"]');
2758
2764
  const badge = spans.find((element) => element.dataset?.dcAgentHeroBadge === 'true')
2759
2765
  ?? spans.find((element) => ['预览版', 'Preview'].includes(element.textContent?.trim()));
@@ -2818,7 +2824,8 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2818
2824
 
2819
2825
  fix();
2820
2826
  observer = typeof MutationObserver === 'function' ? new MutationObserver(fix) : null;
2821
- observer?.observe?.(hero, { childList: true, subtree: true });
2827
+ observer?.observe?.(hero, { childList: true, subtree: true, characterData: true,
2828
+ attributes: true, attributeFilter: ['data-phase'] });
2822
2829
  return () => {
2823
2830
  observer?.disconnect?.();
2824
2831
  for (const logo of ownedLogos.values()) logo.remove();
@@ -2841,6 +2848,22 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2841
2848
  };
2842
2849
  }
2843
2850
 
2851
+ function observeHomePhase(sessionId, enabled, onChange) {
2852
+ onChange(false);
2853
+ if (!enabled || typeof document === 'undefined') return () => {};
2854
+ const marker = [...(document.querySelectorAll?.('.dcAgentExperience') || [])]
2855
+ .find(node => node.dataset?.sessionId === sessionId);
2856
+ // Session snapshots do not expose composerPhase. The Host's own rendered root
2857
+ // is authoritative; never infer a blank conversation from draft text or title.
2858
+ const root = marker?.closest?.('[data-phase]');
2859
+ if (!root) return () => {};
2860
+ const update = () => onChange(root.getAttribute('data-phase') === 'hero');
2861
+ update();
2862
+ const observer = typeof MutationObserver === 'function' ? new MutationObserver(update) : null;
2863
+ observer?.observe(root, { attributes: true, attributeFilter: ['data-phase'] });
2864
+ return () => observer?.disconnect();
2865
+ }
2866
+
2844
2867
  function DataCleaningExperience(props) {
2845
2868
  const { sessionId, session: ownerSession } = props;
2846
2869
  const enabled = useCleaningSession(sessionId);
@@ -2850,7 +2873,10 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
2850
2873
  document.addEventListener(DEPENDENCY_EVENT, listener);
2851
2874
  return () => document.removeEventListener(DEPENDENCY_EVENT, listener);
2852
2875
  }, [sessionId]);
2853
- const hero = ownerSession?.composerPhase === 'blank';
2876
+ const [hero, setHero] = react.useState(false);
2877
+ react.useEffect(() => observeHomePhase(sessionId, enabled,
2878
+ value => setHero(current => current === value ? current : value)),
2879
+ [sessionId, enabled, ownerSession?.openState]);
2854
2880
  const [menuMount, setMenuMount] = react.useState(null);
2855
2881
  react.useEffect(() => {
2856
2882
  if (!enabled) return undefined;
@@ -5244,6 +5270,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
5244
5270
  plainEntityListDataset,
5245
5271
  resultFieldLabel,
5246
5272
  rewriteHeroChrome,
5273
+ observeHomePhase,
5247
5274
  ensureWorkflowTask,
5248
5275
  ensureEditableWorkflowTask,
5249
5276
  queueWorkflowOperation,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-data-cleaning-agent",
3
- "version": "0.9.9",
3
+ "version": "0.9.11",
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",
@@ -20,7 +20,7 @@
20
20
  "install.sh",
21
21
  "marketing",
22
22
  "docs/USER-GUIDE.md",
23
- "docs/RELEASE-0.9.9.md",
23
+ "docs/RELEASE-0.9.11.md",
24
24
  "docs/FIRST-CONTRIBUTION.md",
25
25
  "docs/COMPATIBILITY.md",
26
26
  "docs/UI-V1.5.0-ADOPTION.md",
@@ -1,24 +0,0 @@
1
- # 0.9.9 · Native home title compatibility
2
-
3
- Status: stable release. Date: 2026-09-13.
4
-
5
- ## Scope
6
-
7
- - Adapt the reversible native Hero title bridge to Host layouts where the plugin marker and headline live in sibling branches below the composer container.
8
- - Keep the data-cleaning home title fixed at “数据清洗补全智能体” without modifying another business plugin's headline, prompt UI or input focus.
9
- - Preserve the 0.9.8 Profile history ownership, origin Workspace/Session checks and artifact-download behavior.
10
-
11
- ## Verification
12
-
13
- - The coexistence fixture now exercises a sibling-slot Host structure rather than the obsolete nested Hero structure.
14
- - `npm run check` covers syntax, documentation version consistency, marketing metadata, package allowlist and the full Node test suite.
15
- - The React/Chromium layout matrix remains a separate isolated UI gate; real DSH and production QCC Provider behavior require post-install acceptance.
16
-
17
- ## Install and rollback
18
-
19
- ```sh
20
- dsh plugin --profile web add dsh-data-cleaning-agent@0.9.9
21
- ```
22
-
23
- Rollback package: `dsh plugin --profile web add dsh-data-cleaning-agent@0.9.8`.
24
- Do not move or overwrite existing tags or npm versions.