@xdxer/dingtalk-agent 0.1.4-beta.8 → 0.1.4-beta.9

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.
Files changed (212) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.en.md +395 -0
  3. package/README.md +466 -35
  4. package/dist/bin/dingtalk-agent.js +1058 -10
  5. package/dist/bin/dingtalk-agent.js.map +1 -1
  6. package/dist/src/actions.js +98 -14
  7. package/dist/src/actions.js.map +1 -1
  8. package/dist/src/agent-audit.js +460 -0
  9. package/dist/src/agent-audit.js.map +1 -0
  10. package/dist/src/agent-bindings.js +132 -0
  11. package/dist/src/agent-bindings.js.map +1 -0
  12. package/dist/src/agent-definition.js +182 -0
  13. package/dist/src/agent-definition.js.map +1 -0
  14. package/dist/src/agent-enhance.js +678 -0
  15. package/dist/src/agent-enhance.js.map +1 -0
  16. package/dist/src/bootstrap.js +125 -17
  17. package/dist/src/bootstrap.js.map +1 -1
  18. package/dist/src/development-workspace.js +729 -0
  19. package/dist/src/development-workspace.js.map +1 -0
  20. package/dist/src/dws.js +145 -0
  21. package/dist/src/dws.js.map +1 -1
  22. package/dist/src/eval-evidence.js +193 -0
  23. package/dist/src/eval-evidence.js.map +1 -0
  24. package/dist/src/invocation.js +36 -0
  25. package/dist/src/invocation.js.map +1 -0
  26. package/dist/src/lab.js +679 -0
  27. package/dist/src/lab.js.map +1 -0
  28. package/dist/src/lease.js +100 -0
  29. package/dist/src/lease.js.map +1 -0
  30. package/dist/src/memory/candidates.js +451 -0
  31. package/dist/src/memory/candidates.js.map +1 -0
  32. package/dist/src/memory/completion-evidence.js +536 -0
  33. package/dist/src/memory/completion-evidence.js.map +1 -0
  34. package/dist/src/memory/operational.js +263 -0
  35. package/dist/src/memory/operational.js.map +1 -0
  36. package/dist/src/memory/remote-state.js +478 -0
  37. package/dist/src/memory/remote-state.js.map +1 -0
  38. package/dist/src/memory/task-checkpoints.js +204 -0
  39. package/dist/src/memory/task-checkpoints.js.map +1 -0
  40. package/dist/src/multica-deploy.js +1480 -0
  41. package/dist/src/multica-deploy.js.map +1 -0
  42. package/dist/src/multica-provider.js +685 -0
  43. package/dist/src/multica-provider.js.map +1 -0
  44. package/dist/src/opencode-evals.js +1062 -0
  45. package/dist/src/opencode-evals.js.map +1 -0
  46. package/dist/src/opencode-provider.js +531 -0
  47. package/dist/src/opencode-provider.js.map +1 -0
  48. package/dist/src/opencode-workspace.js +197 -0
  49. package/dist/src/opencode-workspace.js.map +1 -0
  50. package/dist/src/perception.js +225 -0
  51. package/dist/src/perception.js.map +1 -0
  52. package/dist/src/personal-event-evals.js +595 -0
  53. package/dist/src/personal-event-evals.js.map +1 -0
  54. package/dist/src/promotion.js +786 -0
  55. package/dist/src/promotion.js.map +1 -0
  56. package/dist/src/remote-semantic-state-live-evals.js +888 -0
  57. package/dist/src/remote-semantic-state-live-evals.js.map +1 -0
  58. package/dist/src/remote-semantic-state-worker.js +38 -0
  59. package/dist/src/remote-semantic-state-worker.js.map +1 -0
  60. package/dist/src/remote-state-evals.js +501 -0
  61. package/dist/src/remote-state-evals.js.map +1 -0
  62. package/dist/src/response-gate.js +51 -0
  63. package/dist/src/response-gate.js.map +1 -0
  64. package/dist/src/robot-evals.js +770 -0
  65. package/dist/src/robot-evals.js.map +1 -0
  66. package/dist/src/sessions.js +66 -105
  67. package/dist/src/sessions.js.map +1 -1
  68. package/dist/src/skill-manager.js +25 -16
  69. package/dist/src/skill-manager.js.map +1 -1
  70. package/dist/src/skills.js.map +1 -1
  71. package/dist/src/storage-evals.js +26 -0
  72. package/dist/src/storage-evals.js.map +1 -0
  73. package/dist/src/types.js.map +1 -1
  74. package/dist/src/waits.js +5 -1
  75. package/dist/src/waits.js.map +1 -1
  76. package/dist/src/workspace.js +28 -3
  77. package/dist/src/workspace.js.map +1 -1
  78. package/docs/INSTALLATION.md +47 -0
  79. package/docs/SECOND-AGENT-ACCEPTANCE.md +62 -0
  80. package/docs/architecture/agent-memory-topology.png +0 -0
  81. package/docs/architecture/agent-memory-topology.svg +132 -0
  82. package/docs/architecture/general-agent-kernel-topology.png +0 -0
  83. package/docs/architecture/general-agent-kernel-topology.svg +149 -0
  84. package/docs/architecture/provider-bound-development-workspace.png +0 -0
  85. package/docs/architecture/provider-bound-development-workspace.svg +141 -0
  86. package/docs/architecture/task-completion-gate.png +0 -0
  87. package/docs/architecture/task-completion-gate.svg +191 -0
  88. package/docs/schemas/agent-audit-load-evidence.schema.json +14 -0
  89. package/docs/schemas/agent-audit.schema.json +92 -0
  90. package/docs/schemas/agent-bindings.schema.json +54 -0
  91. package/docs/schemas/agent-definition.schema.json +78 -0
  92. package/docs/schemas/agent-enhancement-plan.schema.json +88 -0
  93. package/docs/schemas/agent-enhancement-receipt.schema.json +37 -0
  94. package/docs/schemas/enriched-invocation.schema.json +46 -0
  95. package/docs/schemas/eval-candidate-plan.schema.json +28 -0
  96. package/docs/schemas/eval-candidate-result.schema.json +20 -0
  97. package/docs/schemas/eval-candidate.schema.json +30 -0
  98. package/docs/schemas/invocation.schema.json +19 -0
  99. package/docs/schemas/memory-candidate-proposal.schema.json +18 -0
  100. package/docs/schemas/memory-candidate.schema.json +76 -0
  101. package/docs/schemas/memory-publish-target.schema.json +25 -0
  102. package/docs/schemas/multica-deployment-list.schema.json +29 -0
  103. package/docs/schemas/multica-deployment-operation.schema.json +51 -0
  104. package/docs/schemas/multica-deployment-plan.schema.json +70 -0
  105. package/docs/schemas/multica-deployment-receipt.schema.json +87 -0
  106. package/docs/schemas/multica-deployment-status.schema.json +23 -0
  107. package/docs/schemas/multica-workspace-inspection.schema.json +77 -0
  108. package/docs/schemas/multica-workspace-plan.schema.json +68 -0
  109. package/docs/schemas/multica-workspace-resource-list.schema.json +27 -0
  110. package/docs/schemas/multica-workspace-status.schema.json +34 -0
  111. package/docs/schemas/observation.schema.json +21 -0
  112. package/docs/schemas/operational-memory-provider.schema.json +36 -0
  113. package/docs/schemas/operational-memory-record.schema.json +24 -0
  114. package/docs/schemas/perception-input.schema.json +56 -0
  115. package/docs/schemas/project.schema.json +112 -0
  116. package/docs/schemas/promotion-list.schema.json +36 -0
  117. package/docs/schemas/promotion-plan.schema.json +60 -0
  118. package/docs/schemas/promotion-policy.schema.json +29 -0
  119. package/docs/schemas/promotion-receipt.schema.json +43 -0
  120. package/docs/schemas/promotion-status.schema.json +23 -0
  121. package/docs/schemas/release-readiness.schema.json +65 -0
  122. package/docs/schemas/remote-semantic-state-live-eval.schema.json +60 -0
  123. package/docs/schemas/remote-semantic-state-manifest.schema.json +79 -0
  124. package/docs/schemas/remote-semantic-state-provider.schema.json +98 -0
  125. package/docs/schemas/response-gate.schema.json +20 -0
  126. package/docs/schemas/task-checkpoint.schema.json +71 -0
  127. package/docs/schemas/task-completion-evidence.schema.json +154 -0
  128. package/docs/schemas/workspace-doctor.schema.json +56 -0
  129. package/docs/schemas/workspace-state.schema.json +39 -0
  130. package/evals/baselines/2026-07-16/opencode-basic-010-completion-summary.json +123 -0
  131. package/evals/baselines/2026-07-16/opencode-basic-skill-required-summary.json +69 -0
  132. package/evals/baselines/2026-07-16/opencode-multi-surface-summary.json +63 -0
  133. package/evals/baselines/2026-07-16/remote-state-live-summary.json +70 -0
  134. package/evals/baselines/2026-07-17/agent-enhance-opencode-dogfood-summary.json +98 -0
  135. package/evals/baselines/2026-07-17/personal-event-live-readiness-summary.json +68 -0
  136. package/examples/agents/fde-coach/AGENTS.md +26 -0
  137. package/examples/agents/fde-coach/MEMORY.md +3 -0
  138. package/examples/agents/fde-coach/fields/default/field.json +24 -0
  139. package/examples/agents/fde-coach/knowledge/INDEX.md +4 -0
  140. package/examples/agents/fde-coach/skills/fde-coach/SKILL.md +13 -0
  141. package/examples/agents/release-manager/AGENTS.md +26 -0
  142. package/examples/agents/release-manager/MEMORY.md +3 -0
  143. package/examples/agents/release-manager/fields/default/field.json +24 -0
  144. package/examples/agents/release-manager/knowledge/INDEX.md +4 -0
  145. package/examples/agents/release-manager/skills/release-manager/SKILL.md +13 -0
  146. package/lab/README.md +109 -0
  147. package/lab/agent-eval/catalog.json +91 -0
  148. package/lab/agent-eval/classic-failures.json +177 -0
  149. package/lab/agent-eval/completion-gate-regression.json +99 -0
  150. package/lab/agent-eval/personal-event-live.example.json +94 -0
  151. package/lab/agent-eval/remote-semantic-state-live.example.json +70 -0
  152. package/lab/agent-eval/remote-semantic-state-provider.fixture.json +47 -0
  153. package/lab/agent-eval/remote-state-workspace/AGENTS.md +8 -0
  154. package/lab/agent-eval/remote-state-workspace/opencode.json +7 -0
  155. package/lab/agent-eval/remote-state-workspace/skills/remote-state-operator/SKILL.md +13 -0
  156. package/lab/agent-eval/remote-state.example.json +31 -0
  157. package/lab/agent-eval/workspace/AGENTS.md +7 -0
  158. package/lab/agent-eval/workspace/MEMORY.md +4 -0
  159. package/lab/agent-eval/workspace/artifacts/pending-review.md +3 -0
  160. package/lab/agent-eval/workspace/knowledge/INDEX.md +4 -0
  161. package/lab/agent-eval/workspace/opencode.json +20 -0
  162. package/lab/manifest.example.json +27 -0
  163. package/lab/manifest.personal-event.example.json +27 -0
  164. package/lab/project-workspace/README.md +11 -0
  165. package/lab/project-workspace/fake-multica-provider.mjs +266 -0
  166. package/lab/project-workspace/multica-deploy.fixture.json +29 -0
  167. package/lab/project-workspace/multica-readonly.fixture.json +69 -0
  168. package/lab/project-workspace/observation.fixture.json +14 -0
  169. package/lab/project-workspace/opencode-provider-suite.json +65 -0
  170. package/lab/project-workspace/project.fixture.json +44 -0
  171. package/lab/project-workspace/promotion-policy.fixture.json +15 -0
  172. package/lab/robot-eval/pool.example.json +30 -0
  173. package/lab/robot-eval/suite.json +123 -0
  174. package/lab/robot-eval/workspace/AGENTS.md +21 -0
  175. package/lab/robot-eval/workspace/MEMORY.md +3 -0
  176. package/lab/robot-eval/workspace/knowledge/INDEX.md +5 -0
  177. package/lab/robot-eval/workspace/opencode.json +22 -0
  178. package/lab/schemas/agent-eval-catalog.schema.json +47 -0
  179. package/lab/schemas/lab-manifest.schema.json +70 -0
  180. package/lab/schemas/personal-event-eval.schema.json +91 -0
  181. package/lab/schemas/remote-state-eval.schema.json +66 -0
  182. package/lab/schemas/robot-eval-suite.schema.json +184 -0
  183. package/lab/schemas/robot-pool.schema.json +56 -0
  184. package/package.json +21 -3
  185. package/skills/dingtalk-agent-boot-multica/SKILL.md +40 -0
  186. package/skills/dingtalk-agent-compose/SKILL.md +110 -0
  187. package/skills/dingtalk-agent-compose/assets/AGENTS.template.md +26 -0
  188. package/skills/dingtalk-agent-compose/assets/agent.bindings.dingtalk-doc.template.json +13 -0
  189. package/skills/dingtalk-agent-compose/assets/agent.bindings.local.template.json +13 -0
  190. package/skills/dingtalk-agent-compose/assets/opencode.template.json +12 -0
  191. package/skills/dingtalk-agent-compose/assets/role-skill.template.md +24 -0
  192. package/skills/dingtalk-agent-compose/evals/evals.json +94 -0
  193. package/skills/dingtalk-agent-compose/references/agent-definition-contract.md +55 -0
  194. package/skills/dingtalk-agent-compose/references/opencode-host-contract.md +65 -0
  195. package/skills/dingtalk-agent-compose/references/storage-routing.md +20 -0
  196. package/skills/dingtalk-agent-deploy/SKILL.md +60 -0
  197. package/skills/dingtalk-agent-deploy/references/multica-deployment-contract.md +49 -0
  198. package/skills/dingtalk-agent-deploy/references/promotion-observation-contract.md +49 -0
  199. package/skills/dingtalk-agent-eval/SKILL.md +116 -0
  200. package/skills/dingtalk-agent-eval/assets/eval-catalog.template.json +18 -0
  201. package/skills/dingtalk-agent-eval/evals/evals.json +61 -0
  202. package/skills/dingtalk-agent-eval/references/eval-topology.md +34 -0
  203. package/skills/dingtalk-agent-eval/references/evidence-contract.md +31 -0
  204. package/skills/dingtalk-agent-eval/references/scenario-taxonomy.md +25 -0
  205. package/skills/dingtalk-agent-eval/references/storage-modes.md +75 -0
  206. package/skills/dingtalk-basic-behavior/SKILL.md +63 -3
  207. package/skills/dingtalk-basic-behavior/assets/memory-candidate-proposal.json +10 -0
  208. package/skills/dingtalk-basic-behavior/assets/{task-checkpoint.md → task-checkpoint.json} +2 -21
  209. package/skills/dingtalk-basic-behavior/references/action-contract.md +2 -0
  210. package/skills/dingtalk-basic-behavior/references/memory-and-evolution.md +15 -1
  211. package/skills/dingtalk-basic-behavior/references/perception-and-gates.md +28 -0
  212. package/skills/dingtalk-basic-behavior/references/task-lifecycle.md +32 -7
@@ -0,0 +1,193 @@
1
+ import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, } from 'node:fs';
2
+ import { createHash } from 'node:crypto';
3
+ import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
4
+ import { bootstrap } from './bootstrap.js';
5
+ /**
6
+ * Canonicalize an evidence/tool path even when the final file does not exist yet.
7
+ * Resolving the nearest existing ancestor also normalizes macOS /var -> /private/var
8
+ * aliases, which prevents a valid system-temp sandbox path from being misclassified.
9
+ */
10
+ export function canonicalEvalPath(input) {
11
+ let cursor = resolve(input);
12
+ const missing = [];
13
+ while (!existsSync(cursor)) {
14
+ const parent = dirname(cursor);
15
+ if (parent === cursor)
16
+ break;
17
+ missing.unshift(basename(cursor));
18
+ cursor = parent;
19
+ }
20
+ const existing = existsSync(cursor) ? realpathSync(cursor) : cursor;
21
+ return resolve(existing, ...missing);
22
+ }
23
+ export function isWorkspacePathInside(workspace, input) {
24
+ const rel = relative(canonicalEvalPath(workspace), canonicalEvalPath(input));
25
+ return rel === '' ||
26
+ (rel !== '..' && !rel.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`));
27
+ }
28
+ export function relativeWorkspacePath(workspace, input) {
29
+ return relative(canonicalEvalPath(workspace), canonicalEvalPath(input))
30
+ .split('\\').join('/') || '.';
31
+ }
32
+ export function evaluateWorkspaceEvidence(workspace, expectations = []) {
33
+ const root = realpathSync(resolve(workspace));
34
+ return expectations.map((expectation) => {
35
+ try {
36
+ if (expectation.type === 'agentDefinition') {
37
+ const definition = bootstrap(root).definition;
38
+ const skills = definition.skills.map((item) => item.name);
39
+ const missing = expectation.requiredSkills.filter((name) => !skills.includes(name));
40
+ const passed = definition.status === expectation.status && missing.length === 0;
41
+ return {
42
+ id: expectation.id,
43
+ surface: expectation.surface,
44
+ type: expectation.type,
45
+ passed,
46
+ detail: `status=${definition.status}; skills=${skills.join(',')}; missing=${missing.join(',') || '-'}`,
47
+ hash: definition.hash,
48
+ };
49
+ }
50
+ const path = safeEvidencePath(root, expectation.path);
51
+ const rel = relative(root, path).split('\\').join('/');
52
+ if (expectation.type === 'pathAbsent') {
53
+ return {
54
+ id: expectation.id, surface: expectation.surface, type: expectation.type,
55
+ passed: !existsSync(path), path: rel,
56
+ detail: existsSync(path) ? `unexpected path exists: ${rel}` : `absent: ${rel}`,
57
+ };
58
+ }
59
+ if (!existsSync(path)) {
60
+ return {
61
+ id: expectation.id, surface: expectation.surface, type: expectation.type,
62
+ passed: false, path: rel, detail: `missing: ${rel}`,
63
+ };
64
+ }
65
+ // Existing symlinks are resolved after the lexical check so they cannot escape the sandbox.
66
+ safeEvidencePath(root, expectation.path, true);
67
+ const stat = lstatSync(path);
68
+ if (stat.isSymbolicLink())
69
+ throw new Error(`不接受符号链接证据: ${rel}`);
70
+ if (expectation.type === 'pathExists') {
71
+ const kindMatched = expectation.kind === undefined ||
72
+ (expectation.kind === 'file' ? stat.isFile() : stat.isDirectory());
73
+ const bytes = stat.isFile() ? stat.size : 0;
74
+ const sizeMatched = expectation.minBytes === undefined || bytes >= expectation.minBytes;
75
+ return {
76
+ id: expectation.id, surface: expectation.surface, type: expectation.type,
77
+ passed: kindMatched && sizeMatched, path: rel,
78
+ detail: `kind=${stat.isFile() ? 'file' : stat.isDirectory() ? 'directory' : 'other'}; bytes=${bytes}`,
79
+ hash: stat.isFile() ? sha256(readFileSync(path)) : undefined,
80
+ };
81
+ }
82
+ if (!stat.isFile())
83
+ throw new Error(`文本/JSON 证据必须是文件: ${rel}`);
84
+ const body = readFileSync(path, 'utf8');
85
+ if (expectation.type === 'textIncludesAll' || expectation.type === 'textExcludesAll') {
86
+ const matches = expectation.values.filter((value) => body.includes(value));
87
+ const passed = expectation.type === 'textIncludesAll'
88
+ ? matches.length === expectation.values.length
89
+ : matches.length === 0;
90
+ return {
91
+ id: expectation.id, surface: expectation.surface, type: expectation.type,
92
+ passed, path: rel, hash: sha256(body),
93
+ detail: `matched=${JSON.stringify(matches)}; expected=${JSON.stringify(expectation.values)}`,
94
+ };
95
+ }
96
+ if (expectation.type !== 'jsonEquals')
97
+ throw new Error(`未知证据断言: ${expectation.type}`);
98
+ const parsed = JSON.parse(body);
99
+ const actual = jsonPointer(parsed, expectation.pointer);
100
+ const passed = stable(actual) === stable(expectation.value);
101
+ return {
102
+ id: expectation.id, surface: expectation.surface, type: expectation.type,
103
+ passed, path: rel, hash: sha256(body),
104
+ detail: `pointer=${expectation.pointer}; actual=${stable(actual)}; expected=${stable(expectation.value)}`,
105
+ };
106
+ }
107
+ catch (error) {
108
+ return {
109
+ id: expectation.id,
110
+ surface: expectation.surface,
111
+ type: expectation.type,
112
+ passed: false,
113
+ detail: error.message,
114
+ ...('path' in expectation ? { path: expectation.path } : {}),
115
+ };
116
+ }
117
+ });
118
+ }
119
+ export function snapshotWorkspaceEvidence(workspace, output, expectations = []) {
120
+ const root = realpathSync(resolve(workspace));
121
+ const snapshots = [];
122
+ const seen = new Set();
123
+ for (const expectation of expectations) {
124
+ if (!('path' in expectation) || expectation.type === 'pathAbsent')
125
+ continue;
126
+ const source = safeEvidencePath(root, expectation.path, true);
127
+ if (!existsSync(source))
128
+ continue;
129
+ const stat = lstatSync(source);
130
+ if (!stat.isFile() || stat.isSymbolicLink())
131
+ continue;
132
+ const rel = relative(root, source).split('\\').join('/');
133
+ const key = `${expectation.surface}:${rel}`;
134
+ if (seen.has(key))
135
+ continue;
136
+ seen.add(key);
137
+ const destination = join(output, expectation.surface, rel);
138
+ mkdirSync(dirname(destination), { recursive: true });
139
+ copyFileSync(source, destination);
140
+ const body = readFileSync(source);
141
+ snapshots.push({
142
+ surface: expectation.surface,
143
+ path: `${expectation.surface}/${rel}`,
144
+ hash: sha256(body),
145
+ bytes: body.byteLength,
146
+ });
147
+ }
148
+ return snapshots;
149
+ }
150
+ function safeEvidencePath(root, input, resolveExisting = false) {
151
+ if (!input || isAbsolute(input) || input.split(/[\\/]/).includes('..')) {
152
+ throw new Error(`证据路径必须是 Workspace 内相对路径: ${input}`);
153
+ }
154
+ const candidate = resolve(root, input);
155
+ const lexical = relative(root, candidate);
156
+ if (lexical === '..' || lexical.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`)) {
157
+ throw new Error(`证据路径越界: ${input}`);
158
+ }
159
+ if (resolveExisting && existsSync(candidate)) {
160
+ const actual = realpathSync(candidate);
161
+ const rel = relative(root, actual);
162
+ if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`)) {
163
+ throw new Error(`证据路径通过链接越界: ${input}`);
164
+ }
165
+ }
166
+ return candidate;
167
+ }
168
+ function jsonPointer(value, pointer) {
169
+ if (pointer === '')
170
+ return value;
171
+ if (!pointer.startsWith('/'))
172
+ throw new Error(`JSON pointer 必须以 / 开头: ${pointer}`);
173
+ return pointer.slice(1).split('/').reduce((current, token) => {
174
+ const key = token.replace(/~1/g, '/').replace(/~0/g, '~');
175
+ if (current === null || current === undefined || typeof current !== 'object' || !(key in current)) {
176
+ throw new Error(`JSON pointer 不存在: ${pointer}`);
177
+ }
178
+ return current[key];
179
+ }, value);
180
+ }
181
+ function stable(value) {
182
+ if (Array.isArray(value))
183
+ return `[${value.map(stable).join(',')}]`;
184
+ if (value && typeof value === 'object') {
185
+ return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b))
186
+ .map(([key, item]) => `${JSON.stringify(key)}:${stable(item)}`).join(',')}}`;
187
+ }
188
+ return JSON.stringify(value) ?? 'undefined';
189
+ }
190
+ function sha256(value) {
191
+ return createHash('sha256').update(value).digest('hex');
192
+ }
193
+ //# sourceMappingURL=eval-evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval-evidence.js","sourceRoot":"","sources":["../../src/eval-evidence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, realpathSync,\n} from 'node:fs'\nimport { createHash } from 'node:crypto'\nimport { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { bootstrap } from './bootstrap.js'\n\nexport type EvalEvidenceSurface = 'filesystem' | 'workspace' | 'artifact'\n\ntype PathExpectation = {\n id: string\n surface: EvalEvidenceSurface\n type: 'pathExists'\n path: string\n kind?: 'file' | 'directory'\n minBytes?: number\n}\n\ntype AbsentExpectation = {\n id: string\n surface: EvalEvidenceSurface\n type: 'pathAbsent'\n path: string\n}\n\ntype TextExpectation = {\n id: string\n surface: EvalEvidenceSurface\n type: 'textIncludesAll' | 'textExcludesAll'\n path: string\n values: string[]\n}\n\ntype JsonExpectation = {\n id: string\n surface: EvalEvidenceSurface\n type: 'jsonEquals'\n path: string\n pointer: string\n value: unknown\n}\n\ntype DefinitionExpectation = {\n id: string\n surface: 'workspace'\n type: 'agentDefinition'\n status: 'ready' | 'partial'\n requiredSkills: string[]\n}\n\nexport type EvalEvidenceExpectation = PathExpectation | AbsentExpectation |\n TextExpectation | JsonExpectation | DefinitionExpectation\n\nexport interface EvalEvidenceResult {\n id: string\n surface: EvalEvidenceSurface\n type: EvalEvidenceExpectation['type']\n passed: boolean\n detail: string\n path?: string\n hash?: string\n}\n\n/**\n * Canonicalize an evidence/tool path even when the final file does not exist yet.\n * Resolving the nearest existing ancestor also normalizes macOS /var -> /private/var\n * aliases, which prevents a valid system-temp sandbox path from being misclassified.\n */\nexport function canonicalEvalPath(input: string): string {\n let cursor = resolve(input)\n const missing: string[] = []\n while (!existsSync(cursor)) {\n const parent = dirname(cursor)\n if (parent === cursor) break\n missing.unshift(basename(cursor))\n cursor = parent\n }\n const existing = existsSync(cursor) ? realpathSync(cursor) : cursor\n return resolve(existing, ...missing)\n}\n\nexport function isWorkspacePathInside(workspace: string, input: string): boolean {\n const rel = relative(canonicalEvalPath(workspace), canonicalEvalPath(input))\n return rel === '' ||\n (rel !== '..' && !rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`))\n}\n\nexport function relativeWorkspacePath(workspace: string, input: string): string {\n return relative(canonicalEvalPath(workspace), canonicalEvalPath(input))\n .split('\\\\').join('/') || '.'\n}\n\nexport function evaluateWorkspaceEvidence(\n workspace: string,\n expectations: EvalEvidenceExpectation[] = [],\n): EvalEvidenceResult[] {\n const root = realpathSync(resolve(workspace))\n return expectations.map((expectation) => {\n try {\n if (expectation.type === 'agentDefinition') {\n const definition = bootstrap(root).definition\n const skills = definition.skills.map((item) => item.name)\n const missing = expectation.requiredSkills.filter((name) => !skills.includes(name))\n const passed = definition.status === expectation.status && missing.length === 0\n return {\n id: expectation.id,\n surface: expectation.surface,\n type: expectation.type,\n passed,\n detail: `status=${definition.status}; skills=${skills.join(',')}; missing=${missing.join(',') || '-'}`,\n hash: definition.hash,\n }\n }\n\n const path = safeEvidencePath(root, expectation.path)\n const rel = relative(root, path).split('\\\\').join('/')\n if (expectation.type === 'pathAbsent') {\n return {\n id: expectation.id, surface: expectation.surface, type: expectation.type,\n passed: !existsSync(path), path: rel,\n detail: existsSync(path) ? `unexpected path exists: ${rel}` : `absent: ${rel}`,\n }\n }\n if (!existsSync(path)) {\n return {\n id: expectation.id, surface: expectation.surface, type: expectation.type,\n passed: false, path: rel, detail: `missing: ${rel}`,\n }\n }\n\n // Existing symlinks are resolved after the lexical check so they cannot escape the sandbox.\n safeEvidencePath(root, expectation.path, true)\n const stat = lstatSync(path)\n if (stat.isSymbolicLink()) throw new Error(`不接受符号链接证据: ${rel}`)\n if (expectation.type === 'pathExists') {\n const kindMatched = expectation.kind === undefined ||\n (expectation.kind === 'file' ? stat.isFile() : stat.isDirectory())\n const bytes = stat.isFile() ? stat.size : 0\n const sizeMatched = expectation.minBytes === undefined || bytes >= expectation.minBytes\n return {\n id: expectation.id, surface: expectation.surface, type: expectation.type,\n passed: kindMatched && sizeMatched, path: rel,\n detail: `kind=${stat.isFile() ? 'file' : stat.isDirectory() ? 'directory' : 'other'}; bytes=${bytes}`,\n hash: stat.isFile() ? sha256(readFileSync(path)) : undefined,\n }\n }\n if (!stat.isFile()) throw new Error(`文本/JSON 证据必须是文件: ${rel}`)\n const body = readFileSync(path, 'utf8')\n if (expectation.type === 'textIncludesAll' || expectation.type === 'textExcludesAll') {\n const matches = expectation.values.filter((value) => body.includes(value))\n const passed = expectation.type === 'textIncludesAll'\n ? matches.length === expectation.values.length\n : matches.length === 0\n return {\n id: expectation.id, surface: expectation.surface, type: expectation.type,\n passed, path: rel, hash: sha256(body),\n detail: `matched=${JSON.stringify(matches)}; expected=${JSON.stringify(expectation.values)}`,\n }\n }\n if (expectation.type !== 'jsonEquals') throw new Error(`未知证据断言: ${expectation.type}`)\n const parsed = JSON.parse(body) as unknown\n const actual = jsonPointer(parsed, expectation.pointer)\n const passed = stable(actual) === stable(expectation.value)\n return {\n id: expectation.id, surface: expectation.surface, type: expectation.type,\n passed, path: rel, hash: sha256(body),\n detail: `pointer=${expectation.pointer}; actual=${stable(actual)}; expected=${stable(expectation.value)}`,\n }\n } catch (error) {\n return {\n id: expectation.id,\n surface: expectation.surface,\n type: expectation.type,\n passed: false,\n detail: (error as Error).message,\n ...('path' in expectation ? { path: expectation.path } : {}),\n }\n }\n })\n}\n\nexport function snapshotWorkspaceEvidence(\n workspace: string,\n output: string,\n expectations: EvalEvidenceExpectation[] = [],\n): Array<{ surface: EvalEvidenceSurface; path: string; hash: string; bytes: number }> {\n const root = realpathSync(resolve(workspace))\n const snapshots: Array<{\n surface: EvalEvidenceSurface\n path: string\n hash: string\n bytes: number\n }> = []\n const seen = new Set<string>()\n for (const expectation of expectations) {\n if (!('path' in expectation) || expectation.type === 'pathAbsent') continue\n const source = safeEvidencePath(root, expectation.path, true)\n if (!existsSync(source)) continue\n const stat = lstatSync(source)\n if (!stat.isFile() || stat.isSymbolicLink()) continue\n const rel = relative(root, source).split('\\\\').join('/')\n const key = `${expectation.surface}:${rel}`\n if (seen.has(key)) continue\n seen.add(key)\n const destination = join(output, expectation.surface, rel)\n mkdirSync(dirname(destination), { recursive: true })\n copyFileSync(source, destination)\n const body = readFileSync(source)\n snapshots.push({\n surface: expectation.surface,\n path: `${expectation.surface}/${rel}`,\n hash: sha256(body),\n bytes: body.byteLength,\n })\n }\n return snapshots\n}\n\nfunction safeEvidencePath(root: string, input: string, resolveExisting = false): string {\n if (!input || isAbsolute(input) || input.split(/[\\\\/]/).includes('..')) {\n throw new Error(`证据路径必须是 Workspace 内相对路径: ${input}`)\n }\n const candidate = resolve(root, input)\n const lexical = relative(root, candidate)\n if (lexical === '..' || lexical.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`)) {\n throw new Error(`证据路径越界: ${input}`)\n }\n if (resolveExisting && existsSync(candidate)) {\n const actual = realpathSync(candidate)\n const rel = relative(root, actual)\n if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`)) {\n throw new Error(`证据路径通过链接越界: ${input}`)\n }\n }\n return candidate\n}\n\nfunction jsonPointer(value: unknown, pointer: string): unknown {\n if (pointer === '') return value\n if (!pointer.startsWith('/')) throw new Error(`JSON pointer 必须以 / 开头: ${pointer}`)\n return pointer.slice(1).split('/').reduce((current: any, token) => {\n const key = token.replace(/~1/g, '/').replace(/~0/g, '~')\n if (current === null || current === undefined || typeof current !== 'object' || !(key in current)) {\n throw new Error(`JSON pointer 不存在: ${pointer}`)\n }\n return current[key]\n }, value as any)\n}\n\nfunction stable(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stable).join(',')}]`\n if (value && typeof value === 'object') {\n return `{${Object.entries(value as Record<string, unknown>).sort(([a], [b]) => a.localeCompare(b))\n .map(([key, item]) => `${JSON.stringify(key)}:${stable(item)}`).join(',')}}`\n }\n return JSON.stringify(value) ?? 'undefined'\n}\n\nfunction sha256(value: string | Buffer): string {\n return createHash('sha256').update(value).digest('hex')\n}\n"]}
@@ -0,0 +1,36 @@
1
+ export function directInvocation(sessionKey = '') {
2
+ return {
3
+ $schema: 'dingtalk-agent/invocation@1',
4
+ mode: 'direct',
5
+ authority: 'default',
6
+ eventId: '',
7
+ sessionKey,
8
+ occurredAt: null,
9
+ actor: null,
10
+ target: null,
11
+ conversation: null,
12
+ };
13
+ }
14
+ export function eventInvocation(event, resume = { mode: 'start' }, sessionKey = '', continued = false) {
15
+ return {
16
+ $schema: 'dingtalk-agent/invocation@1',
17
+ mode: resume.mode === 'start' && !continued ? eventMode(event.kind) : 'continuation',
18
+ authority: 'event',
19
+ eventId: event.id,
20
+ sessionKey,
21
+ occurredAt: event.occurredAt,
22
+ actor: event.actor,
23
+ target: event.replyTarget,
24
+ conversation: event.conversation,
25
+ };
26
+ }
27
+ function eventMode(kind) {
28
+ if (kind === 'im.message.mentioned')
29
+ return 'mention';
30
+ if (kind === 'im.message.dm')
31
+ return 'dm';
32
+ if (kind === 'agent.heartbeat')
33
+ return 'heartbeat';
34
+ return 'ambient';
35
+ }
36
+ //# sourceMappingURL=invocation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invocation.js","sourceRoot":"","sources":["../../src/invocation.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,gBAAgB,CAAC,UAAU,GAAG,EAAE;IAC9C,OAAO;QACL,OAAO,EAAE,6BAA6B;QACtC,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,SAAS;QACpB,OAAO,EAAE,EAAE;QACX,UAAU;QACV,UAAU,EAAE,IAAI;QAChB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,YAAY,EAAE,IAAI;KACnB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,KAAsB,EACtB,SAAwB,EAAE,IAAI,EAAE,OAAO,EAAE,EACzC,UAAU,GAAG,EAAE,EACf,SAAS,GAAG,KAAK;IAEjB,OAAO;QACL,OAAO,EAAE,6BAA6B;QACtC,IAAI,EAAE,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc;QACpF,SAAS,EAAE,OAAO;QAClB,OAAO,EAAE,KAAK,CAAC,EAAE;QACjB,UAAU;QACV,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,WAAW;QACzB,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,IAAI,KAAK,sBAAsB;QAAE,OAAO,SAAS,CAAA;IACrD,IAAI,IAAI,KAAK,eAAe;QAAE,OAAO,IAAI,CAAA;IACzC,IAAI,IAAI,KAAK,iBAAiB;QAAE,OAAO,WAAW,CAAA;IAClD,OAAO,SAAS,CAAA;AAClB,CAAC","sourcesContent":["import type {\n InvocationContext, InvocationMode, NormalizedEvent, ResumeContext,\n} from './types.js'\n\nexport function directInvocation(sessionKey = ''): InvocationContext {\n return {\n $schema: 'dingtalk-agent/invocation@1',\n mode: 'direct',\n authority: 'default',\n eventId: '',\n sessionKey,\n occurredAt: null,\n actor: null,\n target: null,\n conversation: null,\n }\n}\n\nexport function eventInvocation(\n event: NormalizedEvent,\n resume: ResumeContext = { mode: 'start' },\n sessionKey = '',\n continued = false,\n): InvocationContext {\n return {\n $schema: 'dingtalk-agent/invocation@1',\n mode: resume.mode === 'start' && !continued ? eventMode(event.kind) : 'continuation',\n authority: 'event',\n eventId: event.id,\n sessionKey,\n occurredAt: event.occurredAt,\n actor: event.actor,\n target: event.replyTarget,\n conversation: event.conversation,\n }\n}\n\nfunction eventMode(kind: string): InvocationMode {\n if (kind === 'im.message.mentioned') return 'mention'\n if (kind === 'im.message.dm') return 'dm'\n if (kind === 'agent.heartbeat') return 'heartbeat'\n return 'ambient'\n}\n"]}