@finalai/agent-definition 0.1.0

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.

Potentially problematic release.


This version of @finalai/agent-definition might be problematic. Click here for more details.

Files changed (206) hide show
  1. package/README.md +16 -0
  2. package/THIRD_PARTY_NOTICES.md +303 -0
  3. package/dist/compiler-assets/chunk-2CZRHOLL.ts +10 -0
  4. package/dist/compiler-assets/chunk-32O3ODZE.ts +39 -0
  5. package/dist/compiler-assets/chunk-5BK6FVRE.ts +75 -0
  6. package/dist/compiler-assets/chunk-6WR3PGNF.ts +0 -0
  7. package/dist/compiler-assets/chunk-7QP2CKPI.ts +30 -0
  8. package/dist/compiler-assets/chunk-7VSSVZM4.ts +55 -0
  9. package/dist/compiler-assets/chunk-7WGYG73V.ts +42 -0
  10. package/dist/compiler-assets/chunk-BLB6JGLO.ts +481 -0
  11. package/dist/compiler-assets/chunk-CWWRTRWW.ts +76 -0
  12. package/dist/compiler-assets/chunk-EVQIK62B.ts +188 -0
  13. package/dist/compiler-assets/chunk-GNR7XBPN.ts +3364 -0
  14. package/dist/compiler-assets/chunk-GTUZOATD.ts +10 -0
  15. package/dist/compiler-assets/chunk-HFS4KLEL.ts +10 -0
  16. package/dist/compiler-assets/chunk-HGW4YHAY.ts +6865 -0
  17. package/dist/compiler-assets/chunk-HNPUTP35.ts +172 -0
  18. package/dist/compiler-assets/chunk-JIPNTA56.ts +59 -0
  19. package/dist/compiler-assets/chunk-JNJE72EH.ts +10 -0
  20. package/dist/compiler-assets/chunk-JPY4L2UJ.ts +349 -0
  21. package/dist/compiler-assets/chunk-JTGTLYDT.ts +0 -0
  22. package/dist/compiler-assets/chunk-LUSAAV4L.ts +33 -0
  23. package/dist/compiler-assets/chunk-MZMSKIKU.ts +472 -0
  24. package/dist/compiler-assets/chunk-NMYHO2QN.ts +25 -0
  25. package/dist/compiler-assets/chunk-NYTOYKKF.ts +28 -0
  26. package/dist/compiler-assets/chunk-OWC6SFFF.ts +295 -0
  27. package/dist/compiler-assets/chunk-QMKWAFVZ.ts +59 -0
  28. package/dist/compiler-assets/chunk-QMWTDPNT.ts +79 -0
  29. package/dist/compiler-assets/chunk-RWUIMTBI.ts +13 -0
  30. package/dist/compiler-assets/chunk-SKTNMUO7.ts +64 -0
  31. package/dist/compiler-assets/chunk-T6WG4L4M.ts +19 -0
  32. package/dist/compiler-assets/chunk-TATN3PYK.ts +81 -0
  33. package/dist/compiler-assets/chunk-VHXHUU7L.ts +16 -0
  34. package/dist/compiler-assets/chunk-WMXMVFHM.ts +121 -0
  35. package/dist/compiler-assets/chunk-XHKPWT3G.ts +55 -0
  36. package/dist/compiler-assets/chunk-ZDLVA6XF.ts +476 -0
  37. package/dist/compiler-assets/src/authoring/agent.ts +10 -0
  38. package/dist/compiler-assets/src/authoring/approval.ts +19 -0
  39. package/dist/compiler-assets/src/authoring/brand.ts +23 -0
  40. package/dist/compiler-assets/src/authoring/channels.ts +26 -0
  41. package/dist/compiler-assets/src/authoring/connections.ts +10 -0
  42. package/dist/compiler-assets/src/authoring/context.ts +7 -0
  43. package/dist/compiler-assets/src/authoring/credentials.ts +21 -0
  44. package/dist/compiler-assets/src/authoring/dynamic.ts +10 -0
  45. package/dist/compiler-assets/src/authoring/harness.ts +17 -0
  46. package/dist/compiler-assets/src/authoring/hooks.ts +28 -0
  47. package/dist/compiler-assets/src/authoring/index.ts +110 -0
  48. package/dist/compiler-assets/src/authoring/instructions.ts +14 -0
  49. package/dist/compiler-assets/src/authoring/sandbox.ts +25 -0
  50. package/dist/compiler-assets/src/authoring/schedules.ts +10 -0
  51. package/dist/compiler-assets/src/authoring/skills.ts +10 -0
  52. package/dist/compiler-assets/src/authoring/tools.ts +23 -0
  53. package/dist/compiler-assets/src/compatibility.ts +14810 -0
  54. package/dist/compiler-assets/src/compiler/evaluate-child.mjs +77 -0
  55. package/dist/compiler-assets/src/index.ts +195 -0
  56. package/dist/compiler-assets/src/manifest.ts +72 -0
  57. package/dist/compiler-assets/src/resolve.ts +19 -0
  58. package/dist/compiler-assets/src/runtime/bundle.ts +72 -0
  59. package/dist/compiler-assets/src/runtime/describe.ts +31 -0
  60. package/dist/compiler-assets/src/runtime/described.ts +142 -0
  61. package/dist/compiler-assets/src/runtime/isolate.ts +28 -0
  62. package/dist/compiler-assets/src/runtime/layout.ts +15 -0
  63. package/dist/compiler-assets/src/runtime/lower.ts +52 -0
  64. package/dist/compiler-assets/src/runtime/schema-validation.ts +21 -0
  65. package/dist/compiler-assets/src/runtime/values.ts +38 -0
  66. package/dist/modules/authoring/agent.d.mts +22 -0
  67. package/dist/modules/authoring/agent.mjs +6 -0
  68. package/dist/modules/authoring/agent.mjs.map +7 -0
  69. package/dist/modules/authoring/approval.d.mts +17 -0
  70. package/dist/modules/authoring/approval.mjs +42 -0
  71. package/dist/modules/authoring/approval.mjs.map +7 -0
  72. package/dist/modules/authoring/brand.d.mts +27 -0
  73. package/dist/modules/authoring/brand.mjs +51 -0
  74. package/dist/modules/authoring/brand.mjs.map +7 -0
  75. package/dist/modules/authoring/channels.d.mts +41 -0
  76. package/dist/modules/authoring/channels.mjs +65 -0
  77. package/dist/modules/authoring/channels.mjs.map +7 -0
  78. package/dist/modules/authoring/connections.d.mts +23 -0
  79. package/dist/modules/authoring/connections.mjs +6 -0
  80. package/dist/modules/authoring/connections.mjs.map +7 -0
  81. package/dist/modules/authoring/context.d.mts +83 -0
  82. package/dist/modules/authoring/context.mjs +12 -0
  83. package/dist/modules/authoring/context.mjs.map +7 -0
  84. package/dist/modules/authoring/credentials.d.mts +10 -0
  85. package/dist/modules/authoring/credentials.mjs +31 -0
  86. package/dist/modules/authoring/credentials.mjs.map +7 -0
  87. package/dist/modules/authoring/dynamic.d.mts +30 -0
  88. package/dist/modules/authoring/dynamic.mjs +15 -0
  89. package/dist/modules/authoring/dynamic.mjs.map +7 -0
  90. package/dist/modules/authoring/harness.d.mts +85 -0
  91. package/dist/modules/authoring/harness.mjs +55 -0
  92. package/dist/modules/authoring/harness.mjs.map +7 -0
  93. package/dist/modules/authoring/hooks.d.mts +120 -0
  94. package/dist/modules/authoring/hooks.mjs +72 -0
  95. package/dist/modules/authoring/hooks.mjs.map +7 -0
  96. package/dist/modules/authoring/index.d.mts +27 -0
  97. package/dist/modules/authoring/index.mjs +63 -0
  98. package/dist/modules/authoring/index.mjs.map +7 -0
  99. package/dist/modules/authoring/instructions.d.mts +13 -0
  100. package/dist/modules/authoring/instructions.mjs +15 -0
  101. package/dist/modules/authoring/instructions.mjs.map +7 -0
  102. package/dist/modules/authoring/sandbox.d.mts +21 -0
  103. package/dist/modules/authoring/sandbox.mjs +13 -0
  104. package/dist/modules/authoring/sandbox.mjs.map +7 -0
  105. package/dist/modules/authoring/schedules.d.mts +8 -0
  106. package/dist/modules/authoring/schedules.mjs +6 -0
  107. package/dist/modules/authoring/schedules.mjs.map +7 -0
  108. package/dist/modules/authoring/skills.d.mts +8 -0
  109. package/dist/modules/authoring/skills.mjs +6 -0
  110. package/dist/modules/authoring/skills.mjs.map +7 -0
  111. package/dist/modules/authoring/tools.d.mts +80 -0
  112. package/dist/modules/authoring/tools.mjs +70 -0
  113. package/dist/modules/authoring/tools.mjs.map +7 -0
  114. package/dist/modules/compatibility.d.mts +36 -0
  115. package/dist/modules/compatibility.mjs +536 -0
  116. package/dist/modules/compatibility.mjs.map +7 -0
  117. package/dist/modules/compiler/assemble.d.mts +30 -0
  118. package/dist/modules/compiler/assemble.mjs +923 -0
  119. package/dist/modules/compiler/assemble.mjs.map +7 -0
  120. package/dist/modules/compiler/bundle.d.mts +22 -0
  121. package/dist/modules/compiler/bundle.mjs +385 -0
  122. package/dist/modules/compiler/bundle.mjs.map +7 -0
  123. package/dist/modules/compiler/diagnostics.d.mts +40 -0
  124. package/dist/modules/compiler/diagnostics.mjs +38 -0
  125. package/dist/modules/compiler/diagnostics.mjs.map +7 -0
  126. package/dist/modules/compiler/discovery.d.mts +36 -0
  127. package/dist/modules/compiler/discovery.mjs +158 -0
  128. package/dist/modules/compiler/discovery.mjs.map +7 -0
  129. package/dist/modules/compiler/evaluate.d.mts +13 -0
  130. package/dist/modules/compiler/evaluate.mjs +194 -0
  131. package/dist/modules/compiler/evaluate.mjs.map +7 -0
  132. package/dist/modules/compiler/files.d.mts +19 -0
  133. package/dist/modules/compiler/files.mjs +90 -0
  134. package/dist/modules/compiler/files.mjs.map +7 -0
  135. package/dist/modules/compiler/frontmatter.d.mts +9 -0
  136. package/dist/modules/compiler/frontmatter.mjs +34 -0
  137. package/dist/modules/compiler/frontmatter.mjs.map +7 -0
  138. package/dist/modules/compiler/index.d.mts +49 -0
  139. package/dist/modules/compiler/index.mjs +244 -0
  140. package/dist/modules/compiler/index.mjs.map +7 -0
  141. package/dist/modules/compiler/load.d.mts +8 -0
  142. package/dist/modules/compiler/load.mjs +45 -0
  143. package/dist/modules/compiler/load.mjs.map +7 -0
  144. package/dist/modules/compiler/local-isolate.d.mts +20 -0
  145. package/dist/modules/compiler/local-isolate.mjs +93 -0
  146. package/dist/modules/compiler/local-isolate.mjs.map +7 -0
  147. package/dist/modules/compiler/packages.d.mts +66 -0
  148. package/dist/modules/compiler/packages.mjs +307 -0
  149. package/dist/modules/compiler/packages.mjs.map +7 -0
  150. package/dist/modules/index.d.mts +7 -0
  151. package/dist/modules/index.mjs +25 -0
  152. package/dist/modules/index.mjs.map +7 -0
  153. package/dist/modules/manifest.d.mts +2 -0
  154. package/dist/modules/manifest.mjs +67 -0
  155. package/dist/modules/manifest.mjs.map +7 -0
  156. package/dist/modules/resolve.d.mts +24 -0
  157. package/dist/modules/resolve.mjs +176 -0
  158. package/dist/modules/resolve.mjs.map +7 -0
  159. package/dist/modules/runtime/bundle.d.mts +12 -0
  160. package/dist/modules/runtime/bundle.mjs +48 -0
  161. package/dist/modules/runtime/bundle.mjs.map +7 -0
  162. package/dist/modules/runtime/describe.d.mts +19 -0
  163. package/dist/modules/runtime/describe.mjs +471 -0
  164. package/dist/modules/runtime/describe.mjs.map +7 -0
  165. package/dist/modules/runtime/described.d.mts +376 -0
  166. package/dist/modules/runtime/described.mjs +116 -0
  167. package/dist/modules/runtime/described.mjs.map +7 -0
  168. package/dist/modules/runtime/isolate.d.mts +70 -0
  169. package/dist/modules/runtime/isolate.mjs +454 -0
  170. package/dist/modules/runtime/isolate.mjs.map +7 -0
  171. package/dist/modules/runtime/layout.d.mts +21 -0
  172. package/dist/modules/runtime/layout.mjs +24 -0
  173. package/dist/modules/runtime/layout.mjs.map +7 -0
  174. package/dist/modules/runtime/lower.d.mts +73 -0
  175. package/dist/modules/runtime/lower.mjs +463 -0
  176. package/dist/modules/runtime/lower.mjs.map +7 -0
  177. package/dist/modules/runtime/schema-validation.d.mts +21 -0
  178. package/dist/modules/runtime/schema-validation.mjs +238 -0
  179. package/dist/modules/runtime/schema-validation.mjs.map +7 -0
  180. package/dist/modules/runtime/values.d.mts +20 -0
  181. package/dist/modules/runtime/values.mjs +48 -0
  182. package/dist/modules/runtime/values.mjs.map +7 -0
  183. package/fixtures/acme-fleet/agent/agent.ts +74 -0
  184. package/fixtures/acme-fleet/agent/instructions.md +1 -0
  185. package/fixtures/assistant/agent/agent.ts +16 -0
  186. package/fixtures/assistant/agent/instructions.md +1 -0
  187. package/fixtures/assistant/agent/tools/current_time.ts +9 -0
  188. package/fixtures/assistant-with-tools/agent/agent.ts +16 -0
  189. package/fixtures/assistant-with-tools/agent/instructions.md +1 -0
  190. package/fixtures/assistant-with-tools/agent/tools/current_time.ts +9 -0
  191. package/fixtures/final-connection/agent/agent.ts +15 -0
  192. package/fixtures/final-connection/agent/connections/final.ts +9 -0
  193. package/fixtures/release-scout/agent/agent.ts +22 -0
  194. package/fixtures/release-scout/agent/channels/github-signature.ts +27 -0
  195. package/fixtures/release-scout/agent/channels/github.ts +38 -0
  196. package/fixtures/release-scout/agent/connections/linear.ts +9 -0
  197. package/fixtures/release-scout/agent/hooks/audit.ts +24 -0
  198. package/fixtures/release-scout/agent/instructions/org-context.ts +26 -0
  199. package/fixtures/release-scout/agent/instructions.md +2 -0
  200. package/fixtures/release-scout/agent/sandbox.ts +20 -0
  201. package/fixtures/release-scout/agent/schedules/daily-digest.md +7 -0
  202. package/fixtures/release-scout/agent/skills/triage/SKILL.md +8 -0
  203. package/fixtures/release-scout/agent/skills/triage/checklist.md +3 -0
  204. package/fixtures/release-scout/agent/tools/lookup_release_notes.ts +24 -0
  205. package/fixtures/tsconfig.json +5 -0
  206. package/package.json +94 -0
@@ -0,0 +1,923 @@
1
+ import {
2
+ agentManifestSchema,
3
+ BaseCapability,
4
+ bundleRef,
5
+ CredentialNodeKind,
6
+ credentialPolicySchema,
7
+ DynamicEvent,
8
+ findDynamicSlots,
9
+ formatProviderRef,
10
+ httpMcpServerBindingSchema,
11
+ InstructionRole,
12
+ jsonObjectSchema,
13
+ MANIFEST_VERSION,
14
+ McpServerBindingKind,
15
+ packageRef,
16
+ ProviderRefKind,
17
+ providerRefSchema,
18
+ SandboxAccess,
19
+ SandboxAttach,
20
+ ScheduleTarget,
21
+ skillBundleSchema,
22
+ ToolApproval,
23
+ toolDescriptorSchema,
24
+ TurnPolicy
25
+ } from "@finalai/agent-provider";
26
+ import { Cron } from "croner";
27
+ import * as z from "zod";
28
+ import { HookEventKeyKind, normalizeHookKey } from "../authoring/hooks.mjs";
29
+ import { AUTHORED_SERVER_KEY, COMBINED_MCP_SERVERS_EXPORT, SlotKind } from "../runtime/layout.mjs";
30
+ import { IssueSeverity } from "../runtime/lower.mjs";
31
+ import {
32
+ diagnostic,
33
+ DiagnosticCode,
34
+ DiagnosticSeverity
35
+ } from "./diagnostics.mjs";
36
+ import { InstructionSourceKind, isModulePath } from "./discovery.mjs";
37
+ import { preparationFiles } from "./files.mjs";
38
+ import { firstParagraphLine, frontMatterString, parseFrontMatter } from "./frontmatter.mjs";
39
+ const SEVERITY = {
40
+ [IssueSeverity.Error]: DiagnosticSeverity.Error,
41
+ [IssueSeverity.Warning]: DiagnosticSeverity.Warning,
42
+ [IssueSeverity.Note]: DiagnosticSeverity.Note
43
+ };
44
+ const isObject = (value) => jsonObjectSchema.safeParse(value).success;
45
+ const DYNAMIC_EVENTS = new Set(Object.values(DynamicEvent));
46
+ const toDynamicEvents = (events) => Object.values(DynamicEvent).filter((event) => events.includes(event));
47
+ const capabilityOf = (name) => Object.values(BaseCapability).find((capability) => capability === name) ?? null;
48
+ const apiKeySecretSchema = z.looseObject({
49
+ kind: z.literal(CredentialNodeKind.ApiKey),
50
+ secret: z.string().min(1)
51
+ });
52
+ const secretRefSchema = z.looseObject({ secretKey: z.string().min(1) });
53
+ const configSecrets = (value) => {
54
+ if (Array.isArray(value)) return value.flatMap(configSecrets);
55
+ if (!isObject(value)) return [];
56
+ const node = apiKeySecretSchema.safeParse(value);
57
+ const ref = secretRefSchema.safeParse(value);
58
+ return [
59
+ ...node.success ? [node.data.secret] : [],
60
+ ...ref.success ? [ref.data.secretKey] : [],
61
+ ...Object.values(value).flatMap(configSecrets)
62
+ ];
63
+ };
64
+ const collectSecrets = (args) => {
65
+ const names = /* @__PURE__ */ new Set([...args.declared, ...args.reads]);
66
+ for (const name of configSecrets(args.config)) names.add(name);
67
+ if (Array.isArray(args.mcpServers)) {
68
+ for (const binding of args.mcpServers) {
69
+ if (binding.kind === McpServerBindingKind.Http && binding.auth != null && "secretKey" in binding.auth) {
70
+ names.add(binding.auth.secretKey);
71
+ }
72
+ }
73
+ }
74
+ return [...names].sort();
75
+ };
76
+ const SECRET_READ = /secrets\s*\.\s*get\(\s*(?:(['"`])([^'"`$\\]+)\1\s*\)|(?!\s*\)))/g;
77
+ const secretReferences = (files) => Object.entries(files).filter(([path]) => isModulePath(path) || /\.[jt]sx$/.test(path)).flatMap(
78
+ ([path, source]) => [...source.matchAll(SECRET_READ)].map((match) => ({ path, name: match[2] ?? null }))
79
+ );
80
+ const assemble = (input) => {
81
+ const diagnostics = [];
82
+ const report = (severity, code, message, path = null) => {
83
+ diagnostics.push(diagnostic({ severity, code, message, path }));
84
+ };
85
+ const modules = {};
86
+ const runtimeExport = (name, path) => {
87
+ modules[name] = path;
88
+ };
89
+ const described = input.described?.modules ?? [];
90
+ for (const module of described) {
91
+ for (const issue of module.issues)
92
+ report(SEVERITY[issue.severity], DiagnosticCode.Module, issue.message, module.path);
93
+ }
94
+ const ofSlot = (slot) => described.filter((module) => module.slot === slot);
95
+ const withDefault = (slot) => ofSlot(slot).filter((module) => module.hasDefault && module.value != null);
96
+ const dynamicSlotFor = (dynamic, resolver, path, slotName) => {
97
+ for (const event of dynamic.events) {
98
+ if (!DYNAMIC_EVENTS.has(event)) {
99
+ report(
100
+ DiagnosticSeverity.Error,
101
+ DiagnosticCode.Module,
102
+ `${slotName} resolves on ${event}; dynamic slots support session.started and turn.started (the harness owns steps)`,
103
+ path
104
+ );
105
+ }
106
+ }
107
+ const events = toDynamicEvents(dynamic.events);
108
+ if (events.length === 0) {
109
+ report(
110
+ DiagnosticSeverity.Error,
111
+ DiagnosticCode.Module,
112
+ `${slotName} defineDynamic has no session.started or turn.started handler`,
113
+ path
114
+ );
115
+ return null;
116
+ }
117
+ runtimeExport(resolver, path);
118
+ const slot = { $dynamic: { resolver, events } };
119
+ if (dynamic.description != null) slot.$dynamic.description = dynamic.description;
120
+ if (dynamic.preview != null) slot.$dynamic.preview = dynamic.preview;
121
+ if (dynamic.description == null && dynamic.preview == null) {
122
+ report(
123
+ DiagnosticSeverity.Note,
124
+ DiagnosticCode.Module,
125
+ `${slotName} is resolved per session; give defineDynamic a description (and a preview) so Build can show what it resolves to`,
126
+ path
127
+ );
128
+ }
129
+ return slot;
130
+ };
131
+ const agentModule = ofSlot(SlotKind.Agent)[0] ?? null;
132
+ let agent = null;
133
+ if (agentModule != null) {
134
+ if (!agentModule.hasDefault) {
135
+ report(
136
+ DiagnosticSeverity.Error,
137
+ DiagnosticCode.Module,
138
+ "agent.ts must export defineAgent({ ... }) as its default export",
139
+ agentModule.path
140
+ );
141
+ } else if (agentModule.value?.type === "agent") agent = agentModule.value;
142
+ }
143
+ const agentPath = agentModule?.path ?? "agent.ts";
144
+ for (const name of input.described?.synthesized ?? []) {
145
+ if (name !== COMBINED_MCP_SERVERS_EXPORT) runtimeExport(name, agentPath);
146
+ }
147
+ let harnessRef = null;
148
+ let config = {};
149
+ if (agent?.harness == null) {
150
+ if (agentModule == null || agent != null) {
151
+ report(
152
+ DiagnosticSeverity.Error,
153
+ DiagnosticCode.Harness,
154
+ "agent.ts must name a harness, e.g. defineAgent({ harness: serverlessPi({ model }) })",
155
+ agentPath
156
+ );
157
+ }
158
+ } else {
159
+ const parsed = providerRefSchema.safeParse(agent.harness.harness);
160
+ if (parsed.success) harnessRef = parsed.data;
161
+ else
162
+ report(
163
+ DiagnosticSeverity.Error,
164
+ DiagnosticCode.Harness,
165
+ "agent.ts harness has an invalid provider reference",
166
+ agentPath
167
+ );
168
+ config = agent.harness.config;
169
+ }
170
+ if (harnessRef?.kind === "bundle") runtimeExport(harnessRef.export, agentPath);
171
+ const credentialPolicies = Object.values(jsonObjectSchema.safeParse(config).data ?? {}).filter(
172
+ (value) => credentialPolicySchema.safeParse(value).success
173
+ );
174
+ if (harnessRef != null && credentialPolicies.length !== 1) {
175
+ report(
176
+ DiagnosticSeverity.Error,
177
+ DiagnosticCode.Harness,
178
+ "Declare exactly one credential policy in the harness config; billing policy belongs to this definition.",
179
+ agentPath
180
+ );
181
+ }
182
+ const configObject = isObject(config) ? config : null;
183
+ if (configObject == null && !findDynamicSlots(config).some((slot) => slot.path === "")) {
184
+ report(
185
+ DiagnosticSeverity.Error,
186
+ DiagnosticCode.Harness,
187
+ "harness config must be an object",
188
+ agentPath
189
+ );
190
+ }
191
+ const instructionFragments = [];
192
+ const instructionSources = [];
193
+ const instructionModules = new Map(
194
+ ofSlot(SlotKind.Instructions).map((module) => [module.path, module])
195
+ );
196
+ for (const source of input.discovery.instructions) {
197
+ if (source.kind === InstructionSourceKind.Markdown) {
198
+ const content = input.files[source.path] ?? "";
199
+ if (content.trim().length === 0) {
200
+ report(
201
+ DiagnosticSeverity.Warning,
202
+ DiagnosticCode.Instructions,
203
+ `${source.path} is empty and was skipped`,
204
+ source.path
205
+ );
206
+ continue;
207
+ }
208
+ instructionFragments.push({ role: InstructionRole.System, content, source: source.path });
209
+ instructionSources.push(source.path);
210
+ continue;
211
+ }
212
+ const module = instructionModules.get(source.path);
213
+ if (module == null || module.value == null) continue;
214
+ if (module.value.type === "instructions") {
215
+ instructionFragments.push({
216
+ role: module.value.role,
217
+ content: module.value.content,
218
+ source: source.path
219
+ });
220
+ instructionSources.push(source.path);
221
+ } else if (module.value.type === "dynamic") {
222
+ const slot = dynamicSlotFor(module.value, module.base, source.path, source.path);
223
+ if (slot != null) {
224
+ instructionFragments.push(slot);
225
+ instructionSources.push(source.path);
226
+ }
227
+ }
228
+ }
229
+ const skills = [];
230
+ const skillSources = [];
231
+ const skillKeys = /* @__PURE__ */ new Set();
232
+ const addSkill = (key, skill, path) => {
233
+ if (skillKeys.has(key)) {
234
+ report(
235
+ DiagnosticSeverity.Error,
236
+ DiagnosticCode.Skills,
237
+ `skill ${key} is defined more than once`,
238
+ path
239
+ );
240
+ return;
241
+ }
242
+ skillKeys.add(key);
243
+ skills.push(skill);
244
+ skillSources.push(path);
245
+ };
246
+ for (const directory of input.discovery.skillDirectories) {
247
+ const skillPath = `${directory.directory}/SKILL.md`;
248
+ const text = input.files[skillPath] ?? "";
249
+ const front = parseFrontMatter(text);
250
+ if (front.error != null)
251
+ report(DiagnosticSeverity.Warning, DiagnosticCode.Skills, front.error, skillPath);
252
+ const description = frontMatterString(front.data, "description") ?? firstParagraphLine(front.body);
253
+ const files = [
254
+ { path: "SKILL.md", content: text },
255
+ ...directory.files.filter((file) => file !== skillPath).map((file) => ({
256
+ path: file.slice(directory.directory.length + 1),
257
+ content: input.files[file] ?? ""
258
+ }))
259
+ ];
260
+ const skill = { key: directory.key, files };
261
+ if (description != null) skill.description = description;
262
+ addSkill(directory.key, skill, skillPath);
263
+ }
264
+ for (const flat of input.discovery.skillMarkdown) {
265
+ const text = input.files[flat.path] ?? "";
266
+ const front = parseFrontMatter(text);
267
+ const description = frontMatterString(front.data, "description") ?? firstParagraphLine(front.body) ?? `Instructions for the ${flat.key} skill.`;
268
+ const content = text.startsWith("---\n") ? text : `---
269
+ name: ${JSON.stringify(flat.key)}
270
+ description: ${JSON.stringify(description)}
271
+ ---
272
+
273
+ ${text}`;
274
+ addSkill(
275
+ flat.key,
276
+ { key: flat.key, description, files: [{ path: "SKILL.md", content }] },
277
+ flat.path
278
+ );
279
+ }
280
+ for (const module of withDefault(SlotKind.Skill)) {
281
+ if (module.value?.type === "skill") {
282
+ const parsed = skillBundleSchema.safeParse(module.value.skill);
283
+ if (parsed.success) addSkill(module.key, parsed.data, module.path);
284
+ } else if (module.value?.type === "dynamic") {
285
+ const slot = dynamicSlotFor(module.value, module.base, module.path, module.path);
286
+ if (slot != null) addSkill(module.key, slot, module.path);
287
+ }
288
+ }
289
+ const directoryFields = { instructions: instructionSources, skills: skillSources };
290
+ if (configObject != null) {
291
+ if (instructionFragments.length > 0) {
292
+ if (configObject["instructions"] != null) {
293
+ report(
294
+ DiagnosticSeverity.Error,
295
+ DiagnosticCode.Conflict,
296
+ "harness config sets instructions and the directory has instruction files; keep one source",
297
+ agentPath
298
+ );
299
+ } else configObject["instructions"] = instructionFragments;
300
+ }
301
+ if (skills.length > 0) {
302
+ if (configObject["skills"] != null) {
303
+ report(
304
+ DiagnosticSeverity.Error,
305
+ DiagnosticCode.Conflict,
306
+ "harness config sets skills and the directory has skills/; keep one source",
307
+ agentPath
308
+ );
309
+ } else configObject["skills"] = skills;
310
+ }
311
+ } else if (instructionFragments.length > 0 || skills.length > 0) {
312
+ report(
313
+ DiagnosticSeverity.Error,
314
+ DiagnosticCode.Conflict,
315
+ "harness config is dynamic, so directory instructions and skills cannot be added to it",
316
+ agentPath
317
+ );
318
+ }
319
+ const toolPolicy = {};
320
+ const toolDescriptors = [];
321
+ const toolApprovals = {};
322
+ let anyDynamicServer = false;
323
+ let anyTurnStartedServer = false;
324
+ for (const module of ofSlot(SlotKind.Tool)) {
325
+ if (!module.hasDefault || module.value == null) continue;
326
+ if (module.value.type === "dynamic") {
327
+ anyDynamicServer = true;
328
+ anyTurnStartedServer ||= module.value.events.includes(DynamicEvent.TurnStarted);
329
+ runtimeExport(module.base, module.path);
330
+ continue;
331
+ }
332
+ if (module.value.type !== "tool") continue;
333
+ const parsed = toolDescriptorSchema.safeParse(module.value.descriptor);
334
+ if (!parsed.success) {
335
+ report(
336
+ DiagnosticSeverity.Error,
337
+ DiagnosticCode.Module,
338
+ `tool ${module.key} has an invalid descriptor`,
339
+ module.path
340
+ );
341
+ continue;
342
+ }
343
+ toolDescriptors.push(parsed.data);
344
+ const approval = module.value.approval === ToolApproval.Ask ? ToolApproval.Ask : ToolApproval.Allow;
345
+ toolApprovals[module.key] = approval;
346
+ if (approval === ToolApproval.Ask && parsed.data.inputApproval == null)
347
+ toolPolicy[`${AUTHORED_SERVER_KEY}/${module.key}`] = ToolApproval.Ask;
348
+ runtimeExport(module.base, module.path);
349
+ }
350
+ const connections = [];
351
+ const connectionKeys = /* @__PURE__ */ new Set();
352
+ for (const module of ofSlot(SlotKind.Connection)) {
353
+ if (!module.hasDefault || module.value == null) continue;
354
+ if (module.key === AUTHORED_SERVER_KEY) {
355
+ report(
356
+ DiagnosticSeverity.Error,
357
+ DiagnosticCode.Connections,
358
+ `connection name ${AUTHORED_SERVER_KEY} is reserved for authored tools`,
359
+ module.path
360
+ );
361
+ continue;
362
+ }
363
+ if (connectionKeys.has(module.key)) {
364
+ report(
365
+ DiagnosticSeverity.Error,
366
+ DiagnosticCode.Connections,
367
+ `connection ${module.key} is defined more than once`,
368
+ module.path
369
+ );
370
+ continue;
371
+ }
372
+ connectionKeys.add(module.key);
373
+ if (module.value.type === "dynamic") {
374
+ anyDynamicServer = true;
375
+ anyTurnStartedServer ||= module.value.events.includes(DynamicEvent.TurnStarted);
376
+ runtimeExport(module.base, module.path);
377
+ continue;
378
+ }
379
+ if (module.value.type !== "connection") continue;
380
+ const parsed = httpMcpServerBindingSchema.safeParse(module.value.binding);
381
+ if (!parsed.success) {
382
+ report(
383
+ DiagnosticSeverity.Error,
384
+ DiagnosticCode.Connections,
385
+ `connection ${module.key} is invalid: ${parsed.error.issues[0]?.message ?? "invalid"}`,
386
+ module.path
387
+ );
388
+ continue;
389
+ }
390
+ connections.push(parsed.data);
391
+ if (parsed.data.inputApprovals != null) runtimeExport(module.base, module.path);
392
+ for (const [tool, approval] of Object.entries(parsed.data.approvals ?? {})) {
393
+ if (approval === ToolApproval.Ask && !Object.hasOwn(parsed.data.inputApprovals ?? {}, tool))
394
+ toolPolicy[`${module.key}/${tool}`] = ToolApproval.Ask;
395
+ }
396
+ }
397
+ let mcpServers;
398
+ if (anyDynamicServer) {
399
+ mcpServers = {
400
+ $dynamic: {
401
+ resolver: COMBINED_MCP_SERVERS_EXPORT,
402
+ events: anyTurnStartedServer ? [DynamicEvent.SessionStarted, DynamicEvent.TurnStarted] : [DynamicEvent.SessionStarted],
403
+ description: "Authored tools and connections, including the dynamic ones, resolved when the session starts."
404
+ }
405
+ };
406
+ runtimeExport(COMBINED_MCP_SERVERS_EXPORT, "<synthesized>");
407
+ } else {
408
+ mcpServers = [
409
+ ...toolDescriptors.length === 0 ? [] : [
410
+ {
411
+ key: AUTHORED_SERVER_KEY,
412
+ kind: McpServerBindingKind.Worker,
413
+ tools: toolDescriptors,
414
+ approvals: toolApprovals
415
+ }
416
+ ],
417
+ ...connections
418
+ ];
419
+ }
420
+ for (const [key, policy] of Object.entries(agent?.toolPolicy ?? {})) {
421
+ toolPolicy[key] = policy === "ask" ? ToolApproval.Ask : ToolApproval.Allow;
422
+ }
423
+ const sandboxModule = ofSlot(SlotKind.Sandbox)[0];
424
+ const sandbox = sandboxModule?.value?.type === "sandbox" ? sandboxModule.value : null;
425
+ const sandboxPath = sandboxModule?.path ?? "sandbox.ts";
426
+ const sandboxes = {};
427
+ const sandboxOpeners = {};
428
+ const providerExportByName = new Map(
429
+ Object.entries(sandbox?.providers ?? {}).map(([exportName, name]) => [name, exportName])
430
+ );
431
+ const duplicateNames = /* @__PURE__ */ new Set();
432
+ for (const name of Object.values(sandbox?.providers ?? {})) {
433
+ if (duplicateNames.has(name))
434
+ report(
435
+ DiagnosticSeverity.Error,
436
+ DiagnosticCode.Sandbox,
437
+ `sandbox.ts exports multiple providers named ${name}; give each provider a distinct name`,
438
+ sandboxPath
439
+ );
440
+ duplicateNames.add(name);
441
+ }
442
+ const providerFor = (args) => {
443
+ if (args.ref != null) {
444
+ const parsed = providerRefSchema.safeParse(args.ref);
445
+ if (parsed.success) return parsed.data;
446
+ }
447
+ if (args.name != null) {
448
+ const exportName = providerExportByName.get(args.name);
449
+ if (exportName != null) {
450
+ runtimeExport(exportName, sandboxPath);
451
+ return bundleRef(exportName);
452
+ }
453
+ report(
454
+ DiagnosticSeverity.Error,
455
+ DiagnosticCode.Sandbox,
456
+ `sandbox target ${args.target} uses provider ${args.name}, which is neither installed nor exported from sandbox.ts`,
457
+ sandboxPath
458
+ );
459
+ return null;
460
+ }
461
+ report(
462
+ DiagnosticSeverity.Error,
463
+ DiagnosticCode.Sandbox,
464
+ `sandbox target ${args.target} is dynamic and its provider cannot be inferred; give defineDynamic a provider ({ provider: computer, events })`,
465
+ sandboxPath
466
+ );
467
+ return null;
468
+ };
469
+ const inferredProvider = (target) => {
470
+ if (providerExportByName.size > 0) return null;
471
+ const specifier = Object.hasOwn(input.installedSandboxProviders ?? {}, target) ? input.installedSandboxProviders?.[target] : void 0;
472
+ if (specifier != null) return { ref: packageRef(specifier), name: target };
473
+ const installed = /* @__PURE__ */ new Map();
474
+ for (const described2 of Object.values(sandbox?.targets ?? {})) {
475
+ const environment = described2.environment;
476
+ const parsed = providerRefSchema.safeParse(environment?.providerRef);
477
+ if (environment?.providerName == null || !parsed.success) continue;
478
+ if (parsed.data.kind !== ProviderRefKind.Package) continue;
479
+ installed.set(formatProviderRef(parsed.data), {
480
+ ref: environment.providerRef,
481
+ name: environment.providerName
482
+ });
483
+ }
484
+ return installed.size === 1 ? [...installed.values()][0] ?? null : null;
485
+ };
486
+ for (const [target, described2] of Object.entries(sandbox?.targets ?? {})) {
487
+ if (described2.environment != null) {
488
+ const environment = described2.environment;
489
+ const provider = providerFor({
490
+ ref: environment.providerRef,
491
+ name: environment.providerName,
492
+ target
493
+ });
494
+ if (provider == null) continue;
495
+ const open = environment.openOptions ?? void 0;
496
+ if (open != null && (!isObject(open) || Object.keys(open).some((key) => key !== "access" && key !== "attach"))) {
497
+ report(
498
+ DiagnosticSeverity.Error,
499
+ DiagnosticCode.Sandbox,
500
+ `sandbox target ${target} open options support only access and attach`,
501
+ sandboxPath
502
+ );
503
+ continue;
504
+ }
505
+ const access = isObject(open) ? open["access"] : void 0;
506
+ const attach = isObject(open) ? open["attach"] : void 0;
507
+ if (access != null && access !== SandboxAccess.Read && access !== SandboxAccess.Execute && access !== SandboxAccess.Write) {
508
+ report(
509
+ DiagnosticSeverity.Error,
510
+ DiagnosticCode.Sandbox,
511
+ `sandbox target ${target} has invalid access ${String(access)}`,
512
+ sandboxPath
513
+ );
514
+ continue;
515
+ }
516
+ if (attach != null && attach !== SandboxAttach.OnPrompt && attach !== SandboxAttach.Lazy) {
517
+ report(
518
+ DiagnosticSeverity.Error,
519
+ DiagnosticCode.Sandbox,
520
+ `sandbox target ${target} has invalid attach ${String(attach)}`,
521
+ sandboxPath
522
+ );
523
+ continue;
524
+ }
525
+ sandboxes[target] = {
526
+ provider,
527
+ environment: environment.options,
528
+ access: access === SandboxAccess.Read || access === SandboxAccess.Execute ? access : SandboxAccess.Write,
529
+ attach: attach === SandboxAttach.OnPrompt ? SandboxAttach.OnPrompt : SandboxAttach.Lazy
530
+ };
531
+ } else if (described2.dynamic != null) {
532
+ const hinted = described2.dynamic.provider;
533
+ const inferred = hinted == null ? inferredProvider(target) : null;
534
+ if (inferred != null) {
535
+ report(
536
+ DiagnosticSeverity.Note,
537
+ DiagnosticCode.Sandbox,
538
+ `sandbox target ${target} is dynamic; its provider is ${inferred.name}, and its resolver must return a ${inferred.name} environment`,
539
+ sandboxPath
540
+ );
541
+ }
542
+ const provider = providerFor({
543
+ ref: hinted?.ref ?? inferred?.ref ?? null,
544
+ name: hinted?.name ?? inferred?.name ?? null,
545
+ target
546
+ });
547
+ const slot = dynamicSlotFor(
548
+ described2.dynamic,
549
+ described2.exportName,
550
+ sandboxPath,
551
+ `sandbox target ${target}`
552
+ );
553
+ if (provider == null || slot == null) continue;
554
+ sandboxes[target] = {
555
+ provider,
556
+ environment: slot,
557
+ access: SandboxAccess.Write,
558
+ attach: SandboxAttach.Lazy
559
+ };
560
+ }
561
+ }
562
+ if (sandbox?.selector === true && sandbox.defaultTarget != null && sandboxes[sandbox.defaultTarget] != null) {
563
+ sandboxOpeners[sandbox.defaultTarget] = "sandbox";
564
+ runtimeExport("sandbox", sandboxPath);
565
+ report(
566
+ DiagnosticSeverity.Note,
567
+ DiagnosticCode.Sandbox,
568
+ `sandbox.ts default export opens target ${sandbox.defaultTarget} for each session`,
569
+ sandboxPath
570
+ );
571
+ }
572
+ const base = {};
573
+ if (agent?.tools != null) {
574
+ for (const [name, target] of Object.entries(agent.tools)) {
575
+ const capability = capabilityOf(name);
576
+ if (capability == null) {
577
+ report(
578
+ DiagnosticSeverity.Error,
579
+ DiagnosticCode.BaseTools,
580
+ `baseTools has unknown capability ${name}`,
581
+ agentPath
582
+ );
583
+ continue;
584
+ }
585
+ if (sandboxes[target] == null) {
586
+ report(
587
+ DiagnosticSeverity.Error,
588
+ DiagnosticCode.BaseTools,
589
+ `baseTools ${name} is bound to ${target}, which is not a sandbox target`,
590
+ agentPath
591
+ );
592
+ continue;
593
+ }
594
+ base[capability] = { target };
595
+ }
596
+ }
597
+ const host = [];
598
+ for (const name of agent?.hostTools ?? []) {
599
+ const capability = capabilityOf(name);
600
+ if (capability == null) {
601
+ report(
602
+ DiagnosticSeverity.Error,
603
+ DiagnosticCode.BaseTools,
604
+ `baseTools has unknown capability ${name}`,
605
+ agentPath
606
+ );
607
+ continue;
608
+ }
609
+ if (base[capability] != null) {
610
+ report(
611
+ DiagnosticSeverity.Error,
612
+ DiagnosticCode.BaseTools,
613
+ `baseTools ${name} is bound both to a sandbox target and to harnessHost`,
614
+ agentPath
615
+ );
616
+ continue;
617
+ }
618
+ host.push(capability);
619
+ }
620
+ const channels = [];
621
+ const channelKeys = /* @__PURE__ */ new Set();
622
+ const channelRoutes = {};
623
+ const addChannel = (binding, path) => {
624
+ if (channelKeys.has(binding.key)) {
625
+ report(
626
+ DiagnosticSeverity.Error,
627
+ DiagnosticCode.Channel,
628
+ `channel ${binding.key} is bound more than once`,
629
+ path
630
+ );
631
+ return;
632
+ }
633
+ channelKeys.add(binding.key);
634
+ channels.push(binding);
635
+ };
636
+ for (const module of withDefault(SlotKind.Channel)) {
637
+ if (module.value?.type !== "channel") continue;
638
+ const { value } = module;
639
+ if (value.disabled) continue;
640
+ if (value.turnPolicy != null && value.turnPolicy !== TurnPolicy.Steer && value.turnPolicy !== TurnPolicy.Queue) {
641
+ report(
642
+ DiagnosticSeverity.Error,
643
+ DiagnosticCode.Channel,
644
+ `channel ${module.key} turnPolicy must be steer or queue`,
645
+ module.path
646
+ );
647
+ }
648
+ for (const route of value.routes) {
649
+ if (!route.path.startsWith("/")) {
650
+ report(
651
+ DiagnosticSeverity.Error,
652
+ DiagnosticCode.Channel,
653
+ `channel ${module.key} route ${route.path} must start with /`,
654
+ module.path
655
+ );
656
+ }
657
+ }
658
+ const parsedConfig = jsonObjectSchema.safeParse(value.config);
659
+ const installed = value.installed == null ? null : providerRefSchema.safeParse(value.installed);
660
+ if (installed != null && !installed.success) {
661
+ report(
662
+ DiagnosticSeverity.Error,
663
+ DiagnosticCode.Channel,
664
+ `channel ${module.key} has an invalid installed reference`,
665
+ module.path
666
+ );
667
+ continue;
668
+ }
669
+ addChannel(
670
+ {
671
+ key: module.key,
672
+ channel: installed == null ? bundleRef(module.base) : installed.data,
673
+ config: parsedConfig.success ? parsedConfig.data : {},
674
+ source: "authored"
675
+ },
676
+ module.path
677
+ );
678
+ if (value.installed != null) continue;
679
+ runtimeExport(module.base, module.path);
680
+ channelRoutes[module.base] = value.routes.map((route) => ({
681
+ method: route.method,
682
+ path: route.path
683
+ }));
684
+ }
685
+ for (const [index, binding] of (agent?.channels ?? []).entries()) {
686
+ const ref = providerRefSchema.safeParse(binding.channel);
687
+ if (!ref.success) {
688
+ report(
689
+ DiagnosticSeverity.Error,
690
+ DiagnosticCode.Channel,
691
+ `agent.ts channels[${index}] has an invalid channel reference`,
692
+ agentPath
693
+ );
694
+ continue;
695
+ }
696
+ const config2 = jsonObjectSchema.safeParse(binding.config);
697
+ const key = binding.key ?? (ref.data.kind === "package" ? ref.data.specifier.split("/").at(-1) ?? ref.data.specifier : ref.data.export);
698
+ addChannel({ key, channel: ref.data, config: config2.success ? config2.data : {} }, agentPath);
699
+ }
700
+ const hooks = [];
701
+ for (const module of withDefault(SlotKind.Hook)) {
702
+ if (module.value?.type !== "hook") continue;
703
+ const events = [];
704
+ for (const key of module.value.keys) {
705
+ const normalized = normalizeHookKey(key);
706
+ switch (normalized.kind) {
707
+ case HookEventKeyKind.Unknown:
708
+ report(
709
+ DiagnosticSeverity.Error,
710
+ DiagnosticCode.Hook,
711
+ `hook ${module.key} subscribes to unknown event ${key}`,
712
+ module.path
713
+ );
714
+ break;
715
+ case HookEventKeyKind.Canonical:
716
+ case HookEventKeyKind.Wildcard:
717
+ events.push(...normalized.events);
718
+ break;
719
+ }
720
+ }
721
+ const unique = [...new Set(events)];
722
+ if (unique.length === 0) {
723
+ report(
724
+ DiagnosticSeverity.Warning,
725
+ DiagnosticCode.Hook,
726
+ `hook ${module.key} subscribes to no events and was left out`,
727
+ module.path
728
+ );
729
+ continue;
730
+ }
731
+ hooks.push({ slug: module.key, export: module.base, events: unique });
732
+ runtimeExport(module.base, module.path);
733
+ }
734
+ const schedules = [];
735
+ const addSchedule = (args) => {
736
+ const { key, path } = args;
737
+ if (args.cron == null) {
738
+ report(
739
+ DiagnosticSeverity.Error,
740
+ DiagnosticCode.Schedule,
741
+ `schedule ${key} needs a cron expression`,
742
+ path
743
+ );
744
+ return;
745
+ }
746
+ const timezone = args.timezone ?? "UTC";
747
+ try {
748
+ new Cron(args.cron, { timezone, paused: true }).nextRun();
749
+ } catch (cause) {
750
+ report(
751
+ DiagnosticSeverity.Error,
752
+ DiagnosticCode.Schedule,
753
+ `schedule ${key}: ${cause instanceof Error ? cause.message : String(cause)}`,
754
+ path
755
+ );
756
+ return;
757
+ }
758
+ const target = Object.values(ScheduleTarget).find(
759
+ (candidate) => candidate === (args.target ?? ScheduleTarget.OwnerDirect)
760
+ );
761
+ if (target == null) {
762
+ report(
763
+ DiagnosticSeverity.Error,
764
+ DiagnosticCode.Schedule,
765
+ `schedule ${key} target must be owner-direct or bound-conversation`,
766
+ path
767
+ );
768
+ return;
769
+ }
770
+ const prompt = args.prompt?.trim() ?? "";
771
+ if (prompt.length === 0) {
772
+ report(
773
+ DiagnosticSeverity.Error,
774
+ DiagnosticCode.Schedule,
775
+ `schedule ${key} needs a prompt`,
776
+ path
777
+ );
778
+ return;
779
+ }
780
+ schedules.push({ key, cron: args.cron, timezone, prompt, target });
781
+ };
782
+ for (const item of input.discovery.scheduleMarkdown) {
783
+ const front = parseFrontMatter(input.files[item.path] ?? "");
784
+ if (front.error != null)
785
+ report(DiagnosticSeverity.Error, DiagnosticCode.Schedule, front.error, item.path);
786
+ const field = (name) => frontMatterString(front.data, name);
787
+ addSchedule({
788
+ key: item.key,
789
+ path: item.path,
790
+ cron: field("cron"),
791
+ timezone: field("timezone"),
792
+ target: field("target"),
793
+ prompt: front.body
794
+ });
795
+ }
796
+ for (const module of withDefault(SlotKind.Schedule)) {
797
+ if (module.value?.type !== "schedule") continue;
798
+ addSchedule({
799
+ key: module.key,
800
+ path: module.path,
801
+ cron: module.value.cron,
802
+ timezone: module.value.timezone,
803
+ target: module.value.target,
804
+ prompt: module.value.markdown
805
+ });
806
+ }
807
+ const scheduleKeys = /* @__PURE__ */ new Set();
808
+ for (const schedule of schedules) {
809
+ if (scheduleKeys.has(schedule.key)) {
810
+ report(
811
+ DiagnosticSeverity.Error,
812
+ DiagnosticCode.Schedule,
813
+ `schedule ${schedule.key} is defined more than once`
814
+ );
815
+ }
816
+ scheduleKeys.add(schedule.key);
817
+ }
818
+ for (const rejected of input.discovery.rejected) {
819
+ report(DiagnosticSeverity.Error, DiagnosticCode.RejectedSlot, rejected.message, rejected.path);
820
+ }
821
+ for (const unsupported of input.discovery.unsupported) {
822
+ report(
823
+ DiagnosticSeverity.Warning,
824
+ DiagnosticCode.RejectedSlot,
825
+ unsupported.message,
826
+ unsupported.path
827
+ );
828
+ }
829
+ const references = secretReferences(input.files);
830
+ const secrets = collectSecrets({
831
+ declared: agent?.secrets ?? [],
832
+ config,
833
+ mcpServers: connections,
834
+ reads: references.flatMap((reference) => reference.name == null ? [] : [reference.name])
835
+ });
836
+ const computedReads = new Set(
837
+ references.flatMap((reference) => reference.name == null ? [reference.path] : [])
838
+ );
839
+ for (const path of computedReads) {
840
+ report(
841
+ DiagnosticSeverity.Note,
842
+ DiagnosticCode.Secrets,
843
+ `${path} reads a secret by a computed name; list it in defineAgent({ secrets: [...] }) or the read fails at run time`,
844
+ path
845
+ );
846
+ }
847
+ if (harnessRef == null) {
848
+ return { manifest: null, modules, sandboxOpeners, channelRoutes, directoryFields, diagnostics };
849
+ }
850
+ const draft = {
851
+ version: MANIFEST_VERSION,
852
+ identity: {
853
+ name: agent?.name ?? input.fallbackName,
854
+ description: agent?.description ?? null,
855
+ avatarUrl: agent?.avatarUrl ?? null
856
+ },
857
+ harness: { harness: harnessRef, config },
858
+ mcpServers,
859
+ sandboxes,
860
+ tools: host.length === 0 ? { base } : { base, host },
861
+ toolPolicy,
862
+ secrets,
863
+ channels,
864
+ channelSources: Object.fromEntries(
865
+ withDefault(SlotKind.Channel).flatMap(
866
+ (module) => module.value?.type === "channel" ? [
867
+ [
868
+ module.key,
869
+ { path: module.path, source: "authored", disabled: module.value.disabled }
870
+ ]
871
+ ] : []
872
+ )
873
+ ),
874
+ hooks,
875
+ schedules,
876
+ bundle: null
877
+ };
878
+ const resolvers = {};
879
+ for (const found of findDynamicSlots(draft)) {
880
+ resolvers[found.path] = {
881
+ export: found.slot.$dynamic.resolver,
882
+ events: found.slot.$dynamic.events
883
+ };
884
+ }
885
+ const hasSandboxes = Object.keys(sandboxes).length > 0;
886
+ if (Object.keys(modules).length > 0 || hasSandboxes) {
887
+ if (input.bundle == null) {
888
+ report(
889
+ DiagnosticSeverity.Error,
890
+ DiagnosticCode.Bundle,
891
+ "the definition needs a bundle but none was produced"
892
+ );
893
+ } else
894
+ draft.bundle = {
895
+ hash: input.bundle.hash,
896
+ resolvers,
897
+ hasPreparationFiles: Object.keys(preparationFiles(input.files)).length > 0
898
+ };
899
+ }
900
+ const validated = agentManifestSchema.safeParse(draft);
901
+ if (!validated.success) {
902
+ for (const issue of validated.error.issues) {
903
+ report(
904
+ DiagnosticSeverity.Error,
905
+ DiagnosticCode.Manifest,
906
+ `manifest ${issue.path.join(".")}: ${issue.message}`
907
+ );
908
+ }
909
+ }
910
+ const failed = diagnostics.some((item) => item.severity === DiagnosticSeverity.Error);
911
+ return {
912
+ manifest: failed || !validated.success ? null : validated.data,
913
+ modules,
914
+ sandboxOpeners,
915
+ channelRoutes,
916
+ directoryFields,
917
+ diagnostics
918
+ };
919
+ };
920
+ export {
921
+ assemble
922
+ };
923
+ //# sourceMappingURL=assemble.mjs.map