@yansirplus/cli 0.5.17 → 0.5.19

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 (53) 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 +73 -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 +90 -0
  13. package/agent-catalog/agentOS/references/public-api/core.md +1907 -0
  14. package/agent-catalog/agentOS/references/public-api/runtime.md +843 -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 +1900 -281
  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 +1629 -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 +1281 -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 +171 -21
  43. package/dist/release-status.mjs +515 -0
  44. package/package.json +8 -4
  45. package/dist/check/check-coverage.mjs +0 -231
  46. package/dist/generate/generate-agent-docs.mjs +0 -435
  47. package/dist/generate/generate-carrier-reference.mjs +0 -514
  48. package/dist/generate/generate-docs.mjs +0 -345
  49. package/dist/generate/generate-effect-skill-manifests.mjs +0 -193
  50. package/dist/generate/project-docs-site.mjs +0 -190
  51. package/dist/lib/boundary-rules.mjs +0 -63
  52. package/dist/lib/capability-routes.mjs +0 -354
  53. 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,659 @@ 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", "dispatchScheduleFireDelivery"], modules.runtimeSchedule)}
306
+ ${renderTypeImport([
307
+ "DefinedSchedule",
308
+ "ScheduleDefinitionProjection",
309
+ "ScheduleFireDeliveryDispatchInput",
310
+ "ScheduleFireDeliveryDispatchResult",
311
+ "ScheduleFireDispatchResult",
312
+ "SchedulePrincipal",
313
+ "ScheduleRuntime",
314
+ ], modules.runtimeSchedule)}
315
+ ${renderTypeImport(["LedgerTruthIdentity"], modules.runtimeProtocol)}
316
+
317
+ type GeneratedScheduleDefinition = {
318
+ readonly scheduleId: string;
319
+ readonly path: string;
320
+ readonly cron: string;
321
+ readonly schedule: DefinedSchedule;
322
+ };
323
+
324
+ export type GeneratedScheduleTriggerInput = {
325
+ readonly scheduleId: string;
326
+ readonly scheduledAt: string | number | Date;
327
+ readonly appPrincipal: SchedulePrincipal;
328
+ };
329
+
330
+ export type GeneratedScheduleDispatchInput = GeneratedScheduleTriggerInput & {
331
+ readonly runtime: ScheduleRuntime;
332
+ readonly identity: LedgerTruthIdentity;
333
+ };
334
+
335
+ export type GeneratedScheduleDeliveryDispatchInput = GeneratedScheduleDispatchInput & {
336
+ readonly history: ScheduleFireDeliveryDispatchInput["history"];
337
+ };
338
+
339
+ export const generatedSchedules = ${entries} as const satisfies ReadonlyArray<GeneratedScheduleDefinition>;
340
+ export const generatedScheduleDefinitions = generatedSchedules.map(
341
+ ({ scheduleId, path, cron }) => ({ scheduleId, path, cron }),
342
+ ) satisfies ReadonlyArray<ScheduleDefinitionProjection>;
343
+ export const generatedScheduleIds = generatedScheduleDefinitions.map((entry) => entry.scheduleId);
344
+ export const generatedScheduleRegistry = new Map(
345
+ generatedSchedules.map((entry) => [entry.scheduleId, entry]),
346
+ );
347
+
348
+ export const dispatchGeneratedSchedule = async (
349
+ input: GeneratedScheduleDispatchInput,
350
+ ): Promise<ScheduleFireDispatchResult> => {
351
+ const entry = generatedScheduleRegistry.get(input.scheduleId);
352
+ if (entry === undefined) {
353
+ throw new Error(\`unknown generated schedule: \${input.scheduleId}\`);
354
+ }
355
+ return dispatchScheduleFire({
356
+ runtime: input.runtime,
357
+ schedule: entry.schedule,
358
+ scheduleId: entry.scheduleId,
359
+ appPrincipal: input.appPrincipal,
360
+ scheduledAt: input.scheduledAt,
361
+ scopeRef: input.identity.scopeRef,
362
+ effectAuthorityRef: input.identity.effectAuthorityRef,
363
+ });
364
+ };
365
+
366
+ export const dispatchGeneratedScheduleDelivery = async (
367
+ input: GeneratedScheduleDeliveryDispatchInput,
368
+ ): Promise<ScheduleFireDeliveryDispatchResult> => {
369
+ const entry = generatedScheduleRegistry.get(input.scheduleId);
370
+ if (entry === undefined) {
371
+ throw new Error(\`unknown generated schedule: \${input.scheduleId}\`);
372
+ }
373
+ return dispatchScheduleFireDelivery({
374
+ history: input.history,
375
+ runtime: input.runtime,
376
+ schedule: entry.schedule,
377
+ scheduleId: entry.scheduleId,
378
+ appPrincipal: input.appPrincipal,
379
+ scheduledAt: input.scheduledAt,
380
+ scopeRef: input.identity.scopeRef,
381
+ effectAuthorityRef: input.identity.effectAuthorityRef,
382
+ });
383
+ };
384
+ `;
385
+ };
386
+ const renderSkillCatalog = (skills) => {
387
+ const entries = sortedSkills(skills).map((skill) => ` ${JSON.stringify(stableJsonValue({
388
+ description: skill.description,
389
+ digest: skill.digest,
390
+ files: skill.files.map((file) => ({
391
+ bytes: file.bytes,
392
+ digest: file.digest,
393
+ path: file.path,
394
+ text: file.text,
395
+ })),
396
+ name: skill.name,
397
+ path: skill.path,
398
+ text: skill.text,
399
+ }))}`);
400
+ return entries.length === 0 ? "[]" : `[\n${entries.join(",\n")}\n]`;
401
+ };
402
+ const renderInstructionFragments = (fragments) => {
403
+ const entries = [...fragments]
404
+ .sort((left, right) => left.fragmentId.localeCompare(right.fragmentId))
405
+ .map((fragment) => ` ${JSON.stringify(stableJsonValue({
406
+ digest: fragment.digest,
407
+ id: fragment.fragmentId,
408
+ text: fragment.text,
409
+ }))}`);
410
+ return entries.length === 0 ? "[]" : `[\n${entries.join(",\n")}\n]`;
411
+ };
412
+ const renderDynamicCapabilityCatalog = (normalized, toolNames, hasSkills) => {
413
+ const manifestTools = normalized.deployment.manifest.tools ?? {};
414
+ const dynamicToolNames = [
415
+ ...toolNames,
416
+ ...(hasSkills ? [GENERATED_LOAD_SKILL_TOOL_NAME, GENERATED_READ_SKILL_FILE_TOOL_NAME] : []),
417
+ ];
418
+ return JSON.stringify(stableJsonValue({
419
+ instructions: normalized.instructionFragments.map((fragment) => ({
420
+ digest: fragment.digest,
421
+ id: fragment.fragmentId,
422
+ })),
423
+ skills: normalized.skills.map((skill) => ({
424
+ digest: skill.digest,
425
+ id: skill.name,
426
+ })),
427
+ tools: [...new Set(dynamicToolNames)].sort().map((toolName) => ({
428
+ id: toolName,
429
+ ...(manifestTools[toolName]?.bindingRef === undefined
430
+ ? {}
431
+ : { bindingRef: manifestTools[toolName]?.bindingRef }),
432
+ })),
433
+ }), null, 2);
434
+ };
435
+ const renderDynamicResolverImportStatements = (resolvers) => sortedDynamicResolvers(resolvers)
436
+ .map((resolver, index) => `import dynamicResolver_${index} from ${jsString(importDynamicResolverPath(resolver.path))};`)
437
+ .join("\n");
438
+ const renderDynamicCapabilitySupport = (normalized, toolNames, hasSkills) => {
439
+ const resolvers = sortedDynamicResolvers(normalized.dynamicResolvers);
440
+ const resolverEntries = resolvers.length === 0
441
+ ? "[]"
442
+ : `[\n${resolvers
443
+ .map((resolver, index) => ` {
444
+ resolverId: ${jsString(resolver.resolverId)},
445
+ slot: ${jsString(resolver.slot)},
446
+ resolve: dynamicResolver_${index},
447
+ },`)
448
+ .join("\n")}\n]`;
449
+ return `${renderDynamicResolverImportStatements(resolvers)}
450
+
451
+ const generatedDynamicCapabilityCatalog = ${renderDynamicCapabilityCatalog(normalized, toolNames, hasSkills)} satisfies DynamicCapabilityCompiledCatalog;
452
+
453
+ const generatedInstructionFragments = ${renderInstructionFragments(normalized.instructionFragments)} satisfies ReadonlyArray<SubmitInstructionFragment>;
454
+
455
+ const generatedDynamicCapabilityResolvers = ${resolverEntries} satisfies ReadonlyArray<DynamicCapabilityResolverDefinition>;
456
+
457
+ const generatedDynamicCapabilityTurnEvent = (
458
+ refs: { readonly sessionRef?: string; readonly turnRef?: string } = {},
459
+ ): DynamicCapabilityEventRef => ({
460
+ name: DYNAMIC_CAPABILITY_EVENT.TURN_STARTED,
461
+ ...(refs.sessionRef === undefined ? {} : { sessionRef: refs.sessionRef }),
462
+ ...(refs.turnRef === undefined ? {} : { turnRef: refs.turnRef }),
463
+ });
464
+
465
+ const generatedDynamicSubmitBindingsFor = async (
466
+ event: DynamicCapabilityEventRef,
467
+ input: DynamicCapabilityRunInput | undefined = undefined,
468
+ ): Promise<GeneratedTargetResult<Pick<AgentSubmitBindings, "dynamicCapabilityProjection" | "instructionFragments">>> => {
469
+ const projection = await runDynamicCapabilityResolvers({
470
+ event,
471
+ catalog: generatedDynamicCapabilityCatalog,
472
+ resolvers: generatedDynamicCapabilityResolvers,
473
+ input,
474
+ materials: semanticManifest.materials ?? {},
475
+ });
476
+ if (!projection.ok) {
477
+ return targetFailure(\`dynamic capability resolver failed: \${JSON.stringify(projection.issues)}\`);
478
+ }
479
+ return {
480
+ ok: true,
481
+ value: {
482
+ dynamicCapabilityProjection: projection.projection,
483
+ instructionFragments: generatedInstructionFragments,
484
+ },
485
+ };
486
+ };`;
487
+ };
488
+ const renderSkillSupport = (skills) => {
489
+ if (skills.length === 0)
490
+ return "";
491
+ return `
492
+ type GeneratedSkill = {
493
+ readonly name: string;
494
+ readonly description: string;
495
+ readonly path: string;
496
+ readonly digest: string;
497
+ readonly text: string;
498
+ readonly files: ReadonlyArray<{
499
+ readonly path: string;
500
+ readonly digest: string;
501
+ readonly bytes: number;
502
+ readonly text: string;
503
+ }>;
504
+ };
505
+
506
+ type GeneratedSkillFile = GeneratedSkill["files"][number];
507
+
508
+ type LoadedGeneratedSkill = Omit<GeneratedSkill, "files"> & {
509
+ readonly files: ReadonlyArray<Omit<GeneratedSkillFile, "text">>;
510
+ };
511
+
512
+ const generatedSkillCatalog = ${renderSkillCatalog(skills)} satisfies ReadonlyArray<GeneratedSkill>;
513
+ const generatedSkillNames = generatedSkillCatalog.map((skill) => skill.name);
514
+ const generatedSkillByName = Object.fromEntries(
515
+ generatedSkillCatalog.map((skill) => [skill.name, skill]),
516
+ ) as Readonly<Record<string, GeneratedSkill>>;
517
+ const generatedSkillFilePathCatalog = generatedSkillCatalog.flatMap((skill) =>
518
+ skill.files.map((file) => ({ name: skill.name, path: file.path })),
519
+ );
520
+ const generatedVisibleSkillCatalogFor = (
521
+ projection: DynamicCapabilityProjection | undefined,
522
+ ): ReadonlyArray<GeneratedSkill> => {
523
+ if (projection === undefined) return generatedSkillCatalog;
524
+ const visible = new Set(
525
+ projection.skills.filter((skill) => skill.visible).map((skill) => skill.id),
526
+ );
527
+ return generatedSkillCatalog.filter((skill) => visible.has(skill.name));
528
+ };
529
+
530
+ const generatedSkillsSystemAdvert = (
531
+ projection: DynamicCapabilityProjection | undefined,
532
+ ): string => [
533
+ "Available agent skills are not loaded by default.",
534
+ ...generatedVisibleSkillCatalogFor(projection).map((skill) => \`- \${skill.name}: \${skill.description}\`),
535
+ "Do not assume a skill's full instructions until ${GENERATED_LOAD_SKILL_TOOL_NAME} returns it.",
536
+ ].join("\\n");
537
+
538
+ const generatedSystemPrompt = (
539
+ system: string | undefined,
540
+ projection: DynamicCapabilityProjection | undefined,
541
+ ): string =>
542
+ system === undefined || system.length === 0
543
+ ? generatedSkillsSystemAdvert(projection)
544
+ : \`\${system}\\n\\n\${generatedSkillsSystemAdvert(projection)}\`;
545
+
546
+ const generatedLoadedSkill = (skill: GeneratedSkill): LoadedGeneratedSkill => ({
547
+ name: skill.name,
548
+ description: skill.description,
549
+ path: skill.path,
550
+ digest: skill.digest,
551
+ text: skill.text,
552
+ files: skill.files.map((file) => ({
553
+ path: file.path,
554
+ digest: file.digest,
555
+ bytes: file.bytes,
556
+ })),
557
+ });
558
+
559
+ const generatedFrameworkToolsFor = (
560
+ projection: DynamicCapabilityProjection | undefined,
561
+ ): Readonly<Record<string, Tool>> => {
562
+ const visibleSkillNames = new Set(
563
+ generatedVisibleSkillCatalogFor(projection).map((skill) => skill.name),
564
+ );
565
+ if (visibleSkillNames.size === 0) return {};
566
+ const visibleSkill = (name: string): GeneratedSkill | null => {
567
+ if (!visibleSkillNames.has(name)) return null;
568
+ return generatedSkillByName[name] ?? null;
569
+ };
570
+ const generatedLoadSkillTool = defineProductTool({
571
+ name: ${jsString(GENERATED_LOAD_SKILL_TOOL_NAME)},
572
+ description: "Load the full text of a CLI-authored agent skill by name.",
573
+ args: Schema.Struct({ name: Schema.String }),
574
+ authority: "agentos.generated.skills",
575
+ authorityId: "agentos.generated.skills.load_skill",
576
+ admit: ({ name }) => Effect.succeed({ ok: visibleSkillNames.has(name) } as const),
577
+ execute: ({ name }) => {
578
+ const skill = visibleSkill(name);
579
+ if (skill === null) return Effect.fail(Error(\`unknown skill \${name}\`));
580
+ return Effect.succeed(generatedLoadedSkill(skill));
581
+ },
582
+ });
583
+
584
+ const generatedReadSkillFileTool = defineProductTool({
585
+ name: ${jsString(GENERATED_READ_SKILL_FILE_TOOL_NAME)},
586
+ description: "Read one declared supporting file from a CLI-authored agent skill package.",
587
+ args: Schema.Struct({
588
+ name: Schema.String,
589
+ path: Schema.String,
590
+ }),
591
+ authority: "agentos.generated.skills",
592
+ authorityId: "agentos.generated.skills.read_skill_file",
593
+ admit: ({ name, path }) =>
594
+ Effect.succeed({
595
+ ok:
596
+ visibleSkillNames.has(name) &&
597
+ generatedSkillFilePathCatalog.some((file) => file.name === name && file.path === path),
598
+ } as const),
599
+ execute: ({ name, path }) => {
600
+ const skill = visibleSkill(name);
601
+ const file = skill?.files.find((candidate) => candidate.path === path);
602
+ if (skill === null || file === undefined) {
603
+ return Effect.fail(Error(\`unknown skill file \${name}/\${path}\`));
604
+ }
605
+ return Effect.succeed({
606
+ name,
607
+ path: file.path,
608
+ digest: file.digest,
609
+ text: file.text,
610
+ });
611
+ },
612
+ });
613
+
614
+ return {
615
+ ${jsString(GENERATED_LOAD_SKILL_TOOL_NAME)}: generatedLoadSkillTool,
616
+ ${jsString(GENERATED_READ_SKILL_FILE_TOOL_NAME)}: generatedReadSkillFileTool,
617
+ } satisfies Readonly<Record<string, Tool>>;
618
+ };
619
+ `;
620
+ };
621
+ const renderSubmitSpecFromRunInput = (hasSkills) => `const submitSpecFromRunInput = (
622
+ input: SubmitRunInput,
623
+ dynamicCapabilityProjection: DynamicCapabilityProjection | undefined,
624
+ ): AgentSubmitSpec => ({
625
+ input,
626
+ intent: input.intent,
627
+ context: input.context,
628
+ ${hasSkills ? "system: generatedSystemPrompt(input.system, dynamicCapabilityProjection)," : "...(input.system === undefined ? {} : { system: input.system }),"}
629
+ ...(input.budget === undefined ? {} : { budget: input.budget }),
630
+ ...(input.outputSchema === undefined ? {} : { outputSchema: input.outputSchema }),
631
+ ...(input.traceContext === undefined ? {} : { traceContext: input.traceContext }),
632
+ ...(input.dynamicCapability === undefined ? {} : { dynamicCapability: input.dynamicCapability }),
633
+ ...(input.materials === undefined ? {} : { materials: input.materials }),
634
+ ...(input.toolContext === undefined ? {} : { toolContext: input.toolContext }),
635
+ ...(input.toolPolicy === undefined ? {} : { toolPolicy: input.toolPolicy }),
636
+ ...(input.decisionInterrupts === undefined ? {} : { decisionInterrupts: input.decisionInterrupts }),
637
+ ...(input.resume === undefined ? {} : { resume: input.resume }),
638
+ });`;
639
+ const renderProductApiHelpers = () => `export interface AgentSessionSubmitTurnInput extends SubmitRunInput {
640
+ readonly sessionRef: string;
641
+ readonly turnRef: string;
642
+ readonly idempotencyKey?: string;
643
+ }
644
+
645
+ export interface AgentWorkflowRunInput extends SubmitRunInput {
646
+ readonly workflowId: string;
647
+ readonly workflowRunId: string;
648
+ readonly idempotencyKey?: string;
649
+ readonly inputDigest?: string;
650
+ }
651
+
652
+ export interface AgentWorkflowRunRef {
653
+ readonly workflowId: string;
654
+ readonly workflowRunId: string;
655
+ }
656
+
657
+ const submitRunInputFields = (input: SubmitRunInput): SubmitRunInput => ({
658
+ intent: input.intent,
659
+ context: input.context,
660
+ ...(input.system === undefined ? {} : { system: input.system }),
661
+ ...(input.budget === undefined ? {} : { budget: input.budget }),
662
+ ...(input.outputSchema === undefined ? {} : { outputSchema: input.outputSchema }),
663
+ ...(input.traceContext === undefined ? {} : { traceContext: input.traceContext }),
664
+ ...(input.dynamicCapability === undefined ? {} : { dynamicCapability: input.dynamicCapability }),
665
+ ...(input.materials === undefined ? {} : { materials: input.materials }),
666
+ ...(input.toolContext === undefined ? {} : { toolContext: input.toolContext }),
667
+ ...(input.toolPolicy === undefined ? {} : { toolPolicy: input.toolPolicy }),
668
+ ...(input.decisionInterrupts === undefined ? {} : { decisionInterrupts: input.decisionInterrupts }),
669
+ ...(input.resume === undefined ? {} : { resume: input.resume }),
670
+ });
671
+
672
+ const submitRunInputFromWorkflowRun = (
673
+ input: AgentWorkflowRunInput,
674
+ ): SubmitRunInput => submitRunInputFields(input);
675
+
676
+ const submitRunInputFromSessionTurn = (
677
+ input: AgentSessionSubmitTurnInput,
678
+ ): SubmitRunInput => submitRunInputFields(input);`;
679
+ const renderProductApiDurableObjectMethods = () => `
680
+ submitSessionTurn(input: AgentSessionSubmitTurnInput): Promise<SubmitResult> {
681
+ return generatedSubmitBindingsFor(
682
+ this.targetEnv,
683
+ generatedDynamicCapabilityTurnEvent({
684
+ sessionRef: input.sessionRef,
685
+ turnRef: input.turnRef,
686
+ }),
687
+ input.dynamicCapability,
688
+ ).then((bindings) =>
689
+ bindings.ok
690
+ ? this.submitWithBindingsAndProductLink(
691
+ submitSpecFromRunInput(
692
+ submitRunInputFromSessionTurn(input),
693
+ bindings.value.dynamicCapabilityProjection,
694
+ ),
695
+ bindings.value,
696
+ {
697
+ kind: "session_turn",
698
+ sessionRef: input.sessionRef,
699
+ turnRef: input.turnRef,
700
+ ...(input.idempotencyKey === undefined ? {} : { idempotencyKey: input.idempotencyKey }),
701
+ },
702
+ )
703
+ : rejectTargetFailure(bindings),
704
+ );
705
+ }
706
+
707
+ inspectSession(input: { readonly sessionRef: string }): Promise<AgentSessionProjection> {
708
+ return this.events(semanticTruthIdentity).then((events) =>
709
+ projectAgentSession(events, input.sessionRef),
710
+ );
711
+ }
712
+
713
+ listSessions(): Promise<AgentSessionListProjection> {
714
+ return this.events(semanticTruthIdentity).then((events) => projectAgentSessions(events));
715
+ }
716
+
717
+ runWorkflow(input: AgentWorkflowRunInput): Promise<SubmitResult> {
718
+ return generatedSubmitBindingsFor(
719
+ this.targetEnv,
720
+ generatedDynamicCapabilityTurnEvent(),
721
+ input.dynamicCapability,
722
+ ).then((bindings) =>
723
+ bindings.ok
724
+ ? this.submitWithBindingsAndProductLink(
725
+ submitSpecFromRunInput(
726
+ submitRunInputFromWorkflowRun(input),
727
+ bindings.value.dynamicCapabilityProjection,
728
+ ),
729
+ bindings.value,
730
+ {
731
+ kind: "workflow_run",
732
+ workflowId: input.workflowId,
733
+ workflowRunId: input.workflowRunId,
734
+ ...(input.idempotencyKey === undefined ? {} : { idempotencyKey: input.idempotencyKey }),
735
+ ...(input.inputDigest === undefined ? {} : { inputDigest: input.inputDigest }),
736
+ },
737
+ )
738
+ : rejectTargetFailure(bindings),
739
+ );
740
+ }
741
+
742
+ inspectWorkflowRun(input: AgentWorkflowRunRef): Promise<WorkflowRunProjection | null> {
743
+ return this.events(semanticTruthIdentity).then((events) =>
744
+ projectWorkflowRun(events, input.workflowId, input.workflowRunId),
745
+ );
746
+ }
747
+
748
+ listWorkflowRuns(input: { readonly workflowId: string }): Promise<WorkflowRunListProjection> {
749
+ return this.events(semanticTruthIdentity).then((events) =>
750
+ projectWorkflowRuns(events, input.workflowId),
751
+ );
752
+ }`;
753
+ const renderScheduleDurableObjectHelpers = () => `
754
+ const generatedScheduleRuntimeFor = (target: {
755
+ readonly submitSessionTurn: (input: AgentSessionSubmitTurnInput) => Promise<SubmitResult>;
756
+ readonly runWorkflow: (input: AgentWorkflowRunInput) => Promise<SubmitResult>;
757
+ }) =>
758
+ Object.freeze({
759
+ sessions: Object.freeze({
760
+ submitTurn: (input: AgentSessionSubmitTurnInput) => target.submitSessionTurn(input),
761
+ }),
762
+ workflows: Object.freeze({
763
+ run: (input: AgentWorkflowRunInput) => target.runWorkflow(input),
764
+ }),
765
+ });`;
766
+ const renderScheduleDurableObjectMethod = () => `
767
+ dispatchSchedule(input: GeneratedScheduleTriggerInput): Promise<unknown> {
768
+ return this.events(semanticTruthIdentity).then((history) =>
769
+ dispatchGeneratedScheduleDelivery({
770
+ ...input,
771
+ history,
772
+ identity: semanticTruthIdentity,
773
+ runtime: generatedScheduleRuntimeFor(this),
774
+ }).then((result) => this.commitScheduleFireDispatchFullWithDelivery(result)),
775
+ );
776
+ }
777
+ `;
778
+ const renderGeneratedWorkspaceOperations = (workspaceToolArray, usesMutationTools, usesShellTools) => `const generatedWorkspaceToolNames = ${workspaceToolArray};
779
+
780
+ const generatedWorkspaceToolInteractionFor = (
781
+ name: (typeof generatedWorkspaceToolNames)[number],
782
+ ): "never" | "approval" => {
783
+ const interaction = semanticManifest.tools?.[name]?.interaction;
784
+ if (interaction === "never" || interaction === "approval") return interaction;
785
+ throw Error(\`invalid workspace tool interaction for \${name}: \${String(interaction)}\`);
786
+ };
787
+
788
+ const generatedWorkspaceToolInteractions = Object.fromEntries(
789
+ generatedWorkspaceToolNames.map((name) => [name, generatedWorkspaceToolInteractionFor(name)]),
790
+ ) as Readonly<Partial<Record<(typeof generatedWorkspaceToolNames)[number], "never" | "approval">>>;
791
+
792
+ const generatedWorkspaceOperations = {
793
+ toolNames: generatedWorkspaceToolNames,
794
+ mutationPolicy: ${usesMutationTools ? '"receipt-backed"' : '"disabled"'},
795
+ shellPolicy: ${usesShellTools ? '"receipt-backed"' : '"disabled"'},
796
+ toolInteractions: generatedWorkspaceToolInteractions,
797
+ } as const;`;
56
798
  const renderWorkspaceStaticTarget = (normalized, toolNames, modules) => {
799
+ const target = cloudflareTargetFor(normalized.target);
800
+ const hasSkills = normalized.skills.length > 0;
801
+ const hasDynamicCapability = true;
802
+ const hasSchedules = normalized.schedules.length > 0;
57
803
  const authoredToolNames = new Set(normalized.authoredToolNames);
58
804
  const workspaceToolList = toolNames.filter((toolName) => isWorkspaceToolName(toolName) && !authoredToolNames.has(toolName));
59
805
  const customToolNames = toolNames.filter((toolName) => authoredToolNames.has(toolName));
@@ -71,23 +817,57 @@ const renderWorkspaceStaticTarget = (normalized, toolNames, modules) => {
71
817
  const handlerRecord = `{\n${normalized.deployment.manifest.handlers
72
818
  .map((handler) => ` ${jsString(handler)}: generatedHandler,`)
73
819
  .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;`)
820
+ const llmEnvBindings = uniqueLlmMaterialEnvBindings(normalized.llmRoutes);
821
+ const generatedLlmEnvFields = llmEnvBindings
822
+ .map((binding) => ` readonly ${binding.envName}?: string;`)
77
823
  .join("\n");
78
824
  const imports = [
79
825
  `import semanticDeclarations from "./manifest.json";`,
80
826
  `import deploymentProvenance from "./deployment.json";`,
81
- renderNamedImport(["createAgentDurableObject", "installCloudflareWorkspaceOperationProvider"], modules.cloudflareDoRuntime),
82
- renderNamedImport(["OpenAiCompatibleLlmTransportLive"], modules.openAiCompatibleTransport),
827
+ ...(hasSchedules
828
+ ? [renderNamedImport(["dispatchGeneratedScheduleDelivery"], "./schedules")]
829
+ : []),
830
+ renderNamedImport(["createAgentDurableObject"], modules.cloudflareDoRuntime),
831
+ renderNamedImport([
832
+ "WORKSPACE_OPERATION_HOST_FACT",
833
+ "defineHost",
834
+ "resolveRuntimeInstallGraph",
835
+ ...(hasDynamicCapability ? ["runDynamicCapabilityResolvers"] : []),
836
+ "workspaceOperations",
837
+ ], modules.runtimeCapability),
838
+ renderNamedImport(["OpenAiCompatibleLlmTransportLive", "preflightOpenAiCompatibleProviderMaterial"], modules.openAiCompatibleTransport),
839
+ renderNamedImport(["DYNAMIC_CAPABILITY_EVENT", "manifestTruthIdentity"], modules.runtimeProtocol),
840
+ renderNamedImport(["projectAgentSession", "projectAgentSessions", "projectWorkflowRun", "projectWorkflowRuns"], modules.runtimeRunProjector),
83
841
  renderNamedImport(["defineWorkspaceAgentMount", "WORKSPACE_AGENT_PROJECTION"], modules.workspaceAgentHost),
84
- renderNamedImport(["bindWorkspaceToolsForRuntime"], modules.workspaceBinding),
85
842
  renderNamedImport(["makeCloudflareWorkspaceEnv"], modules.workspaceEnvCloudflare),
86
843
  renderNamedImport(["getSandbox"], modules.cloudflareSandbox),
87
- renderNamedImport(["deterministicToolInvocation", "unsafeRunToolByName"], modules.coreTools),
88
- renderNamedImport(["Effect"], modules.effect),
844
+ renderNamedImport([
845
+ "deterministicToolInvocation",
846
+ ...(hasSkills ? ["defineProductTool"] : []),
847
+ "unsafeRunToolByName",
848
+ ], modules.coreTools),
849
+ renderNamedImport(hasSkills ? ["Effect", "Schema"] : ["Effect"], modules.effect),
89
850
  renderTypeImport(["AgentManifest", "AgentSubmitBindings", "SubmitResult", "SubmitRunInput"], modules.runtimeProtocol),
851
+ ...(hasDynamicCapability
852
+ ? [
853
+ renderTypeImport([
854
+ "DynamicCapabilityCompiledCatalog",
855
+ "DynamicCapabilityEventRef",
856
+ "DynamicCapabilityProjection",
857
+ "DynamicCapabilityRunInput",
858
+ "SubmitInstructionFragment",
859
+ ], modules.runtimeProtocol),
860
+ renderTypeImport(["DynamicCapabilityResolverDefinition"], modules.runtimeCapability),
861
+ ]
862
+ : []),
863
+ renderTypeImport([
864
+ "AgentSessionListProjection",
865
+ "AgentSessionProjection",
866
+ "WorkflowRunListProjection",
867
+ "WorkflowRunProjection",
868
+ ], modules.runtimeRunProjector),
90
869
  renderTypeImport(["AgentSubmitSpec"], modules.cloudflareDoRuntime),
870
+ ...(hasSchedules ? [renderTypeImport(["GeneratedScheduleTriggerInput"], "./schedules")] : []),
91
871
  renderTypeImport([
92
872
  "WorkspaceAgentDecideInputRequestCommandInput",
93
873
  "WorkspaceAgentCustomCommandInput",
@@ -109,6 +889,7 @@ export const targetDeclarations = semanticDeclarations;
109
889
  export const targetDeployment = deploymentProvenance;
110
890
 
111
891
  const semanticManifest = semanticDeclarations as AgentManifest;
892
+ const semanticTruthIdentity = manifestTruthIdentity(semanticManifest);
112
893
  const generatedHandler = () => undefined;
113
894
 
114
895
  type AgentOSTargetEnv = {
@@ -120,33 +901,36 @@ ${generatedLlmEnvFields}
120
901
  type GeneratedTargetFailure = {
121
902
  readonly ok: false;
122
903
  readonly message: string;
904
+ readonly diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>;
123
905
  };
124
906
 
125
907
  type GeneratedTargetResult<Value> =
126
908
  | { readonly ok: true; readonly value: Value }
127
909
  | GeneratedTargetFailure;
128
910
 
129
- const targetFailure = (message: string): GeneratedTargetFailure => ({ ok: false, message });
911
+ const targetFailure = (
912
+ message: string,
913
+ diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>,
914
+ ): GeneratedTargetFailure => ({
915
+ ok: false,
916
+ message,
917
+ ...(diagnostics === undefined || diagnostics.length === 0 ? {} : { diagnostics }),
918
+ });
130
919
 
131
- const rejectTargetFailure = (failure: GeneratedTargetFailure): Promise<never> =>
132
- Promise.reject(Error(failure.message));
920
+ const rejectTargetFailure = (failure: GeneratedTargetFailure): Promise<never> => {
921
+ const error = Error(failure.message) as Error & {
922
+ diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>;
923
+ };
924
+ if (failure.diagnostics !== undefined) error.diagnostics = failure.diagnostics;
925
+ return Promise.reject(error);
926
+ };
133
927
 
134
- const generatedWorkspaceToolNames = ${workspaceToolArray};
928
+ ${renderGeneratedWorkspaceOperations(workspaceToolArray, usesMutationTools, usesShellTools)}
135
929
  const generatedCustomTools = ${customToolRecord} satisfies Readonly<Record<string, Tool>>;
930
+ ${hasDynamicCapability ? renderDynamicCapabilitySupport(normalized, toolNames, hasSkills) : ""}
931
+ ${renderSkillSupport(normalized.skills)}
136
932
  const generatedWorkspaceSandboxId = ${jsString(normalized.workspace.cloudflareSandboxId)};
137
933
 
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
934
  const workspaceNamespaceFor = (env: AgentOSTargetEnv): DurableObjectNamespace<Sandbox> =>
151
935
  env[${jsString(normalized.workspace.binding)}] as DurableObjectNamespace<Sandbox>;
152
936
 
@@ -221,36 +1005,46 @@ const workspaceEnvFor = (env: AgentOSTargetEnv) =>
221
1005
  workspaceRef: ${jsString(normalized.workspace.providerResourceId)},
222
1006
  });
223
1007
 
224
- const allowWorkspaceTool = () =>
225
- Effect.succeed({ ok: true as const }).pipe(
226
- Effect.withSpan("agentos.generated.workspace.allow_tool"),
227
- );
1008
+ const generatedHostProfileFor = (env: AgentOSTargetEnv) => defineHost({
1009
+ target: "cloudflare-do@1",
1010
+ provides: [
1011
+ "storage.ledger",
1012
+ "durability.do",
1013
+ WORKSPACE_OPERATION_HOST_FACT,
1014
+ "timer.durable",
1015
+ "network.outbound",
1016
+ "secrets.store",
1017
+ "eventLoop.durable",
1018
+ "llm.openai",
1019
+ ],
1020
+ materialize: () => ({
1021
+ [WORKSPACE_OPERATION_HOST_FACT]: () => workspaceEnvFor(env),
1022
+ }),
1023
+ });
228
1024
 
229
- const workspaceOperationInstallFor = (env: AgentOSTargetEnv) =>
230
- installCloudflareWorkspaceOperationProvider({
231
- env: workspaceEnvFor(env),
232
- });
1025
+ const generatedCapabilityInstallGraphFor = (env: AgentOSTargetEnv) => {
1026
+ const graph = resolveRuntimeInstallGraph(
1027
+ generatedHostProfileFor(env),
1028
+ [workspaceOperations(generatedWorkspaceOperations)],
1029
+ { identity: semanticManifest.agentId },
1030
+ );
1031
+ if (!graph.ok) {
1032
+ throw Error(
1033
+ graph.diagnostics
1034
+ .map((diagnostic) => diagnostic.reason)
1035
+ .join("; ") || "capability install graph failed",
1036
+ );
1037
+ }
1038
+ return graph.resolved;
1039
+ };
233
1040
 
234
1041
  const materialEnvValue = (env: AgentOSTargetEnv, name: string): string | null => {
235
1042
  const value = env[name];
236
1043
  return typeof value === "string" && value.length > 0 ? value : null;
237
1044
  };
238
1045
 
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
- };
1046
+ ${renderMaterialValueFunction(normalized.llmRoutes)}
1047
+ ${renderGeneratedProviderPreflight(normalized.llmRoutes)}
254
1048
 
255
1049
  const requiredStringMaterial = (
256
1050
  kind: string,
@@ -261,70 +1055,45 @@ const requiredStringMaterial = (
261
1055
  return targetFailure(\`missing \${kind} material: \${ref}\`);
262
1056
  };
263
1057
 
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
- };
1058
+ ${renderGeneratedLlmRoutesFor(normalized.llmRoutes)}
281
1059
 
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;
1060
+ const generatedSubmitBindingsFor = async (
1061
+ env: AgentOSTargetEnv,
1062
+ event: DynamicCapabilityEventRef = generatedDynamicCapabilityTurnEvent(),
1063
+ dynamicCapability: DynamicCapabilityRunInput | undefined = undefined,
1064
+ ): Promise<GeneratedTargetResult<AgentSubmitBindings>> => {
1065
+ const preflightDiagnostics = generatedProviderPreflightDiagnosticsFor(env);
1066
+ if (preflightDiagnostics.length > 0) {
1067
+ return targetFailure(
1068
+ "OpenAI-compatible provider material preflight failed",
1069
+ preflightDiagnostics,
1070
+ );
1071
+ }
1072
+ const capabilityGraph = generatedCapabilityInstallGraphFor(env);
1073
+ const routes = generatedLlmRoutesFor(env);
1074
+ if (!routes.ok) return routes;
1075
+ const dynamicBindings = await generatedDynamicSubmitBindingsFor(event, dynamicCapability);
1076
+ if (!dynamicBindings.ok) return dynamicBindings;
1077
+ const dynamicCapabilityProjection = dynamicBindings.value.dynamicCapabilityProjection;
299
1078
  return {
300
1079
  ok: true,
301
1080
  value: {
302
- ...workspaceBindings,
303
- llmRoutes: {
304
- default: route.value,
305
- },
1081
+ ...capabilityGraph.bindings,
1082
+ ...dynamicBindings.value,
1083
+ llmRoutes: routes.value,
306
1084
  tools: {
307
- ...(workspaceBindings.tools ?? {}),
1085
+ ...(capabilityGraph.bindings.tools ?? {}),
308
1086
  ...generatedCustomTools,
1087
+ ${hasSkills ? "...generatedFrameworkToolsFor(dynamicCapabilityProjection)," : ""}
309
1088
  },
310
1089
  },
311
1090
  };
312
1091
  };
313
1092
 
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
- });
1093
+ ${renderSubmitSpecFromRunInput(hasSkills)}
1094
+
1095
+ ${renderProductApiHelpers()}
1096
+ ${hasSchedules ? renderScheduleDurableObjectHelpers() : ""}
328
1097
 
329
1098
  export const workspaceMount = defineWorkspaceAgentMount({
330
1099
  driver: { kind: "driver_mount", client: undefined as never },
@@ -337,22 +1106,24 @@ export const workspaceMount = defineWorkspaceAgentMount({
337
1106
  ],
338
1107
  });
339
1108
 
340
- const Base${normalized.target.durableObject.className} = createAgentDurableObject<AgentOSTargetEnv>({
1109
+ const Base${target.durableObject.className} = createAgentDurableObject<AgentOSTargetEnv>({
341
1110
  manifest: semanticManifest,
342
- agentBindings: {
1111
+ agentBindings: (env) => ({
343
1112
  handlers: ${handlerRecord},
344
- },
1113
+ ...generatedCapabilityInstallGraphFor(env).agentBindings,
1114
+ }),
345
1115
  refResolver: (env) => ({
346
1116
  material: (ref) => materialValue(env, ref),
347
1117
  }),
348
1118
  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),
1119
+ extensions: (env) => generatedCapabilityInstallGraphFor(env).extensions,
1120
+ declaredIntents: (env) => generatedCapabilityInstallGraphFor(env).declaredIntents,
1121
+ projections: (env) => generatedCapabilityInstallGraphFor(env).projections,
1122
+ graphStatus: (env) => generatedCapabilityInstallGraphFor(env).graphStatus,
1123
+ eventHandlers: (context, env) => generatedCapabilityInstallGraphFor(env).handlers(context),
353
1124
  });
354
1125
 
355
- export class ${normalized.target.durableObject.className} extends Base${normalized.target.durableObject.className} {
1126
+ export class ${target.durableObject.className} extends Base${target.durableObject.className} {
356
1127
  private readonly targetEnv: AgentOSTargetEnv;
357
1128
 
358
1129
  constructor(ctx: DurableObjectState, env: AgentOSTargetEnv) {
@@ -361,31 +1132,47 @@ export class ${normalized.target.durableObject.className} extends Base${normaliz
361
1132
  }
362
1133
 
363
1134
  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);
1135
+ return generatedSubmitBindingsFor(
1136
+ this.targetEnv,
1137
+ generatedDynamicCapabilityTurnEvent(),
1138
+ spec.dynamicCapability,
1139
+ ).then((bindings) =>
1140
+ bindings.ok ? this.submitWithBindings(spec, bindings.value) : rejectTargetFailure(bindings),
1141
+ );
368
1142
  }
369
1143
 
370
1144
  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);
1145
+ return generatedSubmitBindingsFor(
1146
+ this.targetEnv,
1147
+ generatedDynamicCapabilityTurnEvent(),
1148
+ input.dynamicCapability,
1149
+ ).then((bindings) =>
1150
+ bindings.ok
1151
+ ? this.submitWithBindings(
1152
+ submitSpecFromRunInput(input, bindings.value.dynamicCapabilityProjection),
1153
+ bindings.value,
1154
+ )
1155
+ : rejectTargetFailure(bindings),
1156
+ );
375
1157
  }
376
1158
 
1159
+ ${renderProductApiDurableObjectMethods()}
1160
+ ${hasSchedules ? renderScheduleDurableObjectMethod() : ""}
1161
+
377
1162
  resumeInputRequest(input: WorkspaceAgentResumeInputRequestCommandInput): Promise<SubmitResult> {
378
- const bindings = generatedSubmitBindingsFor(this.targetEnv);
379
- return bindings.ok
380
- ? this.resumeInputRequestWithBindings(input, bindings.value)
381
- : rejectTargetFailure(bindings);
1163
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1164
+ bindings.ok
1165
+ ? this.resumeInputRequestWithBindings(input, bindings.value)
1166
+ : rejectTargetFailure(bindings),
1167
+ );
382
1168
  }
383
1169
 
384
1170
  decideInputRequest(input: WorkspaceAgentDecideInputRequestCommandInput): Promise<SubmitResult> {
385
- const bindings = generatedSubmitBindingsFor(this.targetEnv);
386
- return bindings.ok
387
- ? this.decideInputRequestWithBindings(input, bindings.value)
388
- : rejectTargetFailure(bindings);
1171
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1172
+ bindings.ok
1173
+ ? this.decideInputRequestWithBindings(input, bindings.value)
1174
+ : rejectTargetFailure(bindings),
1175
+ );
389
1176
  }
390
1177
 
391
1178
  customCommand(input: WorkspaceAgentCustomCommandInput): Promise<unknown> {
@@ -453,6 +1240,10 @@ export class ${normalized.target.durableObject.className} extends Base${normaliz
453
1240
  `;
454
1241
  };
455
1242
  const renderChatStaticTarget = (normalized, toolNames, modules) => {
1243
+ const target = cloudflareTargetFor(normalized.target);
1244
+ const hasSkills = normalized.skills.length > 0;
1245
+ const hasDynamicCapability = true;
1246
+ const hasSchedules = normalized.schedules.length > 0;
456
1247
  const authoredToolNames = new Set(normalized.authoredToolNames);
457
1248
  const customToolNames = toolNames.filter((toolName) => authoredToolNames.has(toolName));
458
1249
  const toolImports = customToolNames
@@ -466,39 +1257,324 @@ const renderChatStaticTarget = (normalized, toolNames, modules) => {
466
1257
  const handlerRecord = `{\n${normalized.deployment.manifest.handlers
467
1258
  .map((handler) => ` ${jsString(handler)}: generatedHandler,`)
468
1259
  .join("\n")}\n}`;
1260
+ const llmEnvBindings = uniqueLlmMaterialEnvBindings(normalized.llmRoutes);
1261
+ const generatedLlmEnvFields = llmEnvBindings
1262
+ .map((binding) => ` readonly ${binding.envName}?: string;`)
1263
+ .join("\n");
1264
+ const imports = [
1265
+ `import semanticDeclarations from "./manifest.json";`,
1266
+ `import deploymentProvenance from "./deployment.json";`,
1267
+ ...(hasSchedules
1268
+ ? [renderNamedImport(["dispatchGeneratedScheduleDelivery"], "./schedules")]
1269
+ : []),
1270
+ renderNamedImport(["createAgentDurableObject"], modules.cloudflareDoRuntime),
1271
+ renderNamedImport(["runDynamicCapabilityResolvers"], modules.runtimeCapability),
1272
+ renderNamedImport(["OpenAiCompatibleLlmTransportLive", "preflightOpenAiCompatibleProviderMaterial"], modules.openAiCompatibleTransport),
1273
+ renderNamedImport(["DYNAMIC_CAPABILITY_EVENT", "manifestTruthIdentity"], modules.runtimeProtocol),
1274
+ renderNamedImport(["projectAgentSession", "projectAgentSessions", "projectWorkflowRun", "projectWorkflowRuns"], modules.runtimeRunProjector),
1275
+ renderNamedImport([
1276
+ "deterministicToolInvocation",
1277
+ ...(hasSkills ? ["defineProductTool"] : []),
1278
+ "unsafeRunToolByName",
1279
+ ], modules.coreTools),
1280
+ renderNamedImport(hasSkills ? ["Effect", "Schema"] : ["Effect"], modules.effect),
1281
+ renderTypeImport(["AgentManifest", "AgentSubmitBindings", "SubmitResult", "SubmitRunInput"], modules.runtimeProtocol),
1282
+ ...(hasDynamicCapability
1283
+ ? [
1284
+ renderTypeImport([
1285
+ "DynamicCapabilityCompiledCatalog",
1286
+ "DynamicCapabilityEventRef",
1287
+ "DynamicCapabilityProjection",
1288
+ "DynamicCapabilityRunInput",
1289
+ "SubmitInstructionFragment",
1290
+ ], modules.runtimeProtocol),
1291
+ renderTypeImport(["DynamicCapabilityResolverDefinition"], modules.runtimeCapability),
1292
+ ]
1293
+ : []),
1294
+ renderTypeImport([
1295
+ "AgentSessionListProjection",
1296
+ "AgentSessionProjection",
1297
+ "WorkflowRunListProjection",
1298
+ "WorkflowRunProjection",
1299
+ ], modules.runtimeRunProjector),
1300
+ renderTypeImport(["AgentSubmitSpec"], modules.cloudflareDoRuntime),
1301
+ ...(hasSchedules ? [renderTypeImport(["GeneratedScheduleTriggerInput"], "./schedules")] : []),
1302
+ renderTypeImport([
1303
+ "WorkspaceAgentCustomCommandInput",
1304
+ "WorkspaceAgentDecideInputRequestCommandInput",
1305
+ "WorkspaceAgentResumeInputRequestCommandInput",
1306
+ ], modules.workspaceAgentHost),
1307
+ renderTypeImport(["Tool"], modules.coreTools),
1308
+ ...(toolImports.length === 0 ? [] : [toolImports]),
1309
+ ].join("\n");
1310
+ return `${imports}
1311
+
1312
+ export const targetDeclarations = semanticDeclarations;
1313
+ export const targetDeployment = deploymentProvenance;
1314
+
1315
+ const semanticManifest = semanticDeclarations as AgentManifest;
1316
+ const semanticTruthIdentity = manifestTruthIdentity(semanticManifest);
1317
+ const generatedHandler = () => undefined;
1318
+
1319
+ type AgentOSTargetEnv = {
1320
+ readonly [binding: string]: unknown;
1321
+ ${generatedLlmEnvFields}
1322
+ };
1323
+
1324
+ type GeneratedTargetFailure = {
1325
+ readonly ok: false;
1326
+ readonly message: string;
1327
+ readonly diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>;
1328
+ };
1329
+
1330
+ type GeneratedTargetResult<Value> =
1331
+ | { readonly ok: true; readonly value: Value }
1332
+ | GeneratedTargetFailure;
1333
+
1334
+ const targetFailure = (
1335
+ message: string,
1336
+ diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>,
1337
+ ): GeneratedTargetFailure => ({
1338
+ ok: false,
1339
+ message,
1340
+ ...(diagnostics === undefined || diagnostics.length === 0 ? {} : { diagnostics }),
1341
+ });
1342
+
1343
+ const rejectTargetFailure = (failure: GeneratedTargetFailure): Promise<never> => {
1344
+ const error = Error(failure.message) as Error & {
1345
+ diagnostics?: ReturnType<typeof preflightOpenAiCompatibleProviderMaterial>;
1346
+ };
1347
+ if (failure.diagnostics !== undefined) error.diagnostics = failure.diagnostics;
1348
+ return Promise.reject(error);
1349
+ };
1350
+
1351
+ const generatedCustomTools = ${customToolRecord} satisfies Readonly<Record<string, Tool>>;
1352
+ ${renderDynamicCapabilitySupport(normalized, toolNames, hasSkills)}
1353
+ ${renderSkillSupport(normalized.skills)}
1354
+
1355
+ const materialEnvValue = (env: AgentOSTargetEnv, name: string): string | null => {
1356
+ const value = env[name];
1357
+ return typeof value === "string" && value.length > 0 ? value : null;
1358
+ };
1359
+
1360
+ ${renderMaterialValueFunction(normalized.llmRoutes)}
1361
+ ${renderGeneratedProviderPreflight(normalized.llmRoutes)}
1362
+
1363
+ const requiredStringMaterial = (
1364
+ kind: string,
1365
+ ref: string,
1366
+ value: NonNullable<unknown> | null,
1367
+ ): GeneratedTargetResult<string> => {
1368
+ if (typeof value === "string" && value.length > 0) return { ok: true, value };
1369
+ return targetFailure(\`missing \${kind} material: \${ref}\`);
1370
+ };
1371
+
1372
+ ${renderGeneratedLlmRoutesFor(normalized.llmRoutes)}
1373
+
1374
+ const generatedSubmitBindingsFor = async (
1375
+ env: AgentOSTargetEnv,
1376
+ event: DynamicCapabilityEventRef = generatedDynamicCapabilityTurnEvent(),
1377
+ dynamicCapability: DynamicCapabilityRunInput | undefined = undefined,
1378
+ ): Promise<GeneratedTargetResult<AgentSubmitBindings>> => {
1379
+ const preflightDiagnostics = generatedProviderPreflightDiagnosticsFor(env);
1380
+ if (preflightDiagnostics.length > 0) {
1381
+ return targetFailure(
1382
+ "OpenAI-compatible provider material preflight failed",
1383
+ preflightDiagnostics,
1384
+ );
1385
+ }
1386
+ const routes = generatedLlmRoutesFor(env);
1387
+ if (!routes.ok) return routes;
1388
+ const dynamicBindings = await generatedDynamicSubmitBindingsFor(event, dynamicCapability);
1389
+ if (!dynamicBindings.ok) return dynamicBindings;
1390
+ const dynamicCapabilityProjection = dynamicBindings.value.dynamicCapabilityProjection;
1391
+ return {
1392
+ ok: true,
1393
+ value: {
1394
+ ...dynamicBindings.value,
1395
+ llmRoutes: routes.value,
1396
+ tools: ${hasSkills
1397
+ ? `{
1398
+ ...generatedCustomTools,
1399
+ ...generatedFrameworkToolsFor(dynamicCapabilityProjection),
1400
+ }`
1401
+ : "generatedCustomTools"},
1402
+ },
1403
+ };
1404
+ };
1405
+
1406
+ ${renderSubmitSpecFromRunInput(hasSkills)}
1407
+
1408
+ ${renderProductApiHelpers()}
1409
+ ${hasSchedules ? renderScheduleDurableObjectHelpers() : ""}
1410
+
1411
+ const Base${target.durableObject.className} = createAgentDurableObject<AgentOSTargetEnv>({
1412
+ manifest: semanticManifest,
1413
+ agentBindings: {
1414
+ handlers: ${handlerRecord},
1415
+ },
1416
+ refResolver: (env) => ({
1417
+ material: (ref) => materialValue(env, ref),
1418
+ }),
1419
+ llmTransport: () => OpenAiCompatibleLlmTransportLive,
1420
+ });
1421
+
1422
+ export class ${target.durableObject.className} extends Base${target.durableObject.className} {
1423
+ private readonly targetEnv: AgentOSTargetEnv;
1424
+
1425
+ constructor(ctx: DurableObjectState, env: AgentOSTargetEnv) {
1426
+ super(ctx, env);
1427
+ this.targetEnv = env;
1428
+ }
1429
+
1430
+ override submit(spec: AgentSubmitSpec): Promise<SubmitResult> {
1431
+ return generatedSubmitBindingsFor(
1432
+ this.targetEnv,
1433
+ generatedDynamicCapabilityTurnEvent(),
1434
+ spec.dynamicCapability,
1435
+ ).then((bindings) =>
1436
+ bindings.ok ? this.submitWithBindings(spec, bindings.value) : rejectTargetFailure(bindings),
1437
+ );
1438
+ }
1439
+
1440
+ submitRunInput(input: SubmitRunInput): Promise<SubmitResult> {
1441
+ return generatedSubmitBindingsFor(
1442
+ this.targetEnv,
1443
+ generatedDynamicCapabilityTurnEvent(),
1444
+ input.dynamicCapability,
1445
+ ).then((bindings) =>
1446
+ bindings.ok
1447
+ ? this.submitWithBindings(
1448
+ submitSpecFromRunInput(input, bindings.value.dynamicCapabilityProjection),
1449
+ bindings.value,
1450
+ )
1451
+ : rejectTargetFailure(bindings),
1452
+ );
1453
+ }
1454
+
1455
+ ${renderProductApiDurableObjectMethods()}
1456
+ ${hasSchedules ? renderScheduleDurableObjectMethod() : ""}
1457
+
1458
+ resumeInputRequest(input: WorkspaceAgentResumeInputRequestCommandInput): Promise<SubmitResult> {
1459
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1460
+ bindings.ok
1461
+ ? this.resumeInputRequestWithBindings(input, bindings.value)
1462
+ : rejectTargetFailure(bindings),
1463
+ );
1464
+ }
1465
+
1466
+ decideInputRequest(input: WorkspaceAgentDecideInputRequestCommandInput): Promise<SubmitResult> {
1467
+ return generatedSubmitBindingsFor(this.targetEnv).then((bindings) =>
1468
+ bindings.ok
1469
+ ? this.decideInputRequestWithBindings(input, bindings.value)
1470
+ : rejectTargetFailure(bindings),
1471
+ );
1472
+ }
1473
+
1474
+ customCommand(input: WorkspaceAgentCustomCommandInput): Promise<unknown> {
1475
+ return Effect.runPromise(
1476
+ unsafeRunToolByName(
1477
+ generatedCustomTools,
1478
+ deterministicToolInvocation(input.method, input.input),
1479
+ ),
1480
+ );
1481
+ }
1482
+ }
1483
+ `;
1484
+ };
1485
+ const renderLocalAgentApp = (normalized, toolNames, modules) => {
1486
+ if (normalized.target.kind !== AGENTOS_CONFIG_TARGET.NODE_V1) {
1487
+ throw new TypeError(`local agent app renderer received ${normalized.target.kind}`);
1488
+ }
1489
+ const hasChannels = normalized.channels.length > 0;
1490
+ const hasSkills = normalized.skills.length > 0;
1491
+ const hasSchedules = normalized.schedules.length > 0;
1492
+ const authoredToolNames = new Set(normalized.authoredToolNames);
1493
+ const workspaceToolList = toolNames.filter((toolName) => isWorkspaceToolName(toolName) && !authoredToolNames.has(toolName));
1494
+ const customToolNames = toolNames.filter((toolName) => authoredToolNames.has(toolName));
1495
+ const toolImports = customToolNames
1496
+ .map((toolName, index) => `import tool_${index} from ${jsString(importToolPath(toolName))};`)
1497
+ .join("\n");
1498
+ const customToolRecord = customToolNames.length === 0
1499
+ ? "{}"
1500
+ : `{\n${customToolNames
1501
+ .map((toolName, index) => ` ${jsString(toolName)}: tool_${index},`)
1502
+ .join("\n")}\n}`;
1503
+ const workspaceToolArray = `[${workspaceToolList.map(jsString).join(", ")}] as const`;
1504
+ const usesMutationTools = workspaceToolList.some((toolName) => workspaceMutationToolNames.has(toolName));
1505
+ const usesShellTools = workspaceToolList.some((toolName) => workspaceShellToolNames.has(toolName));
469
1506
  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
1507
  const imports = [
474
1508
  `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),
1509
+ ...(hasChannels ? [renderNamedImport(["dispatchGeneratedChannelRequest"], "./channels")] : []),
1510
+ ...(hasChannels ? [renderTypeImport(["ChannelRuntime"], modules.runtimeChannel)] : []),
1511
+ ...(hasSchedules
1512
+ ? [
1513
+ renderNamedImport([
1514
+ "dispatchGeneratedScheduleDelivery",
1515
+ "generatedScheduleDefinitions",
1516
+ "generatedScheduleIds",
1517
+ ], "./schedules"),
1518
+ ]
1519
+ : []),
1520
+ ...(hasSchedules ? [renderTypeImport(["GeneratedScheduleTriggerInput"], "./schedules")] : []),
1521
+ renderNamedImport(["lowerLocalAgentRuntime"], modules.localRuntime),
1522
+ renderNamedImport(["runDynamicCapabilityResolvers"], modules.runtimeCapability),
1523
+ ...(hasSchedules
1524
+ ? [renderNamedImport(["projectScheduleFireHistory"], modules.runtimeSchedule)]
1525
+ : []),
1526
+ renderNamedImport(["DYNAMIC_CAPABILITY_EVENT", "manifestTruthIdentity"], modules.runtimeProtocol),
1527
+ renderNamedImport(["OpenAiCompatibleLlmTransportLive", "preflightOpenAiCompatibleProviderMaterial"], modules.openAiCompatibleTransport),
1528
+ renderNamedImport([
1529
+ "projectAgentSession",
1530
+ "projectAgentSessions",
1531
+ "projectRunInspection",
1532
+ "projectWorkflowRun",
1533
+ "projectWorkflowRuns",
1534
+ ], modules.runtimeRunProjector),
1535
+ renderTypeImport(["AgentManifest", "SubmitResult", "SubmitRunInput"], modules.runtimeProtocol),
482
1536
  renderTypeImport([
483
- "WorkspaceAgentCustomCommandInput",
484
- "WorkspaceAgentDecideInputRequestCommandInput",
485
- "WorkspaceAgentResumeInputRequestCommandInput",
486
- ], modules.workspaceAgentHost),
1537
+ "AgentSubmitBindings",
1538
+ "DynamicCapabilityCompiledCatalog",
1539
+ "DynamicCapabilityEventRef",
1540
+ "DynamicCapabilityProjection",
1541
+ "DynamicCapabilityRunInput",
1542
+ "SubmitInstructionFragment",
1543
+ ], modules.runtimeProtocol),
1544
+ renderTypeImport(["DynamicCapabilityResolverDefinition"], modules.runtimeCapability),
1545
+ ...(hasSchedules
1546
+ ? [
1547
+ renderTypeImport([
1548
+ "ScheduleDefinitionProjection",
1549
+ "ScheduleFireHistoryProjection",
1550
+ "ScheduleFireProjection",
1551
+ ], modules.runtimeSchedule),
1552
+ ]
1553
+ : []),
1554
+ renderTypeImport([
1555
+ "AgentSessionListProjection",
1556
+ "AgentSessionProjection",
1557
+ "RunInspection",
1558
+ "WorkflowRunListProjection",
1559
+ "WorkflowRunProjection",
1560
+ ], modules.runtimeRunProjector),
1561
+ renderTypeImport(["CreateLocalAgentRuntimeOptions", "LocalAgentRuntime", "LocalAgentSubmitInput"], modules.localRuntime),
1562
+ renderTypeImport(["WorkspaceAgentCustomCommandInput"], modules.workspaceAgentHost),
1563
+ renderNamedImport([
1564
+ ...(hasSkills ? ["defineProductTool"] : []),
1565
+ "deterministicToolInvocation",
1566
+ "unsafeRunToolByName",
1567
+ ], modules.coreTools),
1568
+ renderNamedImport(hasSkills ? ["Effect", "Schema"] : ["Effect"], modules.effect),
487
1569
  renderTypeImport(["Tool"], modules.coreTools),
488
1570
  ...(toolImports.length === 0 ? [] : [toolImports]),
489
1571
  ].join("\n");
490
1572
  return `${imports}
491
1573
 
492
- export const targetDeclarations = semanticDeclarations;
493
- export const targetDeployment = deploymentProvenance;
494
-
495
1574
  const semanticManifest = semanticDeclarations as AgentManifest;
496
- const generatedHandler = () => undefined;
1575
+ const semanticTruthIdentity = manifestTruthIdentity(semanticManifest);
497
1576
 
498
- type AgentOSTargetEnv = {
499
- readonly [binding: string]: unknown;
500
- ${generatedLlmEnvFields}
501
- };
1577
+ type AgentOSTargetEnv = Readonly<Record<string, string | undefined>>;
502
1578
 
503
1579
  type GeneratedTargetFailure = {
504
1580
  readonly ok: false;
@@ -509,12 +1585,33 @@ type GeneratedTargetResult<Value> =
509
1585
  | { readonly ok: true; readonly value: Value }
510
1586
  | GeneratedTargetFailure;
511
1587
 
512
- const targetFailure = (message: string): GeneratedTargetFailure => ({ ok: false, message });
1588
+ const targetFailure = (message: string): GeneratedTargetFailure => ({
1589
+ ok: false,
1590
+ message,
1591
+ });
513
1592
 
514
1593
  const rejectTargetFailure = (failure: GeneratedTargetFailure): Promise<never> =>
515
1594
  Promise.reject(Error(failure.message));
516
1595
 
1596
+ ${renderGeneratedWorkspaceOperations(workspaceToolArray, usesMutationTools, usesShellTools)}
517
1597
  const generatedCustomTools = ${customToolRecord} satisfies Readonly<Record<string, Tool>>;
1598
+ ${renderDynamicCapabilitySupport(normalized, toolNames, hasSkills)}
1599
+ ${renderSkillSupport(normalized.skills)}
1600
+
1601
+ const cleanEnv = (source: AgentOSTargetEnv): Record<string, string> => {
1602
+ const env: Record<string, string> = {};
1603
+ for (const [key, value] of Object.entries(source)) {
1604
+ if (value !== undefined) env[key] = value;
1605
+ }
1606
+ return env;
1607
+ };
1608
+
1609
+ const generatedTargetEnvFor = (
1610
+ options: Pick<CreateLocalAgentAppOptions, "env" | "inheritEnv">,
1611
+ ): AgentOSTargetEnv => ({
1612
+ ...(options.inheritEnv === true ? cleanEnv(process.env) : {}),
1613
+ ...(options.env === undefined ? {} : cleanEnv(options.env)),
1614
+ });
518
1615
 
519
1616
  const materialEnvValue = (env: AgentOSTargetEnv, name: string): string | null => {
520
1617
  const value = env[name];
@@ -537,124 +1634,221 @@ const materialValue = (
537
1634
  return null;
538
1635
  };
539
1636
 
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;
1637
+ const generatedLocalLlmFor = (
1638
+ env: AgentOSTargetEnv,
1639
+ ): NonNullable<CreateLocalAgentRuntimeOptions["llm"]> => {
1640
+ const modelValue = materialValue(env, { kind: "model", ref: ${jsString(normalized.llm.modelRef)} });
556
1641
  return {
557
- ok: true,
558
- value: {
1642
+ kind: "transport",
1643
+ transport: OpenAiCompatibleLlmTransportLive,
1644
+ route: {
559
1645
  kind: "openai-chat-compatible",
560
1646
  endpointRef: ${jsString(normalized.llm.endpointRef)},
561
1647
  credentialRef: ${jsString(normalized.llm.credentialRef)},
562
- modelId: modelId.value,
1648
+ modelId: typeof modelValue === "string" ? modelValue : "",
1649
+ },
1650
+ refResolver: {
1651
+ material: (ref) => materialValue(env, ref),
563
1652
  },
1653
+ preflight: preflightOpenAiCompatibleProviderMaterial,
564
1654
  };
565
1655
  };
566
1656
 
567
- const generatedSubmitBindingsFor = (env: AgentOSTargetEnv): GeneratedTargetResult<AgentSubmitBindings> => {
568
- const route = generatedLlmRouteFor(env);
569
- if (!route.ok) return route;
1657
+ ${renderProductApiHelpers()}
1658
+
1659
+ const generatedLocalSubmitInputFromRunInput = async (
1660
+ input: SubmitRunInput,
1661
+ event: DynamicCapabilityEventRef = generatedDynamicCapabilityTurnEvent(),
1662
+ ): Promise<LocalAgentSubmitInput> => {
1663
+ const dynamicBindings = await generatedDynamicSubmitBindingsFor(event, input.dynamicCapability);
1664
+ if (!dynamicBindings.ok) return rejectTargetFailure(dynamicBindings);
1665
+ const dynamicCapabilityProjection = dynamicBindings.value.dynamicCapabilityProjection;
570
1666
  return {
571
- ok: true,
572
- value: {
573
- llmRoutes: {
574
- default: route.value,
575
- },
576
- tools: generatedCustomTools,
577
- },
1667
+ ...input,
1668
+ ...(input.context === undefined ? {} : { context: input.context }),
1669
+ ...(input.system === undefined && !${hasSkills} ? {} : {
1670
+ system: ${hasSkills ? "generatedSystemPrompt(input.system, dynamicCapabilityProjection)" : "input.system"},
1671
+ }),
1672
+ dynamicCapabilityProjection,
1673
+ instructionFragments: dynamicBindings.value.instructionFragments,
1674
+ tools: ${hasSkills
1675
+ ? `{
1676
+ ...generatedCustomTools,
1677
+ ...generatedFrameworkToolsFor(dynamicCapabilityProjection),
1678
+ }`
1679
+ : "generatedCustomTools"},
578
1680
  };
579
1681
  };
580
1682
 
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
- }
1683
+ export interface LocalAgentAppRuntime extends LocalAgentRuntime {
1684
+ readonly inspectRun: (runId: number | string) => RunInspection;
1685
+ }
628
1686
 
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
- }
1687
+ export interface LocalAgentApp {
1688
+ readonly runtime: LocalAgentAppRuntime;
1689
+ readonly sessions: {
1690
+ readonly submitTurn: (input: AgentSessionSubmitTurnInput) => Promise<SubmitResult>;
1691
+ readonly inspect: (sessionRef: string) => AgentSessionProjection;
1692
+ readonly list: () => AgentSessionListProjection;
1693
+ };
1694
+ readonly workflows: {
1695
+ readonly run: (input: AgentWorkflowRunInput) => Promise<SubmitResult>;
1696
+ readonly inspectRun: (
1697
+ workflowId: string,
1698
+ workflowRunId: string,
1699
+ ) => WorkflowRunProjection | null;
1700
+ readonly listRuns: (workflowId: string) => WorkflowRunListProjection;
1701
+ };
1702
+ ${hasChannels
1703
+ ? `readonly channels: {
1704
+ readonly handle: (request: Request) => Promise<Response | null>;
1705
+ };`
1706
+ : ""}
1707
+ readonly customCommand: (input: WorkspaceAgentCustomCommandInput) => Promise<unknown>;
1708
+ ${hasSchedules
1709
+ ? `readonly schedules: {
1710
+ readonly ids: ReadonlyArray<string>;
1711
+ readonly list: () => ReadonlyArray<ScheduleDefinitionProjection>;
1712
+ readonly trigger: (input: GeneratedScheduleTriggerInput) => Promise<ScheduleFireProjection>;
1713
+ readonly history: (input?: { readonly scheduleId?: string }) => ScheduleFireHistoryProjection;
1714
+ };`
1715
+ : ""}
1716
+ }
635
1717
 
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
- }
1718
+ ${hasChannels
1719
+ ? `export const handleLocalAgentChannelRequest = (
1720
+ request: Request,
1721
+ runtime: ChannelRuntime,
1722
+ ): Promise<Response | null> => dispatchGeneratedChannelRequest(request, runtime);`
1723
+ : ""}
1724
+
1725
+ export interface CreateLocalAgentAppOptions {
1726
+ readonly cwd?: string;
1727
+ readonly env?: CreateLocalAgentRuntimeOptions["env"];
1728
+ readonly inheritEnv?: CreateLocalAgentRuntimeOptions["inheritEnv"];
1729
+ readonly llm?: CreateLocalAgentRuntimeOptions["llm"];
1730
+ }
642
1731
 
643
- customCommand(input: WorkspaceAgentCustomCommandInput): Promise<unknown> {
644
- return Effect.runPromise(
1732
+ export const createLocalAgentApp = async (
1733
+ options: CreateLocalAgentAppOptions = {},
1734
+ ): Promise<LocalAgentApp> => {
1735
+ const targetEnv = generatedTargetEnvFor(options);
1736
+ const lowered = await lowerLocalAgentRuntime({
1737
+ target: "node@1",
1738
+ identity: semanticManifest.agentId,
1739
+ truthIdentity: semanticTruthIdentity,
1740
+ cwd: options.cwd ?? process.cwd(),
1741
+ ...(options.env === undefined ? {} : { env: options.env }),
1742
+ ...(options.inheritEnv === undefined ? {} : { inheritEnv: options.inheritEnv }),
1743
+ llm: options.llm ?? generatedLocalLlmFor(targetEnv),
1744
+ workspaceOperations: generatedWorkspaceOperations,
1745
+ });
1746
+ const sessions = {
1747
+ submitTurn: (input: AgentSessionSubmitTurnInput) =>
1748
+ generatedLocalSubmitInputFromRunInput(
1749
+ submitRunInputFromSessionTurn(input),
1750
+ generatedDynamicCapabilityTurnEvent({
1751
+ sessionRef: input.sessionRef,
1752
+ turnRef: input.turnRef,
1753
+ }),
1754
+ ).then((submitInput) =>
1755
+ lowered.submitWithProductLink(submitInput, {
1756
+ kind: "session_turn",
1757
+ sessionRef: input.sessionRef,
1758
+ turnRef: input.turnRef,
1759
+ ...(input.idempotencyKey === undefined ? {} : { idempotencyKey: input.idempotencyKey }),
1760
+ }),
1761
+ ),
1762
+ inspect: (sessionRef: string) => projectAgentSession(lowered.runtime.events(), sessionRef),
1763
+ list: () => projectAgentSessions(lowered.runtime.events()),
1764
+ };
1765
+ const workflows = {
1766
+ run: (input: AgentWorkflowRunInput) =>
1767
+ generatedLocalSubmitInputFromRunInput(submitRunInputFromWorkflowRun(input)).then(
1768
+ (submitInput) =>
1769
+ lowered.submitWithProductLink(submitInput, {
1770
+ kind: "workflow_run",
1771
+ workflowId: input.workflowId,
1772
+ workflowRunId: input.workflowRunId,
1773
+ ...(input.idempotencyKey === undefined ? {} : { idempotencyKey: input.idempotencyKey }),
1774
+ ...(input.inputDigest === undefined ? {} : { inputDigest: input.inputDigest }),
1775
+ }),
1776
+ ),
1777
+ inspectRun: (workflowId: string, workflowRunId: string) =>
1778
+ projectWorkflowRun(lowered.runtime.events(), workflowId, workflowRunId),
1779
+ listRuns: (workflowId: string) => projectWorkflowRuns(lowered.runtime.events(), workflowId),
1780
+ };
1781
+ const runtime: LocalAgentAppRuntime = {
1782
+ ...lowered.runtime,
1783
+ inspectRun: (runId) =>
1784
+ projectRunInspection(lowered.runtime.events(), runId, lowered.runtime.diagnostics()),
1785
+ };
1786
+ ${hasChannels
1787
+ ? `const channelRuntime: ChannelRuntime = {
1788
+ submit: (input) => lowered.runtime.submit(input),
1789
+ dispatch: async () => {
1790
+ throw new Error("local node channel dispatch is unavailable");
1791
+ },
1792
+ };
1793
+ const channels = {
1794
+ handle: (request: Request) => handleLocalAgentChannelRequest(request, channelRuntime),
1795
+ };`
1796
+ : ""}
1797
+ const customCommand = (input: WorkspaceAgentCustomCommandInput): Promise<unknown> =>
1798
+ Effect.runPromise(
645
1799
  unsafeRunToolByName(
646
1800
  generatedCustomTools,
647
1801
  deterministicToolInvocation(input.method, input.input),
648
1802
  ),
649
1803
  );
650
- }
651
- }
1804
+ ${hasSchedules
1805
+ ? `const scheduleHistory = (
1806
+ input: { readonly scheduleId?: string } = {},
1807
+ ): ScheduleFireHistoryProjection => projectScheduleFireHistory(lowered.runtime.events(), input);
1808
+ const triggerSchedule = async (
1809
+ input: GeneratedScheduleTriggerInput,
1810
+ ): Promise<ScheduleFireProjection> => {
1811
+ const result = await dispatchGeneratedScheduleDelivery({
1812
+ ...input,
1813
+ history: lowered.runtime.events(),
1814
+ identity: semanticTruthIdentity,
1815
+ runtime: { sessions, workflows },
1816
+ });
1817
+ if (result.kind === "attempt") {
1818
+ await lowered.commitScheduleFireDispatchWithDelivery(result);
1819
+ }
1820
+ const projected = scheduleHistory({ scheduleId: input.scheduleId }).fires.find(
1821
+ (fire) => fire.fireId === result.fireId,
1822
+ );
1823
+ if (projected === undefined) {
1824
+ throw new Error(\`schedule fire projection missing after commit: \${result.fireId}\`);
1825
+ }
1826
+ return projected;
1827
+ };`
1828
+ : ""}
1829
+ return {
1830
+ runtime,
1831
+ sessions,
1832
+ workflows,
1833
+ ${hasChannels ? "channels,\n " : ""}customCommand,
1834
+ ${hasSchedules
1835
+ ? `schedules: {
1836
+ ids: generatedScheduleIds,
1837
+ list: () => generatedScheduleDefinitions,
1838
+ trigger: triggerSchedule,
1839
+ history: scheduleHistory,
1840
+ },`
1841
+ : ""}
1842
+ };
1843
+ };
652
1844
  `;
653
1845
  };
654
1846
  const renderStaticTarget = (normalized, toolNames, modules) => normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
655
1847
  ? renderWorkspaceStaticTarget(normalized, toolNames, modules)
656
1848
  : renderChatStaticTarget(normalized, toolNames, modules);
657
- const renderCloudflareScopeHelper = (normalized, modules) => `${renderNamedImport(["durableObjectRpcClient"], `${modules.cloudflareDoRuntime}/do-rpc`)}
1849
+ const renderCloudflareScopeHelper = (normalized, modules) => {
1850
+ const target = cloudflareTargetFor(normalized.target);
1851
+ return `${renderNamedImport(["durableObjectRpcClient"], `${modules.cloudflareDoRuntime}/do-rpc`)}
658
1852
  ${renderNamedImport(["manifestTruthIdentity"], modules.runtimeProtocol)}
659
1853
  ${renderTypeImport(["AgentRuntimeClient"], modules.cloudflareDoRuntime)}
660
1854
  ${renderTypeImport(["DurableObjectRpcClient"], `${modules.cloudflareDoRuntime}/do-rpc`)}
@@ -667,7 +1861,7 @@ export type AgentOSTargetEnv = {
667
1861
 
668
1862
  export const agentOSTruthIdentity = manifestTruthIdentity(manifest as AgentManifest);
669
1863
  export const agentOSScopeId = agentOSTruthIdentity.scopeRef.scopeId;
670
- export const agentOSDurableObjectBinding = ${jsString(normalized.target.durableObject.binding)};
1864
+ export const agentOSDurableObjectBinding = ${jsString(target.durableObject.binding)};
671
1865
 
672
1866
  export const agentOSDurableObjectNamespace = (
673
1867
  env: AgentOSTargetEnv,
@@ -681,18 +1875,79 @@ export const agentOSRpcClient = <
681
1875
  scopeId: string = agentOSScopeId,
682
1876
  ): DurableObjectRpcClient<Rpc> => durableObjectRpcClient<Rpc>(agentOSDurableObjectNamespace(env), scopeId);
683
1877
  `;
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")}
1878
+ };
1879
+ const renderCloudflareWorkerEntry = (normalized, modules) => {
1880
+ const target = cloudflareTargetFor(normalized.target);
1881
+ const hasChannels = normalized.channels.length > 0;
1882
+ const hasSchedules = normalized.schedules.length > 0;
1883
+ const cloudflareScopeImports = [
1884
+ ...(hasChannels || hasSchedules ? ["agentOSRpcClient"] : []),
1885
+ ...(hasSchedules ? ["agentOSScopeId"] : []),
1886
+ ];
1887
+ return `${normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1 ? `${renderNamedImport(["Sandbox"], modules.cloudflareSandbox)}\n` : ""}${renderNamedImport([target.durableObject.className], "./target")}
1888
+ ${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")}
1889
+
1890
+ export { ${target.durableObject.className}${normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1 ? ", Sandbox" : ""} };
686
1891
 
687
- export { ${normalized.target.durableObject.className}${normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1 ? ", Sandbox" : ""} };
1892
+ ${hasChannels
1893
+ ? `type AgentOSChannelRpc = Pick<AgentRuntimeClient, "events" | "streamEvents"> & {
1894
+ readonly submitRunInput: ChannelRuntime["submit"];
1895
+ readonly dispatchToScope: ChannelRuntime["dispatch"];
1896
+ };
1897
+
1898
+ const generatedChannelRuntimeFor = (env: AgentOSTargetEnv): ChannelRuntime => {
1899
+ const runtime = agentOSRpcClient<AgentOSChannelRpc>(env);
1900
+ return Object.freeze({
1901
+ submit: (input) => runtime.submitRunInput(input),
1902
+ dispatch: (spec) => runtime.dispatchToScope(spec),
1903
+ });
1904
+ };
1905
+ `
1906
+ : ""}
1907
+ ${hasSchedules
1908
+ ? `type AgentOSScheduleRpc = {
1909
+ readonly dispatchSchedule: (input: GeneratedScheduleTriggerInput) => Promise<unknown>;
1910
+ };
1911
+
1912
+ const generatedScheduleAppPrincipal: GeneratedScheduleTriggerInput["appPrincipal"] = {
1913
+ authority: "agentos.app",
1914
+ subject: agentOSScopeId,
1915
+ };
1916
+
1917
+ const generatedScheduleInputsFor = (
1918
+ controller: ScheduledController,
1919
+ ): ReadonlyArray<GeneratedScheduleTriggerInput> =>
1920
+ generatedSchedules
1921
+ .filter((entry) => entry.cron === controller.cron)
1922
+ .map((entry) => ({
1923
+ scheduleId: entry.scheduleId,
1924
+ scheduledAt: controller.scheduledTime,
1925
+ appPrincipal: generatedScheduleAppPrincipal,
1926
+ }));
1927
+ `
1928
+ : ""}
688
1929
 
689
1930
  export default {
690
- fetch(): Response {
1931
+ async fetch(request: Request, env: AgentOSTargetEnv): Promise<Response> {
1932
+ ${hasChannels
1933
+ ? `const channelResponse = await dispatchGeneratedChannelRequest(request, generatedChannelRuntimeFor(env));
1934
+ if (channelResponse !== null) return channelResponse;`
1935
+ : ""}
691
1936
  return new Response("agentOS Cloudflare target", { status: 404 });
692
1937
  },
1938
+ ${hasSchedules
1939
+ ? `scheduled(controller: ScheduledController, env: AgentOSTargetEnv, ctx: ExecutionContext): void {
1940
+ const runtime = agentOSRpcClient<AgentOSScheduleRpc>(env);
1941
+ for (const input of generatedScheduleInputsFor(controller)) {
1942
+ ctx.waitUntil(runtime.dispatchSchedule(input));
1943
+ }
1944
+ },`
1945
+ : ""}
693
1946
  } satisfies ExportedHandler<AgentOSTargetEnv>;
694
1947
  `;
1948
+ };
695
1949
  const renderCloudflareWranglerConfig = (normalized) => {
1950
+ const target = cloudflareTargetFor(normalized.target);
696
1951
  const workspaceConfig = normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
697
1952
  ? {
698
1953
  vars: {
@@ -713,15 +1968,15 @@ const renderCloudflareWranglerConfig = (normalized) => {
713
1968
  name: normalized.workspace.binding,
714
1969
  },
715
1970
  {
716
- class_name: normalized.target.durableObject.className,
717
- name: normalized.target.durableObject.binding,
1971
+ class_name: target.durableObject.className,
1972
+ name: target.durableObject.binding,
718
1973
  },
719
1974
  ],
720
1975
  },
721
1976
  migrations: [
722
1977
  {
723
1978
  tag: "v1",
724
- new_sqlite_classes: ["Sandbox", normalized.target.durableObject.className],
1979
+ new_sqlite_classes: ["Sandbox", target.durableObject.className],
725
1980
  },
726
1981
  ],
727
1982
  }
@@ -729,15 +1984,15 @@ const renderCloudflareWranglerConfig = (normalized) => {
729
1984
  durable_objects: {
730
1985
  bindings: [
731
1986
  {
732
- class_name: normalized.target.durableObject.className,
733
- name: normalized.target.durableObject.binding,
1987
+ class_name: target.durableObject.className,
1988
+ name: target.durableObject.binding,
734
1989
  },
735
1990
  ],
736
1991
  },
737
1992
  migrations: [
738
1993
  {
739
1994
  tag: "v1",
740
- new_sqlite_classes: [normalized.target.durableObject.className],
1995
+ new_sqlite_classes: [target.durableObject.className],
741
1996
  },
742
1997
  ],
743
1998
  };
@@ -759,6 +2014,11 @@ const generatedClientModuleImports = (normalized, modules) => [
759
2014
  "createWorkspaceAgentClientBridge",
760
2015
  "CreateWorkspaceAgentClientOptions",
761
2016
  "WorkspaceAgentClientBridge",
2017
+ "WorkspaceAgentProductClient",
2018
+ "WorkspaceAgentProductCommandMap",
2019
+ "WorkspaceAgentProductProjectionTypes",
2020
+ "WorkspaceAgentProductCommandOutputByName",
2021
+ "WORKSPACE_AGENT_PRODUCT_COMMAND",
762
2022
  ]
763
2023
  : [
764
2024
  "WORKSPACE_AGENT_COMMAND",
@@ -807,11 +2067,18 @@ const renderWorkspaceSvelteKitRemote = (normalized, modules) => `${renderNamedIm
807
2067
  ${renderNamedImport(["decodeSseHttpEvents", "responseToSseHttpChunks"], modules.sseHttp)}
808
2068
  ${renderNamedImport(["Result", "Schema"], modules.effect)}
809
2069
  ${renderNamedImport(["WORKSPACE_AGENT_COMMAND"], modules.workspaceAgentHost)}
2070
+ ${renderNamedImport(["WORKSPACE_AGENT_PRODUCT_COMMAND"], modules.workspaceAgentClient)}
810
2071
  ${renderNamedImport(["decodeRuntimeLedgerEvent", "isInputRequestRef", "parseInputRequestResumePayload"], modules.runtimeProtocol)}
811
2072
  ${renderNamedImport(["agentOSRpcClient", "agentOSTruthIdentity"], "./cloudflare-scope")}
812
2073
  ${renderTypeImport(["AgentRuntimeClient"], modules.cloudflareDoRuntime)}
813
2074
  ${renderTypeImport(["SseHttpEvent"], modules.sseHttp)}
814
2075
  ${renderTypeImport(["RuntimeLedgerEvent", "SubmitResult", "SubmitRunInput"], modules.runtimeProtocol)}
2076
+ ${renderTypeImport([
2077
+ "AgentSessionListProjection",
2078
+ "AgentSessionProjection",
2079
+ "WorkflowRunListProjection",
2080
+ "WorkflowRunProjection",
2081
+ ], modules.runtimeRunProjector)}
815
2082
  ${renderTypeImport([
816
2083
  "WorkspaceAgentCustomCommandInput",
817
2084
  "WorkspaceAgentDestroyCommandInput",
@@ -822,10 +2089,28 @@ ${renderTypeImport([
822
2089
  "WorkspaceAgentReadStateCommandInput",
823
2090
  "WorkspaceAgentResetCommandInput",
824
2091
  ], modules.workspaceAgentHost)}
2092
+ ${renderTypeImport([
2093
+ "WorkspaceAgentSessionSubmitTurnInput",
2094
+ "WorkspaceAgentWorkflowRunInput",
2095
+ "WorkspaceAgentWorkflowRunRef",
2096
+ "WorkspaceAgentWorkflowRunsInput",
2097
+ ], modules.workspaceAgentClient)}
825
2098
  ${renderTypeImport(["AgentOSTargetEnv"], "./cloudflare-scope")}
826
2099
 
827
2100
  type AgentOSRpc = Pick<AgentRuntimeClient, "events" | "streamEvents"> & {
828
2101
  readonly submitRunInput: (input: SubmitRunInput) => Promise<SubmitResult>;
2102
+ readonly submitSessionTurn: (input: WorkspaceAgentSessionSubmitTurnInput) => Promise<SubmitResult>;
2103
+ readonly inspectSession: (
2104
+ input: { readonly sessionRef: string },
2105
+ ) => Promise<AgentSessionProjection>;
2106
+ readonly listSessions: () => Promise<AgentSessionListProjection>;
2107
+ readonly runWorkflow: (input: WorkspaceAgentWorkflowRunInput) => Promise<SubmitResult>;
2108
+ readonly inspectWorkflowRun: (
2109
+ input: WorkspaceAgentWorkflowRunRef,
2110
+ ) => Promise<WorkflowRunProjection | null>;
2111
+ readonly listWorkflowRuns: (
2112
+ input: WorkspaceAgentWorkflowRunsInput,
2113
+ ) => Promise<WorkflowRunListProjection>;
829
2114
  readonly resumeInputRequest: (
830
2115
  input: WorkspaceAgentResumeInputRequestCommandInput,
831
2116
  ) => Promise<SubmitResult>;
@@ -908,6 +2193,78 @@ const submitInputFromUnknown = (
908
2193
  return { ok: true, value: { input: value.input as unknown as AgentOSSubmitRunInput } };
909
2194
  };
910
2195
 
2196
+ const productSubmitInputFromUnknown = (
2197
+ value: unknown,
2198
+ label: string,
2199
+ ): GeneratedResult<AgentOSSubmitRunInput> => {
2200
+ if (!isRecord(value)) return fail(400, \`invalid \${label} command input\`);
2201
+ if (typeof value.intent !== "string" || !isRecord(value.context)) {
2202
+ return fail(400, \`invalid \${label} submit run input\`);
2203
+ }
2204
+ return { ok: true, value: value as unknown as AgentOSSubmitRunInput };
2205
+ };
2206
+
2207
+ const sessionTurnInputFromUnknown = (
2208
+ value: unknown,
2209
+ ): GeneratedResult<WorkspaceAgentSessionSubmitTurnInput> => {
2210
+ const submitInput = productSubmitInputFromUnknown(value, "submitSessionTurn");
2211
+ if (!submitInput.ok) return submitInput;
2212
+ if (!isRecord(value)) return fail(400, "invalid submitSessionTurn command input");
2213
+ if (typeof value.sessionRef !== "string" || typeof value.turnRef !== "string") {
2214
+ return fail(400, "invalid session turn identity");
2215
+ }
2216
+ return { ok: true, value: value as unknown as WorkspaceAgentSessionSubmitTurnInput };
2217
+ };
2218
+
2219
+ const sessionInspectInputFromUnknown = (
2220
+ value: unknown,
2221
+ ): GeneratedResult<{ readonly sessionRef: string }> => {
2222
+ if (!isRecord(value) || typeof value.sessionRef !== "string") {
2223
+ return fail(400, "invalid inspectSession command input");
2224
+ }
2225
+ return { ok: true, value: { sessionRef: value.sessionRef } };
2226
+ };
2227
+
2228
+ const workflowRunInputFromUnknown = (
2229
+ value: unknown,
2230
+ ): GeneratedResult<WorkspaceAgentWorkflowRunInput> => {
2231
+ const submitInput = productSubmitInputFromUnknown(value, "runWorkflow");
2232
+ if (!submitInput.ok) return submitInput;
2233
+ if (!isRecord(value)) return fail(400, "invalid runWorkflow command input");
2234
+ if (typeof value.workflowId !== "string" || typeof value.workflowRunId !== "string") {
2235
+ return fail(400, "invalid workflow run identity");
2236
+ }
2237
+ if (value.idempotencyKey !== undefined && typeof value.idempotencyKey !== "string") {
2238
+ return fail(400, "invalid workflow run idempotencyKey");
2239
+ }
2240
+ if (value.inputDigest !== undefined && typeof value.inputDigest !== "string") {
2241
+ return fail(400, "invalid workflow run inputDigest");
2242
+ }
2243
+ return { ok: true, value: value as unknown as WorkspaceAgentWorkflowRunInput };
2244
+ };
2245
+
2246
+ const workflowRunRefFromUnknown = (
2247
+ value: unknown,
2248
+ ): GeneratedResult<WorkspaceAgentWorkflowRunRef> => {
2249
+ if (!isRecord(value)) return fail(400, "invalid inspectWorkflowRun command input");
2250
+ if (typeof value.workflowId !== "string" || typeof value.workflowRunId !== "string") {
2251
+ return fail(400, "invalid workflow run identity");
2252
+ }
2253
+ return {
2254
+ ok: true,
2255
+ value: { workflowId: value.workflowId, workflowRunId: value.workflowRunId },
2256
+ };
2257
+ };
2258
+
2259
+ const workflowRunsInputFromUnknown = (
2260
+ value: unknown,
2261
+ ): GeneratedResult<WorkspaceAgentWorkflowRunsInput> => {
2262
+ if (!isRecord(value) || typeof value.workflowId !== "string") {
2263
+ return fail(400, "invalid listWorkflowRuns command input");
2264
+ }
2265
+ return { ok: true, value: { workflowId: value.workflowId } };
2266
+ };
2267
+
911
2268
  const resumeInputRequestFromUnknown = (
912
2269
  value: unknown,
913
2270
  ): GeneratedResult<WorkspaceAgentResumeInputRequestCommandInput> => {
@@ -1142,6 +2499,33 @@ export const invokeAgentCommand = command(commandInput, ({ name, input }): Promi
1142
2499
  ? runtime.submitRunInput(submitInput.value.input)
1143
2500
  : rejectFailure(submitInput);
1144
2501
  }
2502
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.SUBMIT_SESSION_TURN) {
2503
+ const sessionInput = sessionTurnInputFromUnknown(input);
2504
+ return sessionInput.ok ? runtime.submitSessionTurn(sessionInput.value) : rejectFailure(sessionInput);
2505
+ }
2506
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.INSPECT_SESSION) {
2507
+ const sessionInput = sessionInspectInputFromUnknown(input);
2508
+ return sessionInput.ok ? runtime.inspectSession(sessionInput.value) : rejectFailure(sessionInput);
2509
+ }
2510
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.LIST_SESSIONS) {
2511
+ return runtime.listSessions();
2512
+ }
2513
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.RUN_WORKFLOW) {
2514
+ const workflowInput = workflowRunInputFromUnknown(input);
2515
+ return workflowInput.ok ? runtime.runWorkflow(workflowInput.value) : rejectFailure(workflowInput);
2516
+ }
2517
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.INSPECT_WORKFLOW_RUN) {
2518
+ const workflowInput = workflowRunRefFromUnknown(input);
2519
+ return workflowInput.ok
2520
+ ? runtime.inspectWorkflowRun(workflowInput.value)
2521
+ : rejectFailure(workflowInput);
2522
+ }
2523
+ if (name === WORKSPACE_AGENT_PRODUCT_COMMAND.LIST_WORKFLOW_RUNS) {
2524
+ const workflowInput = workflowRunsInputFromUnknown(input);
2525
+ return workflowInput.ok
2526
+ ? runtime.listWorkflowRuns(workflowInput.value)
2527
+ : rejectFailure(workflowInput);
2528
+ }
1145
2529
  if (name === WORKSPACE_AGENT_COMMAND.RESUME_INPUT_REQUEST) {
1146
2530
  const resumeInput = resumeInputRequestFromUnknown(input);
1147
2531
  return resumeInput.ok
@@ -1500,10 +2884,29 @@ const renderSvelteKitRemote = (normalized, modules) => normalized.profile === AG
1500
2884
  const renderWorkspaceStaticClient = (normalized, modules) => {
1501
2885
  if (normalized.client.kind === AGENTOS_CONFIG_CLIENT.BROWSER_DIRECT_V1) {
1502
2886
  return `${renderNamedImport(["createWorkspaceAgentClientBridge"], modules.workspaceAgentClient)}
1503
- ${renderTypeImport(["CreateWorkspaceAgentClientOptions", "WorkspaceAgentClientBridge"], modules.workspaceAgentClient)}
2887
+ ${renderTypeImport([
2888
+ "AgentSessionListProjection",
2889
+ "AgentSessionProjection",
2890
+ "WorkflowRunListProjection",
2891
+ "WorkflowRunProjection",
2892
+ ], modules.runtimeRunProjector)}
2893
+ ${renderTypeImport([
2894
+ "CreateWorkspaceAgentClientOptions",
2895
+ "WorkspaceAgentClientBridge",
2896
+ "WorkspaceAgentProductCommandMap",
2897
+ "WorkspaceAgentProductProjectionTypes",
2898
+ ], modules.workspaceAgentClient)}
2899
+
2900
+ export interface GeneratedAgentClientProductProjections extends WorkspaceAgentProductProjectionTypes {
2901
+ readonly session: AgentSessionProjection;
2902
+ readonly sessionList: AgentSessionListProjection;
2903
+ readonly workflowRun: WorkflowRunProjection;
2904
+ readonly workflowRunList: WorkflowRunListProjection;
2905
+ }
1504
2906
 
1505
- export type GeneratedAgentClientOptions = CreateWorkspaceAgentClientOptions;
1506
- export type GeneratedAgentClient = WorkspaceAgentClientBridge;
2907
+ export type GeneratedAgentClientOptions =
2908
+ CreateWorkspaceAgentClientOptions<WorkspaceAgentProductCommandMap<GeneratedAgentClientProductProjections>>;
2909
+ export type GeneratedAgentClient = WorkspaceAgentClientBridge<GeneratedAgentClientProductProjections>;
1507
2910
 
1508
2911
  export const createAgentOSClient = (
1509
2912
  options: GeneratedAgentClientOptions = {},
@@ -1514,17 +2917,33 @@ export const createAgentOSClient = (
1514
2917
  import { invokeAgentCommand, runEventStream } from "./sveltekit.remote";
1515
2918
  ${renderNamedImport(["clientReadable", "selectClientReadable"], modules.clientSvelte)}
1516
2919
  ${renderTypeImport(["AgentClientSnapshot"], modules.clientCore)}
2920
+ ${renderTypeImport([
2921
+ "AgentSessionListProjection",
2922
+ "AgentSessionProjection",
2923
+ "WorkflowRunListProjection",
2924
+ "WorkflowRunProjection",
2925
+ ], modules.runtimeRunProjector)}
1517
2926
  ${renderTypeImport([
1518
2927
  "CreateWorkspaceAgentClientOptions",
1519
- "WorkspaceAgentClient",
1520
2928
  "WorkspaceAgentClientBridge",
1521
- "WorkspaceAgentCommandOutputByName",
2929
+ "WorkspaceAgentProductClient",
2930
+ "WorkspaceAgentProductCommandMap",
2931
+ "WorkspaceAgentProductProjectionTypes",
1522
2932
  ], modules.workspaceAgentClient)}
1523
2933
  ${renderTypeImport(["Readable"], modules.svelteStore)}
1524
2934
 
1525
- export type GeneratedAgentClientOptions = CreateWorkspaceAgentClientOptions;
2935
+ export interface GeneratedAgentClientProductProjections extends WorkspaceAgentProductProjectionTypes {
2936
+ readonly session: AgentSessionProjection;
2937
+ readonly sessionList: AgentSessionListProjection;
2938
+ readonly workflowRun: WorkflowRunProjection;
2939
+ readonly workflowRunList: WorkflowRunListProjection;
2940
+ }
1526
2941
 
1527
- export interface GeneratedAgentClient extends WorkspaceAgentClientBridge {
2942
+ export type GeneratedAgentClientOptions =
2943
+ CreateWorkspaceAgentClientOptions<WorkspaceAgentProductCommandMap<GeneratedAgentClientProductProjections>>;
2944
+
2945
+ export interface GeneratedAgentClient
2946
+ extends WorkspaceAgentClientBridge<GeneratedAgentClientProductProjections> {
1528
2947
  readonly snapshot: Readable<AgentClientSnapshot>;
1529
2948
  readonly events: Readable<AgentClientSnapshot["events"]>;
1530
2949
  readonly connection: Readable<AgentClientSnapshot["connection"]>;
@@ -1539,8 +2958,10 @@ const generatedStreamSource: NonNullable<GeneratedAgentClientOptions["streamSour
1539
2958
  }),
1540
2959
  };
1541
2960
 
1542
- const generatedRpcInvoker: WorkspaceAgentClient["invoke"] = (name, input) =>
1543
- invokeAgentCommand({ name, input }) as Promise<WorkspaceAgentCommandOutputByName[typeof name]>;
2961
+ const generatedRpcInvoker = ((name, input) =>
2962
+ invokeAgentCommand({ name, input })) as WorkspaceAgentProductClient<
2963
+ GeneratedAgentClientProductProjections
2964
+ >["invoke"];
1544
2965
 
1545
2966
  export const createAgentOSClient = (
1546
2967
  options: GeneratedAgentClientOptions = {},
@@ -1696,12 +3117,6 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1696
3117
  };
1697
3118
  }
1698
3119
  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
3120
  if (normalized.llm.route !== AGENTOS_CONFIG_LLM_ROUTE.OPENAI_CHAT_COMPATIBLE) {
1706
3121
  return {
1707
3122
  ok: false,
@@ -1709,6 +3124,150 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1709
3124
  };
1710
3125
  }
1711
3126
  const toolNames = Object.keys(normalized.deployment.manifest.tools ?? {}).sort();
3127
+ const hasChannels = normalized.channels.length > 0;
3128
+ const hasSchedules = normalized.schedules.length > 0;
3129
+ if (normalized.target.kind === AGENTOS_CONFIG_TARGET.NODE_V1) {
3130
+ if (normalized.profile !== AGENTOS_CONFIG_PROFILE.WORKSPACE_V1) {
3131
+ return {
3132
+ ok: false,
3133
+ issues: [{ kind: "unsupported_static_target", target: normalized.target.kind }],
3134
+ };
3135
+ }
3136
+ const authoredManifestToolNames = toolNames.filter((toolName) => normalized.authoredToolNames.includes(toolName));
3137
+ const deploymentJson = {
3138
+ deploymentId: normalized.deployment.deploymentId,
3139
+ backend: normalized.deployment.backend,
3140
+ adapter: normalized.deployment.adapter,
3141
+ codec: normalized.deployment.codec,
3142
+ ...(normalized.deployment.providerStrategy === undefined
3143
+ ? {}
3144
+ : { providerStrategy: normalized.deployment.providerStrategy }),
3145
+ workspace: {
3146
+ binding: normalized.workspace.binding,
3147
+ bindingRef: normalized.workspace.bindingRef,
3148
+ root: normalized.workspace.root,
3149
+ topology: normalized.workspace.topology,
3150
+ providerResourceId: normalized.workspace.providerResourceId,
3151
+ },
3152
+ };
3153
+ const moduleGraph = [
3154
+ { kind: "semantic-json", source: "./manifest.json", imports: ["default as declarations"] },
3155
+ { kind: "semantic-json", source: "./deployment.json", imports: ["default as deployment"] },
3156
+ {
3157
+ kind: "local-runtime",
3158
+ source: modules.localRuntime,
3159
+ imports: ["lowerLocalAgentRuntime"],
3160
+ },
3161
+ {
3162
+ kind: "capability-runtime",
3163
+ source: modules.runtimeCapability,
3164
+ imports: ["runDynamicCapabilityResolvers"],
3165
+ },
3166
+ {
3167
+ kind: "workspace-host",
3168
+ source: modules.workspaceAgentHost,
3169
+ imports: ["WorkspaceAgentCustomCommandInput"],
3170
+ },
3171
+ {
3172
+ kind: "target-runtime",
3173
+ source: modules.runtimeRunProjector,
3174
+ imports: [
3175
+ "projectAgentSession",
3176
+ "projectAgentSessions",
3177
+ "projectRunInspection",
3178
+ "projectWorkflowRun",
3179
+ "projectWorkflowRuns",
3180
+ ],
3181
+ },
3182
+ ...generatedToolImports(authoredManifestToolNames),
3183
+ ...generatedDynamicResolverImports(normalized.dynamicResolvers),
3184
+ ...(hasChannels
3185
+ ? [
3186
+ {
3187
+ kind: "channel-runtime",
3188
+ source: modules.runtimeChannel,
3189
+ imports: ["DefinedChannel"],
3190
+ },
3191
+ ...generatedChannelImports(normalized.channels),
3192
+ {
3193
+ kind: "channel-registry",
3194
+ source: "./channels",
3195
+ imports: ["dispatchGeneratedChannelRequest", "generatedChannels"],
3196
+ },
3197
+ ]
3198
+ : []),
3199
+ ...(hasSchedules
3200
+ ? [
3201
+ {
3202
+ kind: "schedule-runtime",
3203
+ source: modules.runtimeSchedule,
3204
+ imports: ["DefinedSchedule"],
3205
+ },
3206
+ ...generatedScheduleImports(normalized.schedules),
3207
+ {
3208
+ kind: "schedule-registry",
3209
+ source: "./schedules",
3210
+ imports: [
3211
+ "dispatchGeneratedSchedule",
3212
+ "dispatchGeneratedScheduleDelivery",
3213
+ "generatedScheduleDefinitions",
3214
+ "generatedSchedules",
3215
+ ],
3216
+ },
3217
+ ]
3218
+ : []),
3219
+ ];
3220
+ return {
3221
+ ok: true,
3222
+ value: {
3223
+ files: [
3224
+ generatedPath(".agentos/generated/manifest.json", stableJson(normalized.deployment.manifest)),
3225
+ generatedPath(".agentos/generated/deployment.json", stableJson(deploymentJson)),
3226
+ generatedPath(".agentos/generated/provenance.json", stableJson(normalized.provenance)),
3227
+ generatedPath(".agentos/generated/fingerprints.json", stableJson({
3228
+ deployment: digestText(stableJson(deploymentJson)),
3229
+ manifest: digestText(stableJson(normalized.deployment.manifest)),
3230
+ targetModuleGraph: digestText(stableJson(moduleGraph)),
3231
+ })),
3232
+ ...(hasChannels
3233
+ ? [
3234
+ generatedPath(".agentos/generated/channels.ts", renderChannelRegistry(normalized.channels, modules)),
3235
+ ]
3236
+ : []),
3237
+ ...(hasSchedules
3238
+ ? [
3239
+ generatedPath(".agentos/generated/schedules.ts", renderScheduleRegistry(normalized.schedules, modules)),
3240
+ ]
3241
+ : []),
3242
+ generatedPath(".agentos/generated/local.ts", renderLocalAgentApp(normalized, toolNames, modules)),
3243
+ ],
3244
+ moduleGraph,
3245
+ canonicalDeployment: {
3246
+ profile: normalized.profile,
3247
+ target: normalized.target.kind,
3248
+ llmRoute: normalized.llm.route,
3249
+ client: normalized.client.kind,
3250
+ workspaceTopology: normalized.workspace.topology,
3251
+ toolNames,
3252
+ },
3253
+ mount: {
3254
+ driver: {
3255
+ kind: "local-node",
3256
+ target: AGENTOS_CONFIG_TARGET.NODE_V1,
3257
+ },
3258
+ projectionSinks: [
3259
+ "agent.info",
3260
+ "workspace.state",
3261
+ "workspace.files",
3262
+ "runtime.events",
3263
+ "runtime.input_requests",
3264
+ ],
3265
+ providerResourceId: normalized.workspace.providerResourceId,
3266
+ },
3267
+ },
3268
+ };
3269
+ }
3270
+ const target = cloudflareTargetFor(normalized.target);
1712
3271
  const authoredToolNames = new Set(normalized.authoredToolNames);
1713
3272
  const authoredManifestToolNames = toolNames.filter((toolName) => authoredToolNames.has(toolName));
1714
3273
  const deploymentJson = {
@@ -1738,10 +3297,64 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1738
3297
  {
1739
3298
  kind: "target-runtime",
1740
3299
  source: modules.cloudflareDoRuntime,
1741
- imports: normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
1742
- ? ["createAgentDurableObject", "installCloudflareWorkspaceOperationProvider"]
1743
- : ["createAgentDurableObject"],
3300
+ imports: ["createAgentDurableObject"],
1744
3301
  },
3302
+ ...(hasChannels
3303
+ ? [
3304
+ {
3305
+ kind: "channel-runtime",
3306
+ source: modules.runtimeChannel,
3307
+ imports: ["DefinedChannel"],
3308
+ },
3309
+ ...generatedChannelImports(normalized.channels),
3310
+ {
3311
+ kind: "channel-registry",
3312
+ source: "./channels",
3313
+ imports: ["dispatchGeneratedChannelRequest", "generatedChannels"],
3314
+ },
3315
+ ]
3316
+ : []),
3317
+ ...(hasSchedules
3318
+ ? [
3319
+ {
3320
+ kind: "schedule-runtime",
3321
+ source: modules.runtimeSchedule,
3322
+ imports: ["DefinedSchedule"],
3323
+ },
3324
+ ...generatedScheduleImports(normalized.schedules),
3325
+ {
3326
+ kind: "schedule-registry",
3327
+ source: "./schedules",
3328
+ imports: [
3329
+ "dispatchGeneratedSchedule",
3330
+ "dispatchGeneratedScheduleDelivery",
3331
+ "generatedScheduleDefinitions",
3332
+ "generatedSchedules",
3333
+ ],
3334
+ },
3335
+ ]
3336
+ : []),
3337
+ ...(normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
3338
+ ? [
3339
+ {
3340
+ kind: "capability-runtime",
3341
+ source: modules.runtimeCapability,
3342
+ imports: [
3343
+ "WORKSPACE_OPERATION_HOST_FACT",
3344
+ "defineHost",
3345
+ "resolveRuntimeInstallGraph",
3346
+ "runDynamicCapabilityResolvers",
3347
+ "workspaceOperations",
3348
+ ],
3349
+ },
3350
+ ]
3351
+ : [
3352
+ {
3353
+ kind: "capability-runtime",
3354
+ source: modules.runtimeCapability,
3355
+ imports: ["runDynamicCapabilityResolvers"],
3356
+ },
3357
+ ]),
1745
3358
  {
1746
3359
  kind: "provider-runtime",
1747
3360
  source: modules.openAiCompatibleTransport,
@@ -1755,13 +3368,9 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1755
3368
  : ["WORKSPACE_AGENT_COMMAND"],
1756
3369
  },
1757
3370
  ...generatedToolImports(authoredManifestToolNames),
3371
+ ...generatedDynamicResolverImports(normalized.dynamicResolvers),
1758
3372
  ...(normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
1759
3373
  ? [
1760
- {
1761
- kind: "workspace-binding",
1762
- source: modules.workspaceBinding,
1763
- imports: ["bindWorkspaceToolsForRuntime"],
1764
- },
1765
3374
  {
1766
3375
  kind: "execution-domain-runtime",
1767
3376
  source: modules.workspaceEnvCloudflare,
@@ -1788,8 +3397,8 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1788
3397
  kind: "target-worker",
1789
3398
  source: "./worker",
1790
3399
  imports: normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
1791
- ? [normalized.target.durableObject.className, "Sandbox"]
1792
- : [normalized.target.durableObject.className],
3400
+ ? [target.durableObject.className, "Sandbox"]
3401
+ : [target.durableObject.className],
1793
3402
  },
1794
3403
  {
1795
3404
  kind: "target-config",
@@ -1810,6 +3419,16 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1810
3419
  manifest: digestText(stableJson(normalized.deployment.manifest)),
1811
3420
  targetModuleGraph: digestText(stableJson(moduleGraph)),
1812
3421
  })),
3422
+ ...(hasChannels
3423
+ ? [
3424
+ generatedPath(".agentos/generated/channels.ts", renderChannelRegistry(normalized.channels, modules)),
3425
+ ]
3426
+ : []),
3427
+ ...(hasSchedules
3428
+ ? [
3429
+ generatedPath(".agentos/generated/schedules.ts", renderScheduleRegistry(normalized.schedules, modules)),
3430
+ ]
3431
+ : []),
1813
3432
  generatedPath(".agentos/generated/target.ts", renderStaticTarget(normalized, toolNames, modules)),
1814
3433
  generatedPath(".agentos/generated/cloudflare-scope.ts", renderCloudflareScopeHelper(normalized, modules)),
1815
3434
  generatedPath(".agentos/generated/worker.ts", renderCloudflareWorkerEntry(normalized, modules)),
@@ -1836,8 +3455,8 @@ export const linkWorkspaceStaticTarget = (normalized, options = {}) => {
1836
3455
  mount: {
1837
3456
  driver: {
1838
3457
  kind: "cloudflare-do",
1839
- className: normalized.target.durableObject.className,
1840
- binding: normalized.target.durableObject.binding,
3458
+ className: target.durableObject.className,
3459
+ binding: target.durableObject.binding,
1841
3460
  },
1842
3461
  projectionSinks: normalized.profile === AGENTOS_CONFIG_PROFILE.WORKSPACE_V1
1843
3462
  ? [