dsh-data-cleaning-agent 0.8.13 → 0.8.15
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 +11 -0
- package/README.en.md +9 -3
- package/README.md +26 -3
- package/docs/G5-HOST-BRIDGE.md +3 -2
- package/lib/client.js +13 -61
- package/lib/qcc-command.js +7 -1
- package/lib/qcc.js +16 -1
- package/lib/web.js +1 -1
- package/marketing/metadata.json +23 -6
- package/package.json +18 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.8.15] - 2026-09-08
|
|
8
|
+
|
|
9
|
+
- 改善搜索元数据、安装说明、能力边界与四产品互链;无运行时或依赖变更。
|
|
10
|
+
|
|
11
|
+
## [0.8.14] - 2026-09-07
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- 质量体检后可直接生成可编辑任务说明,移除手动连接检测、手动调用估算和草稿阶段额度勾选。
|
|
15
|
+
- Host 统一检查所选工具、去重主体及调用上界;中文草稿显示执行范围与账号提示。生成不查询,用户发送后才通过 Agent-owned 工具执行。
|
|
16
|
+
- 候选确认与失败重试保留显式继续查询确认;执行时重新校验工具与范围,保留幂等及原列补空保护。
|
|
17
|
+
|
|
7
18
|
## [0.8.13] - 2026-09-07
|
|
8
19
|
|
|
9
20
|
### Added
|
package/README.en.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# dsh-data-cleaning-agent
|
|
2
2
|
|
|
3
|
+
Data cleaning and data enrichment for CSV/XLSX/JSON enterprise lists in DeepSeek Harness, including spreadsheet cleaning, deduplication, profiling, optional Qichacha MCP and exports.
|
|
4
|
+
|
|
5
|
+
Install a pinned release using the command in the [Chinese quick start](README.md), review the preview or evidence before confirming, and keep the previous version and task-directory backup for rollback. Qichacha calls use the customer's authorized account.
|
|
6
|
+
|
|
7
|
+
Related agents: [数据清洗补全](https://github.com/duhu2000/dsh-data-cleaning-agent) · [AI填表](https://github.com/duhu2000/dsh-form-fill-agent) · [访前尽调](https://github.com/duhu2000/dsh-pre-duediligence) · [招投标](https://github.com/duhu2000/dsh-tender-workbench)
|
|
8
|
+
|
|
3
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.
|
|
4
10
|
>
|
|
5
|
-
> Current source version / 当前源码版本: **0.8.
|
|
11
|
+
> Current source version / 当前源码版本: **0.8.15** (stable release)
|
|
6
12
|
|
|
7
13
|
This release fixes misleading import errors after a successful upload. Files are parsed automatically, with persistent source, filename, and row-count status; text parsing handles only newly pasted content. The same file can be selected again, failed parsing preserves existing data, and pending pasted content must be parsed or cleared before continuing. Automatic mapping for 128 fields, blank-cell enrichment in original columns, QCC-blue menus, the resizable workbench, and native DSH sending remain unchanged. Existing download artifacts are not rewritten.
|
|
8
14
|
|
|
@@ -110,8 +116,8 @@ Besides local deterministic completion, the plugin supports Qichacha MCP enterpr
|
|
|
110
116
|
conversation. The Agent calls `data_cleaning_qcc_run` exactly once; the bridge then dispatches
|
|
111
117
|
dynamic QCC tools as nested executions using the parent execution token and Session. This path
|
|
112
118
|
supports batch enrichment, idempotency, candidate-resolution resume, manual retry of retryable
|
|
113
|
-
failures, and metadata-only auditing.
|
|
114
|
-
|
|
119
|
+
failures, and metadata-only auditing. Since 0.8.14, initial draft staging automatically preflights tools and scope without a billing checkbox; only sending the readable draft starts queries.
|
|
120
|
+
Candidate resolution, retry and legacy direct-execution APIs still require `confirmPaidCalls:true` for the user's own QCC account quota.
|
|
115
121
|
Ambiguous candidates are never auto-selected. A loopback-only, fail-closed E2E runner is ready. On 2026-09-01 an isolated rc.2
|
|
116
122
|
Host passed real OAuth, restart recovery, and 400 QCC calls across 20 public companies. Natural-expiry
|
|
117
123
|
token refresh, dynamic-tool recovery, a post-refresh real call, and 401/429/quota fault injection also passed.
|
package/README.md
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
# dsh-data-cleaning-agent
|
|
2
2
|
|
|
3
|
+
本次补丁仅更新搜索发现与安装转化文档,运行时能力保持上一版本;发布记录见 [发布说明](docs/RELEASE-0.8.15.md)。
|
|
4
|
+
|
|
5
|
+
## 安装与三分钟上手
|
|
6
|
+
|
|
7
|
+
数据清洗补全智能体:面向 Excel/CSV/JSON 企业名单,提供数据清洗、表格清洗、清洗补全、去重、企业数据补全与字段补全,支持企查查 MCP 和结果导出。
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
dsh plugin --profile web add dsh-data-cleaning-agent@0.8.15
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
请先满足下文的 DSH、连接器及侧边栏依赖要求;安装后完整停止并重启对应 Profile。
|
|
14
|
+
|
|
15
|
+
上传一份合成 CSV(如表头“姓名,手机号,金额”,两行重复的“演示用户,13800000000,100”),选择去重并检查结果,再导出新文件。企业字段补全另需已授权的企查查 MCP;先用本地清洗体验流程。
|
|
16
|
+
|
|
17
|
+
**流程样例(示意,非真实调用结果):** 输入两条相同合成记录 → 选择去重规则 → 预览一条保留记录 → 导出结果。
|
|
18
|
+
|
|
19
|
+
**能力边界:** 本地清洗与企业数据补全是不同步骤;外部事实来自用户授权的数据源,无法确定的主体或字段交给人工复核,不编造企业事实。
|
|
20
|
+
|
|
21
|
+
**升级与回滚:** 升级前停止 Profile 并备份任务目录,记录当前精确版本;使用上面的固定版本命令升级,再完整重启。回滚时将版本号替换为升级前记录的版本,并使用升级前任务目录副本;不以旧版直接读取已迁移任务目录。
|
|
22
|
+
|
|
23
|
+
相关智能体:[数据清洗补全](https://github.com/duhu2000/dsh-data-cleaning-agent) · [AI填表](https://github.com/duhu2000/dsh-form-fill-agent) · [访前尽调](https://github.com/duhu2000/dsh-pre-duediligence) · [招投标](https://github.com/duhu2000/dsh-tender-workbench)
|
|
24
|
+
|
|
25
|
+
|
|
3
26
|
> 在 DeepSeek Harness 中清洗、补全、画像企业名单数据的智能体插件:本地 CSV/XLSX/JSON 引擎 + 可选企查查(Qichacha/QCC)MCP 企业数据补全,由企查查(Qichacha/QCC)团队发起并维护。
|
|
4
27
|
>
|
|
5
|
-
> 当前源码版本 / Current source version: **0.8.
|
|
28
|
+
> 当前源码版本 / Current source version: **0.8.15**(正式版本)
|
|
6
29
|
|
|
7
30
|
本版修复文件上传成功后的导入状态误报:文件选择后自动解析,当前来源、文件名和行数持续显示;文本解析仅处理新粘贴内容。支持重新选择同一文件,解析失败保留现有数据,新粘贴内容解析或清空后再进入下一步。保留 128 字段智能映射、原列补空、企查查蓝菜单、可调宽工作台及 DSH 原生发送机制。历史下载文件不自动改写。
|
|
8
31
|
|
|
@@ -102,8 +125,8 @@ bash <(curl -fsSL https://raw.githubusercontent.com/duhu2000/dsh-data-cleaning-a
|
|
|
102
125
|
Host,并只把不含企业名单的 commandId 类型化意图发送到原生会话;Agent 随后准确调用一次
|
|
103
126
|
`data_cleaning_qcc_run`,Bridge 使用该父执行的 token/Session 以 nested execution 调度动态 QCC 工具。
|
|
104
127
|
该路径实现批量补全、请求幂等、多候选人工确认续跑、retryable 失败人工重试与安全审计。
|
|
105
|
-
|
|
106
|
-
|
|
128
|
+
0.8.14 起初始草稿无需额度勾选:Host 自动检查工具与调用范围,用户阅读并发送说明后才查询。
|
|
129
|
+
候选确认、失败重试及旧版直接执行接口仍要求 `confirmPaidCalls:true`;使用用户自有账号额度,多候选绝不自动选择。
|
|
107
130
|
默认关闭的本机 E2E Runner 已就绪;2026-09-01 已在隔离 rc.2 Host 完成真实 OAuth、跨重启恢复和
|
|
108
131
|
20 家公开企业的 400 次 QCC 调用;自然过期 token 的真实刷新、动态工具恢复及 1 行续期后调用也已通过。
|
|
109
132
|
401 / 429 / 配额耗尽使用 Web→Bridge→ToolRuntime 故障注入验证,不额外消耗真实付费批次。
|
package/docs/G5-HOST-BRIDGE.md
CHANGED
|
@@ -53,8 +53,9 @@
|
|
|
53
53
|
|
|
54
54
|
### Agent-owned 命令(正式工作台路径)
|
|
55
55
|
|
|
56
|
-
- `POST /data-cleaning/api/g5/commands
|
|
57
|
-
|
|
56
|
+
- `POST /data-cleaning/api/g5/commands`:0.8.14 起 enrich 暂存不要求额度勾选,Host 自动检查所选工具、行数和调用上界;
|
|
57
|
+
resolve/retry 暂存仍要求 `confirmPaidCalls:true`。返回 commandId、Host estimate 与不含企业名单的可编辑提示,本步骤 `paidCalls:false`。
|
|
58
|
+
生成说明不代表已执行,用户发送可见说明后才由 Agent-owned 工具执行。执行阶段重新检查工具和上限,草稿不伪造“已确认额度”状态。
|
|
58
59
|
- `data_cleaning_qcc_run({commandId})`:只能在 Agent tool execution 内运行,缺少父执行 token/Session
|
|
59
60
|
时返回 `QCC_AGENT_EXECUTION_REQUIRED`。
|
|
60
61
|
- `GET /data-cleaning/api/g5/commands/<commandId>`:同源读取 prepared/running/completed/failed 和完成后的
|
package/lib/client.js
CHANGED
|
@@ -3245,7 +3245,6 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3245
3245
|
const nameField = useStore((state) => state.nameField);
|
|
3246
3246
|
const selectedDomains = useStore((state) => state.selectedDomains);
|
|
3247
3247
|
const qccCapabilities = useStore((state) => state.qccCapabilities);
|
|
3248
|
-
const qccEstimate = useStore((state) => state.qccEstimate);
|
|
3249
3248
|
const qccRun = useStore((state) => state.qccRun);
|
|
3250
3249
|
const paidConfirmed = useStore((state) => state.paidConfirmed);
|
|
3251
3250
|
const jobs = useStore((state) => state.jobs);
|
|
@@ -3546,39 +3545,6 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3546
3545
|
}
|
|
3547
3546
|
};
|
|
3548
3547
|
|
|
3549
|
-
const loadQccCapabilities = async () => {
|
|
3550
|
-
if (busy) return;
|
|
3551
|
-
actions.setBusy(true);
|
|
3552
|
-
actions.setError(null);
|
|
3553
|
-
try {
|
|
3554
|
-
const r = await api('/data-cleaning/api/g5/capabilities');
|
|
3555
|
-
if (r && r.ok !== false) actions.setQccCapabilities(r);
|
|
3556
|
-
else actions.setError((r && (r.message || r.error)) || '企查查能力检测失败');
|
|
3557
|
-
} catch (err) {
|
|
3558
|
-
actions.setError(err instanceof Error ? err.message : String(err));
|
|
3559
|
-
} finally {
|
|
3560
|
-
actions.setBusy(false);
|
|
3561
|
-
}
|
|
3562
|
-
};
|
|
3563
|
-
|
|
3564
|
-
const estimateQcc = async () => {
|
|
3565
|
-
const uniqueCompanies = new Set(runtime.rows.map((row) => String(row?.[nameField] ?? '').trim()).filter(Boolean)).size;
|
|
3566
|
-
const selected = fieldSelection.length ? fieldSelection : DEFAULT_ENRICHMENT_KEYS;
|
|
3567
|
-
const selectedGroups = uiFieldGroups.filter(([, , fields]) => fields.some(([id]) => selected.includes(id)));
|
|
3568
|
-
const sourceTools = [...new Set(selectedGroups.map(([, , , sourceTool]) => sourceTool).filter(Boolean))];
|
|
3569
|
-
const callsPerCompany = 1 + sourceTools.length;
|
|
3570
|
-
const estimatedCalls = uniqueCompanies * callsPerCompany;
|
|
3571
|
-
actions.setQccEstimate({
|
|
3572
|
-
uniqueCompanies,
|
|
3573
|
-
tools: ['主体查询', ...selectedGroups.map(([, label]) => label)],
|
|
3574
|
-
sourceTools,
|
|
3575
|
-
estimatedCalls,
|
|
3576
|
-
maxCalls: 300,
|
|
3577
|
-
withinLimit: runtime.rows.length <= 100 && estimatedCalls <= 300,
|
|
3578
|
-
estimateType: 'upper-bound',
|
|
3579
|
-
});
|
|
3580
|
-
};
|
|
3581
|
-
|
|
3582
3548
|
const applyQccRun = async (run) => {
|
|
3583
3549
|
actions.setQccRun(run);
|
|
3584
3550
|
runtime.rows = Array.isArray(run.rows) ? run.rows : runtime.rows;
|
|
@@ -3631,7 +3597,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3631
3597
|
}
|
|
3632
3598
|
const prepared = await api('/data-cleaning/api/g5/commands', {
|
|
3633
3599
|
...payload,
|
|
3634
|
-
confirmPaidCalls: true,
|
|
3600
|
+
...(payload.kind === 'enrich' ? {} : { confirmPaidCalls: true }),
|
|
3635
3601
|
});
|
|
3636
3602
|
const command = prepared?.command;
|
|
3637
3603
|
if (!command?.commandId || !command?.prompt) throw new Error('Host 未返回有效的企查查任务命令');
|
|
@@ -3652,10 +3618,10 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3652
3618
|
}
|
|
3653
3619
|
const prepared = await api('/data-cleaning/api/g5/commands', {
|
|
3654
3620
|
...payload,
|
|
3655
|
-
confirmPaidCalls: true,
|
|
3656
3621
|
});
|
|
3657
3622
|
const command = prepared?.command;
|
|
3658
3623
|
if (!command?.commandId || !command?.prompt) throw new Error('Host 未返回有效的企查查任务命令');
|
|
3624
|
+
actions.setQccCapabilities({ capabilities: { ready: true } });
|
|
3659
3625
|
setSessionDraft(activeSessionId, command.prompt);
|
|
3660
3626
|
actions.close();
|
|
3661
3627
|
|
|
@@ -3680,7 +3646,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
3680
3646
|
};
|
|
3681
3647
|
|
|
3682
3648
|
const runQcc = async () => {
|
|
3683
|
-
if (busy || !
|
|
3649
|
+
if (busy || !cachedTask?.id || !hasData) return;
|
|
3684
3650
|
actions.setBusy(true);
|
|
3685
3651
|
actions.setError(null);
|
|
3686
3652
|
try {
|
|
@@ -4083,33 +4049,19 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
4083
4049
|
h('p', { className: 'dcAgentHint' }, '统一社会信用代码等强标识优先;名称匹配不明确时进入人工核验队列。'),
|
|
4084
4050
|
),
|
|
4085
4051
|
h('section', { className: 'dcAgentSection' },
|
|
4086
|
-
h('h3', null, '
|
|
4052
|
+
h('h3', null, '准备任务说明'),
|
|
4053
|
+
h('p', { className: 'dcAgentHint' }, `已导入 ${dataset?.rowCount ?? runtime.rows.length} 条记录,已选择 ${fieldSelection.length} 个补全字段。Host 自动检查所需工具并计算去重主体与调用上界。`),
|
|
4054
|
+
h('p', { className: 'dcAgentHint' }, '回填后可修改;点击发送才开始查询,使用你已连接的企查查 MCP 账号及额度。'),
|
|
4087
4055
|
h('div', { className: 'dcAgentRow' },
|
|
4088
|
-
h('button', { type: 'button', className: 'dcAgentButton', disabled: busy, onClick:
|
|
4089
|
-
qccCapabilities ? h('span', { className: 'dcAgentHint' }, qccCapabilities.capabilities?.ready ? '主体查询与工商信息工具已就绪' : '连接未就绪或基础工具不完整') : null,
|
|
4056
|
+
h('button', { type: 'button', className: 'dcAgentButton is-primary', disabled: busy || !hasData || !cachedTask?.id, onClick: runQcc }, busy ? '检查并生成中…' : '生成可编辑任务说明'),
|
|
4090
4057
|
),
|
|
4091
|
-
h('div', { className: 'dcAgentRow' },
|
|
4092
|
-
h('button', { type: 'button', className: 'dcAgentButton', disabled: busy || !runtime.rows.length, onClick: estimateQcc }, '估算调用量'),
|
|
4093
|
-
),
|
|
4094
|
-
qccEstimate ? h('div', null,
|
|
4095
|
-
h('div', { className: 'dcAgentGrid' },
|
|
4096
|
-
stat('唯一企业', qccEstimate.uniqueCompanies),
|
|
4097
|
-
stat('所选工具', qccEstimate.tools.length),
|
|
4098
|
-
stat('调用上界', qccEstimate.estimatedCalls, qccEstimate.withinLimit ? 'good' : 'bad'),
|
|
4099
|
-
stat('调用上限', qccEstimate.maxCalls),
|
|
4100
|
-
),
|
|
4101
|
-
h('label', { className: 'dcAgentCheck' },
|
|
4102
|
-
h('input', { type: 'checkbox', checked: paidConfirmed, 'aria-label': '确认使用当前用户的企查查账号额度', onChange: (event) => actions.setPaidConfirmed(event.target.checked) }),
|
|
4103
|
-
'我已核对企业数量和调用上界,并确认使用自己连接的企查查 MCP 账号;额度或费用由该账号自行承担',
|
|
4104
|
-
),
|
|
4105
|
-
h('p', { className: 'dcAgentHint' }, '下一步只会把中文任务说明回填到中央对话框。你可先阅读、补充备注,点击发送后才开始企查查调用。'),
|
|
4106
|
-
h('div', { className: 'dcAgentRow' },
|
|
4107
|
-
h('button', { type: 'button', className: 'dcAgentButton is-primary', disabled: busy || !paidConfirmed || !qccEstimate.withinLimit, onClick: runQcc }, busy ? '生成中…' : '生成可编辑任务说明'),
|
|
4108
|
-
),
|
|
4109
|
-
) : null,
|
|
4110
4058
|
),
|
|
4111
4059
|
qccRun ? h('section', { className: 'dcAgentSection' },
|
|
4112
4060
|
h('h3', null, `任务 ${qccRun.runId} · ${qccRun.state}`),
|
|
4061
|
+
((qccRun.reviewQueue || []).length || (qccRun.errors || []).some((item) => item.error?.retryable)) ? h('label', { className: 'dcAgentCheck' },
|
|
4062
|
+
h('input', { type: 'checkbox', checked: paidConfirmed, 'aria-label': '确认候选或重试的企查查调用', onChange: (event) => actions.setPaidConfirmed(event.target.checked) }),
|
|
4063
|
+
'确认主体或重试会继续查询,使用当前连接的企查查账号;额度或费用由该账号自行承担。',
|
|
4064
|
+
) : null,
|
|
4113
4065
|
h('div', { className: 'dcAgentGrid' },
|
|
4114
4066
|
stat('已补全', qccRun.summary?.enriched ?? 0, 'good'),
|
|
4115
4067
|
stat('待核验', (qccRun.summary?.ambiguous ?? 0) + (qccRun.summary?.fieldReview ?? 0), (qccRun.summary?.ambiguous || qccRun.summary?.fieldReview) > 0 ? 'warn' : null),
|
|
@@ -4242,7 +4194,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
4242
4194
|
title: runtime.source?.type === 'image' ? '图片识别原始名单(尚未匹配)' : '导入原始清单',
|
|
4243
4195
|
onError: actions.setError,
|
|
4244
4196
|
}) : null,
|
|
4245
|
-
hasData ? h('p', { className: 'dcAgentHint' }, '
|
|
4197
|
+
hasData ? h('p', { className: 'dcAgentHint' }, '请核对完整名单。识别清单不代表已完成企查查匹配。核对后进入「规则与体检」,确认规则生成质量体检;再进入「主体匹配」直接生成可编辑任务说明。Host 自动检查工具和调用范围,回填中央对话框后点击发送才开始查询。') : null,
|
|
4246
4198
|
h('div', { className: 'dcAgentRow' },
|
|
4247
4199
|
h('button', { type: 'button', className: 'dcAgentButton is-primary', disabled: busy || !intake.pendingText, 'aria-label': '解析数据', onClick: handleParse }, busy ? '解析中…' : '解析粘贴内容'),
|
|
4248
4200
|
intake.pendingText && hasData ? h('p', { className: 'dcAgentHint', role: 'status' }, '有尚未解析的新粘贴内容,请先解析或清空后再继续。') : null,
|
|
@@ -4291,7 +4243,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
4291
4243
|
h('span', {
|
|
4292
4244
|
className: 'dcAgentQccBadge',
|
|
4293
4245
|
title: qccRun ? `任务 ${qccRun.runId}` : '仅在当前用户确认使用自己的企查查账号后调用',
|
|
4294
|
-
}, qccRun ? `QCC · ${qccRun.state}` : qccCapabilities ? (qccCapabilities.capabilities?.ready ? 'QCC ·
|
|
4246
|
+
}, qccRun ? `QCC · ${qccRun.state}` : qccCapabilities ? (qccCapabilities.capabilities?.ready ? 'QCC · 工具已就绪' : 'QCC · 能力不完整') : 'QCC · 自动校验'),
|
|
4295
4247
|
h('span', { className: 'dcAgentJobsPill', 'data-state': jobsPill(jobs).state, title: '后台任务状态' }, jobsPill(jobs).label),
|
|
4296
4248
|
h('button', {
|
|
4297
4249
|
className: 'dcAgentWbClose',
|
package/lib/qcc-command.js
CHANGED
|
@@ -91,7 +91,8 @@ export function serializeQccCommandPrompt(command) {
|
|
|
91
91
|
`任务编号:${command.taskId}。`,
|
|
92
92
|
`处理数量:${rowCount} 条企业记录。`,
|
|
93
93
|
...(fields.length ? [`需要补全:${fields.join('、')}。`] : []),
|
|
94
|
-
|
|
94
|
+
...(command.estimate ? [`Host 调用估算:${command.estimate.uniqueCompanies} 家去重主体,最多 ${command.estimate.estimatedCalls} 次;本次调用上限 ${command.estimate.maxCalls} 次。`] : []),
|
|
95
|
+
'执行边界:名单与字段范围已安全暂存在本机 Host。生成说明不会查询;发送本说明即确认按上述范围使用自己连接的企查查 MCP 账号及额度,额度或费用由该账号自行承担。',
|
|
95
96
|
'',
|
|
96
97
|
'你可以在发送前补充任务备注。如需修改名单、匹配规则或补全字段,请先返回工作台调整后重新生成。',
|
|
97
98
|
`安全任务凭证:${command.commandId}`,
|
|
@@ -128,6 +129,9 @@ export class QccCommandStore {
|
|
|
128
129
|
prepare(input) {
|
|
129
130
|
this.cleanup(true);
|
|
130
131
|
const normalized = normalizedInput(input);
|
|
132
|
+
const estimate = normalized.kind === 'enrich'
|
|
133
|
+
? this.bridge.previewEnrichment(normalized.rows, normalized)
|
|
134
|
+
: null;
|
|
131
135
|
const commandId = `dcq-${randomUUID()}`;
|
|
132
136
|
const at = new Date(this.clock()).toISOString();
|
|
133
137
|
const record = {
|
|
@@ -139,6 +143,7 @@ export class QccCommandStore {
|
|
|
139
143
|
updatedAt: at,
|
|
140
144
|
touchedAtMs: this.clock(),
|
|
141
145
|
input: normalized,
|
|
146
|
+
estimate,
|
|
142
147
|
runId: null,
|
|
143
148
|
error: null,
|
|
144
149
|
promise: null,
|
|
@@ -165,6 +170,7 @@ export class QccCommandStore {
|
|
|
165
170
|
updatedAt: record.updatedAt,
|
|
166
171
|
runId: record.runId,
|
|
167
172
|
error: record.error,
|
|
173
|
+
estimate: record.estimate,
|
|
168
174
|
expiresInMs: this.ttlMs,
|
|
169
175
|
});
|
|
170
176
|
}
|
package/lib/qcc.js
CHANGED
|
@@ -970,7 +970,7 @@ export class QccHostBridge {
|
|
|
970
970
|
return this.enrichMatchedCompany({ companyName, creditNo }, options);
|
|
971
971
|
}
|
|
972
972
|
|
|
973
|
-
|
|
973
|
+
planEnrichment(rows, options = {}) {
|
|
974
974
|
if (!Array.isArray(rows)) throw new QccBridgeError('QCC_INVALID_ROWS', 'rows must be an array');
|
|
975
975
|
const maxRows = Math.max(1, Math.trunc(options.maxRows ?? DEFAULT_MAX_ROWS));
|
|
976
976
|
if (rows.length > maxRows) {
|
|
@@ -1000,6 +1000,21 @@ export class QccHostBridge {
|
|
|
1000
1000
|
.map((sourceTool) => SOURCE_TOOL_CONFIG[sourceTool]?.name)
|
|
1001
1001
|
.filter(Boolean),
|
|
1002
1002
|
];
|
|
1003
|
+
return { normalized, names, estimate, maxRows, maxCalls, requiredTools };
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
previewEnrichment(rows, options = {}) {
|
|
1007
|
+
const plan = this.planEnrichment(rows, options);
|
|
1008
|
+
if (!plan.names.length) throw new QccBridgeError('QCC_INVALID_ROWS', '请先确认企业名称或统一社会信用代码的匹配映射。');
|
|
1009
|
+
const missingTools = plan.requiredTools.filter((name) => !this.has(name));
|
|
1010
|
+
if (missingTools.length) throw new QccBridgeError('QCC_NOT_CONNECTED', '企查查连接或所选字段工具未就绪,请在 MCP 连接器完成配置后重新生成任务说明。', {
|
|
1011
|
+
connectRequired: true, retryable: true, details: { missingTools },
|
|
1012
|
+
});
|
|
1013
|
+
return { ...plan.estimate, rowCount: rows.length, maxRows: plan.maxRows, maxCalls: plan.maxCalls, withinLimit: true };
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
async enrichRows(rows, options = {}) {
|
|
1017
|
+
const { normalized, names, estimate, requiredTools } = this.planEnrichment(rows, options);
|
|
1003
1018
|
try {
|
|
1004
1019
|
await Promise.all(requiredTools.map((name) => this.waitForTool(name, {
|
|
1005
1020
|
signal: options.signal,
|
package/lib/web.js
CHANGED
|
@@ -642,7 +642,7 @@ export function mountWebRoutes(wctx, { logger, report, TOOL_NAME, SKILL_NAME })
|
|
|
642
642
|
);
|
|
643
643
|
}
|
|
644
644
|
const payload = JSON.parse((await readBody(req)).toString('utf8'));
|
|
645
|
-
requirePaidConfirmation(payload);
|
|
645
|
+
if (payload.kind && payload.kind !== 'enrich') requirePaidConfirmation(payload);
|
|
646
646
|
return writeJson(res, 201, {
|
|
647
647
|
ok: true,
|
|
648
648
|
marker: 'g5-agent-command',
|
package/marketing/metadata.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"repository": "duhu2000/dsh-data-cleaning-agent",
|
|
4
4
|
"packageName": "dsh-data-cleaning-agent",
|
|
5
5
|
"npm": {
|
|
6
|
-
"description": "
|
|
6
|
+
"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.",
|
|
7
7
|
"requiredKeywords": [
|
|
8
8
|
"deepseek-harness",
|
|
9
9
|
"deepseek",
|
|
@@ -30,11 +30,26 @@
|
|
|
30
30
|
"ai-tools",
|
|
31
31
|
"llm-tools",
|
|
32
32
|
"ai-agents",
|
|
33
|
-
"agent-skills"
|
|
33
|
+
"agent-skills",
|
|
34
|
+
"data-enrichment",
|
|
35
|
+
"spreadsheet-cleaning",
|
|
36
|
+
"数据清洗补全",
|
|
37
|
+
"数据清洗",
|
|
38
|
+
"清洗补全",
|
|
39
|
+
"表格清洗",
|
|
40
|
+
"企业数据补全",
|
|
41
|
+
"字段补全",
|
|
42
|
+
"data cleaning",
|
|
43
|
+
"data enrichment",
|
|
44
|
+
"spreadsheet cleaning",
|
|
45
|
+
"数据 清洗 补全",
|
|
46
|
+
"数据清洗、补全",
|
|
47
|
+
"企查查MCP",
|
|
48
|
+
"企查查 MCP"
|
|
34
49
|
]
|
|
35
50
|
},
|
|
36
51
|
"github": {
|
|
37
|
-
"description": "
|
|
52
|
+
"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.",
|
|
38
53
|
"topics": [
|
|
39
54
|
"deepseek-harness",
|
|
40
55
|
"deepseek",
|
|
@@ -61,7 +76,9 @@
|
|
|
61
76
|
"ai-tools",
|
|
62
77
|
"llm-tools",
|
|
63
78
|
"ai-agents",
|
|
64
|
-
"agent-skills"
|
|
79
|
+
"agent-skills",
|
|
80
|
+
"data-enrichment",
|
|
81
|
+
"spreadsheet-cleaning"
|
|
65
82
|
]
|
|
66
83
|
},
|
|
67
84
|
"readme": {
|
|
@@ -71,8 +88,8 @@
|
|
|
71
88
|
"ctaEn": "If the plugin helps you clean company lists faster, consider [starring the repository](https://github.com/duhu2000/dsh-data-cleaning-agent/stargazers), [filing an issue](https://github.com/duhu2000/dsh-data-cleaning-agent/issues), or [contributing a fix](CONTRIBUTING.md)."
|
|
72
89
|
},
|
|
73
90
|
"externalListing": {
|
|
74
|
-
"en": "Data cleaning
|
|
75
|
-
"zh": "
|
|
91
|
+
"en": "Data cleaning and data enrichment for CSV/XLSX/JSON enterprise lists in DeepSeek Harness, including spreadsheet cleaning, deduplication, profiling, optional Qichacha MCP and exports.",
|
|
92
|
+
"zh": "数据清洗补全智能体:面向 Excel/CSV/JSON 企业名单,提供数据清洗、表格清洗、清洗补全、去重、企业数据补全与字段补全,支持企查查 MCP 和结果导出。"
|
|
76
93
|
},
|
|
77
94
|
"links": {
|
|
78
95
|
"repository": "https://github.com/duhu2000/dsh-data-cleaning-agent",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-data-cleaning-agent",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.8.15",
|
|
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",
|
|
7
7
|
"exports": {
|
|
@@ -84,7 +84,22 @@
|
|
|
84
84
|
"ai-tools",
|
|
85
85
|
"llm-tools",
|
|
86
86
|
"ai-agents",
|
|
87
|
-
"agent-skills"
|
|
87
|
+
"agent-skills",
|
|
88
|
+
"数据清洗补全",
|
|
89
|
+
"数据清洗",
|
|
90
|
+
"清洗补全",
|
|
91
|
+
"表格清洗",
|
|
92
|
+
"企业数据补全",
|
|
93
|
+
"字段补全",
|
|
94
|
+
"data cleaning",
|
|
95
|
+
"data enrichment",
|
|
96
|
+
"spreadsheet cleaning",
|
|
97
|
+
"数据 清洗 补全",
|
|
98
|
+
"数据清洗、补全",
|
|
99
|
+
"企查查MCP",
|
|
100
|
+
"企查查 MCP",
|
|
101
|
+
"data-enrichment",
|
|
102
|
+
"spreadsheet-cleaning"
|
|
88
103
|
],
|
|
89
104
|
"license": "MIT",
|
|
90
105
|
"repository": {
|