dsh-data-cleaning-agent 0.9.12 → 0.9.13
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 +6 -0
- package/README.en.md +2 -2
- package/README.md +3 -3
- package/docs/RELEASE-0.9.13.md +9 -0
- package/lib/client.js +91 -6
- package/package.json +2 -2
- package/docs/RELEASE-0.9.12.md +0 -9
package/CHANGELOG.md
CHANGED
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.
|
|
13
|
+
> Current source version / 当前源码版本: **0.9.13** (stable release)
|
|
14
14
|
|
|
15
|
-
0.9.
|
|
15
|
+
0.9.13 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.
|
|
12
|
+
dsh plugin --profile web add dsh-data-cleaning-agent@0.9.13
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
请先满足下文的 DSH、连接器及侧边栏依赖要求;安装后完整停止并重启对应 Profile。
|
|
@@ -27,9 +27,9 @@ dsh plugin --profile web add dsh-data-cleaning-agent@0.9.12
|
|
|
27
27
|
|
|
28
28
|
> 在 DeepSeek Harness 中清洗、补全、画像企业名单数据的智能体插件:本地 CSV/XLSX/JSON 引擎 + 可选企查查(Qichacha/QCC)MCP 企业数据补全,由企查查(Qichacha/QCC)团队发起并维护。
|
|
29
29
|
>
|
|
30
|
-
> 当前源码版本 / Current source version: **0.9.
|
|
30
|
+
> 当前源码版本 / Current source version: **0.9.13**(正式版本)
|
|
31
31
|
|
|
32
|
-
0.9.
|
|
32
|
+
0.9.13 统一简洁首页:移除副标题与占位,保留原生工作区、模式和输入框。菜单名称固定并防止重复创建;品牌标题仅在所属首页生效,任务记录与模型运行状态明确区分。保留 0.9.11 的真实 Host 阶段与会话切换修复。
|
|
33
33
|
|
|
34
34
|
0.9.10 补齐首页 settling → hero 阶段监听,避免首次挂载漏掉 Logo 与标题替换;兼容“探索未知之境”,未知结构不做全局标题改写。回滚版本为 0.9.9。
|
|
35
35
|
|
package/lib/client.js
CHANGED
|
@@ -2136,14 +2136,12 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
2136
2136
|
function watchHostedCommand(actions, sessionId, command) {
|
|
2137
2137
|
const generation = commandWatchGeneration;
|
|
2138
2138
|
const isActive = () => generation === commandWatchGeneration;
|
|
2139
|
-
let openedForExecution = false;
|
|
2140
|
-
const ownerVisible = () => typeof document === 'undefined' || [...document.querySelectorAll('.dcAgentExperience')].some(node => node.dataset.sessionId === sessionId);
|
|
2141
2139
|
void waitForQccCommand(command.commandId, 1800, async (status) => {
|
|
2142
2140
|
if (!status || status.state === 'prepared') return;
|
|
2143
2141
|
await refreshHostedTask(actions, sessionId, command.taskId, null, true).catch(() => {});
|
|
2144
|
-
if (
|
|
2145
|
-
|
|
2146
|
-
|
|
2142
|
+
if (isActive() && workflowTaskBySession.get(String(sessionId))?.id === command.taskId) {
|
|
2143
|
+
sessionWorkbenchController?.revealSubmitted(sessionId, command.commandId,
|
|
2144
|
+
workflowTaskBySession.get(String(sessionId))?.stage || 'match');
|
|
2147
2145
|
}
|
|
2148
2146
|
if (isCleaningSession(sessionId) && workflowTaskBySession.get(String(sessionId))?.id === command.taskId) actions.setCommandProgress?.({ taskId: command.taskId, ...status.progress });
|
|
2149
2147
|
}, isActive).then(async (completed) => {
|
|
@@ -2438,7 +2436,73 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
2438
2436
|
if (!sessionConversation || typeof sessionConversation.send !== 'function') {
|
|
2439
2437
|
throw new Error('当前 DSH 版本没有可用的 Session conversation.send 能力');
|
|
2440
2438
|
}
|
|
2441
|
-
await sessionConversation.send(prompt);
|
|
2439
|
+
const result = await sessionConversation.send(prompt);
|
|
2440
|
+
if (result !== false) sessionWorkbenchController?.revealSubmitted(sessionId, submittedCommandId(prompt));
|
|
2441
|
+
}
|
|
2442
|
+
|
|
2443
|
+
function submittedCommandId(prompt) {
|
|
2444
|
+
return String(prompt || '').match(/\bdc[qi]-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i)?.[0] || null;
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2447
|
+
/** Observe the public admission settlement; drafts and failed sends never reveal a Tab. */
|
|
2448
|
+
function installSubmittedWorkbenchBridge(ctx, controller) {
|
|
2449
|
+
const sessions = typeof ctx.get === 'function' ? ctx.get('sessions') : ctx.sessions;
|
|
2450
|
+
let stopSession = () => {};
|
|
2451
|
+
let current = null;
|
|
2452
|
+
let currentFace = null;
|
|
2453
|
+
const connect = () => {
|
|
2454
|
+
const sessionId = sessions?.list?.getSnapshot?.()?.current;
|
|
2455
|
+
const face = sessionId ? sessions?.binding?.(sessionId)?.session : null;
|
|
2456
|
+
if (sessionId === current && face === currentFace) return;
|
|
2457
|
+
stopSession(); stopSession = () => {}; current = sessionId; currentFace = face;
|
|
2458
|
+
if (!sessionId) return;
|
|
2459
|
+
if (typeof face?.beginSubmission === 'function') {
|
|
2460
|
+
const original = face.beginSubmission;
|
|
2461
|
+
const wrapped = function(input) {
|
|
2462
|
+
if (!isCleaningSession(sessionId)) return original.call(this, input);
|
|
2463
|
+
let observed = false;
|
|
2464
|
+
return original.call(this, { ...input, onRetire: settlement => {
|
|
2465
|
+
try { input.onRetire?.(settlement); }
|
|
2466
|
+
finally {
|
|
2467
|
+
if (settlement.reason === 'observed' && !observed) {
|
|
2468
|
+
observed = true;
|
|
2469
|
+
controller.revealSubmitted(sessionId, submittedCommandId(input.text));
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
} });
|
|
2473
|
+
};
|
|
2474
|
+
face.beginSubmission = wrapped;
|
|
2475
|
+
stopSession = () => { if (face.beginSubmission === wrapped) face.beginSubmission = original; };
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
// Older DSH versions publish committed nodes on the Session read face.
|
|
2479
|
+
if (!face?.subscribe || !face?.getSnapshot) return;
|
|
2480
|
+
let previous = face.getSnapshot();
|
|
2481
|
+
let baseline = previous.nodes?.length ?? 0;
|
|
2482
|
+
let highestSeq = Math.max(0, ...(previous.nodes || []).map(node => Number(node.seq) || 0));
|
|
2483
|
+
stopSession = face.subscribe(() => {
|
|
2484
|
+
const snapshot = face.getSnapshot();
|
|
2485
|
+
const nodes = snapshot.nodes || [];
|
|
2486
|
+
const appended = highestSeq ? nodes.filter(node => node.seq > highestSeq) : nodes.slice(baseline);
|
|
2487
|
+
highestSeq = Math.max(highestSeq, ...nodes.map(node => Number(node.seq) || 0));
|
|
2488
|
+
baseline = nodes.length;
|
|
2489
|
+
const restoring = (previous.openState && previous.openState !== 'open') || snapshot.loadingOlder;
|
|
2490
|
+
previous = snapshot;
|
|
2491
|
+
if (restoring) return;
|
|
2492
|
+
if (!isCleaningSession(sessionId)) return;
|
|
2493
|
+
for (const node of appended) {
|
|
2494
|
+
if (node.kind !== 'user' && node.role !== 'user' && node.message?.role !== 'user') continue;
|
|
2495
|
+
const content = node.message?.content ?? node.content ?? node.blocks ?? node.parts;
|
|
2496
|
+
const prompt = node.text || (typeof content === 'string' ? content
|
|
2497
|
+
: Array.isArray(content) ? content.map(part => typeof part === 'string' ? part : part.text || '').join('\n') : '');
|
|
2498
|
+
controller.revealSubmitted(sessionId, submittedCommandId(prompt));
|
|
2499
|
+
}
|
|
2500
|
+
});
|
|
2501
|
+
};
|
|
2502
|
+
connect();
|
|
2503
|
+
const stopList = sessions?.list?.subscribe?.(connect);
|
|
2504
|
+
connect();
|
|
2505
|
+
return () => { stopSession(); stopList?.(); };
|
|
2442
2506
|
}
|
|
2443
2507
|
|
|
2444
2508
|
function setQccAgentDraft(ctx, sessionId, prompt) {
|
|
@@ -4940,6 +5004,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
4940
5004
|
}
|
|
4941
5005
|
let disposed = false;
|
|
4942
5006
|
const instances = new Map();
|
|
5007
|
+
const revealedCommands = new Set();
|
|
4943
5008
|
const spec = createWorkbenchStore();
|
|
4944
5009
|
const instanceFor = sessionId => {
|
|
4945
5010
|
if (!sessionId) throw new Error('请先打开数据清洗会话。');
|
|
@@ -5054,6 +5119,21 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
5054
5119
|
sessions.open(task.originSessionId);
|
|
5055
5120
|
// Navigation only: no task binding, command preparation, or draft writes.
|
|
5056
5121
|
},
|
|
5122
|
+
revealSubmitted(sessionId, commandId, step) {
|
|
5123
|
+
if (disposed || !sessionId) return false;
|
|
5124
|
+
const key = commandId && `${sessionId}:${commandId}`;
|
|
5125
|
+
if (key && revealedCommands.has(key)) return false;
|
|
5126
|
+
// Consume the event even if its owner is no longer visible. Polling must
|
|
5127
|
+
// not pull open an old task when the user later returns to its Session.
|
|
5128
|
+
if (key) revealedCommands.add(key);
|
|
5129
|
+
const sessions = typeof ctx.get === 'function' ? ctx.get('sessions') : ctx.sessions;
|
|
5130
|
+
if (sessions?.list?.getSnapshot?.()?.current !== sessionId || !isCleaningSession(sessionId)) return false;
|
|
5131
|
+
try { return controller.open(sessionId, step); }
|
|
5132
|
+
catch (error) {
|
|
5133
|
+
instanceFor(sessionId).actions.setError(error.message || String(error));
|
|
5134
|
+
return false;
|
|
5135
|
+
}
|
|
5136
|
+
},
|
|
5057
5137
|
storeFor: instanceFor,
|
|
5058
5138
|
actionsFor: sessionId => instanceFor(sessionId).actions,
|
|
5059
5139
|
open(sessionId, step) {
|
|
@@ -5069,6 +5149,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
5069
5149
|
},
|
|
5070
5150
|
};
|
|
5071
5151
|
sessionWorkbenchController = controller;
|
|
5152
|
+
const stopSubmittedBridge = installSubmittedWorkbenchBridge(ctx, controller);
|
|
5072
5153
|
const listeners = {
|
|
5073
5154
|
[WORKBENCH_OPEN_EVENT]: event => {
|
|
5074
5155
|
const detail = event.detail || {};
|
|
@@ -5116,6 +5197,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
5116
5197
|
const shared = { controller, references: 1, release() {
|
|
5117
5198
|
if (--shared.references > 0) return;
|
|
5118
5199
|
disposed = true;
|
|
5200
|
+
stopSubmittedBridge();
|
|
5119
5201
|
commandWatchGeneration += 1;
|
|
5120
5202
|
for (const remove of bindings) remove();
|
|
5121
5203
|
host.removeEventListener?.('click', previewClick, true);
|
|
@@ -5124,6 +5206,7 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
5124
5206
|
disconnectFixture();
|
|
5125
5207
|
void providerFiber?.dispose();
|
|
5126
5208
|
instances.clear();
|
|
5209
|
+
revealedCommands.clear();
|
|
5127
5210
|
if (host[CONTROLLER_KEY] === shared) delete host[CONTROLLER_KEY];
|
|
5128
5211
|
if (sessionWorkbenchController === controller) sessionWorkbenchController = null;
|
|
5129
5212
|
} };
|
|
@@ -5218,6 +5301,8 @@ body:has(.dcAgentPromptBackdrop) { overflow: hidden; }
|
|
|
5218
5301
|
createWorkbenchStore,
|
|
5219
5302
|
WorkbenchContent,
|
|
5220
5303
|
installSessionWorkbench,
|
|
5304
|
+
sendQccAgentCommand,
|
|
5305
|
+
installSubmittedWorkbenchBridge,
|
|
5221
5306
|
DatabaseLogo,
|
|
5222
5307
|
visibleCatalogFields,
|
|
5223
5308
|
installCapabilityMount,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-data-cleaning-agent",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.13",
|
|
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,7 +21,7 @@
|
|
|
21
21
|
"marketing",
|
|
22
22
|
"docs/USER-GUIDE.md",
|
|
23
23
|
"docs/RELEASE-0.9.11.md",
|
|
24
|
-
"docs/RELEASE-0.9.
|
|
24
|
+
"docs/RELEASE-0.9.13.md",
|
|
25
25
|
"docs/UNIFIED-HOME-1.5.4-ADOPTION.md",
|
|
26
26
|
"docs/FIRST-CONTRIBUTION.md",
|
|
27
27
|
"docs/COMPATIBILITY.md",
|
package/docs/RELEASE-0.9.12.md
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
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 不动。
|