@xdxer/dingtalk-agent 0.1.4-beta.8 → 0.1.4
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 +233 -0
- package/README.en.md +167 -0
- package/README.md +101 -248
- package/dist/bin/dingtalk-agent.js +1255 -25
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/actions.js +98 -14
- package/dist/src/actions.js.map +1 -1
- package/dist/src/agent-audit.js +1385 -0
- package/dist/src/agent-audit.js.map +1 -0
- package/dist/src/agent-bindings.js +132 -0
- package/dist/src/agent-bindings.js.map +1 -0
- package/dist/src/agent-definition.js +182 -0
- package/dist/src/agent-definition.js.map +1 -0
- package/dist/src/agent-enhance.js +711 -0
- package/dist/src/agent-enhance.js.map +1 -0
- package/dist/src/agent-platform.js +299 -0
- package/dist/src/agent-platform.js.map +1 -0
- package/dist/src/bootstrap.js +125 -17
- package/dist/src/bootstrap.js.map +1 -1
- package/dist/src/config.js +1 -7
- package/dist/src/config.js.map +1 -1
- package/dist/src/development-workspace.js +755 -0
- package/dist/src/development-workspace.js.map +1 -0
- package/dist/src/doctor.js +74 -15
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/dws.js +145 -0
- package/dist/src/dws.js.map +1 -1
- package/dist/src/eval-evidence.js +193 -0
- package/dist/src/eval-evidence.js.map +1 -0
- package/dist/src/host-detect.js +146 -0
- package/dist/src/host-detect.js.map +1 -0
- package/dist/src/instruction-path.js +270 -0
- package/dist/src/instruction-path.js.map +1 -0
- package/dist/src/invocation.js +36 -0
- package/dist/src/invocation.js.map +1 -0
- package/dist/src/lab.js +679 -0
- package/dist/src/lab.js.map +1 -0
- package/dist/src/lease.js +100 -0
- package/dist/src/lease.js.map +1 -0
- package/dist/src/map.js +157 -0
- package/dist/src/map.js.map +1 -0
- package/dist/src/memory/candidates.js +451 -0
- package/dist/src/memory/candidates.js.map +1 -0
- package/dist/src/memory/completion-evidence.js +536 -0
- package/dist/src/memory/completion-evidence.js.map +1 -0
- package/dist/src/memory/operational.js +263 -0
- package/dist/src/memory/operational.js.map +1 -0
- package/dist/src/memory/remote-state.js +478 -0
- package/dist/src/memory/remote-state.js.map +1 -0
- package/dist/src/memory/task-checkpoints.js +204 -0
- package/dist/src/memory/task-checkpoints.js.map +1 -0
- package/dist/src/multica-deploy.js +1538 -0
- package/dist/src/multica-deploy.js.map +1 -0
- package/dist/src/multica-provider.js +685 -0
- package/dist/src/multica-provider.js.map +1 -0
- package/dist/src/opencode-evals.js +1547 -0
- package/dist/src/opencode-evals.js.map +1 -0
- package/dist/src/opencode-isolation.js +124 -0
- package/dist/src/opencode-isolation.js.map +1 -0
- package/dist/src/opencode-provider.js +532 -0
- package/dist/src/opencode-provider.js.map +1 -0
- package/dist/src/opencode-workspace.js +208 -0
- package/dist/src/opencode-workspace.js.map +1 -0
- package/dist/src/perception.js +225 -0
- package/dist/src/perception.js.map +1 -0
- package/dist/src/personal-event-evals.js +595 -0
- package/dist/src/personal-event-evals.js.map +1 -0
- package/dist/src/promotion.js +786 -0
- package/dist/src/promotion.js.map +1 -0
- package/dist/src/remote-semantic-state-live-evals.js +888 -0
- package/dist/src/remote-semantic-state-live-evals.js.map +1 -0
- package/dist/src/remote-semantic-state-worker.js +38 -0
- package/dist/src/remote-semantic-state-worker.js.map +1 -0
- package/dist/src/remote-state-evals.js +502 -0
- package/dist/src/remote-state-evals.js.map +1 -0
- package/dist/src/response-gate.js +51 -0
- package/dist/src/response-gate.js.map +1 -0
- package/dist/src/robot-evals.js +771 -0
- package/dist/src/robot-evals.js.map +1 -0
- package/dist/src/sessions.js +66 -105
- package/dist/src/sessions.js.map +1 -1
- package/dist/src/setup.js +6 -5
- package/dist/src/setup.js.map +1 -1
- package/dist/src/skill-manager.js +162 -24
- package/dist/src/skill-manager.js.map +1 -1
- package/dist/src/skills.js +2 -1
- package/dist/src/skills.js.map +1 -1
- package/dist/src/storage-evals.js +26 -0
- package/dist/src/storage-evals.js.map +1 -0
- package/dist/src/types.js.map +1 -1
- package/dist/src/upgrade.js +23 -27
- package/dist/src/upgrade.js.map +1 -1
- package/dist/src/version.js +73 -0
- package/dist/src/version.js.map +1 -0
- package/dist/src/waits.js +5 -1
- package/dist/src/waits.js.map +1 -1
- package/dist/src/workspace.js +28 -3
- package/dist/src/workspace.js.map +1 -1
- package/docs/INSTALLATION.md +50 -3
- package/docs/SECOND-AGENT-ACCEPTANCE.md +62 -0
- package/docs/architecture/agent-memory-topology.png +0 -0
- package/docs/architecture/agent-memory-topology.svg +132 -0
- package/docs/architecture/general-agent-kernel-topology.png +0 -0
- package/docs/architecture/general-agent-kernel-topology.svg +149 -0
- package/docs/architecture/provider-bound-development-workspace.png +0 -0
- package/docs/architecture/provider-bound-development-workspace.svg +141 -0
- package/docs/architecture/task-completion-gate.png +0 -0
- package/docs/architecture/task-completion-gate.svg +191 -0
- package/docs/assets/agent-delivery-lifecycle.svg +103 -0
- package/docs/schemas/agent-audit-load-evidence.schema.json +14 -0
- package/docs/schemas/agent-audit.schema.json +92 -0
- package/docs/schemas/agent-bindings.schema.json +54 -0
- package/docs/schemas/agent-definition.schema.json +78 -0
- package/docs/schemas/agent-enhancement-plan.schema.json +88 -0
- package/docs/schemas/agent-enhancement-receipt.schema.json +37 -0
- package/docs/schemas/agent-platform.schema.json +13 -0
- package/docs/schemas/enriched-invocation.schema.json +46 -0
- package/docs/schemas/eval-candidate-plan.schema.json +28 -0
- package/docs/schemas/eval-candidate-result.schema.json +20 -0
- package/docs/schemas/eval-candidate.schema.json +30 -0
- package/docs/schemas/invocation.schema.json +19 -0
- package/docs/schemas/memory-candidate-proposal.schema.json +18 -0
- package/docs/schemas/memory-candidate.schema.json +76 -0
- package/docs/schemas/memory-publish-target.schema.json +25 -0
- package/docs/schemas/multica-deployment-list.schema.json +29 -0
- package/docs/schemas/multica-deployment-operation.schema.json +51 -0
- package/docs/schemas/multica-deployment-plan.schema.json +70 -0
- package/docs/schemas/multica-deployment-receipt.schema.json +87 -0
- package/docs/schemas/multica-deployment-status.schema.json +23 -0
- package/docs/schemas/multica-workspace-inspection.schema.json +77 -0
- package/docs/schemas/multica-workspace-plan.schema.json +68 -0
- package/docs/schemas/multica-workspace-resource-list.schema.json +27 -0
- package/docs/schemas/multica-workspace-status.schema.json +34 -0
- package/docs/schemas/observation.schema.json +21 -0
- package/docs/schemas/operational-memory-provider.schema.json +36 -0
- package/docs/schemas/operational-memory-record.schema.json +24 -0
- package/docs/schemas/perception-input.schema.json +56 -0
- package/docs/schemas/project.schema.json +115 -0
- package/docs/schemas/promotion-list.schema.json +36 -0
- package/docs/schemas/promotion-plan.schema.json +60 -0
- package/docs/schemas/promotion-policy.schema.json +29 -0
- package/docs/schemas/promotion-receipt.schema.json +43 -0
- package/docs/schemas/promotion-status.schema.json +23 -0
- package/docs/schemas/release-readiness.schema.json +66 -0
- package/docs/schemas/remote-semantic-state-live-eval.schema.json +60 -0
- package/docs/schemas/remote-semantic-state-manifest.schema.json +79 -0
- package/docs/schemas/remote-semantic-state-provider.schema.json +98 -0
- package/docs/schemas/response-gate.schema.json +20 -0
- package/docs/schemas/task-checkpoint.schema.json +71 -0
- package/docs/schemas/task-completion-evidence.schema.json +154 -0
- package/docs/schemas/workspace-doctor.schema.json +56 -0
- package/docs/schemas/workspace-state.schema.json +39 -0
- package/evals/README.md +17 -0
- package/evals/baselines/2026-07-16/opencode-basic-010-completion-summary.json +123 -0
- package/evals/baselines/2026-07-16/opencode-basic-skill-required-summary.json +69 -0
- package/evals/baselines/2026-07-16/opencode-multi-surface-summary.json +63 -0
- package/evals/baselines/2026-07-16/remote-state-live-summary.json +70 -0
- package/evals/baselines/2026-07-17/agent-enhance-opencode-dogfood-summary.json +98 -0
- package/evals/baselines/2026-07-17/personal-event-live-readiness-summary.json +68 -0
- package/examples/agents/fde-coach/AGENTS.md +26 -0
- package/examples/agents/fde-coach/MEMORY.md +3 -0
- package/examples/agents/fde-coach/fields/default/field.json +24 -0
- package/examples/agents/fde-coach/knowledge/INDEX.md +4 -0
- package/examples/agents/fde-coach/skills/fde-coach/SKILL.md +13 -0
- package/examples/agents/release-manager/AGENTS.md +26 -0
- package/examples/agents/release-manager/MEMORY.md +3 -0
- package/examples/agents/release-manager/fields/default/field.json +24 -0
- package/examples/agents/release-manager/knowledge/INDEX.md +4 -0
- package/examples/agents/release-manager/skills/release-manager/SKILL.md +13 -0
- package/lab/README.md +109 -0
- package/lab/agent-eval/catalog.json +91 -0
- package/lab/agent-eval/classic-failures.json +177 -0
- package/lab/agent-eval/completion-gate-regression.json +99 -0
- package/lab/agent-eval/personal-event-live.example.json +94 -0
- package/lab/agent-eval/remote-semantic-state-live.example.json +70 -0
- package/lab/agent-eval/remote-semantic-state-provider.fixture.json +47 -0
- package/lab/agent-eval/remote-state-workspace/AGENTS.md +8 -0
- package/lab/agent-eval/remote-state-workspace/opencode.json +7 -0
- package/lab/agent-eval/remote-state-workspace/skills/remote-state-operator/SKILL.md +13 -0
- package/lab/agent-eval/remote-state.example.json +31 -0
- package/lab/agent-eval/workspace/AGENTS.md +7 -0
- package/lab/agent-eval/workspace/MEMORY.md +4 -0
- package/lab/agent-eval/workspace/artifacts/pending-review.md +3 -0
- package/lab/agent-eval/workspace/knowledge/INDEX.md +4 -0
- package/lab/agent-eval/workspace/opencode.json +20 -0
- package/lab/manifest.example.json +27 -0
- package/lab/manifest.personal-event.example.json +27 -0
- package/lab/project-workspace/README.md +11 -0
- package/lab/project-workspace/fake-multica-provider.mjs +277 -0
- package/lab/project-workspace/multica-deploy.fixture.json +29 -0
- package/lab/project-workspace/multica-readonly.fixture.json +69 -0
- package/lab/project-workspace/observation.fixture.json +14 -0
- package/lab/project-workspace/opencode-provider-suite.json +65 -0
- package/lab/project-workspace/project.fixture.json +44 -0
- package/lab/project-workspace/promotion-policy.fixture.json +15 -0
- package/lab/robot-eval/pool.example.json +30 -0
- package/lab/robot-eval/suite.json +123 -0
- package/lab/robot-eval/workspace/AGENTS.md +21 -0
- package/lab/robot-eval/workspace/MEMORY.md +3 -0
- package/lab/robot-eval/workspace/knowledge/INDEX.md +5 -0
- package/lab/robot-eval/workspace/opencode.json +22 -0
- package/lab/schemas/agent-eval-catalog.schema.json +47 -0
- package/lab/schemas/lab-manifest.schema.json +70 -0
- package/lab/schemas/personal-event-eval.schema.json +91 -0
- package/lab/schemas/remote-state-eval.schema.json +66 -0
- package/lab/schemas/robot-eval-suite.schema.json +184 -0
- package/lab/schemas/robot-pool.schema.json +56 -0
- package/package.json +28 -9
- package/skills/README.md +23 -0
- package/skills/core/dingtalk-agent-compose/SKILL.md +151 -0
- package/skills/core/dingtalk-agent-compose/assets/AGENTS.template.md +35 -0
- package/skills/core/dingtalk-agent-compose/assets/agent.bindings.dingtalk-doc.template.json +13 -0
- package/skills/core/dingtalk-agent-compose/assets/agent.bindings.local.template.json +13 -0
- package/skills/core/dingtalk-agent-compose/assets/hosts/opencode/opencode.template.json +12 -0
- package/skills/core/dingtalk-agent-compose/assets/role-skill.template.md +32 -0
- package/skills/core/dingtalk-agent-compose/evals/evals.json +129 -0
- package/skills/core/dingtalk-agent-compose/references/agent-definition-contract.md +55 -0
- package/skills/core/dingtalk-agent-compose/references/host-loading-contract.md +58 -0
- package/skills/core/dingtalk-agent-compose/references/hosts/claude-code.md +48 -0
- package/skills/core/dingtalk-agent-compose/references/hosts/opencode.md +77 -0
- package/skills/core/dingtalk-agent-compose/references/storage-routing.md +20 -0
- package/skills/core/dingtalk-agent-eval/SKILL.md +140 -0
- package/skills/core/dingtalk-agent-eval/assets/eval-catalog.template.json +18 -0
- package/skills/core/dingtalk-agent-eval/evals/evals.json +83 -0
- package/skills/core/dingtalk-agent-eval/references/eval-topology.md +48 -0
- package/skills/core/dingtalk-agent-eval/references/evidence-contract.md +52 -0
- package/skills/core/dingtalk-agent-eval/references/failure-to-case.md +35 -0
- package/skills/core/dingtalk-agent-eval/references/interactive-debug-channels.md +93 -0
- package/skills/core/dingtalk-agent-eval/references/local-connector-smoke.md +75 -0
- package/skills/core/dingtalk-agent-eval/references/scenario-taxonomy.md +25 -0
- package/skills/core/dingtalk-agent-eval/references/storage-modes.md +75 -0
- package/skills/core/dingtalk-basic-behavior/SKILL.md +87 -0
- package/skills/core/dingtalk-basic-behavior/assets/memory-candidate-proposal.json +10 -0
- package/skills/{dingtalk-basic-behavior/assets/task-checkpoint.md → core/dingtalk-basic-behavior/assets/task-checkpoint.json} +2 -21
- package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/action-contract.md +2 -0
- package/skills/core/dingtalk-basic-behavior/references/memory-and-evolution.md +53 -0
- package/skills/core/dingtalk-basic-behavior/references/perception-and-gates.md +28 -0
- package/skills/core/dingtalk-basic-behavior/references/risk-authority-and-privacy.md +62 -0
- package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/task-lifecycle.md +47 -10
- package/skills/core/dingtalk-basic-behavior/references/truth-and-recovery.md +65 -0
- package/skills/platforms/deap/PLATFORM.md +3 -0
- package/skills/platforms/deap/README.md +3 -0
- package/skills/platforms/multica-dingtalk/PLATFORM.md +40 -0
- package/skills/platforms/multica-dingtalk/dingtalk-agent-boot-multica/SKILL.md +40 -0
- package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/SKILL.md +60 -0
- package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/references/multica-deployment-contract.md +49 -0
- package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/references/promotion-observation-contract.md +49 -0
- package/skills/platforms/multica-dingtalk/multica-external/SKILL.md +282 -0
- package/skills/platforms/multica-dingtalk/multica-external/scripts/bootstrap.sh +78 -0
- package/skills/platforms/multica-dingtalk/multica-external/scripts/multica_ext.py +1180 -0
- package/skills/dingtalk-basic-behavior/SKILL.md +0 -86
- package/skills/dingtalk-basic-behavior/references/memory-and-evolution.md +0 -27
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/event-to-behavior.md +0 -0
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/runtime-modes.md +0 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, renameSync, writeFileSync, } from 'node:fs';
|
|
2
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
3
|
+
import { digest, stableStringify } from '../events.js';
|
|
4
|
+
import { acquireLease } from '../lease.js';
|
|
5
|
+
import { isCompletionEvidenceId, resolveCompletionEvidence, } from './completion-evidence.js';
|
|
6
|
+
const TRANSITIONS = {
|
|
7
|
+
missing: ['working'],
|
|
8
|
+
working: ['working', 'waiting', 'verifying', 'blocked', 'cancelled'],
|
|
9
|
+
waiting: ['waiting', 'working', 'blocked', 'cancelled'],
|
|
10
|
+
verifying: ['verifying', 'working', 'waiting', 'blocked', 'completed', 'cancelled'],
|
|
11
|
+
blocked: ['blocked', 'working', 'cancelled'],
|
|
12
|
+
completed: ['completed'],
|
|
13
|
+
cancelled: ['cancelled'],
|
|
14
|
+
};
|
|
15
|
+
export function showTaskCheckpoint(root, cfg, options = {}) {
|
|
16
|
+
const context = resolveTaskContext(root, cfg, options, false);
|
|
17
|
+
const path = join(context.sessionPath, 'memory', 'task.json');
|
|
18
|
+
if (!existsSync(path))
|
|
19
|
+
return result(path, null);
|
|
20
|
+
return result(path, validateTaskCheckpoint(readJson(path), context.session));
|
|
21
|
+
}
|
|
22
|
+
export function checkpointTask(root, cfg, value, expectedRevision, options = {}) {
|
|
23
|
+
if (!Number.isInteger(expectedRevision) || expectedRevision < 0) {
|
|
24
|
+
throw new Error('expect-revision 必须是非负整数');
|
|
25
|
+
}
|
|
26
|
+
const context = resolveTaskContext(root, cfg, options, true);
|
|
27
|
+
const path = join(context.sessionPath, 'memory', 'task.json');
|
|
28
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
29
|
+
const release = acquireLease(`${path}.lock`, `Task ${context.session.id} 正在更新`, {
|
|
30
|
+
waitMs: 3_000, staleAfterMs: 2 * 60_000,
|
|
31
|
+
});
|
|
32
|
+
try {
|
|
33
|
+
const current = existsSync(path)
|
|
34
|
+
? validateTaskCheckpoint(readJson(path), context.session) : null;
|
|
35
|
+
const actualRevision = current?.revision || 0;
|
|
36
|
+
if (actualRevision !== expectedRevision) {
|
|
37
|
+
throw new Error(`Task revision 冲突:expected=${expectedRevision}, actual=${actualRevision};` +
|
|
38
|
+
'请重新 task show 后合并');
|
|
39
|
+
}
|
|
40
|
+
const input = validateTaskCheckpoint(value, context.session);
|
|
41
|
+
if (input.revision !== expectedRevision + 1) {
|
|
42
|
+
throw new Error(`Task 新 revision 必须是 ${expectedRevision + 1},实际为 ${input.revision}`);
|
|
43
|
+
}
|
|
44
|
+
const previous = current?.status || 'missing';
|
|
45
|
+
if (!TRANSITIONS[previous].includes(input.status)) {
|
|
46
|
+
throw new Error(`Task 状态不能从 ${previous} 迁移到 ${input.status}`);
|
|
47
|
+
}
|
|
48
|
+
if (input.status === 'completed') {
|
|
49
|
+
resolveCompletionEvidence(root, cfg, context.sessionPath, input.doneWhen, input.evidence);
|
|
50
|
+
}
|
|
51
|
+
const checkpoint = {
|
|
52
|
+
...input,
|
|
53
|
+
updatedAt: new Date().toISOString(),
|
|
54
|
+
updatedByRunId: context.run.id,
|
|
55
|
+
};
|
|
56
|
+
writeJsonAtomic(path, checkpoint);
|
|
57
|
+
const readback = validateTaskCheckpoint(readJson(path), context.session);
|
|
58
|
+
if (stableStringify(readback) !== stableStringify(checkpoint)) {
|
|
59
|
+
throw new Error('Task checkpoint 原子写后回读不一致');
|
|
60
|
+
}
|
|
61
|
+
return result(path, readback);
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
release();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function snapshotTaskCheckpoint(sessionPath, runPath) {
|
|
68
|
+
const path = join(sessionPath, 'memory', 'task.json');
|
|
69
|
+
if (!existsSync(path))
|
|
70
|
+
return null;
|
|
71
|
+
const session = readJson(join(sessionPath, 'session.json'));
|
|
72
|
+
const checkpoint = validateTaskCheckpoint(readJson(path), session);
|
|
73
|
+
writeJsonAtomic(join(runPath, 'context', 'task-checkpoint.json'), checkpoint);
|
|
74
|
+
return checkpoint;
|
|
75
|
+
}
|
|
76
|
+
function resolveTaskContext(root, cfg, options, requireRun) {
|
|
77
|
+
const configuredRoot = resolve(root, cfg.runtime.sessionRoot || '.dingtalk-agent/sessions');
|
|
78
|
+
if (!existsSync(configuredRoot))
|
|
79
|
+
throw new Error('当前 Workspace 还没有 Session state root');
|
|
80
|
+
const sessionInput = String(options.sessionPath || process.env.DTA_SESSION || '').trim();
|
|
81
|
+
if (!sessionInput)
|
|
82
|
+
throw new Error('task 需要 Prepared Run 的 DTA_SESSION');
|
|
83
|
+
const sessionPath = realpathSync(resolve(sessionInput));
|
|
84
|
+
assertInside(configuredRoot, sessionPath, 'Task Session');
|
|
85
|
+
const session = readJson(join(sessionPath, 'session.json'));
|
|
86
|
+
if (!session.id || !session.contextId)
|
|
87
|
+
throw new Error('Task Session 缺少 id/contextId');
|
|
88
|
+
const runInput = String(options.runPath || process.env.DTA_RUN || '').trim();
|
|
89
|
+
if (!runInput) {
|
|
90
|
+
if (requireRun)
|
|
91
|
+
throw new Error('task checkpoint 只能由 Prepared Run 写入,缺少 DTA_RUN');
|
|
92
|
+
return { sessionPath, session, run: { id: '' } };
|
|
93
|
+
}
|
|
94
|
+
const runPath = realpathSync(resolve(runInput));
|
|
95
|
+
assertInside(join(sessionPath, 'runs'), runPath, 'Task Run');
|
|
96
|
+
const run = readJson(join(runPath, 'run.json'));
|
|
97
|
+
if (run.sessionId !== session.id || run.contextId !== session.contextId) {
|
|
98
|
+
throw new Error('Task Run 与 Session 身份不一致');
|
|
99
|
+
}
|
|
100
|
+
return { sessionPath, session, run };
|
|
101
|
+
}
|
|
102
|
+
function validateTaskCheckpoint(value, session) {
|
|
103
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
104
|
+
throw new Error('Task checkpoint 必须是 JSON object');
|
|
105
|
+
}
|
|
106
|
+
const input = value;
|
|
107
|
+
const allowed = new Set([
|
|
108
|
+
'$schema', 'taskId', 'scopeId', 'status', 'revision', 'goal', 'deliverable',
|
|
109
|
+
'doneWhen', 'checkpoint', 'nextAction', 'waitingFor', 'assumptions', 'sourceRefs',
|
|
110
|
+
'evidence', 'updatedAt', 'updatedByRunId',
|
|
111
|
+
]);
|
|
112
|
+
const extra = Object.keys(input).filter((key) => !allowed.has(key));
|
|
113
|
+
if (extra.length)
|
|
114
|
+
throw new Error(`Task checkpoint 含未知字段: ${extra.join(', ')}`);
|
|
115
|
+
if (input.$schema !== 'dingtalk-agent/task-checkpoint@1') {
|
|
116
|
+
throw new Error('Task checkpoint schema 非法');
|
|
117
|
+
}
|
|
118
|
+
if (input.taskId !== session.id || input.scopeId !== session.contextId) {
|
|
119
|
+
throw new Error(`Task checkpoint 作用域不一致:taskId=${input.taskId || '-'}, scopeId=${input.scopeId || '-'}`);
|
|
120
|
+
}
|
|
121
|
+
if (!Object.prototype.hasOwnProperty.call(TRANSITIONS, input.status)) {
|
|
122
|
+
throw new Error(`Task status 非法: ${input.status || '-'}`);
|
|
123
|
+
}
|
|
124
|
+
if (!Number.isInteger(input.revision) || input.revision < 1) {
|
|
125
|
+
throw new Error('Task revision 必须是正整数');
|
|
126
|
+
}
|
|
127
|
+
for (const key of ['goal', 'deliverable', 'doneWhen', 'checkpoint', 'nextAction',
|
|
128
|
+
'updatedAt', 'updatedByRunId']) {
|
|
129
|
+
if (typeof input[key] !== 'string')
|
|
130
|
+
throw new Error(`Task ${key} 必须是 string`);
|
|
131
|
+
}
|
|
132
|
+
if (!input.goal.trim())
|
|
133
|
+
throw new Error('Task goal 不能为空');
|
|
134
|
+
if (!['completed', 'cancelled'].includes(input.status) && !input.nextAction.trim()) {
|
|
135
|
+
throw new Error(`Task ${input.status} 状态必须有 nextAction`);
|
|
136
|
+
}
|
|
137
|
+
for (const key of ['assumptions', 'sourceRefs', 'evidence']) {
|
|
138
|
+
if (!Array.isArray(input[key]) || input[key].some((item) => typeof item !== 'string')) {
|
|
139
|
+
throw new Error(`Task ${key} 必须是 string[]`);
|
|
140
|
+
}
|
|
141
|
+
if (input[key].some((item) => !item.trim())) {
|
|
142
|
+
throw new Error(`Task ${key} 不能包含空字符串`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (input.evidence.some((item) => !isCompletionEvidenceId(item))) {
|
|
146
|
+
throw new Error('Task evidence 只能引用宿主签发的 evidenceId');
|
|
147
|
+
}
|
|
148
|
+
if (input.waitingFor !== null) {
|
|
149
|
+
if (!input.waitingFor || typeof input.waitingFor !== 'object' ||
|
|
150
|
+
Array.isArray(input.waitingFor) ||
|
|
151
|
+
typeof input.waitingFor.kind !== 'string' ||
|
|
152
|
+
typeof input.waitingFor.condition !== 'string' ||
|
|
153
|
+
(input.waitingFor.subject !== undefined && typeof input.waitingFor.subject !== 'string')) {
|
|
154
|
+
throw new Error('Task waitingFor 必须是 null 或 {kind, subject?, condition}');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (input.status === 'waiting' && !input.waitingFor) {
|
|
158
|
+
throw new Error('Task waiting 状态必须填写 waitingFor');
|
|
159
|
+
}
|
|
160
|
+
if (['verifying', 'completed'].includes(input.status)) {
|
|
161
|
+
if (!input.deliverable.trim())
|
|
162
|
+
throw new Error(`Task ${input.status} 状态必须填写 deliverable`);
|
|
163
|
+
if (!input.doneWhen.trim())
|
|
164
|
+
throw new Error(`Task ${input.status} 状态必须填写 doneWhen`);
|
|
165
|
+
}
|
|
166
|
+
if (input.status === 'completed') {
|
|
167
|
+
if (!input.checkpoint.trim())
|
|
168
|
+
throw new Error('Task completed 状态必须填写最终 checkpoint');
|
|
169
|
+
if (!input.evidence.length) {
|
|
170
|
+
throw new Error('Task completed 状态必须引用宿主签发的 completion evidenceId');
|
|
171
|
+
}
|
|
172
|
+
if (input.waitingFor)
|
|
173
|
+
throw new Error('Task completed 状态不能仍有 waitingFor');
|
|
174
|
+
if (input.nextAction.trim())
|
|
175
|
+
throw new Error('Task completed 状态不能仍有 nextAction');
|
|
176
|
+
}
|
|
177
|
+
return JSON.parse(JSON.stringify(input));
|
|
178
|
+
}
|
|
179
|
+
function result(path, checkpoint) {
|
|
180
|
+
return {
|
|
181
|
+
$schema: 'dingtalk-agent/task-checkpoint-result@1',
|
|
182
|
+
found: Boolean(checkpoint),
|
|
183
|
+
path,
|
|
184
|
+
hash: checkpoint ? digest(stableStringify(checkpoint)) : '',
|
|
185
|
+
checkpoint,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function assertInside(root, path, label) {
|
|
189
|
+
const rootReal = realpathSync(resolve(root));
|
|
190
|
+
const rel = relative(rootReal, path);
|
|
191
|
+
if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`)) {
|
|
192
|
+
throw new Error(`${label} 必须位于配置的 sessionRoot 内`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function readJson(path) {
|
|
196
|
+
return JSON.parse(readFileSync(path, 'utf8'));
|
|
197
|
+
}
|
|
198
|
+
function writeJsonAtomic(path, value) {
|
|
199
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
200
|
+
const temp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
201
|
+
writeFileSync(temp, JSON.stringify(value, null, 2) + '\n', { flag: 'wx' });
|
|
202
|
+
renameSync(temp, path);
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=task-checkpoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-checkpoints.js","sourceRoot":"","sources":["../../../src/memory/task-checkpoints.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n existsSync, mkdirSync, readFileSync, realpathSync, renameSync, writeFileSync,\n} from 'node:fs'\nimport { dirname, join, relative, resolve } from 'node:path'\nimport { digest, stableStringify } from '../events.js'\nimport { acquireLease } from '../lease.js'\nimport type { AgentConfig } from '../types.js'\nimport {\n isCompletionEvidenceId, resolveCompletionEvidence,\n} from './completion-evidence.js'\n\nexport type TaskStatus =\n | 'working' | 'waiting' | 'verifying' | 'blocked' | 'completed' | 'cancelled'\n\nexport interface TaskCheckpoint {\n $schema: 'dingtalk-agent/task-checkpoint@1'\n taskId: string\n scopeId: string\n status: TaskStatus\n revision: number\n goal: string\n deliverable: string\n doneWhen: string\n checkpoint: string\n nextAction: string\n waitingFor: null | { kind: string; subject?: string; condition: string }\n assumptions: string[]\n sourceRefs: string[]\n evidence: string[]\n updatedAt: string\n updatedByRunId: string\n}\n\nexport interface TaskContextOptions {\n sessionPath?: string\n runPath?: string\n}\n\nexport interface TaskCheckpointResult {\n $schema: 'dingtalk-agent/task-checkpoint-result@1'\n found: boolean\n path: string\n hash: string\n checkpoint: TaskCheckpoint | null\n}\n\nconst TRANSITIONS: Record<TaskStatus | 'missing', TaskStatus[]> = {\n missing: ['working'],\n working: ['working', 'waiting', 'verifying', 'blocked', 'cancelled'],\n waiting: ['waiting', 'working', 'blocked', 'cancelled'],\n verifying: ['verifying', 'working', 'waiting', 'blocked', 'completed', 'cancelled'],\n blocked: ['blocked', 'working', 'cancelled'],\n completed: ['completed'],\n cancelled: ['cancelled'],\n}\n\nexport function showTaskCheckpoint(\n root: string,\n cfg: AgentConfig,\n options: TaskContextOptions = {},\n): TaskCheckpointResult {\n const context = resolveTaskContext(root, cfg, options, false)\n const path = join(context.sessionPath, 'memory', 'task.json')\n if (!existsSync(path)) return result(path, null)\n return result(path, validateTaskCheckpoint(readJson(path), context.session))\n}\n\nexport function checkpointTask(\n root: string,\n cfg: AgentConfig,\n value: unknown,\n expectedRevision: number,\n options: TaskContextOptions = {},\n): TaskCheckpointResult {\n if (!Number.isInteger(expectedRevision) || expectedRevision < 0) {\n throw new Error('expect-revision 必须是非负整数')\n }\n const context = resolveTaskContext(root, cfg, options, true)\n const path = join(context.sessionPath, 'memory', 'task.json')\n mkdirSync(dirname(path), { recursive: true })\n const release = acquireLease(`${path}.lock`, `Task ${context.session.id} 正在更新`, {\n waitMs: 3_000, staleAfterMs: 2 * 60_000,\n })\n try {\n const current = existsSync(path)\n ? validateTaskCheckpoint(readJson(path), context.session) : null\n const actualRevision = current?.revision || 0\n if (actualRevision !== expectedRevision) {\n throw new Error(\n `Task revision 冲突:expected=${expectedRevision}, actual=${actualRevision};` +\n '请重新 task show 后合并',\n )\n }\n const input = validateTaskCheckpoint(value, context.session)\n if (input.revision !== expectedRevision + 1) {\n throw new Error(\n `Task 新 revision 必须是 ${expectedRevision + 1},实际为 ${input.revision}`,\n )\n }\n const previous = current?.status || 'missing'\n if (!TRANSITIONS[previous].includes(input.status)) {\n throw new Error(`Task 状态不能从 ${previous} 迁移到 ${input.status}`)\n }\n if (input.status === 'completed') {\n resolveCompletionEvidence(\n root, cfg, context.sessionPath, input.doneWhen, input.evidence,\n )\n }\n const checkpoint: TaskCheckpoint = {\n ...input,\n updatedAt: new Date().toISOString(),\n updatedByRunId: context.run.id,\n }\n writeJsonAtomic(path, checkpoint)\n const readback = validateTaskCheckpoint(readJson(path), context.session)\n if (stableStringify(readback) !== stableStringify(checkpoint)) {\n throw new Error('Task checkpoint 原子写后回读不一致')\n }\n return result(path, readback)\n } finally {\n release()\n }\n}\n\nexport function snapshotTaskCheckpoint(sessionPath: string, runPath: string): TaskCheckpoint | null {\n const path = join(sessionPath, 'memory', 'task.json')\n if (!existsSync(path)) return null\n const session = readJson(join(sessionPath, 'session.json'))\n const checkpoint = validateTaskCheckpoint(readJson(path), session)\n writeJsonAtomic(join(runPath, 'context', 'task-checkpoint.json'), checkpoint)\n return checkpoint\n}\n\nfunction resolveTaskContext(\n root: string,\n cfg: AgentConfig,\n options: TaskContextOptions,\n requireRun: boolean,\n): { sessionPath: string; session: Record<string, any>; run: Record<string, any> } {\n const configuredRoot = resolve(root, cfg.runtime.sessionRoot || '.dingtalk-agent/sessions')\n if (!existsSync(configuredRoot)) throw new Error('当前 Workspace 还没有 Session state root')\n const sessionInput = String(options.sessionPath || process.env.DTA_SESSION || '').trim()\n if (!sessionInput) throw new Error('task 需要 Prepared Run 的 DTA_SESSION')\n const sessionPath = realpathSync(resolve(sessionInput))\n assertInside(configuredRoot, sessionPath, 'Task Session')\n const session = readJson(join(sessionPath, 'session.json'))\n if (!session.id || !session.contextId) throw new Error('Task Session 缺少 id/contextId')\n\n const runInput = String(options.runPath || process.env.DTA_RUN || '').trim()\n if (!runInput) {\n if (requireRun) throw new Error('task checkpoint 只能由 Prepared Run 写入,缺少 DTA_RUN')\n return { sessionPath, session, run: { id: '' } }\n }\n const runPath = realpathSync(resolve(runInput))\n assertInside(join(sessionPath, 'runs'), runPath, 'Task Run')\n const run = readJson(join(runPath, 'run.json'))\n if (run.sessionId !== session.id || run.contextId !== session.contextId) {\n throw new Error('Task Run 与 Session 身份不一致')\n }\n return { sessionPath, session, run }\n}\n\nfunction validateTaskCheckpoint(value: unknown, session: Record<string, any>): TaskCheckpoint {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Task checkpoint 必须是 JSON object')\n }\n const input = value as Record<string, any>\n const allowed = new Set([\n '$schema', 'taskId', 'scopeId', 'status', 'revision', 'goal', 'deliverable',\n 'doneWhen', 'checkpoint', 'nextAction', 'waitingFor', 'assumptions', 'sourceRefs',\n 'evidence', 'updatedAt', 'updatedByRunId',\n ])\n const extra = Object.keys(input).filter((key) => !allowed.has(key))\n if (extra.length) throw new Error(`Task checkpoint 含未知字段: ${extra.join(', ')}`)\n if (input.$schema !== 'dingtalk-agent/task-checkpoint@1') {\n throw new Error('Task checkpoint schema 非法')\n }\n if (input.taskId !== session.id || input.scopeId !== session.contextId) {\n throw new Error(\n `Task checkpoint 作用域不一致:taskId=${input.taskId || '-'}, scopeId=${input.scopeId || '-'}`,\n )\n }\n if (!Object.prototype.hasOwnProperty.call(TRANSITIONS, input.status)) {\n throw new Error(`Task status 非法: ${input.status || '-'}`)\n }\n if (!Number.isInteger(input.revision) || input.revision < 1) {\n throw new Error('Task revision 必须是正整数')\n }\n for (const key of ['goal', 'deliverable', 'doneWhen', 'checkpoint', 'nextAction',\n 'updatedAt', 'updatedByRunId']) {\n if (typeof input[key] !== 'string') throw new Error(`Task ${key} 必须是 string`)\n }\n if (!input.goal.trim()) throw new Error('Task goal 不能为空')\n if (!['completed', 'cancelled'].includes(input.status) && !input.nextAction.trim()) {\n throw new Error(`Task ${input.status} 状态必须有 nextAction`)\n }\n for (const key of ['assumptions', 'sourceRefs', 'evidence']) {\n if (!Array.isArray(input[key]) || input[key].some((item: unknown) => typeof item !== 'string')) {\n throw new Error(`Task ${key} 必须是 string[]`)\n }\n if (input[key].some((item: string) => !item.trim())) {\n throw new Error(`Task ${key} 不能包含空字符串`)\n }\n }\n if (input.evidence.some((item: string) => !isCompletionEvidenceId(item))) {\n throw new Error('Task evidence 只能引用宿主签发的 evidenceId')\n }\n if (input.waitingFor !== null) {\n if (!input.waitingFor || typeof input.waitingFor !== 'object' ||\n Array.isArray(input.waitingFor) ||\n typeof input.waitingFor.kind !== 'string' ||\n typeof input.waitingFor.condition !== 'string' ||\n (input.waitingFor.subject !== undefined && typeof input.waitingFor.subject !== 'string')) {\n throw new Error('Task waitingFor 必须是 null 或 {kind, subject?, condition}')\n }\n }\n if (input.status === 'waiting' && !input.waitingFor) {\n throw new Error('Task waiting 状态必须填写 waitingFor')\n }\n if (['verifying', 'completed'].includes(input.status)) {\n if (!input.deliverable.trim()) throw new Error(`Task ${input.status} 状态必须填写 deliverable`)\n if (!input.doneWhen.trim()) throw new Error(`Task ${input.status} 状态必须填写 doneWhen`)\n }\n if (input.status === 'completed') {\n if (!input.checkpoint.trim()) throw new Error('Task completed 状态必须填写最终 checkpoint')\n if (!input.evidence.length) {\n throw new Error('Task completed 状态必须引用宿主签发的 completion evidenceId')\n }\n if (input.waitingFor) throw new Error('Task completed 状态不能仍有 waitingFor')\n if (input.nextAction.trim()) throw new Error('Task completed 状态不能仍有 nextAction')\n }\n return JSON.parse(JSON.stringify(input)) as TaskCheckpoint\n}\n\nfunction result(path: string, checkpoint: TaskCheckpoint | null): TaskCheckpointResult {\n return {\n $schema: 'dingtalk-agent/task-checkpoint-result@1',\n found: Boolean(checkpoint),\n path,\n hash: checkpoint ? digest(stableStringify(checkpoint)) : '',\n checkpoint,\n }\n}\n\nfunction assertInside(root: string, path: string, label: string): void {\n const rootReal = realpathSync(resolve(root))\n const rel = relative(rootReal, path)\n if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`)) {\n throw new Error(`${label} 必须位于配置的 sessionRoot 内`)\n }\n}\n\nfunction readJson(path: string): Record<string, any> {\n return JSON.parse(readFileSync(path, 'utf8'))\n}\n\nfunction writeJsonAtomic(path: string, value: unknown): void {\n mkdirSync(dirname(path), { recursive: true })\n const temp = `${path}.${process.pid}.${Date.now()}.tmp`\n writeFileSync(temp, JSON.stringify(value, null, 2) + '\\n', { flag: 'wx' })\n renameSync(temp, path)\n}\n"]}
|