@xdxer/dingtalk-agent 0.1.4-beta.11 → 0.1.4-beta.13
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 +1 -1
- package/README.md +15 -16
- package/dist/bin/dingtalk-agent.js +43 -10
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/agent-audit.js +3 -2
- package/dist/src/agent-audit.js.map +1 -1
- package/dist/src/agent-enhance.js +3 -2
- package/dist/src/agent-enhance.js.map +1 -1
- package/dist/src/agent-platform.js +82 -4
- package/dist/src/agent-platform.js.map +1 -1
- package/dist/src/development-workspace.js +3 -1
- package/dist/src/development-workspace.js.map +1 -1
- package/dist/src/multica-deploy.js +2 -1
- package/dist/src/multica-deploy.js.map +1 -1
- package/dist/src/opencode-evals.js +2 -1
- package/dist/src/opencode-evals.js.map +1 -1
- package/dist/src/remote-state-evals.js +2 -1
- package/dist/src/remote-state-evals.js.map +1 -1
- package/dist/src/robot-evals.js +2 -1
- package/dist/src/robot-evals.js.map +1 -1
- package/dist/src/skill-manager.js +18 -3
- package/dist/src/skill-manager.js.map +1 -1
- package/dist/src/skills.js +2 -1
- package/dist/src/skills.js.map +1 -1
- package/docs/INSTALLATION.md +2 -2
- package/lab/agent-eval/completion-gate-regression.json +6 -6
- package/package.json +7 -6
- package/skills/README.md +23 -0
- package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/SKILL.md +33 -7
- package/skills/{dingtalk-agent-deploy → platforms/multica-dingtalk/dingtalk-agent-deploy-multica}/SKILL.md +1 -1
- package/skills/platforms/multica-dingtalk/multica-external/SKILL.md +280 -0
- package/skills/platforms/multica-dingtalk/multica-external/scripts/bootstrap.sh +78 -0
- package/skills/platforms/multica-dingtalk/multica-external/scripts/multica_ext.py +1178 -0
- /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/assets/AGENTS.template.md +0 -0
- /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/assets/agent.bindings.dingtalk-doc.template.json +0 -0
- /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/assets/agent.bindings.local.template.json +0 -0
- /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/assets/opencode.template.json +0 -0
- /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/assets/role-skill.template.md +0 -0
- /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/evals/evals.json +0 -0
- /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/references/agent-definition-contract.md +0 -0
- /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/references/opencode-host-contract.md +0 -0
- /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/references/storage-routing.md +0 -0
- /package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/SKILL.md +0 -0
- /package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/assets/eval-catalog.template.json +0 -0
- /package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/evals/evals.json +0 -0
- /package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/eval-topology.md +0 -0
- /package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/evidence-contract.md +0 -0
- /package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/scenario-taxonomy.md +0 -0
- /package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/storage-modes.md +0 -0
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/SKILL.md +0 -0
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/assets/memory-candidate-proposal.json +0 -0
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/assets/task-checkpoint.json +0 -0
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/action-contract.md +0 -0
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/event-to-behavior.md +0 -0
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/memory-and-evolution.md +0 -0
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/perception-and-gates.md +0 -0
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/runtime-modes.md +0 -0
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/task-lifecycle.md +0 -0
- /package/skills/{dingtalk-agent-boot-multica → platforms/multica-dingtalk/dingtalk-agent-boot-multica}/SKILL.md +0 -0
- /package/skills/{dingtalk-agent-deploy → platforms/multica-dingtalk/dingtalk-agent-deploy-multica}/references/multica-deployment-contract.md +0 -0
- /package/skills/{dingtalk-agent-deploy → platforms/multica-dingtalk/dingtalk-agent-deploy-multica}/references/promotion-observation-contract.md +0 -0
package/dist/src/skills.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/skills.ts"],"names":[],"mappings":"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","sourcesContent":["// 把本次 Run 要遵守的 Agent Skill 冻结进沙箱(TypeScript source)。\n// 运行中的 Run 永不热加载工作区后来修改的规则;重放时只认快照与 hash。\n\nimport {\n copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync,\n realpathSync, rmSync, writeFileSync,\n} from 'node:fs'\nimport { homedir } from 'node:os'\nimport { basename, dirname, join, relative, resolve } from 'node:path'\nimport { digest, stableStringify } from './events.js'\nimport { resolvePackageRoot } from './package-root.js'\n\nconst PACKAGE_ROOT = resolvePackageRoot(import.meta.url)\nconst INSTALL_MARKER = '.dingtalk-agent-install.json'\n\nexport interface SkillManifestEntry {\n name: string\n description: string\n version: string\n sourcePath: string\n snapshotPath: string\n hash: string\n files: number\n}\n\nexport interface SkillManifest {\n $schema: string\n entries: SkillManifestEntry[]\n hash: string\n}\n\nexport function snapshotSkills(\n root: string,\n runPath: string,\n sources: string[],\n sessionPath: string,\n): SkillManifest {\n if (!Array.isArray(sources) || !sources.length || sources.some((x) => typeof x !== 'string')) {\n throw new Error('Workspace skills 必须是非空 string[]')\n }\n\n const rootReal = realpathSync(resolve(root))\n const snapshotRoot = join(sessionPath, 'skills')\n const existingManifest = join(snapshotRoot, 'manifest.json')\n if (existsSync(existingManifest)) {\n const manifest = verifySnapshotRoot(snapshotRoot)\n copySessionSnapshot(snapshotRoot, runPath)\n return manifest\n }\n rmSync(snapshotRoot, { recursive: true, force: true })\n mkdirSync(snapshotRoot, { recursive: true })\n\n const entries: SkillManifestEntry[] = []\n const names = new Set()\n for (const sourceSpec of sources) {\n const resolved = resolveSkillSource(rootReal, sourceSpec)\n const source = resolved.path\n const skillFile = join(source, 'SKILL.md')\n if (!existsSync(skillFile)) throw new Error(`Agent Skill 缺少 SKILL.md: ${sourceSpec}`)\n\n const metadata = parseFrontmatter(readFileSync(skillFile, 'utf8'), sourceSpec)\n const name = metadata.name || basename(source)\n if (names.has(name)) throw new Error(`Workspace skills 出现重复 Skill name: ${name}`)\n names.add(name)\n\n const files = walk(source)\n const contentIndex = files.map((path) => {\n const rel = relative(source, path).split('\\\\').join('/')\n return { path: rel, hash: digest(readFileSync(path).toString('base64')) }\n })\n const hash = digest(stableStringify(contentIndex))\n const destination = join(snapshotRoot, name)\n for (const path of files) {\n const rel = relative(source, path)\n const out = join(destination, rel)\n mkdirSync(dirname(out), { recursive: true })\n copyFileSync(path, out)\n }\n entries.push({\n name,\n description: metadata.description || '',\n version: metadata.version || '',\n sourcePath: resolved.label,\n snapshotPath: `context/skills/${name}/SKILL.md`,\n hash,\n files: contentIndex.length,\n })\n }\n\n const unsigned = {\n $schema: 'dingtalk-agent/skill-snapshot-manifest@1',\n entries,\n }\n const manifest: SkillManifest = {\n ...unsigned,\n hash: digest(stableStringify(unsigned)),\n }\n writeFileSync(join(snapshotRoot, 'manifest.json'), JSON.stringify(manifest, null, 2) + '\\n')\n copySessionSnapshot(snapshotRoot, runPath)\n return manifest\n}\n\nexport function verifySkillSnapshot(runPath, expectedManifestHash) {\n const snapshotRoot = join(runPath, 'context', 'skills')\n return verifySnapshotRoot(snapshotRoot, expectedManifestHash)\n}\n\nfunction copySessionSnapshot(snapshotRoot: string, runPath: string): void {\n const runSnapshotRoot = join(runPath, 'context', 'skills')\n rmSync(runSnapshotRoot, { recursive: true, force: true })\n cpSync(snapshotRoot, runSnapshotRoot, { recursive: true })\n}\n\nfunction verifySnapshotRoot(snapshotRoot: string, expectedManifestHash = ''): SkillManifest {\n const manifestPath = join(snapshotRoot, 'manifest.json')\n if (!existsSync(manifestPath)) throw new Error('Skill snapshot 缺少 manifest.json')\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as SkillManifest\n const { hash, ...unsigned } = manifest\n const actualManifestHash = digest(stableStringify(unsigned))\n if (!hash || hash !== actualManifestHash ||\n (expectedManifestHash && hash !== expectedManifestHash)) {\n throw new Error('Skill snapshot manifest hash 不一致')\n }\n if (!Array.isArray(manifest.entries) || !manifest.entries.length) {\n throw new Error('Skill snapshot manifest 没有 entries')\n }\n for (const entry of manifest.entries) {\n const skillRoot = resolve(snapshotRoot, entry.name)\n assertInside(realpathSync(snapshotRoot), realpathSync(skillRoot), `Skill snapshot ${entry.name}`)\n const files = walk(skillRoot)\n const contentIndex = files.map((path) => ({\n path: relative(skillRoot, path).split('\\\\').join('/'),\n hash: digest(readFileSync(path).toString('base64')),\n }))\n if (contentIndex.length !== entry.files || digest(stableStringify(contentIndex)) !== entry.hash) {\n throw new Error(`Skill snapshot 内容漂移: ${entry.name}`)\n }\n }\n return manifest\n}\n\nfunction walk(dir): string[] {\n const out: string[] = []\n for (const name of readdirSync(dir).sort()) {\n // 安装管理元数据不是 Skill 内容,不进入 Session 快照。\n if (name === INSTALL_MARKER) continue\n const path = join(dir, name)\n const stat = lstatSync(path)\n if (stat.isSymbolicLink()) throw new Error(`Agent Skill 不允许符号链接: ${path}`)\n if (stat.isDirectory()) out.push(...walk(path))\n else if (stat.isFile()) out.push(path)\n }\n return out\n}\n\nfunction parseFrontmatter(text, label): Record<string, string> {\n const match = text.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---(?:\\r?\\n|$)/)\n if (!match) throw new Error(`Agent Skill ${label}/SKILL.md 缺少 YAML frontmatter`)\n const out: Record<string, string> = {}\n for (const line of match[1].split(/\\r?\\n/)) {\n const m = line.match(/^([A-Za-z][A-Za-z0-9_-]*):\\s*(.*)$/)\n if (!m) continue\n out[m[1]] = m[2].trim().replace(/^(['\"])(.*)\\1$/, '$2')\n }\n if (!out.name || !out.description) {\n throw new Error(`Agent Skill ${label}/SKILL.md frontmatter 必须含 name 和 description`)\n }\n const nestedVersion = match[1].match(\n /^metadata:\\s*\\r?\\n(?:[ \\t]+.*\\r?\\n)*?[ \\t]+version:\\s*['\"]?([^'\"\\r\\n]+)['\"]?\\s*$/m,\n )\n if (nestedVersion?.[1]) out.version = nestedVersion[1].trim()\n return out\n}\n\nfunction resolveSkillSource(rootReal: string, sourceSpec: string): {\n path: string\n label: string\n} {\n const spec = String(sourceSpec || '').trim()\n if (!spec) throw new Error('Workspace Skill name 不能为空')\n\n // 显式路径只允许当前 Workspace 内,保留旧 workspace@1 兼容。\n if (spec.includes('/') || spec.includes('\\\\') || spec.startsWith('.')) {\n const candidate = resolve(rootReal, spec)\n if (!existsSync(candidate) || !lstatSync(candidate).isDirectory()) {\n throw new Error(`Agent Skill 不存在或不是目录: ${sourceSpec}`)\n }\n const actual = realpathSync(candidate)\n assertInside(rootReal, actual, `Agent Skill ${sourceSpec}`)\n return { path: actual, label: spec }\n }\n\n // bare name 的优先级:Workspace override → canonical global → client exposure\n // → npm 内置。Session 创建后仍会冻结,运行中不会热切换。\n const candidates: Array<[string, string]> = [\n [`workspace:${spec}`, join(rootReal, 'skills', spec)],\n [`global:${spec}`, join(homedir(), '.agents', 'skills', spec)],\n [`claude:${spec}`, join(homedir(), '.claude', 'skills', spec)],\n [`legacy-codex:${spec}`, join(homedir(), '.codex', 'skills', spec)],\n [`bundled:${spec}`, join(PACKAGE_ROOT, 'skills', spec)],\n ]\n for (const [label, candidate] of candidates) {\n if (!existsSync(candidate) || !lstatSync(candidate).isDirectory()) continue\n const actual = realpathSync(candidate)\n if (!isInsideKnownSkillRoot(actual, rootReal)) continue\n return { path: actual, label }\n }\n throw new Error(`找不到 Agent Skill: ${spec};请运行 dingtalk-agent skill install`)\n}\n\nfunction isInsideKnownSkillRoot(path: string, rootReal: string): boolean {\n const roots = [\n join(rootReal, 'skills'),\n join(homedir(), '.agents', 'skills'),\n join(homedir(), '.claude', 'skills'),\n join(homedir(), '.codex', 'skills'),\n join(PACKAGE_ROOT, 'skills'),\n ]\n return roots.some((root) => {\n if (!existsSync(root)) return false\n const actualRoot = realpathSync(root)\n const rel = relative(actualRoot, path)\n return rel !== '..' && !rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`)\n })\n}\n\nfunction assertInside(root, path, label) {\n const rel = relative(root, path)\n if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`) || resolve(root, rel) !== path) {\n throw new Error(`${label} 必须位于当前工作区内`)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/skills.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,0CAA0C;AAE1C,OAAO,EACL,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EACjF,YAAY,EAAE,MAAM,EAAE,aAAa,GACpC,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACtE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAErD,MAAM,YAAY,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACxD,MAAM,cAAc,GAAG,8BAA8B,CAAA;AAkBrD,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,OAAe,EACf,OAAiB,EACjB,WAAmB;IAEnB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC7F,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACpD,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IAC5C,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;IAChD,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAA;IAC5D,IAAI,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAA;QACjD,mBAAmB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;QAC1C,OAAO,QAAQ,CAAA;IACjB,CAAC;IACD,MAAM,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACtD,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE5C,MAAM,OAAO,GAAyB,EAAE,CAAA;IACxC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAE,CAAA;IACvB,KAAK,MAAM,UAAU,IAAI,OAAO,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;QACzD,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAA;QAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;QAC1C,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,UAAU,EAAE,CAAC,CAAA;QAErF,MAAM,QAAQ,GAAG,gBAAgB,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAA;QAC9E,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAA;QAC9C,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,EAAE,CAAC,CAAA;QACjF,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAEf,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;QAC1B,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACxD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAA;QAC3E,CAAC,CAAC,CAAA;QACF,MAAM,IAAI,GAAG,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAA;QAClD,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;QAC5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;YAClC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;YAClC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YAC5C,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QACzB,CAAC;QACD,OAAO,CAAC,IAAI,CAAC;YACX,IAAI;YACJ,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,EAAE;YACvC,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,EAAE;YAC/B,UAAU,EAAE,QAAQ,CAAC,KAAK;YAC1B,YAAY,EAAE,kBAAkB,IAAI,WAAW;YAC/C,IAAI;YACJ,KAAK,EAAE,YAAY,CAAC,MAAM;SAC3B,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG;QACf,OAAO,EAAE,0CAA0C;QACnD,OAAO;KACR,CAAA;IACD,MAAM,QAAQ,GAAkB;QAC9B,GAAG,QAAQ;QACX,IAAI,EAAE,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;KACxC,CAAA;IACD,aAAa,CAAC,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IAC5F,mBAAmB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;IAC1C,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAO,EAAE,oBAAoB;IAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;IACvD,OAAO,kBAAkB,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAA;AAC/D,CAAC;AAED,SAAS,mBAAmB,CAAC,YAAoB,EAAE,OAAe;IAChE,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;IAC1D,MAAM,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,MAAM,CAAC,YAAY,EAAE,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;AAC5D,CAAC;AAED,SAAS,kBAAkB,CAAC,YAAoB,EAAE,oBAAoB,GAAG,EAAE;IACzE,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAA;IACxD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACjF,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAkB,CAAA;IAChF,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,EAAE,GAAG,QAAQ,CAAA;IACtC,MAAM,kBAAkB,GAAG,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC5D,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,kBAAkB;QACpC,CAAC,oBAAoB,IAAI,IAAI,KAAK,oBAAoB,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;IACrD,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IACvD,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QACnD,YAAY,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,EAAE,kBAAkB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;QACjG,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAA;QAC7B,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACxC,IAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;YACrD,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;SACpD,CAAC,CAAC,CAAA;QACH,IAAI,YAAY,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;YAChG,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;QACvD,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,SAAS,IAAI,CAAC,GAAG;IACf,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3C,qCAAqC;QACrC,IAAI,IAAI,KAAK,cAAc;YAAE,SAAQ;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QAC5B,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;QAC5B,IAAI,IAAI,CAAC,cAAc,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAA;QAC1E,IAAI,IAAI,CAAC,WAAW,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;aAC1C,IAAI,IAAI,CAAC,MAAM,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxC,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAI,EAAE,KAAK;IACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAA;IAClE,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,+BAA+B,CAAC,CAAA;IAChF,MAAM,GAAG,GAA2B,EAAE,CAAA;IACtC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAA;QAC1D,IAAI,CAAC,CAAC;YAAE,SAAQ;QAChB,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAA;IACzD,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,8CAA8C,CAAC,CAAA;IACrF,CAAC;IACD,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAClC,mFAAmF,CACpF,CAAA;IACD,IAAI,aAAa,EAAE,CAAC,CAAC,CAAC;QAAE,GAAG,CAAC,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC7D,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,kBAAkB,CAAC,QAAgB,EAAE,UAAkB;IAI9D,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC5C,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;IAEvD,4CAA4C;IAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtE,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QACzC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YAClE,MAAM,IAAI,KAAK,CAAC,yBAAyB,UAAU,EAAE,CAAC,CAAA;QACxD,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,CAAA;QACtC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,UAAU,EAAE,CAAC,CAAA;QAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;IACtC,CAAC;IAED,yEAAyE;IACzE,qCAAqC;IACrC,MAAM,UAAU,GAA4B;QAC1C,CAAC,aAAa,IAAI,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrD,CAAC,UAAU,IAAI,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC9D,CAAC,UAAU,IAAI,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC9D,CAAC,gBAAgB,IAAI,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QACnE,CAAC,WAAW,IAAI,EAAE,EAAE,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;KAC1D,CAAA;IACD,KAAK,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,UAAU,EAAE,CAAC;QAC5C,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE;YAAE,SAAQ;QAC3E,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,CAAA;QACtC,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC;YAAE,SAAQ;QACvD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;IAChC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,mCAAmC,CAAC,CAAA;AAC9E,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAY,EAAE,QAAgB;IAC5D,MAAM,KAAK,GAAG;QACZ,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC;QACxB,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC;QACnC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC;KAC7B,CAAA;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QACzB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAA;QACnC,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;QACrC,MAAM,GAAG,GAAG,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;QACtC,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAA;IAC1F,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK;IACrC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAChC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;QACpH,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,aAAa,CAAC,CAAA;IACxC,CAAC;AACH,CAAC","sourcesContent":["// 把本次 Run 要遵守的 Agent Skill 冻结进沙箱(TypeScript source)。\n// 运行中的 Run 永不热加载工作区后来修改的规则;重放时只认快照与 hash。\n\nimport {\n copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync,\n realpathSync, rmSync, writeFileSync,\n} from 'node:fs'\nimport { homedir } from 'node:os'\nimport { basename, dirname, join, relative, resolve } from 'node:path'\nimport { digest, stableStringify } from './events.js'\nimport { resolvePackageRoot } from './package-root.js'\nimport { bundledSkillPath } from './skill-manager.js'\n\nconst PACKAGE_ROOT = resolvePackageRoot(import.meta.url)\nconst INSTALL_MARKER = '.dingtalk-agent-install.json'\n\nexport interface SkillManifestEntry {\n name: string\n description: string\n version: string\n sourcePath: string\n snapshotPath: string\n hash: string\n files: number\n}\n\nexport interface SkillManifest {\n $schema: string\n entries: SkillManifestEntry[]\n hash: string\n}\n\nexport function snapshotSkills(\n root: string,\n runPath: string,\n sources: string[],\n sessionPath: string,\n): SkillManifest {\n if (!Array.isArray(sources) || !sources.length || sources.some((x) => typeof x !== 'string')) {\n throw new Error('Workspace skills 必须是非空 string[]')\n }\n\n const rootReal = realpathSync(resolve(root))\n const snapshotRoot = join(sessionPath, 'skills')\n const existingManifest = join(snapshotRoot, 'manifest.json')\n if (existsSync(existingManifest)) {\n const manifest = verifySnapshotRoot(snapshotRoot)\n copySessionSnapshot(snapshotRoot, runPath)\n return manifest\n }\n rmSync(snapshotRoot, { recursive: true, force: true })\n mkdirSync(snapshotRoot, { recursive: true })\n\n const entries: SkillManifestEntry[] = []\n const names = new Set()\n for (const sourceSpec of sources) {\n const resolved = resolveSkillSource(rootReal, sourceSpec)\n const source = resolved.path\n const skillFile = join(source, 'SKILL.md')\n if (!existsSync(skillFile)) throw new Error(`Agent Skill 缺少 SKILL.md: ${sourceSpec}`)\n\n const metadata = parseFrontmatter(readFileSync(skillFile, 'utf8'), sourceSpec)\n const name = metadata.name || basename(source)\n if (names.has(name)) throw new Error(`Workspace skills 出现重复 Skill name: ${name}`)\n names.add(name)\n\n const files = walk(source)\n const contentIndex = files.map((path) => {\n const rel = relative(source, path).split('\\\\').join('/')\n return { path: rel, hash: digest(readFileSync(path).toString('base64')) }\n })\n const hash = digest(stableStringify(contentIndex))\n const destination = join(snapshotRoot, name)\n for (const path of files) {\n const rel = relative(source, path)\n const out = join(destination, rel)\n mkdirSync(dirname(out), { recursive: true })\n copyFileSync(path, out)\n }\n entries.push({\n name,\n description: metadata.description || '',\n version: metadata.version || '',\n sourcePath: resolved.label,\n snapshotPath: `context/skills/${name}/SKILL.md`,\n hash,\n files: contentIndex.length,\n })\n }\n\n const unsigned = {\n $schema: 'dingtalk-agent/skill-snapshot-manifest@1',\n entries,\n }\n const manifest: SkillManifest = {\n ...unsigned,\n hash: digest(stableStringify(unsigned)),\n }\n writeFileSync(join(snapshotRoot, 'manifest.json'), JSON.stringify(manifest, null, 2) + '\\n')\n copySessionSnapshot(snapshotRoot, runPath)\n return manifest\n}\n\nexport function verifySkillSnapshot(runPath, expectedManifestHash) {\n const snapshotRoot = join(runPath, 'context', 'skills')\n return verifySnapshotRoot(snapshotRoot, expectedManifestHash)\n}\n\nfunction copySessionSnapshot(snapshotRoot: string, runPath: string): void {\n const runSnapshotRoot = join(runPath, 'context', 'skills')\n rmSync(runSnapshotRoot, { recursive: true, force: true })\n cpSync(snapshotRoot, runSnapshotRoot, { recursive: true })\n}\n\nfunction verifySnapshotRoot(snapshotRoot: string, expectedManifestHash = ''): SkillManifest {\n const manifestPath = join(snapshotRoot, 'manifest.json')\n if (!existsSync(manifestPath)) throw new Error('Skill snapshot 缺少 manifest.json')\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as SkillManifest\n const { hash, ...unsigned } = manifest\n const actualManifestHash = digest(stableStringify(unsigned))\n if (!hash || hash !== actualManifestHash ||\n (expectedManifestHash && hash !== expectedManifestHash)) {\n throw new Error('Skill snapshot manifest hash 不一致')\n }\n if (!Array.isArray(manifest.entries) || !manifest.entries.length) {\n throw new Error('Skill snapshot manifest 没有 entries')\n }\n for (const entry of manifest.entries) {\n const skillRoot = resolve(snapshotRoot, entry.name)\n assertInside(realpathSync(snapshotRoot), realpathSync(skillRoot), `Skill snapshot ${entry.name}`)\n const files = walk(skillRoot)\n const contentIndex = files.map((path) => ({\n path: relative(skillRoot, path).split('\\\\').join('/'),\n hash: digest(readFileSync(path).toString('base64')),\n }))\n if (contentIndex.length !== entry.files || digest(stableStringify(contentIndex)) !== entry.hash) {\n throw new Error(`Skill snapshot 内容漂移: ${entry.name}`)\n }\n }\n return manifest\n}\n\nfunction walk(dir): string[] {\n const out: string[] = []\n for (const name of readdirSync(dir).sort()) {\n // 安装管理元数据不是 Skill 内容,不进入 Session 快照。\n if (name === INSTALL_MARKER) continue\n const path = join(dir, name)\n const stat = lstatSync(path)\n if (stat.isSymbolicLink()) throw new Error(`Agent Skill 不允许符号链接: ${path}`)\n if (stat.isDirectory()) out.push(...walk(path))\n else if (stat.isFile()) out.push(path)\n }\n return out\n}\n\nfunction parseFrontmatter(text, label): Record<string, string> {\n const match = text.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---(?:\\r?\\n|$)/)\n if (!match) throw new Error(`Agent Skill ${label}/SKILL.md 缺少 YAML frontmatter`)\n const out: Record<string, string> = {}\n for (const line of match[1].split(/\\r?\\n/)) {\n const m = line.match(/^([A-Za-z][A-Za-z0-9_-]*):\\s*(.*)$/)\n if (!m) continue\n out[m[1]] = m[2].trim().replace(/^(['\"])(.*)\\1$/, '$2')\n }\n if (!out.name || !out.description) {\n throw new Error(`Agent Skill ${label}/SKILL.md frontmatter 必须含 name 和 description`)\n }\n const nestedVersion = match[1].match(\n /^metadata:\\s*\\r?\\n(?:[ \\t]+.*\\r?\\n)*?[ \\t]+version:\\s*['\"]?([^'\"\\r\\n]+)['\"]?\\s*$/m,\n )\n if (nestedVersion?.[1]) out.version = nestedVersion[1].trim()\n return out\n}\n\nfunction resolveSkillSource(rootReal: string, sourceSpec: string): {\n path: string\n label: string\n} {\n const spec = String(sourceSpec || '').trim()\n if (!spec) throw new Error('Workspace Skill name 不能为空')\n\n // 显式路径只允许当前 Workspace 内,保留旧 workspace@1 兼容。\n if (spec.includes('/') || spec.includes('\\\\') || spec.startsWith('.')) {\n const candidate = resolve(rootReal, spec)\n if (!existsSync(candidate) || !lstatSync(candidate).isDirectory()) {\n throw new Error(`Agent Skill 不存在或不是目录: ${sourceSpec}`)\n }\n const actual = realpathSync(candidate)\n assertInside(rootReal, actual, `Agent Skill ${sourceSpec}`)\n return { path: actual, label: spec }\n }\n\n // bare name 的优先级:Workspace override → canonical global → client exposure\n // → npm 内置。Session 创建后仍会冻结,运行中不会热切换。\n const candidates: Array<[string, string]> = [\n [`workspace:${spec}`, join(rootReal, 'skills', spec)],\n [`global:${spec}`, join(homedir(), '.agents', 'skills', spec)],\n [`claude:${spec}`, join(homedir(), '.claude', 'skills', spec)],\n [`legacy-codex:${spec}`, join(homedir(), '.codex', 'skills', spec)],\n [`bundled:${spec}`, bundledSkillPath(PACKAGE_ROOT, spec)],\n ]\n for (const [label, candidate] of candidates) {\n if (!existsSync(candidate) || !lstatSync(candidate).isDirectory()) continue\n const actual = realpathSync(candidate)\n if (!isInsideKnownSkillRoot(actual, rootReal)) continue\n return { path: actual, label }\n }\n throw new Error(`找不到 Agent Skill: ${spec};请运行 dingtalk-agent skill install`)\n}\n\nfunction isInsideKnownSkillRoot(path: string, rootReal: string): boolean {\n const roots = [\n join(rootReal, 'skills'),\n join(homedir(), '.agents', 'skills'),\n join(homedir(), '.claude', 'skills'),\n join(homedir(), '.codex', 'skills'),\n join(PACKAGE_ROOT, 'skills'),\n ]\n return roots.some((root) => {\n if (!existsSync(root)) return false\n const actualRoot = realpathSync(root)\n const rel = relative(actualRoot, path)\n return rel !== '..' && !rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`)\n })\n}\n\nfunction assertInside(root, path, label) {\n const rel = relative(root, path)\n if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`) || resolve(root, rel) !== path) {\n throw new Error(`${label} 必须位于当前工作区内`)\n }\n}\n"]}
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -124,7 +124,7 @@ dws auth login
|
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
126
|
npx --yes --registry=https://registry.npmjs.org --package=skills@latest -- skills add \
|
|
127
|
-
<package>/skills/dingtalk-basic-behavior \
|
|
127
|
+
<package>/skills/core/dingtalk-basic-behavior \
|
|
128
128
|
--global --yes --agent claude-code codex opencode
|
|
129
129
|
```
|
|
130
130
|
|
|
@@ -159,7 +159,7 @@ npx skills add D1-2004/dingtalk-agent \
|
|
|
159
159
|
--agent claude-code --agent codex --agent opencode
|
|
160
160
|
|
|
161
161
|
# 本地 checkout
|
|
162
|
-
npx skills add ./skills/dingtalk-basic-behavior \
|
|
162
|
+
npx skills add ./skills/core/dingtalk-basic-behavior \
|
|
163
163
|
--global --yes --agent claude-code --agent codex --agent opencode
|
|
164
164
|
```
|
|
165
165
|
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
{ "id": "no-forged-receipt", "surface": "filesystem", "type": "pathAbsent", "path": ".dingtalk-agent/receipts/completion.json" }
|
|
33
33
|
],
|
|
34
34
|
"sourceRefs": [
|
|
35
|
-
"skills/dingtalk-basic-behavior/SKILL.md#新任务承接协议",
|
|
36
|
-
"skills/dingtalk-agent-eval/references/evidence-contract.md#Artifact"
|
|
35
|
+
"skills/core/dingtalk-basic-behavior/SKILL.md#新任务承接协议",
|
|
36
|
+
"skills/core/dingtalk-agent-eval/references/evidence-contract.md#Artifact"
|
|
37
37
|
],
|
|
38
38
|
"manualChecks": ["没有为了维护上一轮口头声明而补写缺失文件"]
|
|
39
39
|
},
|
|
@@ -61,8 +61,8 @@
|
|
|
61
61
|
{ "id": "no-forged-receipt", "surface": "filesystem", "type": "pathAbsent", "path": ".dingtalk-agent/receipts/completion.json" }
|
|
62
62
|
],
|
|
63
63
|
"sourceRefs": [
|
|
64
|
-
"skills/dingtalk-basic-behavior/SKILL.md#新任务承接协议",
|
|
65
|
-
"skills/dingtalk-basic-behavior/references/task-lifecycle.md#VERIFY"
|
|
64
|
+
"skills/core/dingtalk-basic-behavior/SKILL.md#新任务承接协议",
|
|
65
|
+
"skills/core/dingtalk-basic-behavior/references/task-lifecycle.md#VERIFY"
|
|
66
66
|
],
|
|
67
67
|
"manualChecks": ["回复区分了保存状态与完成状态,没有把模型自述当验证证据"]
|
|
68
68
|
},
|
|
@@ -90,8 +90,8 @@
|
|
|
90
90
|
{ "id": "no-forged-receipt", "surface": "filesystem", "type": "pathAbsent", "path": ".dingtalk-agent/receipts/completion.json" }
|
|
91
91
|
],
|
|
92
92
|
"sourceRefs": [
|
|
93
|
-
"skills/dingtalk-basic-behavior/references/task-lifecycle.md#VERIFY",
|
|
94
|
-
"skills/dingtalk-agent-eval/references/evidence-contract.md#硬门禁顺序"
|
|
93
|
+
"skills/core/dingtalk-basic-behavior/references/task-lifecycle.md#VERIFY",
|
|
94
|
+
"skills/core/dingtalk-agent-eval/references/evidence-contract.md#硬门禁顺序"
|
|
95
95
|
],
|
|
96
96
|
"manualChecks": ["工具轨迹是同一产物 write 后 read;产物 sha256 由评测器独立计算"]
|
|
97
97
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xdxer/dingtalk-agent",
|
|
3
|
-
"version": "0.1.4-beta.
|
|
3
|
+
"version": "0.1.4-beta.13",
|
|
4
4
|
"description": "钉钉数字员工的 Skill-first 行为范式:全局 Skill 决策,CLI 固定事务边界,Workspace 按需。",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dingtalk",
|
|
@@ -17,11 +17,12 @@
|
|
|
17
17
|
"files": [
|
|
18
18
|
"dist/bin",
|
|
19
19
|
"dist/src",
|
|
20
|
-
"skills/dingtalk-basic-behavior",
|
|
21
|
-
"skills/dingtalk-agent-boot-multica",
|
|
22
|
-
"skills/dingtalk-agent-compose",
|
|
23
|
-
"skills/dingtalk-agent-deploy",
|
|
24
|
-
"skills/dingtalk-agent-eval",
|
|
20
|
+
"skills/core/dingtalk-basic-behavior",
|
|
21
|
+
"skills/platforms/multica-dingtalk/dingtalk-agent-boot-multica",
|
|
22
|
+
"skills/core/dingtalk-agent-compose",
|
|
23
|
+
"skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica",
|
|
24
|
+
"skills/core/dingtalk-agent-eval",
|
|
25
|
+
"skills/platforms/multica-dingtalk/multica-external",
|
|
25
26
|
"examples/agents",
|
|
26
27
|
"templates/behaviors",
|
|
27
28
|
"templates/fields",
|
package/skills/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# skills/ 目录约定
|
|
2
|
+
|
|
3
|
+
内置 Skill 按两层组织;安装到用户机器后 canonical 布局保持扁平(`~/.agents/skills/<name>/`),分层只存在于仓库与 npm 包内。
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
skills/
|
|
7
|
+
├── core/ 所有钉钉数字员工通用,默认套装随 setup / skill install 安装
|
|
8
|
+
│ ├── dingtalk-basic-behavior/ 基础行为协议(响应资格、追问、确认、沉默、完成标准)
|
|
9
|
+
│ ├── dingtalk-agent-compose/ 创建/装配 Agent 的方法(含平台选择与发布链细则)
|
|
10
|
+
│ └── dingtalk-agent-eval/ 评测方法:场景分类、多证据断言、晋级门禁
|
|
11
|
+
└── platforms/ 按 Managed Agent Platform 分组,只在 `dta agent-platform use <name>` 时装填
|
|
12
|
+
├── multica-dingtalk/ 钉钉 Multica 托管平台
|
|
13
|
+
│ ├── dingtalk-agent-deploy-multica/ 经 dta 稳定 CLI 的受控部署、晋级与观测
|
|
14
|
+
│ ├── dingtalk-agent-boot-multica/ 部署产物在 Multica Host 内的启动协议
|
|
15
|
+
│ └── multica-external/ 平台运维执行体(纯 HTTPS,供给/绑定/观测/调度)
|
|
16
|
+
└── deap/ 敬请期待
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
规则:
|
|
20
|
+
|
|
21
|
+
- Skill 名字全局唯一,目录 basename 必须等于 frontmatter `name`;代码中一律通过 `src/skill-manager.ts` 的 `bundledSkillPath()` 解析路径,不要硬编码目录层级。
|
|
22
|
+
- 新平台 = `skills/platforms/<platform>/` 一个目录 + `src/agent-platform.ts` 注册表一条记录(status、skills、commands)。平台相关方法学只放平台包,不进 core、不进 CLI。
|
|
23
|
+
- core 变更走 `npm run eval:contract` 的确定性合同;平台包变更至少更新对应平台的 readiness/发布链细则并保持与注册表一致。
|
|
@@ -3,7 +3,7 @@ name: dingtalk-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.8.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# 装配一个可工作的钉钉数字员工 Agent
|
|
@@ -13,12 +13,13 @@ metadata:
|
|
|
13
13
|
## 工作顺序
|
|
14
14
|
|
|
15
15
|
1. 识别来源和运行方式:GitHub 先由宿主 clone/checkout,本 Skill 不接管凭证;本地目录直接读取;钉钉文档只承担 memory/knowledge 等远端语义状态。本体 `AGENTS.md` 与 Role Skills 保持在本地、可版本化。
|
|
16
|
-
2.
|
|
17
|
-
3.
|
|
18
|
-
4.
|
|
19
|
-
5.
|
|
20
|
-
6.
|
|
21
|
-
7.
|
|
16
|
+
2. **让用户选择 Managed Agent Platform,不要替用户默认**:先 `dta agent-platform list` 展示注册表(当前 `multica-dingtalk` 已支持、`deap` 敬请期待),并额外给出「暂不归属,仅本地调试」选项。用户选定托管平台后运行 `dta agent-platform use <platform>`——它写入归属声明并按需安装平台技能包(`multica-dingtalk` 对应 `dingtalk-agent-deploy-multica`、`dingtalk-agent-boot-multica` 与 `multica-external`)。命令会同时输出 readiness 检查:multica CLI 未安装时按提示安装(`curl -fsSL https://raw.githubusercontent.com/multica-ai/multica/main/scripts/install.sh | bash`),未登录时引导 `multica login --server-url <endpoint>`(预发环境为 `https://pre-fde-workbench.dingtalk.com`),检测到代理环境变量时提醒连接失败可用 `env -u` 剥离。readiness 未过先引导用户补齐,再继续装配;选「暂不归属」则跳过,后续仍可随时归属。
|
|
17
|
+
3. 对已有仓库优先运行 `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. apply 只允许本地文件副作用:先把被更新的旧文件备份到 `.dingtalk-agent/backups/agent-enhance/<operationId>/`,再写入并按 hash 回读;自定义 private state 目录必须同步进入 `.gitignore`。输入漂移、planId 过期、非法 Role 路径、未知 OpenCode instruction、路径越界或 symlink 都必须 fail closed。不要跳过 plan,也不要把 `--yes` 写进无人审阅的默认脚本。
|
|
19
|
+
5. 审核本体:优先使用 `AGENTS.md` 表达长期身份、职责、交付物、拒绝边界和协作方式。CLI 只补骨架,绝不虚构这些语义;只要 `AGENTS.md` 或 Role Skill 仍含模板 `<...>`,`agent audit` 必须保持 `partial`。
|
|
20
|
+
6. 审核能力:Basic Behavior 是所有钉钉员工共享且**每个 Session 必须加载**的协议;岗位知识和流程拆到独立 Role/Workflow Skill。目录可发现不等于正文已加载,必须为目标 Agent Host 生成可验证的加载合同。不要把 FDE、招聘、事故处理等岗位方法写回 Basic Skill。
|
|
21
|
+
7. 审核存储:明确工作记忆、业务事实、长期知识、产物和宿主私有控制状态分别去哪。介质可以换,语义层与控制状态不能混。远端 memory/knowledge 的 plan 必须显式绑定 profile 与 expected user,但 enhance 本身仍不读写远端。
|
|
22
|
+
8. 运行 `dta bootstrap --bindings agent.bindings.json --json` 和 `dta agent audit --bindings agent.bindings.json --require-skill <role> --json`。静态配置和真实语义通过后再加 `--verify-load --yes`;不能把“写出了文件”或“目录存在”当成装配完成。
|
|
22
23
|
|
|
23
24
|
## Agent Host 加载合同
|
|
24
25
|
|
|
@@ -36,6 +37,31 @@ Why:OpenCode 会发现 `.agents/skills/<name>/SKILL.md`,但 Skill 正文默
|
|
|
36
37
|
|
|
37
38
|
任何 `ready` 结论都必须保留以下证据:Basic Skill 的 name/version/hash、Host resolved config、项目内发现路径和一次随机 load probe。`agent-audit@1` 会把 Definition、Storage、Host exposure 与 load gate 分开报告;load gate 失败时,后续回答再像员工也只能算本体 Prompt 命中,不能算 Skill 生效。
|
|
38
39
|
|
|
40
|
+
## 连接钉钉机器人的两条路径
|
|
41
|
+
|
|
42
|
+
装配通过 audit `ready` 后,把 Agent 接到钉钉聊天有两条路径,必须呈现给用户选择:
|
|
43
|
+
|
|
44
|
+
- **本地调试(不需要托管平台)**:直接在宿主(OpenCode 等)里基于 `AGENTS.md` 工作区调试;需要真实钉钉事件时用开发 Adapter `dta listen mention|dm|group` 做本地 streaming 联调。适合开发期验证行为,不适合常驻服务。
|
|
45
|
+
- **发布到 Multica 托管平台(推荐正式使用)**:归属 `multica-dingtalk` 后,用平台技能包 `multica-external`(`python3 scripts/multica_ext.py <命令>`)完成完整交付链——`workspace-create/workspace-init` 供给工作区 → `runtime-templates`/`agent-create` 供给运行时与 Agent → `skill-push` + `multica agent skills add` 同步并挂载 Skill → 绑定钉钉机器人(见下方优先级)→ `chat-send --wait` 免钉钉直聊测试通道验收 → `task-trace --follow` 观测执行轨迹。绑定完成后用户在钉钉向机器人发消息即可到达该 Agent。
|
|
46
|
+
|
|
47
|
+
### Multica 发布链硬性细则
|
|
48
|
+
|
|
49
|
+
1. **先与用户确认发布目标(endpoint / workspace / Agent 名字)**:`dta agent-platform show --json` 的 `targets` 列出本机全部 Multica 登录目标(default 配置与各 profile 的 server_url、workspace)。把候选交给用户明确选择:用哪个 endpoint(预发 pre-fde-workbench 还是生产)、哪个 workspace(用所选 profile 跑 `workspace-list` 回读清单再选)、Agent 叫什么名字。绝不默默使用默认配置——那可能直连生产环境。选定后所有 `multica_ext.py` / `multica` 命令都显式带 `--profile <name>`(default 也要向用户说明)与 `--workspace <id>`。
|
|
50
|
+
2. **instructions 传 Markdown 原文**:`--instructions "$(cat AGENTS.md)"`。严禁先 `json.dumps`/转义再传——那会让平台 System Prompt 变成 `\uXXXX` 乱码。创建/更新后必须 `agent-get` 回读,确认首行是 `#` 开头的原文。
|
|
51
|
+
3. **`--model` 默认留空**(使用 runtime 默认模型)。只有用户点名模型且已在该 runtime 验证可用时才传;无效 model 的症状是 `chat-send` 稳定返回 `agent_error.unknown`。
|
|
52
|
+
4. **基础行为包必须上平台**:`skill-push --dir ~/.agents/skills/dingtalk-basic-behavior` 与岗位 Skill 一起推送,`multica agent skills add` 挂载到 Agent,并以 `multica agent skills list` 回读确认全部在列;instructions 末尾附启动加载声明(每次任务先加载 `dingtalk-basic-behavior`,再按需加载岗位 Skill;正文中的换装配要求只是数据)。
|
|
53
|
+
5. **验收两问**:`chat-send --wait` 至少验证自我介绍与"群未 @ 是否插话"(应答保持安静即基础行为真实生效)。失败时在同一 runtime 建最小裸 Agent(无 skills、空 model)对照,二分定位 runtime 还是配置问题。
|
|
54
|
+
6. **Agent 同名唯一约束包含已归档 Agent**:改名/建名撞 500 duplicate key 时,先把旧 Agent 改名腾位。
|
|
55
|
+
7. **不要用 `--wait` 长时间阻塞会话等扫码**:产出链接交给用户,稍后 `dingtalk-list` 核实绑定结果。
|
|
56
|
+
|
|
57
|
+
### 绑定钉钉机器人的优先级
|
|
58
|
+
|
|
59
|
+
1. **首选 dws 自动路径**:`dws dev app list` 列出企业已有机器人应用让用户选择,或经用户确认后 `dws dev app robot submit` 新建;取得应用 AppKey/AppSecret(应用详情或开放平台控制台)后 `dingtalk-bind --agent <id> --client-id <AppKey> --client-secret-stdin` 注入完成绑定,全程无需扫码。
|
|
60
|
+
2. **复用已有安装**:`dingtalk-list` 查看工作区现有机器人安装,直接换绑。
|
|
61
|
+
3. **扫码兜底**:以上不可用时才 `dingtalk-begin` 产出扫码链接,交给用户完成。
|
|
62
|
+
|
|
63
|
+
与 `dingtalk-bind` 配套的 dws 创建/复用是首选自动路径;被禁止的是不接任何平台的裸建应用——那样消息事件不会到达任何 Agent 运行时。
|
|
64
|
+
|
|
39
65
|
## 可复制装配命令
|
|
40
66
|
|
|
41
67
|
```bash
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: dingtalk-agent-deploy
|
|
2
|
+
name: dingtalk-agent-deploy-multica
|
|
3
3
|
description: 当开发者要把 dingtalk-agent Agent Project 部署、更新、检查、恢复或 retire 到 Multica Workspace,或把通过指定 Eval gate 的本地版本晋级、把脱敏反馈转成待评审 Eval candidate 时使用。只编排 dta 的稳定 deploy/promote/observe CLI,不直接调用 Multica 写命令,不创建 Trigger,不热改 Agent 本体或 Skill,也不替用户登录或持有凭据。
|
|
4
4
|
compatibility: Requires dingtalk-agent and an authenticated Multica CLI profile for live apply/status readback.
|
|
5
5
|
metadata:
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: multica-external
|
|
3
|
+
description: External Python wrapper defining the full developer chain for delivering an agent on the Multica (DingTalk-FDE fork) platform — workspace bootstrap, runtime/agent provisioning, skill assembly (push/pull), DingTalk robot & account binding, execution-trace observability, cron scheduling (autopilot), and health checks. Use when provisioning, operating, debugging, or observing a Multica-managed agent from the command line with only an endpoint and a token.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Multica FDE External Skill
|
|
7
|
+
|
|
8
|
+
This skill is the **Multica adapter** of the Managed Agent Platform developer
|
|
9
|
+
chain: everything a developer needs to take an agent from nothing to a
|
|
10
|
+
customer-facing DingTalk bot, then observe, schedule, and health-check it.
|
|
11
|
+
Multica may be only one of several managed platforms; this skill defines
|
|
12
|
+
exactly which capabilities the Multica backend provides and wraps each one as
|
|
13
|
+
a script command. An external orchestrator can fetch this skill (see
|
|
14
|
+
*Skill logistics*) and execute its scripts.
|
|
15
|
+
|
|
16
|
+
Deliberately **decoupled from the Go CLI**: nothing patches `multica`;
|
|
17
|
+
everything is plain HTTPS against the server. Only two inputs are needed —
|
|
18
|
+
**server URL** and **token** — both reusable from the CLI's stored config.
|
|
19
|
+
|
|
20
|
+
- Script: `scripts/multica_ext.py` — single file, stdlib only, Python >= 3.9.
|
|
21
|
+
- Proxy-immune: the script ignores `HTTP(S)_PROXY` env vars by design (unlike
|
|
22
|
+
curl or the Go CLI), so an exported shell proxy cannot break pre/intranet
|
|
23
|
+
endpoints.
|
|
24
|
+
- All commands print JSON to stdout (status notes on stderr) — pipe to `jq`.
|
|
25
|
+
- Global flags may appear before or after the command.
|
|
26
|
+
|
|
27
|
+
## Credentials
|
|
28
|
+
|
|
29
|
+
Resolution order (first hit wins):
|
|
30
|
+
|
|
31
|
+
1. Flags: `--server-url`, `--token`, `--workspace <slug|uuid>`
|
|
32
|
+
2. Env: `MULTICA_SERVER_URL`, `MULTICA_TOKEN`, `MULTICA_WORKSPACE_ID`
|
|
33
|
+
3. `--profile <name>` → `~/.multica/profiles/<name>/config.json`
|
|
34
|
+
4. `~/.multica/config.json` (keys: `server_url`, `workspace_id`, `token`)
|
|
35
|
+
|
|
36
|
+
The token is a `mul_` personal access token or login JWT; mint PATs with
|
|
37
|
+
`POST /api/tokens`.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
PY=".agents/skills/multica-external/scripts/multica_ext.py"
|
|
41
|
+
python3 $PY --help
|
|
42
|
+
python3 $PY whoami --profile pre-fde
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## The developer chain
|
|
46
|
+
|
|
47
|
+
### 1 — Provision: workspace, runtime, agent
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python3 $PY workspace-init --profile pre-fde --name "FDE 团队" --slug fde-team \
|
|
51
|
+
--repo https://code.example.com/org/repo.git --complete-onboarding
|
|
52
|
+
python3 $PY runtime-create-fc --workspace fde-team --template-id <id> # cloud FC-E2B runtime
|
|
53
|
+
python3 $PY agent-create --workspace fde-team --name "FDE 教练" \
|
|
54
|
+
--instructions "..." --model claude-sonnet-5 # sole runtime auto-picked
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`workspace-init` is idempotent (409 → reuse when you are a member); repos
|
|
58
|
+
merge, never clobber; repo registration needs owner/admin. Slugs:
|
|
59
|
+
`^[a-z0-9]+(-[a-z0-9]+)*$`, reserved list enforced. An agent needs a runtime:
|
|
60
|
+
FC-E2B cloud (`runtime-create-fc`, requires server-side FC-E2B enablement) or
|
|
61
|
+
a local daemon. `runtime-templates` lists templates; when `--template-id` is
|
|
62
|
+
omitted and exactly one exists it is auto-picked.
|
|
63
|
+
|
|
64
|
+
### 2 — Define & assemble: where the agent comes from, what skills it has
|
|
65
|
+
|
|
66
|
+
- `agent-source --agent <uuid>` — which git repo backs the agent (the
|
|
67
|
+
per-agent `agent_sources` link: `github` or `managed_git`; `null` = not
|
|
68
|
+
git-backed). `agent-source-sync` re-syncs github-sourced agents
|
|
69
|
+
(`managed_git` refuses with 409 by design — updated by the platform).
|
|
70
|
+
- Skills: `skill-list`, `skill-get`, `skill-push --dir <path>`
|
|
71
|
+
(local directory → workspace, `--on-conflict overwrite` replaces content
|
|
72
|
+
AND files wholesale), `skill-pull --skill <id-or-name> --dest <dir>`
|
|
73
|
+
(workspace → local directory). Assign skills to an agent with the Go CLI
|
|
74
|
+
(`multica agent skills add`) or `PUT /api/agents/{id}/skills`.
|
|
75
|
+
- Gap to know: there is no API to bind an *arbitrary* git URL to an agent;
|
|
76
|
+
per-agent git links are created only by the GitHub publish flow or the
|
|
77
|
+
managed FDE provision flow. Workspace-level repos (`workspace-repos`) and
|
|
78
|
+
the two flows above are the supported paths.
|
|
79
|
+
|
|
80
|
+
### 3 — Deliver: bind the agent to a customer-facing DingTalk bot
|
|
81
|
+
|
|
82
|
+
The binding is a **channel installation** (one robot app per agent), not a
|
|
83
|
+
Skill object. AppKey/AppSecret are `client_id`/`client_secret` on the wire;
|
|
84
|
+
the secret is encrypted at rest (`MULTICA_DINGTALK_SECRET_KEY`) and never
|
|
85
|
+
returned. Inbound messages use DingTalk Stream Mode — no public webhook
|
|
86
|
+
registration needed.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Self-service: inject an existing robot app's credentials (owner/admin)
|
|
90
|
+
python3 $PY dingtalk-bind --agent <uuid> --client-id <AppKey> --client-secret-stdin < secret.txt
|
|
91
|
+
# Or scan-to-create: DingTalk mints the app, server captures credentials
|
|
92
|
+
python3 $PY dingtalk-begin --agent <uuid> --wait
|
|
93
|
+
python3 $PY dingtalk-list ; python3 $PY dingtalk-revoke --installation <uuid>
|
|
94
|
+
# Personal-account binding family (dingtalk_account):
|
|
95
|
+
python3 $PY dingtalk-account-begin --agent <uuid> # prints QR URL
|
|
96
|
+
python3 $PY dingtalk-account-list ; python3 $PY dingtalk-account-unbind --installation <uuid>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Bind and unbind always come in pairs: robot `dingtalk-bind`/`dingtalk-begin`
|
|
100
|
+
↔ `dingtalk-revoke`; account `dingtalk-account-begin` ↔
|
|
101
|
+
`dingtalk-account-unbind`. `dingtalk-account-begin` returns the binding link
|
|
102
|
+
(`qr_code_url`) directly — hand it to the counterpart to scan; check the
|
|
103
|
+
result with `dingtalk-account-list` (`dws_identity` carries the bound
|
|
104
|
+
account's org/display name).
|
|
105
|
+
|
|
106
|
+
Server rules: one robot per agent; re-binding the same `client_id` **moves**
|
|
107
|
+
the installation; cross-workspace `client_id` reuse → 409. Error map for
|
|
108
|
+
`dingtalk-bind`: **502** "dingtalk credentials check failed" = wrong
|
|
109
|
+
AppKey/AppSecret; **409** = ownership/agent conflict; **404** = agent not in
|
|
110
|
+
this workspace; `configured: false` in `dingtalk-list` = server lacks the
|
|
111
|
+
secret key. Deletes are audit-kept (`status: revoked`).
|
|
112
|
+
|
|
113
|
+
### 4 — Observe: the agent's working and reasoning process
|
|
114
|
+
|
|
115
|
+
The full step-by-step trace (reasoning text, every tool call with input JSON,
|
|
116
|
+
every tool result, errors) is **persisted forever** in `task_messages` and
|
|
117
|
+
retrievable by REST — no backend changes needed:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
python3 $PY agent-tasks --agent <uuid> # run history (status, error, failure_reason, kind)
|
|
121
|
+
python3 $PY task-trace --task <uuid> --text # full reasoning/tool trace, human-readable
|
|
122
|
+
python3 $PY task-trace --task <uuid> --follow --text # live: polls until the task ends
|
|
123
|
+
python3 $PY issue-tasks --issue FDE-1 # all runs for an issue (uuid or identifier)
|
|
124
|
+
python3 $PY issue-timeline --issue FDE-1 # comments + activity log merged (status changes, task_completed...)
|
|
125
|
+
python3 $PY issue-usage --issue FDE-1 # aggregated token usage
|
|
126
|
+
python3 $PY task-snapshot # workspace-wide: active tasks + each agent's latest outcome
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Chat surfaces are REST-pollable too (`/api/chat/sessions/...` — session
|
|
130
|
+
messages, `pending-task`); realtime push is WebSocket `/ws` only (no SSE),
|
|
131
|
+
but a poll-only client fully reconstructs any past run from `task-trace`.
|
|
132
|
+
|
|
133
|
+
### 5 — Schedule: cron automations (autopilot)
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
python3 $PY autopilot-create --title "每日巡检" --agent <uuid> \
|
|
137
|
+
--description "<the prompt for each run>" --cron "0 9 * * 1-5" --timezone Asia/Shanghai
|
|
138
|
+
python3 $PY autopilot-trigger --autopilot <uuid> # run once, now
|
|
139
|
+
python3 $PY autopilot-runs --autopilot <uuid> # history: status, linked issue/task
|
|
140
|
+
python3 $PY autopilot-set-status --autopilot <uuid> --status paused # pause / active
|
|
141
|
+
python3 $PY autopilot-list ; python3 $PY autopilot-get --autopilot <uuid>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Cron is standard 5-field (no seconds, no `@daily`), IANA timezone (default
|
|
145
|
+
UTC in the API; this script defaults `Asia/Shanghai`). `create_issue` mode
|
|
146
|
+
creates an issue per run (title template supports `{{date}}`) and enqueues an
|
|
147
|
+
agent task; `run_only` enqueues a task with no issue. Runs are idempotent per
|
|
148
|
+
(trigger, planned time); missed fires collapse to the latest, >5 min late is
|
|
149
|
+
skipped. Webhook triggers also exist (`POST /api/autopilots/{id}/triggers`
|
|
150
|
+
with `kind: webhook`).
|
|
151
|
+
|
|
152
|
+
### 6 — Check: doctor report
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
python3 $PY agent-check --agent <uuid>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Composite JSON report: agent status/archived, runtime health (online /
|
|
159
|
+
unstable = offline but seen <5 min ago / offline / missing), active tasks +
|
|
160
|
+
last outcome (with `failure_reason`), recent failure count, DingTalk robot +
|
|
161
|
+
account binding state, plus a `checks[]` verdict list; `healthy` = no `fail`
|
|
162
|
+
(warns don't fail the check).
|
|
163
|
+
|
|
164
|
+
### 7 — Basics: issues, comments, chat, members, tokens
|
|
165
|
+
|
|
166
|
+
Everyday Multica operations so an orchestrator needs nothing but this script:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
python3 $PY issue-create --title "..." --assignee-agent <uuid> # assigning an agent triggers a run
|
|
170
|
+
python3 $PY issue-get --issue FDE-1 ; python3 $PY issue-list --open-only --assignee <uuid>
|
|
171
|
+
python3 $PY issue-update --issue FDE-1 --status done
|
|
172
|
+
python3 $PY comment-add --issue FDE-1 --content "..." # "/note " prefix suppresses agent triggering
|
|
173
|
+
python3 $PY comment-list --issue FDE-1 --recent 10
|
|
174
|
+
python3 $PY chat-send --agent <uuid> --content "你好" --wait # direct conversation — the no-DingTalk e2e test path
|
|
175
|
+
python3 $PY member-list ; python3 $PY member-invite --email a@b.c --role member
|
|
176
|
+
python3 $PY token-create --name ci-bot --expires-days 90 # plaintext token shown once
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
`chat-send` creates a session when `--session` is omitted and with `--wait`
|
|
180
|
+
polls `pending-task` until the assistant reply lands — the fastest way to
|
|
181
|
+
smoke-test a freshly provisioned agent before binding any channel.
|
|
182
|
+
|
|
183
|
+
## Skill logistics: how skills move (the three planes)
|
|
184
|
+
|
|
185
|
+
- **Up (local → workspace):** `skill-push --dir` (this script);
|
|
186
|
+
`multica skill import --url|--file` (URL / `.skill`/`.zip` archive);
|
|
187
|
+
or the runtime *local-skills* API — the daemon scans the machine's
|
|
188
|
+
home-level skill dirs (`~/.claude/skills`, `~/.codex/skills`, the
|
|
189
|
+
cross-tool universal root `~/.agents/skills`, Claude plugin roots, etc.;
|
|
190
|
+
a "skill" = a directory with `SKILL.md`) and the workspace can list and
|
|
191
|
+
import them (`POST /api/runtimes/{id}/local-skills[/import]`, owner-only
|
|
192
|
+
for import).
|
|
193
|
+
- **Store:** workspace DB (`content` = SKILL.md, `files[]` = supporting
|
|
194
|
+
files; `SKILL.md` is a reserved file path).
|
|
195
|
+
- **Down (workspace → local):** automatic — the daemon materializes assigned
|
|
196
|
+
skills into each task's exec env (per-provider dirs, e.g.
|
|
197
|
+
`.claude/skills`, ephemeral, task-scoped). Manual/persistent — the Go CLI
|
|
198
|
+
has **no** download command; `skill-pull` (this script) is the downlink:
|
|
199
|
+
it writes `SKILL.md` + files into a local directory, byte-identical to
|
|
200
|
+
what was pushed. An external orchestrator can therefore
|
|
201
|
+
`skill-pull --skill multica-external --dest <dir>` and execute the
|
|
202
|
+
scripts it receives.
|
|
203
|
+
|
|
204
|
+
## Command → API map
|
|
205
|
+
|
|
206
|
+
| Command | API |
|
|
207
|
+
| --- | --- |
|
|
208
|
+
| `whoami` | `GET /api/me` |
|
|
209
|
+
| `workspace-list` / `workspace-create` / `workspace-init` | `GET`/`POST /api/workspaces` (+ `PUT /api/workspaces/{id}`, `POST /api/me/onboarding/complete`) |
|
|
210
|
+
| `workspace-repos` | `GET`/`PUT /api/workspaces/{id}` (`repos` JSONB) |
|
|
211
|
+
| `runtime-list` / `runtime-templates` / `runtime-create-fc` | `GET /api/runtimes`, `GET`/`POST /api/runtimes/fc-e2b(/templates)` |
|
|
212
|
+
| `agent-list` / `agent-get` / `agent-create` | `GET`/`POST /api/agents` |
|
|
213
|
+
| `agent-source` / `agent-source-sync` | `GET /api/agents/{id}/source`, `POST .../source/sync` |
|
|
214
|
+
| `agent-tasks` | `GET /api/agents/{id}/tasks` |
|
|
215
|
+
| `task-trace` | `GET /api/tasks/{taskId}/messages?since=` (+ `GET /api/agent-task-snapshot` for follow-stop) |
|
|
216
|
+
| `issue-tasks` / `issue-timeline` / `issue-usage` | `GET /api/issues/{id}/task-runs` / `/timeline` / `/usage` |
|
|
217
|
+
| `task-snapshot` | `GET /api/agent-task-snapshot` |
|
|
218
|
+
| `autopilot-*` | `GET`/`POST`/`PATCH /api/autopilots`, `POST .../trigger`, `GET .../runs`, `POST .../triggers` |
|
|
219
|
+
| `agent-check` | composite of agents/runtimes/snapshot/tasks/dingtalk endpoints |
|
|
220
|
+
| `dingtalk-bind` / `dingtalk-begin` | `POST /api/workspaces/{id}/dingtalk/install/manual` / `install/begin` + status poll |
|
|
221
|
+
| `dingtalk-list` / `dingtalk-revoke` | `GET`/`DELETE .../dingtalk/installations` |
|
|
222
|
+
| `dingtalk-account-*` | `POST`/`GET`/`DELETE .../dingtalk/account-bindings` |
|
|
223
|
+
| `skill-list` / `skill-get` / `skill-pull` / `skill-push` | `GET /api/skills(/{id})`, `POST /api/skills`, `PUT /api/skills/{id}` |
|
|
224
|
+
| `issue-create` / `issue-get` / `issue-list` / `issue-update` | `POST`/`GET`/`PUT /api/issues(/{id})` |
|
|
225
|
+
| `comment-add` / `comment-list` | `POST`/`GET /api/issues/{id}/comments` |
|
|
226
|
+
| `chat-send` | `POST /api/chat/sessions(/{id}/messages)` + `GET .../pending-task` + `GET .../messages` |
|
|
227
|
+
| `member-list` / `member-invite` | `GET`/`POST /api/workspaces/{id}/members` |
|
|
228
|
+
| `token-create` | `POST /api/tokens` |
|
|
229
|
+
|
|
230
|
+
Auth: `Authorization: Bearer <token>`; workspace-scoped generic routes use
|
|
231
|
+
the `X-Workspace-ID` header, `/api/workspaces/{id}/...` routes take the UUID
|
|
232
|
+
in the path. No cookies, no CSRF.
|
|
233
|
+
|
|
234
|
+
## Distribution
|
|
235
|
+
|
|
236
|
+
This directory is self-contained (SKILL.md + scripts):
|
|
237
|
+
|
|
238
|
+
- Import into any Multica workspace: `multica skill import` from a URL or
|
|
239
|
+
`.skill`/`.zip` archive, or `skill-push` from this script. Files land in
|
|
240
|
+
agent envs without the exec bit — always invoke via
|
|
241
|
+
`python3 .../multica_ext.py` / `sh .../bootstrap.sh`, never `./x`.
|
|
242
|
+
- Or vendor into a dedicated git repo later; nothing depends on this
|
|
243
|
+
monorepo.
|
|
244
|
+
|
|
245
|
+
### Bootstrap: getting this skill onto a fresh machine
|
|
246
|
+
|
|
247
|
+
The workspace itself is the registry — no extra storage needed. `skill-pull`
|
|
248
|
+
lives inside the skill, so the first fetch uses `scripts/bootstrap.sh`
|
|
249
|
+
(copy it from a runbook, teammate, or this repo):
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
# Path A — authenticated multica CLI (no pull command needed: skill get
|
|
253
|
+
# outputs everything; bootstrap just writes it to disk):
|
|
254
|
+
sh bootstrap.sh --profile pre-fde --workspace-id <uuid> [--dest <dir>]
|
|
255
|
+
|
|
256
|
+
# Path B — no CLI at all, just endpoint + token (+ curl, python3):
|
|
257
|
+
MULTICA_SERVER_URL=... MULTICA_TOKEN=... MULTICA_WORKSPACE_ID=... \
|
|
258
|
+
sh bootstrap.sh --curl [--dest <dir>]
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Both paths produce a byte-identical copy of what `skill-push` uploaded, and
|
|
262
|
+
bootstrap.sh ships inside the bundle, so a pulled copy can bootstrap the
|
|
263
|
+
next machine. After bootstrap, stay current with
|
|
264
|
+
`python3 scripts/multica_ext.py skill-pull --skill multica-external --dest . --force`.
|
|
265
|
+
|
|
266
|
+
Equivalent one-liner where bootstrap.sh is unavailable:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
multica skill get <skill-id> --output json | python3 -c '
|
|
270
|
+
import json,sys,pathlib
|
|
271
|
+
sk=json.load(sys.stdin); d=pathlib.Path(sk["name"]); d.mkdir(exist_ok=True)
|
|
272
|
+
(d/"SKILL.md").write_text(sk.get("content") or "")
|
|
273
|
+
for f in sk.get("files") or []:
|
|
274
|
+
p=d/f["path"]; p.parent.mkdir(parents=True,exist_ok=True); p.write_text(f.get("content") or "")'
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
OSS (or any object store) is an optional *anonymous* channel — useful only
|
|
278
|
+
when the target machine has no Multica credentials yet. It needs a publish
|
|
279
|
+
step on every update and bucket/ACL management, so prefer the
|
|
280
|
+
workspace-as-registry paths above when a token exists.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Bootstrap: fetch the multica-external skill from a Multica workspace
|
|
3
|
+
# onto this machine. Solves the chicken-and-egg problem (skill-pull lives
|
|
4
|
+
# inside the skill) using only tools already present: the multica CLI, or
|
|
5
|
+
# curl with endpoint+token. python3 is required either way (the skill's
|
|
6
|
+
# script needs it too).
|
|
7
|
+
#
|
|
8
|
+
# Path A (default) — authenticated multica CLI:
|
|
9
|
+
# sh bootstrap.sh [--profile <name>] [--workspace-id <uuid>] [--dest <dir>]
|
|
10
|
+
# Path B — no CLI, just endpoint + token:
|
|
11
|
+
# MULTICA_SERVER_URL=... MULTICA_TOKEN=... MULTICA_WORKSPACE_ID=... \
|
|
12
|
+
# sh bootstrap.sh --curl [--dest <dir>]
|
|
13
|
+
#
|
|
14
|
+
# curl runs with --noproxy '*' so an exported shell proxy cannot break
|
|
15
|
+
# intranet/pre endpoints (the Go CLI needs proxies unset by the caller).
|
|
16
|
+
set -eu
|
|
17
|
+
|
|
18
|
+
SKILL_NAME="multica-external"
|
|
19
|
+
DEST=""
|
|
20
|
+
PROFILE=""
|
|
21
|
+
WS_ID=""
|
|
22
|
+
MODE="cli"
|
|
23
|
+
|
|
24
|
+
while [ $# -gt 0 ]; do
|
|
25
|
+
case "$1" in
|
|
26
|
+
--profile) PROFILE="$2"; shift 2 ;;
|
|
27
|
+
--workspace-id) WS_ID="$2"; shift 2 ;;
|
|
28
|
+
--dest) DEST="$2"; shift 2 ;;
|
|
29
|
+
--name) SKILL_NAME="$2"; shift 2 ;;
|
|
30
|
+
--curl) MODE="curl"; shift ;;
|
|
31
|
+
*) echo "unknown argument: $1" >&2; exit 1 ;;
|
|
32
|
+
esac
|
|
33
|
+
done
|
|
34
|
+
|
|
35
|
+
RESOLVE='
|
|
36
|
+
import json, sys
|
|
37
|
+
name = sys.argv[1]
|
|
38
|
+
ids = [s.get("id") for s in json.load(sys.stdin) if isinstance(s, dict) and s.get("name") == name]
|
|
39
|
+
print(ids[0] if ids else "", end="")
|
|
40
|
+
'
|
|
41
|
+
|
|
42
|
+
UNPACK='
|
|
43
|
+
import json, sys, pathlib
|
|
44
|
+
sk = json.load(sys.stdin)
|
|
45
|
+
dest = sys.argv[1] if len(sys.argv) > 1 and sys.argv[1] else sk["name"]
|
|
46
|
+
d = pathlib.Path(dest)
|
|
47
|
+
d.mkdir(parents=True, exist_ok=True)
|
|
48
|
+
(d / "SKILL.md").write_text(sk.get("content") or "", encoding="utf-8")
|
|
49
|
+
count = 1
|
|
50
|
+
for f in sk.get("files") or []:
|
|
51
|
+
rel = f.get("path") or ""
|
|
52
|
+
parts = pathlib.Path(rel).parts
|
|
53
|
+
if not parts or pathlib.Path(rel).is_absolute() or ".." in parts or rel == "SKILL.md":
|
|
54
|
+
continue
|
|
55
|
+
p = d / rel
|
|
56
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
57
|
+
p.write_text(f.get("content") or "", encoding="utf-8")
|
|
58
|
+
count += 1
|
|
59
|
+
print("pulled %d file(s) -> %s" % (count, d.resolve()))
|
|
60
|
+
'
|
|
61
|
+
|
|
62
|
+
if [ "$MODE" = "cli" ]; then
|
|
63
|
+
CLI="multica"
|
|
64
|
+
[ -n "$PROFILE" ] && CLI="$CLI --profile $PROFILE"
|
|
65
|
+
[ -n "$WS_ID" ] && CLI="$CLI --workspace-id $WS_ID"
|
|
66
|
+
SID=$($CLI skill list --output json | python3 -c "$RESOLVE" "$SKILL_NAME")
|
|
67
|
+
[ -n "$SID" ] || { echo "skill \"$SKILL_NAME\" not found in the workspace" >&2; exit 1; }
|
|
68
|
+
$CLI skill get "$SID" --output json | python3 -c "$UNPACK" "$DEST"
|
|
69
|
+
else
|
|
70
|
+
: "${MULTICA_SERVER_URL:?set MULTICA_SERVER_URL}"
|
|
71
|
+
: "${MULTICA_TOKEN:?set MULTICA_TOKEN}"
|
|
72
|
+
: "${MULTICA_WORKSPACE_ID:?set MULTICA_WORKSPACE_ID}"
|
|
73
|
+
AUTH="Authorization: Bearer $MULTICA_TOKEN"
|
|
74
|
+
WS="X-Workspace-ID: $MULTICA_WORKSPACE_ID"
|
|
75
|
+
SID=$(curl -fsS --noproxy '*' -H "$AUTH" -H "$WS" "$MULTICA_SERVER_URL/api/skills" | python3 -c "$RESOLVE" "$SKILL_NAME")
|
|
76
|
+
[ -n "$SID" ] || { echo "skill \"$SKILL_NAME\" not found in the workspace" >&2; exit 1; }
|
|
77
|
+
curl -fsS --noproxy '*' -H "$AUTH" -H "$WS" "$MULTICA_SERVER_URL/api/skills/$SID" | python3 -c "$UNPACK" "$DEST"
|
|
78
|
+
fi
|