@xdxer/dingtalk-agent 0.1.4-beta.1 → 0.1.4-beta.10
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 +50 -0
- package/README.en.md +397 -0
- package/README.md +497 -46
- package/dist/bin/dingtalk-agent.js +1162 -340
- 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 +460 -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 +678 -0
- package/dist/src/agent-enhance.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 +729 -0
- package/dist/src/development-workspace.js.map +1 -0
- package/dist/src/doctor.js +18 -7
- 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/init.js +1 -1
- package/dist/src/init.js.map +1 -1
- 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/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 +1480 -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 +1062 -0
- package/dist/src/opencode-evals.js.map +1 -0
- package/dist/src/opencode-provider.js +531 -0
- package/dist/src/opencode-provider.js.map +1 -0
- package/dist/src/opencode-workspace.js +197 -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 +501 -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 +770 -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 +10 -9
- package/dist/src/setup.js.map +1 -1
- package/dist/src/skill-manager.js +102 -203
- package/dist/src/skill-manager.js.map +1 -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 +137 -0
- package/dist/src/upgrade.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 +118 -13
- 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/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/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 +112 -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 +65 -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/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 +266 -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 +26 -14
- package/skills/dingtalk-agent-boot-multica/SKILL.md +40 -0
- package/skills/dingtalk-agent-compose/SKILL.md +110 -0
- package/skills/dingtalk-agent-compose/assets/AGENTS.template.md +26 -0
- package/skills/dingtalk-agent-compose/assets/agent.bindings.dingtalk-doc.template.json +13 -0
- package/skills/dingtalk-agent-compose/assets/agent.bindings.local.template.json +13 -0
- package/skills/dingtalk-agent-compose/assets/opencode.template.json +12 -0
- package/skills/dingtalk-agent-compose/assets/role-skill.template.md +24 -0
- package/skills/dingtalk-agent-compose/evals/evals.json +94 -0
- package/skills/dingtalk-agent-compose/references/agent-definition-contract.md +55 -0
- package/skills/dingtalk-agent-compose/references/opencode-host-contract.md +65 -0
- package/skills/dingtalk-agent-compose/references/storage-routing.md +20 -0
- package/skills/dingtalk-agent-deploy/SKILL.md +60 -0
- package/skills/dingtalk-agent-deploy/references/multica-deployment-contract.md +49 -0
- package/skills/dingtalk-agent-deploy/references/promotion-observation-contract.md +49 -0
- package/skills/dingtalk-agent-eval/SKILL.md +116 -0
- package/skills/dingtalk-agent-eval/assets/eval-catalog.template.json +18 -0
- package/skills/dingtalk-agent-eval/evals/evals.json +61 -0
- package/skills/dingtalk-agent-eval/references/eval-topology.md +34 -0
- package/skills/dingtalk-agent-eval/references/evidence-contract.md +31 -0
- package/skills/dingtalk-agent-eval/references/scenario-taxonomy.md +25 -0
- package/skills/dingtalk-agent-eval/references/storage-modes.md +75 -0
- package/skills/dingtalk-basic-behavior/SKILL.md +63 -3
- package/skills/dingtalk-basic-behavior/assets/memory-candidate-proposal.json +10 -0
- package/skills/dingtalk-basic-behavior/assets/{task-checkpoint.md → task-checkpoint.json} +2 -21
- package/skills/dingtalk-basic-behavior/references/action-contract.md +2 -0
- package/skills/dingtalk-basic-behavior/references/memory-and-evolution.md +15 -1
- package/skills/dingtalk-basic-behavior/references/perception-and-gates.md +28 -0
- package/skills/dingtalk-basic-behavior/references/task-lifecycle.md +32 -7
- package/dist/src/boot.js +0 -70
- package/dist/src/boot.js.map +0 -1
- package/dist/src/duty.js +0 -74
- package/dist/src/duty.js.map +0 -1
- package/dist/src/kb.js +0 -240
- package/dist/src/kb.js.map +0 -1
- package/dist/src/runs.js +0 -79
- package/dist/src/runs.js.map +0 -1
- package/docs/ARCHITECTURE.md +0 -217
- package/docs/MINIMAL-WORKSPACE-V1.md +0 -172
- package/docs/OPEN-SOURCE-REFERENCES.md +0 -107
- package/docs/SELF-TEST.md +0 -252
- package/docs//345/206/205/347/275/221/345/256/236/347/233/270.md +0 -77
- package/evals/baselines/2026-07-14/behavior-summary.json +0 -28
- package/evals/baselines/2026-07-14/contract-summary.json +0 -18
- package/evals/baselines/2026-07-14/live-canary-summary.json +0 -25
- package/evals/baselines/2026-07-15/dingtalk-basic-behavior-0.3.0/SKILL.md +0 -72
- package/evals/baselines/2026-07-15/dingtalk-basic-behavior-0.3.0/references/action-contract.md +0 -31
- package/evals/baselines/2026-07-15/dingtalk-basic-behavior-0.3.0/references/event-to-behavior.md +0 -22
- package/evals/baselines/2026-07-15/dingtalk-basic-behavior-0.3.0/references/memory-and-evolution.md +0 -25
- package/evals/baselines/2026-07-15/dingtalk-basic-behavior-0.3.0/references/runtime-modes.md +0 -34
- package/evals/baselines/2026-07-15/task-lifecycle-summary.json +0 -50
- package/evals/evals.json +0 -316
- package/evals/fixtures/dm-ambiguous-send.json +0 -4
- package/evals/fixtures/dm-blocked.json +0 -4
- package/evals/fixtures/dm-clear.json +0 -4
- package/evals/fixtures/dm-discussion.json +0 -4
- package/evals/fixtures/dm-doc-write-no-tool.json +0 -4
- package/evals/fixtures/dm-long-task-ack.json +0 -4
- package/evals/fixtures/dm-nonblocking-gap.json +0 -4
- package/evals/fixtures/dm-structured-task.json +0 -4
- package/evals/fixtures/group.json +0 -10
- package/evals/fixtures/mentioned.json +0 -3
- package/evals/run-contract-evals.mjs +0 -1106
- package/evals/run-shadow-evals.mjs +0 -267
- package/evals/runners/README.md +0 -66
- package/evals/runners/claude-shadow.mjs +0 -533
- package/evals/schemas/action-request.schema.json +0 -77
- package/evals/shadow-evals.json +0 -133
- package/skills/AGENTS.md +0 -104
- package/skills//344/273/273/345/212/241.md +0 -48
- package/skills//345/237/272/347/241/200/350/241/214/344/270/272.md +0 -44
- package/skills//345/277/203/350/267/263.md +0 -79
- package/skills//346/266/210/346/201/257.md +0 -50
- package/skills//347/237/245/350/257/206.md +0 -55
- package/skills//350/257/204/346/265/213.md +0 -62
- package/skills//351/222/211/351/222/211.md +0 -64
- package/templates/ontology/index.md +0 -24
- package/templates/ontology/self/access.md +0 -38
- package/templates/ontology/self/role-spec.md +0 -34
- package/templates/ontology/self/workspace.md +0 -41
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmdirSync, rmSync, writeFileSync, } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
5
|
+
import { CURRENT_WORKSPACE_FILE, WORKSPACE_STATE_ROOT, inspectAgentProject, showDevelopmentWorkspace, } from './development-workspace.js';
|
|
6
|
+
import { digest, stableStringify } from './events.js';
|
|
7
|
+
import { prepareOpenCodeEvalAgent, runOpenCodeEvaluation, runOpenCodePrompt, } from './opencode-evals.js';
|
|
8
|
+
import { bindRequiredBasicSkill, verifyRequiredBasicSkill, } from './opencode-workspace.js';
|
|
9
|
+
export const OPENCODE_WORKSPACE_ROOT = '.dingtalk-agent/development-workspaces';
|
|
10
|
+
export const OPENCODE_EVIDENCE_ROOT = '.dingtalk-agent/development-workspace-evidence';
|
|
11
|
+
export function planOpenCodeWorkspace(start, name, cliVersion = '') {
|
|
12
|
+
const info = inspectAgentProject(start, cliVersion);
|
|
13
|
+
const workspace = requireOpenCodeWorkspace(info.root, name, cliVersion);
|
|
14
|
+
const target = managedWorkspacePath(info.root, name);
|
|
15
|
+
const artifactPath = artifactStoragePath(info.root, workspace);
|
|
16
|
+
const observedHash = existsSync(target) ? hashTree(target) : '';
|
|
17
|
+
const state = workspace.state;
|
|
18
|
+
const intact = Boolean(state && state.provider === 'opencode' &&
|
|
19
|
+
state.desiredHash === workspace.desiredHash && state.observedHash === observedHash &&
|
|
20
|
+
state.binding.managedPath === relative(info.root, target) &&
|
|
21
|
+
existsSync(artifactPath) && lstatSync(artifactPath).isDirectory());
|
|
22
|
+
const action = !existsSync(target) ? 'create' : intact ? 'noop' : 'rebuild';
|
|
23
|
+
const planId = `opencode_plan_${digest(stableStringify({
|
|
24
|
+
workspace: name, desiredHash: workspace.desiredHash, observedHash, action,
|
|
25
|
+
})).slice(0, 24)}`;
|
|
26
|
+
return {
|
|
27
|
+
$schema: 'dingtalk-agent/opencode-workspace-plan@1',
|
|
28
|
+
planId,
|
|
29
|
+
workspace: name,
|
|
30
|
+
provider: 'opencode',
|
|
31
|
+
model: workspace.provider.model,
|
|
32
|
+
action,
|
|
33
|
+
root: info.root,
|
|
34
|
+
managedPath: relative(info.root, target),
|
|
35
|
+
sourceHash: workspace.sourceHash,
|
|
36
|
+
desiredHash: workspace.desiredHash,
|
|
37
|
+
observedHash,
|
|
38
|
+
currentState: workspace.status,
|
|
39
|
+
writes: action === 'noop' ? [] : [
|
|
40
|
+
relative(info.root, target),
|
|
41
|
+
relative(info.root, artifactPath),
|
|
42
|
+
join(WORKSPACE_STATE_ROOT, `${name}.json`),
|
|
43
|
+
],
|
|
44
|
+
sideEffect: false,
|
|
45
|
+
dingtalkSideEffect: false,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function applyOpenCodeWorkspace(start, name, options = {}) {
|
|
49
|
+
if (!options.yes)
|
|
50
|
+
throw new Error('workspace create 会写本地 managed Workspace;必须显式传 --yes');
|
|
51
|
+
const cliVersion = options.cliVersion || '';
|
|
52
|
+
const plan = planOpenCodeWorkspace(start, name, cliVersion);
|
|
53
|
+
const workspace = requireOpenCodeWorkspace(plan.root, name, cliVersion);
|
|
54
|
+
const target = resolve(plan.root, plan.managedPath);
|
|
55
|
+
const artifactPath = artifactStoragePath(plan.root, workspace);
|
|
56
|
+
const artifactExisted = existsSync(artifactPath);
|
|
57
|
+
const command = options.command || process.env.DTA_OPENCODE_BIN || 'opencode';
|
|
58
|
+
if (plan.action === 'noop') {
|
|
59
|
+
const binding = workspace.state?.binding || {};
|
|
60
|
+
const stateStatus = workspace.state?.status === 'ready' ? 'ready' : 'verifying';
|
|
61
|
+
return {
|
|
62
|
+
...plan,
|
|
63
|
+
$schema: 'dingtalk-agent/opencode-workspace-apply@1',
|
|
64
|
+
applied: false,
|
|
65
|
+
idempotent: true,
|
|
66
|
+
status: stateStatus,
|
|
67
|
+
binding,
|
|
68
|
+
sideEffect: 'local-managed-workspace',
|
|
69
|
+
dingtalkSideEffect: false,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
73
|
+
const staging = `${target}.tmp-${process.pid}-${randomUUID().slice(0, 8)}`;
|
|
74
|
+
const backup = `${target}.backup-${process.pid}-${randomUUID().slice(0, 8)}`;
|
|
75
|
+
const preflightSandbox = mkdtempSync(join(tmpdir(), `dta-opencode-workspace-preflight-${safeName(name)}-`));
|
|
76
|
+
let preflight = null;
|
|
77
|
+
try {
|
|
78
|
+
mkdirSync(staging, { recursive: false });
|
|
79
|
+
materializeProject(plan.root, staging, workspace);
|
|
80
|
+
prepareOpenCodeEvalAgent(staging, 'none');
|
|
81
|
+
bindRequiredBasicSkill(staging);
|
|
82
|
+
cpSync(staging, preflightSandbox, { recursive: true });
|
|
83
|
+
preflight = verifyRequiredBasicSkill(bindRequiredBasicSkill(preflightSandbox), command);
|
|
84
|
+
if (existsSync(target))
|
|
85
|
+
renameSync(target, backup);
|
|
86
|
+
renameSync(staging, target);
|
|
87
|
+
mkdirSync(artifactPath, { recursive: true });
|
|
88
|
+
if (existsSync(backup))
|
|
89
|
+
rmSync(backup, { recursive: true, force: true });
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
rmSync(staging, { recursive: true, force: true });
|
|
93
|
+
if (existsSync(backup)) {
|
|
94
|
+
rmSync(target, { recursive: true, force: true });
|
|
95
|
+
renameSync(backup, target);
|
|
96
|
+
}
|
|
97
|
+
else if (existsSync(target) && plan.action === 'create') {
|
|
98
|
+
rmSync(target, { recursive: true, force: true });
|
|
99
|
+
}
|
|
100
|
+
if (!artifactExisted && existsSync(artifactPath)) {
|
|
101
|
+
try {
|
|
102
|
+
rmdirSync(artifactPath);
|
|
103
|
+
}
|
|
104
|
+
catch { /* preserve non-empty concurrent writes */ }
|
|
105
|
+
}
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
rmSync(preflightSandbox, { recursive: true, force: true });
|
|
110
|
+
}
|
|
111
|
+
const observedHash = hashTree(target);
|
|
112
|
+
const binding = {
|
|
113
|
+
managedPath: relative(plan.root, target),
|
|
114
|
+
model: workspace.provider.model,
|
|
115
|
+
sourceHash: workspace.sourceHash,
|
|
116
|
+
basicHash: String(preflight?.skill.hash || ''),
|
|
117
|
+
basicVersion: String(preflight?.skill.version || ''),
|
|
118
|
+
configHash: String(preflight?.configHash || ''),
|
|
119
|
+
openCodeVersion: String(preflight?.openCodeVersion || ''),
|
|
120
|
+
};
|
|
121
|
+
writeWorkspaceState(plan.root, {
|
|
122
|
+
$schema: 'dingtalk-agent/workspace-state@1',
|
|
123
|
+
workspace: name,
|
|
124
|
+
provider: 'opencode',
|
|
125
|
+
status: 'verifying',
|
|
126
|
+
binding,
|
|
127
|
+
desiredHash: workspace.desiredHash,
|
|
128
|
+
observedHash,
|
|
129
|
+
lastPlanId: plan.planId,
|
|
130
|
+
lastReceiptId: '',
|
|
131
|
+
lastEvalId: '',
|
|
132
|
+
});
|
|
133
|
+
return {
|
|
134
|
+
...plan,
|
|
135
|
+
$schema: 'dingtalk-agent/opencode-workspace-apply@1',
|
|
136
|
+
applied: true,
|
|
137
|
+
idempotent: false,
|
|
138
|
+
status: 'verifying',
|
|
139
|
+
observedHash,
|
|
140
|
+
binding,
|
|
141
|
+
sideEffect: 'local-managed-workspace',
|
|
142
|
+
dingtalkSideEffect: false,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export function useOpenCodeWorkspace(start, name, cliVersion = '') {
|
|
146
|
+
const info = inspectAgentProject(start, cliVersion);
|
|
147
|
+
const workspace = requireOpenCodeWorkspace(info.root, name, cliVersion);
|
|
148
|
+
assertManagedWorkspaceIntact(info.root, workspace);
|
|
149
|
+
const path = join(info.root, CURRENT_WORKSPACE_FILE);
|
|
150
|
+
atomicText(path, `${name}\n`);
|
|
151
|
+
const readback = readFileSync(path, 'utf8').trim();
|
|
152
|
+
if (readback !== name)
|
|
153
|
+
throw new Error('current-workspace 写后回读不一致');
|
|
154
|
+
return {
|
|
155
|
+
$schema: 'dingtalk-agent/workspace-selection@1',
|
|
156
|
+
workspace: name,
|
|
157
|
+
provider: 'opencode',
|
|
158
|
+
previous: info.currentWorkspace,
|
|
159
|
+
current: readback,
|
|
160
|
+
sideEffect: 'local-selection',
|
|
161
|
+
dingtalkSideEffect: false,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
export function runOpenCodeWorkspace(start, name, prompt, options = {}) {
|
|
165
|
+
if (!prompt.trim())
|
|
166
|
+
throw new Error('workspace run prompt 不能为空');
|
|
167
|
+
const info = inspectAgentProject(start);
|
|
168
|
+
const workspace = requireOpenCodeWorkspace(info.root, name);
|
|
169
|
+
const managed = assertManagedWorkspaceIntact(info.root, workspace);
|
|
170
|
+
const timeoutMs = options.timeoutMs ?? 120_000;
|
|
171
|
+
if (!Number.isInteger(timeoutMs) || timeoutMs < 10_000 || timeoutMs > 300_000) {
|
|
172
|
+
throw new Error('workspace run timeoutMs 必须为 10000..300000');
|
|
173
|
+
}
|
|
174
|
+
const plan = {
|
|
175
|
+
$schema: 'dingtalk-agent/opencode-workspace-run-plan@1',
|
|
176
|
+
workspace: name,
|
|
177
|
+
provider: 'opencode',
|
|
178
|
+
model: workspace.provider.model,
|
|
179
|
+
desiredHash: workspace.desiredHash,
|
|
180
|
+
observedHash: workspace.observedHash,
|
|
181
|
+
promptHash: sha256(prompt),
|
|
182
|
+
loadProbe: 'random-per-run',
|
|
183
|
+
tools: 'none',
|
|
184
|
+
sideEffect: 'model-only',
|
|
185
|
+
dingtalkSideEffect: false,
|
|
186
|
+
};
|
|
187
|
+
if (!options.execute)
|
|
188
|
+
return { ...plan, ready: true, executeRequired: true };
|
|
189
|
+
if (!options.yes)
|
|
190
|
+
throw new Error('workspace run 会调用 OpenCode 模型;必须同时传 --execute --yes');
|
|
191
|
+
const runId = `opencode_workspace_run_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
192
|
+
const evidence = safeProjectPath(info.root, options.out || join(OPENCODE_EVIDENCE_ROOT, name, 'runs', runId), false);
|
|
193
|
+
const sandbox = mkdtempSync(join(tmpdir(), `dta-opencode-workspace-${safeName(name)}-`));
|
|
194
|
+
const command = options.command || process.env.DTA_OPENCODE_BIN || 'opencode';
|
|
195
|
+
let report;
|
|
196
|
+
try {
|
|
197
|
+
cpSync(managed, sandbox, { recursive: true });
|
|
198
|
+
const probe = randomUUID();
|
|
199
|
+
const skillPath = join(sandbox, '.agents', 'skills', 'dingtalk-basic-behavior', 'SKILL.md');
|
|
200
|
+
const skillBody = readFileSync(skillPath, 'utf8');
|
|
201
|
+
writeFileSync(skillPath, `${skillBody.trimEnd()}\n\n<!-- dta-load-probe:${probe} -->\n`);
|
|
202
|
+
const preflight = verifyRequiredBasicSkill(bindRequiredBasicSkill(sandbox), command);
|
|
203
|
+
const probePrompt = '这是加载链路探针。只依据 Basic Skill 正文末尾注释回答;严格输出 `dta-load-probe=<值>`;' +
|
|
204
|
+
'若看不到则输出 `dta-load-probe=not-loaded`。禁止调用工具或解释。';
|
|
205
|
+
const probeExecution = runOpenCodePrompt(command, sandbox, workspace.provider.model, probePrompt, `DTA Workspace ${name} load probe`, timeoutMs);
|
|
206
|
+
const exactProbe = `dta-load-probe=${probe}`;
|
|
207
|
+
const loadPassed = probeExecution.exitCode === 0 && probeExecution.answer.trim() === exactProbe &&
|
|
208
|
+
probeExecution.toolCalls === 0 && probeExecution.directoryMatched;
|
|
209
|
+
const marker = `[DTA-WORKSPACE-RUN-${safeName(name)}-${randomUUID()}]`;
|
|
210
|
+
const execution = loadPassed ? runOpenCodePrompt(command, sandbox, workspace.provider.model, `${marker}\n执行协议:第一行逐字符原样输出 ${marker};从第二行回答用户任务;禁止调用任何工具。\n${prompt}`, `DTA Workspace ${name} run`, timeoutMs) : emptyExecution('load-probe-failed');
|
|
211
|
+
const exactAttributed = execution.answer.startsWith(marker);
|
|
212
|
+
const answer = exactAttributed ? execution.answer.slice(marker.length).trim() : execution.answer;
|
|
213
|
+
const passed = loadPassed && execution.exitCode === 0 && execution.toolCalls === 0 &&
|
|
214
|
+
execution.directoryMatched && exactAttributed;
|
|
215
|
+
report = {
|
|
216
|
+
$schema: 'dingtalk-agent/opencode-workspace-run@1',
|
|
217
|
+
passed,
|
|
218
|
+
runId,
|
|
219
|
+
workspace: name,
|
|
220
|
+
provider: 'opencode',
|
|
221
|
+
model: workspace.provider.model,
|
|
222
|
+
sourceHash: workspace.sourceHash,
|
|
223
|
+
desiredHash: workspace.desiredHash,
|
|
224
|
+
observedHash: workspace.observedHash,
|
|
225
|
+
evidencePath: relative(info.root, evidence),
|
|
226
|
+
basic: {
|
|
227
|
+
version: preflight.skill.version,
|
|
228
|
+
sourceHash: workspace.state?.binding.basicHash || '',
|
|
229
|
+
instrumentedHash: preflight.skill.hash,
|
|
230
|
+
},
|
|
231
|
+
loadProbe: executionSummary(probeExecution, {
|
|
232
|
+
expected: exactProbe, exactLoaded: probeExecution.answer.trim() === exactProbe,
|
|
233
|
+
}),
|
|
234
|
+
execution: executionSummary(execution, { marker, exactAttributed, answer }),
|
|
235
|
+
sideEffect: 'model-only',
|
|
236
|
+
dingtalkSideEffect: false,
|
|
237
|
+
};
|
|
238
|
+
mkdirSync(evidence, { recursive: true });
|
|
239
|
+
writeFileSync(join(evidence, 'prompt.txt'), prompt);
|
|
240
|
+
writeFileSync(join(evidence, 'load-probe.stdout.ndjson'), probeExecution.stdout);
|
|
241
|
+
writeFileSync(join(evidence, 'run.stdout.ndjson'), execution.stdout);
|
|
242
|
+
atomicJson(join(evidence, 'report.json'), report);
|
|
243
|
+
writeProviderOutcome(info.root, workspace, passed ? 'ready' : 'failed', {
|
|
244
|
+
lastReceiptId: runId,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
report = {
|
|
249
|
+
...plan,
|
|
250
|
+
$schema: 'dingtalk-agent/opencode-workspace-run@1',
|
|
251
|
+
passed: false,
|
|
252
|
+
runId,
|
|
253
|
+
evidencePath: relative(info.root, evidence),
|
|
254
|
+
failure: error.message,
|
|
255
|
+
};
|
|
256
|
+
mkdirSync(evidence, { recursive: true });
|
|
257
|
+
atomicJson(join(evidence, 'report.json'), report);
|
|
258
|
+
writeProviderOutcome(info.root, workspace, 'failed', { lastReceiptId: runId });
|
|
259
|
+
}
|
|
260
|
+
finally {
|
|
261
|
+
rmSync(sandbox, { recursive: true, force: true });
|
|
262
|
+
}
|
|
263
|
+
return report;
|
|
264
|
+
}
|
|
265
|
+
export function evalOpenCodeWorkspace(start, name, suite, options = {}) {
|
|
266
|
+
const info = inspectAgentProject(start);
|
|
267
|
+
const workspace = requireOpenCodeWorkspace(info.root, name);
|
|
268
|
+
const managed = assertManagedWorkspaceIntact(info.root, workspace);
|
|
269
|
+
const selectedOut = options.out || join(OPENCODE_EVIDENCE_ROOT, name, 'evals', `opencode_eval_${Date.now()}_${randomUUID().slice(0, 8)}`);
|
|
270
|
+
const report = runOpenCodeEvaluation(info.root, relative(info.root, managed), suite, {
|
|
271
|
+
...options,
|
|
272
|
+
model: workspace.provider.model,
|
|
273
|
+
out: selectedOut,
|
|
274
|
+
});
|
|
275
|
+
if (!options.execute) {
|
|
276
|
+
return {
|
|
277
|
+
$schema: 'dingtalk-agent/opencode-workspace-eval-plan@1',
|
|
278
|
+
workspace: name,
|
|
279
|
+
provider: 'opencode',
|
|
280
|
+
sourceHash: workspace.sourceHash,
|
|
281
|
+
desiredHash: workspace.desiredHash,
|
|
282
|
+
observedHash: workspace.observedHash,
|
|
283
|
+
report,
|
|
284
|
+
sideEffect: report.sideEffect,
|
|
285
|
+
dingtalkSideEffect: false,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
const passed = report.passed === true && report.summary?.loadGate === true &&
|
|
289
|
+
report.summary?.hardGate === true;
|
|
290
|
+
const evalBinding = bindEvalEvidence(info.root, workspace, report);
|
|
291
|
+
writeProviderOutcome(info.root, workspace, passed ? 'ready' : 'failed', {
|
|
292
|
+
lastEvalId: String(report.runId || ''),
|
|
293
|
+
binding: evalBinding,
|
|
294
|
+
});
|
|
295
|
+
return {
|
|
296
|
+
$schema: 'dingtalk-agent/opencode-workspace-eval@1',
|
|
297
|
+
workspace: name,
|
|
298
|
+
provider: 'opencode',
|
|
299
|
+
sourceHash: workspace.sourceHash,
|
|
300
|
+
desiredHash: workspace.desiredHash,
|
|
301
|
+
observedHash: workspace.observedHash,
|
|
302
|
+
passed,
|
|
303
|
+
report,
|
|
304
|
+
sideEffect: report.sideEffect,
|
|
305
|
+
dingtalkSideEffect: false,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function materializeProject(root, target, workspace) {
|
|
309
|
+
const info = inspectAgentProject(root);
|
|
310
|
+
copyProjectEntry(root, target, info.project.definition);
|
|
311
|
+
if (existsSync(join(root, 'opencode.json')))
|
|
312
|
+
copyProjectEntry(root, target, 'opencode.json');
|
|
313
|
+
for (const name of info.project.skills) {
|
|
314
|
+
const source = `skills/${name}`;
|
|
315
|
+
if (existsSync(join(root, source)))
|
|
316
|
+
copyProjectEntry(root, target, source);
|
|
317
|
+
copyProjectEntry(root, target, `.agents/skills/${name}`);
|
|
318
|
+
}
|
|
319
|
+
for (const route of [workspace.storage.memory, workspace.storage.knowledge]) {
|
|
320
|
+
if (!route.startsWith('local-md:'))
|
|
321
|
+
continue;
|
|
322
|
+
copyProjectEntry(root, target, route.slice('local-md:'.length));
|
|
323
|
+
}
|
|
324
|
+
bindDefinitionInstruction(target, info.project.definition);
|
|
325
|
+
}
|
|
326
|
+
function bindDefinitionInstruction(target, definition) {
|
|
327
|
+
const path = join(target, 'opencode.json');
|
|
328
|
+
const config = existsSync(path) ? JSON.parse(readFileSync(path, 'utf8')) : {};
|
|
329
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) {
|
|
330
|
+
throw new Error('opencode.json 必须是 JSON object');
|
|
331
|
+
}
|
|
332
|
+
const instructions = Array.isArray(config.instructions)
|
|
333
|
+
? config.instructions.filter((item) => typeof item === 'string') : [];
|
|
334
|
+
config.instructions = [definition, ...instructions.filter((item) => item !== definition)];
|
|
335
|
+
atomicJson(path, config);
|
|
336
|
+
}
|
|
337
|
+
function copyProjectEntry(root, target, ref) {
|
|
338
|
+
const source = safeProjectPath(root, ref, true);
|
|
339
|
+
const destination = safeTargetPath(target, ref);
|
|
340
|
+
if (lstatSync(source).isSymbolicLink())
|
|
341
|
+
throw new Error(`Project source 不允许符号链接: ${ref}`);
|
|
342
|
+
mkdirSync(dirname(destination), { recursive: true });
|
|
343
|
+
cpSync(source, destination, {
|
|
344
|
+
recursive: true,
|
|
345
|
+
filter: (path) => !lstatSync(path).isSymbolicLink(),
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
function requireOpenCodeWorkspace(start, name, cliVersion = '') {
|
|
349
|
+
const workspace = showDevelopmentWorkspace(start, name, cliVersion);
|
|
350
|
+
if (workspace.provider.kind !== 'opencode' || workspace.legacy) {
|
|
351
|
+
throw new Error(`Workspace ${name} 不是 opencode Provider;W2 不执行 ${workspace.provider.kind}`);
|
|
352
|
+
}
|
|
353
|
+
return workspace;
|
|
354
|
+
}
|
|
355
|
+
function assertManagedWorkspaceIntact(root, workspace) {
|
|
356
|
+
const target = managedWorkspacePath(root, workspace.name);
|
|
357
|
+
if (!existsSync(target) || !workspace.state) {
|
|
358
|
+
throw new Error(`Workspace ${workspace.name} 尚未 materialize;先执行 workspace create ${workspace.name} --yes`);
|
|
359
|
+
}
|
|
360
|
+
const expectedRelative = relative(root, target);
|
|
361
|
+
const actualHash = hashTree(target);
|
|
362
|
+
const failures = [];
|
|
363
|
+
if (workspace.state.provider !== 'opencode')
|
|
364
|
+
failures.push('provider');
|
|
365
|
+
if (workspace.state.binding.managedPath !== expectedRelative)
|
|
366
|
+
failures.push('managedPath');
|
|
367
|
+
if (workspace.state.binding.sourceHash !== workspace.sourceHash)
|
|
368
|
+
failures.push('sourceHash');
|
|
369
|
+
if (workspace.state.desiredHash !== workspace.desiredHash)
|
|
370
|
+
failures.push('desiredHash');
|
|
371
|
+
if (workspace.state.observedHash !== actualHash)
|
|
372
|
+
failures.push('observedHash');
|
|
373
|
+
if (failures.length) {
|
|
374
|
+
throw new Error(`Workspace ${workspace.name} managed state 漂移: ${failures.join(', ')}`);
|
|
375
|
+
}
|
|
376
|
+
return target;
|
|
377
|
+
}
|
|
378
|
+
function writeProviderOutcome(root, workspace, status, patch) {
|
|
379
|
+
if (!workspace.state)
|
|
380
|
+
throw new Error('Provider outcome 缺少 Workspace state');
|
|
381
|
+
const target = assertManagedWorkspaceIntact(root, workspace);
|
|
382
|
+
writeWorkspaceState(root, {
|
|
383
|
+
...workspace.state,
|
|
384
|
+
status,
|
|
385
|
+
binding: { ...workspace.state.binding, ...(patch.binding || {}) },
|
|
386
|
+
observedHash: hashTree(target),
|
|
387
|
+
lastReceiptId: patch.lastReceiptId ?? workspace.state.lastReceiptId,
|
|
388
|
+
lastEvalId: patch.lastEvalId ?? workspace.state.lastEvalId,
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
function bindEvalEvidence(root, workspace, report) {
|
|
392
|
+
const runId = String(report.runId || '');
|
|
393
|
+
const evidencePath = String(report.evidencePath || '');
|
|
394
|
+
if (!runId || !evidencePath || report.$schema !== 'dingtalk-agent/opencode-eval-report@1') {
|
|
395
|
+
throw new Error('OpenCode Eval report 缺少可绑定的 runId/evidencePath/schema');
|
|
396
|
+
}
|
|
397
|
+
const evidenceRoot = safeProjectPath(root, evidencePath, true);
|
|
398
|
+
if (!lstatSync(evidenceRoot).isDirectory() || lstatSync(evidenceRoot).isSymbolicLink()) {
|
|
399
|
+
throw new Error('OpenCode Eval evidence root 必须是 Project 内真实目录');
|
|
400
|
+
}
|
|
401
|
+
const planPath = safeProjectPath(root, join(evidencePath, 'plan.json'), true);
|
|
402
|
+
const suitePath = safeProjectPath(root, join(evidencePath, 'suite.json'), true);
|
|
403
|
+
const reportPath = safeProjectPath(root, join(evidencePath, 'report.json'), true);
|
|
404
|
+
const plan = JSON.parse(readFileSync(planPath, 'utf8'));
|
|
405
|
+
const suite = JSON.parse(readFileSync(suitePath, 'utf8'));
|
|
406
|
+
const persistedReport = JSON.parse(readFileSync(reportPath, 'utf8'));
|
|
407
|
+
if (stableStringify(persistedReport) !== stableStringify(report) ||
|
|
408
|
+
String(persistedReport.runId || '') !== runId ||
|
|
409
|
+
String(plan.suite || '') !== String(suite.id || '')) {
|
|
410
|
+
throw new Error('OpenCode Eval evidence 写后回读与内存 report/suite 不一致');
|
|
411
|
+
}
|
|
412
|
+
const target = assertManagedWorkspaceIntact(root, workspace);
|
|
413
|
+
return {
|
|
414
|
+
evalRunId: runId,
|
|
415
|
+
evalEvidencePath: evidencePath,
|
|
416
|
+
evalPlanHash: sha256(readFileSync(planPath)),
|
|
417
|
+
evalSuiteHash: digest(stableStringify(suite)),
|
|
418
|
+
evalReportHash: sha256(readFileSync(reportPath)),
|
|
419
|
+
evalSuiteId: String(suite.id || ''),
|
|
420
|
+
evalModel: String(report.engine?.model || ''),
|
|
421
|
+
evalSourceHash: workspace.sourceHash,
|
|
422
|
+
evalDesiredHash: workspace.desiredHash,
|
|
423
|
+
evalObservedHash: hashTree(target),
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
function writeWorkspaceState(root, state) {
|
|
427
|
+
const path = join(root, WORKSPACE_STATE_ROOT, `${state.workspace}.json`);
|
|
428
|
+
atomicJson(path, state);
|
|
429
|
+
const readback = JSON.parse(readFileSync(path, 'utf8'));
|
|
430
|
+
if (stableStringify(readback) !== stableStringify(state)) {
|
|
431
|
+
throw new Error(`Workspace state 写后回读不一致: ${state.workspace}`);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
function managedWorkspacePath(root, name) {
|
|
435
|
+
return safeProjectPath(root, join(OPENCODE_WORKSPACE_ROOT, safeName(name)), false);
|
|
436
|
+
}
|
|
437
|
+
function artifactStoragePath(root, workspace) {
|
|
438
|
+
const route = workspace.storage.artifacts;
|
|
439
|
+
if (!route.startsWith('local-dir:')) {
|
|
440
|
+
throw new Error(`Workspace ${workspace.name} Artifact route 必须是 local-dir`);
|
|
441
|
+
}
|
|
442
|
+
return safeProjectPath(root, route.slice('local-dir:'.length), false);
|
|
443
|
+
}
|
|
444
|
+
function hashTree(root) {
|
|
445
|
+
const rootReal = realpathSync(resolve(root));
|
|
446
|
+
const entries = [];
|
|
447
|
+
const visit = (directory, prefix = '') => {
|
|
448
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })
|
|
449
|
+
.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
450
|
+
const path = join(directory, entry.name);
|
|
451
|
+
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
452
|
+
if (entry.isSymbolicLink())
|
|
453
|
+
throw new Error(`Managed Workspace 不允许符号链接: ${rel}`);
|
|
454
|
+
if (entry.isDirectory())
|
|
455
|
+
visit(path, rel);
|
|
456
|
+
else if (entry.isFile())
|
|
457
|
+
entries.push({ path: rel, hash: sha256(readFileSync(path)) });
|
|
458
|
+
else
|
|
459
|
+
throw new Error(`Managed Workspace 包含特殊文件: ${rel}`);
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
visit(rootReal);
|
|
463
|
+
return digest(stableStringify(entries));
|
|
464
|
+
}
|
|
465
|
+
function safeProjectPath(root, ref, mustExist) {
|
|
466
|
+
const rootReal = realpathSync(resolve(root));
|
|
467
|
+
const candidate = resolve(rootReal, ref);
|
|
468
|
+
const rel = relative(rootReal, candidate);
|
|
469
|
+
if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`)) {
|
|
470
|
+
throw new Error(`OpenCode Provider 路径必须位于 Project 内: ${ref}`);
|
|
471
|
+
}
|
|
472
|
+
if (mustExist && !existsSync(candidate))
|
|
473
|
+
throw new Error(`Project source 不存在: ${ref}`);
|
|
474
|
+
if (mustExist && realpathSync(candidate) !== candidate && !isInside(rootReal, realpathSync(candidate))) {
|
|
475
|
+
throw new Error(`Project source 真实路径越界: ${ref}`);
|
|
476
|
+
}
|
|
477
|
+
return candidate;
|
|
478
|
+
}
|
|
479
|
+
function safeTargetPath(target, ref) {
|
|
480
|
+
const candidate = resolve(target, ref);
|
|
481
|
+
if (!isInside(resolve(target), candidate) || candidate === resolve(target)) {
|
|
482
|
+
throw new Error(`Materialized path 必须位于 Workspace 内: ${ref}`);
|
|
483
|
+
}
|
|
484
|
+
return candidate;
|
|
485
|
+
}
|
|
486
|
+
function executionSummary(execution, extra) {
|
|
487
|
+
return {
|
|
488
|
+
answer: execution.answer,
|
|
489
|
+
rawAnswer: execution.answer,
|
|
490
|
+
...extra,
|
|
491
|
+
exitCode: execution.exitCode,
|
|
492
|
+
sessionId: execution.sessionId,
|
|
493
|
+
sessionDirectory: execution.sessionDirectory,
|
|
494
|
+
directoryMatched: execution.directoryMatched,
|
|
495
|
+
toolCalls: execution.toolCalls,
|
|
496
|
+
toolNames: execution.toolNames,
|
|
497
|
+
tokens: execution.tokens,
|
|
498
|
+
cost: execution.cost,
|
|
499
|
+
durationMs: execution.durationMs,
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
function emptyExecution(reason) {
|
|
503
|
+
return {
|
|
504
|
+
exitCode: null, stdout: '', stderr: reason, answer: '', sessionId: '', toolCalls: 0,
|
|
505
|
+
toolNames: [], toolPaths: [], toolTrace: [], tokens: null, cost: null, durationMs: 0,
|
|
506
|
+
directoryMatched: false, sessionDirectory: '',
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
function atomicJson(path, value) {
|
|
510
|
+
atomicText(path, JSON.stringify(value, null, 2) + '\n');
|
|
511
|
+
}
|
|
512
|
+
function atomicText(path, body) {
|
|
513
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
514
|
+
const temporary = `${path}.${process.pid}.${randomUUID().slice(0, 8)}.tmp`;
|
|
515
|
+
writeFileSync(temporary, body, { flag: 'wx' });
|
|
516
|
+
renameSync(temporary, path);
|
|
517
|
+
}
|
|
518
|
+
function sha256(value) {
|
|
519
|
+
return createHash('sha256').update(value).digest('hex');
|
|
520
|
+
}
|
|
521
|
+
function safeName(value) {
|
|
522
|
+
if (!/^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/.test(value)) {
|
|
523
|
+
throw new Error(`Workspace name 非法: ${value}`);
|
|
524
|
+
}
|
|
525
|
+
return value;
|
|
526
|
+
}
|
|
527
|
+
function isInside(root, candidate) {
|
|
528
|
+
const rel = relative(root, candidate);
|
|
529
|
+
return rel === '' || (rel !== '..' && !rel.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`));
|
|
530
|
+
}
|
|
531
|
+
//# sourceMappingURL=opencode-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode-provider.js","sourceRoot":"","sources":["../../src/opencode-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EACL,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAChF,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAC3D,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC5D,OAAO,EACL,sBAAsB,EAAE,oBAAoB,EAC5C,mBAAmB,EAAE,wBAAwB,GAE9C,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EACL,wBAAwB,EAAE,qBAAqB,EAAE,iBAAiB,GAEnE,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,sBAAsB,EAAE,wBAAwB,GACjD,MAAM,yBAAyB,CAAA;AAEhC,MAAM,CAAC,MAAM,uBAAuB,GAAG,wCAAwC,CAAA;AAC/E,MAAM,CAAC,MAAM,sBAAsB,GAAG,gDAAgD,CAAA;AAyCtF,MAAM,UAAU,qBAAqB,CACnC,KAAa,EAAE,IAAY,EAAE,UAAU,GAAG,EAAE;IAE5C,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;IACnD,MAAM,SAAS,GAAG,wBAAwB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;IACvE,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IACpD,MAAM,YAAY,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAC9D,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC/D,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAA;IAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,KAAK,UAAU;QAC3D,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,WAAW,IAAI,KAAK,CAAC,YAAY,KAAK,YAAY;QAClF,KAAK,CAAC,OAAO,CAAC,WAAW,KAAK,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;QACzD,UAAU,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC,CAAA;IACpE,MAAM,MAAM,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;IAC3E,MAAM,MAAM,GAAG,iBAAiB,MAAM,CAAC,eAAe,CAAC;QACrD,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC,WAAW,EAAE,YAAY,EAAE,MAAM;KAC1E,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAA;IAClB,OAAO;QACL,OAAO,EAAE,0CAA0C;QACnD,MAAM;QACN,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK;QAC/B,MAAM;QACN,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;QACxC,UAAU,EAAE,SAAS,CAAC,UAAU;QAChC,WAAW,EAAE,SAAS,CAAC,WAAW;QAClC,YAAY;QACZ,YAAY,EAAE,SAAS,CAAC,MAAM;QAC9B,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/B,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;YAC3B,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;YACjC,IAAI,CAAC,oBAAoB,EAAE,GAAG,IAAI,OAAO,CAAC;SAC3C;QACD,UAAU,EAAE,KAAK;QACjB,kBAAkB,EAAE,KAAK;KAC1B,CAAA;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,KAAa,EACb,IAAY,EACZ,UAAoE,EAAE;IAEtE,IAAI,CAAC,OAAO,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAA;IACxF,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAA;IAC3C,MAAM,IAAI,GAAG,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;IAC3D,MAAM,SAAS,GAAG,wBAAwB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;IACnD,MAAM,YAAY,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAC9D,MAAM,eAAe,GAAG,UAAU,CAAC,YAAY,CAAC,CAAA;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,UAAU,CAAA;IAC7E,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAA;QAC9C,MAAM,WAAW,GAAG,SAAS,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAA;QAC/E,OAAO;YACL,GAAG,IAAI;YACP,OAAO,EAAE,2CAA2C;YACpD,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,WAAW;YACnB,OAAO;YACP,UAAU,EAAE,yBAAyB;YACrC,kBAAkB,EAAE,KAAK;SAC1B,CAAA;IACH,CAAC;IAED,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC/C,MAAM,OAAO,GAAG,GAAG,MAAM,QAAQ,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;IAC1E,MAAM,MAAM,GAAG,GAAG,MAAM,WAAW,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;IAC5E,MAAM,gBAAgB,GAAG,WAAW,CAAC,IAAI,CACvC,MAAM,EAAE,EAAE,oCAAoC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAChE,CAAC,CAAA;IACF,IAAI,SAAS,GAAkC,IAAI,CAAA;IACnD,IAAI,CAAC;QACH,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAA;QACxC,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,CAAA;QACjD,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACzC,sBAAsB,CAAC,OAAO,CAAC,CAAA;QAC/B,MAAM,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACtD,SAAS,GAAG,wBAAwB,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC,CAAA;QACvF,IAAI,UAAU,CAAC,MAAM,CAAC;YAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAClD,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC3B,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC5C,IAAI,UAAU,CAAC,MAAM,CAAC;YAAE,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QACjD,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;YAChD,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC5B,CAAC;aAAM,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC1D,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAClD,CAAC;QACD,IAAI,CAAC,eAAe,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YACjD,IAAI,CAAC;gBAAC,SAAS,CAAC,YAAY,CAAC,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,0CAA0C,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAC5D,CAAC;IAED,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IACrC,MAAM,OAAO,GAAG;QACd,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;QACxC,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK;QAC/B,UAAU,EAAE,SAAS,CAAC,UAAU;QAChC,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QAC9C,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;QACpD,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,UAAU,IAAI,EAAE,CAAC;QAC/C,eAAe,EAAE,MAAM,CAAC,SAAS,EAAE,eAAe,IAAI,EAAE,CAAC;KAC1D,CAAA;IACD,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE;QAC7B,OAAO,EAAE,kCAAkC;QAC3C,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,WAAW;QACnB,OAAO;QACP,WAAW,EAAE,SAAS,CAAC,WAAW;QAClC,YAAY;QACZ,UAAU,EAAE,IAAI,CAAC,MAAM;QACvB,aAAa,EAAE,EAAE;QACjB,UAAU,EAAE,EAAE;KACf,CAAC,CAAA;IACF,OAAO;QACL,GAAG,IAAI;QACP,OAAO,EAAE,2CAA2C;QACpD,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,WAAW;QACnB,YAAY;QACZ,OAAO;QACP,UAAU,EAAE,yBAAyB;QACrC,kBAAkB,EAAE,KAAK;KAC1B,CAAA;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAa,EAAE,IAAY,EAAE,UAAU,GAAG,EAAE;IAC/E,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;IACnD,MAAM,SAAS,GAAG,wBAAwB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;IACvE,4BAA4B,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAA;IACpD,UAAU,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,CAAA;IAC7B,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAA;IAClD,IAAI,QAAQ,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;IACnE,OAAO;QACL,OAAO,EAAE,sCAAsC;QAC/C,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,IAAI,CAAC,gBAAgB;QAC/B,OAAO,EAAE,QAAQ;QACjB,UAAU,EAAE,iBAAiB;QAC7B,kBAAkB,EAAE,KAAK;KAC1B,CAAA;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,KAAa,EACb,IAAY,EACZ,MAAc,EACd,UAAuC,EAAE;IAEzC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;IAChE,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;IACvC,MAAM,SAAS,GAAG,wBAAwB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAC3D,MAAM,OAAO,GAAG,4BAA4B,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAClE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAA;IAC9C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,MAAM,IAAI,SAAS,GAAG,OAAO,EAAE,CAAC;QAC9E,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9D,CAAC;IACD,MAAM,IAAI,GAAG;QACX,OAAO,EAAE,8CAA8C;QACvD,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK;QAC/B,WAAW,EAAE,SAAS,CAAC,WAAW;QAClC,YAAY,EAAE,SAAS,CAAC,YAAY;QACpC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC;QAC1B,SAAS,EAAE,gBAAgB;QAC3B,KAAK,EAAE,MAAM;QACb,UAAU,EAAE,YAAY;QACxB,kBAAkB,EAAE,KAAK;KAC1B,CAAA;IACD,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,CAAA;IAC5E,IAAI,CAAC,OAAO,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAA;IAExF,MAAM,KAAK,GAAG,0BAA0B,IAAI,CAAC,GAAG,EAAE,IAAI,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;IAChF,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,IAAI,IAAI,CAC7D,sBAAsB,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAA;IACtD,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,0BAA0B,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IACxF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,UAAU,CAAA;IAC7E,IAAI,MAA2B,CAAA;IAC/B,IAAI,CAAC;QACH,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7C,MAAM,KAAK,GAAG,UAAU,EAAE,CAAA;QAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,yBAAyB,EAAE,UAAU,CAAC,CAAA;QAC3F,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QACjD,aAAa,CAAC,SAAS,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,2BAA2B,KAAK,QAAQ,CAAC,CAAA;QACxF,MAAM,SAAS,GAAG,wBAAwB,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAA;QACpF,MAAM,WAAW,GACf,8DAA8D;YAC9D,gDAAgD,CAAA;QAClD,MAAM,cAAc,GAAG,iBAAiB,CACtC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,EACvD,iBAAiB,IAAI,aAAa,EAAE,SAAS,CAC9C,CAAA;QACD,MAAM,UAAU,GAAG,kBAAkB,KAAK,EAAE,CAAA;QAC5C,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,KAAK,CAAC,IAAI,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,UAAU;YAC7F,cAAc,CAAC,SAAS,KAAK,CAAC,IAAI,cAAc,CAAC,gBAAgB,CAAA;QACnE,MAAM,MAAM,GAAG,sBAAsB,QAAQ,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,GAAG,CAAA;QACtE,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,iBAAiB,CAC9C,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,EAC1C,GAAG,MAAM,qBAAqB,MAAM,0BAA0B,MAAM,EAAE,EACtE,iBAAiB,IAAI,MAAM,EAAE,SAAS,CACvC,CAAC,CAAC,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAA;QACvC,MAAM,eAAe,GAAG,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;QAC3D,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAA;QAChG,MAAM,MAAM,GAAG,UAAU,IAAI,SAAS,CAAC,QAAQ,KAAK,CAAC,IAAI,SAAS,CAAC,SAAS,KAAK,CAAC;YAChF,SAAS,CAAC,gBAAgB,IAAI,eAAe,CAAA;QAC/C,MAAM,GAAG;YACP,OAAO,EAAE,yCAAyC;YAClD,MAAM;YACN,KAAK;YACL,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,UAAU;YACpB,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK;YAC/B,UAAU,EAAE,SAAS,CAAC,UAAU;YAChC,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,YAAY,EAAE,SAAS,CAAC,YAAY;YACpC,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;YAC3C,KAAK,EAAE;gBACL,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,OAAO;gBAChC,UAAU,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE;gBACpD,gBAAgB,EAAE,SAAS,CAAC,KAAK,CAAC,IAAI;aACvC;YACD,SAAS,EAAE,gBAAgB,CAAC,cAAc,EAAE;gBAC1C,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,UAAU;aAC/E,CAAC;YACF,SAAS,EAAE,gBAAgB,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,CAAC;YAC3E,UAAU,EAAE,YAAY;YACxB,kBAAkB,EAAE,KAAK;SAC1B,CAAA;QACD,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACxC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAA;QACnD,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,0BAA0B,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;QAChF,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAA;QACpE,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAA;QACjD,oBAAoB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;YACtE,aAAa,EAAE,KAAK;SACrB,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,GAAG;YACP,GAAG,IAAI;YACP,OAAO,EAAE,yCAAyC;YAClD,MAAM,EAAE,KAAK;YACb,KAAK;YACL,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;YAC3C,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAA;QACD,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACxC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAA;QACjD,oBAAoB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAA;IAChF,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACnD,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,KAAa,EACb,IAAY,EACZ,KAAa,EACb,UAAwC,EAAE;IAE1C,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;IACvC,MAAM,SAAS,GAAG,wBAAwB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAC3D,MAAM,OAAO,GAAG,4BAA4B,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAClE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CACrC,sBAAsB,EAAE,IAAI,EAAE,OAAO,EACrC,iBAAiB,IAAI,CAAC,GAAG,EAAE,IAAI,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAC1D,CAAA;IACD,MAAM,MAAM,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE;QACnF,GAAG,OAAO;QACV,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK;QAC/B,GAAG,EAAE,WAAW;KACjB,CAAC,CAAA;IACF,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO;YACL,OAAO,EAAE,+CAA+C;YACxD,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,UAAU;YACpB,UAAU,EAAE,SAAS,CAAC,UAAU;YAChC,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,YAAY,EAAE,SAAS,CAAC,YAAY;YACpC,MAAM;YACN,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,kBAAkB,EAAE,KAAK;SAC1B,CAAA;IACH,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,QAAQ,KAAK,IAAI;QACxE,MAAM,CAAC,OAAO,EAAE,QAAQ,KAAK,IAAI,CAAA;IACnC,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAA;IAClE,oBAAoB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;QACtE,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QACtC,OAAO,EAAE,WAAW;KACrB,CAAC,CAAA;IACF,OAAO;QACL,OAAO,EAAE,0CAA0C;QACnD,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,UAAU;QACpB,UAAU,EAAE,SAAS,CAAC,UAAU;QAChC,WAAW,EAAE,SAAS,CAAC,WAAW;QAClC,YAAY,EAAE,SAAS,CAAC,YAAY;QACpC,MAAM;QACN,MAAM;QACN,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,kBAAkB,EAAE,KAAK;KAC1B,CAAA;AACH,CAAC;AAED,SAAS,kBAAkB,CACzB,IAAY,EAAE,MAAc,EAAE,SAAmC;IAEjE,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAA;IACtC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACvD,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAAE,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,CAAA;IAC5F,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,UAAU,IAAI,EAAE,CAAA;QAC/B,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAAE,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QAC1E,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,kBAAkB,IAAI,EAAE,CAAC,CAAA;IAC1D,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5E,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,SAAQ;QAC5C,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;IACjE,CAAC;IACD,yBAAyB,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;AAC5D,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAc,EAAE,UAAkB;IACnE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC7E,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;IAClD,CAAC;IACD,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC;QACrD,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,IAAa,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAChG,MAAM,CAAC,YAAY,GAAG,CAAC,UAAU,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAA;IACjG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAC1B,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,MAAc,EAAE,GAAW;IACjE,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;IAC/C,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/C,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,cAAc,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAA;IACzF,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACpD,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE;QAC1B,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,cAAc,EAAE;KACpD,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,wBAAwB,CAC/B,KAAa,EAAE,IAAY,EAAE,UAAU,GAAG,EAAE;IAE5C,MAAM,SAAS,GAAG,wBAAwB,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;IACnE,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,KAAK,UAAU,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,gCAAgC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAC7F,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,4BAA4B,CAAC,IAAY,EAAE,SAAmC;IACrF,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;IACzD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,aAAa,SAAS,CAAC,IAAI,wCAAwC,SAAS,CAAC,IAAI,QAAQ,CAAC,CAAA;IAC5G,CAAC;IACD,MAAM,gBAAgB,GAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC/C,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IACnC,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,IAAI,SAAS,CAAC,KAAK,CAAC,QAAQ,KAAK,UAAU;QAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACtE,IAAI,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,KAAK,gBAAgB;QAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAC1F,IAAI,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,UAAU;QAAE,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAC5F,IAAI,SAAS,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,WAAW;QAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IACvF,IAAI,SAAS,CAAC,KAAK,CAAC,YAAY,KAAK,UAAU;QAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IAC9E,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,aAAa,SAAS,CAAC,IAAI,sBAAsB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACzF,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,oBAAoB,CAC3B,IAAY,EACZ,SAAmC,EACnC,MAA0B,EAC1B,KAIC;IAED,IAAI,CAAC,SAAS,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IAC5E,MAAM,MAAM,GAAG,4BAA4B,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAC5D,mBAAmB,CAAC,IAAI,EAAE;QACxB,GAAG,SAAS,CAAC,KAAK;QAClB,MAAM;QACN,OAAO,EAAE,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE;QACjE,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC;QAC9B,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,SAAS,CAAC,KAAK,CAAC,aAAa;QACnE,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,SAAS,CAAC,KAAK,CAAC,UAAU;KAC3D,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,gBAAgB,CACvB,IAAY,EACZ,SAAmC,EACnC,MAA2B;IAE3B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;IACxC,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC,CAAA;IACtD,IAAI,CAAC,KAAK,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC,OAAO,KAAK,uCAAuC,EAAE,CAAC;QAC1F,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAA;IAC1E,CAAC;IACD,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,CAAA;IAC9D,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,IAAI,SAAS,CAAC,YAAY,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC;QACvF,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAClE,CAAC;IACD,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,CAAA;IAC7E,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,CAAA;IAC/E,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,CAAA;IACjF,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAwB,CAAA;IAC9E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAwB,CAAA;IAChF,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAwB,CAAA;IAC3F,IAAI,eAAe,CAAC,eAAe,CAAC,KAAK,eAAe,CAAC,MAAM,CAAC;QAC5D,MAAM,CAAC,eAAe,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK;QAC7C,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;IACpE,CAAC;IACD,MAAM,MAAM,GAAG,4BAA4B,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAC5D,OAAO;QACL,SAAS,EAAE,KAAK;QAChB,gBAAgB,EAAE,YAAY;QAC9B,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC5C,aAAa,EAAE,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAC7C,cAAc,EAAE,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAChD,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;QACnC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;QAC7C,cAAc,EAAE,SAAS,CAAC,UAAU;QACpC,eAAe,EAAE,SAAS,CAAC,WAAW;QACtC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC;KACnC,CAAA;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY,EAAE,KAAgC;IACzE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,oBAAoB,EAAE,GAAG,KAAK,CAAC,SAAS,OAAO,CAAC,CAAA;IACxE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;IACvD,IAAI,eAAe,CAAC,QAAQ,CAAC,KAAK,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,CAAC,SAAS,EAAE,CAAC,CAAA;IAChE,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY,EAAE,IAAY;IACtD,OAAO,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,uBAAuB,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;AACpF,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY,EAAE,SAAmC;IAC5E,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,SAAS,CAAA;IACzC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,aAAa,SAAS,CAAC,IAAI,+BAA+B,CAAC,CAAA;IAC7E,CAAC;IACD,OAAO,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAA;AACvE,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IAC5C,MAAM,OAAO,GAA0C,EAAE,CAAA;IACzD,MAAM,KAAK,GAAG,CAAC,SAAiB,EAAE,MAAM,GAAG,EAAE,EAAQ,EAAE;QACrD,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;aAChE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;YACxC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAA;YAC3D,IAAI,KAAK,CAAC,cAAc,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAA;YAChF,IAAI,KAAK,CAAC,WAAW,EAAE;gBAAE,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;iBACpC,IAAI,KAAK,CAAC,MAAM,EAAE;gBAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAA;;gBACjF,MAAM,IAAI,KAAK,CAAC,6BAA6B,GAAG,EAAE,CAAC,CAAA;QAC1D,CAAC;IACH,CAAC,CAAA;IACD,KAAK,CAAC,QAAQ,CAAC,CAAA;IACf,OAAO,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAA;AACzC,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,GAAW,EAAE,SAAkB;IACpE,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IAC5C,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;IACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;IACzC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;QACrF,MAAM,IAAI,KAAK,CAAC,uCAAuC,GAAG,EAAE,CAAC,CAAA;IAC/D,CAAC;IACD,IAAI,SAAS,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,EAAE,CAAC,CAAA;IACtF,IAAI,SAAS,IAAI,YAAY,CAAC,SAAS,CAAC,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;QACvG,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,EAAE,CAAC,CAAA;IAClD,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,GAAW;IACjD,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACtC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,IAAI,SAAS,KAAK,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,uCAAuC,GAAG,EAAE,CAAC,CAAA;IAC/D,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,gBAAgB,CAAC,SAA4B,EAAE,KAA8B;IACpF,OAAO;QACL,MAAM,EAAE,SAAS,CAAC,MAAM;QACxB,SAAS,EAAE,SAAS,CAAC,MAAM;QAC3B,GAAG,KAAK;QACR,QAAQ,EAAE,SAAS,CAAC,QAAQ;QAC5B,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,gBAAgB,EAAE,SAAS,CAAC,gBAAgB;QAC5C,gBAAgB,EAAE,SAAS,CAAC,gBAAgB;QAC5C,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,MAAM,EAAE,SAAS,CAAC,MAAM;QACxB,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,UAAU,EAAE,SAAS,CAAC,UAAU;KACjC,CAAA;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAAc;IACpC,OAAO;QACL,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC;QACnF,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QACpF,gBAAgB,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE;KAC9C,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,KAAc;IAC9C,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;AACzD,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,IAAY;IAC5C,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7C,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAA;IAC1E,aAAa,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9C,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;AAC7B,CAAC;AAED,SAAS,MAAM,CAAC,KAAsB;IACpC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACzD,CAAC;AAED,SAAS,QAAQ,CAAC,KAAa;IAC7B,IAAI,CAAC,0CAA0C,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAA;IAChD,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,SAAiB;IAC/C,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IACrC,OAAO,GAAG,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;AAC1G,CAAC","sourcesContent":["import { createHash, randomUUID } from 'node:crypto'\nimport {\n cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync,\n realpathSync, renameSync, rmdirSync, rmSync, writeFileSync,\n} from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { dirname, join, relative, resolve } from 'node:path'\nimport {\n CURRENT_WORKSPACE_FILE, WORKSPACE_STATE_ROOT,\n inspectAgentProject, showDevelopmentWorkspace,\n type DevelopmentWorkspaceState, type DevelopmentWorkspaceView,\n} from './development-workspace.js'\nimport { digest, stableStringify } from './events.js'\nimport {\n prepareOpenCodeEvalAgent, runOpenCodeEvaluation, runOpenCodePrompt,\n type OpenCodeEvalOptions, type OpenCodeExecution,\n} from './opencode-evals.js'\nimport {\n bindRequiredBasicSkill, verifyRequiredBasicSkill, type OpenCodeSkillPreflight,\n} from './opencode-workspace.js'\n\nexport const OPENCODE_WORKSPACE_ROOT = '.dingtalk-agent/development-workspaces'\nexport const OPENCODE_EVIDENCE_ROOT = '.dingtalk-agent/development-workspace-evidence'\n\nexport interface OpenCodeWorkspacePlan {\n $schema: 'dingtalk-agent/opencode-workspace-plan@1'\n planId: string\n workspace: string\n provider: 'opencode'\n model: string\n action: 'create' | 'rebuild' | 'noop'\n root: string\n managedPath: string\n sourceHash: string\n desiredHash: string\n observedHash: string\n currentState: string\n writes: string[]\n sideEffect: false\n dingtalkSideEffect: false\n}\n\nexport interface OpenCodeWorkspaceApplyResult extends Omit<OpenCodeWorkspacePlan, '$schema' | 'sideEffect'> {\n $schema: 'dingtalk-agent/opencode-workspace-apply@1'\n applied: boolean\n idempotent: boolean\n status: 'verifying' | 'ready'\n observedHash: string\n binding: Record<string, string>\n sideEffect: 'local-managed-workspace'\n dingtalkSideEffect: false\n}\n\nexport interface OpenCodeWorkspaceRunOptions {\n execute?: boolean\n yes?: boolean\n command?: string\n timeoutMs?: number\n out?: string\n}\n\nexport interface OpenCodeWorkspaceEvalOptions extends OpenCodeEvalOptions {}\n\nexport function planOpenCodeWorkspace(\n start: string, name: string, cliVersion = '',\n): OpenCodeWorkspacePlan {\n const info = inspectAgentProject(start, cliVersion)\n const workspace = requireOpenCodeWorkspace(info.root, name, cliVersion)\n const target = managedWorkspacePath(info.root, name)\n const artifactPath = artifactStoragePath(info.root, workspace)\n const observedHash = existsSync(target) ? hashTree(target) : ''\n const state = workspace.state\n const intact = Boolean(state && state.provider === 'opencode' &&\n state.desiredHash === workspace.desiredHash && state.observedHash === observedHash &&\n state.binding.managedPath === relative(info.root, target) &&\n existsSync(artifactPath) && lstatSync(artifactPath).isDirectory())\n const action = !existsSync(target) ? 'create' : intact ? 'noop' : 'rebuild'\n const planId = `opencode_plan_${digest(stableStringify({\n workspace: name, desiredHash: workspace.desiredHash, observedHash, action,\n })).slice(0, 24)}`\n return {\n $schema: 'dingtalk-agent/opencode-workspace-plan@1',\n planId,\n workspace: name,\n provider: 'opencode',\n model: workspace.provider.model,\n action,\n root: info.root,\n managedPath: relative(info.root, target),\n sourceHash: workspace.sourceHash,\n desiredHash: workspace.desiredHash,\n observedHash,\n currentState: workspace.status,\n writes: action === 'noop' ? [] : [\n relative(info.root, target),\n relative(info.root, artifactPath),\n join(WORKSPACE_STATE_ROOT, `${name}.json`),\n ],\n sideEffect: false,\n dingtalkSideEffect: false,\n }\n}\n\nexport function applyOpenCodeWorkspace(\n start: string,\n name: string,\n options: { yes?: boolean; command?: string; cliVersion?: string } = {},\n): OpenCodeWorkspaceApplyResult {\n if (!options.yes) throw new Error('workspace create 会写本地 managed Workspace;必须显式传 --yes')\n const cliVersion = options.cliVersion || ''\n const plan = planOpenCodeWorkspace(start, name, cliVersion)\n const workspace = requireOpenCodeWorkspace(plan.root, name, cliVersion)\n const target = resolve(plan.root, plan.managedPath)\n const artifactPath = artifactStoragePath(plan.root, workspace)\n const artifactExisted = existsSync(artifactPath)\n const command = options.command || process.env.DTA_OPENCODE_BIN || 'opencode'\n if (plan.action === 'noop') {\n const binding = workspace.state?.binding || {}\n const stateStatus = workspace.state?.status === 'ready' ? 'ready' : 'verifying'\n return {\n ...plan,\n $schema: 'dingtalk-agent/opencode-workspace-apply@1',\n applied: false,\n idempotent: true,\n status: stateStatus,\n binding,\n sideEffect: 'local-managed-workspace',\n dingtalkSideEffect: false,\n }\n }\n\n mkdirSync(dirname(target), { recursive: true })\n const staging = `${target}.tmp-${process.pid}-${randomUUID().slice(0, 8)}`\n const backup = `${target}.backup-${process.pid}-${randomUUID().slice(0, 8)}`\n const preflightSandbox = mkdtempSync(join(\n tmpdir(), `dta-opencode-workspace-preflight-${safeName(name)}-`,\n ))\n let preflight: OpenCodeSkillPreflight | null = null\n try {\n mkdirSync(staging, { recursive: false })\n materializeProject(plan.root, staging, workspace)\n prepareOpenCodeEvalAgent(staging, 'none')\n bindRequiredBasicSkill(staging)\n cpSync(staging, preflightSandbox, { recursive: true })\n preflight = verifyRequiredBasicSkill(bindRequiredBasicSkill(preflightSandbox), command)\n if (existsSync(target)) renameSync(target, backup)\n renameSync(staging, target)\n mkdirSync(artifactPath, { recursive: true })\n if (existsSync(backup)) rmSync(backup, { recursive: true, force: true })\n } catch (error) {\n rmSync(staging, { recursive: true, force: true })\n if (existsSync(backup)) {\n rmSync(target, { recursive: true, force: true })\n renameSync(backup, target)\n } else if (existsSync(target) && plan.action === 'create') {\n rmSync(target, { recursive: true, force: true })\n }\n if (!artifactExisted && existsSync(artifactPath)) {\n try { rmdirSync(artifactPath) } catch { /* preserve non-empty concurrent writes */ }\n }\n throw error\n } finally {\n rmSync(preflightSandbox, { recursive: true, force: true })\n }\n\n const observedHash = hashTree(target)\n const binding = {\n managedPath: relative(plan.root, target),\n model: workspace.provider.model,\n sourceHash: workspace.sourceHash,\n basicHash: String(preflight?.skill.hash || ''),\n basicVersion: String(preflight?.skill.version || ''),\n configHash: String(preflight?.configHash || ''),\n openCodeVersion: String(preflight?.openCodeVersion || ''),\n }\n writeWorkspaceState(plan.root, {\n $schema: 'dingtalk-agent/workspace-state@1',\n workspace: name,\n provider: 'opencode',\n status: 'verifying',\n binding,\n desiredHash: workspace.desiredHash,\n observedHash,\n lastPlanId: plan.planId,\n lastReceiptId: '',\n lastEvalId: '',\n })\n return {\n ...plan,\n $schema: 'dingtalk-agent/opencode-workspace-apply@1',\n applied: true,\n idempotent: false,\n status: 'verifying',\n observedHash,\n binding,\n sideEffect: 'local-managed-workspace',\n dingtalkSideEffect: false,\n }\n}\n\nexport function useOpenCodeWorkspace(start: string, name: string, cliVersion = ''): Record<string, unknown> {\n const info = inspectAgentProject(start, cliVersion)\n const workspace = requireOpenCodeWorkspace(info.root, name, cliVersion)\n assertManagedWorkspaceIntact(info.root, workspace)\n const path = join(info.root, CURRENT_WORKSPACE_FILE)\n atomicText(path, `${name}\\n`)\n const readback = readFileSync(path, 'utf8').trim()\n if (readback !== name) throw new Error('current-workspace 写后回读不一致')\n return {\n $schema: 'dingtalk-agent/workspace-selection@1',\n workspace: name,\n provider: 'opencode',\n previous: info.currentWorkspace,\n current: readback,\n sideEffect: 'local-selection',\n dingtalkSideEffect: false,\n }\n}\n\nexport function runOpenCodeWorkspace(\n start: string,\n name: string,\n prompt: string,\n options: OpenCodeWorkspaceRunOptions = {},\n): Record<string, any> {\n if (!prompt.trim()) throw new Error('workspace run prompt 不能为空')\n const info = inspectAgentProject(start)\n const workspace = requireOpenCodeWorkspace(info.root, name)\n const managed = assertManagedWorkspaceIntact(info.root, workspace)\n const timeoutMs = options.timeoutMs ?? 120_000\n if (!Number.isInteger(timeoutMs) || timeoutMs < 10_000 || timeoutMs > 300_000) {\n throw new Error('workspace run timeoutMs 必须为 10000..300000')\n }\n const plan = {\n $schema: 'dingtalk-agent/opencode-workspace-run-plan@1',\n workspace: name,\n provider: 'opencode',\n model: workspace.provider.model,\n desiredHash: workspace.desiredHash,\n observedHash: workspace.observedHash,\n promptHash: sha256(prompt),\n loadProbe: 'random-per-run',\n tools: 'none',\n sideEffect: 'model-only',\n dingtalkSideEffect: false,\n }\n if (!options.execute) return { ...plan, ready: true, executeRequired: true }\n if (!options.yes) throw new Error('workspace run 会调用 OpenCode 模型;必须同时传 --execute --yes')\n\n const runId = `opencode_workspace_run_${Date.now()}_${randomUUID().slice(0, 8)}`\n const evidence = safeProjectPath(info.root, options.out || join(\n OPENCODE_EVIDENCE_ROOT, name, 'runs', runId), false)\n const sandbox = mkdtempSync(join(tmpdir(), `dta-opencode-workspace-${safeName(name)}-`))\n const command = options.command || process.env.DTA_OPENCODE_BIN || 'opencode'\n let report: Record<string, any>\n try {\n cpSync(managed, sandbox, { recursive: true })\n const probe = randomUUID()\n const skillPath = join(sandbox, '.agents', 'skills', 'dingtalk-basic-behavior', 'SKILL.md')\n const skillBody = readFileSync(skillPath, 'utf8')\n writeFileSync(skillPath, `${skillBody.trimEnd()}\\n\\n<!-- dta-load-probe:${probe} -->\\n`)\n const preflight = verifyRequiredBasicSkill(bindRequiredBasicSkill(sandbox), command)\n const probePrompt =\n '这是加载链路探针。只依据 Basic Skill 正文末尾注释回答;严格输出 `dta-load-probe=<值>`;' +\n '若看不到则输出 `dta-load-probe=not-loaded`。禁止调用工具或解释。'\n const probeExecution = runOpenCodePrompt(\n command, sandbox, workspace.provider.model, probePrompt,\n `DTA Workspace ${name} load probe`, timeoutMs,\n )\n const exactProbe = `dta-load-probe=${probe}`\n const loadPassed = probeExecution.exitCode === 0 && probeExecution.answer.trim() === exactProbe &&\n probeExecution.toolCalls === 0 && probeExecution.directoryMatched\n const marker = `[DTA-WORKSPACE-RUN-${safeName(name)}-${randomUUID()}]`\n const execution = loadPassed ? runOpenCodePrompt(\n command, sandbox, workspace.provider.model,\n `${marker}\\n执行协议:第一行逐字符原样输出 ${marker};从第二行回答用户任务;禁止调用任何工具。\\n${prompt}`,\n `DTA Workspace ${name} run`, timeoutMs,\n ) : emptyExecution('load-probe-failed')\n const exactAttributed = execution.answer.startsWith(marker)\n const answer = exactAttributed ? execution.answer.slice(marker.length).trim() : execution.answer\n const passed = loadPassed && execution.exitCode === 0 && execution.toolCalls === 0 &&\n execution.directoryMatched && exactAttributed\n report = {\n $schema: 'dingtalk-agent/opencode-workspace-run@1',\n passed,\n runId,\n workspace: name,\n provider: 'opencode',\n model: workspace.provider.model,\n sourceHash: workspace.sourceHash,\n desiredHash: workspace.desiredHash,\n observedHash: workspace.observedHash,\n evidencePath: relative(info.root, evidence),\n basic: {\n version: preflight.skill.version,\n sourceHash: workspace.state?.binding.basicHash || '',\n instrumentedHash: preflight.skill.hash,\n },\n loadProbe: executionSummary(probeExecution, {\n expected: exactProbe, exactLoaded: probeExecution.answer.trim() === exactProbe,\n }),\n execution: executionSummary(execution, { marker, exactAttributed, answer }),\n sideEffect: 'model-only',\n dingtalkSideEffect: false,\n }\n mkdirSync(evidence, { recursive: true })\n writeFileSync(join(evidence, 'prompt.txt'), prompt)\n writeFileSync(join(evidence, 'load-probe.stdout.ndjson'), probeExecution.stdout)\n writeFileSync(join(evidence, 'run.stdout.ndjson'), execution.stdout)\n atomicJson(join(evidence, 'report.json'), report)\n writeProviderOutcome(info.root, workspace, passed ? 'ready' : 'failed', {\n lastReceiptId: runId,\n })\n } catch (error) {\n report = {\n ...plan,\n $schema: 'dingtalk-agent/opencode-workspace-run@1',\n passed: false,\n runId,\n evidencePath: relative(info.root, evidence),\n failure: error.message,\n }\n mkdirSync(evidence, { recursive: true })\n atomicJson(join(evidence, 'report.json'), report)\n writeProviderOutcome(info.root, workspace, 'failed', { lastReceiptId: runId })\n } finally {\n rmSync(sandbox, { recursive: true, force: true })\n }\n return report\n}\n\nexport function evalOpenCodeWorkspace(\n start: string,\n name: string,\n suite: string,\n options: OpenCodeWorkspaceEvalOptions = {},\n): Record<string, any> {\n const info = inspectAgentProject(start)\n const workspace = requireOpenCodeWorkspace(info.root, name)\n const managed = assertManagedWorkspaceIntact(info.root, workspace)\n const selectedOut = options.out || join(\n OPENCODE_EVIDENCE_ROOT, name, 'evals',\n `opencode_eval_${Date.now()}_${randomUUID().slice(0, 8)}`,\n )\n const report = runOpenCodeEvaluation(info.root, relative(info.root, managed), suite, {\n ...options,\n model: workspace.provider.model,\n out: selectedOut,\n })\n if (!options.execute) {\n return {\n $schema: 'dingtalk-agent/opencode-workspace-eval-plan@1',\n workspace: name,\n provider: 'opencode',\n sourceHash: workspace.sourceHash,\n desiredHash: workspace.desiredHash,\n observedHash: workspace.observedHash,\n report,\n sideEffect: report.sideEffect,\n dingtalkSideEffect: false,\n }\n }\n const passed = report.passed === true && report.summary?.loadGate === true &&\n report.summary?.hardGate === true\n const evalBinding = bindEvalEvidence(info.root, workspace, report)\n writeProviderOutcome(info.root, workspace, passed ? 'ready' : 'failed', {\n lastEvalId: String(report.runId || ''),\n binding: evalBinding,\n })\n return {\n $schema: 'dingtalk-agent/opencode-workspace-eval@1',\n workspace: name,\n provider: 'opencode',\n sourceHash: workspace.sourceHash,\n desiredHash: workspace.desiredHash,\n observedHash: workspace.observedHash,\n passed,\n report,\n sideEffect: report.sideEffect,\n dingtalkSideEffect: false,\n }\n}\n\nfunction materializeProject(\n root: string, target: string, workspace: DevelopmentWorkspaceView,\n): void {\n const info = inspectAgentProject(root)\n copyProjectEntry(root, target, info.project.definition)\n if (existsSync(join(root, 'opencode.json'))) copyProjectEntry(root, target, 'opencode.json')\n for (const name of info.project.skills) {\n const source = `skills/${name}`\n if (existsSync(join(root, source))) copyProjectEntry(root, target, source)\n copyProjectEntry(root, target, `.agents/skills/${name}`)\n }\n for (const route of [workspace.storage.memory, workspace.storage.knowledge]) {\n if (!route.startsWith('local-md:')) continue\n copyProjectEntry(root, target, route.slice('local-md:'.length))\n }\n bindDefinitionInstruction(target, info.project.definition)\n}\n\nfunction bindDefinitionInstruction(target: string, definition: string): void {\n const path = join(target, 'opencode.json')\n const config = existsSync(path) ? JSON.parse(readFileSync(path, 'utf8')) : {}\n if (!config || typeof config !== 'object' || Array.isArray(config)) {\n throw new Error('opencode.json 必须是 JSON object')\n }\n const instructions = Array.isArray(config.instructions)\n ? config.instructions.filter((item: unknown): item is string => typeof item === 'string') : []\n config.instructions = [definition, ...instructions.filter((item: string) => item !== definition)]\n atomicJson(path, config)\n}\n\nfunction copyProjectEntry(root: string, target: string, ref: string): void {\n const source = safeProjectPath(root, ref, true)\n const destination = safeTargetPath(target, ref)\n if (lstatSync(source).isSymbolicLink()) throw new Error(`Project source 不允许符号链接: ${ref}`)\n mkdirSync(dirname(destination), { recursive: true })\n cpSync(source, destination, {\n recursive: true,\n filter: (path) => !lstatSync(path).isSymbolicLink(),\n })\n}\n\nfunction requireOpenCodeWorkspace(\n start: string, name: string, cliVersion = '',\n): DevelopmentWorkspaceView {\n const workspace = showDevelopmentWorkspace(start, name, cliVersion)\n if (workspace.provider.kind !== 'opencode' || workspace.legacy) {\n throw new Error(`Workspace ${name} 不是 opencode Provider;W2 不执行 ${workspace.provider.kind}`)\n }\n return workspace\n}\n\nfunction assertManagedWorkspaceIntact(root: string, workspace: DevelopmentWorkspaceView): string {\n const target = managedWorkspacePath(root, workspace.name)\n if (!existsSync(target) || !workspace.state) {\n throw new Error(`Workspace ${workspace.name} 尚未 materialize;先执行 workspace create ${workspace.name} --yes`)\n }\n const expectedRelative = relative(root, target)\n const actualHash = hashTree(target)\n const failures: string[] = []\n if (workspace.state.provider !== 'opencode') failures.push('provider')\n if (workspace.state.binding.managedPath !== expectedRelative) failures.push('managedPath')\n if (workspace.state.binding.sourceHash !== workspace.sourceHash) failures.push('sourceHash')\n if (workspace.state.desiredHash !== workspace.desiredHash) failures.push('desiredHash')\n if (workspace.state.observedHash !== actualHash) failures.push('observedHash')\n if (failures.length) {\n throw new Error(`Workspace ${workspace.name} managed state 漂移: ${failures.join(', ')}`)\n }\n return target\n}\n\nfunction writeProviderOutcome(\n root: string,\n workspace: DevelopmentWorkspaceView,\n status: 'ready' | 'failed',\n patch: {\n lastReceiptId?: string\n lastEvalId?: string\n binding?: Record<string, string>\n },\n): void {\n if (!workspace.state) throw new Error('Provider outcome 缺少 Workspace state')\n const target = assertManagedWorkspaceIntact(root, workspace)\n writeWorkspaceState(root, {\n ...workspace.state,\n status,\n binding: { ...workspace.state.binding, ...(patch.binding || {}) },\n observedHash: hashTree(target),\n lastReceiptId: patch.lastReceiptId ?? workspace.state.lastReceiptId,\n lastEvalId: patch.lastEvalId ?? workspace.state.lastEvalId,\n })\n}\n\nfunction bindEvalEvidence(\n root: string,\n workspace: DevelopmentWorkspaceView,\n report: Record<string, any>,\n): Record<string, string> {\n const runId = String(report.runId || '')\n const evidencePath = String(report.evidencePath || '')\n if (!runId || !evidencePath || report.$schema !== 'dingtalk-agent/opencode-eval-report@1') {\n throw new Error('OpenCode Eval report 缺少可绑定的 runId/evidencePath/schema')\n }\n const evidenceRoot = safeProjectPath(root, evidencePath, true)\n if (!lstatSync(evidenceRoot).isDirectory() || lstatSync(evidenceRoot).isSymbolicLink()) {\n throw new Error('OpenCode Eval evidence root 必须是 Project 内真实目录')\n }\n const planPath = safeProjectPath(root, join(evidencePath, 'plan.json'), true)\n const suitePath = safeProjectPath(root, join(evidencePath, 'suite.json'), true)\n const reportPath = safeProjectPath(root, join(evidencePath, 'report.json'), true)\n const plan = JSON.parse(readFileSync(planPath, 'utf8')) as Record<string, any>\n const suite = JSON.parse(readFileSync(suitePath, 'utf8')) as Record<string, any>\n const persistedReport = JSON.parse(readFileSync(reportPath, 'utf8')) as Record<string, any>\n if (stableStringify(persistedReport) !== stableStringify(report) ||\n String(persistedReport.runId || '') !== runId ||\n String(plan.suite || '') !== String(suite.id || '')) {\n throw new Error('OpenCode Eval evidence 写后回读与内存 report/suite 不一致')\n }\n const target = assertManagedWorkspaceIntact(root, workspace)\n return {\n evalRunId: runId,\n evalEvidencePath: evidencePath,\n evalPlanHash: sha256(readFileSync(planPath)),\n evalSuiteHash: digest(stableStringify(suite)),\n evalReportHash: sha256(readFileSync(reportPath)),\n evalSuiteId: String(suite.id || ''),\n evalModel: String(report.engine?.model || ''),\n evalSourceHash: workspace.sourceHash,\n evalDesiredHash: workspace.desiredHash,\n evalObservedHash: hashTree(target),\n }\n}\n\nfunction writeWorkspaceState(root: string, state: DevelopmentWorkspaceState): void {\n const path = join(root, WORKSPACE_STATE_ROOT, `${state.workspace}.json`)\n atomicJson(path, state)\n const readback = JSON.parse(readFileSync(path, 'utf8'))\n if (stableStringify(readback) !== stableStringify(state)) {\n throw new Error(`Workspace state 写后回读不一致: ${state.workspace}`)\n }\n}\n\nfunction managedWorkspacePath(root: string, name: string): string {\n return safeProjectPath(root, join(OPENCODE_WORKSPACE_ROOT, safeName(name)), false)\n}\n\nfunction artifactStoragePath(root: string, workspace: DevelopmentWorkspaceView): string {\n const route = workspace.storage.artifacts\n if (!route.startsWith('local-dir:')) {\n throw new Error(`Workspace ${workspace.name} Artifact route 必须是 local-dir`)\n }\n return safeProjectPath(root, route.slice('local-dir:'.length), false)\n}\n\nfunction hashTree(root: string): string {\n const rootReal = realpathSync(resolve(root))\n const entries: Array<{ path: string; hash: string }> = []\n const visit = (directory: string, prefix = ''): void => {\n for (const entry of readdirSync(directory, { withFileTypes: true })\n .sort((a, b) => a.name.localeCompare(b.name))) {\n const path = join(directory, entry.name)\n const rel = prefix ? `${prefix}/${entry.name}` : entry.name\n if (entry.isSymbolicLink()) throw new Error(`Managed Workspace 不允许符号链接: ${rel}`)\n if (entry.isDirectory()) visit(path, rel)\n else if (entry.isFile()) entries.push({ path: rel, hash: sha256(readFileSync(path)) })\n else throw new Error(`Managed Workspace 包含特殊文件: ${rel}`)\n }\n }\n visit(rootReal)\n return digest(stableStringify(entries))\n}\n\nfunction safeProjectPath(root: string, ref: string, mustExist: boolean): string {\n const rootReal = realpathSync(resolve(root))\n const candidate = resolve(rootReal, ref)\n const rel = relative(rootReal, candidate)\n if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`)) {\n throw new Error(`OpenCode Provider 路径必须位于 Project 内: ${ref}`)\n }\n if (mustExist && !existsSync(candidate)) throw new Error(`Project source 不存在: ${ref}`)\n if (mustExist && realpathSync(candidate) !== candidate && !isInside(rootReal, realpathSync(candidate))) {\n throw new Error(`Project source 真实路径越界: ${ref}`)\n }\n return candidate\n}\n\nfunction safeTargetPath(target: string, ref: string): string {\n const candidate = resolve(target, ref)\n if (!isInside(resolve(target), candidate) || candidate === resolve(target)) {\n throw new Error(`Materialized path 必须位于 Workspace 内: ${ref}`)\n }\n return candidate\n}\n\nfunction executionSummary(execution: OpenCodeExecution, extra: Record<string, unknown>): Record<string, unknown> {\n return {\n answer: execution.answer,\n rawAnswer: execution.answer,\n ...extra,\n exitCode: execution.exitCode,\n sessionId: execution.sessionId,\n sessionDirectory: execution.sessionDirectory,\n directoryMatched: execution.directoryMatched,\n toolCalls: execution.toolCalls,\n toolNames: execution.toolNames,\n tokens: execution.tokens,\n cost: execution.cost,\n durationMs: execution.durationMs,\n }\n}\n\nfunction emptyExecution(reason: string): OpenCodeExecution {\n return {\n exitCode: null, stdout: '', stderr: reason, answer: '', sessionId: '', toolCalls: 0,\n toolNames: [], toolPaths: [], toolTrace: [], tokens: null, cost: null, durationMs: 0,\n directoryMatched: false, sessionDirectory: '',\n }\n}\n\nfunction atomicJson(path: string, value: unknown): void {\n atomicText(path, JSON.stringify(value, null, 2) + '\\n')\n}\n\nfunction atomicText(path: string, body: string): void {\n mkdirSync(dirname(path), { recursive: true })\n const temporary = `${path}.${process.pid}.${randomUUID().slice(0, 8)}.tmp`\n writeFileSync(temporary, body, { flag: 'wx' })\n renameSync(temporary, path)\n}\n\nfunction sha256(value: string | Buffer): string {\n return createHash('sha256').update(value).digest('hex')\n}\n\nfunction safeName(value: string): string {\n if (!/^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/.test(value)) {\n throw new Error(`Workspace name 非法: ${value}`)\n }\n return value\n}\n\nfunction isInside(root: string, candidate: string): boolean {\n const rel = relative(root, candidate)\n return rel === '' || (rel !== '..' && !rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`))\n}\n"]}
|