@xdxer/dingtalk-agent 0.1.5-beta.13 → 0.1.5-beta.15
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 +29 -0
- package/README.en.md +10 -6
- package/README.md +13 -8
- package/dist/bin/dingtalk-agent.js +7 -6
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/agent-audit.js +28 -10
- package/dist/src/agent-audit.js.map +1 -1
- package/dist/src/agent-enhance.js +63 -30
- package/dist/src/agent-enhance.js.map +1 -1
- package/dist/src/opencode-evals.js +28 -16
- package/dist/src/opencode-evals.js.map +1 -1
- package/dist/src/opencode-workspace.js +1 -0
- package/dist/src/opencode-workspace.js.map +1 -1
- package/docs/ARCHITECTURE.md +15 -13
- package/docs/INSTALLATION.md +4 -2
- package/docs/SELF-TEST.md +1 -1
- package/docs/architecture/agent-platform-connection-layer.svg +1 -1
- package/docs/architecture/dingtalk-agent-architecture.svg +1 -1
- package/docs/schemas/agent-enhancement-plan.schema.json +2 -1
- package/docs/schemas/agent-enhancement-receipt.schema.json +2 -1
- package/lab/agent-eval/remote-state.example.json +1 -1
- package/lab/project-workspace/project.fixture.json +1 -1
- package/lab/robot-eval/pool.example.json +1 -1
- package/package.json +2 -2
- package/skills/core/dta-agent-compose/SKILL.md +5 -3
|
@@ -6,6 +6,7 @@ import { tmpdir } from 'node:os';
|
|
|
6
6
|
import { countInstructionsForPath, instructionTargetsPath, instructionUsesGlob, } from './instruction-path.js';
|
|
7
7
|
export const REQUIRED_BASIC_SKILL = 'dta-basic-behavior';
|
|
8
8
|
export const REQUIRED_BASIC_SKILL_INSTRUCTION = '.agents/skills/dta-basic-behavior/SKILL.md';
|
|
9
|
+
export const DEFAULT_OPENCODE_MODEL = 'deepseek/deepseek-v4-flash';
|
|
9
10
|
/**
|
|
10
11
|
* OpenCode only discovers project Skills by default; it does not load their body.
|
|
11
12
|
* This binding makes the Basic Skill an unconditional instruction while retaining
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opencode-workspace.js","sourceRoot":"","sources":["../../src/opencode-workspace.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto'\nimport {\n existsSync, mkdtempSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync,\n} from 'node:fs'\nimport { spawnSync } from 'node:child_process'\nimport { join, relative, resolve } from 'node:path'\nimport { tmpdir } from 'node:os'\nimport {\n countInstructionsForPath, instructionTargetsPath, instructionUsesGlob,\n} from './instruction-path.js'\n\nexport const REQUIRED_BASIC_SKILL = 'dta-basic-behavior'\nexport const REQUIRED_BASIC_SKILL_INSTRUCTION =\n '.agents/skills/dta-basic-behavior/SKILL.md'\n\nexport interface OpenCodeSkillBinding {\n $schema: 'dingtalk-agent/opencode-skill-binding@1'\n host: 'opencode'\n required: true\n strategy: 'instructions'\n workspace: string\n configPath: string\n instruction: string\n skill: {\n name: string\n version: string\n path: string\n hash: string\n }\n configHash: string\n}\n\nexport interface OpenCodeSkillPreflight extends OpenCodeSkillBinding {\n verified: true\n openCodeVersion: string\n resolvedInstruction: true\n resolvedInstructions: string[]\n discoveredProjectSkill: true\n}\n\n/**\n * OpenCode only discovers project Skills by default; it does not load their body.\n * This binding makes the Basic Skill an unconditional instruction while retaining\n * the native project Skill for discovery and explicit inspection.\n */\nexport function bindRequiredBasicSkill(workspace: string): OpenCodeSkillBinding {\n const workspaceReal = realpathSync(resolve(workspace))\n const skillPath = join(workspaceReal, REQUIRED_BASIC_SKILL_INSTRUCTION)\n if (!existsSync(skillPath)) {\n throw new Error(`OpenCode 必需 Basic Skill 不存在: ${skillPath}`)\n }\n const skillBody = readFileSync(skillPath, 'utf8')\n const name = frontmatterValue(skillBody, 'name')\n const version = metadataVersion(skillBody)\n if (name !== REQUIRED_BASIC_SKILL || !version) {\n throw new Error(`OpenCode Basic Skill 元数据非法: name=${name || 'missing'} version=${version || 'missing'}`)\n }\n\n const configPath = join(workspaceReal, 'opencode.json')\n const config = existsSync(configPath)\n ? parseObject(readFileSync(configPath, 'utf8'), 'opencode.json')\n : {}\n const instructions = config.instructions === undefined\n ? []\n : stringArray(config.instructions, 'opencode.json#instructions')\n const conflictingGlob = instructions.find((item) =>\n instructionUsesGlob(item) && instructionTargetsPath(\n workspaceReal, item, REQUIRED_BASIC_SKILL_INSTRUCTION))\n if (conflictingGlob) {\n throw new Error(\n `OpenCode instruction glob 命中 Basic Skill,无法安全去重: ${conflictingGlob}`)\n }\n config.$schema ||= 'https://opencode.ai/config.json'\n config.instructions = [\n REQUIRED_BASIC_SKILL_INSTRUCTION,\n ...instructions.filter((item) => !instructionTargetsPath(\n workspaceReal, item, REQUIRED_BASIC_SKILL_INSTRUCTION)),\n ]\n\n const permission = config.permission === undefined\n ? {}\n : objectValue(config.permission, 'opencode.json#permission')\n const skillPermission = permission.skill === undefined\n ? {}\n : objectValue(permission.skill, 'opencode.json#permission.skill')\n skillPermission[REQUIRED_BASIC_SKILL] = 'allow'\n permission.skill = skillPermission\n config.permission = permission\n atomicJson(configPath, config)\n\n return {\n $schema: 'dingtalk-agent/opencode-skill-binding@1',\n host: 'opencode',\n required: true,\n strategy: 'instructions',\n workspace: workspaceReal,\n configPath,\n instruction: REQUIRED_BASIC_SKILL_INSTRUCTION,\n skill: {\n name,\n version,\n path: realpathSync(skillPath),\n hash: sha256(skillBody),\n },\n configHash: sha256(readFileSync(configPath, 'utf8')),\n }\n}\n\nexport function verifyRequiredBasicSkill(\n binding: OpenCodeSkillBinding,\n command = process.env.DTA_OPENCODE_BIN || 'opencode',\n environment?: NodeJS.ProcessEnv,\n): OpenCodeSkillPreflight {\n const current = bindRequiredBasicSkill(binding.workspace)\n if (current.skill.hash !== binding.skill.hash || current.configHash !== binding.configHash) {\n throw new Error('OpenCode Basic Skill 或配置在 preflight 前发生漂移')\n }\n\n const versionRun = runOpenCode(command, ['--version'], binding.workspace, undefined, environment)\n const configRun = runOpenCode(\n command, ['debug', 'config', '--pure'], binding.workspace, undefined, environment)\n const resolved = parseObject(configRun, 'opencode debug config')\n const resolvedInstructions = stringArray(\n resolved.instructions || [], 'opencode resolved instructions')\n if (countInstructionsForPath(\n binding.workspace, resolvedInstructions, REQUIRED_BASIC_SKILL_INSTRUCTION,\n ) !== 1) {\n throw new Error('OpenCode resolved config 未唯一加载 dta-basic-behavior')\n }\n\n const isolatedHome = mkdtempSync(join(tmpdir(), 'dta-opencode-preflight-'))\n let skillsRun = ''\n try {\n skillsRun = runOpenCode(\n command, ['debug', 'skill', '--pure'], binding.workspace, 4 * 1024 * 1024, {\n ...(environment || process.env),\n HOME: isolatedHome,\n XDG_CONFIG_HOME: join(isolatedHome, 'config'),\n XDG_DATA_HOME: join(isolatedHome, 'data'),\n XDG_CACHE_HOME: join(isolatedHome, 'cache'),\n XDG_STATE_HOME: join(isolatedHome, 'state'),\n })\n } finally {\n rmSync(isolatedHome, { recursive: true, force: true })\n }\n const discoveredLocation = skillsRun.match(\n new RegExp(`\"name\":\\\\s*\"${REQUIRED_BASIC_SKILL}\"[\\\\s\\\\S]{0,4000}?\"location\":\\\\s*\"([^\"]+)\"`),\n )?.[1]\n let discovered = false\n if (discoveredLocation) {\n try {\n const decoded = JSON.parse(`\"${discoveredLocation}\"`)\n discovered = existsSync(decoded) && realpathSync(decoded) === binding.skill.path\n } catch { /* malformed or truncated debug output */ }\n }\n if (!discovered) {\n const marker = skillsRun.indexOf(REQUIRED_BASIC_SKILL)\n const nearby = marker >= 0\n ? skillsRun.slice(Math.max(0, marker - 160), marker + 600).replace(/\\s+/g, ' ')\n : `debug skill bytes=${Buffer.byteLength(skillsRun)}`\n throw new Error(`OpenCode 未从当前项目发现 Basic Skill: ${binding.skill.path}; ${nearby}`)\n }\n\n return {\n ...binding,\n verified: true,\n openCodeVersion: versionRun.trim(),\n resolvedInstruction: true,\n resolvedInstructions,\n discoveredProjectSkill: true,\n }\n}\n\nexport function removeRequiredBasicSkillInstruction(workspace: string): void {\n const workspaceReal = realpathSync(resolve(workspace))\n const configPath = join(workspaceReal, 'opencode.json')\n const config = existsSync(configPath)\n ? parseObject(readFileSync(configPath, 'utf8'), 'opencode.json')\n : {}\n const instructions = config.instructions === undefined\n ? []\n : stringArray(config.instructions, 'opencode.json#instructions')\n const conflictingGlob = instructions.find((item) =>\n instructionUsesGlob(item) && instructionTargetsPath(\n workspaceReal, item, REQUIRED_BASIC_SKILL_INSTRUCTION))\n if (conflictingGlob) {\n throw new Error(\n `OpenCode instruction glob 命中 Basic Skill,无法生成可信 without-skill baseline: ${conflictingGlob}`)\n }\n config.instructions = instructions.filter((item) => !instructionTargetsPath(\n workspaceReal, item, REQUIRED_BASIC_SKILL_INSTRUCTION))\n const permission = config.permission === undefined\n ? {}\n : objectValue(config.permission, 'opencode.json#permission')\n const skillPermission = permission.skill === undefined\n ? {}\n : objectValue(permission.skill, 'opencode.json#permission.skill')\n skillPermission[REQUIRED_BASIC_SKILL] = 'deny'\n permission.skill = skillPermission\n config.permission = permission\n atomicJson(configPath, config)\n}\n\nfunction runOpenCode(\n command: string,\n args: string[],\n cwd: string,\n maxBuffer = 4 * 1024 * 1024,\n environment?: NodeJS.ProcessEnv,\n): string {\n const child = spawnSync(command, args, {\n cwd,\n encoding: 'utf8',\n timeout: 30_000,\n maxBuffer,\n env: environment || process.env,\n })\n if (child.error || child.status !== 0) {\n throw new Error(`OpenCode preflight 失败 (${args.join(' ')}): ${\n child.error?.message || String(child.stderr || child.stdout || `exit=${child.status}`).trim()}`)\n }\n return String(child.stdout || '')\n}\n\nfunction frontmatterValue(body: string, key: string): string {\n const frontmatter = body.match(/^---\\s*\\n([\\s\\S]*?)\\n---/)?.[1] || ''\n return frontmatter.match(new RegExp(`^${key}:\\\\s*[\"']?([^\"'\\\\n]+)[\"']?\\\\s*$`, 'm'))?.[1]?.trim() || ''\n}\n\nfunction metadataVersion(body: string): string {\n const frontmatter = body.match(/^---\\s*\\n([\\s\\S]*?)\\n---/)?.[1] || ''\n return frontmatter.match(/^metadata:\\s*\\n(?:^[ \\t]+.*\\n)*?^[ \\t]+version:\\s*[\"']?([^\"'\\n]+)[\"']?\\s*$/m)?.[1]?.trim() || ''\n}\n\nfunction parseObject(text: string, label: string): Record<string, any> {\n let value: unknown\n try { value = JSON.parse(text) }\n catch (error) { throw new Error(`${label} 不是合法 JSON: ${(error as Error).message}`) }\n return objectValue(value, label)\n}\n\nfunction objectValue(value: unknown, label: string): Record<string, any> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`${label} 必须是 JSON object`)\n }\n return value as Record<string, any>\n}\n\nfunction stringArray(value: unknown, label: string): string[] {\n if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) {\n throw new Error(`${label} 必须是 string[]`)\n }\n return value as string[]\n}\n\nfunction sha256(value: string): string {\n return createHash('sha256').update(value).digest('hex')\n}\n\nfunction atomicJson(path: string, value: unknown): void {\n const body = JSON.stringify(value, null, 2) + '\\n'\n const temporary = `${path}.${process.pid}.${Date.now()}.tmp`\n writeFileSync(temporary, body, { flag: 'wx' })\n renameSync(temporary, path)\n}\n\nexport function relativeBinding(binding: OpenCodeSkillBinding): Record<string, unknown> {\n return {\n ...binding,\n configPath: relative(binding.workspace, binding.configPath),\n skill: {\n ...binding.skill,\n path: relative(binding.workspace, binding.skill.path),\n },\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"opencode-workspace.js","sourceRoot":"","sources":["../../src/opencode-workspace.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto'\nimport {\n existsSync, mkdtempSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync,\n} from 'node:fs'\nimport { spawnSync } from 'node:child_process'\nimport { join, relative, resolve } from 'node:path'\nimport { tmpdir } from 'node:os'\nimport {\n countInstructionsForPath, instructionTargetsPath, instructionUsesGlob,\n} from './instruction-path.js'\n\nexport const REQUIRED_BASIC_SKILL = 'dta-basic-behavior'\nexport const REQUIRED_BASIC_SKILL_INSTRUCTION =\n '.agents/skills/dta-basic-behavior/SKILL.md'\nexport const DEFAULT_OPENCODE_MODEL = 'deepseek/deepseek-v4-flash'\n\nexport interface OpenCodeSkillBinding {\n $schema: 'dingtalk-agent/opencode-skill-binding@1'\n host: 'opencode'\n required: true\n strategy: 'instructions'\n workspace: string\n configPath: string\n instruction: string\n skill: {\n name: string\n version: string\n path: string\n hash: string\n }\n configHash: string\n}\n\nexport interface OpenCodeSkillPreflight extends OpenCodeSkillBinding {\n verified: true\n openCodeVersion: string\n resolvedInstruction: true\n resolvedInstructions: string[]\n discoveredProjectSkill: true\n}\n\n/**\n * OpenCode only discovers project Skills by default; it does not load their body.\n * This binding makes the Basic Skill an unconditional instruction while retaining\n * the native project Skill for discovery and explicit inspection.\n */\nexport function bindRequiredBasicSkill(workspace: string): OpenCodeSkillBinding {\n const workspaceReal = realpathSync(resolve(workspace))\n const skillPath = join(workspaceReal, REQUIRED_BASIC_SKILL_INSTRUCTION)\n if (!existsSync(skillPath)) {\n throw new Error(`OpenCode 必需 Basic Skill 不存在: ${skillPath}`)\n }\n const skillBody = readFileSync(skillPath, 'utf8')\n const name = frontmatterValue(skillBody, 'name')\n const version = metadataVersion(skillBody)\n if (name !== REQUIRED_BASIC_SKILL || !version) {\n throw new Error(`OpenCode Basic Skill 元数据非法: name=${name || 'missing'} version=${version || 'missing'}`)\n }\n\n const configPath = join(workspaceReal, 'opencode.json')\n const config = existsSync(configPath)\n ? parseObject(readFileSync(configPath, 'utf8'), 'opencode.json')\n : {}\n const instructions = config.instructions === undefined\n ? []\n : stringArray(config.instructions, 'opencode.json#instructions')\n const conflictingGlob = instructions.find((item) =>\n instructionUsesGlob(item) && instructionTargetsPath(\n workspaceReal, item, REQUIRED_BASIC_SKILL_INSTRUCTION))\n if (conflictingGlob) {\n throw new Error(\n `OpenCode instruction glob 命中 Basic Skill,无法安全去重: ${conflictingGlob}`)\n }\n config.$schema ||= 'https://opencode.ai/config.json'\n config.instructions = [\n REQUIRED_BASIC_SKILL_INSTRUCTION,\n ...instructions.filter((item) => !instructionTargetsPath(\n workspaceReal, item, REQUIRED_BASIC_SKILL_INSTRUCTION)),\n ]\n\n const permission = config.permission === undefined\n ? {}\n : objectValue(config.permission, 'opencode.json#permission')\n const skillPermission = permission.skill === undefined\n ? {}\n : objectValue(permission.skill, 'opencode.json#permission.skill')\n skillPermission[REQUIRED_BASIC_SKILL] = 'allow'\n permission.skill = skillPermission\n config.permission = permission\n atomicJson(configPath, config)\n\n return {\n $schema: 'dingtalk-agent/opencode-skill-binding@1',\n host: 'opencode',\n required: true,\n strategy: 'instructions',\n workspace: workspaceReal,\n configPath,\n instruction: REQUIRED_BASIC_SKILL_INSTRUCTION,\n skill: {\n name,\n version,\n path: realpathSync(skillPath),\n hash: sha256(skillBody),\n },\n configHash: sha256(readFileSync(configPath, 'utf8')),\n }\n}\n\nexport function verifyRequiredBasicSkill(\n binding: OpenCodeSkillBinding,\n command = process.env.DTA_OPENCODE_BIN || 'opencode',\n environment?: NodeJS.ProcessEnv,\n): OpenCodeSkillPreflight {\n const current = bindRequiredBasicSkill(binding.workspace)\n if (current.skill.hash !== binding.skill.hash || current.configHash !== binding.configHash) {\n throw new Error('OpenCode Basic Skill 或配置在 preflight 前发生漂移')\n }\n\n const versionRun = runOpenCode(command, ['--version'], binding.workspace, undefined, environment)\n const configRun = runOpenCode(\n command, ['debug', 'config', '--pure'], binding.workspace, undefined, environment)\n const resolved = parseObject(configRun, 'opencode debug config')\n const resolvedInstructions = stringArray(\n resolved.instructions || [], 'opencode resolved instructions')\n if (countInstructionsForPath(\n binding.workspace, resolvedInstructions, REQUIRED_BASIC_SKILL_INSTRUCTION,\n ) !== 1) {\n throw new Error('OpenCode resolved config 未唯一加载 dta-basic-behavior')\n }\n\n const isolatedHome = mkdtempSync(join(tmpdir(), 'dta-opencode-preflight-'))\n let skillsRun = ''\n try {\n skillsRun = runOpenCode(\n command, ['debug', 'skill', '--pure'], binding.workspace, 4 * 1024 * 1024, {\n ...(environment || process.env),\n HOME: isolatedHome,\n XDG_CONFIG_HOME: join(isolatedHome, 'config'),\n XDG_DATA_HOME: join(isolatedHome, 'data'),\n XDG_CACHE_HOME: join(isolatedHome, 'cache'),\n XDG_STATE_HOME: join(isolatedHome, 'state'),\n })\n } finally {\n rmSync(isolatedHome, { recursive: true, force: true })\n }\n const discoveredLocation = skillsRun.match(\n new RegExp(`\"name\":\\\\s*\"${REQUIRED_BASIC_SKILL}\"[\\\\s\\\\S]{0,4000}?\"location\":\\\\s*\"([^\"]+)\"`),\n )?.[1]\n let discovered = false\n if (discoveredLocation) {\n try {\n const decoded = JSON.parse(`\"${discoveredLocation}\"`)\n discovered = existsSync(decoded) && realpathSync(decoded) === binding.skill.path\n } catch { /* malformed or truncated debug output */ }\n }\n if (!discovered) {\n const marker = skillsRun.indexOf(REQUIRED_BASIC_SKILL)\n const nearby = marker >= 0\n ? skillsRun.slice(Math.max(0, marker - 160), marker + 600).replace(/\\s+/g, ' ')\n : `debug skill bytes=${Buffer.byteLength(skillsRun)}`\n throw new Error(`OpenCode 未从当前项目发现 Basic Skill: ${binding.skill.path}; ${nearby}`)\n }\n\n return {\n ...binding,\n verified: true,\n openCodeVersion: versionRun.trim(),\n resolvedInstruction: true,\n resolvedInstructions,\n discoveredProjectSkill: true,\n }\n}\n\nexport function removeRequiredBasicSkillInstruction(workspace: string): void {\n const workspaceReal = realpathSync(resolve(workspace))\n const configPath = join(workspaceReal, 'opencode.json')\n const config = existsSync(configPath)\n ? parseObject(readFileSync(configPath, 'utf8'), 'opencode.json')\n : {}\n const instructions = config.instructions === undefined\n ? []\n : stringArray(config.instructions, 'opencode.json#instructions')\n const conflictingGlob = instructions.find((item) =>\n instructionUsesGlob(item) && instructionTargetsPath(\n workspaceReal, item, REQUIRED_BASIC_SKILL_INSTRUCTION))\n if (conflictingGlob) {\n throw new Error(\n `OpenCode instruction glob 命中 Basic Skill,无法生成可信 without-skill baseline: ${conflictingGlob}`)\n }\n config.instructions = instructions.filter((item) => !instructionTargetsPath(\n workspaceReal, item, REQUIRED_BASIC_SKILL_INSTRUCTION))\n const permission = config.permission === undefined\n ? {}\n : objectValue(config.permission, 'opencode.json#permission')\n const skillPermission = permission.skill === undefined\n ? {}\n : objectValue(permission.skill, 'opencode.json#permission.skill')\n skillPermission[REQUIRED_BASIC_SKILL] = 'deny'\n permission.skill = skillPermission\n config.permission = permission\n atomicJson(configPath, config)\n}\n\nfunction runOpenCode(\n command: string,\n args: string[],\n cwd: string,\n maxBuffer = 4 * 1024 * 1024,\n environment?: NodeJS.ProcessEnv,\n): string {\n const child = spawnSync(command, args, {\n cwd,\n encoding: 'utf8',\n timeout: 30_000,\n maxBuffer,\n env: environment || process.env,\n })\n if (child.error || child.status !== 0) {\n throw new Error(`OpenCode preflight 失败 (${args.join(' ')}): ${\n child.error?.message || String(child.stderr || child.stdout || `exit=${child.status}`).trim()}`)\n }\n return String(child.stdout || '')\n}\n\nfunction frontmatterValue(body: string, key: string): string {\n const frontmatter = body.match(/^---\\s*\\n([\\s\\S]*?)\\n---/)?.[1] || ''\n return frontmatter.match(new RegExp(`^${key}:\\\\s*[\"']?([^\"'\\\\n]+)[\"']?\\\\s*$`, 'm'))?.[1]?.trim() || ''\n}\n\nfunction metadataVersion(body: string): string {\n const frontmatter = body.match(/^---\\s*\\n([\\s\\S]*?)\\n---/)?.[1] || ''\n return frontmatter.match(/^metadata:\\s*\\n(?:^[ \\t]+.*\\n)*?^[ \\t]+version:\\s*[\"']?([^\"'\\n]+)[\"']?\\s*$/m)?.[1]?.trim() || ''\n}\n\nfunction parseObject(text: string, label: string): Record<string, any> {\n let value: unknown\n try { value = JSON.parse(text) }\n catch (error) { throw new Error(`${label} 不是合法 JSON: ${(error as Error).message}`) }\n return objectValue(value, label)\n}\n\nfunction objectValue(value: unknown, label: string): Record<string, any> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`${label} 必须是 JSON object`)\n }\n return value as Record<string, any>\n}\n\nfunction stringArray(value: unknown, label: string): string[] {\n if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) {\n throw new Error(`${label} 必须是 string[]`)\n }\n return value as string[]\n}\n\nfunction sha256(value: string): string {\n return createHash('sha256').update(value).digest('hex')\n}\n\nfunction atomicJson(path: string, value: unknown): void {\n const body = JSON.stringify(value, null, 2) + '\\n'\n const temporary = `${path}.${process.pid}.${Date.now()}.tmp`\n writeFileSync(temporary, body, { flag: 'wx' })\n renameSync(temporary, path)\n}\n\nexport function relativeBinding(binding: OpenCodeSkillBinding): Record<string, unknown> {\n return {\n ...binding,\n configPath: relative(binding.workspace, binding.configPath),\n skill: {\n ...binding.skill,\n path: relative(binding.workspace, binding.skill.path),\n },\n }\n}\n"]}
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -35,18 +35,20 @@
|
|
|
35
35
|
|
|
36
36
|
> ⚠️ **这张等式回答的是「一个跑起来的数字员工由什么组成」,用途是界定依赖——它不是「本项目做什么」的答案。** 把两者混为一谈会严重低估本项目的范围。「本项目做什么」要换一个正交的视角看:**开发域**。
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
**开发域:开发者要走完四段——建起来、部署交付、评测、观察。** 他坐在自己熟悉的终端里,由 Coding Agent 带着走;dta 在每一步给的主要是提示与引导,只有会产生不可逆副作用的地方才拦一道。
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
|
43
|
-
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
40
|
+
这四段拆开做是六个环节。开发者不必记住编号,它是给在本仓库工作的人定位用的:
|
|
41
|
+
|
|
42
|
+
| 开发者走的 | 内部的段 | 本项目替他完成什么 |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| **建起来** | ① 本体与员工技能 | 一份可继承、可 hash、可验证的共享行为合同(响应资格、意图分级、授权模型、风险分级、证据阶梯、完成判定、记忆与遗忘),加本体与岗位骨架 |
|
|
45
|
+
| | ② 身份获取与事件感知 | 把来路不明的原始事件归一成稳定合同,冻结回复目标与执行身份,按 Field 绑定权限与出口,补齐现场,并保证同一事件只产生一个 Run |
|
|
46
|
+
| **部署交付** | ③ 托管平台部署 | 把手工搬运变成 plan → apply → 独立回读 → 加载烟测 → Receipt 的受控发布链,幂等、可回滚、可退役 |
|
|
47
|
+
| | ④ 驱动它在钉钉里干活 | 四个动作原语 + Action Gate:副作用前冻结目标身份,副作用后强制平台回读,完成必须有物证 |
|
|
48
|
+
| **评测** | ⑤ 评测设计 | L0–L4 证据分层方法学、四个 runner、多面证据硬门禁,以及「真实事故 → 可复跑场景」的沉淀路径 |
|
|
49
|
+
| **观察** | ⑥ 观测与计量 | 目前**最薄的一段**:只有把线上人工观察安全灌回评测素材的受控通道;用量计量尚未实现(见 §8) |
|
|
48
50
|
|
|
49
|
-
逐段的能力、边界与缺口见 [§8 开发生命周期](#8-开发生命周期从定义到观测)
|
|
51
|
+
逐段的能力、边界与缺口见 [§8 开发生命周期](#8-开发生命周期从定义到观测)。一句话概括这两个视角的关系:**运行时的底座我们不造;把 Agent 变成数字员工这条路上的判断、门禁与证据,是我们的。**这与「小而硬的连接层」不矛盾——管住整条路,不等于什么都自己实现:能靠引导讲清的不写成命令,能交给 DWS 与托管平台做的不复制一遍。
|
|
50
52
|
|
|
51
53
|
三类东西的可变性完全不同,必须分开对待:
|
|
52
54
|
|
|
@@ -95,7 +97,7 @@ Host 原生发现目录不是发布源。OpenCode 的 `.agents/skills/`、Claude
|
|
|
95
97
|
|---|---|---|
|
|
96
98
|
| **组织身份、场域与权限** | 钉钉数字员工平台 | 不发证、不改写、不扩权;只把签发结果冻结进 Session 并全程审计 |
|
|
97
99
|
| **事件信封**(谁、在哪、说了什么) | 钉钉事件中心 / DWS | **不拥有触发器**(见下);只要求信封可信、可幂等 |
|
|
98
|
-
| **平台能力执行** | DWS | 不复制 DWS 命令面,只在需要冻结事务边界时包一层。`src/dws.ts`
|
|
100
|
+
| **平台能力执行** | DWS | 不复制 DWS 命令面,只在需要冻结事务边界时包一层。`src/dws.ts` 是唯一走 DWS 能力面的地方(`doctor` 为探测版本与登录态直接起 `dws` 是唯一例外);实战缺陷见 [DWS Field Notes](DWS-FIELD-NOTES.md) |
|
|
99
101
|
| **运行位置** | Managed Agent Platform / Agent Host | 不自己做 Host、不自建 Runtime;通过 registry + adapter 连接,只要求一份可验证的加载合同 |
|
|
100
102
|
| **本体、行为、状态与效果证据** | **本仓库 + Git** | 唯一拥有的一行 |
|
|
101
103
|
|
|
@@ -235,7 +237,7 @@ dingtalk-doc:<node-or-url> DWS 拉取在线文档的只读快照
|
|
|
235
237
|
| **4 评测与证据** | 在花钱、外发和上线之前,用最低成本的层级证明它真会做事;失败沉淀成可复跑场景而不是一次口头修正 | `lab` `robot-evals` `opencode-evals` `remote-state-evals` `remote-semantic-state-*` `personal-event-evals` `storage-evals` `eval-evidence` | `lab *` `workspace eval` | `dta-agent-eval` | 6.2k |
|
|
236
238
|
| **5 状态与记忆** | 让 Run 崩了、沙箱没了、进程换了之后,事情还能接着做;同时不让 Markdown 承担它承担不了的并发控制 | `memory/*` | `task show/checkpoint` `memory operational` `memory candidate` | — | 2.6k |
|
|
237
239
|
| **6 机器与分发** | 一台新机器一条命令拿到 CLI、PATH、DWS 检查和 core Skill 套装,升级不产生第二份副本;并探测本机有哪些 Coding Agent Host 以及 Skill 对它们是否可见 | `setup` `doctor` `host-detect` `upgrade` `init` `skill-manager` `version` `package-root` | `setup` `doctor` `upgrade` `skill *` `init` | — | 1.4k |
|
|
238
|
-
| **平台适配** |
|
|
240
|
+
| **平台适配** | 唯一走 DWS 能力面的地方(doctor 的探测除外) | `dws` | — | — | 0.5k |
|
|
239
241
|
|
|
240
242
|
重心分布本身是个结论:交付链与评测各占约四分之一,合计超过一半。这个项目的难点从来不是"让模型说话",而是**证明它真的装好了、真的做对了、真的上线了**。
|
|
241
243
|
|
|
@@ -280,7 +282,7 @@ dingtalk-doc:<node-or-url> DWS 拉取在线文档的只读快照
|
|
|
280
282
|
|
|
281
283
|
### ⑤ 评测设计
|
|
282
284
|
|
|
283
|
-
**做**:给出「选最低够用的环境层级」的判断表与 L0–L4 分层;规定一次结论必须同时采集哪几个证据面,且回复正文永远不能自证完成;把硬门禁的判定顺序固定下来,防止安全失败被质量分平均掉;提供四个默认零副作用的 runner(真实外发需四道 gate 同时打开);给出「真实事故 → 可复跑场景」的沉淀路径与「这条该修进 CLI 还是修进 Skill」的判别原则;仓库自身的
|
|
285
|
+
**做**:给出「选最低够用的环境层级」的判断表与 L0–L4 分层;规定一次结论必须同时采集哪几个证据面,且回复正文永远不能自证完成;把硬门禁的判定顺序固定下来,防止安全失败被质量分平均掉;提供四个默认零副作用的 runner(真实外发需四道 gate 同时打开);给出「真实事故 → 可复跑场景」的沉淀路径与「这条该修进 CLI 还是修进 Skill」的判别原则;仓库自身的 75 个合同即范例,**每条都成对写明证明什么、不证明什么**。
|
|
284
286
|
|
|
285
287
|
**不做**:不做自然度与主观质量的自动判定,不允许用模型主观高分覆盖已实现的安全失败;不自动清理测试产物(写入授权不等于删除授权);不支持 prod 晋级。
|
|
286
288
|
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -199,11 +199,13 @@ dta prepare --event-file event.json --json
|
|
|
199
199
|
```bash
|
|
200
200
|
# 在 Agent 根目录
|
|
201
201
|
dta agent enhance --project-name <agent-name> \
|
|
202
|
-
--role-skill <role-skill-name>
|
|
202
|
+
--role-skill <role-skill-name> \
|
|
203
|
+
--host <opencode|none> --dry-run --json
|
|
203
204
|
|
|
204
205
|
# 审阅 plan 后执行其 apply.command(当前 plan-id + 显式 yes)
|
|
205
206
|
dta agent enhance --project-name <agent-name> \
|
|
206
207
|
--role-skill <role-skill-name> \
|
|
208
|
+
--host <opencode|none> \
|
|
207
209
|
--plan-id <current-plan-id> --yes --json
|
|
208
210
|
|
|
209
211
|
# 把 AGENTS.md 与 Role Skill 的模板占位符替换为真实岗位语义后
|
|
@@ -216,7 +218,7 @@ dta agent audit --bindings agent.bindings.json \
|
|
|
216
218
|
--require-skill <role-skill-name> --verify-load --yes --json
|
|
217
219
|
```
|
|
218
220
|
|
|
219
|
-
`agent enhance` 默认只生成计划,不写文件、不访问 DWS、也不创建 Trigger
|
|
221
|
+
`agent enhance` 默认只生成计划,不写文件、不访问 DWS、也不创建 Trigger;新项目必须显式用 `--host opencode` 选择当前完整 adapter,或用 `--host none` 只落成 harness 无关交付包(审计上限为 `partial`)。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
222
|
|
|
221
223
|
远端 memory/knowledge 需要另跑授权的 `dta lab eval --engine storage`,再把其报告传给 `--remote-report`。审计不会用旧缓存替代 DWS 身份、类型、hash 和独立回读,也不会把远端文档升级为 Wait、Receipt、锁或凭据介质。
|
|
222
224
|
|
package/docs/SELF-TEST.md
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
## 怎么加一个场景
|
|
35
35
|
|
|
36
|
-
合同评测有
|
|
36
|
+
合同评测有 75 个场景(core 39 / extended 36)。加一个新场景是四步:
|
|
37
37
|
|
|
38
38
|
1. **在 `evals/evals.json` 追加一条**:`id`(顺延)、`prompt`(这个场景在测什么)、`expected_output`、`files`、`expectations`(逐条断言的自然语言描述),以及 **`tier`**。
|
|
39
39
|
2. **在 `evals/run-contract-evals.mjs` 写同名实现函数** `eval<Name>()`,返回 `{ output, checks: [...] }`。runner 会硬断言 `checks.length === expectations.length`——两边对不上直接失败,这是防止"加了断言忘了写说明"的闸门。
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
<rect width="1440" height="840" fill="#ffffff"/>
|
|
23
23
|
|
|
24
|
-
<text x="40" y="48" class="title">把 Agent
|
|
24
|
+
<text x="40" y="48" class="title">把 Agent 接进钉钉:运行平台可替换,判断与门禁不变</text>
|
|
25
25
|
<text x="40" y="75" class="subtitle">本仓库是连接层:不发身份、不建 Runtime、不复制 DWS 命令面——只把 Agent 装配成合格的钉钉数字员工。</text>
|
|
26
26
|
|
|
27
27
|
<!-- ── 泳道 1:运行位置 ───────────────────────────────── -->
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
</defs>
|
|
22
22
|
<rect width="1200" height="880" fill="#ffffff"/>
|
|
23
23
|
<text x="40" y="46" class="title">dingtalk-agent 架构:五个部件,五个权威,本仓库只拥有一个</text>
|
|
24
|
-
<text x="40" y="70" class="subtitle"
|
|
24
|
+
<text x="40" y="70" class="subtitle">在你熟悉的终端里,把现成的 Agent 装配成合格的钉钉数字员工。实心编号 = 本仓库拥有;空心编号 = 外部提供。</text>
|
|
25
25
|
<rect x="40" y="92" width="1120" height="122" rx="8" fill="#f9fafb" stroke="#d1d5db" stroke-width="1.5" stroke-dasharray="7 5"/>
|
|
26
26
|
<circle cx="62" cy="110" r="11" fill="#ffffff" stroke="#64748b" stroke-width="1.6"/>
|
|
27
27
|
<text x="62" y="114" text-anchor="middle" fill="#64748b" font-size="12" font-weight="700">5</text>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"required": [
|
|
8
8
|
"$schema", "planId", "ready", "status", "sideEffect", "dingtalkSideEffect",
|
|
9
9
|
"triggerSideEffect", "root", "source", "projectName", "roleSkills", "bindings",
|
|
10
|
-
"baselineHash", "desiredHash", "operations", "blockers", "warnings",
|
|
10
|
+
"host", "baselineHash", "desiredHash", "operations", "blockers", "warnings",
|
|
11
11
|
"semanticReview", "apply", "verification"
|
|
12
12
|
],
|
|
13
13
|
"properties": {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"type": "array", "uniqueItems": true,
|
|
34
34
|
"items": { "type": "string", "minLength": 1 }
|
|
35
35
|
},
|
|
36
|
+
"host": { "enum": ["opencode", "none", "unselected"] },
|
|
36
37
|
"bindings": { "type": "string", "minLength": 1 },
|
|
37
38
|
"baselineHash": { "$ref": "#/$defs/hash" },
|
|
38
39
|
"desiredHash": { "$ref": "#/$defs/hash" },
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"additionalProperties": false,
|
|
7
7
|
"required": [
|
|
8
8
|
"$schema", "status", "operationId", "planId", "sideEffect", "dingtalkSideEffect",
|
|
9
|
-
"triggerSideEffect", "root", "backupRoot", "idempotent", "changes", "audit"
|
|
9
|
+
"triggerSideEffect", "root", "backupRoot", "host", "idempotent", "changes", "audit"
|
|
10
10
|
],
|
|
11
11
|
"properties": {
|
|
12
12
|
"$schema": { "const": "dingtalk-agent/agent-enhancement-receipt@1" },
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"triggerSideEffect": { "const": false },
|
|
19
19
|
"root": { "type": "string", "minLength": 1 },
|
|
20
20
|
"backupRoot": { "type": "string" },
|
|
21
|
+
"host": { "enum": ["opencode", "none"] },
|
|
21
22
|
"idempotent": { "type": "boolean" },
|
|
22
23
|
"changes": {
|
|
23
24
|
"type": "array",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
}
|
|
25
25
|
],
|
|
26
26
|
"modelProbe": {
|
|
27
|
-
"model": "deepseek/deepseek-
|
|
27
|
+
"model": "deepseek/deepseek-v4-flash",
|
|
28
28
|
"prompt": "只根据宿主已经挂载的长期记忆和知识回答:先写记忆评测代号,再写知识评测代号。两者之间用一个空格,不要猜测。",
|
|
29
29
|
"expectedText": ["DTA_REMOTE_MEMORY_SENTINEL", "DTA_REMOTE_KNOWLEDGE_SENTINEL"]
|
|
30
30
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xdxer/dingtalk-agent",
|
|
3
|
-
"version": "0.1.5-beta.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.5-beta.15",
|
|
4
|
+
"description": "在你熟悉的终端里,用手边的 Coding Agent 把现成的 Agent 装配成钉钉数字员工:建起来、部署交付、评测、观察四段全程有引导,硬门禁只挡不可逆的副作用。",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dingtalk",
|
|
7
7
|
"agent",
|
|
@@ -3,7 +3,7 @@ name: dta-agent-compose
|
|
|
3
3
|
description: 当用户要创建、新建、装配一个 Agent 或钉钉数字员工——包括把 GitHub 仓库、本地文件夹或钉钉文档定义成 Agent,或要审计、补齐、优化 Agent 的 AGENTS.md、本体职责、岗位 Skills、记忆/知识/产物存储、DWS 权限绑定与「谁叫醒它」的驱动节律时使用。即使尚未 init Workspace,也按 dingtalk-agent 的 AgentDefinition 范式给出可运行的最小装配方案;声明驱动节律但不实现触发器本身。
|
|
4
4
|
compatibility: Requires dingtalk-agent on PATH; remote DingTalk documents require authenticated dws.
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.17.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# 装配一个可工作的钉钉数字员工 Agent
|
|
@@ -15,7 +15,7 @@ metadata:
|
|
|
15
15
|
1. 识别来源和运行方式:GitHub 先由宿主 clone/checkout,本 Skill 不接管凭证;本地目录直接读取;钉钉文档只承担 memory/knowledge 等远端语义状态。新项目的本体与 Role Skills 统一放在可版本化的 `agent/` 交付包;已有仓库按 manifest 显式路径读取。
|
|
16
16
|
2. **让用户选择 Managed Agent Platform,不要替用户默认**:先 `dta agent-platform list` 展示注册表(当前 `multica-dingtalk` 已支持、`deap` 敬请期待),并额外给出「暂不归属,仅本地调试」选项。用户选定托管平台后运行 `dta agent-platform use <platform>`——它写入归属声明并按需安装平台技能包(`multica-dingtalk` 对应 `dta-deploy-multica` 与 `dta-ops-multica`)。命令会同时输出 readiness 检查:multica CLI 未安装时按提示安装(`curl -fsSL https://raw.githubusercontent.com/multica-ai/multica/main/scripts/install.sh | bash`),未登录时 readiness 会给出带解析 endpoint 的完整登录命令(endpoint 来源见 `dta agent-platform show` 的 Endpoint 行:env `MULTICA_SERVER_URL` > 项目 config > profile > 建议值;建议值为线上正式域名,仍标「未确认」,须先与用户确认再用),检测到代理环境变量时提醒连接失败可用 `env -u` 剥离。readiness 未过先引导用户补齐,再继续装配;选「暂不归属」则跳过,后续仍可随时归属。切换到某平台后,`agent-platform use/show` 会给出该平台的 `平台说明: <PLATFORM.md 路径>`——先读它,了解该平台 deploy/ops 技能的用途、完整交付链与绑定/验收/解绑方式,再开始平台侧操作。
|
|
17
17
|
3. **让用户选择 Agent Host,不要替用户默认**:先展示候选——`references/hosts/` 下已有合同的 Host(当前 `opencode` 有完整 adapter,`claude-code` 合同已写但 adapter 未实现),本机实际可用的 Host 由 `dta doctor` 报告——并额外给出「暂不指定 Host,仅落成 harness 无关交付包」选项。绝不默默使用 OpenCode 或当前正在运行本 Skill 的 Host 作为默认。Host exposure 由 dta 在隔离运行/评测目录临时生成,不提交回仓库;选「暂不指定」时明确结论上限是 `partial`。
|
|
18
|
-
4. 对已有仓库优先运行 `dta agent enhance --project-name <name> --role-skill <role> --dry-run --json`。它只生成 `agent-enhancement-plan@1`,不会写文件、访问 DWS 或创建 Trigger。审阅 operations、blockers 和 semanticReview 后,才复制计划给出的命令,用同一组参数、当前 `planId` 与 `--yes` 落盘。
|
|
18
|
+
4. 对已有仓库优先运行 `dta agent enhance --project-name <name> --role-skill <role> --host <opencode|none> --dry-run --json`。`opencode` 声明本地 OpenCode workspace 并合并 `opencode.json`;`none` 只落成 harness 无关交付包,不声明 local workspace,审计结论上限为 `partial`。它只生成 `agent-enhancement-plan@1`,不会写文件、访问 DWS 或创建 Trigger。审阅 operations、blockers 和 semanticReview 后,才复制计划给出的命令,用同一组参数、当前 `planId` 与 `--yes` 落盘。
|
|
19
19
|
5. apply 只允许本地文件副作用:先把被更新的旧文件备份到 `.dingtalk-agent/backups/agent-enhance/<operationId>/`,再写入并按 hash 回读;自定义 private state 目录必须同步进入 `.gitignore`。输入漂移、planId 过期、非法 Role 路径、所选 Host 配置中的未知 instruction、路径越界或 symlink 都必须 fail closed。不要跳过 plan,也不要把 `--yes` 写进无人审阅的默认脚本。
|
|
20
20
|
6. 审核本体:优先使用 `agent/AGENTS.md` 精简表达四块长期语义——定义、不能做的底线、做事标准范式、常犯错误。模板必须保留一条可执行的 Basic 启动继承声明:在分析、回复或调用岗位能力前,先通过 Host 原生 Skill 工具加载 Basic,未成功加载则不继续;以及不猜身份/目标/权限、不扩大副作用、不虚报完成、隐私不越界四条最小公共底线。完整协议仍只在 Basic Skill。CLI 只补骨架,绝不虚构岗位语义;只要 Agent Definition 或 Role Skill 仍含模板 `<...>`,`agent audit` 必须保持 `partial`。
|
|
21
21
|
7. 审核能力:Basic Behavior 是所有钉钉员工共享且**每个 Session 必须加载**的协议;岗位知识和流程拆到独立 Role/Workflow Skill。目录可发现不等于正文已加载,必须为目标 Agent Host 生成可验证的加载合同。不要把 FDE、招聘、事故处理等岗位方法写回 Basic Skill。
|
|
@@ -98,11 +98,13 @@ metadata:
|
|
|
98
98
|
```bash
|
|
99
99
|
# GitHub 仓库由宿主先 checkout;默认只生成改造计划,零写入
|
|
100
100
|
dta agent enhance --project-name <agent-name> \
|
|
101
|
-
--role-skill <role-skill-name>
|
|
101
|
+
--role-skill <role-skill-name> \
|
|
102
|
+
--host <opencode|none> --dry-run --json
|
|
102
103
|
|
|
103
104
|
# 审阅后执行 plan.apply.command;必须使用当前 planId + 显式 yes
|
|
104
105
|
dta agent enhance --project-name <agent-name> \
|
|
105
106
|
--role-skill <role-skill-name> \
|
|
107
|
+
--host <opencode|none> \
|
|
106
108
|
--plan-id <current-plan-id> --yes --json
|
|
107
109
|
|
|
108
110
|
# 填完 AGENTS.md 与 Role Skill 的真实身份、职责、SOP 和验收后再水合
|