dsh-data-cleaning-agent 0.8.21 → 0.8.23
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 +14 -0
- package/README.en.md +1 -1
- package/README.md +3 -3
- package/docs/RELEASE-0.8.22.md +11 -0
- package/lib/client.js +51 -13
- package/lib/qcc.js +5 -1
- package/package.json +2 -2
- package/docs/RELEASE-0.8.21.md +0 -9
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.8.23] - 2026-09-09
|
|
8
|
+
|
|
9
|
+
- 工作台顶部仅保留产品标题和展开、关闭按钮,移除重复状态与技术标识。
|
|
10
|
+
- 完整任务状态保留在进度卡;约束标题收缩,避免窄屏时与按钮重叠。
|
|
11
|
+
- 246 项测试与 10 组深浅主题、不同视口布局回归通过。
|
|
12
|
+
|
|
13
|
+
## [0.8.22] - 2026-09-09
|
|
14
|
+
|
|
15
|
+
- 表格预览保留可读列宽、横向滚动和固定表头,避免多列挤压成竖排。
|
|
16
|
+
- 结果文件操作分行并留白,长文件名换行;失败计数单独展示,避免零补全被标绿。
|
|
17
|
+
- 失败行导出保留规范化错误码和工具名,不输出原始上游响应或凭据。
|
|
18
|
+
- 修复自动展开后关闭/切换会话时,排队中的尺寸回调重新写入布局留白的竞态。
|
|
19
|
+
- 延续 0.8.21 的实际 Host 文件地址和执行自动展开功能。
|
|
20
|
+
|
|
7
21
|
## [0.8.21] - 2026-09-09
|
|
8
22
|
|
|
9
23
|
- 从实际 Host 请求获取文件地址的协议和主机;修复本地 HTTP 链接被补成 HTTPS 的问题。
|
package/README.en.md
CHANGED
|
@@ -8,7 +8,7 @@ Related agents: [数据清洗补全](https://github.com/duhu2000/dsh-data-cleani
|
|
|
8
8
|
|
|
9
9
|
> 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.
|
|
10
10
|
>
|
|
11
|
-
> Current source version / 当前源码版本: **0.8.
|
|
11
|
+
> Current source version / 当前源码版本: **0.8.23** (stable release)
|
|
12
12
|
|
|
13
13
|
This release unifies spreadsheet previews, column mapping, and enrichment scope across the prompt wizard and workbench. Mapping statuses use color and text; mapped fields automatically enter the scope, with optional extra fields collapsed. Multiple confirmed output columns may share a non-identity field while preserving non-empty values. It fixes saved drafts resetting the scope to five defaults and detects stale Host versions. Preparing a draft does not query QCC; sending starts execution. Fully restart DSH after upgrading. Existing download artifacts are not rewritten.
|
|
14
14
|
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# dsh-data-cleaning-agent
|
|
2
2
|
|
|
3
|
-
本版统一向导与工作台的 Host 执行闭环:发送后自动生成新 Excel,原文件不修改,工作台入口可恢复;发布记录见 [发布说明](docs/RELEASE-0.8.
|
|
3
|
+
本版统一向导与工作台的 Host 执行闭环:发送后自动生成新 Excel,原文件不修改,工作台入口可恢复;发布记录见 [发布说明](docs/RELEASE-0.8.22.md)。
|
|
4
4
|
|
|
5
5
|
## 安装与三分钟上手
|
|
6
6
|
|
|
7
7
|
数据清洗补全智能体:面向 Excel/CSV/JSON 企业名单,提供数据清洗、表格清洗、清洗补全、去重、企业数据补全与字段补全,支持企查查 MCP 和结果导出。
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
dsh plugin --profile web add dsh-data-cleaning-agent@0.8.
|
|
10
|
+
dsh plugin --profile web add dsh-data-cleaning-agent@0.8.23
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
请先满足下文的 DSH、连接器及侧边栏依赖要求;安装后完整停止并重启对应 Profile。
|
|
@@ -25,7 +25,7 @@ dsh plugin --profile web add dsh-data-cleaning-agent@0.8.21
|
|
|
25
25
|
|
|
26
26
|
> 在 DeepSeek Harness 中清洗、补全、画像企业名单数据的智能体插件:本地 CSV/XLSX/JSON 引擎 + 可选企查查(Qichacha/QCC)MCP 企业数据补全,由企查查(Qichacha/QCC)团队发起并维护。
|
|
27
27
|
>
|
|
28
|
-
> 当前源码版本 / Current source version: **0.8.
|
|
28
|
+
> 当前源码版本 / Current source version: **0.8.23**(正式版本)
|
|
29
29
|
|
|
30
30
|
本版上传表格后展示完整清单及空白数量,用绿色、琥珀色、红色及文字区分已通过、待确认和未匹配映射。已映射字段自动纳入补全范围,额外字段默认折叠;多个原列可经确认使用同一非主体字段,分别补空并保留非空原值。修复 Host 草稿重置为默认五字段的问题,增加前后端版本错配提示。生成说明不查询,发送才执行;升级后需完整重启 DSH,历史下载文件不自动改写。
|
|
31
31
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# 0.8.22 发布说明
|
|
2
|
+
|
|
3
|
+
包含 0.8.21 的实际 Host 协议文件链接与执行自动展开功能;额外修复尺寸回调在工作台关闭后写回留白的竞态。
|
|
4
|
+
|
|
5
|
+
- 表格不压缩列宽,支持左右滚动;纵向滚动固定表头。
|
|
6
|
+
- 预览和下载操作分行留白,长文件名不再挤压按钮。
|
|
7
|
+
- 单独显示失败数量;失败行在异常清单保留规范化错误码和工具名。
|
|
8
|
+
|
|
9
|
+
本次不改变企查查查询范围,不自动重跑历史任务;历史异常文件不会补写已遗漏的错误信息。
|
|
10
|
+
|
|
11
|
+
升级后完整重启 DSH。历史错误链接文本不会重写,可从工作台访问原有文件,不需要重新查询。
|
package/lib/client.js
CHANGED
|
@@ -89,19 +89,27 @@ window.__ModuleLoader__.load({
|
|
|
89
89
|
const handle = drawer.querySelector('.dcAgentResizeHandle');
|
|
90
90
|
if (!handle || !view) return () => {};
|
|
91
91
|
const reservations = new Map();
|
|
92
|
+
const registryKey = Symbol.for('dsh.data-cleaning.sizing-reservations');
|
|
93
|
+
const registry = doc[registryKey] || (doc[registryKey] = new WeakMap());
|
|
94
|
+
let disposed = false;
|
|
92
95
|
let requested = expanded ? 980 : preferredWidth;
|
|
93
96
|
let current = 0;
|
|
94
97
|
let drag = null;
|
|
95
98
|
const boundsForView = () => workbenchWidthBounds(view.innerWidth,
|
|
96
99
|
doc.querySelector('[data-conversation-scroll]')?.getBoundingClientRect().width || view.innerWidth);
|
|
97
100
|
const reserve = () => {
|
|
101
|
+
if (disposed) return;
|
|
98
102
|
const width = boundsForView().mobile ? 0 : drawer.getBoundingClientRect().width;
|
|
99
103
|
for (const el of doc.querySelectorAll('[data-conversation-scroll]')) {
|
|
100
104
|
if (!reservations.has(el)) {
|
|
101
|
-
|
|
105
|
+
const previous = registry.get(el) || {
|
|
102
106
|
value: el.style.getPropertyValue('--dc-agent-workbench-reserve'),
|
|
103
107
|
priority: el.style.getPropertyPriority('--dc-agent-workbench-reserve'),
|
|
104
|
-
|
|
108
|
+
owners: 0,
|
|
109
|
+
};
|
|
110
|
+
previous.owners += 1;
|
|
111
|
+
registry.set(el, previous);
|
|
112
|
+
reservations.set(el, previous);
|
|
105
113
|
sizeObserver?.observe(el, { box: 'border-box' });
|
|
106
114
|
}
|
|
107
115
|
if (el.style.getPropertyValue('--dc-agent-workbench-reserve') !== `${width}px`) {
|
|
@@ -110,6 +118,7 @@ window.__ModuleLoader__.load({
|
|
|
110
118
|
}
|
|
111
119
|
};
|
|
112
120
|
const apply = (value) => {
|
|
121
|
+
if (disposed) return;
|
|
113
122
|
const bounds = boundsForView();
|
|
114
123
|
const fallback = view.innerWidth <= 1040 ? Math.min(420, view.innerWidth * .48) : Math.min(460, view.innerWidth * .42);
|
|
115
124
|
current = Math.round(Math.min(bounds.max, Math.max(bounds.min, Number.isFinite(value) ? value : fallback)));
|
|
@@ -173,6 +182,7 @@ window.__ModuleLoader__.load({
|
|
|
173
182
|
observer?.observe(doc.body, { childList: true, subtree: true });
|
|
174
183
|
apply(requested);
|
|
175
184
|
return () => {
|
|
185
|
+
disposed = true;
|
|
176
186
|
cancel();
|
|
177
187
|
observer?.disconnect();
|
|
178
188
|
sizeObserver?.disconnect();
|
|
@@ -188,6 +198,9 @@ window.__ModuleLoader__.load({
|
|
|
188
198
|
drawer.style.removeProperty('--dc-agent-panel-width');
|
|
189
199
|
delete drawer.dataset.narrow;
|
|
190
200
|
for (const [el, previous] of reservations) {
|
|
201
|
+
previous.owners -= 1;
|
|
202
|
+
if (previous.owners > 0) continue;
|
|
203
|
+
registry.delete(el);
|
|
191
204
|
if (previous.value) el.style.setProperty('--dc-agent-workbench-reserve', previous.value, previous.priority);
|
|
192
205
|
else el.style.removeProperty('--dc-agent-workbench-reserve');
|
|
193
206
|
}
|
|
@@ -626,6 +639,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
626
639
|
|
|
627
640
|
.dcAgentWbTitle b,
|
|
628
641
|
.dcAgentWbTitle small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
642
|
+
.dcAgentWbTitle > div { min-width: 0; }
|
|
629
643
|
.dcAgentWbTitle b { display: block; font-size: 15px; }
|
|
630
644
|
.dcAgentWbTitle small { display: block; max-width: 190px; color: var(--dc-muted); font-size: 12px; }
|
|
631
645
|
|
|
@@ -970,6 +984,25 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
970
984
|
}
|
|
971
985
|
.dcAgentFieldAction:hover, .dcAgentFieldAction:focus-visible { background: var(--dc-selected); }
|
|
972
986
|
.dcAgentPreviewTable { margin-top: 12px; overflow: auto; border: 1px solid var(--dc-border); border-radius: 8px; }
|
|
987
|
+
.dcAgentArtifactList { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; min-width: 0; }
|
|
988
|
+
.dcAgentArtifactList > .dcAgentButton { display: inline-flex; align-items: center; box-sizing: border-box; max-width: 100%; min-width: 0; height: auto; white-space: normal; overflow-wrap: anywhere; line-height: 1.5; text-decoration: none; }
|
|
989
|
+
.dcAgentArtifactList > a.dcAgentButton { flex-basis: 100%; }
|
|
990
|
+
.dcAgentPreviewTable { min-width: 0; max-width: 100%; scrollbar-gutter: stable; }
|
|
991
|
+
.dcAgentPreviewTable > .dcAgentTable {
|
|
992
|
+
width: max-content; min-width: 100%; max-width: none;
|
|
993
|
+
table-layout: auto; border-collapse: separate; border-spacing: 0;
|
|
994
|
+
}
|
|
995
|
+
.dcAgentPreviewTable > .dcAgentTable th,
|
|
996
|
+
.dcAgentPreviewTable > .dcAgentTable td {
|
|
997
|
+
min-width: 140px; max-width: none; white-space: nowrap;
|
|
998
|
+
word-break: normal; overflow-wrap: normal;
|
|
999
|
+
border-right: 1px solid var(--dc-border);
|
|
1000
|
+
}
|
|
1001
|
+
.dcAgentPreviewTable > .dcAgentTable th:first-child,
|
|
1002
|
+
.dcAgentPreviewTable > .dcAgentTable td:first-child { min-width: 64px; }
|
|
1003
|
+
.dcAgentPreviewTable > .dcAgentTable th {
|
|
1004
|
+
position: sticky; top: 0; z-index: 2; background: var(--dc-table-head);
|
|
1005
|
+
}
|
|
973
1006
|
.dcAgentHistoryTask { display: block; width: 100%; padding: 10px; text-align: left; }
|
|
974
1007
|
.dcAgentHistoryTask h3 { margin: 0; font-size: 12px; }
|
|
975
1008
|
/*
|
|
@@ -1863,10 +1896,11 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
1863
1896
|
}
|
|
1864
1897
|
function watchHostedCommand(actions, sessionId, command) {
|
|
1865
1898
|
let openedForExecution = false;
|
|
1899
|
+
const ownerVisible = () => typeof document === 'undefined' || [...document.querySelectorAll('.dcAgentExperience')].some(node => node.dataset.sessionId === sessionId);
|
|
1866
1900
|
void waitForQccCommand(command.commandId, 1800, async (status) => {
|
|
1867
1901
|
if (!status || status.state === 'prepared') return;
|
|
1868
1902
|
await refreshHostedTask(actions, sessionId, command.taskId, null, true).catch(() => {});
|
|
1869
|
-
if (!openedForExecution && isCleaningSession(sessionId) && workflowTaskBySession.get(String(sessionId))?.id === command.taskId) {
|
|
1903
|
+
if (!openedForExecution && ownerVisible() && isCleaningSession(sessionId) && workflowTaskBySession.get(String(sessionId))?.id === command.taskId) {
|
|
1870
1904
|
openedForExecution = true;
|
|
1871
1905
|
openWorkbench(actions, workflowTaskBySession.get(String(sessionId))?.stage || 'match', sessionId);
|
|
1872
1906
|
}
|
|
@@ -2185,6 +2219,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
2185
2219
|
const WORKBENCH_DATASET_EVENT = 'dsh:data-cleaning-workbench-dataset';
|
|
2186
2220
|
const WORKBENCH_DRAFT_EVENT = 'dsh:data-cleaning-workbench-draft';
|
|
2187
2221
|
const WORKBENCH_PREPARE_EVENT = 'dsh:data-cleaning-workbench-prepare';
|
|
2222
|
+
const WORKBENCH_OWNER_LEFT_EVENT = 'dsh:data-cleaning-workbench-owner-left';
|
|
2188
2223
|
|
|
2189
2224
|
// session scope 不能复用 root scope 的 store handle。DSH 当前会分别物化 root/session
|
|
2190
2225
|
// 插槽组件,因此以 document 事件跨 scope 通知;闭包引用仅作为无 DOM 测试降级。
|
|
@@ -2547,6 +2582,10 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
2547
2582
|
function DataCleaningExperience(props) {
|
|
2548
2583
|
const { sessionId, session: ownerSession } = props;
|
|
2549
2584
|
const enabled = useCleaningSession(sessionId);
|
|
2585
|
+
react.useEffect(() => {
|
|
2586
|
+
if (!enabled) return undefined;
|
|
2587
|
+
return () => document.dispatchEvent(new CustomEvent(WORKBENCH_OWNER_LEFT_EVENT, { detail: { sessionId } }));
|
|
2588
|
+
}, [enabled, sessionId]);
|
|
2550
2589
|
const hero = ownerSession?.composerPhase === 'blank';
|
|
2551
2590
|
const [menuMount, setMenuMount] = react.useState(null);
|
|
2552
2591
|
react.useEffect(() => {
|
|
@@ -3428,7 +3467,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3428
3467
|
h('p', { className: 'dcAgentHint', role: 'status' }, complete
|
|
3429
3468
|
? `共 ${total} 条,当前显示 ${total ? start + 1 : 0}–${Math.min(start + pageSize, total)} 条;共 ${columns.length} 列,可横向滚动。`
|
|
3430
3469
|
: `完整清单尚未就绪:预期 ${expectedCount} 条,当前载入 ${total} 条。请等待同步;刷新后若仍缺失,请重新上传源文件。`),
|
|
3431
|
-
h('div', { className: 'dcAgentPreviewTable', style: { overflow: 'auto', maxHeight: '420px' } },
|
|
3470
|
+
h('div', { className: 'dcAgentPreviewTable', tabIndex: 0, role: 'region', 'aria-label': '表格预览,可横向和纵向滚动,表头固定', style: { overflow: 'auto', maxHeight: '420px' } },
|
|
3432
3471
|
h('table', { className: 'dcAgentTable' },
|
|
3433
3472
|
h('thead', null, h('tr', null, h('th', null, '序号'), columns.map((key) => h('th', { key }, resultFieldLabel(key))))),
|
|
3434
3473
|
h('tbody', null, rows.slice(start, start + pageSize).map((row, index) => h('tr', { key: start + index },
|
|
@@ -3493,6 +3532,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3493
3532
|
|
|
3494
3533
|
react.useEffect(() => {
|
|
3495
3534
|
rootWorkbenchActions = actions;
|
|
3535
|
+
const handleOwnerLeft = () => actions.close();
|
|
3496
3536
|
const handleOpen = (event) => {
|
|
3497
3537
|
event?.preventDefault?.();
|
|
3498
3538
|
const detail = event?.detail ?? {};
|
|
@@ -3545,6 +3585,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3545
3585
|
};
|
|
3546
3586
|
if (typeof document !== 'undefined' && typeof document.addEventListener === 'function') {
|
|
3547
3587
|
document.addEventListener(WORKBENCH_OPEN_EVENT, handleOpen);
|
|
3588
|
+
document.addEventListener(WORKBENCH_OWNER_LEFT_EVENT, handleOwnerLeft);
|
|
3548
3589
|
document.addEventListener(WORKBENCH_DATASET_EVENT, handleDataset);
|
|
3549
3590
|
document.addEventListener(WORKBENCH_DRAFT_EVENT, handleDraft);
|
|
3550
3591
|
document.addEventListener(WORKBENCH_PREPARE_EVENT, handlePrepare);
|
|
@@ -3552,6 +3593,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3552
3593
|
return () => {
|
|
3553
3594
|
if (typeof document !== 'undefined' && typeof document.removeEventListener === 'function') {
|
|
3554
3595
|
document.removeEventListener(WORKBENCH_OPEN_EVENT, handleOpen);
|
|
3596
|
+
document.removeEventListener(WORKBENCH_OWNER_LEFT_EVENT, handleOwnerLeft);
|
|
3555
3597
|
document.removeEventListener(WORKBENCH_DATASET_EVENT, handleDataset);
|
|
3556
3598
|
document.removeEventListener(WORKBENCH_DRAFT_EVENT, handleDraft);
|
|
3557
3599
|
document.removeEventListener(WORKBENCH_PREPARE_EVENT, handlePrepare);
|
|
@@ -4143,6 +4185,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
4143
4185
|
? (qccRun.summary?.ambiguous ?? 0) + (qccRun.summary?.fieldReview ?? 0)
|
|
4144
4186
|
: cachedTask?.enrichmentSummary?.reviewRequired
|
|
4145
4187
|
?? cachedTask?.matchSummary?.reviewRequired;
|
|
4188
|
+
const qccFailedCount = qccRun?.summary?.failed ?? cachedTask?.enrichmentSummary?.failed ?? cachedTask?.matchSummary?.failed ?? 0;
|
|
4146
4189
|
const stat = (label, value, tone) => h('div', { className: 'dcAgentCard' },
|
|
4147
4190
|
h('span', null, label),
|
|
4148
4191
|
h('b', { className: tone ? `is-${tone}` : null }, displayStatValue(value))
|
|
@@ -4378,12 +4421,13 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
4378
4421
|
const availableArtifacts = (cachedTask?.artifacts || []).filter(artifact => artifact.kind !== 'review' || artifact.rowCount > 0);
|
|
4379
4422
|
const canCreateArtifacts = Boolean(exportRows()?.length) && ['rules_confirmed', 'diagnosed', 'export_ready', 'partial'].includes(cachedTask?.state);
|
|
4380
4423
|
pane = h('div', { className: 'dcAgentPane' },
|
|
4381
|
-
h('p', { className: 'dcAgentHint' }, '结果文件由 Host
|
|
4424
|
+
h('p', { className: 'dcAgentHint' }, '结果文件由 Host 保存;有失败、未匹配或待核验记录时展示异常清单。任务或插件重启后,可从任务历史继续下载;无需再次调用企查查。'),
|
|
4382
4425
|
h('div', { className: 'dcAgentGrid' },
|
|
4383
4426
|
stat('输入行数', dataset ? dataset.rowCount : workflowTask?.source?.rowCount ?? '—'),
|
|
4384
4427
|
stat('匹配补全', qccEnrichedCount, qccEnrichedCount > 0 ? 'good' : null),
|
|
4385
4428
|
stat('待核验', qccReviewCount, qccReviewCount > 0 ? 'warn' : null),
|
|
4386
4429
|
stat('任务状态', WORKFLOW_STATE_LABELS[cachedTask?.state] || cachedTask?.state || '进行中'),
|
|
4430
|
+
stat('失败', qccFailedCount, qccFailedCount > 0 ? 'bad' : null),
|
|
4387
4431
|
),
|
|
4388
4432
|
availableArtifacts.length ? h('div', { className: 'dcAgentArtifactList' },
|
|
4389
4433
|
availableArtifacts.filter(artifact => artifact.format === 'xlsx').map(artifact => h('a', {
|
|
@@ -4503,15 +4547,9 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
4503
4547
|
h('span', { className: 'dcAgentWbIcon', 'aria-hidden': 'true' }, h(DatabaseLogo, { size: 22 })),
|
|
4504
4548
|
h('div', null,
|
|
4505
4549
|
h('b', null, '数据清洗补全'),
|
|
4506
|
-
h('small', null, cachedTask ? `${WORKFLOW_STATE_LABELS[cachedTask.state] || cachedTask.state} · ${cachedTask.id.slice(0, 18)}` : '正在创建 Host taskId…'),
|
|
4507
4550
|
),
|
|
4508
4551
|
),
|
|
4509
4552
|
h('div', { className: 'dcAgentWbActions' },
|
|
4510
|
-
h('span', {
|
|
4511
|
-
className: 'dcAgentQccBadge',
|
|
4512
|
-
title: qccRun ? `任务 ${qccRun.runId}` : '仅在当前用户确认使用自己的企查查账号后调用',
|
|
4513
|
-
}, qccRun ? `QCC · ${qccRun.state}` : qccCapabilities ? (qccCapabilities.capabilities?.ready ? 'QCC · 工具已就绪' : 'QCC · 能力不完整') : 'QCC · 自动校验'),
|
|
4514
|
-
h('span', { className: 'dcAgentJobsPill', 'data-state': cachedTask?.state || 'idle', title: '当前清洗任务状态' }, cachedTask ? WORKFLOW_STATE_LABELS[cachedTask.state] || cachedTask.state : '尚未开始'),
|
|
4515
4553
|
h('button', {
|
|
4516
4554
|
className: 'dcAgentWbClose',
|
|
4517
4555
|
type: 'button',
|
|
@@ -4560,8 +4598,8 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
4560
4598
|
max: commandProgress.totalUnique, value: Math.min(commandProgress.totalUnique, Math.max(0, commandProgress.completedUnique || 0)),
|
|
4561
4599
|
'aria-label': '主体处理进度', style: { width: '100%', accentColor: cachedTask.state === 'completed' ? '#16845b' : cachedTask.state === 'failed' ? '#c62828' : cachedTask.state === 'partial' ? '#a66a00' : '#087dcc' },
|
|
4562
4600
|
}) : null,
|
|
4563
|
-
h('p', { style: { color: Number(qccReviewCount) > 0 ? '#a66a00' :
|
|
4564
|
-
Number.isFinite(qccEnrichedCount) ? `已处理并补全 ${qccEnrichedCount} 条 · 待核验 ${Number.isFinite(qccReviewCount) ? qccReviewCount : '统计中'} 条(按输入行统计;未披露字段保留空白)` : '结果统计中,处理结束后展示补全与待核验数量'),
|
|
4601
|
+
h('p', { style: { color: qccFailedCount > 0 ? '#c62828' : Number(qccReviewCount) > 0 ? '#a66a00' : qccEnrichedCount > 0 ? '#16845b' : 'inherit' } },
|
|
4602
|
+
Number.isFinite(qccEnrichedCount) ? `已处理并补全 ${qccEnrichedCount} 条 · 待核验 ${Number.isFinite(qccReviewCount) ? qccReviewCount : '统计中'} 条 · 失败 ${qccFailedCount} 条(按输入行统计;未披露字段保留空白)` : '结果统计中,处理结束后展示补全与待核验数量'),
|
|
4565
4603
|
) : null,
|
|
4566
4604
|
error ? h('div', { className: 'dcAgentError', role: 'alert' }, error) : null,
|
|
4567
4605
|
step !== 'history' ? h('details', { className: 'dcAgentSection' },
|
package/lib/qcc.js
CHANGED
|
@@ -1074,7 +1074,11 @@ export class QccHostBridge {
|
|
|
1074
1074
|
...(result.fieldIssues ? { qcc_field_notes: Object.entries(result.fieldIssues).filter(([, issue]) => issue.reviewRequired === false).map(([field, issue]) => field + ': ' + issue.message).join(';') } : {}),
|
|
1075
1075
|
};
|
|
1076
1076
|
}
|
|
1077
|
-
return {
|
|
1077
|
+
return {
|
|
1078
|
+
...row, qcc_match_status: result?.status ?? 'failed',
|
|
1079
|
+
// Only export normalized diagnostic identifiers, never raw upstream messages or credentials.
|
|
1080
|
+
...(result?.error ? { qcc_error: [result.error.code, result.error.toolName, result.error.upstreamCode].filter(Boolean).join(' · ') } : {}),
|
|
1081
|
+
};
|
|
1078
1082
|
});
|
|
1079
1083
|
|
|
1080
1084
|
const indexesFor = (name) => normalized.filter((item) => item.companyName === name).map((item) => item.index);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-data-cleaning-agent",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.23",
|
|
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",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"docs/RELEASE-0.8.1.md",
|
|
41
41
|
"docs/RELEASE-0.8.16.md",
|
|
42
42
|
"docs/RELEASE-0.8.17.md",
|
|
43
|
-
"docs/RELEASE-0.8.
|
|
43
|
+
"docs/RELEASE-0.8.22.md",
|
|
44
44
|
"docs/TEMPLATE-MAPPING-ACCEPTANCE.md",
|
|
45
45
|
"docs/UI-WORKFLOW-V2.md",
|
|
46
46
|
"docs/UI-WORKFLOW-V2-MIGRATION.md",
|
package/docs/RELEASE-0.8.21.md
DELETED