dsh-data-cleaning-agent 0.7.0 → 0.8.1

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/lib/web.js CHANGED
@@ -16,6 +16,13 @@ import { PHASE3_BATCH_LIMITS, Phase3BatchService, Phase3RunStore } from './qcc-p
16
16
  import { publicWorkflowContract } from './workflow-contract.js';
17
17
  import { DataCleaningWorkflowStore, WorkflowError } from './workflow.js';
18
18
  import { ArtifactError, WorkflowArtifactStore } from './artifacts.js';
19
+ import {
20
+ ImageIntakeError,
21
+ ImageIntakeStore,
22
+ registerImageIntakeTool,
23
+ serializeImageExtractionPrompt,
24
+ TOOL_IMAGE_EXTRACT,
25
+ } from './image-intake.js';
19
26
 
20
27
  const MAX_BODY = 16 * 1024 * 1024; // 16 MiB 上传上限(MVP)
21
28
 
@@ -119,6 +126,17 @@ function writeWorkflowError(res, error) {
119
126
  });
120
127
  }
121
128
 
129
+ function writeImageError(res, error) {
130
+ if (error instanceof ImageIntakeError) {
131
+ return writeJson(res, error.status, { ok: false, code: error.code, message: error.message });
132
+ }
133
+ return writeJson(res, 500, {
134
+ ok: false,
135
+ code: 'DC_IMAGE_INTERNAL',
136
+ message: '图片名单接入请求失败。',
137
+ });
138
+ }
139
+
122
140
  /** 从 JSON 协议解析上传:{ filename, content }。content 为字符串;xlsx 时为 base64。 */
123
141
  async function parseUpload(body) {
124
142
  let payload;
@@ -285,13 +303,17 @@ export function mountWebRoutes(wctx, { logger, report, TOOL_NAME, SKILL_NAME })
285
303
  const skills = wctx.skills;
286
304
  const disposers = [];
287
305
  const qccBridge = new QccHostBridge({ tools, logger });
306
+ const imageIntake = new ImageIntakeStore({ tools });
288
307
  const g5Runs = new G5RunStore();
289
308
  const qccCommands = new QccCommandStore({ bridge: qccBridge, runs: g5Runs });
290
309
  if (typeof tools?.register === 'function') {
291
310
  disposers.push(registerQccCommandTool(tools, qccCommands));
311
+ disposers.push(registerImageIntakeTool(tools, imageIntake));
292
312
  report.qccCommandToolRegistered = true;
313
+ report.imageIntakeToolRegistered = true;
293
314
  } else {
294
315
  report.qccCommandToolRegistered = false;
316
+ report.imageIntakeToolRegistered = false;
295
317
  }
296
318
  const phase3Service = new Phase3BatchService(qccBridge);
297
319
  const phase3Runs = new Phase3RunStore();
@@ -347,11 +369,65 @@ export function mountWebRoutes(wctx, { logger, report, TOOL_NAME, SKILL_NAME })
347
369
  workflowV2: Boolean(wctx.storageDomain),
348
370
  durableArtifacts: Boolean(artifactStore),
349
371
  artifactBinaryStrategy: artifactStore ? 'xlsx-base64-over-writeText' : 'unavailable',
372
+ imageIntake: imageIntake.capabilities(),
350
373
  qccBridge: qccBridge.capabilities(),
351
374
  },
352
375
  });
353
376
  });
354
377
 
378
+ register('/data-cleaning/api/images/capabilities', (req, res) => {
379
+ if (!isTrusted(req)) return writeJson(res, 403, { ok: false, error: 'untrusted origin' });
380
+ if (req.method !== 'GET') return writeJson(res, 405, { ok: false, code: 'DC_METHOD', message: 'GET required' });
381
+ writeJson(res, 200, {
382
+ ok: true,
383
+ marker: 'data-cleaning-image-intake-v1',
384
+ tool: TOOL_IMAGE_EXTRACT,
385
+ toolRegistered: report.imageIntakeToolRegistered === true,
386
+ capabilities: imageIntake.capabilities(),
387
+ qccCalls: true,
388
+ billing: 'current-user-qcc-document-account',
389
+ });
390
+ });
391
+
392
+ register('/data-cleaning/api/images/commands', async (req, res) => {
393
+ if (!isTrusted(req)) return writeJson(res, 403, { ok: false, error: 'untrusted origin' });
394
+ try {
395
+ const pathname = new URL(req.url ?? '/data-cleaning/api/images/commands', 'http://127.0.0.1').pathname;
396
+ const segments = pathname.split('/').filter(Boolean);
397
+ const commandsIndex = segments.indexOf('commands');
398
+ const rest = commandsIndex >= 0 ? segments.slice(commandsIndex + 1) : [];
399
+ if (rest.length === 0 && req.method === 'POST') {
400
+ if (report.imageIntakeToolRegistered !== true) {
401
+ throw new ImageIntakeError('DC_IMAGE_TOOL_UNAVAILABLE', '当前 DSH Host 无法注册图片名单高层工具。', 503);
402
+ }
403
+ const payload = JSON.parse((await readBody(req)).toString('utf8'));
404
+ const command = await imageIntake.prepare(payload);
405
+ return writeJson(res, 201, {
406
+ ok: true,
407
+ marker: 'data-cleaning-image-intake-v1',
408
+ command: { ...command, prompt: serializeImageExtractionPrompt(command) },
409
+ });
410
+ }
411
+ if (rest.length === 1 && req.method === 'GET') {
412
+ return writeJson(res, 200, {
413
+ ok: true,
414
+ marker: 'data-cleaning-image-intake-v1',
415
+ command: imageIntake.status(decodeURIComponent(rest[0])),
416
+ });
417
+ }
418
+ if (rest.length === 1 && req.method === 'DELETE') {
419
+ await imageIntake.remove(decodeURIComponent(rest[0]));
420
+ return writeJson(res, 200, { ok: true, marker: 'data-cleaning-image-intake-v1', removed: true });
421
+ }
422
+ return writeJson(res, 405, { ok: false, code: 'DC_METHOD', message: 'POST a command, GET its status, or DELETE it.' });
423
+ } catch (error) {
424
+ if (error instanceof SyntaxError) {
425
+ return writeJson(res, 400, { ok: false, code: 'DC_BAD_JSON', message: 'Request body must be valid JSON.' });
426
+ }
427
+ return writeImageError(res, error);
428
+ }
429
+ });
430
+
355
431
  register('/data-cleaning/api/workflow/contract', (req, res) => {
356
432
  if (!isTrusted(req)) return writeJson(res, 403, { ok: false, error: 'untrusted origin' });
357
433
  if (req.method !== 'GET') {
@@ -955,6 +1031,7 @@ export function mountWebRoutes(wctx, { logger, report, TOOL_NAME, SKILL_NAME })
955
1031
  return () => {
956
1032
  if (state) { state.dispose().catch(() => {}); }
957
1033
  if (workflow) { workflow.dispose().catch(() => {}); }
1034
+ imageIntake.dispose().catch(() => {});
958
1035
  for (const dispose of disposers) dispose();
959
1036
  };
960
1037
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-data-cleaning-agent",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "Clean, complete, and profile enterprise name lists in DeepSeek Harness — a data cleaning & completion agent plugin with local CSV/XLSX/JSON engine and optional Qichacha (QCC) MCP enrichment. Maintained by Qichacha/QCC.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -36,6 +36,8 @@
36
36
  "docs/RELEASE-0.6.2.md",
37
37
  "docs/RELEASE-0.6.3.md",
38
38
  "docs/RELEASE-0.7.0.md",
39
+ "docs/RELEASE-0.8.0.md",
40
+ "docs/RELEASE-0.8.1.md",
39
41
  "docs/UI-WORKFLOW-V2.md",
40
42
  "docs/UI-WORKFLOW-V2-MIGRATION.md",
41
43
  "docs/UI-WORKFLOW-V2-ACCEPTANCE.md",
@@ -44,7 +46,7 @@
44
46
  ],
45
47
  "scripts": {
46
48
  "test": "node --test",
47
- "lint": "node --check lib/index.js && node --check lib/engine.js && node --check lib/artifacts.js && node --check lib/tools.js && node --check lib/skill.js && node --check lib/qcc-field-catalog.js && node --check lib/qcc-phase2.js && node --check lib/qcc-phase3.js && node --check lib/qcc-phase3-batch.js && node --check lib/qcc-phase2-acceptance.js && node --check lib/skill-enrich.js && node --check lib/jobs.js && node --check lib/workflow-contract.js && node --check lib/workflow.js && node --check lib/qcc-safety.js && node --check lib/qcc.js && node --check lib/qcc-command.js && node --check lib/qcc-runs.js && node --check lib/web.js && node --check lib/client.js && node --check scripts/check-readme-version.mjs && node --check scripts/check-market-registration.mjs && node --check scripts/g5-e2e.mjs && node --check scripts/phase3-e2e.mjs && node --check scripts/phase2-acceptance.mjs",
49
+ "lint": "node --check lib/index.js && node --check lib/engine.js && node --check lib/artifacts.js && node --check lib/image-intake.js && node --check lib/tools.js && node --check lib/skill.js && node --check lib/qcc-field-catalog.js && node --check lib/qcc-phase2.js && node --check lib/qcc-phase3.js && node --check lib/qcc-phase3-batch.js && node --check lib/qcc-phase2-acceptance.js && node --check lib/skill-enrich.js && node --check lib/jobs.js && node --check lib/workflow-contract.js && node --check lib/workflow.js && node --check lib/qcc-safety.js && node --check lib/qcc.js && node --check lib/qcc-command.js && node --check lib/qcc-runs.js && node --check lib/web.js && node --check lib/client.js && node --check scripts/check-readme-version.mjs && node --check scripts/check-market-registration.mjs && node --check scripts/g5-e2e.mjs && node --check scripts/phase3-e2e.mjs && node --check scripts/phase2-acceptance.mjs",
48
50
  "docs:check": "node scripts/check-readme-version.mjs",
49
51
  "marketing:check": "node scripts/check-marketing.mjs",
50
52
  "verify-pack": "node scripts/verify-pack.mjs",