@xdxer/dingtalk-agent 0.1.4-beta.1 → 0.1.4-beta.11
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 +70 -0
- package/README.en.md +397 -0
- package/README.md +500 -47
- package/dist/bin/dingtalk-agent.js +1263 -351
- 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/agent-platform.js +158 -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 +736 -0
- package/dist/src/development-workspace.js.map +1 -0
- package/dist/src/doctor.js +49 -22
- 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/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 +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 +14 -12
- package/dist/src/setup.js.map +1 -1
- package/dist/src/skill-manager.js +128 -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 +119 -14
- 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/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 +113 -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/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
package/dist/src/workspace.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Agent Workspace:一个物理目录对应一个稳定 Context/Field。
|
|
2
2
|
// 人和模型读取 Markdown;机器控制状态仍留在宿主私有 JSON 中。
|
|
3
|
-
import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync, } from 'node:fs';
|
|
3
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, writeFileSync, } from 'node:fs';
|
|
4
4
|
import { basename, dirname, join, relative, resolve } from 'node:path';
|
|
5
5
|
import { digest } from './events.js';
|
|
6
6
|
import * as dws from './dws.js';
|
|
@@ -27,9 +27,10 @@ export function ensureWorkspace(root, options = {}) {
|
|
|
27
27
|
dws: { profile: '', expectedUserId: '' },
|
|
28
28
|
// 用 Skill name 声明,不把 Workspace 绑死到某个物理安装目录。
|
|
29
29
|
// Resolver 依次查 Workspace override、全局安装和 npm 内置版本。
|
|
30
|
-
skills: ['dingtalk-basic-behavior'],
|
|
30
|
+
skills: ['dingtalk-basic-behavior', ...discoverLocalSkillNames(root)],
|
|
31
31
|
mounts: {
|
|
32
|
-
profile: '
|
|
32
|
+
profile: existsSync(join(root, 'AGENTS.md'))
|
|
33
|
+
? 'local-md:AGENTS.md' : 'local-md:WORKSPACE.md',
|
|
33
34
|
memory: options.memory || 'local-md:MEMORY.md',
|
|
34
35
|
knowledge: options.knowledge || 'local-md:knowledge/INDEX.md',
|
|
35
36
|
skills: 'local-dir:skills',
|
|
@@ -167,6 +168,30 @@ function writeDefaultMarkdown(root, spec) {
|
|
|
167
168
|
function safeName(value) {
|
|
168
169
|
return value.replace(/[^a-zA-Z0-9._-]+/g, '-');
|
|
169
170
|
}
|
|
171
|
+
function discoverLocalSkillNames(root) {
|
|
172
|
+
const directory = join(root, 'skills');
|
|
173
|
+
if (!existsSync(directory) || !lstatSync(directory).isDirectory())
|
|
174
|
+
return [];
|
|
175
|
+
const names = [];
|
|
176
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
177
|
+
if (!entry.isDirectory())
|
|
178
|
+
continue;
|
|
179
|
+
const path = join(directory, entry.name, 'SKILL.md');
|
|
180
|
+
if (!existsSync(path))
|
|
181
|
+
continue;
|
|
182
|
+
const markdown = readFileSync(path, 'utf8');
|
|
183
|
+
const frontmatter = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1] || '';
|
|
184
|
+
const name = frontmatter.match(/^name:\s*['"]?([^'"\r\n]+)['"]?\s*$/m)?.[1]?.trim() || '';
|
|
185
|
+
if (!name)
|
|
186
|
+
throw new Error(`本地 Role Skill 缺少 frontmatter name: ${path}`);
|
|
187
|
+
if (name !== entry.name) {
|
|
188
|
+
throw new Error(`本地 Role Skill 目录名与 name 不一致: ${entry.name} != ${name}`);
|
|
189
|
+
}
|
|
190
|
+
if (name !== 'dingtalk-basic-behavior')
|
|
191
|
+
names.push(name);
|
|
192
|
+
}
|
|
193
|
+
return [...new Set(names)].sort();
|
|
194
|
+
}
|
|
170
195
|
function clean(value) {
|
|
171
196
|
return typeof value === 'string' ? value.trim() : '';
|
|
172
197
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/workspace.ts"],"names":[],"mappings":"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","sourcesContent":["// Agent Workspace:一个物理目录对应一个稳定 Context/Field。\n// 人和模型读取 Markdown;机器控制状态仍留在宿主私有 JSON 中。\n\nimport {\n existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync,\n} from 'node:fs'\nimport { basename, dirname, join, relative, resolve } from 'node:path'\nimport { digest } from './events.js'\nimport * as dws from './dws.js'\n\nexport const WORKSPACE_FILE = '.dingtalk-agent/workspace.json'\n\nexport interface WorkspaceSpec {\n $schema: 'dingtalk-agent/workspace@1'\n id: string\n contextId: string\n fieldId: string\n dws: { profile: string; expectedUserId: string }\n skills: string[]\n mounts: Record<'profile' | 'memory' | 'knowledge' | 'skills', string>\n}\n\nexport interface WorkspaceInitOptions {\n contextId?: string\n id?: string\n memory?: string\n knowledge?: string\n}\n\nexport interface MountSnapshot {\n slot: string\n provider: 'local-md' | 'local-dir' | 'dingtalk-doc'\n source: string\n snapshotPath: string\n hash: string\n}\n\nexport function workspacePath(root: string): string {\n return join(root, WORKSPACE_FILE)\n}\n\nexport function ensureWorkspace(\n root: string,\n options: WorkspaceInitOptions = {},\n): WorkspaceSpec {\n const path = workspacePath(root)\n if (existsSync(path)) {\n const current = loadWorkspace(root)\n if (options.contextId && options.contextId !== current.contextId) {\n throw new Error(\n `当前目录已绑定 contextId=${current.contextId};一个物理 Workspace 不能重新绑定为 ${options.contextId}`,\n )\n }\n return current\n }\n\n const contextId = clean(options.contextId || basename(resolve(root)) || 'default')\n const id = clean(options.id || contextId)\n const spec: WorkspaceSpec = {\n $schema: 'dingtalk-agent/workspace@1',\n id,\n contextId,\n fieldId: 'default',\n dws: { profile: '', expectedUserId: '' },\n // 用 Skill name 声明,不把 Workspace 绑死到某个物理安装目录。\n // Resolver 依次查 Workspace override、全局安装和 npm 内置版本。\n skills: ['dingtalk-basic-behavior'],\n mounts: {\n profile: 'local-md:WORKSPACE.md',\n memory: options.memory || 'local-md:MEMORY.md',\n knowledge: options.knowledge || 'local-md:knowledge/INDEX.md',\n skills: 'local-dir:skills',\n },\n }\n\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, JSON.stringify(spec, null, 2) + '\\n', { flag: 'wx' })\n writeDefaultMarkdown(root, spec)\n for (const dir of ['.dingtalk-agent/cache', '.dingtalk-agent/pending']) {\n mkdirSync(join(root, dir), { recursive: true })\n }\n return spec\n}\n\nexport function loadWorkspace(root: string): WorkspaceSpec {\n const path = workspacePath(root)\n if (!existsSync(path)) {\n throw new Error(\n '缺少 .dingtalk-agent/workspace.json;只有 Prepared Run runtime 才需要 `dingtalk-agent init`。' +\n '普通 Agent Session 请使用全局 Skill,按需运行 `dingtalk-agent bootstrap`。',\n )\n }\n let value: unknown\n try { value = JSON.parse(readFileSync(path, 'utf8')) }\n catch (error) { throw new Error(`Workspace manifest 不是合法 JSON: ${error.message}`) }\n return validateWorkspace(value)\n}\n\nexport function resolveContextId(spec: WorkspaceSpec, supplied = ''): string {\n const contextId = clean(supplied || spec.contextId)\n if (contextId !== spec.contextId) {\n throw new Error(\n `contextId=${contextId} 不属于当前 Workspace(期望 ${spec.contextId});请由上游选择正确工作目录`,\n )\n }\n return contextId\n}\n\n/**\n * Provider 只负责把语义内容冻结成本地 Markdown;锁、Wait、去重和 Receipt 不走这里。\n * dingtalk-doc 只读显式 node,不搜索、不创建、不覆盖。\n */\nexport function snapshotWorkspaceMounts(\n root: string,\n runPath: string,\n spec: WorkspaceSpec,\n): MountSnapshot[] {\n const destination = join(runPath, 'context', 'mounts')\n mkdirSync(destination, { recursive: true })\n const snapshots: MountSnapshot[] = []\n\n for (const [slot, uri] of Object.entries(spec.mounts)) {\n const mount = parseMount(uri)\n if (mount.provider === 'local-dir') {\n // skills 是逻辑槽:实际内容由 Skill resolver 从 Workspace override、\n // 全局目录或 npm 内置版本解析并在 Session 创建时冻结。\n if (slot !== 'skills') safeLocalPath(root, mount.ref)\n snapshots.push({\n slot, provider: mount.provider, source: uri,\n // P0 的目录型 mount 只有 skills;真实内容由 Session 绑定并冻结到这里。\n snapshotPath: slot === 'skills' ? 'context/skills' : '', hash: '',\n })\n continue\n }\n\n const markdown = mount.provider === 'local-md'\n ? readFileSync(safeLocalPath(root, mount.ref), 'utf8')\n : String(dws.readDoc(mount.ref, spec.dws.profile))\n const path = join(destination, `${safeName(slot)}.md`)\n writeFileSync(path, markdown.endsWith('\\n') ? markdown : markdown + '\\n')\n snapshots.push({\n slot,\n provider: mount.provider,\n source: uri,\n snapshotPath: relative(runPath, path).split('\\\\').join('/'),\n hash: digest(markdown),\n })\n }\n\n writeFileSync(\n join(destination, 'manifest.json'),\n JSON.stringify({ $schema: 'dingtalk-agent/mount-snapshot@1', entries: snapshots }, null, 2) + '\\n',\n )\n return snapshots\n}\n\nfunction validateWorkspace(value: unknown): WorkspaceSpec {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Workspace manifest 必须是 JSON object')\n }\n const input = value as Record<string, any>\n if (input.$schema !== 'dingtalk-agent/workspace@1') {\n throw new Error('Workspace manifest 缺少 dingtalk-agent/workspace@1 schema')\n }\n for (const key of ['id', 'contextId', 'fieldId']) {\n if (!clean(input[key])) throw new Error(`Workspace manifest 缺少 ${key}`)\n }\n if (!Array.isArray(input.skills) || input.skills.some((item: unknown) => typeof item !== 'string')) {\n throw new Error('Workspace skills 必须是 string[]')\n }\n if (!input.dws || typeof input.dws.profile !== 'string' ||\n typeof input.dws.expectedUserId !== 'string') {\n throw new Error('Workspace dws 必须包含 string profile / expectedUserId')\n }\n const requiredSlots = ['profile', 'memory', 'knowledge', 'skills']\n if (!input.mounts || requiredSlots.some((slot) => typeof input.mounts[slot] !== 'string')) {\n throw new Error(`Workspace mounts 必须包含 ${requiredSlots.join(' / ')}`)\n }\n for (const uri of Object.values(input.mounts)) parseMount(String(uri))\n return input as WorkspaceSpec\n}\n\nfunction parseMount(uri: string): {\n provider: 'local-md' | 'local-dir' | 'dingtalk-doc'\n ref: string\n} {\n const separator = uri.indexOf(':')\n const provider = uri.slice(0, separator)\n const ref = separator >= 0 ? uri.slice(separator + 1).trim() : ''\n if (!['local-md', 'local-dir', 'dingtalk-doc'].includes(provider) || !ref) {\n throw new Error(`不支持的 Workspace mount: ${uri}`)\n }\n return { provider: provider as 'local-md' | 'local-dir' | 'dingtalk-doc', ref }\n}\n\nfunction safeLocalPath(root: string, ref: string): string {\n const rootReal = realpathSync(resolve(root))\n const candidate = resolve(rootReal, ref)\n if (!existsSync(candidate)) throw new Error(`Workspace mount 不存在: ${ref}`)\n const actual = realpathSync(candidate)\n const rel = relative(rootReal, actual)\n if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`)) {\n throw new Error(`Workspace local mount 必须位于当前目录内: ${ref}`)\n }\n return actual\n}\n\nfunction writeDefaultMarkdown(root: string, spec: WorkspaceSpec): void {\n const files: Array<[string, string]> = [\n ['WORKSPACE.md', `# Agent Workspace\\n\\n- Context ID: ${spec.contextId}\\n- Workspace: ${spec.id}\\n- Field: ${spec.fieldId}\\n\\n这里定义稳定的身份、职责、协作边界和内容挂载。\\n`],\n ['MEMORY.md', '# Long-term Memory\\n\\n只保存经过筛选、带来源的长期记忆。当前事项放在 Session memory。\\n'],\n ['knowledge/INDEX.md', '# Knowledge Index\\n\\n按需列出本 Workspace 可用的知识入口。\\n'],\n ]\n for (const [rel, content] of files) {\n const path = join(root, rel)\n mkdirSync(dirname(path), { recursive: true })\n if (!existsSync(path)) writeFileSync(path, content)\n }\n}\n\nfunction safeName(value: string): string {\n return value.replace(/[^a-zA-Z0-9._-]+/g, '-')\n}\n\nfunction clean(value: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/workspace.ts"],"names":[],"mappings":"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","sourcesContent":["// Agent Workspace:一个物理目录对应一个稳定 Context/Field。\n// 人和模型读取 Markdown;机器控制状态仍留在宿主私有 JSON 中。\n\nimport {\n existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, writeFileSync,\n} from 'node:fs'\nimport { basename, dirname, join, relative, resolve } from 'node:path'\nimport { digest } from './events.js'\nimport * as dws from './dws.js'\n\nexport const WORKSPACE_FILE = '.dingtalk-agent/workspace.json'\n\nexport interface WorkspaceSpec {\n $schema: 'dingtalk-agent/workspace@1'\n id: string\n contextId: string\n fieldId: string\n dws: { profile: string; expectedUserId: string }\n skills: string[]\n mounts: Record<'profile' | 'memory' | 'knowledge' | 'skills', string>\n}\n\nexport interface WorkspaceInitOptions {\n contextId?: string\n id?: string\n memory?: string\n knowledge?: string\n}\n\nexport interface MountSnapshot {\n slot: string\n provider: 'local-md' | 'local-dir' | 'dingtalk-doc'\n source: string\n snapshotPath: string\n hash: string\n}\n\nexport function workspacePath(root: string): string {\n return join(root, WORKSPACE_FILE)\n}\n\nexport function ensureWorkspace(\n root: string,\n options: WorkspaceInitOptions = {},\n): WorkspaceSpec {\n const path = workspacePath(root)\n if (existsSync(path)) {\n const current = loadWorkspace(root)\n if (options.contextId && options.contextId !== current.contextId) {\n throw new Error(\n `当前目录已绑定 contextId=${current.contextId};一个物理 Workspace 不能重新绑定为 ${options.contextId}`,\n )\n }\n return current\n }\n\n const contextId = clean(options.contextId || basename(resolve(root)) || 'default')\n const id = clean(options.id || contextId)\n const spec: WorkspaceSpec = {\n $schema: 'dingtalk-agent/workspace@1',\n id,\n contextId,\n fieldId: 'default',\n dws: { profile: '', expectedUserId: '' },\n // 用 Skill name 声明,不把 Workspace 绑死到某个物理安装目录。\n // Resolver 依次查 Workspace override、全局安装和 npm 内置版本。\n skills: ['dingtalk-basic-behavior', ...discoverLocalSkillNames(root)],\n mounts: {\n profile: existsSync(join(root, 'AGENTS.md'))\n ? 'local-md:AGENTS.md' : 'local-md:WORKSPACE.md',\n memory: options.memory || 'local-md:MEMORY.md',\n knowledge: options.knowledge || 'local-md:knowledge/INDEX.md',\n skills: 'local-dir:skills',\n },\n }\n\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, JSON.stringify(spec, null, 2) + '\\n', { flag: 'wx' })\n writeDefaultMarkdown(root, spec)\n for (const dir of ['.dingtalk-agent/cache', '.dingtalk-agent/pending']) {\n mkdirSync(join(root, dir), { recursive: true })\n }\n return spec\n}\n\nexport function loadWorkspace(root: string): WorkspaceSpec {\n const path = workspacePath(root)\n if (!existsSync(path)) {\n throw new Error(\n '缺少 .dingtalk-agent/workspace.json;只有 Prepared Run runtime 才需要 `dingtalk-agent init`。' +\n '普通 Agent Session 请使用全局 Skill,按需运行 `dingtalk-agent bootstrap`。',\n )\n }\n let value: unknown\n try { value = JSON.parse(readFileSync(path, 'utf8')) }\n catch (error) { throw new Error(`Workspace manifest 不是合法 JSON: ${error.message}`) }\n return validateWorkspace(value)\n}\n\nexport function resolveContextId(spec: WorkspaceSpec, supplied = ''): string {\n const contextId = clean(supplied || spec.contextId)\n if (contextId !== spec.contextId) {\n throw new Error(\n `contextId=${contextId} 不属于当前 Workspace(期望 ${spec.contextId});请由上游选择正确工作目录`,\n )\n }\n return contextId\n}\n\n/**\n * Provider 只负责把语义内容冻结成本地 Markdown;锁、Wait、去重和 Receipt 不走这里。\n * dingtalk-doc 只读显式 node,不搜索、不创建、不覆盖。\n */\nexport function snapshotWorkspaceMounts(\n root: string,\n runPath: string,\n spec: WorkspaceSpec,\n): MountSnapshot[] {\n const destination = join(runPath, 'context', 'mounts')\n mkdirSync(destination, { recursive: true })\n const snapshots: MountSnapshot[] = []\n\n for (const [slot, uri] of Object.entries(spec.mounts)) {\n const mount = parseMount(uri)\n if (mount.provider === 'local-dir') {\n // skills 是逻辑槽:实际内容由 Skill resolver 从 Workspace override、\n // 全局目录或 npm 内置版本解析并在 Session 创建时冻结。\n if (slot !== 'skills') safeLocalPath(root, mount.ref)\n snapshots.push({\n slot, provider: mount.provider, source: uri,\n // P0 的目录型 mount 只有 skills;真实内容由 Session 绑定并冻结到这里。\n snapshotPath: slot === 'skills' ? 'context/skills' : '', hash: '',\n })\n continue\n }\n\n const markdown = mount.provider === 'local-md'\n ? readFileSync(safeLocalPath(root, mount.ref), 'utf8')\n : String(dws.readDoc(mount.ref, spec.dws.profile))\n const path = join(destination, `${safeName(slot)}.md`)\n writeFileSync(path, markdown.endsWith('\\n') ? markdown : markdown + '\\n')\n snapshots.push({\n slot,\n provider: mount.provider,\n source: uri,\n snapshotPath: relative(runPath, path).split('\\\\').join('/'),\n hash: digest(markdown),\n })\n }\n\n writeFileSync(\n join(destination, 'manifest.json'),\n JSON.stringify({ $schema: 'dingtalk-agent/mount-snapshot@1', entries: snapshots }, null, 2) + '\\n',\n )\n return snapshots\n}\n\nfunction validateWorkspace(value: unknown): WorkspaceSpec {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Workspace manifest 必须是 JSON object')\n }\n const input = value as Record<string, any>\n if (input.$schema !== 'dingtalk-agent/workspace@1') {\n throw new Error('Workspace manifest 缺少 dingtalk-agent/workspace@1 schema')\n }\n for (const key of ['id', 'contextId', 'fieldId']) {\n if (!clean(input[key])) throw new Error(`Workspace manifest 缺少 ${key}`)\n }\n if (!Array.isArray(input.skills) || input.skills.some((item: unknown) => typeof item !== 'string')) {\n throw new Error('Workspace skills 必须是 string[]')\n }\n if (!input.dws || typeof input.dws.profile !== 'string' ||\n typeof input.dws.expectedUserId !== 'string') {\n throw new Error('Workspace dws 必须包含 string profile / expectedUserId')\n }\n const requiredSlots = ['profile', 'memory', 'knowledge', 'skills']\n if (!input.mounts || requiredSlots.some((slot) => typeof input.mounts[slot] !== 'string')) {\n throw new Error(`Workspace mounts 必须包含 ${requiredSlots.join(' / ')}`)\n }\n for (const uri of Object.values(input.mounts)) parseMount(String(uri))\n return input as WorkspaceSpec\n}\n\nfunction parseMount(uri: string): {\n provider: 'local-md' | 'local-dir' | 'dingtalk-doc'\n ref: string\n} {\n const separator = uri.indexOf(':')\n const provider = uri.slice(0, separator)\n const ref = separator >= 0 ? uri.slice(separator + 1).trim() : ''\n if (!['local-md', 'local-dir', 'dingtalk-doc'].includes(provider) || !ref) {\n throw new Error(`不支持的 Workspace mount: ${uri}`)\n }\n return { provider: provider as 'local-md' | 'local-dir' | 'dingtalk-doc', ref }\n}\n\nfunction safeLocalPath(root: string, ref: string): string {\n const rootReal = realpathSync(resolve(root))\n const candidate = resolve(rootReal, ref)\n if (!existsSync(candidate)) throw new Error(`Workspace mount 不存在: ${ref}`)\n const actual = realpathSync(candidate)\n const rel = relative(rootReal, actual)\n if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`)) {\n throw new Error(`Workspace local mount 必须位于当前目录内: ${ref}`)\n }\n return actual\n}\n\nfunction writeDefaultMarkdown(root: string, spec: WorkspaceSpec): void {\n const files: Array<[string, string]> = [\n ['WORKSPACE.md', `# Agent Workspace\\n\\n- Context ID: ${spec.contextId}\\n- Workspace: ${spec.id}\\n- Field: ${spec.fieldId}\\n\\n这里定义稳定的身份、职责、协作边界和内容挂载。\\n`],\n ['MEMORY.md', '# Long-term Memory\\n\\n只保存经过筛选、带来源的长期记忆。当前事项放在 Session memory。\\n'],\n ['knowledge/INDEX.md', '# Knowledge Index\\n\\n按需列出本 Workspace 可用的知识入口。\\n'],\n ]\n for (const [rel, content] of files) {\n const path = join(root, rel)\n mkdirSync(dirname(path), { recursive: true })\n if (!existsSync(path)) writeFileSync(path, content)\n }\n}\n\nfunction safeName(value: string): string {\n return value.replace(/[^a-zA-Z0-9._-]+/g, '-')\n}\n\nfunction discoverLocalSkillNames(root: string): string[] {\n const directory = join(root, 'skills')\n if (!existsSync(directory) || !lstatSync(directory).isDirectory()) return []\n const names: string[] = []\n for (const entry of readdirSync(directory, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const path = join(directory, entry.name, 'SKILL.md')\n if (!existsSync(path)) continue\n const markdown = readFileSync(path, 'utf8')\n const frontmatter = markdown.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---/)?.[1] || ''\n const name = frontmatter.match(/^name:\\s*['\"]?([^'\"\\r\\n]+)['\"]?\\s*$/m)?.[1]?.trim() || ''\n if (!name) throw new Error(`本地 Role Skill 缺少 frontmatter name: ${path}`)\n if (name !== entry.name) {\n throw new Error(`本地 Role Skill 目录名与 name 不一致: ${entry.name} != ${name}`)\n }\n if (name !== 'dingtalk-basic-behavior') names.push(name)\n }\n return [...new Set(names)].sort()\n}\n\nfunction clean(value: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n"]}
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -2,21 +2,74 @@
|
|
|
2
2
|
|
|
3
3
|
## 推荐入口
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
首次安装和升级都从确定性的用户级 `npm install` 开始:
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
npm install --global --prefix "$HOME/.local" \
|
|
9
|
+
--registry=https://registry.npmjs.org @xdxer/dingtalk-agent@beta
|
|
10
|
+
"$HOME/.local/bin/dta" setup --skip-cli-install
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
Why
|
|
13
|
+
Why:如果 PATH 中已有旧版 `dta`,npm exec 可能直接复用旧 binary,而不执行指定的新版本;`npm install --prefix` 会确定性升级,绝对路径则不依赖当前 shell 是否已载入新 PATH。安装完成后优先使用短命令;`dta` 与完整名称完全等价:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
dta --version
|
|
17
|
+
dta doctor
|
|
18
|
+
# 等价于 dingtalk-agent doctor
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 自升级
|
|
22
|
+
|
|
23
|
+
完成第一次安装后,CLI 可以自行升级:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
dta upgrade
|
|
27
|
+
dta upgrade --dry-run
|
|
28
|
+
dta upgrade --channel beta
|
|
29
|
+
dta upgrade --channel latest
|
|
30
|
+
dta upgrade --version 0.1.4-beta.7
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
默认通道由当前版本决定:预发布版继续跟随 `beta`,稳定版跟随 `latest`。升级过程按顺序执行:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
npm view 解析目标版本
|
|
37
|
+
→ npm install --global --prefix ~/.local 安装目标
|
|
38
|
+
→ 使用 ~/.local/bin/dta --version 校验新 binary
|
|
39
|
+
→ 使用新 binary 执行 setup --skip-cli-install
|
|
40
|
+
→ 复核 PATH、DWS、Skill 与 Claude Code/Codex/OpenCode
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`--force` 可用于重装当前版本和修复损坏安装;`--json` 可供自动化宿主读取。CLI 升级成功但 DWS 等环境检查未 ready 时,不会把升级回滚成旧代码,而会返回退出码 2 和明确的复核命令。
|
|
44
|
+
|
|
45
|
+
## 发布前隔离验收
|
|
46
|
+
|
|
47
|
+
在 checkout 中准备 beta 候选时运行:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm run release:check
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
这不是 `npm pack --dry-run` 的别名。它会:
|
|
54
|
+
|
|
55
|
+
1. 核对 `package.json` / `package-lock.json` / CLI 版本;
|
|
56
|
+
2. 生成真实 tarball,检查必需运行时、Schema、Skill、fixture 和 baseline,拒绝 state/results/凭据路径;
|
|
57
|
+
3. 用 `npm install --offline` 安装到全新 HOME/prefix;
|
|
58
|
+
4. 使用合成 DWS 与 skills installer 执行 setup/doctor,确认 Basic 只有一份 canonical copy,Claude Code 为相对链接,Codex/OpenCode 共享 canonical;
|
|
59
|
+
5. 从安装包运行 direct bootstrap 和 plan-only OpenCode eval;
|
|
60
|
+
6. 从同一 tarball 强制重装,再生成上一 beta 的显式 rollback dry-run。
|
|
61
|
+
|
|
62
|
+
验收不联系真实 DWS/Multica,不创建机器人或 Trigger,也不执行 Tag、GitHub Release 或 npm publish。这些操作必须在 Live 缺口处理并获得用户单独授权后执行。
|
|
63
|
+
|
|
64
|
+
npm 全局命令会被链接到 `{prefix}/bin`,但不同 Node 版本管理器可能使用不同 prefix;包已经安装不代表该目录已进入当前 shell 的 PATH。因此固定使用 `~/.local` prefix,并用绝对路径启动一次 setup,由它幂等补齐后续 shell PATH。
|
|
12
65
|
|
|
13
66
|
## setup 做什么
|
|
14
67
|
|
|
15
68
|
```text
|
|
16
|
-
|
|
69
|
+
npm install → dta setup
|
|
17
70
|
→ 安装当前版本到 ~/.local/bin
|
|
18
71
|
→ 检查并幂等补充 ~/.zshrc / ~/.bashrc PATH
|
|
19
|
-
→ 安装 canonical Basic Behavior
|
|
72
|
+
→ 安装 canonical 内置 Skill(Basic Behavior + Compose)
|
|
20
73
|
→ 暴露给 Claude Code,验证 Codex/OpenCode 共享发现
|
|
21
74
|
→ 检查 DWS 版本和认证
|
|
22
75
|
→ 给出唯一下一条命令
|
|
@@ -42,7 +95,9 @@ export PATH="$HOME/.local/bin:$PATH"
|
|
|
42
95
|
不希望修改 shell 配置时:
|
|
43
96
|
|
|
44
97
|
```bash
|
|
45
|
-
|
|
98
|
+
npm install --global --prefix "$HOME/.local" \
|
|
99
|
+
--registry=https://registry.npmjs.org @xdxer/dingtalk-agent@beta
|
|
100
|
+
"$HOME/.local/bin/dta" setup --skip-cli-install --no-shell-write
|
|
46
101
|
```
|
|
47
102
|
|
|
48
103
|
### DWS
|
|
@@ -65,7 +120,15 @@ dws auth login
|
|
|
65
120
|
|
|
66
121
|
## Skill 安装策略
|
|
67
122
|
|
|
68
|
-
`
|
|
123
|
+
`dta` 不维护第二套 Skill 安装器。`dta skill install` 等价于把 npm 包内的 Skill 目录交给开放生态的 `npx skills add`:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npx --yes --registry=https://registry.npmjs.org --package=skills@latest -- skills add \
|
|
127
|
+
<package>/skills/dingtalk-basic-behavior \
|
|
128
|
+
--global --yes --agent claude-code codex opencode
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
上游 `skills` CLI 负责 canonical copy、客户端链接、覆盖和卸载语义:
|
|
69
132
|
|
|
70
133
|
| 客户端 | 发现方式 | 路径 |
|
|
71
134
|
|---|---|---|
|
|
@@ -73,13 +136,16 @@ dws auth login
|
|
|
73
136
|
| Codex | shared Agent Skills | `~/.agents/skills/dingtalk-basic-behavior` |
|
|
74
137
|
| OpenCode | shared Agent Skills | `~/.agents/skills/dingtalk-basic-behavior` |
|
|
75
138
|
|
|
76
|
-
|
|
139
|
+
检查、重装当前 npm 包内版本和卸载:
|
|
77
140
|
|
|
78
141
|
```bash
|
|
79
|
-
|
|
80
|
-
|
|
142
|
+
dta skill status
|
|
143
|
+
dta skill upgrade
|
|
144
|
+
dta skill uninstall
|
|
81
145
|
```
|
|
82
146
|
|
|
147
|
+
`skill status` 只做只读发现检查;`install/upgrade/uninstall` 分别委托 `skills add/add/remove`。这里显式指定 `--package=skills@latest -- skills`,避免 setup 本身由 npx 启动时产生 nested npx 简写解析问题。旧版 dta 写入的管理 marker 会在第一次 `skills add` 时被上游 canonical copy 替换,此后不再存在两套管理状态。
|
|
148
|
+
|
|
83
149
|
OpenCode 官方同时支持 `.opencode/skills`、`.claude/skills` 和 `.agents/skills`,所以不需要再复制第三份内容。
|
|
84
150
|
|
|
85
151
|
## 使用 npx skills
|
|
@@ -97,7 +163,7 @@ npx skills add ./skills/dingtalk-basic-behavior \
|
|
|
97
163
|
--global --yes --agent claude-code --agent codex --agent opencode
|
|
98
164
|
```
|
|
99
165
|
|
|
100
|
-
|
|
166
|
+
也可以完全绕过 `dta skill ...`,直接使用 `npx skills` 管理;两种入口最终调用的是同一个上游安装器。
|
|
101
167
|
|
|
102
168
|
## 初始化的三个层级
|
|
103
169
|
|
|
@@ -110,14 +176,14 @@ init Workspace 级,可选:只为长期 Workspace / Prepared Run 创建
|
|
|
110
176
|
普通 Claude Code、Codex 或 OpenCode 会话:
|
|
111
177
|
|
|
112
178
|
```bash
|
|
113
|
-
|
|
179
|
+
dta bootstrap --json
|
|
114
180
|
```
|
|
115
181
|
|
|
116
182
|
需要可信钉钉事件、Session/Run/Wait/Receipt 时才执行:
|
|
117
183
|
|
|
118
184
|
```bash
|
|
119
|
-
|
|
120
|
-
|
|
185
|
+
dta init
|
|
186
|
+
dta prepare --event-file event.json --json
|
|
121
187
|
```
|
|
122
188
|
|
|
123
189
|
## Doctor 退出码
|
|
@@ -126,6 +192,45 @@ dingtalk-agent prepare --event-file event.json --json
|
|
|
126
192
|
- `2`:至少一个必要条件不满足,同时输出确定的修复命令;
|
|
127
193
|
- `--json`:输出 `dingtalk-agent/doctor@1`,供安装器、CI 或宿主解析。
|
|
128
194
|
|
|
195
|
+
## 开发者 Golden Path
|
|
196
|
+
|
|
197
|
+
安装完成后,一个岗位 Agent 只需要三组输入:本地 `AGENTS.md`、本地 `skills/<role>/SKILL.md`,以及从 compose Skill 模板创建的 `agent.bindings.json`。本地模板把 memory/knowledge 指向 Markdown;远端模板只把这两个语义槽路由到专用钉钉文档,产物与控制状态仍留在 Agent 根目录。
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# 在 Agent 根目录
|
|
201
|
+
dta agent enhance --project-name <agent-name> \
|
|
202
|
+
--role-skill <role-skill-name> --dry-run --json
|
|
203
|
+
|
|
204
|
+
# 审阅 plan 后执行其 apply.command(当前 plan-id + 显式 yes)
|
|
205
|
+
dta agent enhance --project-name <agent-name> \
|
|
206
|
+
--role-skill <role-skill-name> \
|
|
207
|
+
--plan-id <current-plan-id> --yes --json
|
|
208
|
+
|
|
209
|
+
# 把 AGENTS.md 与 Role Skill 的模板占位符替换为真实岗位语义后
|
|
210
|
+
dta bootstrap --bindings agent.bindings.json --json
|
|
211
|
+
dta agent audit --bindings agent.bindings.json \
|
|
212
|
+
--require-skill <role-skill-name> --json
|
|
213
|
+
|
|
214
|
+
# 静态项修复后,证明 Basic Skill 在 OpenCode 中真正加载
|
|
215
|
+
dta agent audit --bindings agent.bindings.json \
|
|
216
|
+
--require-skill <role-skill-name> --verify-load --yes --json
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
`agent enhance` 默认只生成计划,不写文件、不访问 DWS、也不创建 Trigger;apply 更新旧文件前把原值备份到 gitignored state 目录,并在 source/config 漂移时拒绝旧 plan-id。第一次 `agent audit` 默认不访问 DWS、不调用模型。它分别检查 Definition、本地文件/产物目录、Role Skill 真实语义、OpenCode Basic instruction/exposure 和已有证据,缺口用稳定 check ID 与修复动作返回;`partial` 的退出码是 2。`--verify-load --yes` 只增加隔离 OpenCode 评测,并生成与当前 Definition、bindings、配置和 Skill hash 绑定的 load evidence。
|
|
220
|
+
|
|
221
|
+
远端 memory/knowledge 需要另跑授权的 `dta lab eval --engine storage`,再把其报告传给 `--remote-report`。审计不会用旧缓存替代 DWS 身份、类型、hash 和独立回读,也不会把远端文档升级为 Wait、Receipt、锁或凭据介质。
|
|
222
|
+
|
|
223
|
+
## 错误提示约定
|
|
224
|
+
|
|
225
|
+
CLI 错误统一包含两层信息:
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
错误: 发生了什么,以及为什么拒绝继续
|
|
229
|
+
提示: 下一条可复制执行的恢复命令
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
命令拼写错误会建议最接近的命令;DWS 错误指向 `dta doctor`/`dws auth login`;没有可信 Run 时会明确要求先 `prepare`,不会暗中初始化或猜测目标。
|
|
233
|
+
|
|
129
234
|
## 设计依据
|
|
130
235
|
|
|
131
236
|
- [npm Folders](https://docs.npmjs.com/files/folders.html/):Unix 全局 executable 被链接到 `{prefix}/bin`;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# 一小时复制第二个岗位 Agent
|
|
2
|
+
|
|
3
|
+
## 结论
|
|
4
|
+
|
|
5
|
+
第二个 Agent 不复制运行时,只复制一份 Agent kit 并替换四类绑定:`AGENTS.md`、Role Skills、Field/存储、DWS authority。事件监听不在本流程内;没有事件时 Agent 仍以 Direct/Mounted Session 正常工作,有可信事件时再进入同一个 Prepared Runtime。
|
|
6
|
+
|
|
7
|
+
仓库提供两份已通过同一合同的实例:
|
|
8
|
+
|
|
9
|
+
- `examples/agents/fde-coach`:FDE 教练;
|
|
10
|
+
- `examples/agents/release-manager`:发布经理。
|
|
11
|
+
|
|
12
|
+
两者共享 Basic Behavior、Invocation、Session/Run/Wait、双半闸门与 Receipt;Definition、Role Skill、Field、Session state、记忆和权限完全隔离。
|
|
13
|
+
|
|
14
|
+
## 60 分钟执行表
|
|
15
|
+
|
|
16
|
+
| 时间 | 开发者动作 | 验收标准 |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| 0–10 分钟 | 复制任一 example,改目录名 | 原 example 不被覆盖,新目录不含 `.dingtalk-agent` |
|
|
19
|
+
| 10–20 分钟 | 改 `AGENTS.md` 的身份、服务对象、职责、交付与拒绝边界 | 另一个 Agent 能回答“我是谁、负责什么、不做什么” |
|
|
20
|
+
| 20–30 分钟 | 新建/改名 `skills/<role>/SKILL.md` | 目录名等于 frontmatter `name`;只含岗位方法,不重复基础行为 |
|
|
21
|
+
| 30–40 分钟 | 配置 Field、存储路由和 DWS authority | 使用可信 ID;不同 Agent 不共用 state root、业务 scope 或生产权限 |
|
|
22
|
+
| 40–50 分钟 | 先 `dta bootstrap --json`,需要 Prepared Run 时再显式 `dta init` | Direct 默认 ready/partial 可解释;init 采用 `AGENTS.md` 并发现 Role Skill |
|
|
23
|
+
| 50–60 分钟 | 跑合同/mock Lab,检查冻结快照和隔离 | 无可信 target 不外发;两个 Agent 的 Definition/Session/记忆/权限不串 |
|
|
24
|
+
|
|
25
|
+
## 最小操作
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cp -R examples/agents/release-manager /path/to/my-agent
|
|
29
|
+
cd /path/to/my-agent
|
|
30
|
+
|
|
31
|
+
# 先验证本体;这一步不要求 Workspace,也不产生钉钉副作用
|
|
32
|
+
dta bootstrap --json
|
|
33
|
+
|
|
34
|
+
# 只有需要可信事件和 Prepared Run 时才初始化一次
|
|
35
|
+
dta init
|
|
36
|
+
dta bootstrap --json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
首次 `init` 会优先采用已有 `AGENTS.md`,发现 `skills/*/SKILL.md`,并保留已有 `fields/default/field.json`。初始化后新增 Skill 不会自动热启用:离线评审后把 Skill name 加入 `.dingtalk-agent/workspace.json#skills`,由新 Session 重新冻结。
|
|
40
|
+
|
|
41
|
+
## 自动化验收
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm run typecheck
|
|
45
|
+
npm run eval:contract
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
合同 42 会从两份 example 分别创建临时 Workspace,并检查:
|
|
49
|
+
|
|
50
|
+
1. 初始化前 Direct bootstrap 可工作且没有可信 target;
|
|
51
|
+
2. 初始化后 `AGENTS.md`、Role Skill 与显式 Field 被正确采用;
|
|
52
|
+
3. 两个 Definition、DWS profile、Session ID 不同,共享 Basic Behavior hash;
|
|
53
|
+
4. FDE 的 Task Checkpoint 与 Memory Candidate 在发布经理 state root 中不可见;
|
|
54
|
+
5. 两者都通过同一 fake-DWS Lab 的 Action/Receipt/平台回读合同。
|
|
55
|
+
|
|
56
|
+
2026-07-16 本地基线为 42/42,通过;双 Agent 合同自动执行约 2–3 秒。这个数字证明模板化装配和隔离可自动验证,不代表真实账号、专用群、AI 表格和钉钉文档已接通。真实 L4 仍需为每个 Agent 提供专用测试对象、allowlist 和明确 `--live --yes` 授权。
|
|
57
|
+
|
|
58
|
+
## 验收边界
|
|
59
|
+
|
|
60
|
+
- 通过:开发者只改本体、岗位 Skill、存储/Field/authority,即可得到第二个结构完整、状态隔离的 Agent;
|
|
61
|
+
- 不包含:Webhook、定时器、personal-event listener 等触发端;
|
|
62
|
+
- 不冒充:mock 平台可见不等于真实钉钉送达,真实写入必须另走 Lab L3/L4 晋级门禁。
|
|
Binary file
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 900" width="1440" height="900" role="img" aria-labelledby="title desc">
|
|
2
|
+
<title id="title">dingtalk-agent 三层语义记忆与控制状态拓扑</title>
|
|
3
|
+
<desc id="desc">Agent Run 按需读写三层语义记忆:Session 工作记忆、钉钉原生业务记忆、长期知识;Wait、锁、generation、幂等和 Receipt 位于独立控制状态;Git 用于定义与 Skill 的版本发布,不作为运行时锁或 PCB。</desc>
|
|
4
|
+
<style>
|
|
5
|
+
text { font-family:'Helvetica Neue',Helvetica,Arial,'PingFang SC','Microsoft YaHei',sans-serif; }
|
|
6
|
+
.title { fill:#111827;font-size:28px;font-weight:700; }
|
|
7
|
+
.subtitle { fill:#6b7280;font-size:14px; }
|
|
8
|
+
.lane { fill:#475569;font-size:12px;font-weight:700;letter-spacing:.08em; }
|
|
9
|
+
.node-title { fill:#111827;font-size:16px;font-weight:700; }
|
|
10
|
+
.node-sub { fill:#4b5563;font-size:12px; }
|
|
11
|
+
.small { fill:#64748b;font-size:11px; }
|
|
12
|
+
.label { fill:#475569;font-size:11px;font-weight:600; }
|
|
13
|
+
</style>
|
|
14
|
+
<defs>
|
|
15
|
+
<marker id="blue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#2563eb"/></marker>
|
|
16
|
+
<marker id="green" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#059669"/></marker>
|
|
17
|
+
<marker id="purple" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#7c3aed"/></marker>
|
|
18
|
+
<marker id="rose" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#dc2626"/></marker>
|
|
19
|
+
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%"><feDropShadow dx="0" dy="2" stdDeviation="3" flood-color="#0f172a" flood-opacity=".10"/></filter>
|
|
20
|
+
</defs>
|
|
21
|
+
|
|
22
|
+
<rect width="1440" height="900" fill="#ffffff"/>
|
|
23
|
+
<text x="40" y="48" class="title">三层语义记忆,各归各的介质</text>
|
|
24
|
+
<text x="40" y="75" class="subtitle">语义记忆服务“想起什么”;控制状态保证“只执行一次、从正确位置继续”。两者必须分开。</text>
|
|
25
|
+
|
|
26
|
+
<rect x="30" y="105" width="300" height="620" rx="14" fill="#eff6ff" stroke="#60a5fa" stroke-width="1.6"/>
|
|
27
|
+
<text x="50" y="132" class="lane">AGENT RUNTIME</text>
|
|
28
|
+
|
|
29
|
+
<rect x="70" y="180" width="220" height="122" rx="12" fill="#ffffff" stroke="#60a5fa" stroke-width="2.2" filter="url(#shadow)"/>
|
|
30
|
+
<rect x="74" y="184" width="212" height="114" rx="9" fill="none" stroke="#60a5fa" stroke-width=".8" opacity=".5"/>
|
|
31
|
+
<text x="180" y="218" text-anchor="middle" class="node-title">Agent Run</text>
|
|
32
|
+
<text x="180" y="243" text-anchor="middle" class="node-sub">一次事件唤醒</text>
|
|
33
|
+
<text x="180" y="265" text-anchor="middle" class="node-sub">推理 · 工具 · ActionRequest</text>
|
|
34
|
+
<text x="180" y="286" text-anchor="middle" class="small">沙箱可丢弃</text>
|
|
35
|
+
|
|
36
|
+
<rect x="70" y="355" width="220" height="132" rx="10" fill="#faf5ff" stroke="#c084fc" stroke-width="1.7"/>
|
|
37
|
+
<text x="180" y="388" text-anchor="middle" class="node-title">Session</text>
|
|
38
|
+
<text x="180" y="412" text-anchor="middle" class="node-sub">一件事的稳定语义边界</text>
|
|
39
|
+
<text x="180" y="435" text-anchor="middle" class="node-sub">goal · checkpoint · next</text>
|
|
40
|
+
<text x="180" y="457" text-anchor="middle" class="node-sub">waitFor · evidence</text>
|
|
41
|
+
<text x="180" y="478" text-anchor="middle" class="small">跨 Run,不跨事项</text>
|
|
42
|
+
|
|
43
|
+
<rect x="70" y="540" width="220" height="128" rx="10" fill="#fef2f2" stroke="#f87171" stroke-width="1.8" stroke-dasharray="6 4"/>
|
|
44
|
+
<text x="180" y="572" text-anchor="middle" class="node-title">Control State Client</text>
|
|
45
|
+
<text x="180" y="596" text-anchor="middle" class="node-sub">claim · resume · commit</text>
|
|
46
|
+
<text x="180" y="619" text-anchor="middle" class="node-sub">不暴露平台凭据</text>
|
|
47
|
+
<text x="180" y="643" text-anchor="middle" class="small">通过宿主原子接口读写</text>
|
|
48
|
+
|
|
49
|
+
<path d="M180 302 L180 355" fill="none" stroke="#2563eb" stroke-width="2" marker-end="url(#blue)"/>
|
|
50
|
+
<path d="M180 487 L180 540" fill="none" stroke="#dc2626" stroke-width="1.8" marker-end="url(#rose)"/>
|
|
51
|
+
|
|
52
|
+
<rect x="365" y="105" width="645" height="620" rx="14" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.2" stroke-dasharray="7 5"/>
|
|
53
|
+
<text x="385" y="132" class="lane">THREE SEMANTIC MEMORY TIERS</text>
|
|
54
|
+
|
|
55
|
+
<rect x="405" y="165" width="565" height="138" rx="12" fill="#eff6ff" stroke="#93c5fd" stroke-width="1.8" filter="url(#shadow)"/>
|
|
56
|
+
<rect x="425" y="184" width="78" height="34" rx="17" fill="#2563eb"/><text x="464" y="207" text-anchor="middle" fill="#ffffff" font-size="13" font-weight="700">L1 短期</text>
|
|
57
|
+
<text x="525" y="205" class="node-title">Session 工作记忆</text>
|
|
58
|
+
<text x="425" y="242" class="node-sub">介质:宿主 state root / 原子本地存储;可生成 Markdown checkpoint 供人审阅</text>
|
|
59
|
+
<text x="425" y="267" class="node-sub">内容:当前目标、做到哪、下一步、在等什么、已有哪些证据</text>
|
|
60
|
+
<text x="425" y="289" class="small">高频更新 · 事项结束后归档/压缩 · 不承担锁和幂等</text>
|
|
61
|
+
|
|
62
|
+
<rect x="405" y="348" width="565" height="138" rx="12" fill="#f0fdfa" stroke="#5eead4" stroke-width="1.8" filter="url(#shadow)"/>
|
|
63
|
+
<rect x="425" y="367" width="78" height="34" rx="17" fill="#0f766e"/><text x="464" y="390" text-anchor="middle" fill="#ffffff" font-size="13" font-weight="700">L2 工作</text>
|
|
64
|
+
<text x="525" y="388" class="node-title">钉钉原生业务记忆</text>
|
|
65
|
+
<text x="425" y="425" class="node-sub">介质:AI 表格宽表 / Todo / Calendar / 业务系统的唯一事实源</text>
|
|
66
|
+
<text x="425" y="450" class="node-sub">内容:日报摘要、待办快照、互动记录、可聚合的业务热数据</text>
|
|
67
|
+
<text x="425" y="472" class="small">结构化查询 · 跨 Agent 可读 · ID 与 schema 必须显式绑定</text>
|
|
68
|
+
|
|
69
|
+
<rect x="405" y="531" width="565" height="138" rx="12" fill="#f0fdf4" stroke="#86efac" stroke-width="1.8" filter="url(#shadow)"/>
|
|
70
|
+
<rect x="425" y="550" width="78" height="34" rx="17" fill="#15803d"/><text x="464" y="573" text-anchor="middle" fill="#ffffff" font-size="13" font-weight="700">L3 长期</text>
|
|
71
|
+
<text x="525" y="571" class="node-title">知识与能力资产</text>
|
|
72
|
+
<text x="425" y="608" class="node-sub">介质:钉钉文档树 / 知识库 / Wiki;按来源、范围与版本治理</text>
|
|
73
|
+
<text x="425" y="633" class="node-sub">内容:身份、职责、Skill、SOP、人物模式、错误库、稳定知识</text>
|
|
74
|
+
<text x="425" y="655" class="small">低频写入 · 需证据与准入 · 新 Run 才加载已发布版本</text>
|
|
75
|
+
|
|
76
|
+
<path d="M405 220 L330 220" fill="none" stroke="#059669" stroke-width="1.8" marker-end="url(#green)"/>
|
|
77
|
+
<path d="M330 258 L405 258" fill="none" stroke="#059669" stroke-width="1.6" stroke-dasharray="5 3" marker-end="url(#green)"/>
|
|
78
|
+
<rect x="342" y="194" width="52" height="20" rx="5" fill="#ffffff" opacity=".96"/><text x="368" y="209" text-anchor="middle" class="label">read</text>
|
|
79
|
+
<rect x="342" y="266" width="52" height="20" rx="5" fill="#ffffff" opacity=".96"/><text x="368" y="281" text-anchor="middle" class="label">write</text>
|
|
80
|
+
|
|
81
|
+
<path d="M405 400 L330 400" fill="none" stroke="#059669" stroke-width="1.8" marker-end="url(#green)"/>
|
|
82
|
+
<path d="M330 444 L405 444" fill="none" stroke="#059669" stroke-width="1.6" stroke-dasharray="5 3" marker-end="url(#green)"/>
|
|
83
|
+
<rect x="337" y="374" width="62" height="20" rx="5" fill="#ffffff" opacity=".96"/><text x="368" y="389" text-anchor="middle" class="label">query</text>
|
|
84
|
+
<rect x="342" y="452" width="52" height="20" rx="5" fill="#ffffff" opacity=".96"/><text x="368" y="467" text-anchor="middle" class="label">write</text>
|
|
85
|
+
|
|
86
|
+
<path d="M405 583 L330 583" fill="none" stroke="#059669" stroke-width="1.8" marker-end="url(#green)"/>
|
|
87
|
+
<path d="M330 627 L405 627" fill="none" stroke="#059669" stroke-width="1.6" stroke-dasharray="5 3" marker-end="url(#green)"/>
|
|
88
|
+
<rect x="342" y="557" width="52" height="20" rx="5" fill="#ffffff" opacity=".96"/><text x="368" y="572" text-anchor="middle" class="label">load</text>
|
|
89
|
+
<rect x="335" y="635" width="66" height="20" rx="5" fill="#ffffff" opacity=".96"/><text x="368" y="650" text-anchor="middle" class="label">propose</text>
|
|
90
|
+
|
|
91
|
+
<path d="M687 303 L687 348" fill="none" stroke="#7c3aed" stroke-width="1.7" marker-end="url(#purple)"/>
|
|
92
|
+
<path d="M687 486 L687 531" fill="none" stroke="#7c3aed" stroke-width="1.7" marker-end="url(#purple)"/>
|
|
93
|
+
<rect x="700" y="316" width="78" height="20" rx="5" fill="#ffffff" opacity=".96"/><text x="739" y="331" text-anchor="middle" class="label">结构化</text>
|
|
94
|
+
<rect x="700" y="499" width="78" height="20" rx="5" fill="#ffffff" opacity=".96"/><text x="739" y="514" text-anchor="middle" class="label">验证沉淀</text>
|
|
95
|
+
|
|
96
|
+
<rect x="1045" y="105" width="365" height="320" rx="14" fill="#fef2f2" stroke="#f87171" stroke-width="1.6" stroke-dasharray="7 5"/>
|
|
97
|
+
<text x="1065" y="132" fill="#b91c1c" font-size="12" font-weight="700" letter-spacing=".08em">CONTROL PLANE · 不是记忆</text>
|
|
98
|
+
<text x="1227" y="173" text-anchor="middle" class="node-title">宿主控制状态</text>
|
|
99
|
+
|
|
100
|
+
<rect x="1080" y="200" width="295" height="176" rx="10" fill="#ffffff" stroke="#fca5a5" stroke-width="1.5"/>
|
|
101
|
+
<text x="1105" y="230" class="node-sub">• EventIndex / delivery claim</text>
|
|
102
|
+
<text x="1105" y="258" class="node-sub">• Wait / correlation / timer</text>
|
|
103
|
+
<text x="1105" y="286" class="node-sub">• lock / generation / cancellation</text>
|
|
104
|
+
<text x="1105" y="314" class="node-sub">• idempotency key / action budget</text>
|
|
105
|
+
<text x="1105" y="342" class="node-sub">• Action intent / attempt / receipt</text>
|
|
106
|
+
<text x="1227" y="366" text-anchor="middle" class="small">需要 CAS / 原子写 / 可恢复语义</text>
|
|
107
|
+
|
|
108
|
+
<path d="M1045 270 L1018 270 L1018 708 L320 708 L320 604 L290 604" fill="none" stroke="#dc2626" stroke-width="1.8" marker-end="url(#rose)"/>
|
|
109
|
+
<rect x="925" y="681" width="88" height="20" rx="5" fill="#ffffff" opacity=".96"/><text x="969" y="696" text-anchor="middle" class="label">atomic state</text>
|
|
110
|
+
|
|
111
|
+
<rect x="1045" y="465" width="365" height="260" rx="14" fill="#faf5ff" stroke="#c084fc" stroke-width="1.6"/>
|
|
112
|
+
<text x="1065" y="492" fill="#7e22ce" font-size="12" font-weight="700" letter-spacing=".08em">GIT RELEASE PLANE</text>
|
|
113
|
+
<text x="1227" y="535" text-anchor="middle" class="node-title">定义与 Skill 的版本面</text>
|
|
114
|
+
<text x="1080" y="574" class="node-sub">• Agent Definition / Skill 源码与快照</text>
|
|
115
|
+
<text x="1080" y="603" class="node-sub">• 候选改进、评审、发布、回滚</text>
|
|
116
|
+
<text x="1080" y="632" class="node-sub">• 人可干预的语义 checkpoint 导出</text>
|
|
117
|
+
<rect x="1080" y="656" width="295" height="42" rx="8" fill="#ffffff" stroke="#d8b4fe" stroke-width="1.2"/>
|
|
118
|
+
<text x="1227" y="675" text-anchor="middle" fill="#7e22ce" font-size="12" font-weight="700">Git ≠ runtime lock / Wait / PCB authority</text>
|
|
119
|
+
<text x="1227" y="692" text-anchor="middle" class="small">发布是双向的,运行控制仍归宿主</text>
|
|
120
|
+
|
|
121
|
+
<path d="M1045 585 L1000 585 L1000 600 L970 600" fill="none" stroke="#7c3aed" stroke-width="1.7" stroke-dasharray="5 3" marker-end="url(#purple)"/>
|
|
122
|
+
<rect x="980" y="556" width="63" height="20" rx="5" fill="#ffffff" opacity=".96"/><text x="1011" y="571" text-anchor="middle" class="label">publish</text>
|
|
123
|
+
|
|
124
|
+
<rect x="30" y="765" width="1380" height="78" rx="10" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
|
125
|
+
<text x="50" y="792" fill="#111827" font-size="13" font-weight="700">介质选择原则</text>
|
|
126
|
+
<text x="50" y="821" fill="#334155" font-size="14">当前事项 → Session | 可统计业务事实 → 原生表/任务/日历 | 稳定可复用知识 → 文档/Wiki | 并发与副作用 → Control State | 发布与回滚 → Git</text>
|
|
127
|
+
|
|
128
|
+
<line x1="40" y1="873" x2="76" y2="873" stroke="#059669" stroke-width="1.8" marker-end="url(#green)"/><text x="84" y="877" class="small">读取</text>
|
|
129
|
+
<line x1="150" y1="873" x2="186" y2="873" stroke="#059669" stroke-width="1.6" stroke-dasharray="5 3" marker-end="url(#green)"/><text x="194" y="877" class="small">写入</text>
|
|
130
|
+
<line x1="265" y1="873" x2="301" y2="873" stroke="#7c3aed" stroke-width="1.7" marker-end="url(#purple)"/><text x="309" y="877" class="small">压缩 / 发布</text>
|
|
131
|
+
<line x1="440" y1="873" x2="476" y2="873" stroke="#dc2626" stroke-width="1.8" marker-end="url(#rose)"/><text x="484" y="877" class="small">原子控制</text>
|
|
132
|
+
</svg>
|
|
Binary file
|