@yansirplus/cli 0.5.17 → 0.5.18

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 (52) hide show
  1. package/README.md +12 -6
  2. package/agent-catalog/agentOS/SKILL.md +22 -0
  3. package/agent-catalog/agentOS/references/agent/decision-graph.json +530 -0
  4. package/agent-catalog/agentOS/references/agent/errors.json +497 -0
  5. package/agent-catalog/agentOS/references/agent/invariant-matrix.json +337 -0
  6. package/agent-catalog/agentOS/references/agent/primitives.json +989 -0
  7. package/agent-catalog/agentOS/references/agent/recipes.json +109 -0
  8. package/agent-catalog/agentOS/references/agent/start-here.md +25 -0
  9. package/agent-catalog/agentOS/references/package-map.md +72 -0
  10. package/agent-catalog/agentOS/references/provenance.json +251 -0
  11. package/agent-catalog/agentOS/references/public-api/cli.md +20 -0
  12. package/agent-catalog/agentOS/references/public-api/client.md +88 -0
  13. package/agent-catalog/agentOS/references/public-api/core.md +1817 -0
  14. package/agent-catalog/agentOS/references/public-api/runtime.md +794 -0
  15. package/dist/build/agent-authoring/config.d.ts +20 -5
  16. package/dist/build/agent-authoring/config.js +132 -32
  17. package/dist/build/agent-authoring/manifest-compiler.d.ts +131 -2
  18. package/dist/build/agent-authoring/manifest-compiler.js +630 -8
  19. package/dist/build/agent-authoring/shared.d.ts +2 -0
  20. package/dist/build/agent-authoring/shared.js +2 -0
  21. package/dist/build/agent-authoring/static-target.d.ts +6 -3
  22. package/dist/build/agent-authoring/static-target.js +1807 -286
  23. package/dist/build/agent-authoring.d.ts +3 -3
  24. package/dist/build/agent-authoring.js +1 -1
  25. package/dist/build/build-cli.d.ts +1 -1
  26. package/dist/build/build-cli.js +1614 -26
  27. package/dist/check/algorithmic/client-boundary-checks.mjs +3 -34
  28. package/dist/check/algorithmic/convergence-smoke-checks.mjs +652 -6
  29. package/dist/check/algorithmic/distribution-checks.mjs +8 -7
  30. package/dist/check/algorithmic/package-boundary-checks.mjs +3 -2
  31. package/dist/check/algorithmic/repo-surface-checks.mjs +55 -1
  32. package/dist/check/algorithmic/static-target-checks.mjs +83 -5
  33. package/dist/check/algorithmic-checks.mjs +10 -17
  34. package/dist/check/default-gate.mjs +3 -3
  35. package/dist/check/effect-scan-gate.mjs +121 -0
  36. package/dist/check/package-graph.mjs +2 -32
  37. package/dist/consumer-overlay.mjs +802 -0
  38. package/dist/lib/public-api-model.mjs +19 -0
  39. package/dist/lib/repo-source-files.mjs +26 -0
  40. package/dist/lib/ts-module-loader.mjs +44 -0
  41. package/dist/lib/workspace-manifest.mjs +77 -0
  42. package/dist/main.mjs +151 -21
  43. package/package.json +8 -4
  44. package/dist/check/check-coverage.mjs +0 -231
  45. package/dist/generate/generate-agent-docs.mjs +0 -435
  46. package/dist/generate/generate-carrier-reference.mjs +0 -514
  47. package/dist/generate/generate-docs.mjs +0 -345
  48. package/dist/generate/generate-effect-skill-manifests.mjs +0 -193
  49. package/dist/generate/project-docs-site.mjs +0 -190
  50. package/dist/lib/boundary-rules.mjs +0 -63
  51. package/dist/lib/capability-routes.mjs +0 -354
  52. package/dist/lib/projection-sink.mjs +0 -113
@@ -1,6 +1,6 @@
1
1
  import { WORKSPACE_TOOL_EXPOSURE_PROFILES } from "@yansirplus/runtime";
2
- import { digestText, isWorkspaceToolName } from "./shared.js";
3
- import { AGENTOS_CONFIG_CLIENT, AGENTOS_CONFIG_LLM_ROUTE, AGENTOS_CONFIG_PROFILE, AGENTOS_CONFIG_TARGET, llmMaterialEnvBindings, } from "./config.js";
2
+ import { digestText, GENERATED_LOAD_SKILL_TOOL_NAME, GENERATED_READ_SKILL_FILE_TOOL_NAME, isWorkspaceToolName, } from "./shared.js";
3
+ import { AGENTOS_CONFIG_CLIENT, AGENTOS_CONFIG_LLM_ROUTE, AGENTOS_CONFIG_PROFILE, AGENTOS_CONFIG_TARGET, llmMaterialEnvBindings, llmMaterialEnvBindingsForRoutes, } from "./config.js";
4
4
  const generatedPath = (path, text) => ({
5
5
  path,
6
6
  text,
@@ -18,7 +18,91 @@ const stableJsonValue = (value) => {
18
18
  };
19
19
  const stableJson = (value) => `${JSON.stringify(stableJsonValue(value), null, 2)}\n`;
20
20
  const jsString = (value) => JSON.stringify(value);
21
+ const identifierSuffix = (value) => value.replace(/[^A-Za-z0-9_$]+/g, "_").replace(/^[^A-Za-z_$]+/u, "_$&");
22
+ const routeEntries = (routes) => Object.entries(routes).sort(([left], [right]) => left.localeCompare(right));
23
+ const uniqueLlmMaterialEnvBindings = (routes) => {
24
+ const bindings = new Map();
25
+ for (const binding of llmMaterialEnvBindingsForRoutes(routes)) {
26
+ bindings.set(`${binding.kind}:${binding.ref}`, binding);
27
+ }
28
+ return [...bindings.values()].sort((left, right) => `${left.kind}:${left.ref}`.localeCompare(`${right.kind}:${right.ref}`));
29
+ };
30
+ const renderMaterialValueFunction = (routes) => {
31
+ const bindings = uniqueLlmMaterialEnvBindings(routes);
32
+ const cases = bindings
33
+ .map((binding) => ` if (ref.kind === ${jsString(binding.kind)} && ref.ref === ${jsString(binding.ref)}) {
34
+ return materialEnvValue(env, ${jsString(binding.envName)});
35
+ }`)
36
+ .join("\n");
37
+ return `const materialValue = (
38
+ env: AgentOSTargetEnv,
39
+ ref: { readonly kind: string; readonly ref: string },
40
+ ): NonNullable<unknown> | null => {
41
+ ${cases}
42
+ return null;
43
+ };`;
44
+ };
45
+ const renderGeneratedProviderPreflight = (routes) => {
46
+ const diagnostics = routeEntries(routes)
47
+ .map(([bindingRef, route]) => ` ...preflightOpenAiCompatibleProviderMaterial({
48
+ route: {
49
+ kind: ${jsString(route.route)},
50
+ endpointRef: ${jsString(route.endpointRef)},
51
+ credentialRef: ${jsString(route.credentialRef)},
52
+ modelId: typeof materialValue(env, { kind: "model", ref: ${jsString(route.modelRef)} }) === "string"
53
+ ? materialValue(env, { kind: "model", ref: ${jsString(route.modelRef)} }) as string
54
+ : "",
55
+ },
56
+ refResolver: { material: (ref) => materialValue(env, ref) },
57
+ routeBindingRef: ${jsString(bindingRef)},
58
+ modelMaterial: {
59
+ ref: ${jsString(route.modelRef)},
60
+ value: materialValue(env, { kind: "model", ref: ${jsString(route.modelRef)} }),
61
+ },
62
+ }),`)
63
+ .join("\n");
64
+ return `const generatedProviderPreflightDiagnosticsFor = (
65
+ env: AgentOSTargetEnv,
66
+ ): ReturnType<typeof preflightOpenAiCompatibleProviderMaterial> => [
67
+ ${diagnostics}
68
+ ];`;
69
+ };
70
+ const renderGeneratedLlmRoutesFor = (routes) => {
71
+ const checks = routeEntries(routes)
72
+ .map(([bindingRef, route]) => {
73
+ const suffix = identifierSuffix(bindingRef);
74
+ return ` const modelId_${suffix} = requiredStringMaterial(
75
+ "model",
76
+ ${jsString(route.modelRef)},
77
+ materialValue(env, { kind: "model", ref: ${jsString(route.modelRef)} }),
78
+ );
79
+ if (!modelId_${suffix}.ok) return modelId_${suffix};`;
80
+ })
81
+ .join("\n");
82
+ const entries = routeEntries(routes)
83
+ .map(([bindingRef, route]) => ` ${jsString(bindingRef)}: {
84
+ kind: ${jsString(route.route)},
85
+ endpointRef: ${jsString(route.endpointRef)},
86
+ credentialRef: ${jsString(route.credentialRef)},
87
+ modelId: modelId_${identifierSuffix(bindingRef)}.value,
88
+ },`)
89
+ .join("\n");
90
+ return `const generatedLlmRoutesFor = (
91
+ env: AgentOSTargetEnv,
92
+ ): GeneratedTargetResult<NonNullable<AgentSubmitBindings["llmRoutes"]>> => {
93
+ ${checks}
94
+ return {
95
+ ok: true,
96
+ value: {
97
+ ${entries}
98
+ },
99
+ };
100
+ };`;
101
+ };
21
102
  const importToolPath = (toolName) => `../../agent/tools/${toolName}`;
103
+ const importChannelPath = (path) => `../../${path.replace(/\.ts$/u, "")}`;
104
+ const importSchedulePath = (path) => `../../${path.replace(/\.ts$/u, "")}`;
105
+ const importDynamicResolverPath = (resolverPath) => `../../${resolverPath.replace(/\.ts$/u, "")}`;
22
106
  const workspaceMutationToolNames = new Set(WORKSPACE_TOOL_EXPOSURE_PROFILES.mutation);
23
107
  const workspaceShellToolNames = new Set(WORKSPACE_TOOL_EXPOSURE_PROFILES.shell);
24
108
  const SOURCE_PACKAGE_SCOPE = "@agent-os";
@@ -28,13 +112,23 @@ const DEFAULT_STATIC_TARGET_PACKAGE_SCOPE = packageScopePattern.test(INJECTED_PU
28
112
  ? INJECTED_PUBLIC_PACKAGE_SCOPE
29
113
  : SOURCE_PACKAGE_SCOPE;
30
114
  const publicPackageSpecifier = (scope, name) => `${scope}/${name}`;
115
+ const cloudflareTargetFor = (target) => {
116
+ if (target.kind === AGENTOS_CONFIG_TARGET.CLOUDFLARE_DO_V1)
117
+ return target;
118
+ throw new TypeError(`cloudflare target renderer received ${target.kind}`);
119
+ };
31
120
  const staticTargetModules = (scope) => ({
121
+ runtimeCapability: publicPackageSpecifier(scope, "runtime/capability"),
32
122
  cloudflareDoRuntime: publicPackageSpecifier(scope, "runtime/cloudflare"),
33
- openAiCompatibleTransport: publicPackageSpecifier(scope, "runtime/llm-effect-ai"),
123
+ localRuntime: publicPackageSpecifier(scope, "runtime/local"),
124
+ openAiCompatibleTransport: publicPackageSpecifier(scope, "runtime/llm-effect-ai/openai-compatible"),
34
125
  workspaceAgentHost: publicPackageSpecifier(scope, "runtime/workspace-agent"),
35
126
  workspaceAgentClient: publicPackageSpecifier(scope, "client/workspace-agent"),
36
127
  workspaceBinding: publicPackageSpecifier(scope, "runtime/workspace-binding"),
37
128
  workspaceEnvCloudflare: publicPackageSpecifier(scope, "runtime/cloudflare"),
129
+ runtimeChannel: publicPackageSpecifier(scope, "runtime/channel"),
130
+ runtimeSchedule: publicPackageSpecifier(scope, "runtime/schedule"),
131
+ runtimeRunProjector: publicPackageSpecifier(scope, "runtime/run-projector"),
38
132
  clientCore: publicPackageSpecifier(scope, "client"),
39
133
  clientSvelte: publicPackageSpecifier(scope, "client/svelte"),
40
134
  runtimeProtocol: publicPackageSpecifier(scope, "core/runtime-protocol"),
@@ -53,7 +147,622 @@ const generatedToolImports = (toolNames) => toolNames.map((toolName, index) => (
53
147
  source: importToolPath(toolName),
54
148
  imports: [`default as tool_${index}`],
55
149
  }));
150
+ const sortedSkills = (skills) => [...skills].sort((left, right) => left.name.localeCompare(right.name));
151
+ const sortedChannels = (channels) => [...channels].sort((left, right) => left.name.localeCompare(right.name));
152
+ const sortedSchedules = (schedules) => [...schedules].sort((left, right) => left.scheduleId.localeCompare(right.scheduleId));
153
+ const generatedChannelImports = (channels) => sortedChannels(channels).map((channel, index) => ({
154
+ kind: "authored-channel",
155
+ source: importChannelPath(channel.path),
156
+ imports: [`default as channel_${index}`],
157
+ }));
158
+ const generatedScheduleImports = (schedules) => sortedSchedules(schedules).map((schedule, index) => ({
159
+ kind: "authored-schedule",
160
+ source: importSchedulePath(schedule.path),
161
+ imports: [`default as schedule_${index}`],
162
+ }));
163
+ const sortedDynamicResolvers = (resolvers) => [...resolvers].sort((left, right) => left.slot.localeCompare(right.slot) || left.resolverId.localeCompare(right.resolverId));
164
+ const generatedDynamicResolverImports = (resolvers) => sortedDynamicResolvers(resolvers).map((resolver, index) => ({
165
+ kind: "authored-dynamic-resolver",
166
+ source: importDynamicResolverPath(resolver.path),
167
+ imports: [`default as dynamicResolver_${index}`],
168
+ }));
169
+ const renderChannelRegistry = (channels, modules) => {
170
+ const ordered = sortedChannels(channels);
171
+ const channelImports = ordered
172
+ .map((channel, index) => `import channel_${index} from ${jsString(importChannelPath(channel.path))};`)
173
+ .join("\n");
174
+ const entries = ordered.length === 0
175
+ ? "[]"
176
+ : `[\n${ordered
177
+ .map((channel, index) => ` { name: ${jsString(channel.name)}, path: ${jsString(channel.path)}, channel: channel_${index} as DefinedChannel },`)
178
+ .join("\n")}\n]`;
179
+ return `${channelImports}
180
+ ${renderNamedImport(["createChannelContext"], modules.runtimeChannel)}
181
+ ${renderTypeImport(["ChannelMethod", "ChannelRequest", "ChannelRoute", "ChannelRuntime", "DefinedChannel"], modules.runtimeChannel)}
182
+
183
+ type GeneratedChannelDefinition = {
184
+ readonly name: string;
185
+ readonly path: string;
186
+ readonly channel: DefinedChannel;
187
+ };
188
+
189
+ type GeneratedChannelRoute = ChannelRoute & {
190
+ readonly channelName: string;
191
+ readonly mountPath: string;
192
+ readonly channel: DefinedChannel;
193
+ };
194
+
195
+ export const generatedChannels = ${entries} as const satisfies ReadonlyArray<GeneratedChannelDefinition>;
196
+
197
+ const mountedChannelPath = (channelName: string, routePath: string): string =>
198
+ routePath === "/" ? \`/channels/\${channelName}\` : \`/channels/\${channelName}\${routePath}\`;
199
+
200
+ const generatedRoutes = generatedChannels.flatMap((entry): ReadonlyArray<GeneratedChannelRoute> =>
201
+ entry.channel.routes.map((route) => ({
202
+ ...route,
203
+ channelName: entry.name,
204
+ mountPath: mountedChannelPath(entry.name, route.path),
205
+ channel: entry.channel,
206
+ })),
207
+ );
208
+
209
+ const routeSegments = (path: string): ReadonlyArray<string> =>
210
+ path
211
+ .split("/")
212
+ .map((segment) => segment.trim())
213
+ .filter((segment) => segment.length > 0);
214
+
215
+ const isRouteParamSegment = (segment: string): boolean => segment.startsWith(":");
216
+
217
+ const routePatternsConflict = (left: string, right: string): boolean => {
218
+ const leftSegments = routeSegments(left);
219
+ const rightSegments = routeSegments(right);
220
+ if (leftSegments.length !== rightSegments.length) return false;
221
+ return leftSegments.every((leftSegment, index) => {
222
+ const rightSegment = rightSegments[index] ?? "";
223
+ return leftSegment === rightSegment || isRouteParamSegment(leftSegment) || isRouteParamSegment(rightSegment);
224
+ });
225
+ };
226
+
227
+ const assertNoGeneratedChannelRouteConflicts = (routes: ReadonlyArray<GeneratedChannelRoute>): void => {
228
+ for (let leftIndex = 0; leftIndex < routes.length; leftIndex += 1) {
229
+ const left = routes[leftIndex];
230
+ if (left === undefined) continue;
231
+ for (let rightIndex = leftIndex + 1; rightIndex < routes.length; rightIndex += 1) {
232
+ const right = routes[rightIndex];
233
+ if (right === undefined || left.method !== right.method) continue;
234
+ if (!routePatternsConflict(left.mountPath, right.mountPath)) continue;
235
+ throw new Error(
236
+ \`generated channel route conflict: \${left.method} \${left.mountPath} conflicts with \${right.mountPath}\`,
237
+ );
238
+ }
239
+ }
240
+ };
241
+
242
+ assertNoGeneratedChannelRouteConflicts(generatedRoutes);
243
+
244
+ export const generatedChannelNames = generatedChannels.map((entry) => entry.name);
245
+ export const generatedChannelRoutes = generatedRoutes;
246
+
247
+ const matchGeneratedChannelPath = (
248
+ pattern: string,
249
+ pathname: string,
250
+ ): Readonly<Record<string, string>> | null => {
251
+ const patternSegments = routeSegments(pattern);
252
+ const pathSegments = routeSegments(pathname);
253
+ if (patternSegments.length !== pathSegments.length) return null;
254
+ const params: Record<string, string> = {};
255
+ for (let index = 0; index < patternSegments.length; index += 1) {
256
+ const patternSegment = patternSegments[index] ?? "";
257
+ const pathSegment = pathSegments[index] ?? "";
258
+ if (patternSegment.startsWith(":")) {
259
+ const paramName = patternSegment.slice(1);
260
+ if (paramName.length === 0) return null;
261
+ params[paramName] = decodeURIComponent(pathSegment);
262
+ continue;
263
+ }
264
+ if (patternSegment !== pathSegment) return null;
265
+ }
266
+ return params;
267
+ };
268
+
269
+ export const dispatchGeneratedChannelRequest = async (
270
+ request: Request,
271
+ runtime: ChannelRuntime,
272
+ ): Promise<Response | null> => {
273
+ const url = new URL(request.url);
274
+ const method = request.method.toUpperCase() as ChannelMethod;
275
+ for (const route of generatedChannelRoutes) {
276
+ if (route.method !== method) continue;
277
+ const params = matchGeneratedChannelPath(route.mountPath, url.pathname);
278
+ if (params === null) continue;
279
+ const channelRequest: ChannelRequest = {
280
+ method: route.method,
281
+ path: url.pathname,
282
+ params,
283
+ request,
284
+ url,
285
+ };
286
+ const principal = await route.channel.verify(channelRequest);
287
+ const context = createChannelContext(runtime, principal);
288
+ return route.handler(channelRequest, context);
289
+ }
290
+ return null;
291
+ };
292
+ `;
293
+ };
294
+ const renderScheduleRegistry = (schedules, modules) => {
295
+ const ordered = sortedSchedules(schedules);
296
+ const scheduleImports = ordered
297
+ .map((schedule, index) => `import schedule_${index} from ${jsString(importSchedulePath(schedule.path))};`)
298
+ .join("\n");
299
+ const entries = ordered.length === 0
300
+ ? "[]"
301
+ : `[\n${ordered
302
+ .map((schedule, index) => ` { scheduleId: ${jsString(schedule.scheduleId)}, path: ${jsString(schedule.path)}, cron: ${jsString(schedule.cron)}, schedule: schedule_${index} as DefinedSchedule },`)
303
+ .join("\n")}\n]`;
304
+ return `${scheduleImports}
305
+ ${renderNamedImport(["dispatchScheduleFire"], modules.runtimeSchedule)}
306
+ ${renderTypeImport([
307
+ "DefinedSchedule",
308
+ "ScheduleDefinitionProjection",
309
+ "ScheduleFireDispatchResult",
310
+ "SchedulePrincipal",
311
+ "ScheduleRuntime",
312
+ ], modules.runtimeSchedule)}
313
+ ${renderTypeImport(["LedgerTruthIdentity"], modules.runtimeProtocol)}
314
+
315
+ type GeneratedScheduleDefinition = {
316
+ readonly scheduleId: string;
317
+ readonly path: string;
318
+ readonly cron: string;
319
+ readonly schedule: DefinedSchedule;
320
+ };
321
+
322
+ export type GeneratedScheduleTriggerInput = {
323
+ readonly scheduleId: string;
324
+ readonly scheduledAt: string | number | Date;
325
+ readonly appPrincipal: SchedulePrincipal;
326
+ };
327
+
328
+ export type GeneratedScheduleDispatchInput = GeneratedScheduleTriggerInput & {
329
+ readonly runtime: ScheduleRuntime;
330
+ readonly identity: LedgerTruthIdentity;
331
+ };
332
+
333
+ export const generatedSchedules = ${entries} as const satisfies ReadonlyArray<GeneratedScheduleDefinition>;
334
+ export const generatedScheduleDefinitions = generatedSchedules.map(
335
+ ({ scheduleId, path, cron }) => ({ scheduleId, path, cron }),
336
+ ) satisfies ReadonlyArray<ScheduleDefinitionProjection>;
337
+ export const generatedScheduleIds = generatedScheduleDefinitions.map((entry) => entry.scheduleId);
338
+ export const generatedScheduleRegistry = new Map(
339
+ generatedSchedules.map((entry) => [entry.scheduleId, entry]),
340
+ );
341
+
342
+ export const dispatchGeneratedSchedule = async (
343
+ input: GeneratedScheduleDispatchInput,
344
+ ): Promise<ScheduleFireDispatchResult> => {
345
+ const entry = generatedScheduleRegistry.get(input.scheduleId);
346
+ if (entry === undefined) {
347
+ throw new Error(\`unknown generated schedule: \${input.scheduleId}\`);
348
+ }
349
+ return dispatchScheduleFire({
350
+ runtime: input.runtime,
351
+ schedule: entry.schedule,
352
+ scheduleId: entry.scheduleId,
353
+ appPrincipal: input.appPrincipal,
354
+ scheduledAt: input.scheduledAt,
355
+ scopeRef: input.identity.scopeRef,
356
+ effectAuthorityRef: input.identity.effectAuthorityRef,
357
+ });
358
+ };
359
+ `;
360
+ };
361
+ const renderSkillCatalog = (skills) => {
362
+ const entries = sortedSkills(skills).map((skill) => ` ${JSON.stringify(stableJsonValue({
363
+ description: skill.description,
364
+ digest: skill.digest,
365
+ files: skill.files.map((file) => ({
366
+ bytes: file.bytes,
367
+ digest: file.digest,
368
+ path: file.path,
369
+ text: file.text,
370
+ })),
371
+ name: skill.name,
372
+ path: skill.path,
373
+ text: skill.text,
374
+ }))}`);
375
+ return entries.length === 0 ? "[]" : `[\n${entries.join(",\n")}\n]`;
376
+ };
377
+ const renderInstructionFragments = (fragments) => {
378
+ const entries = [...fragments]
379
+ .sort((left, right) => left.fragmentId.localeCompare(right.fragmentId))
380
+ .map((fragment) => ` ${JSON.stringify(stableJsonValue({
381
+ digest: fragment.digest,
382
+ id: fragment.fragmentId,
383
+ text: fragment.text,
384
+ }))}`);
385
+ return entries.length === 0 ? "[]" : `[\n${entries.join(",\n")}\n]`;
386
+ };
387
+ const renderDynamicCapabilityCatalog = (normalized, toolNames, hasSkills) => {
388
+ const manifestTools = normalized.deployment.manifest.tools ?? {};
389
+ const dynamicToolNames = [
390
+ ...toolNames,
391
+ ...(hasSkills ? [GENERATED_LOAD_SKILL_TOOL_NAME, GENERATED_READ_SKILL_FILE_TOOL_NAME] : []),
392
+ ];
393
+ return JSON.stringify(stableJsonValue({
394
+ instructions: normalized.instructionFragments.map((fragment) => ({
395
+ digest: fragment.digest,
396
+ id: fragment.fragmentId,
397
+ })),
398
+ skills: normalized.skills.map((skill) => ({
399
+ digest: skill.digest,
400
+ id: skill.name,
401
+ })),
402
+ tools: [...new Set(dynamicToolNames)].sort().map((toolName) => ({
403
+ id: toolName,
404
+ ...(manifestTools[toolName]?.bindingRef === undefined
405
+ ? {}
406
+ : { bindingRef: manifestTools[toolName]?.bindingRef }),
407
+ })),
408
+ }), null, 2);
409
+ };
410
+ const renderDynamicResolverImportStatements = (resolvers) => sortedDynamicResolvers(resolvers)
411
+ .map((resolver, index) => `import dynamicResolver_${index} from ${jsString(importDynamicResolverPath(resolver.path))};`)
412
+ .join("\n");
413
+ const renderDynamicCapabilitySupport = (normalized, toolNames, hasSkills) => {
414
+ const resolvers = sortedDynamicResolvers(normalized.dynamicResolvers);
415
+ const resolverEntries = resolvers.length === 0
416
+ ? "[]"
417
+ : `[\n${resolvers
418
+ .map((resolver, index) => ` {
419
+ resolverId: ${jsString(resolver.resolverId)},
420
+ slot: ${jsString(resolver.slot)},
421
+ resolve: dynamicResolver_${index},
422
+ },`)
423
+ .join("\n")}\n]`;
424
+ return `${renderDynamicResolverImportStatements(resolvers)}
425
+
426
+ const generatedDynamicCapabilityCatalog = ${renderDynamicCapabilityCatalog(normalized, toolNames, hasSkills)} satisfies DynamicCapabilityCompiledCatalog;
427
+
428
+ const generatedInstructionFragments = ${renderInstructionFragments(normalized.instructionFragments)} satisfies ReadonlyArray<SubmitInstructionFragment>;
429
+
430
+ const generatedDynamicCapabilityResolvers = ${resolverEntries} satisfies ReadonlyArray<DynamicCapabilityResolverDefinition>;
431
+
432
+ const generatedDynamicCapabilityTurnEvent = (
433
+ refs: { readonly sessionRef?: string; readonly turnRef?: string } = {},
434
+ ): DynamicCapabilityEventRef => ({
435
+ name: DYNAMIC_CAPABILITY_EVENT.TURN_STARTED,
436
+ ...(refs.sessionRef === undefined ? {} : { sessionRef: refs.sessionRef }),
437
+ ...(refs.turnRef === undefined ? {} : { turnRef: refs.turnRef }),
438
+ });
439
+
440
+ const generatedDynamicSubmitBindingsFor = async (
441
+ event: DynamicCapabilityEventRef,
442
+ ): Promise<GeneratedTargetResult<Pick<AgentSubmitBindings, "dynamicCapabilityProjection" | "instructionFragments">>> => {
443
+ const projection = await runDynamicCapabilityResolvers({
444
+ event,
445
+ catalog: generatedDynamicCapabilityCatalog,
446
+ resolvers: generatedDynamicCapabilityResolvers,
447
+ materials: semanticManifest.materials ?? {},
448
+ });
449
+ if (!projection.ok) {
450
+ return targetFailure(\`dynamic capability resolver failed: \${JSON.stringify(projection.issues)}\`);
451
+ }
452
+ return {
453
+ ok: true,
454
+ value: {
455
+ dynamicCapabilityProjection: projection.projection,
456
+ instructionFragments: generatedInstructionFragments,
457
+ },
458
+ };
459
+ };`;
460
+ };
461
+ const renderSkillSupport = (skills) => {
462
+ if (skills.length === 0)
463
+ return "";
464
+ return `
465
+ type GeneratedSkill = {
466
+ readonly name: string;
467
+ readonly description: string;
468
+ readonly path: string;
469
+ readonly digest: string;
470
+ readonly text: string;
471
+ readonly files: ReadonlyArray<{
472
+ readonly path: string;
473
+ readonly digest: string;
474
+ readonly bytes: number;
475
+ readonly text: string;
476
+ }>;
477
+ };
478
+
479
+ type GeneratedSkillFile = GeneratedSkill["files"][number];
480
+
481
+ type LoadedGeneratedSkill = Omit<GeneratedSkill, "files"> & {
482
+ readonly files: ReadonlyArray<Omit<GeneratedSkillFile, "text">>;
483
+ };
484
+
485
+ const generatedSkillCatalog = ${renderSkillCatalog(skills)} satisfies ReadonlyArray<GeneratedSkill>;
486
+ const generatedSkillNames = generatedSkillCatalog.map((skill) => skill.name);
487
+ const generatedSkillByName = Object.fromEntries(
488
+ generatedSkillCatalog.map((skill) => [skill.name, skill]),
489
+ ) as Readonly<Record<string, GeneratedSkill>>;
490
+ const generatedSkillFilePathCatalog = generatedSkillCatalog.flatMap((skill) =>
491
+ skill.files.map((file) => ({ name: skill.name, path: file.path })),
492
+ );
493
+ const generatedVisibleSkillCatalogFor = (
494
+ projection: DynamicCapabilityProjection | undefined,
495
+ ): ReadonlyArray<GeneratedSkill> => {
496
+ if (projection === undefined) return generatedSkillCatalog;
497
+ const visible = new Set(
498
+ projection.skills.filter((skill) => skill.visible).map((skill) => skill.id),
499
+ );
500
+ return generatedSkillCatalog.filter((skill) => visible.has(skill.name));
501
+ };
502
+
503
+ const generatedSkillsSystemAdvert = (
504
+ projection: DynamicCapabilityProjection | undefined,
505
+ ): string => [
506
+ "Available agent skills are not loaded by default.",
507
+ ...generatedVisibleSkillCatalogFor(projection).map((skill) => \`- \${skill.name}: \${skill.description}\`),
508
+ "Do not assume a skill's full instructions until ${GENERATED_LOAD_SKILL_TOOL_NAME} returns it.",
509
+ ].join("\\n");
510
+
511
+ const generatedSystemPrompt = (
512
+ system: string | undefined,
513
+ projection: DynamicCapabilityProjection | undefined,
514
+ ): string =>
515
+ system === undefined || system.length === 0
516
+ ? generatedSkillsSystemAdvert(projection)
517
+ : \`\${system}\\n\\n\${generatedSkillsSystemAdvert(projection)}\`;
518
+
519
+ const generatedLoadedSkill = (skill: GeneratedSkill): LoadedGeneratedSkill => ({
520
+ name: skill.name,
521
+ description: skill.description,
522
+ path: skill.path,
523
+ digest: skill.digest,
524
+ text: skill.text,
525
+ files: skill.files.map((file) => ({
526
+ path: file.path,
527
+ digest: file.digest,
528
+ bytes: file.bytes,
529
+ })),
530
+ });
531
+
532
+ const generatedFrameworkToolsFor = (
533
+ projection: DynamicCapabilityProjection | undefined,
534
+ ): Readonly<Record<string, Tool>> => {
535
+ const visibleSkillNames = new Set(
536
+ generatedVisibleSkillCatalogFor(projection).map((skill) => skill.name),
537
+ );
538
+ if (visibleSkillNames.size === 0) return {};
539
+ const visibleSkill = (name: string): GeneratedSkill | null => {
540
+ if (!visibleSkillNames.has(name)) return null;
541
+ return generatedSkillByName[name] ?? null;
542
+ };
543
+ const generatedLoadSkillTool = defineProductTool({
544
+ name: ${jsString(GENERATED_LOAD_SKILL_TOOL_NAME)},
545
+ description: "Load the full text of a CLI-authored agent skill by name.",
546
+ args: Schema.Struct({ name: Schema.String }),
547
+ authority: "agentos.generated.skills",
548
+ authorityId: "agentos.generated.skills.load_skill",
549
+ admit: ({ name }) => Effect.succeed({ ok: visibleSkillNames.has(name) } as const),
550
+ execute: ({ name }) => {
551
+ const skill = visibleSkill(name);
552
+ if (skill === null) return Effect.fail(Error(\`unknown skill \${name}\`));
553
+ return Effect.succeed(generatedLoadedSkill(skill));
554
+ },
555
+ });
556
+
557
+ const generatedReadSkillFileTool = defineProductTool({
558
+ name: ${jsString(GENERATED_READ_SKILL_FILE_TOOL_NAME)},
559
+ description: "Read one declared supporting file from a CLI-authored agent skill package.",
560
+ args: Schema.Struct({
561
+ name: Schema.String,
562
+ path: Schema.String,
563
+ }),
564
+ authority: "agentos.generated.skills",
565
+ authorityId: "agentos.generated.skills.read_skill_file",
566
+ admit: ({ name, path }) =>
567
+ Effect.succeed({
568
+ ok:
569
+ visibleSkillNames.has(name) &&
570
+ generatedSkillFilePathCatalog.some((file) => file.name === name && file.path === path),
571
+ } as const),
572
+ execute: ({ name, path }) => {
573
+ const skill = visibleSkill(name);
574
+ const file = skill?.files.find((candidate) => candidate.path === path);
575
+ if (skill === null || file === undefined) {
576
+ return Effect.fail(Error(\`unknown skill file \${name}/\${path}\`));
577
+ }
578
+ return Effect.succeed({
579
+ name,
580
+ path: file.path,
581
+ digest: file.digest,
582
+ text: file.text,
583
+ });
584
+ },
585
+ });
586
+
587
+ return {
588
+ ${jsString(GENERATED_LOAD_SKILL_TOOL_NAME)}: generatedLoadSkillTool,
589
+ ${jsString(GENERATED_READ_SKILL_FILE_TOOL_NAME)}: generatedReadSkillFileTool,
590
+ } satisfies Readonly<Record<string, Tool>>;
591
+ };
592
+ `;
593
+ };
594
+ const renderSubmitSpecFromRunInput = (hasSkills) => `const submitSpecFromRunInput = (
595
+ input: SubmitRunInput,
596
+ dynamicCapabilityProjection: DynamicCapabilityProjection | undefined,
597
+ ): AgentSubmitSpec => ({
598
+ input,
599
+ intent: input.intent,
600
+ context: input.context,
601
+ ${hasSkills ? "system: generatedSystemPrompt(input.system, dynamicCapabilityProjection)," : "...(input.system === undefined ? {} : { system: input.system }),"}
602
+ ...(input.budget === undefined ? {} : { budget: input.budget }),
603
+ ...(input.outputSchema === undefined ? {} : { outputSchema: input.outputSchema }),
604
+ ...(input.traceContext === undefined ? {} : { traceContext: input.traceContext }),
605
+ ...(input.materials === undefined ? {} : { materials: input.materials }),
606
+ ...(input.toolContext === undefined ? {} : { toolContext: input.toolContext }),
607
+ ...(input.toolPolicy === undefined ? {} : { toolPolicy: input.toolPolicy }),
608
+ ...(input.decisionInterrupts === undefined ? {} : { decisionInterrupts: input.decisionInterrupts }),
609
+ ...(input.resume === undefined ? {} : { resume: input.resume }),
610
+ });`;
611
+ const renderProductApiHelpers = () => `export interface AgentSessionSubmitTurnInput extends SubmitRunInput {
612
+ readonly sessionRef: string;
613
+ readonly turnRef: string;
614
+ readonly idempotencyKey?: string;
615
+ }
616
+
617
+ export interface AgentWorkflowRunInput extends SubmitRunInput {
618
+ readonly workflowId: string;
619
+ readonly workflowRunId: string;
620
+ readonly idempotencyKey?: string;
621
+ readonly inputDigest?: string;
622
+ }
623
+
624
+ export interface AgentWorkflowRunRef {
625
+ readonly workflowId: string;
626
+ readonly workflowRunId: string;
627
+ }
628
+
629
+ const submitRunInputFields = (input: SubmitRunInput): SubmitRunInput => ({
630
+ intent: input.intent,
631
+ context: input.context,
632
+ ...(input.system === undefined ? {} : { system: input.system }),
633
+ ...(input.budget === undefined ? {} : { budget: input.budget }),
634
+ ...(input.outputSchema === undefined ? {} : { outputSchema: input.outputSchema }),
635
+ ...(input.traceContext === undefined ? {} : { traceContext: input.traceContext }),
636
+ ...(input.materials === undefined ? {} : { materials: input.materials }),
637
+ ...(input.toolContext === undefined ? {} : { toolContext: input.toolContext }),
638
+ ...(input.toolPolicy === undefined ? {} : { toolPolicy: input.toolPolicy }),
639
+ ...(input.decisionInterrupts === undefined ? {} : { decisionInterrupts: input.decisionInterrupts }),
640
+ ...(input.resume === undefined ? {} : { resume: input.resume }),
641
+ });
642
+
643
+ const submitRunInputFromWorkflowRun = (
644
+ input: AgentWorkflowRunInput,
645
+ ): SubmitRunInput => submitRunInputFields(input);
646
+
647
+ const submitRunInputFromSessionTurn = (
648
+ input: AgentSessionSubmitTurnInput,
649
+ ): SubmitRunInput => submitRunInputFields(input);`;
650
+ const renderProductApiDurableObjectMethods = () => `
651
+ submitSessionTurn(input: AgentSessionSubmitTurnInput): Promise<SubmitResult> {
652
+ return generatedSubmitBindingsFor(
653
+ this.targetEnv,
654
+ generatedDynamicCapabilityTurnEvent({
655
+ sessionRef: input.sessionRef,
656
+ turnRef: input.turnRef,
657
+ }),
658
+ ).then((bindings) =>
659
+ bindings.ok
660
+ ? this.submitWithBindingsAndProductLink(
661
+ submitSpecFromRunInput(
662
+ submitRunInputFromSessionTurn(input),
663
+ bindings.value.dynamicCapabilityProjection,
664
+ ),
665
+ bindings.value,
666
+ {
667
+ kind: "session_turn",
668
+ sessionRef: input.sessionRef,
669
+ turnRef: input.turnRef,
670
+ ...(input.idempotencyKey === undefined ? {} : { idempotencyKey: input.idempotencyKey }),
671
+ },
672
+ )
673
+ : rejectTargetFailure(bindings),
674
+ );
675
+ }
676
+
677
+ inspectSession(input: { readonly sessionRef: string }): Promise<AgentSessionProjection> {
678
+ return this.events(semanticTruthIdentity).then((events) =>
679
+ projectAgentSession(events, input.sessionRef),
680
+ );
681
+ }
682
+
683
+ listSessions(): Promise<AgentSessionListProjection> {
684
+ return this.events(semanticTruthIdentity).then((events) => projectAgentSessions(events));
685
+ }
686
+
687
+ runWorkflow(input: AgentWorkflowRunInput): Promise<SubmitResult> {
688
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
689
+ bindings.ok
690
+ ? this.submitWithBindingsAndProductLink(
691
+ submitSpecFromRunInput(
692
+ submitRunInputFromWorkflowRun(input),
693
+ bindings.value.dynamicCapabilityProjection,
694
+ ),
695
+ bindings.value,
696
+ {
697
+ kind: "workflow_run",
698
+ workflowId: input.workflowId,
699
+ workflowRunId: input.workflowRunId,
700
+ ...(input.idempotencyKey === undefined ? {} : { idempotencyKey: input.idempotencyKey }),
701
+ ...(input.inputDigest === undefined ? {} : { inputDigest: input.inputDigest }),
702
+ },
703
+ )
704
+ : rejectTargetFailure(bindings),
705
+ );
706
+ }
707
+
708
+ inspectWorkflowRun(input: AgentWorkflowRunRef): Promise<WorkflowRunProjection | null> {
709
+ return this.events(semanticTruthIdentity).then((events) =>
710
+ projectWorkflowRun(events, input.workflowId, input.workflowRunId),
711
+ );
712
+ }
713
+
714
+ listWorkflowRuns(input: { readonly workflowId: string }): Promise<WorkflowRunListProjection> {
715
+ return this.events(semanticTruthIdentity).then((events) =>
716
+ projectWorkflowRuns(events, input.workflowId),
717
+ );
718
+ }`;
719
+ const renderScheduleDurableObjectHelpers = () => `
720
+ const generatedScheduleRuntimeFor = (target: {
721
+ readonly submitSessionTurn: (input: AgentSessionSubmitTurnInput) => Promise<SubmitResult>;
722
+ readonly runWorkflow: (input: AgentWorkflowRunInput) => Promise<SubmitResult>;
723
+ }) =>
724
+ Object.freeze({
725
+ sessions: Object.freeze({
726
+ submitTurn: (input: AgentSessionSubmitTurnInput) => target.submitSessionTurn(input),
727
+ }),
728
+ workflows: Object.freeze({
729
+ run: (input: AgentWorkflowRunInput) => target.runWorkflow(input),
730
+ }),
731
+ });`;
732
+ const renderScheduleDurableObjectMethod = () => `
733
+ dispatchSchedule(input: GeneratedScheduleTriggerInput): Promise<unknown> {
734
+ return dispatchGeneratedSchedule({
735
+ ...input,
736
+ identity: semanticTruthIdentity,
737
+ runtime: generatedScheduleRuntimeFor(this),
738
+ }).then((result) => this.commitScheduleFireDispatchFull(result));
739
+ }
740
+ `;
741
+ const renderGeneratedWorkspaceOperations = (workspaceToolArray, usesMutationTools, usesShellTools) => `const generatedWorkspaceToolNames = ${workspaceToolArray};
742
+
743
+ const generatedWorkspaceToolInteractionFor = (
744
+ name: (typeof generatedWorkspaceToolNames)[number],
745
+ ): "never" | "approval" => {
746
+ const interaction = semanticManifest.tools?.[name]?.interaction;
747
+ if (interaction === "never" || interaction === "approval") return interaction;
748
+ throw Error(\`invalid workspace tool interaction for \${name}: \${String(interaction)}\`);
749
+ };
750
+
751
+ const generatedWorkspaceToolInteractions = Object.fromEntries(
752
+ generatedWorkspaceToolNames.map((name) => [name, generatedWorkspaceToolInteractionFor(name)]),
753
+ ) as Readonly<Partial<Record<(typeof generatedWorkspaceToolNames)[number], "never" | "approval">>>;
754
+
755
+ const generatedWorkspaceOperations = {
756
+ toolNames: generatedWorkspaceToolNames,
757
+ mutationPolicy: ${usesMutationTools ? '"receipt-backed"' : '"disabled"'},
758
+ shellPolicy: ${usesShellTools ? '"receipt-backed"' : '"disabled"'},
759
+ toolInteractions: generatedWorkspaceToolInteractions,
760
+ } as const;`;
56
761
  const renderWorkspaceStaticTarget = (normalized, toolNames, modules) => {
762
+ const target = cloudflareTargetFor(normalized.target);
763
+ const hasSkills = normalized.skills.length > 0;
764
+ const hasDynamicCapability = true;
765
+ const hasSchedules = normalized.schedules.length > 0;
57
766
  const authoredToolNames = new Set(normalized.authoredToolNames);
58
767
  const workspaceToolList = toolNames.filter((toolName) => isWorkspaceToolName(toolName) && !authoredToolNames.has(toolName));
59
768
  const customToolNames = toolNames.filter((toolName) => authoredToolNames.has(toolName));
@@ -71,23 +780,54 @@ const renderWorkspaceStaticTarget = (normalized, toolNames, modules) => {
71
780
  const handlerRecord = `{\n${normalized.deployment.manifest.handlers
72
781
  .map((handler) => ` ${jsString(handler)}: generatedHandler,`)
73
782
  .join("\n")}\n}`;
74
- const llmEnvByKind = Object.fromEntries(llmMaterialEnvBindings(normalized.llm).map((binding) => [binding.kind, binding.envName]));
75
- const generatedLlmEnvFields = Object.values(llmEnvByKind)
76
- .map((envName) => ` readonly ${envName}?: string;`)
783
+ const llmEnvBindings = uniqueLlmMaterialEnvBindings(normalized.llmRoutes);
784
+ const generatedLlmEnvFields = llmEnvBindings
785
+ .map((binding) => ` readonly ${binding.envName}?: string;`)
77
786
  .join("\n");
78
787
  const imports = [
79
788
  `import semanticDeclarations from "./manifest.json";`,
80
789
  `import deploymentProvenance from "./deployment.json";`,
81
- renderNamedImport(["createAgentDurableObject", "installCloudflareWorkspaceOperationProvider"], modules.cloudflareDoRuntime),
82
- renderNamedImport(["OpenAiCompatibleLlmTransportLive"], modules.openAiCompatibleTransport),
790
+ ...(hasSchedules ? [renderNamedImport(["dispatchGeneratedSchedule"], "./schedules")] : []),
791
+ renderNamedImport(["createAgentDurableObject"], modules.cloudflareDoRuntime),
792
+ renderNamedImport([
793
+ "WORKSPACE_OPERATION_HOST_FACT",
794
+ "defineHost",
795
+ "resolveRuntimeInstallGraph",
796
+ ...(hasDynamicCapability ? ["runDynamicCapabilityResolvers"] : []),
797
+ "workspaceOperations",
798
+ ], modules.runtimeCapability),
799
+ renderNamedImport(["OpenAiCompatibleLlmTransportLive", "preflightOpenAiCompatibleProviderMaterial"], modules.openAiCompatibleTransport),
800
+ renderNamedImport(["DYNAMIC_CAPABILITY_EVENT", "manifestTruthIdentity"], modules.runtimeProtocol),
801
+ renderNamedImport(["projectAgentSession", "projectAgentSessions", "projectWorkflowRun", "projectWorkflowRuns"], modules.runtimeRunProjector),
83
802
  renderNamedImport(["defineWorkspaceAgentMount", "WORKSPACE_AGENT_PROJECTION"], modules.workspaceAgentHost),
84
- renderNamedImport(["bindWorkspaceToolsForRuntime"], modules.workspaceBinding),
85
803
  renderNamedImport(["makeCloudflareWorkspaceEnv"], modules.workspaceEnvCloudflare),
86
804
  renderNamedImport(["getSandbox"], modules.cloudflareSandbox),
87
- renderNamedImport(["deterministicToolInvocation", "unsafeRunToolByName"], modules.coreTools),
88
- renderNamedImport(["Effect"], modules.effect),
805
+ renderNamedImport([
806
+ "deterministicToolInvocation",
807
+ ...(hasSkills ? ["defineProductTool"] : []),
808
+ "unsafeRunToolByName",
809
+ ], modules.coreTools),
810
+ renderNamedImport(hasSkills ? ["Effect", "Schema"] : ["Effect"], modules.effect),
89
811
  renderTypeImport(["AgentManifest", "AgentSubmitBindings", "SubmitResult", "SubmitRunInput"], modules.runtimeProtocol),
812
+ ...(hasDynamicCapability
813
+ ? [
814
+ renderTypeImport([
815
+ "DynamicCapabilityCompiledCatalog",
816
+ "DynamicCapabilityEventRef",
817
+ "DynamicCapabilityProjection",
818
+ "SubmitInstructionFragment",
819
+ ], modules.runtimeProtocol),
820
+ renderTypeImport(["DynamicCapabilityResolverDefinition"], modules.runtimeCapability),
821
+ ]
822
+ : []),
823
+ renderTypeImport([
824
+ "AgentSessionListProjection",
825
+ "AgentSessionProjection",
826
+ "WorkflowRunListProjection",
827
+ "WorkflowRunProjection",
828
+ ], modules.runtimeRunProjector),
90
829
  renderTypeImport(["AgentSubmitSpec"], modules.cloudflareDoRuntime),
830
+ ...(hasSchedules ? [renderTypeImport(["GeneratedScheduleTriggerInput"], "./schedules")] : []),
91
831
  renderTypeImport([
92
832
  "WorkspaceAgentDecideInputRequestCommandInput",
93
833
  "WorkspaceAgentCustomCommandInput",
@@ -109,6 +849,7 @@ export const targetDeclarations = semanticDeclarations;
109
849
  export const targetDeployment = deploymentProvenance;
110
850
 
111
851
  const semanticManifest = semanticDeclarations as AgentManifest;
852
+ const semanticTruthIdentity = manifestTruthIdentity(semanticManifest);
112
853
  const generatedHandler = () => undefined;
113
854
 
114
855
  type AgentOSTargetEnv = {
@@ -120,33 +861,36 @@ ${generatedLlmEnvFields}
120
861
  type GeneratedTargetFailure = {
121
862
  readonly ok: false;
122
863
  readonly message: string;
864
+ readonly diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>;
123
865
  };
124
866
 
125
867
  type GeneratedTargetResult<Value> =
126
868
  | { readonly ok: true; readonly value: Value }
127
869
  | GeneratedTargetFailure;
128
870
 
129
- const targetFailure = (message: string): GeneratedTargetFailure => ({ ok: false, message });
871
+ const targetFailure = (
872
+ message: string,
873
+ diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>,
874
+ ): GeneratedTargetFailure => ({
875
+ ok: false,
876
+ message,
877
+ ...(diagnostics === undefined || diagnostics.length === 0 ? {} : { diagnostics }),
878
+ });
130
879
 
131
- const rejectTargetFailure = (failure: GeneratedTargetFailure): Promise<never> =>
132
- Promise.reject(Error(failure.message));
880
+ const rejectTargetFailure = (failure: GeneratedTargetFailure): Promise<never> => {
881
+ const error = Error(failure.message) as Error & {
882
+ diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>;
883
+ };
884
+ if (failure.diagnostics !== undefined) error.diagnostics = failure.diagnostics;
885
+ return Promise.reject(error);
886
+ };
133
887
 
134
- const generatedWorkspaceToolNames = ${workspaceToolArray};
888
+ ${renderGeneratedWorkspaceOperations(workspaceToolArray, usesMutationTools, usesShellTools)}
135
889
  const generatedCustomTools = ${customToolRecord} satisfies Readonly<Record<string, Tool>>;
890
+ ${hasDynamicCapability ? renderDynamicCapabilitySupport(normalized, toolNames, hasSkills) : ""}
891
+ ${renderSkillSupport(normalized.skills)}
136
892
  const generatedWorkspaceSandboxId = ${jsString(normalized.workspace.cloudflareSandboxId)};
137
893
 
138
- const generatedWorkspaceToolInteractionFor = (
139
- name: (typeof generatedWorkspaceToolNames)[number],
140
- ): "never" | "approval" => {
141
- const interaction = semanticManifest.tools?.[name]?.interaction;
142
- if (interaction === "never" || interaction === "approval") return interaction;
143
- throw Error(\`invalid workspace tool interaction for \${name}: \${String(interaction)}\`);
144
- };
145
-
146
- const generatedWorkspaceToolInteractions = Object.fromEntries(
147
- generatedWorkspaceToolNames.map((name) => [name, generatedWorkspaceToolInteractionFor(name)]),
148
- ) as Readonly<Partial<Record<(typeof generatedWorkspaceToolNames)[number], "never" | "approval">>>;
149
-
150
894
  const workspaceNamespaceFor = (env: AgentOSTargetEnv): DurableObjectNamespace<Sandbox> =>
151
895
  env[${jsString(normalized.workspace.binding)}] as DurableObjectNamespace<Sandbox>;
152
896
 
@@ -221,36 +965,46 @@ const workspaceEnvFor = (env: AgentOSTargetEnv) =>
221
965
  workspaceRef: ${jsString(normalized.workspace.providerResourceId)},
222
966
  });
223
967
 
224
- const allowWorkspaceTool = () =>
225
- Effect.succeed({ ok: true as const }).pipe(
226
- Effect.withSpan("agentos.generated.workspace.allow_tool"),
227
- );
968
+ const generatedHostProfileFor = (env: AgentOSTargetEnv) => defineHost({
969
+ target: "cloudflare-do@1",
970
+ provides: [
971
+ "storage.ledger",
972
+ "durability.do",
973
+ WORKSPACE_OPERATION_HOST_FACT,
974
+ "timer.durable",
975
+ "network.outbound",
976
+ "secrets.store",
977
+ "eventLoop.durable",
978
+ "llm.openai",
979
+ ],
980
+ materialize: () => ({
981
+ [WORKSPACE_OPERATION_HOST_FACT]: () => workspaceEnvFor(env),
982
+ }),
983
+ });
228
984
 
229
- const workspaceOperationInstallFor = (env: AgentOSTargetEnv) =>
230
- installCloudflareWorkspaceOperationProvider({
231
- env: workspaceEnvFor(env),
232
- });
985
+ const generatedCapabilityInstallGraphFor = (env: AgentOSTargetEnv) => {
986
+ const graph = resolveRuntimeInstallGraph(
987
+ generatedHostProfileFor(env),
988
+ [workspaceOperations(generatedWorkspaceOperations)],
989
+ { identity: semanticManifest.agentId },
990
+ );
991
+ if (!graph.ok) {
992
+ throw Error(
993
+ graph.diagnostics
994
+ .map((diagnostic) => diagnostic.reason)
995
+ .join("; ") || "capability install graph failed",
996
+ );
997
+ }
998
+ return graph.resolved;
999
+ };
233
1000
 
234
1001
  const materialEnvValue = (env: AgentOSTargetEnv, name: string): string | null => {
235
1002
  const value = env[name];
236
1003
  return typeof value === "string" && value.length > 0 ? value : null;
237
1004
  };
238
1005
 
239
- const materialValue = (
240
- env: AgentOSTargetEnv,
241
- ref: { readonly kind: string; readonly ref: string },
242
- ): NonNullable<unknown> | null => {
243
- if (ref.kind === "endpoint" && ref.ref === ${jsString(normalized.llm.endpointRef)}) {
244
- return materialEnvValue(env, ${jsString(llmEnvByKind.endpoint)});
245
- }
246
- if (ref.kind === "credential" && ref.ref === ${jsString(normalized.llm.credentialRef)}) {
247
- return materialEnvValue(env, ${jsString(llmEnvByKind.credential)});
248
- }
249
- if (ref.kind === "model" && ref.ref === ${jsString(normalized.llm.modelRef)}) {
250
- return materialEnvValue(env, ${jsString(llmEnvByKind.model)});
251
- }
252
- return null;
253
- };
1006
+ ${renderMaterialValueFunction(normalized.llmRoutes)}
1007
+ ${renderGeneratedProviderPreflight(normalized.llmRoutes)}
254
1008
 
255
1009
  const requiredStringMaterial = (
256
1010
  kind: string,
@@ -261,70 +1015,44 @@ const requiredStringMaterial = (
261
1015
  return targetFailure(\`missing \${kind} material: \${ref}\`);
262
1016
  };
263
1017
 
264
- const generatedLlmRouteFor = (env: AgentOSTargetEnv): GeneratedTargetResult<NonNullable<AgentSubmitBindings["llmRoutes"]>["default"]> => {
265
- const modelId = requiredStringMaterial(
266
- "model",
267
- ${jsString(normalized.llm.modelRef)},
268
- materialValue(env, { kind: "model", ref: ${jsString(normalized.llm.modelRef)} }),
269
- );
270
- if (!modelId.ok) return modelId;
271
- return {
272
- ok: true,
273
- value: {
274
- kind: "openai-chat-compatible",
275
- endpointRef: ${jsString(normalized.llm.endpointRef)},
276
- credentialRef: ${jsString(normalized.llm.credentialRef)},
277
- modelId: modelId.value,
278
- },
279
- };
280
- };
1018
+ ${renderGeneratedLlmRoutesFor(normalized.llmRoutes)}
281
1019
 
282
- const generatedWorkspaceBindingsFor = (env: AgentOSTargetEnv): AgentSubmitBindings =>
283
- generatedWorkspaceToolNames.length === 0
284
- ? {}
285
- : bindWorkspaceToolsForRuntime({
286
- env: workspaceEnvFor(env),
287
- authority: "agentos.workspace.static-target",
288
- admit: allowWorkspaceTool,
289
- toolNames: generatedWorkspaceToolNames,
290
- mutationPolicy: ${usesMutationTools ? '"receipt-backed"' : '"disabled"'},
291
- shellPolicy: ${usesShellTools ? '"receipt-backed"' : '"disabled"'},
292
- toolInteractions: generatedWorkspaceToolInteractions,
293
- });
294
-
295
- const generatedSubmitBindingsFor = (env: AgentOSTargetEnv): GeneratedTargetResult<AgentSubmitBindings> => {
296
- const workspaceBindings = generatedWorkspaceBindingsFor(env);
297
- const route = generatedLlmRouteFor(env);
298
- if (!route.ok) return route;
1020
+ const generatedSubmitBindingsFor = async (
1021
+ env: AgentOSTargetEnv,
1022
+ event: DynamicCapabilityEventRef = generatedDynamicCapabilityTurnEvent(),
1023
+ ): Promise<GeneratedTargetResult<AgentSubmitBindings>> => {
1024
+ const preflightDiagnostics = generatedProviderPreflightDiagnosticsFor(env);
1025
+ if (preflightDiagnostics.length > 0) {
1026
+ return targetFailure(
1027
+ "OpenAI-compatible provider material preflight failed",
1028
+ preflightDiagnostics,
1029
+ );
1030
+ }
1031
+ const capabilityGraph = generatedCapabilityInstallGraphFor(env);
1032
+ const routes = generatedLlmRoutesFor(env);
1033
+ if (!routes.ok) return routes;
1034
+ const dynamicBindings = await generatedDynamicSubmitBindingsFor(event);
1035
+ if (!dynamicBindings.ok) return dynamicBindings;
1036
+ const dynamicCapabilityProjection = dynamicBindings.value.dynamicCapabilityProjection;
299
1037
  return {
300
1038
  ok: true,
301
1039
  value: {
302
- ...workspaceBindings,
303
- llmRoutes: {
304
- default: route.value,
305
- },
1040
+ ...capabilityGraph.bindings,
1041
+ ...dynamicBindings.value,
1042
+ llmRoutes: routes.value,
306
1043
  tools: {
307
- ...(workspaceBindings.tools ?? {}),
1044
+ ...(capabilityGraph.bindings.tools ?? {}),
308
1045
  ...generatedCustomTools,
1046
+ ${hasSkills ? "...generatedFrameworkToolsFor(dynamicCapabilityProjection)," : ""}
309
1047
  },
310
1048
  },
311
1049
  };
312
1050
  };
313
1051
 
314
- const submitSpecFromRunInput = (input: SubmitRunInput): AgentSubmitSpec => ({
315
- input,
316
- intent: input.intent,
317
- context: input.context,
318
- ...(input.system === undefined ? {} : { system: input.system }),
319
- ...(input.budget === undefined ? {} : { budget: input.budget }),
320
- ...(input.outputSchema === undefined ? {} : { outputSchema: input.outputSchema }),
321
- ...(input.traceContext === undefined ? {} : { traceContext: input.traceContext }),
322
- ...(input.materials === undefined ? {} : { materials: input.materials }),
323
- ...(input.toolContext === undefined ? {} : { toolContext: input.toolContext }),
324
- ...(input.toolPolicy === undefined ? {} : { toolPolicy: input.toolPolicy }),
325
- ...(input.decisionInterrupts === undefined ? {} : { decisionInterrupts: input.decisionInterrupts }),
326
- ...(input.resume === undefined ? {} : { resume: input.resume }),
327
- });
1052
+ ${renderSubmitSpecFromRunInput(hasSkills)}
1053
+
1054
+ ${renderProductApiHelpers()}
1055
+ ${hasSchedules ? renderScheduleDurableObjectHelpers() : ""}
328
1056
 
329
1057
  export const workspaceMount = defineWorkspaceAgentMount({
330
1058
  driver: { kind: "driver_mount", client: undefined as never },
@@ -337,22 +1065,24 @@ export const workspaceMount = defineWorkspaceAgentMount({
337
1065
  ],
338
1066
  });
339
1067
 
340
- const Base${normalized.target.durableObject.className} = createAgentDurableObject<AgentOSTargetEnv>({
1068
+ const Base${target.durableObject.className} = createAgentDurableObject<AgentOSTargetEnv>({
341
1069
  manifest: semanticManifest,
342
- agentBindings: {
1070
+ agentBindings: (env) => ({
343
1071
  handlers: ${handlerRecord},
344
- },
1072
+ ...generatedCapabilityInstallGraphFor(env).agentBindings,
1073
+ }),
345
1074
  refResolver: (env) => ({
346
1075
  material: (ref) => materialValue(env, ref),
347
1076
  }),
348
1077
  llmTransport: () => OpenAiCompatibleLlmTransportLive,
349
- extensions: (env) => workspaceOperationInstallFor(env).extensions,
350
- declaredIntents: (env) => workspaceOperationInstallFor(env).declaredIntents,
351
- projections: (env) => workspaceOperationInstallFor(env).projections,
352
- eventHandlers: (context, env) => workspaceOperationInstallFor(env).eventHandlers(context),
1078
+ extensions: (env) => generatedCapabilityInstallGraphFor(env).extensions,
1079
+ declaredIntents: (env) => generatedCapabilityInstallGraphFor(env).declaredIntents,
1080
+ projections: (env) => generatedCapabilityInstallGraphFor(env).projections,
1081
+ graphStatus: (env) => generatedCapabilityInstallGraphFor(env).graphStatus,
1082
+ eventHandlers: (context, env) => generatedCapabilityInstallGraphFor(env).handlers(context),
353
1083
  });
354
1084
 
355
- export class ${normalized.target.durableObject.className} extends Base${normalized.target.durableObject.className} {
1085
+ export class ${target.durableObject.className} extends Base${target.durableObject.className} {
356
1086
  private readonly targetEnv: AgentOSTargetEnv;
357
1087
 
358
1088
  constructor(ctx: DurableObjectState, env: AgentOSTargetEnv) {
@@ -361,31 +1091,39 @@ export class ${normalized.target.durableObject.className} extends Base${normaliz
361
1091
  }
362
1092
 
363
1093
  override submit(spec: AgentSubmitSpec): Promise<SubmitResult> {
364
- const bindings = generatedSubmitBindingsFor(this.targetEnv);
365
- return bindings.ok
366
- ? this.submitWithBindings(spec, bindings.value)
367
- : rejectTargetFailure(bindings);
1094
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1095
+ bindings.ok ? this.submitWithBindings(spec, bindings.value) : rejectTargetFailure(bindings),
1096
+ );
368
1097
  }
369
1098
 
370
1099
  submitRunInput(input: SubmitRunInput): Promise<SubmitResult> {
371
- const bindings = generatedSubmitBindingsFor(this.targetEnv);
372
- return bindings.ok
373
- ? this.submitWithBindings(submitSpecFromRunInput(input), bindings.value)
374
- : rejectTargetFailure(bindings);
1100
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1101
+ bindings.ok
1102
+ ? this.submitWithBindings(
1103
+ submitSpecFromRunInput(input, bindings.value.dynamicCapabilityProjection),
1104
+ bindings.value,
1105
+ )
1106
+ : rejectTargetFailure(bindings),
1107
+ );
375
1108
  }
376
1109
 
1110
+ ${renderProductApiDurableObjectMethods()}
1111
+ ${hasSchedules ? renderScheduleDurableObjectMethod() : ""}
1112
+
377
1113
  resumeInputRequest(input: WorkspaceAgentResumeInputRequestCommandInput): Promise<SubmitResult> {
378
- const bindings = generatedSubmitBindingsFor(this.targetEnv);
379
- return bindings.ok
380
- ? this.resumeInputRequestWithBindings(input, bindings.value)
381
- : rejectTargetFailure(bindings);
1114
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1115
+ bindings.ok
1116
+ ? this.resumeInputRequestWithBindings(input, bindings.value)
1117
+ : rejectTargetFailure(bindings),
1118
+ );
382
1119
  }
383
1120
 
384
1121
  decideInputRequest(input: WorkspaceAgentDecideInputRequestCommandInput): Promise<SubmitResult> {
385
- const bindings = generatedSubmitBindingsFor(this.targetEnv);
386
- return bindings.ok
387
- ? this.decideInputRequestWithBindings(input, bindings.value)
388
- : rejectTargetFailure(bindings);
1122
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1123
+ bindings.ok
1124
+ ? this.decideInputRequestWithBindings(input, bindings.value)
1125
+ : rejectTargetFailure(bindings),
1126
+ );
389
1127
  }
390
1128
 
391
1129
  customCommand(input: WorkspaceAgentCustomCommandInput): Promise<unknown> {
@@ -452,8 +1190,246 @@ export class ${normalized.target.durableObject.className} extends Base${normaliz
452
1190
  }
453
1191
  `;
454
1192
  };
455
- const renderChatStaticTarget = (normalized, toolNames, modules) => {
1193
+ const renderChatStaticTarget = (normalized, toolNames, modules) => {
1194
+ const target = cloudflareTargetFor(normalized.target);
1195
+ const hasSkills = normalized.skills.length > 0;
1196
+ const hasDynamicCapability = true;
1197
+ const hasSchedules = normalized.schedules.length > 0;
1198
+ const authoredToolNames = new Set(normalized.authoredToolNames);
1199
+ const customToolNames = toolNames.filter((toolName) => authoredToolNames.has(toolName));
1200
+ const toolImports = customToolNames
1201
+ .map((toolName, index) => `import tool_${index} from ${jsString(importToolPath(toolName))};`)
1202
+ .join("\n");
1203
+ const customToolRecord = customToolNames.length === 0
1204
+ ? "{}"
1205
+ : `{\n${customToolNames
1206
+ .map((toolName, index) => ` ${jsString(toolName)}: tool_${index},`)
1207
+ .join("\n")}\n}`;
1208
+ const handlerRecord = `{\n${normalized.deployment.manifest.handlers
1209
+ .map((handler) => ` ${jsString(handler)}: generatedHandler,`)
1210
+ .join("\n")}\n}`;
1211
+ const llmEnvBindings = uniqueLlmMaterialEnvBindings(normalized.llmRoutes);
1212
+ const generatedLlmEnvFields = llmEnvBindings
1213
+ .map((binding) => ` readonly ${binding.envName}?: string;`)
1214
+ .join("\n");
1215
+ const imports = [
1216
+ `import semanticDeclarations from "./manifest.json";`,
1217
+ `import deploymentProvenance from "./deployment.json";`,
1218
+ ...(hasSchedules ? [renderNamedImport(["dispatchGeneratedSchedule"], "./schedules")] : []),
1219
+ renderNamedImport(["createAgentDurableObject"], modules.cloudflareDoRuntime),
1220
+ renderNamedImport(["runDynamicCapabilityResolvers"], modules.runtimeCapability),
1221
+ renderNamedImport(["OpenAiCompatibleLlmTransportLive", "preflightOpenAiCompatibleProviderMaterial"], modules.openAiCompatibleTransport),
1222
+ renderNamedImport(["DYNAMIC_CAPABILITY_EVENT", "manifestTruthIdentity"], modules.runtimeProtocol),
1223
+ renderNamedImport(["projectAgentSession", "projectAgentSessions", "projectWorkflowRun", "projectWorkflowRuns"], modules.runtimeRunProjector),
1224
+ renderNamedImport([
1225
+ "deterministicToolInvocation",
1226
+ ...(hasSkills ? ["defineProductTool"] : []),
1227
+ "unsafeRunToolByName",
1228
+ ], modules.coreTools),
1229
+ renderNamedImport(hasSkills ? ["Effect", "Schema"] : ["Effect"], modules.effect),
1230
+ renderTypeImport(["AgentManifest", "AgentSubmitBindings", "SubmitResult", "SubmitRunInput"], modules.runtimeProtocol),
1231
+ ...(hasDynamicCapability
1232
+ ? [
1233
+ renderTypeImport([
1234
+ "DynamicCapabilityCompiledCatalog",
1235
+ "DynamicCapabilityEventRef",
1236
+ "DynamicCapabilityProjection",
1237
+ "SubmitInstructionFragment",
1238
+ ], modules.runtimeProtocol),
1239
+ renderTypeImport(["DynamicCapabilityResolverDefinition"], modules.runtimeCapability),
1240
+ ]
1241
+ : []),
1242
+ renderTypeImport([
1243
+ "AgentSessionListProjection",
1244
+ "AgentSessionProjection",
1245
+ "WorkflowRunListProjection",
1246
+ "WorkflowRunProjection",
1247
+ ], modules.runtimeRunProjector),
1248
+ renderTypeImport(["AgentSubmitSpec"], modules.cloudflareDoRuntime),
1249
+ ...(hasSchedules ? [renderTypeImport(["GeneratedScheduleTriggerInput"], "./schedules")] : []),
1250
+ renderTypeImport([
1251
+ "WorkspaceAgentCustomCommandInput",
1252
+ "WorkspaceAgentDecideInputRequestCommandInput",
1253
+ "WorkspaceAgentResumeInputRequestCommandInput",
1254
+ ], modules.workspaceAgentHost),
1255
+ renderTypeImport(["Tool"], modules.coreTools),
1256
+ ...(toolImports.length === 0 ? [] : [toolImports]),
1257
+ ].join("\n");
1258
+ return `${imports}
1259
+
1260
+ export const targetDeclarations = semanticDeclarations;
1261
+ export const targetDeployment = deploymentProvenance;
1262
+
1263
+ const semanticManifest = semanticDeclarations as AgentManifest;
1264
+ const semanticTruthIdentity = manifestTruthIdentity(semanticManifest);
1265
+ const generatedHandler = () => undefined;
1266
+
1267
+ type AgentOSTargetEnv = {
1268
+ readonly [binding: string]: unknown;
1269
+ ${generatedLlmEnvFields}
1270
+ };
1271
+
1272
+ type GeneratedTargetFailure = {
1273
+ readonly ok: false;
1274
+ readonly message: string;
1275
+ readonly diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>;
1276
+ };
1277
+
1278
+ type GeneratedTargetResult<Value> =
1279
+ | { readonly ok: true; readonly value: Value }
1280
+ | GeneratedTargetFailure;
1281
+
1282
+ const targetFailure = (
1283
+ message: string,
1284
+ diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>,
1285
+ ): GeneratedTargetFailure => ({
1286
+ ok: false,
1287
+ message,
1288
+ ...(diagnostics === undefined || diagnostics.length === 0 ? {} : { diagnostics }),
1289
+ });
1290
+
1291
+ const rejectTargetFailure = (failure: GeneratedTargetFailure): Promise<never> => {
1292
+ const error = Error(failure.message) as Error & {
1293
+ diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>;
1294
+ };
1295
+ if (failure.diagnostics !== undefined) error.diagnostics = failure.diagnostics;
1296
+ return Promise.reject(error);
1297
+ };
1298
+
1299
+ const generatedCustomTools = ${customToolRecord} satisfies Readonly<Record<string, Tool>>;
1300
+ ${renderDynamicCapabilitySupport(normalized, toolNames, hasSkills)}
1301
+ ${renderSkillSupport(normalized.skills)}
1302
+
1303
+ const materialEnvValue = (env: AgentOSTargetEnv, name: string): string | null => {
1304
+ const value = env[name];
1305
+ return typeof value === "string" && value.length > 0 ? value : null;
1306
+ };
1307
+
1308
+ ${renderMaterialValueFunction(normalized.llmRoutes)}
1309
+ ${renderGeneratedProviderPreflight(normalized.llmRoutes)}
1310
+
1311
+ const requiredStringMaterial = (
1312
+ kind: string,
1313
+ ref: string,
1314
+ value: NonNullable<unknown> | null,
1315
+ ): GeneratedTargetResult<string> => {
1316
+ if (typeof value === "string" && value.length > 0) return { ok: true, value };
1317
+ return targetFailure(\`missing \${kind} material: \${ref}\`);
1318
+ };
1319
+
1320
+ ${renderGeneratedLlmRoutesFor(normalized.llmRoutes)}
1321
+
1322
+ const generatedSubmitBindingsFor = async (
1323
+ env: AgentOSTargetEnv,
1324
+ event: DynamicCapabilityEventRef = generatedDynamicCapabilityTurnEvent(),
1325
+ ): Promise<GeneratedTargetResult<AgentSubmitBindings>> => {
1326
+ const preflightDiagnostics = generatedProviderPreflightDiagnosticsFor(env);
1327
+ if (preflightDiagnostics.length > 0) {
1328
+ return targetFailure(
1329
+ "OpenAI-compatible provider material preflight failed",
1330
+ preflightDiagnostics,
1331
+ );
1332
+ }
1333
+ const routes = generatedLlmRoutesFor(env);
1334
+ if (!routes.ok) return routes;
1335
+ const dynamicBindings = await generatedDynamicSubmitBindingsFor(event);
1336
+ if (!dynamicBindings.ok) return dynamicBindings;
1337
+ const dynamicCapabilityProjection = dynamicBindings.value.dynamicCapabilityProjection;
1338
+ return {
1339
+ ok: true,
1340
+ value: {
1341
+ ...dynamicBindings.value,
1342
+ llmRoutes: routes.value,
1343
+ tools: ${hasSkills
1344
+ ? `{
1345
+ ...generatedCustomTools,
1346
+ ...generatedFrameworkToolsFor(dynamicCapabilityProjection),
1347
+ }`
1348
+ : "generatedCustomTools"},
1349
+ },
1350
+ };
1351
+ };
1352
+
1353
+ ${renderSubmitSpecFromRunInput(hasSkills)}
1354
+
1355
+ ${renderProductApiHelpers()}
1356
+ ${hasSchedules ? renderScheduleDurableObjectHelpers() : ""}
1357
+
1358
+ const Base${target.durableObject.className} = createAgentDurableObject<AgentOSTargetEnv>({
1359
+ manifest: semanticManifest,
1360
+ agentBindings: {
1361
+ handlers: ${handlerRecord},
1362
+ },
1363
+ refResolver: (env) => ({
1364
+ material: (ref) => materialValue(env, ref),
1365
+ }),
1366
+ llmTransport: () => OpenAiCompatibleLlmTransportLive,
1367
+ });
1368
+
1369
+ export class ${target.durableObject.className} extends Base${target.durableObject.className} {
1370
+ private readonly targetEnv: AgentOSTargetEnv;
1371
+
1372
+ constructor(ctx: DurableObjectState, env: AgentOSTargetEnv) {
1373
+ super(ctx, env);
1374
+ this.targetEnv = env;
1375
+ }
1376
+
1377
+ override submit(spec: AgentSubmitSpec): Promise<SubmitResult> {
1378
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1379
+ bindings.ok ? this.submitWithBindings(spec, bindings.value) : rejectTargetFailure(bindings),
1380
+ );
1381
+ }
1382
+
1383
+ submitRunInput(input: SubmitRunInput): Promise<SubmitResult> {
1384
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1385
+ bindings.ok
1386
+ ? this.submitWithBindings(
1387
+ submitSpecFromRunInput(input, bindings.value.dynamicCapabilityProjection),
1388
+ bindings.value,
1389
+ )
1390
+ : rejectTargetFailure(bindings),
1391
+ );
1392
+ }
1393
+
1394
+ ${renderProductApiDurableObjectMethods()}
1395
+ ${hasSchedules ? renderScheduleDurableObjectMethod() : ""}
1396
+
1397
+ resumeInputRequest(input: WorkspaceAgentResumeInputRequestCommandInput): Promise<SubmitResult> {
1398
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1399
+ bindings.ok
1400
+ ? this.resumeInputRequestWithBindings(input, bindings.value)
1401
+ : rejectTargetFailure(bindings),
1402
+ );
1403
+ }
1404
+
1405
+ decideInputRequest(input: WorkspaceAgentDecideInputRequestCommandInput): Promise<SubmitResult> {
1406
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1407
+ bindings.ok
1408
+ ? this.decideInputRequestWithBindings(input, bindings.value)
1409
+ : rejectTargetFailure(bindings),
1410
+ );
1411
+ }
1412
+
1413
+ customCommand(input: WorkspaceAgentCustomCommandInput): Promise<unknown> {
1414
+ return Effect.runPromise(
1415
+ unsafeRunToolByName(
1416
+ generatedCustomTools,
1417
+ deterministicToolInvocation(input.method, input.input),
1418
+ ),
1419
+ );
1420
+ }
1421
+ }
1422
+ `;
1423
+ };
1424
+ const renderLocalAgentApp = (normalized, toolNames, modules) => {
1425
+ if (normalized.target.kind !== AGENTOS_CONFIG_TARGET.NODE_V1) {
1426
+ throw new TypeError(`local agent app renderer received ${normalized.target.kind}`);
1427
+ }
1428
+ const hasChannels = normalized.channels.length > 0;
1429
+ const hasSkills = normalized.skills.length > 0;
1430
+ const hasSchedules = normalized.schedules.length > 0;
456
1431
  const authoredToolNames = new Set(normalized.authoredToolNames);
1432
+ const workspaceToolList = toolNames.filter((toolName) => isWorkspaceToolName(toolName) && !authoredToolNames.has(toolName));
457
1433
  const customToolNames = toolNames.filter((toolName) => authoredToolNames.has(toolName));
458
1434
  const toolImports = customToolNames
459
1435
  .map((toolName, index) => `import tool_${index} from ${jsString(importToolPath(toolName))};`)
@@ -463,42 +1439,69 @@ const renderChatStaticTarget = (normalized, toolNames, modules) => {
463
1439
  : `{\n${customToolNames
464
1440
  .map((toolName, index) => ` ${jsString(toolName)}: tool_${index},`)
465
1441
  .join("\n")}\n}`;
466
- const handlerRecord = `{\n${normalized.deployment.manifest.handlers
467
- .map((handler) => ` ${jsString(handler)}: generatedHandler,`)
468
- .join("\n")}\n}`;
1442
+ const workspaceToolArray = `[${workspaceToolList.map(jsString).join(", ")}] as const`;
1443
+ const usesMutationTools = workspaceToolList.some((toolName) => workspaceMutationToolNames.has(toolName));
1444
+ const usesShellTools = workspaceToolList.some((toolName) => workspaceShellToolNames.has(toolName));
469
1445
  const llmEnvByKind = Object.fromEntries(llmMaterialEnvBindings(normalized.llm).map((binding) => [binding.kind, binding.envName]));
470
- const generatedLlmEnvFields = Object.values(llmEnvByKind)
471
- .map((envName) => ` readonly ${envName}?: string;`)
472
- .join("\n");
473
1446
  const imports = [
474
1447
  `import semanticDeclarations from "./manifest.json";`,
475
- `import deploymentProvenance from "./deployment.json";`,
476
- renderNamedImport(["createAgentDurableObject"], modules.cloudflareDoRuntime),
477
- renderNamedImport(["OpenAiCompatibleLlmTransportLive"], modules.openAiCompatibleTransport),
478
- renderNamedImport(["deterministicToolInvocation", "unsafeRunToolByName"], modules.coreTools),
479
- renderNamedImport(["Effect"], modules.effect),
480
- renderTypeImport(["AgentManifest", "AgentSubmitBindings", "SubmitResult", "SubmitRunInput"], modules.runtimeProtocol),
481
- renderTypeImport(["AgentSubmitSpec"], modules.cloudflareDoRuntime),
1448
+ ...(hasChannels ? [renderNamedImport(["dispatchGeneratedChannelRequest"], "./channels")] : []),
1449
+ ...(hasChannels ? [renderTypeImport(["ChannelRuntime"], modules.runtimeChannel)] : []),
1450
+ ...(hasSchedules
1451
+ ? [
1452
+ renderNamedImport(["dispatchGeneratedSchedule", "generatedScheduleDefinitions", "generatedScheduleIds"], "./schedules"),
1453
+ ]
1454
+ : []),
1455
+ ...(hasSchedules ? [renderTypeImport(["GeneratedScheduleTriggerInput"], "./schedules")] : []),
1456
+ renderNamedImport(["lowerLocalAgentRuntime"], modules.localRuntime),
1457
+ renderNamedImport(["runDynamicCapabilityResolvers"], modules.runtimeCapability),
1458
+ ...(hasSchedules
1459
+ ? [renderNamedImport(["projectScheduleFireHistory"], modules.runtimeSchedule)]
1460
+ : []),
1461
+ renderNamedImport(["DYNAMIC_CAPABILITY_EVENT", "manifestTruthIdentity"], modules.runtimeProtocol),
1462
+ renderNamedImport(["OpenAiCompatibleLlmTransportLive", "preflightOpenAiCompatibleProviderMaterial"], modules.openAiCompatibleTransport),
1463
+ renderNamedImport(["projectAgentSession", "projectAgentSessions", "projectWorkflowRun", "projectWorkflowRuns"], modules.runtimeRunProjector),
1464
+ renderTypeImport(["AgentManifest", "SubmitResult", "SubmitRunInput"], modules.runtimeProtocol),
482
1465
  renderTypeImport([
483
- "WorkspaceAgentCustomCommandInput",
484
- "WorkspaceAgentDecideInputRequestCommandInput",
485
- "WorkspaceAgentResumeInputRequestCommandInput",
486
- ], modules.workspaceAgentHost),
1466
+ "AgentSubmitBindings",
1467
+ "DynamicCapabilityCompiledCatalog",
1468
+ "DynamicCapabilityEventRef",
1469
+ "DynamicCapabilityProjection",
1470
+ "SubmitInstructionFragment",
1471
+ ], modules.runtimeProtocol),
1472
+ renderTypeImport(["DynamicCapabilityResolverDefinition"], modules.runtimeCapability),
1473
+ ...(hasSchedules
1474
+ ? [
1475
+ renderTypeImport([
1476
+ "ScheduleDefinitionProjection",
1477
+ "ScheduleFireHistoryProjection",
1478
+ "ScheduleFireProjection",
1479
+ ], modules.runtimeSchedule),
1480
+ ]
1481
+ : []),
1482
+ renderTypeImport([
1483
+ "AgentSessionListProjection",
1484
+ "AgentSessionProjection",
1485
+ "WorkflowRunListProjection",
1486
+ "WorkflowRunProjection",
1487
+ ], modules.runtimeRunProjector),
1488
+ renderTypeImport(["CreateLocalAgentRuntimeOptions", "LocalAgentRuntime", "LocalAgentSubmitInput"], modules.localRuntime),
1489
+ renderTypeImport(["WorkspaceAgentCustomCommandInput"], modules.workspaceAgentHost),
1490
+ renderNamedImport([
1491
+ ...(hasSkills ? ["defineProductTool"] : []),
1492
+ "deterministicToolInvocation",
1493
+ "unsafeRunToolByName",
1494
+ ], modules.coreTools),
1495
+ renderNamedImport(hasSkills ? ["Effect", "Schema"] : ["Effect"], modules.effect),
487
1496
  renderTypeImport(["Tool"], modules.coreTools),
488
1497
  ...(toolImports.length === 0 ? [] : [toolImports]),
489
1498
  ].join("\n");
490
1499
  return `${imports}
491
1500
 
492
- export const targetDeclarations = semanticDeclarations;
493
- export const targetDeployment = deploymentProvenance;
494
-
495
1501
  const semanticManifest = semanticDeclarations as AgentManifest;
496
- const generatedHandler = () => undefined;
1502
+ const semanticTruthIdentity = manifestTruthIdentity(semanticManifest);
497
1503
 
498
- type AgentOSTargetEnv = {
499
- readonly [binding: string]: unknown;
500
- ${generatedLlmEnvFields}
501
- };
1504
+ type AgentOSTargetEnv = Readonly<Record<string, string | undefined>>;
502
1505
 
503
1506
  type GeneratedTargetFailure = {
504
1507
  readonly ok: false;
@@ -509,12 +1512,33 @@ type GeneratedTargetResult<Value> =
509
1512
  | { readonly ok: true; readonly value: Value }
510
1513
  | GeneratedTargetFailure;
511
1514
 
512
- const targetFailure = (message: string): GeneratedTargetFailure => ({ ok: false, message });
1515
+ const targetFailure = (message: string): GeneratedTargetFailure => ({
1516
+ ok: false,
1517
+ message,
1518
+ });
513
1519
 
514
1520
  const rejectTargetFailure = (failure: GeneratedTargetFailure): Promise<never> =>
515
1521
  Promise.reject(Error(failure.message));
516
1522
 
1523
+ ${renderGeneratedWorkspaceOperations(workspaceToolArray, usesMutationTools, usesShellTools)}
517
1524
  const generatedCustomTools = ${customToolRecord} satisfies Readonly<Record<string, Tool>>;
1525
+ ${renderDynamicCapabilitySupport(normalized, toolNames, hasSkills)}
1526
+ ${renderSkillSupport(normalized.skills)}
1527
+
1528
+ const cleanEnv = (source: AgentOSTargetEnv): Record<string, string> => {
1529
+ const env: Record<string, string> = {};
1530
+ for (const [key, value] of Object.entries(source)) {
1531
+ if (value !== undefined) env[key] = value;
1532
+ }
1533
+ return env;
1534
+ };
1535
+
1536
+ const generatedTargetEnvFor = (
1537
+ options: Pick<CreateLocalAgentAppOptions, "env" | "inheritEnv">,
1538
+ ): AgentOSTargetEnv => ({
1539
+ ...(options.inheritEnv === true ? cleanEnv(process.env) : {}),
1540
+ ...(options.env === undefined ? {} : cleanEnv(options.env)),
1541
+ });
518
1542
 
519
1543
  const materialEnvValue = (env: AgentOSTargetEnv, name: string): string | null => {
520
1544
  const value = env[name];
@@ -537,124 +1561,209 @@ const materialValue = (
537
1561
  return null;
538
1562
  };
539
1563
 
540
- const requiredStringMaterial = (
541
- kind: string,
542
- ref: string,
543
- value: NonNullable<unknown> | null,
544
- ): GeneratedTargetResult<string> => {
545
- if (typeof value === "string" && value.length > 0) return { ok: true, value };
546
- return targetFailure(\`missing \${kind} material: \${ref}\`);
547
- };
548
-
549
- const generatedLlmRouteFor = (env: AgentOSTargetEnv): GeneratedTargetResult<NonNullable<AgentSubmitBindings["llmRoutes"]>["default"]> => {
550
- const modelId = requiredStringMaterial(
551
- "model",
552
- ${jsString(normalized.llm.modelRef)},
553
- materialValue(env, { kind: "model", ref: ${jsString(normalized.llm.modelRef)} }),
554
- );
555
- if (!modelId.ok) return modelId;
1564
+ const generatedLocalLlmFor = (
1565
+ env: AgentOSTargetEnv,
1566
+ ): NonNullable<CreateLocalAgentRuntimeOptions["llm"]> => {
1567
+ const modelValue = materialValue(env, { kind: "model", ref: ${jsString(normalized.llm.modelRef)} });
556
1568
  return {
557
- ok: true,
558
- value: {
1569
+ kind: "transport",
1570
+ transport: OpenAiCompatibleLlmTransportLive,
1571
+ route: {
559
1572
  kind: "openai-chat-compatible",
560
1573
  endpointRef: ${jsString(normalized.llm.endpointRef)},
561
1574
  credentialRef: ${jsString(normalized.llm.credentialRef)},
562
- modelId: modelId.value,
1575
+ modelId: typeof modelValue === "string" ? modelValue : "",
563
1576
  },
1577
+ refResolver: {
1578
+ material: (ref) => materialValue(env, ref),
1579
+ },
1580
+ preflight: preflightOpenAiCompatibleProviderMaterial,
564
1581
  };
565
1582
  };
566
1583
 
567
- const generatedSubmitBindingsFor = (env: AgentOSTargetEnv): GeneratedTargetResult<AgentSubmitBindings> => {
568
- const route = generatedLlmRouteFor(env);
569
- if (!route.ok) return route;
1584
+ ${renderProductApiHelpers()}
1585
+
1586
+ const generatedLocalSubmitInputFromRunInput = async (
1587
+ input: SubmitRunInput,
1588
+ event: DynamicCapabilityEventRef = generatedDynamicCapabilityTurnEvent(),
1589
+ ): Promise<LocalAgentSubmitInput> => {
1590
+ const dynamicBindings = await generatedDynamicSubmitBindingsFor(event);
1591
+ if (!dynamicBindings.ok) return rejectTargetFailure(dynamicBindings);
1592
+ const dynamicCapabilityProjection = dynamicBindings.value.dynamicCapabilityProjection;
570
1593
  return {
571
- ok: true,
572
- value: {
573
- llmRoutes: {
574
- default: route.value,
575
- },
576
- tools: generatedCustomTools,
577
- },
1594
+ ...input,
1595
+ ...(input.context === undefined ? {} : { context: input.context }),
1596
+ ...(input.system === undefined && !${hasSkills} ? {} : {
1597
+ system: ${hasSkills ? "generatedSystemPrompt(input.system, dynamicCapabilityProjection)" : "input.system"},
1598
+ }),
1599
+ dynamicCapabilityProjection,
1600
+ instructionFragments: dynamicBindings.value.instructionFragments,
1601
+ tools: ${hasSkills
1602
+ ? `{
1603
+ ...generatedCustomTools,
1604
+ ...generatedFrameworkToolsFor(dynamicCapabilityProjection),
1605
+ }`
1606
+ : "generatedCustomTools"},
578
1607
  };
579
1608
  };
580
1609
 
581
- const submitSpecFromRunInput = (input: SubmitRunInput): AgentSubmitSpec => ({
582
- input,
583
- intent: input.intent,
584
- context: input.context,
585
- ...(input.system === undefined ? {} : { system: input.system }),
586
- ...(input.budget === undefined ? {} : { budget: input.budget }),
587
- ...(input.outputSchema === undefined ? {} : { outputSchema: input.outputSchema }),
588
- ...(input.traceContext === undefined ? {} : { traceContext: input.traceContext }),
589
- ...(input.materials === undefined ? {} : { materials: input.materials }),
590
- ...(input.toolContext === undefined ? {} : { toolContext: input.toolContext }),
591
- ...(input.toolPolicy === undefined ? {} : { toolPolicy: input.toolPolicy }),
592
- ...(input.decisionInterrupts === undefined ? {} : { decisionInterrupts: input.decisionInterrupts }),
593
- ...(input.resume === undefined ? {} : { resume: input.resume }),
594
- });
595
-
596
- const Base${normalized.target.durableObject.className} = createAgentDurableObject<AgentOSTargetEnv>({
597
- manifest: semanticManifest,
598
- agentBindings: {
599
- handlers: ${handlerRecord},
600
- },
601
- refResolver: (env) => ({
602
- material: (ref) => materialValue(env, ref),
603
- }),
604
- llmTransport: () => OpenAiCompatibleLlmTransportLive,
605
- });
606
-
607
- export class ${normalized.target.durableObject.className} extends Base${normalized.target.durableObject.className} {
608
- private readonly targetEnv: AgentOSTargetEnv;
609
-
610
- constructor(ctx: DurableObjectState, env: AgentOSTargetEnv) {
611
- super(ctx, env);
612
- this.targetEnv = env;
613
- }
614
-
615
- override submit(spec: AgentSubmitSpec): Promise<SubmitResult> {
616
- const bindings = generatedSubmitBindingsFor(this.targetEnv);
617
- return bindings.ok
618
- ? this.submitWithBindings(spec, bindings.value)
619
- : rejectTargetFailure(bindings);
620
- }
621
-
622
- submitRunInput(input: SubmitRunInput): Promise<SubmitResult> {
623
- const bindings = generatedSubmitBindingsFor(this.targetEnv);
624
- return bindings.ok
625
- ? this.submitWithBindings(submitSpecFromRunInput(input), bindings.value)
626
- : rejectTargetFailure(bindings);
627
- }
628
-
629
- resumeInputRequest(input: WorkspaceAgentResumeInputRequestCommandInput): Promise<SubmitResult> {
630
- const bindings = generatedSubmitBindingsFor(this.targetEnv);
631
- return bindings.ok
632
- ? this.resumeInputRequestWithBindings(input, bindings.value)
633
- : rejectTargetFailure(bindings);
634
- }
1610
+ export interface LocalAgentApp {
1611
+ readonly runtime: LocalAgentRuntime;
1612
+ readonly sessions: {
1613
+ readonly submitTurn: (input: AgentSessionSubmitTurnInput) => Promise<SubmitResult>;
1614
+ readonly inspect: (sessionRef: string) => AgentSessionProjection;
1615
+ readonly list: () => AgentSessionListProjection;
1616
+ };
1617
+ readonly workflows: {
1618
+ readonly run: (input: AgentWorkflowRunInput) => Promise<SubmitResult>;
1619
+ readonly inspectRun: (
1620
+ workflowId: string,
1621
+ workflowRunId: string,
1622
+ ) => WorkflowRunProjection | null;
1623
+ readonly listRuns: (workflowId: string) => WorkflowRunListProjection;
1624
+ };
1625
+ ${hasChannels
1626
+ ? `readonly channels: {
1627
+ readonly handle: (request: Request) => Promise<Response | null>;
1628
+ };`
1629
+ : ""}
1630
+ readonly customCommand: (input: WorkspaceAgentCustomCommandInput) => Promise<unknown>;
1631
+ ${hasSchedules
1632
+ ? `readonly schedules: {
1633
+ readonly ids: ReadonlyArray<string>;
1634
+ readonly list: () => ReadonlyArray<ScheduleDefinitionProjection>;
1635
+ readonly trigger: (input: GeneratedScheduleTriggerInput) => Promise<ScheduleFireProjection>;
1636
+ readonly history: (input?: { readonly scheduleId?: string }) => ScheduleFireHistoryProjection;
1637
+ };`
1638
+ : ""}
1639
+ }
635
1640
 
636
- decideInputRequest(input: WorkspaceAgentDecideInputRequestCommandInput): Promise<SubmitResult> {
637
- const bindings = generatedSubmitBindingsFor(this.targetEnv);
638
- return bindings.ok
639
- ? this.decideInputRequestWithBindings(input, bindings.value)
640
- : rejectTargetFailure(bindings);
641
- }
1641
+ ${hasChannels
1642
+ ? `export const handleLocalAgentChannelRequest = (
1643
+ request: Request,
1644
+ runtime: ChannelRuntime,
1645
+ ): Promise<Response | null> => dispatchGeneratedChannelRequest(request, runtime);`
1646
+ : ""}
1647
+
1648
+ export interface CreateLocalAgentAppOptions {
1649
+ readonly cwd?: string;
1650
+ readonly env?: CreateLocalAgentRuntimeOptions["env"];
1651
+ readonly inheritEnv?: CreateLocalAgentRuntimeOptions["inheritEnv"];
1652
+ readonly llm?: CreateLocalAgentRuntimeOptions["llm"];
1653
+ }
642
1654
 
643
- customCommand(input: WorkspaceAgentCustomCommandInput): Promise<unknown> {
644
- return Effect.runPromise(
1655
+ export const createLocalAgentApp = async (
1656
+ options: CreateLocalAgentAppOptions = {},
1657
+ ): Promise<LocalAgentApp> => {
1658
+ const targetEnv = generatedTargetEnvFor(options);
1659
+ const lowered = await lowerLocalAgentRuntime({
1660
+ target: "node@1",
1661
+ identity: semanticManifest.agentId,
1662
+ truthIdentity: semanticTruthIdentity,
1663
+ cwd: options.cwd ?? process.cwd(),
1664
+ ...(options.env === undefined ? {} : { env: options.env }),
1665
+ ...(options.inheritEnv === undefined ? {} : { inheritEnv: options.inheritEnv }),
1666
+ llm: options.llm ?? generatedLocalLlmFor(targetEnv),
1667
+ workspaceOperations: generatedWorkspaceOperations,
1668
+ });
1669
+ const sessions = {
1670
+ submitTurn: (input: AgentSessionSubmitTurnInput) =>
1671
+ generatedLocalSubmitInputFromRunInput(
1672
+ submitRunInputFromSessionTurn(input),
1673
+ generatedDynamicCapabilityTurnEvent({
1674
+ sessionRef: input.sessionRef,
1675
+ turnRef: input.turnRef,
1676
+ }),
1677
+ ).then((submitInput) =>
1678
+ lowered.submitWithProductLink(submitInput, {
1679
+ kind: "session_turn",
1680
+ sessionRef: input.sessionRef,
1681
+ turnRef: input.turnRef,
1682
+ ...(input.idempotencyKey === undefined ? {} : { idempotencyKey: input.idempotencyKey }),
1683
+ }),
1684
+ ),
1685
+ inspect: (sessionRef: string) => projectAgentSession(lowered.runtime.events(), sessionRef),
1686
+ list: () => projectAgentSessions(lowered.runtime.events()),
1687
+ };
1688
+ const workflows = {
1689
+ run: (input: AgentWorkflowRunInput) =>
1690
+ generatedLocalSubmitInputFromRunInput(submitRunInputFromWorkflowRun(input)).then(
1691
+ (submitInput) =>
1692
+ lowered.submitWithProductLink(submitInput, {
1693
+ kind: "workflow_run",
1694
+ workflowId: input.workflowId,
1695
+ workflowRunId: input.workflowRunId,
1696
+ ...(input.idempotencyKey === undefined ? {} : { idempotencyKey: input.idempotencyKey }),
1697
+ ...(input.inputDigest === undefined ? {} : { inputDigest: input.inputDigest }),
1698
+ }),
1699
+ ),
1700
+ inspectRun: (workflowId: string, workflowRunId: string) =>
1701
+ projectWorkflowRun(lowered.runtime.events(), workflowId, workflowRunId),
1702
+ listRuns: (workflowId: string) => projectWorkflowRuns(lowered.runtime.events(), workflowId),
1703
+ };
1704
+ ${hasChannels
1705
+ ? `const channelRuntime: ChannelRuntime = {
1706
+ submit: (input) => lowered.runtime.submit(input),
1707
+ dispatch: async () => {
1708
+ throw new Error("local node channel dispatch is unavailable");
1709
+ },
1710
+ };
1711
+ const channels = {
1712
+ handle: (request: Request) => handleLocalAgentChannelRequest(request, channelRuntime),
1713
+ };`
1714
+ : ""}
1715
+ const customCommand = (input: WorkspaceAgentCustomCommandInput): Promise<unknown> =>
1716
+ Effect.runPromise(
645
1717
  unsafeRunToolByName(
646
1718
  generatedCustomTools,
647
1719
  deterministicToolInvocation(input.method, input.input),
648
1720
  ),
649
1721
  );
650
- }
651
- }
1722
+ ${hasSchedules
1723
+ ? `const scheduleHistory = (
1724
+ input: { readonly scheduleId?: string } = {},
1725
+ ): ScheduleFireHistoryProjection => projectScheduleFireHistory(lowered.runtime.events(), input);
1726
+ const triggerSchedule = async (
1727
+ input: GeneratedScheduleTriggerInput,
1728
+ ): Promise<ScheduleFireProjection> => {
1729
+ const result = await dispatchGeneratedSchedule({
1730
+ ...input,
1731
+ identity: semanticTruthIdentity,
1732
+ runtime: { sessions, workflows },
1733
+ });
1734
+ await lowered.commitScheduleFireDispatch(result);
1735
+ const projected = scheduleHistory({ scheduleId: input.scheduleId }).fires.find(
1736
+ (fire) => fire.fireId === result.fireId,
1737
+ );
1738
+ if (projected === undefined) {
1739
+ throw new Error(\`schedule fire projection missing after commit: \${result.fireId}\`);
1740
+ }
1741
+ return projected;
1742
+ };`
1743
+ : ""}
1744
+ return {
1745
+ runtime: lowered.runtime,
1746
+ sessions,
1747
+ workflows,
1748
+ ${hasChannels ? "channels,\n " : ""}customCommand,
1749
+ ${hasSchedules
1750
+ ? `schedules: {
1751
+ ids: generatedScheduleIds,
1752
+ list: () => generatedScheduleDefinitions,
1753
+ trigger: triggerSchedule,
1754
+ history: scheduleHistory,
1755
+ },`
1756
+ : ""}
1757
+ };
1758
+ };
652
1759
  `;
653
1760
  };
654
1761
  const renderStaticTarget = (normalized, toolNames, modules) => normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
655
1762
  ? renderWorkspaceStaticTarget(normalized, toolNames, modules)
656
1763
  : renderChatStaticTarget(normalized, toolNames, modules);
657
- const renderCloudflareScopeHelper = (normalized, modules) => `${renderNamedImport(["durableObjectRpcClient"], `${modules.cloudflareDoRuntime}/do-rpc`)}
1764
+ const renderCloudflareScopeHelper = (normalized, modules) => {
1765
+ const target = cloudflareTargetFor(normalized.target);
1766
+ return `${renderNamedImport(["durableObjectRpcClient"], `${modules.cloudflareDoRuntime}/do-rpc`)}
658
1767
  ${renderNamedImport(["manifestTruthIdentity"], modules.runtimeProtocol)}
659
1768
  ${renderTypeImport(["AgentRuntimeClient"], modules.cloudflareDoRuntime)}
660
1769
  ${renderTypeImport(["DurableObjectRpcClient"], `${modules.cloudflareDoRuntime}/do-rpc`)}
@@ -667,7 +1776,7 @@ export type AgentOSTargetEnv = {
667
1776
 
668
1777
  export const agentOSTruthIdentity = manifestTruthIdentity(manifest as AgentManifest);
669
1778
  export const agentOSScopeId = agentOSTruthIdentity.scopeRef.scopeId;
670
- export const agentOSDurableObjectBinding = ${jsString(normalized.target.durableObject.binding)};
1779
+ export const agentOSDurableObjectBinding = ${jsString(target.durableObject.binding)};
671
1780
 
672
1781
  export const agentOSDurableObjectNamespace = (
673
1782
  env: AgentOSTargetEnv,
@@ -681,18 +1790,79 @@ export const agentOSRpcClient = <
681
1790
  scopeId: string = agentOSScopeId,
682
1791
  ): DurableObjectRpcClient<Rpc> => durableObjectRpcClient<Rpc>(agentOSDurableObjectNamespace(env), scopeId);
683
1792
  `;
684
- const renderCloudflareWorkerEntry = (normalized, modules) => `${normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1 ? `${renderNamedImport(["Sandbox"], modules.cloudflareSandbox)}\n` : ""}${renderNamedImport([normalized.target.durableObject.className], "./target")}
685
- ${renderTypeImport(["AgentOSTargetEnv"], "./cloudflare-scope")}
1793
+ };
1794
+ const renderCloudflareWorkerEntry = (normalized, modules) => {
1795
+ const target = cloudflareTargetFor(normalized.target);
1796
+ const hasChannels = normalized.channels.length > 0;
1797
+ const hasSchedules = normalized.schedules.length > 0;
1798
+ const cloudflareScopeImports = [
1799
+ ...(hasChannels || hasSchedules ? ["agentOSRpcClient"] : []),
1800
+ ...(hasSchedules ? ["agentOSScopeId"] : []),
1801
+ ];
1802
+ return `${normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1 ? `${renderNamedImport(["Sandbox"], modules.cloudflareSandbox)}\n` : ""}${renderNamedImport([target.durableObject.className], "./target")}
1803
+ ${hasChannels ? `${renderNamedImport(["dispatchGeneratedChannelRequest"], "./channels")}\n${renderTypeImport(["AgentRuntimeClient"], modules.cloudflareDoRuntime)}\n${renderTypeImport(["ChannelRuntime"], modules.runtimeChannel)}\n` : ""}${hasSchedules ? `${renderNamedImport(["generatedSchedules"], "./schedules")}\n${renderTypeImport(["GeneratedScheduleTriggerInput"], "./schedules")}\n` : ""}${cloudflareScopeImports.length === 0 ? "" : `${renderNamedImport(cloudflareScopeImports, "./cloudflare-scope")}\n`}${renderTypeImport(["AgentOSTargetEnv"], "./cloudflare-scope")}
1804
+
1805
+ export { ${target.durableObject.className}${normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1 ? ", Sandbox" : ""} };
1806
+
1807
+ ${hasChannels
1808
+ ? `type AgentOSChannelRpc = Pick<AgentRuntimeClient, "events" | "streamEvents"> & {
1809
+ readonly submitRunInput: ChannelRuntime["submit"];
1810
+ readonly dispatchToScope: ChannelRuntime["dispatch"];
1811
+ };
1812
+
1813
+ const generatedChannelRuntimeFor = (env: AgentOSTargetEnv): ChannelRuntime => {
1814
+ const runtime = agentOSRpcClient<AgentOSChannelRpc>(env);
1815
+ return Object.freeze({
1816
+ submit: (input) => runtime.submitRunInput(input),
1817
+ dispatch: (spec) => runtime.dispatchToScope(spec),
1818
+ });
1819
+ };
1820
+ `
1821
+ : ""}
1822
+ ${hasSchedules
1823
+ ? `type AgentOSScheduleRpc = {
1824
+ readonly dispatchSchedule: (input: GeneratedScheduleTriggerInput) => Promise<unknown>;
1825
+ };
1826
+
1827
+ const generatedScheduleAppPrincipal: GeneratedScheduleTriggerInput["appPrincipal"] = {
1828
+ authority: "agentos.app",
1829
+ subject: agentOSScopeId,
1830
+ };
686
1831
 
687
- export { ${normalized.target.durableObject.className}${normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1 ? ", Sandbox" : ""} };
1832
+ const generatedScheduleInputsFor = (
1833
+ controller: ScheduledController,
1834
+ ): ReadonlyArray<GeneratedScheduleTriggerInput> =>
1835
+ generatedSchedules
1836
+ .filter((entry) => entry.cron === controller.cron)
1837
+ .map((entry) => ({
1838
+ scheduleId: entry.scheduleId,
1839
+ scheduledAt: controller.scheduledTime,
1840
+ appPrincipal: generatedScheduleAppPrincipal,
1841
+ }));
1842
+ `
1843
+ : ""}
688
1844
 
689
1845
  export default {
690
- fetch(): Response {
1846
+ async fetch(request: Request, env: AgentOSTargetEnv): Promise<Response> {
1847
+ ${hasChannels
1848
+ ? `const channelResponse = await dispatchGeneratedChannelRequest(request, generatedChannelRuntimeFor(env));
1849
+ if (channelResponse !== null) return channelResponse;`
1850
+ : ""}
691
1851
  return new Response("agentOS Cloudflare target", { status: 404 });
692
1852
  },
1853
+ ${hasSchedules
1854
+ ? `scheduled(controller: ScheduledController, env: AgentOSTargetEnv, ctx: ExecutionContext): void {
1855
+ const runtime = agentOSRpcClient<AgentOSScheduleRpc>(env);
1856
+ for (const input of generatedScheduleInputsFor(controller)) {
1857
+ ctx.waitUntil(runtime.dispatchSchedule(input));
1858
+ }
1859
+ },`
1860
+ : ""}
693
1861
  } satisfies ExportedHandler<AgentOSTargetEnv>;
694
1862
  `;
1863
+ };
695
1864
  const renderCloudflareWranglerConfig = (normalized) => {
1865
+ const target = cloudflareTargetFor(normalized.target);
696
1866
  const workspaceConfig = normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
697
1867
  ? {
698
1868
  vars: {
@@ -713,15 +1883,15 @@ const renderCloudflareWranglerConfig = (normalized) => {
713
1883
  name: normalized.workspace.binding,
714
1884
  },
715
1885
  {
716
- class_name: normalized.target.durableObject.className,
717
- name: normalized.target.durableObject.binding,
1886
+ class_name: target.durableObject.className,
1887
+ name: target.durableObject.binding,
718
1888
  },
719
1889
  ],
720
1890
  },
721
1891
  migrations: [
722
1892
  {
723
1893
  tag: "v1",
724
- new_sqlite_classes: ["Sandbox", normalized.target.durableObject.className],
1894
+ new_sqlite_classes: ["Sandbox", target.durableObject.className],
725
1895
  },
726
1896
  ],
727
1897
  }
@@ -729,15 +1899,15 @@ const renderCloudflareWranglerConfig = (normalized) => {
729
1899
  durable_objects: {
730
1900
  bindings: [
731
1901
  {
732
- class_name: normalized.target.durableObject.className,
733
- name: normalized.target.durableObject.binding,
1902
+ class_name: target.durableObject.className,
1903
+ name: target.durableObject.binding,
734
1904
  },
735
1905
  ],
736
1906
  },
737
1907
  migrations: [
738
1908
  {
739
1909
  tag: "v1",
740
- new_sqlite_classes: [normalized.target.durableObject.className],
1910
+ new_sqlite_classes: [target.durableObject.className],
741
1911
  },
742
1912
  ],
743
1913
  };
@@ -759,6 +1929,11 @@ const generatedClientModuleImports = (normalized, modules) => [
759
1929
  "createWorkspaceAgentClientBridge",
760
1930
  "CreateWorkspaceAgentClientOptions",
761
1931
  "WorkspaceAgentClientBridge",
1932
+ "WorkspaceAgentProductClient",
1933
+ "WorkspaceAgentProductCommandMap",
1934
+ "WorkspaceAgentProductProjectionTypes",
1935
+ "WorkspaceAgentProductCommandOutputByName",
1936
+ "WORKSPACE_AGENT_PRODUCT_COMMAND",
762
1937
  ]
763
1938
  : [
764
1939
  "WORKSPACE_AGENT_COMMAND",
@@ -807,11 +1982,18 @@ const renderWorkspaceSvelteKitRemote = (normalized, modules) => `${renderNamedIm
807
1982
  ${renderNamedImport(["decodeSseHttpEvents", "responseToSseHttpChunks"], modules.sseHttp)}
808
1983
  ${renderNamedImport(["Result", "Schema"], modules.effect)}
809
1984
  ${renderNamedImport(["WORKSPACE_AGENT_COMMAND"], modules.workspaceAgentHost)}
1985
+ ${renderNamedImport(["WORKSPACE_AGENT_PRODUCT_COMMAND"], modules.workspaceAgentClient)}
810
1986
  ${renderNamedImport(["decodeRuntimeLedgerEvent", "isInputRequestRef", "parseInputRequestResumePayload"], modules.runtimeProtocol)}
811
1987
  ${renderNamedImport(["agentOSRpcClient", "agentOSTruthIdentity"], "./cloudflare-scope")}
812
1988
  ${renderTypeImport(["AgentRuntimeClient"], modules.cloudflareDoRuntime)}
813
1989
  ${renderTypeImport(["SseHttpEvent"], modules.sseHttp)}
814
1990
  ${renderTypeImport(["RuntimeLedgerEvent", "SubmitResult", "SubmitRunInput"], modules.runtimeProtocol)}
1991
+ ${renderTypeImport([
1992
+ "AgentSessionListProjection",
1993
+ "AgentSessionProjection",
1994
+ "WorkflowRunListProjection",
1995
+ "WorkflowRunProjection",
1996
+ ], modules.runtimeRunProjector)}
815
1997
  ${renderTypeImport([
816
1998
  "WorkspaceAgentCustomCommandInput",
817
1999
  "WorkspaceAgentDestroyCommandInput",
@@ -822,10 +2004,28 @@ ${renderTypeImport([
822
2004
  "WorkspaceAgentReadStateCommandInput",
823
2005
  "WorkspaceAgentResetCommandInput",
824
2006
  ], modules.workspaceAgentHost)}
2007
+ ${renderTypeImport([
2008
+ "WorkspaceAgentSessionSubmitTurnInput",
2009
+ "WorkspaceAgentWorkflowRunInput",
2010
+ "WorkspaceAgentWorkflowRunRef",
2011
+ "WorkspaceAgentWorkflowRunsInput",
2012
+ ], modules.workspaceAgentClient)}
825
2013
  ${renderTypeImport(["AgentOSTargetEnv"], "./cloudflare-scope")}
826
2014
 
827
2015
  type AgentOSRpc = Pick<AgentRuntimeClient, "events" | "streamEvents"> & {
828
2016
  readonly submitRunInput: (input: SubmitRunInput) => Promise<SubmitResult>;
2017
+ readonly submitSessionTurn: (input: WorkspaceAgentSessionSubmitTurnInput) => Promise<SubmitResult>;
2018
+ readonly inspectSession: (
2019
+ input: { readonly sessionRef: string },
2020
+ ) => Promise<AgentSessionProjection>;
2021
+ readonly listSessions: () => Promise<AgentSessionListProjection>;
2022
+ readonly runWorkflow: (input: WorkspaceAgentWorkflowRunInput) => Promise<SubmitResult>;
2023
+ readonly inspectWorkflowRun: (
2024
+ input: WorkspaceAgentWorkflowRunRef,
2025
+ ) => Promise<WorkflowRunProjection | null>;
2026
+ readonly listWorkflowRuns: (
2027
+ input: WorkspaceAgentWorkflowRunsInput,
2028
+ ) => Promise<WorkflowRunListProjection>;
829
2029
  readonly resumeInputRequest: (
830
2030
  input: WorkspaceAgentResumeInputRequestCommandInput,
831
2031
  ) => Promise<SubmitResult>;
@@ -908,6 +2108,78 @@ const submitInputFromUnknown = (
908
2108
  return { ok: true, value: { input: value.input as unknown as AgentOSSubmitRunInput } };
909
2109
  };
910
2110
 
2111
+ const productSubmitInputFromUnknown = (
2112
+ value: unknown,
2113
+ label: string,
2114
+ ): GeneratedResult<AgentOSSubmitRunInput> => {
2115
+ if (!isRecord(value)) return fail(400, \`invalid \${label} command input\`);
2116
+ if (typeof value.intent !== "string" || !isRecord(value.context)) {
2117
+ return fail(400, \`invalid \${label} submit run input\`);
2118
+ }
2119
+ return { ok: true, value: value as unknown as AgentOSSubmitRunInput };
2120
+ };
2121
+
2122
+ const sessionTurnInputFromUnknown = (
2123
+ value: unknown,
2124
+ ): GeneratedResult<WorkspaceAgentSessionSubmitTurnInput> => {
2125
+ const submitInput = productSubmitInputFromUnknown(value, "submitSessionTurn");
2126
+ if (!submitInput.ok) return submitInput;
2127
+ if (!isRecord(value)) return fail(400, "invalid submitSessionTurn command input");
2128
+ if (typeof value.sessionRef !== "string" || typeof value.turnRef !== "string") {
2129
+ return fail(400, "invalid session turn identity");
2130
+ }
2131
+ return { ok: true, value: value as unknown as WorkspaceAgentSessionSubmitTurnInput };
2132
+ };
2133
+
2134
+ const sessionInspectInputFromUnknown = (
2135
+ value: unknown,
2136
+ ): GeneratedResult<{ readonly sessionRef: string }> => {
2137
+ if (!isRecord(value) || typeof value.sessionRef !== "string") {
2138
+ return fail(400, "invalid inspectSession command input");
2139
+ }
2140
+ return { ok: true, value: { sessionRef: value.sessionRef } };
2141
+ };
2142
+
2143
+ const workflowRunInputFromUnknown = (
2144
+ value: unknown,
2145
+ ): GeneratedResult<WorkspaceAgentWorkflowRunInput> => {
2146
+ const submitInput = productSubmitInputFromUnknown(value, "runWorkflow");
2147
+ if (!submitInput.ok) return submitInput;
2148
+ if (!isRecord(value)) return fail(400, "invalid runWorkflow command input");
2149
+ if (typeof value.workflowId !== "string" || typeof value.workflowRunId !== "string") {
2150
+ return fail(400, "invalid workflow run identity");
2151
+ }
2152
+ if (value.idempotencyKey !== undefined && typeof value.idempotencyKey !== "string") {
2153
+ return fail(400, "invalid workflow run idempotencyKey");
2154
+ }
2155
+ if (value.inputDigest !== undefined && typeof value.inputDigest !== "string") {
2156
+ return fail(400, "invalid workflow run inputDigest");
2157
+ }
2158
+ return { ok: true, value: value as unknown as WorkspaceAgentWorkflowRunInput };
2159
+ };
2160
+
2161
+ const workflowRunRefFromUnknown = (
2162
+ value: unknown,
2163
+ ): GeneratedResult<WorkspaceAgentWorkflowRunRef> => {
2164
+ if (!isRecord(value)) return fail(400, "invalid inspectWorkflowRun command input");
2165
+ if (typeof value.workflowId !== "string" || typeof value.workflowRunId !== "string") {
2166
+ return fail(400, "invalid workflow run identity");
2167
+ }
2168
+ return {
2169
+ ok: true,
2170
+ value: { workflowId: value.workflowId, workflowRunId: value.workflowRunId },
2171
+ };
2172
+ };
2173
+
2174
+ const workflowRunsInputFromUnknown = (
2175
+ value: unknown,
2176
+ ): GeneratedResult<WorkspaceAgentWorkflowRunsInput> => {
2177
+ if (!isRecord(value) || typeof value.workflowId !== "string") {
2178
+ return fail(400, "invalid listWorkflowRuns command input");
2179
+ }
2180
+ return { ok: true, value: { workflowId: value.workflowId } };
2181
+ };
2182
+
911
2183
  const resumeInputRequestFromUnknown = (
912
2184
  value: unknown,
913
2185
  ): GeneratedResult<WorkspaceAgentResumeInputRequestCommandInput> => {
@@ -1142,6 +2414,33 @@ export const invokeAgentCommand = command(commandInput, ({ name, input }): Promi
1142
2414
  ? runtime.submitRunInput(submitInput.value.input)
1143
2415
  : rejectFailure(submitInput);
1144
2416
  }
2417
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.SUBMIT_SESSION_TURN) {
2418
+ const sessionInput = sessionTurnInputFromUnknown(input);
2419
+ return sessionInput.ok ? runtime.submitSessionTurn(sessionInput.value) : rejectFailure(sessionInput);
2420
+ }
2421
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.INSPECT_SESSION) {
2422
+ const sessionInput = sessionInspectInputFromUnknown(input);
2423
+ return sessionInput.ok ? runtime.inspectSession(sessionInput.value) : rejectFailure(sessionInput);
2424
+ }
2425
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.LIST_SESSIONS) {
2426
+ return runtime.listSessions();
2427
+ }
2428
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.RUN_WORKFLOW) {
2429
+ const workflowInput = workflowRunInputFromUnknown(input);
2430
+ return workflowInput.ok ? runtime.runWorkflow(workflowInput.value) : rejectFailure(workflowInput);
2431
+ }
2432
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.INSPECT_WORKFLOW_RUN) {
2433
+ const workflowInput = workflowRunRefFromUnknown(input);
2434
+ return workflowInput.ok
2435
+ ? runtime.inspectWorkflowRun(workflowInput.value)
2436
+ : rejectFailure(workflowInput);
2437
+ }
2438
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.LIST_WORKFLOW_RUNS) {
2439
+ const workflowInput = workflowRunsInputFromUnknown(input);
2440
+ return workflowInput.ok
2441
+ ? runtime.listWorkflowRuns(workflowInput.value)
2442
+ : rejectFailure(workflowInput);
2443
+ }
1145
2444
  if (name === WORKSPACE_AGENT_COMMAND.RESUME_INPUT_REQUEST) {
1146
2445
  const resumeInput = resumeInputRequestFromUnknown(input);
1147
2446
  return resumeInput.ok
@@ -1500,10 +2799,29 @@ const renderSvelteKitRemote = (normalized, modules) => normalized.profile === AG
1500
2799
  const renderWorkspaceStaticClient = (normalized, modules) => {
1501
2800
  if (normalized.client.kind === AGENTOS_CONFIG_CLIENT.BROWSER_DIRECT_V1) {
1502
2801
  return `${renderNamedImport(["createWorkspaceAgentClientBridge"], modules.workspaceAgentClient)}
1503
- ${renderTypeImport(["CreateWorkspaceAgentClientOptions", "WorkspaceAgentClientBridge"], modules.workspaceAgentClient)}
2802
+ ${renderTypeImport([
2803
+ "AgentSessionListProjection",
2804
+ "AgentSessionProjection",
2805
+ "WorkflowRunListProjection",
2806
+ "WorkflowRunProjection",
2807
+ ], modules.runtimeRunProjector)}
2808
+ ${renderTypeImport([
2809
+ "CreateWorkspaceAgentClientOptions",
2810
+ "WorkspaceAgentClientBridge",
2811
+ "WorkspaceAgentProductCommandMap",
2812
+ "WorkspaceAgentProductProjectionTypes",
2813
+ ], modules.workspaceAgentClient)}
2814
+
2815
+ export interface GeneratedAgentClientProductProjections extends WorkspaceAgentProductProjectionTypes {
2816
+ readonly session: AgentSessionProjection;
2817
+ readonly sessionList: AgentSessionListProjection;
2818
+ readonly workflowRun: WorkflowRunProjection;
2819
+ readonly workflowRunList: WorkflowRunListProjection;
2820
+ }
1504
2821
 
1505
- export type GeneratedAgentClientOptions = CreateWorkspaceAgentClientOptions;
1506
- export type GeneratedAgentClient = WorkspaceAgentClientBridge;
2822
+ export type GeneratedAgentClientOptions =
2823
+ CreateWorkspaceAgentClientOptions<WorkspaceAgentProductCommandMap<GeneratedAgentClientProductProjections>>;
2824
+ export type GeneratedAgentClient = WorkspaceAgentClientBridge<GeneratedAgentClientProductProjections>;
1507
2825
 
1508
2826
  export const createAgentOSClient = (
1509
2827
  options: GeneratedAgentClientOptions = {},
@@ -1514,17 +2832,33 @@ export const createAgentOSClient = (
1514
2832
  import { invokeAgentCommand, runEventStream } from "./sveltekit.remote";
1515
2833
  ${renderNamedImport(["clientReadable", "selectClientReadable"], modules.clientSvelte)}
1516
2834
  ${renderTypeImport(["AgentClientSnapshot"], modules.clientCore)}
2835
+ ${renderTypeImport([
2836
+ "AgentSessionListProjection",
2837
+ "AgentSessionProjection",
2838
+ "WorkflowRunListProjection",
2839
+ "WorkflowRunProjection",
2840
+ ], modules.runtimeRunProjector)}
1517
2841
  ${renderTypeImport([
1518
2842
  "CreateWorkspaceAgentClientOptions",
1519
- "WorkspaceAgentClient",
1520
2843
  "WorkspaceAgentClientBridge",
1521
- "WorkspaceAgentCommandOutputByName",
2844
+ "WorkspaceAgentProductClient",
2845
+ "WorkspaceAgentProductCommandMap",
2846
+ "WorkspaceAgentProductProjectionTypes",
1522
2847
  ], modules.workspaceAgentClient)}
1523
2848
  ${renderTypeImport(["Readable"], modules.svelteStore)}
1524
2849
 
1525
- export type GeneratedAgentClientOptions = CreateWorkspaceAgentClientOptions;
2850
+ export interface GeneratedAgentClientProductProjections extends WorkspaceAgentProductProjectionTypes {
2851
+ readonly session: AgentSessionProjection;
2852
+ readonly sessionList: AgentSessionListProjection;
2853
+ readonly workflowRun: WorkflowRunProjection;
2854
+ readonly workflowRunList: WorkflowRunListProjection;
2855
+ }
2856
+
2857
+ export type GeneratedAgentClientOptions =
2858
+ CreateWorkspaceAgentClientOptions<WorkspaceAgentProductCommandMap<GeneratedAgentClientProductProjections>>;
1526
2859
 
1527
- export interface GeneratedAgentClient extends WorkspaceAgentClientBridge {
2860
+ export interface GeneratedAgentClient
2861
+ extends WorkspaceAgentClientBridge<GeneratedAgentClientProductProjections> {
1528
2862
  readonly snapshot: Readable<AgentClientSnapshot>;
1529
2863
  readonly events: Readable<AgentClientSnapshot["events"]>;
1530
2864
  readonly connection: Readable<AgentClientSnapshot["connection"]>;
@@ -1539,8 +2873,10 @@ const generatedStreamSource: NonNullable<GeneratedAgentClientOptions["streamSour
1539
2873
  }),
1540
2874
  };
1541
2875
 
1542
- const generatedRpcInvoker: WorkspaceAgentClient["invoke"] = (name, input) =>
1543
- invokeAgentCommand({ name, input }) as Promise<WorkspaceAgentCommandOutputByName[typeof name]>;
2876
+ const generatedRpcInvoker = ((name, input) =>
2877
+ invokeAgentCommand({ name, input })) as WorkspaceAgentProductClient<
2878
+ GeneratedAgentClientProductProjections
2879
+ >["invoke"];
1544
2880
 
1545
2881
  export const createAgentOSClient = (
1546
2882
  options: GeneratedAgentClientOptions = {},
@@ -1696,12 +3032,6 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1696
3032
  };
1697
3033
  }
1698
3034
  const modules = staticTargetModules(packageScope);
1699
- if (normalized.target.kind !== AGENTOS_CONFIG_TARGET.CLOUDFLARE_DO_V1) {
1700
- return {
1701
- ok: false,
1702
- issues: [{ kind: "unsupported_static_target", target: normalized.target.kind }],
1703
- };
1704
- }
1705
3035
  if (normalized.llm.route !== AGENTOS_CONFIG_LLM_ROUTE.OPENAI_CHAT_COMPATIBLE) {
1706
3036
  return {
1707
3037
  ok: false,
@@ -1709,6 +3039,138 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1709
3039
  };
1710
3040
  }
1711
3041
  const toolNames = Object.keys(normalized.deployment.manifest.tools ?? {}).sort();
3042
+ const hasChannels = normalized.channels.length > 0;
3043
+ const hasSchedules = normalized.schedules.length > 0;
3044
+ if (normalized.target.kind === AGENTOS_CONFIG_TARGET.NODE_V1) {
3045
+ if (normalized.profile !== AGENTOS_CONFIG_PROFILE.WORKSPACE_V1) {
3046
+ return {
3047
+ ok: false,
3048
+ issues: [{ kind: "unsupported_static_target", target: normalized.target.kind }],
3049
+ };
3050
+ }
3051
+ const authoredManifestToolNames = toolNames.filter((toolName) => normalized.authoredToolNames.includes(toolName));
3052
+ const deploymentJson = {
3053
+ deploymentId: normalized.deployment.deploymentId,
3054
+ backend: normalized.deployment.backend,
3055
+ adapter: normalized.deployment.adapter,
3056
+ codec: normalized.deployment.codec,
3057
+ ...(normalized.deployment.providerStrategy === undefined
3058
+ ? {}
3059
+ : { providerStrategy: normalized.deployment.providerStrategy }),
3060
+ workspace: {
3061
+ binding: normalized.workspace.binding,
3062
+ bindingRef: normalized.workspace.bindingRef,
3063
+ root: normalized.workspace.root,
3064
+ topology: normalized.workspace.topology,
3065
+ providerResourceId: normalized.workspace.providerResourceId,
3066
+ },
3067
+ };
3068
+ const moduleGraph = [
3069
+ { kind: "semantic-json", source: "./manifest.json", imports: ["default as declarations"] },
3070
+ { kind: "semantic-json", source: "./deployment.json", imports: ["default as deployment"] },
3071
+ {
3072
+ kind: "local-runtime",
3073
+ source: modules.localRuntime,
3074
+ imports: ["lowerLocalAgentRuntime"],
3075
+ },
3076
+ {
3077
+ kind: "capability-runtime",
3078
+ source: modules.runtimeCapability,
3079
+ imports: ["runDynamicCapabilityResolvers"],
3080
+ },
3081
+ {
3082
+ kind: "workspace-host",
3083
+ source: modules.workspaceAgentHost,
3084
+ imports: ["WorkspaceAgentCustomCommandInput"],
3085
+ },
3086
+ ...generatedToolImports(authoredManifestToolNames),
3087
+ ...generatedDynamicResolverImports(normalized.dynamicResolvers),
3088
+ ...(hasChannels
3089
+ ? [
3090
+ {
3091
+ kind: "channel-runtime",
3092
+ source: modules.runtimeChannel,
3093
+ imports: ["DefinedChannel"],
3094
+ },
3095
+ ...generatedChannelImports(normalized.channels),
3096
+ {
3097
+ kind: "channel-registry",
3098
+ source: "./channels",
3099
+ imports: ["dispatchGeneratedChannelRequest", "generatedChannels"],
3100
+ },
3101
+ ]
3102
+ : []),
3103
+ ...(hasSchedules
3104
+ ? [
3105
+ {
3106
+ kind: "schedule-runtime",
3107
+ source: modules.runtimeSchedule,
3108
+ imports: ["DefinedSchedule"],
3109
+ },
3110
+ ...generatedScheduleImports(normalized.schedules),
3111
+ {
3112
+ kind: "schedule-registry",
3113
+ source: "./schedules",
3114
+ imports: [
3115
+ "dispatchGeneratedSchedule",
3116
+ "generatedScheduleDefinitions",
3117
+ "generatedSchedules",
3118
+ ],
3119
+ },
3120
+ ]
3121
+ : []),
3122
+ ];
3123
+ return {
3124
+ ok: true,
3125
+ value: {
3126
+ files: [
3127
+ generatedPath(".agentos/generated/manifest.json", stableJson(normalized.deployment.manifest)),
3128
+ generatedPath(".agentos/generated/deployment.json", stableJson(deploymentJson)),
3129
+ generatedPath(".agentos/generated/provenance.json", stableJson(normalized.provenance)),
3130
+ generatedPath(".agentos/generated/fingerprints.json", stableJson({
3131
+ deployment: digestText(stableJson(deploymentJson)),
3132
+ manifest: digestText(stableJson(normalized.deployment.manifest)),
3133
+ targetModuleGraph: digestText(stableJson(moduleGraph)),
3134
+ })),
3135
+ ...(hasChannels
3136
+ ? [
3137
+ generatedPath(".agentos/generated/channels.ts", renderChannelRegistry(normalized.channels, modules)),
3138
+ ]
3139
+ : []),
3140
+ ...(hasSchedules
3141
+ ? [
3142
+ generatedPath(".agentos/generated/schedules.ts", renderScheduleRegistry(normalized.schedules, modules)),
3143
+ ]
3144
+ : []),
3145
+ generatedPath(".agentos/generated/local.ts", renderLocalAgentApp(normalized, toolNames, modules)),
3146
+ ],
3147
+ moduleGraph,
3148
+ canonicalDeployment: {
3149
+ profile: normalized.profile,
3150
+ target: normalized.target.kind,
3151
+ llmRoute: normalized.llm.route,
3152
+ client: normalized.client.kind,
3153
+ workspaceTopology: normalized.workspace.topology,
3154
+ toolNames,
3155
+ },
3156
+ mount: {
3157
+ driver: {
3158
+ kind: "local-node",
3159
+ target: AGENTOS_CONFIG_TARGET.NODE_V1,
3160
+ },
3161
+ projectionSinks: [
3162
+ "agent.info",
3163
+ "workspace.state",
3164
+ "workspace.files",
3165
+ "runtime.events",
3166
+ "runtime.input_requests",
3167
+ ],
3168
+ providerResourceId: normalized.workspace.providerResourceId,
3169
+ },
3170
+ },
3171
+ };
3172
+ }
3173
+ const target = cloudflareTargetFor(normalized.target);
1712
3174
  const authoredToolNames = new Set(normalized.authoredToolNames);
1713
3175
  const authoredManifestToolNames = toolNames.filter((toolName) => authoredToolNames.has(toolName));
1714
3176
  const deploymentJson = {
@@ -1738,10 +3200,63 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1738
3200
  {
1739
3201
  kind: "target-runtime",
1740
3202
  source: modules.cloudflareDoRuntime,
1741
- imports: normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
1742
- ? ["createAgentDurableObject", "installCloudflareWorkspaceOperationProvider"]
1743
- : ["createAgentDurableObject"],
3203
+ imports: ["createAgentDurableObject"],
1744
3204
  },
3205
+ ...(hasChannels
3206
+ ? [
3207
+ {
3208
+ kind: "channel-runtime",
3209
+ source: modules.runtimeChannel,
3210
+ imports: ["DefinedChannel"],
3211
+ },
3212
+ ...generatedChannelImports(normalized.channels),
3213
+ {
3214
+ kind: "channel-registry",
3215
+ source: "./channels",
3216
+ imports: ["dispatchGeneratedChannelRequest", "generatedChannels"],
3217
+ },
3218
+ ]
3219
+ : []),
3220
+ ...(hasSchedules
3221
+ ? [
3222
+ {
3223
+ kind: "schedule-runtime",
3224
+ source: modules.runtimeSchedule,
3225
+ imports: ["DefinedSchedule"],
3226
+ },
3227
+ ...generatedScheduleImports(normalized.schedules),
3228
+ {
3229
+ kind: "schedule-registry",
3230
+ source: "./schedules",
3231
+ imports: [
3232
+ "dispatchGeneratedSchedule",
3233
+ "generatedScheduleDefinitions",
3234
+ "generatedSchedules",
3235
+ ],
3236
+ },
3237
+ ]
3238
+ : []),
3239
+ ...(normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
3240
+ ? [
3241
+ {
3242
+ kind: "capability-runtime",
3243
+ source: modules.runtimeCapability,
3244
+ imports: [
3245
+ "WORKSPACE_OPERATION_HOST_FACT",
3246
+ "defineHost",
3247
+ "resolveRuntimeInstallGraph",
3248
+ "runDynamicCapabilityResolvers",
3249
+ "workspaceOperations",
3250
+ ],
3251
+ },
3252
+ ]
3253
+ : [
3254
+ {
3255
+ kind: "capability-runtime",
3256
+ source: modules.runtimeCapability,
3257
+ imports: ["runDynamicCapabilityResolvers"],
3258
+ },
3259
+ ]),
1745
3260
  {
1746
3261
  kind: "provider-runtime",
1747
3262
  source: modules.openAiCompatibleTransport,
@@ -1755,13 +3270,9 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1755
3270
  : ["WORKSPACE_AGENT_COMMAND"],
1756
3271
  },
1757
3272
  ...generatedToolImports(authoredManifestToolNames),
3273
+ ...generatedDynamicResolverImports(normalized.dynamicResolvers),
1758
3274
  ...(normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
1759
3275
  ? [
1760
- {
1761
- kind: "workspace-binding",
1762
- source: modules.workspaceBinding,
1763
- imports: ["bindWorkspaceToolsForRuntime"],
1764
- },
1765
3276
  {
1766
3277
  kind: "execution-domain-runtime",
1767
3278
  source: modules.workspaceEnvCloudflare,
@@ -1788,8 +3299,8 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1788
3299
  kind: "target-worker",
1789
3300
  source: "./worker",
1790
3301
  imports: normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
1791
- ? [normalized.target.durableObject.className, "Sandbox"]
1792
- : [normalized.target.durableObject.className],
3302
+ ? [target.durableObject.className, "Sandbox"]
3303
+ : [target.durableObject.className],
1793
3304
  },
1794
3305
  {
1795
3306
  kind: "target-config",
@@ -1810,6 +3321,16 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1810
3321
  manifest: digestText(stableJson(normalized.deployment.manifest)),
1811
3322
  targetModuleGraph: digestText(stableJson(moduleGraph)),
1812
3323
  })),
3324
+ ...(hasChannels
3325
+ ? [
3326
+ generatedPath(".agentos/generated/channels.ts", renderChannelRegistry(normalized.channels, modules)),
3327
+ ]
3328
+ : []),
3329
+ ...(hasSchedules
3330
+ ? [
3331
+ generatedPath(".agentos/generated/schedules.ts", renderScheduleRegistry(normalized.schedules, modules)),
3332
+ ]
3333
+ : []),
1813
3334
  generatedPath(".agentos/generated/target.ts", renderStaticTarget(normalized, toolNames, modules)),
1814
3335
  generatedPath(".agentos/generated/cloudflare-scope.ts", renderCloudflareScopeHelper(normalized, modules)),
1815
3336
  generatedPath(".agentos/generated/worker.ts", renderCloudflareWorkerEntry(normalized, modules)),
@@ -1836,8 +3357,8 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1836
3357
  mount: {
1837
3358
  driver: {
1838
3359
  kind: "cloudflare-do",
1839
- className: normalized.target.durableObject.className,
1840
- binding: normalized.target.durableObject.binding,
3360
+ className: target.durableObject.className,
3361
+ binding: target.durableObject.binding,
1841
3362
  },
1842
3363
  projectionSinks: normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
1843
3364
  ? [