experimental-ash 0.41.0 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/docs/internals/hooks.md +53 -11
  3. package/dist/docs/public/README.md +8 -8
  4. package/dist/docs/public/advanced/{auth-and-route-protection.md → auth-and-route-protection.mdx} +11 -0
  5. package/dist/docs/public/advanced/context-control.md +4 -4
  6. package/dist/docs/public/advanced/{evals.md → evals.mdx} +11 -1
  7. package/dist/docs/public/advanced/{hooks.md → hooks.mdx} +37 -46
  8. package/dist/docs/public/advanced/instrumentation.md +92 -3
  9. package/dist/docs/public/advanced/project-layout.md +5 -5
  10. package/dist/docs/public/advanced/runs-and-streaming.md +8 -2
  11. package/dist/docs/public/advanced/session-context.md +1 -1
  12. package/dist/docs/public/advanced/typescript-api.md +49 -6
  13. package/dist/docs/public/advanced/vercel-deployment.md +1 -1
  14. package/dist/docs/public/agent-ts.md +5 -5
  15. package/dist/docs/public/channels/{discord.md → discord.mdx} +11 -0
  16. package/dist/docs/public/channels/index.md +10 -10
  17. package/dist/docs/public/channels/{slack.md → slack.mdx} +11 -0
  18. package/dist/docs/public/channels/{teams.md → teams.mdx} +12 -0
  19. package/dist/docs/public/channels/{telegram.md → telegram.mdx} +11 -0
  20. package/dist/docs/public/channels/{twilio.md → twilio.mdx} +11 -0
  21. package/dist/docs/public/{connections.md → connections.mdx} +18 -6
  22. package/dist/docs/public/frontend/README.md +16 -0
  23. package/dist/docs/public/frontend/meta.json +3 -0
  24. package/dist/docs/public/frontend/nextjs.md +192 -0
  25. package/dist/docs/public/frontend/use-ash-agent.md +332 -0
  26. package/dist/docs/public/{getting-started.md → getting-started.mdx} +12 -1
  27. package/dist/docs/public/{human-in-the-loop.md → human-in-the-loop.mdx} +12 -1
  28. package/dist/docs/public/meta.json +1 -0
  29. package/dist/docs/public/sandbox.md +1 -1
  30. package/dist/docs/public/{schedules.md → schedules.mdx} +9 -0
  31. package/dist/docs/public/skills.md +2 -2
  32. package/dist/docs/public/{subagents.md → subagents.mdx} +10 -0
  33. package/dist/docs/public/{tools.md → tools.mdx} +62 -36
  34. package/dist/src/channel/adapter.d.ts +13 -0
  35. package/dist/src/channel/instrumentation.d.ts +10 -0
  36. package/dist/src/channel/instrumentation.js +1 -0
  37. package/dist/src/channel/send.js +1 -1
  38. package/dist/src/channel/types.d.ts +16 -0
  39. package/dist/src/cli/commands/channels.d.ts +2 -1
  40. package/dist/src/cli/commands/channels.js +1 -1
  41. package/dist/src/compiler/manifest.d.ts +13 -1
  42. package/dist/src/compiler/manifest.js +1 -1
  43. package/dist/src/compiler/module-map.js +1 -1
  44. package/dist/src/compiler/normalize-manifest.js +1 -1
  45. package/dist/src/compiler/normalize-skill.d.ts +15 -2
  46. package/dist/src/compiler/normalize-skill.js +1 -1
  47. package/dist/src/compiler/normalize-tool.js +1 -1
  48. package/dist/src/context/dynamic-skill-lifecycle.d.ts +23 -0
  49. package/dist/src/context/dynamic-skill-lifecycle.js +1 -0
  50. package/dist/src/context/dynamic-tool-lifecycle.d.ts +19 -23
  51. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  52. package/dist/src/context/hook-lifecycle.d.ts +4 -6
  53. package/dist/src/context/hook-lifecycle.js +1 -1
  54. package/dist/src/context/keys.d.ts +10 -9
  55. package/dist/src/context/keys.js +1 -1
  56. package/dist/src/context/providers/connection.d.ts +9 -0
  57. package/dist/src/context/providers/connection.js +1 -1
  58. package/dist/src/context/providers/sandbox.js +1 -1
  59. package/dist/src/execution/ash-workflow-attributes.d.ts +118 -0
  60. package/dist/src/execution/ash-workflow-attributes.js +1 -0
  61. package/dist/src/execution/channel-context.d.ts +5 -0
  62. package/dist/src/execution/channel-context.js +1 -0
  63. package/dist/src/execution/create-session-step.d.ts +28 -1
  64. package/dist/src/execution/create-session-step.js +1 -1
  65. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  66. package/dist/src/execution/durable-session-store.d.ts +7 -0
  67. package/dist/src/execution/node-step.d.ts +2 -2
  68. package/dist/src/execution/node-step.js +1 -1
  69. package/dist/src/execution/runtime-context.js +1 -1
  70. package/dist/src/execution/sandbox/prewarm.js +1 -1
  71. package/dist/src/execution/session.d.ts +6 -0
  72. package/dist/src/execution/session.js +2 -2
  73. package/dist/src/execution/skills/instructions.d.ts +3 -2
  74. package/dist/src/execution/subagent-tool.js +1 -1
  75. package/dist/src/execution/workflow-entry.js +1 -1
  76. package/dist/src/execution/workflow-steps.js +1 -1
  77. package/dist/src/harness/attachment-staging.js +1 -1
  78. package/dist/src/harness/code-mode.d.ts +0 -5
  79. package/dist/src/harness/code-mode.js +1 -1
  80. package/dist/src/harness/emission.d.ts +1 -1
  81. package/dist/src/harness/emission.js +1 -1
  82. package/dist/src/harness/instrumentation-config.d.ts +1 -1
  83. package/dist/src/harness/instrumentation-metadata.d.ts +23 -0
  84. package/dist/src/harness/instrumentation-metadata.js +1 -0
  85. package/dist/src/harness/otel-integration.d.ts +2 -2
  86. package/dist/src/harness/otel-integration.js +1 -1
  87. package/dist/src/harness/step-hooks.js +1 -1
  88. package/dist/src/harness/tool-loop.js +1 -1
  89. package/dist/src/harness/turn-tag-state.d.ts +50 -0
  90. package/dist/src/harness/turn-tag-state.js +1 -0
  91. package/dist/src/harness/types.d.ts +20 -2
  92. package/dist/src/internal/application/package.js +1 -1
  93. package/dist/src/internal/authored-definition/schema-backed.d.ts +0 -1
  94. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  95. package/dist/src/internal/instrumentation.d.ts +39 -0
  96. package/dist/src/internal/instrumentation.js +1 -0
  97. package/dist/src/internal/workflow/builtins.d.ts +32 -0
  98. package/dist/src/internal/workflow/builtins.js +1 -1
  99. package/dist/src/internal/workflow-bundle/dynamic-tool-transform.d.ts +1 -1
  100. package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +1 -1
  101. package/dist/src/internal/workflow-bundle/workflow-core-shim.d.ts +34 -0
  102. package/dist/src/internal/workflow-bundle/workflow-core-shim.js +1 -1
  103. package/dist/src/internal/workflow-bundle/workflow-transformer.js +1 -1
  104. package/dist/src/packages/ash-scaffold/src/channels.js +1 -1
  105. package/dist/src/packages/ash-scaffold/src/steps/run-add-to-agent.js +2 -2
  106. package/dist/src/public/channels/slack/attachments.js +1 -1
  107. package/dist/src/public/channels/slack/index.d.ts +1 -1
  108. package/dist/src/public/channels/slack/slackChannel.d.ts +6 -0
  109. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  110. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  111. package/dist/src/public/channels/twilio/index.d.ts +1 -1
  112. package/dist/src/public/channels/twilio/twilioChannel.d.ts +6 -0
  113. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  114. package/dist/src/public/definitions/defineChannel.d.ts +12 -2
  115. package/dist/src/public/definitions/defineChannel.js +1 -1
  116. package/dist/src/public/definitions/hook.d.ts +3 -11
  117. package/dist/src/public/definitions/instrumentation.d.ts +88 -2
  118. package/dist/src/public/definitions/skill.d.ts +5 -0
  119. package/dist/src/public/definitions/tool.d.ts +25 -66
  120. package/dist/src/public/definitions/tool.js +1 -1
  121. package/dist/src/public/instrumentation/index.d.ts +1 -4
  122. package/dist/src/public/instrumentation/index.js +1 -1
  123. package/dist/src/public/skills/index.d.ts +2 -0
  124. package/dist/src/public/skills/index.js +1 -1
  125. package/dist/src/public/tools/index.d.ts +2 -2
  126. package/dist/src/public/tools/index.js +1 -1
  127. package/dist/src/runtime/agent/mock-model-adapter.js +4 -7
  128. package/dist/src/runtime/agent/mock-model-skill-selection.d.ts +9 -0
  129. package/dist/src/runtime/agent/mock-model-skill-selection.js +4 -0
  130. package/dist/src/runtime/attributes/emit.d.ts +73 -0
  131. package/dist/src/runtime/attributes/emit.js +1 -0
  132. package/dist/src/runtime/channels/registry.js +1 -1
  133. package/dist/src/runtime/connections/mcp-client.js +1 -1
  134. package/dist/src/runtime/framework-tools/code-mode-connection-auth.d.ts +2 -0
  135. package/dist/src/runtime/framework-tools/connection-search-dynamic.d.ts +34 -0
  136. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -0
  137. package/dist/src/runtime/framework-tools/index.d.ts +7 -5
  138. package/dist/src/runtime/framework-tools/index.js +1 -1
  139. package/dist/src/runtime/prompt/connections.js +1 -1
  140. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  141. package/dist/src/runtime/resolve-agent.js +1 -1
  142. package/dist/src/runtime/resolve-dynamic-skill.d.ts +8 -0
  143. package/dist/src/runtime/resolve-dynamic-skill.js +1 -0
  144. package/dist/src/runtime/resolve-dynamic-tool.js +1 -1
  145. package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
  146. package/dist/src/runtime/sessions/runtime-context-keys.js +1 -1
  147. package/dist/src/runtime/types.d.ts +13 -4
  148. package/dist/src/shared/dynamic-tool-definition.d.ts +57 -80
  149. package/dist/src/shared/dynamic-tool-definition.js +1 -1
  150. package/dist/src/shared/guards.d.ts +14 -0
  151. package/dist/src/shared/guards.js +1 -1
  152. package/dist/src/shared/skill-definition.d.ts +5 -4
  153. package/dist/src/shared/tool-definition.d.ts +12 -0
  154. package/package.json +2 -1
  155. package/dist/src/runtime/framework-tools/connection-search.d.ts +0 -57
  156. package/dist/src/runtime/framework-tools/connection-search.js +0 -1
  157. package/dist/src/runtime/framework-tools/connection-tools.d.ts +0 -55
  158. package/dist/src/runtime/framework-tools/connection-tools.js +0 -1
@@ -75,6 +75,8 @@ export interface FetchFileResult {
75
75
  readonly mediaType?: string;
76
76
  readonly filename?: string;
77
77
  }
78
+ export type ChannelInstrumentationMetadata = Readonly<Record<string, unknown>>;
79
+ export type ChannelInstrumentationMetadataProjector = (state: Record<string, unknown> | undefined) => ChannelInstrumentationMetadata;
78
80
  /**
79
81
  * Plain-object channel adapter with durable state, an optional inbound
80
82
  * delivery hook, event handlers, and optional attachment resolution.
@@ -122,6 +124,17 @@ export type ChannelAdapter<TCtx extends ChannelAdapterContext<any> = ChannelAdap
122
124
  * construction time.
123
125
  */
124
126
  readonly fetchFile?: (url: string) => Promise<Buffer | FetchFileResult | null>;
127
+ /**
128
+ * Framework-owned observability projection for the active channel.
129
+ *
130
+ * Channel implementations decide which state fields are safe and
131
+ * meaningful to expose to instrumentation callbacks. The harness reads
132
+ * the resulting projection through a seed context key rather than
133
+ * inspecting adapter state directly.
134
+ */
135
+ readonly instrumentation?: {
136
+ readonly metadata?: ChannelInstrumentationMetadataProjector;
137
+ };
125
138
  } & ChannelEventHandlers<TCtx>;
126
139
  /**
127
140
  * Produces the default {@link StepInput} when no custom adapter `deliver`
@@ -0,0 +1,10 @@
1
+ import type { ChannelAdapter, ChannelInstrumentationMetadata } from "#channel/adapter.js";
2
+ export interface ChannelInstrumentationProjection {
3
+ readonly kind: string;
4
+ readonly metadata: ChannelInstrumentationMetadata;
5
+ }
6
+ export declare function buildChannelInstrumentationProjection(input: {
7
+ readonly adapter: ChannelAdapter;
8
+ readonly channelName?: string;
9
+ readonly existingKind?: string;
10
+ }): ChannelInstrumentationProjection;
@@ -0,0 +1 @@
1
+ import{createLogger}from"#internal/logging.js";import{getAdapterKind}from"#channel/adapter.js";import{isInstrumentationChannelKind,resolveInstrumentationProjection}from"#internal/instrumentation.js";const log=createLogger(`channel.instrumentation`);function buildChannelInstrumentationProjection(e){let{adapter:t,channelName:n,existingKind:r}=e;return{kind:resolveKind({adapter:t,channelName:n,existingKind:r}),metadata:resolveMetadata(t)}}function resolveKind(e){let{adapter:r,channelName:i,existingKind:a}=e;if(a!==void 0)return a;if(i!==void 0&&i.length>0)return`channel:${i}`;let o=getAdapterKind(r);return isInstrumentationChannelKind(o)?o:`channel:${o}`}function resolveMetadata(e){let n=e.instrumentation?.metadata;return n===void 0?{}:resolveInstrumentationProjection({invoke:()=>n(e.state),log,source:getAdapterKind(e)})??{}}export{buildChannelInstrumentationProjection};
@@ -1 +1 @@
1
- import{createSession}from"#channel/session.js";import{createLogger}from"#internal/logging.js";import{isRuntimeNoActiveSessionError}from"#execution/runtime-errors.js";import{serializeUrlFilePart}from"#internal/attachments/url-refs.js";const log=createLogger(`channel.send`);function createSendFn(t,r,i){return async(a,o)=>{let s=o.auth,c=o.callback,l=o.mode??`conversation`,u=o.state,d=o.continuationToken,f=`${i}:${d}`,{message:p,inputResponses:m,modelContext:h}=normalizeSendInput(a),g=serializeUrlFilePartsInMessage(p);try{let{sessionId:n}=await t.deliver({auth:s,continuationToken:f,payload:{inputResponses:m,message:g,modelContext:h}});return createSession(n,d,t)}catch(e){isRuntimeNoActiveSessionError(e)||log.warn(`deliver failed, falling back to starting a new session`,{continuationToken:f})}if(m&&m.length>0)throw Error(`Cannot deliver inputResponses — the target session was not found via continuation token.`);let _=u?{...r,state:{...r.state,...u}}:r;return createSession((await t.run({adapter:_,auth:s,capabilities:l===`conversation`?{requestInput:!0}:void 0,callback:c,continuationToken:f,input:{message:g??``,modelContext:h},mode:l})).sessionId,d,t)}}function serializeUrlFilePartsInMessage(e){if(e===void 0||typeof e==`string`)return e;let t=!1,n=e.map(e=>e.type===`file`&&e.data instanceof URL&&e.data.protocol!==`data:`?(t=!0,{...e,data:serializeUrlFilePart(e.data)}):e);return t?n:e}function normalizeSendInput(e){return typeof e==`string`||Array.isArray(e)?{message:e}:e}export{createSendFn};
1
+ import{createSession}from"#channel/session.js";import{createLogger}from"#internal/logging.js";import{isRuntimeNoActiveSessionError}from"#execution/runtime-errors.js";import{serializeUrlFilePart}from"#internal/attachments/url-refs.js";const log=createLogger(`channel.send`);function createSendFn(t,r,i){return async(a,o)=>{let s=o.auth,c=o.callback,l=o.mode??`conversation`,u=o.state,d=o.continuationToken,f=`${i}:${d}`,{message:p,inputResponses:m,modelContext:h}=normalizeSendInput(a),g=serializeUrlFilePartsInMessage(p);try{let{sessionId:n}=await t.deliver({auth:s,continuationToken:f,payload:{inputResponses:m,message:g,modelContext:h}});return createSession(n,d,t)}catch(e){isRuntimeNoActiveSessionError(e)||log.warn(`deliver failed, falling back to starting a new session`,{continuationToken:f})}if(m&&m.length>0)throw Error(`Cannot deliver inputResponses — the target session was not found via continuation token.`);let _=u?{...r,state:{...r.state,...u}}:r;return createSession((await t.run({adapter:_,auth:s,capabilities:l===`conversation`?{requestInput:!0}:void 0,channelName:i,callback:c,continuationToken:f,input:{message:g??``,modelContext:h},mode:l})).sessionId,d,t)}}function serializeUrlFilePartsInMessage(e){if(e===void 0||typeof e==`string`)return e;let t=!1,n=e.map(e=>e.type===`file`&&e.data instanceof URL&&e.data.protocol!==`data:`?(t=!0,{...e,data:serializeUrlFilePart(e.data)}):e);return t?n:e}function normalizeSendInput(e){return typeof e==`string`||Array.isArray(e)?{message:e}:e}export{createSendFn};
@@ -5,6 +5,7 @@ import type { RuntimeActionResult } from "#runtime/actions/types.js";
5
5
  import type { InputRequest, InputResponse } from "#runtime/input/types.js";
6
6
  import type { ChannelAdapter } from "#channel/adapter.js";
7
7
  export type { ContextAccessor } from "#context/key.js";
8
+ export type { ChannelInstrumentationProjection } from "#channel/instrumentation.js";
8
9
  /**
9
10
  * Identifies one turn within a session.
10
11
  */
@@ -15,8 +16,17 @@ export interface SessionTurn {
15
16
  /**
16
17
  * Stable lineage metadata describing the immediate Ash parent execution that
17
18
  * delegated the current session.
19
+ *
20
+ * `sessionId` and `turn` always describe the **immediate** parent — the
21
+ * agent that dispatched this child. `rootSessionId` denormalizes the top
22
+ * of the dispatch chain so descendants can identify the user-facing
23
+ * session without walking back up parent-by-parent. It is always
24
+ * populated at dispatch: a first-level child sets it to the top
25
+ * session's id (its immediate parent), and deeper descendants inherit
26
+ * the same root.
18
27
  */
19
28
  export interface SessionParent {
29
+ readonly rootSessionId: string;
20
30
  readonly sessionId: string;
21
31
  readonly turn: SessionTurn;
22
32
  }
@@ -162,6 +172,12 @@ export interface SessionCapabilities {
162
172
  */
163
173
  export interface RunInput {
164
174
  readonly adapter: ChannelAdapter<any>;
175
+ /**
176
+ * Registered channel name for root sessions started from an authored
177
+ * channel route. Framework runs omit this and use their framework
178
+ * adapter kind (`http`, `schedule`, `subagent`) directly.
179
+ */
180
+ readonly channelName?: string;
165
181
  /**
166
182
  * Authenticated caller principal for this session. `null` means the
167
183
  * request was accepted with no credentials.
@@ -1,4 +1,4 @@
1
- import { type RunAddToAgentOptions } from "@vercel/ash-scaffold/steps";
1
+ import { type DeployProjectOptions, type RunAddToAgentOptions } from "@vercel/ash-scaffold/steps";
2
2
  import { type ChannelAddPrompter } from "@vercel/ash-scaffold/cli";
3
3
  import { type DeploymentInfo } from "@vercel/ash-scaffold/primitives";
4
4
  export interface CliLogger {
@@ -11,6 +11,7 @@ export interface AddChannelCommandOptions {
11
11
  export interface ChannelsAddDependencies {
12
12
  createPrompter?: () => ChannelAddPrompter;
13
13
  detectDeployment(projectPath: string): Promise<DeploymentInfo>;
14
+ deployProject(options: DeployProjectOptions): Promise<void>;
14
15
  runAddToAgent(options: RunAddToAgentOptions): Promise<void>;
15
16
  }
16
17
  export declare function runChannelsAddCommand(logger: CliLogger, appRoot: string, args: {
@@ -1 +1 @@
1
- import{assertCanAddSelectedChannels,inspectExistingChannelRegistrations}from"./channel-add-conflicts.js";import{isAshProject}from"../../packages/ash-scaffold/src/project.js";import{listAuthoredChannels}from"../../packages/ash-scaffold/src/channels.js";import"../../packages/ash-scaffold/src/index.js";import{detectDeployment}from"../../packages/ash-scaffold/src/primitives/detect-deployment.js";import{createAddToAgentState,runAddToAgent}from"../../packages/ash-scaffold/src/steps/run-add-to-agent.js";import"../../packages/ash-scaffold/src/steps/index.js";import{ChannelAddCancelledError,createChannelAddPrompter}from"../../packages/ash-scaffold/src/cli/channel-add-prompter.js";import"../../packages/ash-scaffold/src/cli/index.js";import"../../packages/ash-scaffold/src/primitives/index.js";const NOT_AN_AGENT_MESSAGE="No Ash agent in this directory. Run `pnpm create experimental-ash-agent`, then run this command from inside the new project.",KNOWN_CHANNEL_KINDS=[`slack`,`web`];function isChannelKind(e){return KNOWN_CHANNEL_KINDS.includes(e)}function parseChannelKind(e){if(!isChannelKind(e))throw Error(`Unknown channel kind "${e}". Known: ${KNOWN_CHANNEL_KINDS.join(`, `)}.`);return e}const defaultChannelsAddDependencies={detectDeployment,runAddToAgent};async function runAddChannelsFlow(n,r,i,o){if(r===void 0&&(!process.stdin.isTTY||!process.stdout.isTTY))throw Error(`Pass a channel kind: \`ash channels add <${KNOWN_CHANNEL_KINDS.join(`|`)}>\`.`);let s=o.createPrompter?.()??createChannelAddPrompter();s.intro(`Add channels to your Ash agent`),s.log.message(`Checking the current Vercel project...`);let c=createAddToAgentState(await o.detectDeployment(n)),l;function inspectRegistrations(){return l===void 0&&(s.log.message(`Inspecting existing channel registrations...`),l=inspectExistingChannelRegistrations(n)),l}let u=r===void 0?(await inspectRegistrations()).disabledChannelReasons:void 0;await o.runAddToAgent({prompter:s,projectPath:n,state:c,presetChannels:r===void 0?void 0:[r],disabledChannelReasons:u,force:i.force,validateSelectedChannels:async t=>{!t.includes(`web`)&&!t.includes(`slack`)||assertCanAddSelectedChannels(t,await inspectRegistrations())}}),s.outro(c.channels.length===0?`No channels added.`:`Channels added.`)}async function runChannelsAddCommand(e,t,r,i=defaultChannelsAddDependencies){if(!await isAshProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}try{await runAddChannelsFlow(t,r.kind===void 0?void 0:parseChannelKind(r.kind),r.options,i)}catch(t){if(t instanceof ChannelAddCancelledError)return;e.error(t instanceof Error?t.message:String(t)),process.exitCode=1}}async function runChannelsListCommand(e,t,i){if(!await isAshProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}let a=await listAuthoredChannels(t);if(i.json){e.log(JSON.stringify({channels:a},null,2));return}if(a.length===0){e.log("No channels defined. Run `ash channels add` to add one.");return}for(let t of a)e.log(t)}export{runChannelsAddCommand,runChannelsListCommand};
1
+ import{assertCanAddSelectedChannels,inspectExistingChannelRegistrations}from"./channel-add-conflicts.js";import{isAshProject}from"../../packages/ash-scaffold/src/project.js";import{listAuthoredChannels}from"../../packages/ash-scaffold/src/channels.js";import"../../packages/ash-scaffold/src/index.js";import{detectDeployment}from"../../packages/ash-scaffold/src/primitives/detect-deployment.js";import{createAddToAgentState,deployProject,runAddToAgent}from"../../packages/ash-scaffold/src/steps/run-add-to-agent.js";import"../../packages/ash-scaffold/src/steps/index.js";import{ChannelAddCancelledError,createChannelAddPrompter}from"../../packages/ash-scaffold/src/cli/channel-add-prompter.js";import"../../packages/ash-scaffold/src/cli/index.js";import"../../packages/ash-scaffold/src/primitives/index.js";const NOT_AN_AGENT_MESSAGE="No Ash agent in this directory. Run `pnpm create experimental-ash-agent`, then run this command from inside the new project.",KNOWN_CHANNEL_KINDS=[`slack`,`web`];function isChannelKind(e){return KNOWN_CHANNEL_KINDS.includes(e)}function parseChannelKind(e){if(!isChannelKind(e))throw Error(`Unknown channel kind "${e}". Known: ${KNOWN_CHANNEL_KINDS.join(`, `)}.`);return e}const defaultChannelsAddDependencies={detectDeployment,deployProject,runAddToAgent};async function runAddChannelsFlow(n,r,i,o){if(r===void 0&&(!process.stdin.isTTY||!process.stdout.isTTY))throw Error(`Pass a channel kind: \`ash channels add <${KNOWN_CHANNEL_KINDS.join(`|`)}>\`.`);let s=o.createPrompter?.()??createChannelAddPrompter();s.intro(`Add channels to your Ash agent`),s.log.message(`Checking the current Vercel project...`);let c=createAddToAgentState(await o.detectDeployment(n)),l;function inspectRegistrations(){return l===void 0&&(s.log.message(`Inspecting existing channel registrations...`),l=inspectExistingChannelRegistrations(n)),l}let u=r===void 0?(await inspectRegistrations()).disabledChannelReasons:void 0;await o.runAddToAgent({prompter:s,projectPath:n,state:c,presetChannels:r===void 0?void 0:[r],disabledChannelReasons:u,force:i.force,validateSelectedChannels:async t=>{!t.includes(`web`)&&!t.includes(`slack`)||assertCanAddSelectedChannels(t,await inspectRegistrations())}}),await o.deployProject({prompter:s,projectPath:n,vercelProjectId:c.vercelProjectId,state:c}),s.outro(c.channels.length===0?`No channels added.`:`Channels added.`)}async function runChannelsAddCommand(e,t,r,i=defaultChannelsAddDependencies){if(!await isAshProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}try{await runAddChannelsFlow(t,r.kind===void 0?void 0:parseChannelKind(r.kind),r.options,i)}catch(t){if(t instanceof ChannelAddCancelledError)return;e.error(t instanceof Error?t.message:String(t)),process.exitCode=1}}async function runChannelsListCommand(e,t,i){if(!await isAshProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}let a=await listAuthoredChannels(t);if(i.json){e.log(JSON.stringify({channels:a},null,2));return}if(a.length===0){e.log("No channels defined. Run `ash channels add` to add one.");return}for(let t of a)e.log(t)}export{runChannelsAddCommand,runChannelsListCommand};
@@ -107,7 +107,15 @@ export type CompiledToolDefinition = InternalToolDefinition & ModuleSourceRef;
107
107
  */
108
108
  export interface CompiledDynamicToolDefinition extends ModuleSourceRef {
109
109
  readonly slug: string;
110
- readonly identity: "single" | "multi";
110
+ readonly eventNames: readonly string[];
111
+ }
112
+ /**
113
+ * Compiled dynamic skill resolver entry. Mirrors
114
+ * {@link CompiledDynamicToolDefinition} — the resolver produces skill
115
+ * packages at runtime rather than tool definitions.
116
+ */
117
+ export interface CompiledDynamicSkillDefinition extends ModuleSourceRef {
118
+ readonly slug: string;
111
119
  readonly eventNames: readonly string[];
112
120
  }
113
121
  /**
@@ -223,6 +231,7 @@ declare const compiledAgentNodeManifestSchema: z.ZodObject<{
223
231
  warnings: z.ZodNumber;
224
232
  }, z.core.$strict>;
225
233
  disabledFrameworkTools: z.ZodReadonly<z.ZodArray<z.ZodString>>;
234
+ dynamicSkills: z.ZodDefault<z.ZodArray<z.ZodType<CompiledDynamicSkillDefinition, unknown, z.core.$ZodTypeInternals<CompiledDynamicSkillDefinition, unknown>>>>;
226
235
  dynamicTools: z.ZodDefault<z.ZodArray<z.ZodType<CompiledDynamicToolDefinition, unknown, z.core.$ZodTypeInternals<CompiledDynamicToolDefinition, unknown>>>>;
227
236
  hooks: z.ZodArray<z.ZodType<CompiledHookDefinition, unknown, z.core.$ZodTypeInternals<CompiledHookDefinition, unknown>>>;
228
237
  sandbox: z.ZodNullable<z.ZodObject<{
@@ -309,6 +318,7 @@ export declare const compiledAgentManifestSchema: z.ZodObject<{
309
318
  warnings: z.ZodNumber;
310
319
  }, z.core.$strict>;
311
320
  disabledFrameworkTools: z.ZodReadonly<z.ZodArray<z.ZodString>>;
321
+ dynamicSkills: z.ZodDefault<z.ZodArray<z.ZodType<CompiledDynamicSkillDefinition, unknown, z.core.$ZodTypeInternals<CompiledDynamicSkillDefinition, unknown>>>>;
312
322
  dynamicTools: z.ZodDefault<z.ZodArray<z.ZodType<CompiledDynamicToolDefinition, unknown, z.core.$ZodTypeInternals<CompiledDynamicToolDefinition, unknown>>>>;
313
323
  hooks: z.ZodArray<z.ZodType<CompiledHookDefinition, unknown, z.core.$ZodTypeInternals<CompiledHookDefinition, unknown>>>;
314
324
  kind: z.ZodLiteral<"ash-agent-compiled-manifest">;
@@ -397,6 +407,7 @@ export declare function createCompiledAgentNodeManifest(input: {
397
407
  readonly connections?: readonly CompiledConnectionDefinition[];
398
408
  readonly diagnosticsSummary?: DiscoverDiagnosticsSummary;
399
409
  readonly disabledFrameworkTools?: readonly string[];
410
+ readonly dynamicSkills?: readonly CompiledDynamicSkillDefinition[];
400
411
  readonly dynamicTools?: readonly CompiledDynamicToolDefinition[];
401
412
  readonly hooks?: readonly CompiledHookDefinition[];
402
413
  readonly remoteAgents?: readonly CompiledRemoteAgentNode[];
@@ -436,6 +447,7 @@ export declare function createCompiledAgentManifest(input: {
436
447
  readonly connections?: readonly CompiledConnectionDefinition[];
437
448
  readonly diagnosticsSummary?: DiscoverDiagnosticsSummary;
438
449
  readonly disabledFrameworkTools?: readonly string[];
450
+ readonly dynamicSkills?: readonly CompiledDynamicSkillDefinition[];
439
451
  readonly dynamicTools?: readonly CompiledDynamicToolDefinition[];
440
452
  readonly hooks?: readonly CompiledHookDefinition[];
441
453
  readonly remoteAgents?: readonly CompiledRemoteAgentNode[];
@@ -1 +1 @@
1
- import{z}from"#compiled/zod/index.js";import{discoverDiagnosticsSummarySchema}from"#discover/diagnostics.js";import{compiledRemoteAgentNodeSchema}from"#compiler/remote-agent-node.js";import{jsonObjectSchema}from"#shared/json-schemas.js";const COMPILED_AGENT_MANIFEST_KIND=`ash-agent-compiled-manifest`,ROOT_COMPILED_AGENT_NODE_ID=`__root__`,COMPILED_AGENT_MANIFEST_VERSION=25,moduleSourceRefSchema=z.object({exportName:z.string().optional(),sourceKind:z.literal(`module`),logicalPath:z.string(),sourceId:z.string()}).strict(),channelMethodSchema=z.union([z.literal(`GET`),z.literal(`POST`),z.literal(`PUT`),z.literal(`PATCH`),z.literal(`DELETE`)]),compiledChannelDefinitionSchema=z.object({kind:z.literal(`channel`),name:z.string(),logicalPath:z.string(),method:channelMethodSchema,urlPath:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`),exportName:z.string().optional(),adapterKind:z.string().optional()}).strict(),disabledCompiledChannelEntrySchema=z.object({kind:z.literal(`disabled`),name:z.string(),logicalPath:z.string()}).strict(),compiledChannelEntrySchema=z.union([compiledChannelDefinitionSchema,disabledCompiledChannelEntrySchema]),compiledRuntimeModelReferenceSchema=z.object({contextWindowTokens:z.number().int().positive().optional(),id:z.string(),source:moduleSourceRefSchema.optional(),providerOptions:z.record(z.string(),jsonObjectSchema).optional()}).strict(),compiledAgentBuildDefinitionSchema=z.object({externalDependencies:z.array(z.string()).optional()}).strict(),compiledAgentCompactionDefinitionSchema=z.object({model:compiledRuntimeModelReferenceSchema.optional(),thresholdPercent:z.number().finite().min(0).max(1).optional()}).strict(),compiledAgentConfigSchema=z.object({build:compiledAgentBuildDefinitionSchema.optional(),compaction:compiledAgentCompactionDefinitionSchema.optional(),description:z.string().optional(),experimental:z.object({codeMode:z.boolean().optional()}).strict().optional(),model:compiledRuntimeModelReferenceSchema,name:z.string(),source:moduleSourceRefSchema.optional()}).strict(),compiledInstructionsSchema=z.object({name:z.string(),logicalPath:z.string(),markdown:z.string(),sourceId:z.string(),sourceKind:z.union([z.literal(`markdown`),z.literal(`module`)])}).strict(),compiledSkillBaseFields={name:z.string(),description:z.string(),license:z.string().optional(),markdown:z.string(),metadata:z.record(z.string(),z.string()).optional(),sourceId:z.string(),logicalPath:z.string()},compiledSkillSourceSchema=z.discriminatedUnion(`sourceKind`,[z.object({...compiledSkillBaseFields,sourceKind:z.literal(`markdown`)}).strict(),z.object({...compiledSkillBaseFields,sourceKind:z.literal(`module`),exportName:z.string().optional()}).strict(),z.object({...compiledSkillBaseFields,sourceKind:z.literal(`skill-package`),skillId:z.string(),skillFilePath:z.string(),rootPath:z.string(),assetsPath:z.string().optional(),referencesPath:z.string().optional(),scriptsPath:z.string().optional()}).strict()]),compiledScheduleDefinitionSchema=z.object({cron:z.string(),hasRun:z.boolean(),name:z.string(),logicalPath:z.string(),markdown:z.string().optional(),sourceId:z.string(),sourceKind:z.union([z.literal(`markdown`),z.literal(`module`)])}).strict(),compiledSandboxDefinitionSchema=z.object({description:z.string().optional(),exportName:z.string().optional(),logicalPath:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`)}).strict(),compiledSandboxWorkspaceSchema=z.object({logicalPath:z.string(),rootEntries:z.array(z.string()).readonly(),sourceId:z.string(),sourcePath:z.string()}).strict(),compiledWorkspaceResourceRootSchema=z.object({logicalPath:z.string(),rootEntries:z.array(z.string()).readonly()}).strict(),compiledConnectionDefinitionSchema=z.object({connectionName:z.string(),description:z.string(),exportName:z.string().optional(),logicalPath:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`),url:z.string(),vercelConnect:z.object({connector:z.string()}).strict().optional()}).strict(),compiledToolDefinitionSchema=z.object({description:z.string(),exportName:z.string().optional(),inputSchema:jsonObjectSchema.nullable(),logicalPath:z.string(),name:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`)}).strict(),compiledDynamicToolDefinitionSchema=z.object({eventNames:z.array(z.string()).readonly(),exportName:z.string().optional(),identity:z.enum([`single`,`multi`]),logicalPath:z.string(),slug:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`)}).strict(),compiledHookDefinitionSchema=z.object({exportName:z.string().optional(),logicalPath:z.string(),slug:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`)}).strict(),compiledAgentNodeManifestSchema=z.object({agentRoot:z.string(),appRoot:z.string(),channels:z.array(compiledChannelEntrySchema),config:compiledAgentConfigSchema,connections:z.array(compiledConnectionDefinitionSchema),diagnosticsSummary:discoverDiagnosticsSummarySchema,disabledFrameworkTools:z.array(z.string()).readonly(),dynamicTools:z.array(compiledDynamicToolDefinitionSchema).default([]),hooks:z.array(compiledHookDefinitionSchema),sandbox:compiledSandboxDefinitionSchema.nullable(),sandboxWorkspaces:z.array(compiledSandboxWorkspaceSchema),schedules:z.array(compiledScheduleDefinitionSchema),remoteAgents:z.array(compiledRemoteAgentNodeSchema),skills:z.array(compiledSkillSourceSchema).readonly(),instructions:compiledInstructionsSchema.optional(),tools:z.array(compiledToolDefinitionSchema),workspaceResourceRoot:compiledWorkspaceResourceRootSchema}).strict(),compiledSubagentNodeSchema=z.object({agent:compiledAgentNodeManifestSchema,description:z.string(),entryPath:z.string(),logicalPath:z.string(),name:z.string(),nodeId:z.string(),rootPath:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`),exportName:z.string().optional()}).strict(),compiledSubagentEdgeSchema=z.object({childNodeId:z.string(),parentNodeId:z.string()}).strict(),compiledAgentManifestSchema=z.object({agentRoot:z.string(),appRoot:z.string(),channels:z.array(compiledChannelEntrySchema),config:compiledAgentConfigSchema,connections:z.array(compiledConnectionDefinitionSchema),diagnosticsSummary:discoverDiagnosticsSummarySchema,disabledFrameworkTools:z.array(z.string()).readonly(),dynamicTools:z.array(compiledDynamicToolDefinitionSchema).default([]),hooks:z.array(compiledHookDefinitionSchema),kind:z.literal(COMPILED_AGENT_MANIFEST_KIND),remoteAgents:z.array(compiledRemoteAgentNodeSchema),sandbox:compiledSandboxDefinitionSchema.nullable(),sandboxWorkspaces:z.array(compiledSandboxWorkspaceSchema),schedules:z.array(compiledScheduleDefinitionSchema),skills:z.array(compiledSkillSourceSchema).readonly(),subagentEdges:z.array(compiledSubagentEdgeSchema),subagents:z.array(compiledSubagentNodeSchema),instructions:compiledInstructionsSchema.optional(),tools:z.array(compiledToolDefinitionSchema),version:z.literal(25),workspaceResourceRoot:compiledWorkspaceResourceRootSchema}).strict();function createCompiledAgentNodeManifest(e){let t={agentRoot:e.agentRoot,appRoot:e.appRoot,channels:[...e.channels??[]],connections:[...e.connections??[]],config:{build:e.config.build===void 0?void 0:{externalDependencies:e.config.build.externalDependencies===void 0?void 0:[...e.config.build.externalDependencies]},compaction:{model:e.config.compaction?.model===void 0?void 0:cloneCompiledRuntimeModelReference(e.config.compaction.model),thresholdPercent:e.config.compaction?.thresholdPercent},description:e.config.description,experimental:e.config.experimental===void 0?void 0:{codeMode:e.config.experimental.codeMode},model:cloneCompiledRuntimeModelReference(e.config.model),name:e.config.name,source:e.config.source===void 0?void 0:{...e.config.source}},diagnosticsSummary:e.diagnosticsSummary??{errors:0,warnings:0},disabledFrameworkTools:[...e.disabledFrameworkTools??[]],dynamicTools:[...e.dynamicTools??[]],hooks:[...e.hooks??[]],remoteAgents:[...e.remoteAgents??[]],sandbox:e.sandbox??null,sandboxWorkspaces:[...e.sandboxWorkspaces??[]],schedules:[...e.schedules??[]],skills:[...e.skills??[]],tools:[...e.tools??[]],workspaceResourceRoot:e.workspaceResourceRoot??{logicalPath:``,rootEntries:deriveResourceRootEntries({sandboxWorkspaces:e.sandboxWorkspaces,skills:e.skills})}};return e.instructions!==void 0&&(t.instructions=e.instructions),t}function deriveResourceRootEntries(e){let t=new Set;(e.skills??[]).length>0&&t.add(`skills/`);for(let n of e.sandboxWorkspaces??[])for(let e of n.rootEntries)t.add(e);return[...t].sort((e,t)=>e.localeCompare(t))}function createCompiledSubagentNodeId(e,t){return e===`__root__`?t:`${e}::${t}`}function createCompiledAgentManifest(e){return{...createCompiledAgentNodeManifest(e),kind:COMPILED_AGENT_MANIFEST_KIND,subagentEdges:[...e.subagentEdges??[]],subagents:[...e.subagents??[]],version:25}}function cloneCompiledRuntimeModelReference(e){return e.contextWindowTokens===void 0&&e.source===void 0&&e.providerOptions===void 0?{id:e.id}:e.source===void 0?e.providerOptions===void 0?{contextWindowTokens:e.contextWindowTokens,id:e.id}:{contextWindowTokens:e.contextWindowTokens,id:e.id,providerOptions:{...e.providerOptions}}:e.contextWindowTokens===void 0&&e.providerOptions===void 0?{id:e.id,source:{...e.source}}:{contextWindowTokens:e.contextWindowTokens,id:e.id,providerOptions:e.providerOptions===void 0?void 0:{...e.providerOptions},source:{...e.source}}}export{COMPILED_AGENT_MANIFEST_KIND,COMPILED_AGENT_MANIFEST_VERSION,ROOT_COMPILED_AGENT_NODE_ID,compiledAgentManifestSchema,createCompiledAgentManifest,createCompiledAgentNodeManifest,createCompiledSubagentNodeId,deriveResourceRootEntries};
1
+ import{z}from"#compiled/zod/index.js";import{discoverDiagnosticsSummarySchema}from"#discover/diagnostics.js";import{compiledRemoteAgentNodeSchema}from"#compiler/remote-agent-node.js";import{jsonObjectSchema}from"#shared/json-schemas.js";const COMPILED_AGENT_MANIFEST_KIND=`ash-agent-compiled-manifest`,ROOT_COMPILED_AGENT_NODE_ID=`__root__`,COMPILED_AGENT_MANIFEST_VERSION=25,moduleSourceRefSchema=z.object({exportName:z.string().optional(),sourceKind:z.literal(`module`),logicalPath:z.string(),sourceId:z.string()}).strict(),channelMethodSchema=z.union([z.literal(`GET`),z.literal(`POST`),z.literal(`PUT`),z.literal(`PATCH`),z.literal(`DELETE`)]),compiledChannelDefinitionSchema=z.object({kind:z.literal(`channel`),name:z.string(),logicalPath:z.string(),method:channelMethodSchema,urlPath:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`),exportName:z.string().optional(),adapterKind:z.string().optional()}).strict(),disabledCompiledChannelEntrySchema=z.object({kind:z.literal(`disabled`),name:z.string(),logicalPath:z.string()}).strict(),compiledChannelEntrySchema=z.union([compiledChannelDefinitionSchema,disabledCompiledChannelEntrySchema]),compiledRuntimeModelReferenceSchema=z.object({contextWindowTokens:z.number().int().positive().optional(),id:z.string(),source:moduleSourceRefSchema.optional(),providerOptions:z.record(z.string(),jsonObjectSchema).optional()}).strict(),compiledAgentBuildDefinitionSchema=z.object({externalDependencies:z.array(z.string()).optional()}).strict(),compiledAgentCompactionDefinitionSchema=z.object({model:compiledRuntimeModelReferenceSchema.optional(),thresholdPercent:z.number().finite().min(0).max(1).optional()}).strict(),compiledAgentConfigSchema=z.object({build:compiledAgentBuildDefinitionSchema.optional(),compaction:compiledAgentCompactionDefinitionSchema.optional(),description:z.string().optional(),experimental:z.object({codeMode:z.boolean().optional()}).strict().optional(),model:compiledRuntimeModelReferenceSchema,name:z.string(),source:moduleSourceRefSchema.optional()}).strict(),compiledInstructionsSchema=z.object({name:z.string(),logicalPath:z.string(),markdown:z.string(),sourceId:z.string(),sourceKind:z.union([z.literal(`markdown`),z.literal(`module`)])}).strict(),compiledSkillBaseFields={name:z.string(),description:z.string(),license:z.string().optional(),markdown:z.string(),metadata:z.record(z.string(),z.string()).optional(),sourceId:z.string(),logicalPath:z.string()},compiledSkillSourceSchema=z.discriminatedUnion(`sourceKind`,[z.object({...compiledSkillBaseFields,sourceKind:z.literal(`markdown`)}).strict(),z.object({...compiledSkillBaseFields,sourceKind:z.literal(`module`),exportName:z.string().optional()}).strict(),z.object({...compiledSkillBaseFields,sourceKind:z.literal(`skill-package`),skillId:z.string(),skillFilePath:z.string(),rootPath:z.string(),assetsPath:z.string().optional(),referencesPath:z.string().optional(),scriptsPath:z.string().optional()}).strict()]),compiledScheduleDefinitionSchema=z.object({cron:z.string(),hasRun:z.boolean(),name:z.string(),logicalPath:z.string(),markdown:z.string().optional(),sourceId:z.string(),sourceKind:z.union([z.literal(`markdown`),z.literal(`module`)])}).strict(),compiledSandboxDefinitionSchema=z.object({description:z.string().optional(),exportName:z.string().optional(),logicalPath:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`)}).strict(),compiledSandboxWorkspaceSchema=z.object({logicalPath:z.string(),rootEntries:z.array(z.string()).readonly(),sourceId:z.string(),sourcePath:z.string()}).strict(),compiledWorkspaceResourceRootSchema=z.object({logicalPath:z.string(),rootEntries:z.array(z.string()).readonly()}).strict(),compiledConnectionDefinitionSchema=z.object({connectionName:z.string(),description:z.string(),exportName:z.string().optional(),logicalPath:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`),url:z.string(),vercelConnect:z.object({connector:z.string()}).strict().optional()}).strict(),compiledToolDefinitionSchema=z.object({description:z.string(),exportName:z.string().optional(),inputSchema:jsonObjectSchema.nullable(),logicalPath:z.string(),name:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`)}).strict(),compiledDynamicToolDefinitionSchema=z.object({eventNames:z.array(z.string()).readonly(),exportName:z.string().optional(),logicalPath:z.string(),slug:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`)}).strict(),compiledDynamicSkillDefinitionSchema=z.object({eventNames:z.array(z.string()).readonly(),exportName:z.string().optional(),logicalPath:z.string(),slug:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`)}).strict(),compiledHookDefinitionSchema=z.object({exportName:z.string().optional(),logicalPath:z.string(),slug:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`)}).strict(),compiledAgentNodeManifestSchema=z.object({agentRoot:z.string(),appRoot:z.string(),channels:z.array(compiledChannelEntrySchema),config:compiledAgentConfigSchema,connections:z.array(compiledConnectionDefinitionSchema),diagnosticsSummary:discoverDiagnosticsSummarySchema,disabledFrameworkTools:z.array(z.string()).readonly(),dynamicSkills:z.array(compiledDynamicSkillDefinitionSchema).default([]),dynamicTools:z.array(compiledDynamicToolDefinitionSchema).default([]),hooks:z.array(compiledHookDefinitionSchema),sandbox:compiledSandboxDefinitionSchema.nullable(),sandboxWorkspaces:z.array(compiledSandboxWorkspaceSchema),schedules:z.array(compiledScheduleDefinitionSchema),remoteAgents:z.array(compiledRemoteAgentNodeSchema),skills:z.array(compiledSkillSourceSchema).readonly(),instructions:compiledInstructionsSchema.optional(),tools:z.array(compiledToolDefinitionSchema),workspaceResourceRoot:compiledWorkspaceResourceRootSchema}).strict(),compiledSubagentNodeSchema=z.object({agent:compiledAgentNodeManifestSchema,description:z.string(),entryPath:z.string(),logicalPath:z.string(),name:z.string(),nodeId:z.string(),rootPath:z.string(),sourceId:z.string(),sourceKind:z.literal(`module`),exportName:z.string().optional()}).strict(),compiledSubagentEdgeSchema=z.object({childNodeId:z.string(),parentNodeId:z.string()}).strict(),compiledAgentManifestSchema=z.object({agentRoot:z.string(),appRoot:z.string(),channels:z.array(compiledChannelEntrySchema),config:compiledAgentConfigSchema,connections:z.array(compiledConnectionDefinitionSchema),diagnosticsSummary:discoverDiagnosticsSummarySchema,disabledFrameworkTools:z.array(z.string()).readonly(),dynamicSkills:z.array(compiledDynamicSkillDefinitionSchema).default([]),dynamicTools:z.array(compiledDynamicToolDefinitionSchema).default([]),hooks:z.array(compiledHookDefinitionSchema),kind:z.literal(COMPILED_AGENT_MANIFEST_KIND),remoteAgents:z.array(compiledRemoteAgentNodeSchema),sandbox:compiledSandboxDefinitionSchema.nullable(),sandboxWorkspaces:z.array(compiledSandboxWorkspaceSchema),schedules:z.array(compiledScheduleDefinitionSchema),skills:z.array(compiledSkillSourceSchema).readonly(),subagentEdges:z.array(compiledSubagentEdgeSchema),subagents:z.array(compiledSubagentNodeSchema),instructions:compiledInstructionsSchema.optional(),tools:z.array(compiledToolDefinitionSchema),version:z.literal(25),workspaceResourceRoot:compiledWorkspaceResourceRootSchema}).strict();function createCompiledAgentNodeManifest(e){let t={agentRoot:e.agentRoot,appRoot:e.appRoot,channels:[...e.channels??[]],connections:[...e.connections??[]],config:{build:e.config.build===void 0?void 0:{externalDependencies:e.config.build.externalDependencies===void 0?void 0:[...e.config.build.externalDependencies]},compaction:{model:e.config.compaction?.model===void 0?void 0:cloneCompiledRuntimeModelReference(e.config.compaction.model),thresholdPercent:e.config.compaction?.thresholdPercent},description:e.config.description,experimental:e.config.experimental===void 0?void 0:{codeMode:e.config.experimental.codeMode},model:cloneCompiledRuntimeModelReference(e.config.model),name:e.config.name,source:e.config.source===void 0?void 0:{...e.config.source}},diagnosticsSummary:e.diagnosticsSummary??{errors:0,warnings:0},disabledFrameworkTools:[...e.disabledFrameworkTools??[]],dynamicSkills:[...e.dynamicSkills??[]],dynamicTools:[...e.dynamicTools??[]],hooks:[...e.hooks??[]],remoteAgents:[...e.remoteAgents??[]],sandbox:e.sandbox??null,sandboxWorkspaces:[...e.sandboxWorkspaces??[]],schedules:[...e.schedules??[]],skills:[...e.skills??[]],tools:[...e.tools??[]],workspaceResourceRoot:e.workspaceResourceRoot??{logicalPath:``,rootEntries:deriveResourceRootEntries({sandboxWorkspaces:e.sandboxWorkspaces,skills:e.skills})}};return e.instructions!==void 0&&(t.instructions=e.instructions),t}function deriveResourceRootEntries(e){let t=new Set;(e.skills??[]).length>0&&t.add(`skills/`);for(let n of e.sandboxWorkspaces??[])for(let e of n.rootEntries)t.add(e);return[...t].sort((e,t)=>e.localeCompare(t))}function createCompiledSubagentNodeId(e,t){return e===`__root__`?t:`${e}::${t}`}function createCompiledAgentManifest(e){return{...createCompiledAgentNodeManifest(e),kind:COMPILED_AGENT_MANIFEST_KIND,subagentEdges:[...e.subagentEdges??[]],subagents:[...e.subagents??[]],version:25}}function cloneCompiledRuntimeModelReference(e){return e.contextWindowTokens===void 0&&e.source===void 0&&e.providerOptions===void 0?{id:e.id}:e.source===void 0?e.providerOptions===void 0?{contextWindowTokens:e.contextWindowTokens,id:e.id}:{contextWindowTokens:e.contextWindowTokens,id:e.id,providerOptions:{...e.providerOptions}}:e.contextWindowTokens===void 0&&e.providerOptions===void 0?{id:e.id,source:{...e.source}}:{contextWindowTokens:e.contextWindowTokens,id:e.id,providerOptions:e.providerOptions===void 0?void 0:{...e.providerOptions},source:{...e.source}}}export{COMPILED_AGENT_MANIFEST_KIND,COMPILED_AGENT_MANIFEST_VERSION,ROOT_COMPILED_AGENT_NODE_ID,compiledAgentManifestSchema,createCompiledAgentManifest,createCompiledAgentNodeManifest,createCompiledSubagentNodeId,deriveResourceRootEntries};
@@ -1,5 +1,5 @@
1
1
  import{z}from"#compiled/zod/index.js";import{ROOT_COMPILED_AGENT_NODE_ID}from"#compiler/manifest.js";import{normalizeEsmImportSpecifier}from"#internal/application/import-specifier.js";const compiledModuleNodeScopeSchema=z.object({modules:z.record(z.string(),z.object({}).passthrough())}).strict(),compiledModuleMapSchema=z.object({nodes:z.record(z.string(),compiledModuleNodeScopeSchema)}).strict();function createCompiledModuleMapSource(e){let n=dirnameFilesystemPath(e.moduleMapPath),r=e.importSpecifierStyle??`relative`,i=0,a=[collectModuleNodeScope({agentRoot:e.manifest.agentRoot,importSpecifierStyle:r,manifest:e.manifest,moduleMapDirectory:n,nextBindingName(){return`module_${i++}`},nodeId:ROOT_COMPILED_AGENT_NODE_ID}),...[...e.manifest.subagents].sort((e,t)=>e.nodeId.localeCompare(t.nodeId)).map(e=>collectModuleNodeScope({agentRoot:e.agent.agentRoot,importSpecifierStyle:r,manifest:e.agent,moduleMapDirectory:n,nextBindingName(){return`module_${i++}`},nodeId:e.nodeId}))],o=a.flatMap(e=>e.modules.map(e=>`import * as ${e.bindingName} from ${JSON.stringify(e.importSpecifier)};`));return[`// Generated by Ash. Do not edit by hand.`,``,...o,...o.length>0?[``]:[],`export const moduleMap = ${renderModuleMap(a)};`,``,`export default moduleMap;`,``].join(`
2
- `)}function collectModuleNodeScope(e){return{modules:collectModuleRefsForManifest(e.manifest).sort((e,t)=>e.sourceId.localeCompare(t.sourceId)).map(t=>({bindingName:e.nextBindingName(),importSpecifier:createImportSpecifier({fromDirectory:e.moduleMapDirectory,importSpecifierStyle:e.importSpecifierStyle,targetPath:joinFilesystemPath(e.agentRoot,t.logicalPath)}),sourceId:t.sourceId})),nodeId:e.nodeId}}function collectModuleRefsForManifest(e){let t=new Map;e.config.source!==void 0&&t.set(e.config.source.sourceId,e.config.source),e.config.model.source!==void 0&&t.set(e.config.model.source.sourceId,e.config.model.source);for(let n of e.channels)n.kind!==`disabled`&&t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.connections)t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.tools)t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.dynamicTools)t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.remoteAgents)t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.hooks)t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.schedules)n.sourceKind!==`module`||!n.hasRun||t.set(n.sourceId,{sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});return e.sandbox!==null&&t.set(e.sandbox.sourceId,{exportName:e.sandbox.exportName,sourceKind:`module`,logicalPath:e.sandbox.logicalPath,sourceId:e.sandbox.sourceId}),[...t.values()]}function createImportSpecifier(e){if(e.importSpecifierStyle===`absolute`)return normalizeEsmImportSpecifier(normalizeFilesystemPath(e.targetPath));let t=relativeFilesystemPath(e.fromDirectory,e.targetPath);return t.startsWith(`.`)?t:`./${t}`}function renderModuleMap(e){return renderFrozenObject([{key:`nodes`,value:renderFrozenObject(e.map(e=>({key:e.nodeId,value:renderFrozenObject([{key:`modules`,value:renderFrozenObject(e.modules.map(e=>({key:e.sourceId,value:e.bindingName})))}],3)})))}],0)}function renderFrozenObject(e,t=1){if(e.length===0)return`Object.freeze({})`;let n=` `.repeat(t),r=` `.repeat(t+1);return[`Object.freeze({`,e.map(e=>`${r}${JSON.stringify(e.key)}: ${e.value.replaceAll(`
2
+ `)}function collectModuleNodeScope(e){return{modules:collectModuleRefsForManifest(e.manifest).sort((e,t)=>e.sourceId.localeCompare(t.sourceId)).map(t=>({bindingName:e.nextBindingName(),importSpecifier:createImportSpecifier({fromDirectory:e.moduleMapDirectory,importSpecifierStyle:e.importSpecifierStyle,targetPath:joinFilesystemPath(e.agentRoot,t.logicalPath)}),sourceId:t.sourceId})),nodeId:e.nodeId}}function collectModuleRefsForManifest(e){let t=new Map;e.config.source!==void 0&&t.set(e.config.source.sourceId,e.config.source),e.config.model.source!==void 0&&t.set(e.config.model.source.sourceId,e.config.model.source);for(let n of e.channels)n.kind!==`disabled`&&t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.connections)t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.tools)t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.dynamicSkills)t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.dynamicTools)t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.remoteAgents)t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.hooks)t.set(n.sourceId,{exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});for(let n of e.schedules)n.sourceKind!==`module`||!n.hasRun||t.set(n.sourceId,{sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId});return e.sandbox!==null&&t.set(e.sandbox.sourceId,{exportName:e.sandbox.exportName,sourceKind:`module`,logicalPath:e.sandbox.logicalPath,sourceId:e.sandbox.sourceId}),[...t.values()]}function createImportSpecifier(e){if(e.importSpecifierStyle===`absolute`)return normalizeEsmImportSpecifier(normalizeFilesystemPath(e.targetPath));let t=relativeFilesystemPath(e.fromDirectory,e.targetPath);return t.startsWith(`.`)?t:`./${t}`}function renderModuleMap(e){return renderFrozenObject([{key:`nodes`,value:renderFrozenObject(e.map(e=>({key:e.nodeId,value:renderFrozenObject([{key:`modules`,value:renderFrozenObject(e.modules.map(e=>({key:e.sourceId,value:e.bindingName})))}],3)})))}],0)}function renderFrozenObject(e,t=1){if(e.length===0)return`Object.freeze({})`;let n=` `.repeat(t),r=` `.repeat(t+1);return[`Object.freeze({`,e.map(e=>`${r}${JSON.stringify(e.key)}: ${e.value.replaceAll(`
3
3
  `,`\n${r}`)}`).join(`,
4
4
  `),`${n}})`].join(`
5
5
  `)}function dirnameFilesystemPath(e){let t=splitFilesystemPath(e);return t.segments.length===0?t.root.length===0?`.`:t.root:createFilesystemPath(t.root,t.segments.slice(0,-1))}function joinFilesystemPath(e,t){let n=splitFilesystemPath(e),r=splitFilesystemPath(t);return r.root.length>0?createFilesystemPath(r.root,r.segments):createFilesystemPath(n.root,[...n.segments,...r.segments])}function relativeFilesystemPath(e,t){let n=splitFilesystemPath(e),r=splitFilesystemPath(t);if(n.root!==r.root)return normalizeFilesystemPath(t);let i=0;for(;i<n.segments.length&&i<r.segments.length&&n.segments[i]===r.segments[i];)i+=1;let a=[...Array.from({length:n.segments.length-i},()=>`..`),...r.segments.slice(i)];return a.length===0?`.`:a.join(`/`)}function normalizeFilesystemPath(e){let t=splitFilesystemPath(e);return createFilesystemPath(t.root,t.segments)}function splitFilesystemPath(e){let t=e.replaceAll(`\\`,`/`),n=``,r=t,i=t.match(/^[A-Za-z]:/);i===null?t.startsWith(`/`)&&(n=`/`,r=t.slice(1)):(n=i[0],r=t.slice(n.length),r.startsWith(`/`)&&(n=`${n}/`,r=r.slice(1)));let a=[];for(let e of r.split(`/`))if(!(e.length===0||e===`.`)){if(e===`..`){if(a.length>0&&a[a.length-1]!==`..`){a.pop();continue}n.length===0&&a.push(e);continue}a.push(e)}return{root:n,segments:a}}function createFilesystemPath(e,t){return e===`/`?t.length===0?`/`:`/${t.join(`/`)}`:e.endsWith(`/`)?t.length===0?e:`${e}${t.join(`/`)}`:e.length>0?t.length===0?e:`${e}/${t.join(`/`)}`:t.length===0?`.`:t.join(`/`)}export{collectModuleRefsForManifest,compiledModuleMapSchema,createCompiledModuleMapSource};
@@ -1 +1 @@
1
- import{compileChannelDefinition}from"#compiler/normalize-channel.js";import{ROOT_COMPILED_AGENT_NODE_ID,createCompiledAgentManifest,createCompiledAgentNodeManifest}from"#compiler/manifest.js";import{createCompiledRuntimeModelCatalogLoader}from"#compiler/model-catalog.js";import{compileAgentConfig}from"#compiler/normalize-agent-config.js";import{compileConnectionDefinition}from"#compiler/normalize-connection.js";import{compileHookEntry}from"#compiler/normalize-hook.js";import{compileSandboxDefinition}from"#compiler/normalize-sandbox.js";import{compileInstructions}from"#compiler/normalize-instructions.js";import{compileScheduleDefinition}from"#compiler/normalize-schedule.js";import{compileSkillSource}from"#compiler/normalize-skill.js";import{compileSubagentGraph}from"#compiler/normalize-subagent.js";import{compileToolEntry}from"#compiler/normalize-tool.js";async function compileAgentManifest(e){let r={modelCatalog:createCompiledRuntimeModelCatalogLoader(e.appRoot)},[a,o]=await Promise.all([compileAgentNodeManifest(e,r),compileSubagentGraph({appRoot:e.appRoot,compileAgentNodeManifest,context:r,parentNodeId:ROOT_COMPILED_AGENT_NODE_ID,subagents:e.subagents})]);return createCompiledAgentManifest({...a,remoteAgents:o.remoteAgents,subagentEdges:o.edges,subagents:o.nodes})}async function compileAgentNodeManifest(t,n){let i=await Promise.all(t.tools.map(e=>compileToolEntry(t.agentRoot,e))),s=[],c=[],l=[];for(let e of i)e.kind===`tool`?s.push(e.definition):e.kind===`dynamic-tool`?c.push(e.definition):l.push(e.name);let u=(await Promise.all(t.channels.map(n=>compileChannelDefinition(t.agentRoot,n)))).flat();return createCompiledAgentNodeManifest({agentRoot:t.agentRoot,appRoot:t.appRoot,channels:u,config:await compileAgentConfig(t,n),connections:await Promise.all(t.connections.map(e=>compileConnectionDefinition(t.agentRoot,e))),diagnosticsSummary:t.diagnosticsSummary,disabledFrameworkTools:l,dynamicTools:c,hooks:t.hooks.map(e=>compileHookEntry(e)),sandbox:t.sandbox===null?null:await compileSandboxDefinition(t.agentRoot,t.sandbox),sandboxWorkspaces:t.sandboxWorkspaces.map(e=>({logicalPath:e.logicalPath,rootEntries:[...e.rootEntries],sourceId:e.sourceId,sourcePath:e.sourcePath})),schedules:await Promise.all(t.schedules.map(e=>compileScheduleDefinition(t.agentRoot,e))),skills:await Promise.all(t.skills.map(e=>compileSkillSource(t.agentRoot,e))),instructions:t.instructions===void 0?void 0:await compileInstructions(t.agentRoot,t.instructions),tools:s})}export{compileAgentManifest};
1
+ import{compileChannelDefinition}from"#compiler/normalize-channel.js";import{ROOT_COMPILED_AGENT_NODE_ID,createCompiledAgentManifest,createCompiledAgentNodeManifest}from"#compiler/manifest.js";import{createCompiledRuntimeModelCatalogLoader}from"#compiler/model-catalog.js";import{compileAgentConfig}from"#compiler/normalize-agent-config.js";import{compileConnectionDefinition}from"#compiler/normalize-connection.js";import{compileHookEntry}from"#compiler/normalize-hook.js";import{compileSandboxDefinition}from"#compiler/normalize-sandbox.js";import{compileInstructions}from"#compiler/normalize-instructions.js";import{compileScheduleDefinition}from"#compiler/normalize-schedule.js";import{compileSkillSource}from"#compiler/normalize-skill.js";import{compileSubagentGraph}from"#compiler/normalize-subagent.js";import{compileToolEntry}from"#compiler/normalize-tool.js";async function compileAgentManifest(e){let r={modelCatalog:createCompiledRuntimeModelCatalogLoader(e.appRoot)},[a,o]=await Promise.all([compileAgentNodeManifest(e,r),compileSubagentGraph({appRoot:e.appRoot,compileAgentNodeManifest,context:r,parentNodeId:ROOT_COMPILED_AGENT_NODE_ID,subagents:e.subagents})]);return createCompiledAgentManifest({...a,remoteAgents:o.remoteAgents,subagentEdges:o.edges,subagents:o.nodes})}async function compileAgentNodeManifest(t,n){let i=await Promise.all(t.tools.map(e=>compileToolEntry(t.agentRoot,e))),s=[],c=[],l=[];for(let e of i)e.kind===`tool`?s.push(e.definition):e.kind===`dynamic-tool`?c.push(e.definition):l.push(e.name);let u=(await Promise.all(t.channels.map(n=>compileChannelDefinition(t.agentRoot,n)))).flat(),d=await Promise.all(t.skills.map(e=>compileSkillSource(t.agentRoot,e))),f=[],p=[];for(let e of d)e.kind===`skill`?f.push(e.definition):p.push(e.definition);return createCompiledAgentNodeManifest({agentRoot:t.agentRoot,appRoot:t.appRoot,channels:u,config:await compileAgentConfig(t,n),connections:await Promise.all(t.connections.map(e=>compileConnectionDefinition(t.agentRoot,e))),diagnosticsSummary:t.diagnosticsSummary,disabledFrameworkTools:l,dynamicSkills:p,dynamicTools:c,hooks:t.hooks.map(e=>compileHookEntry(e)),sandbox:t.sandbox===null?null:await compileSandboxDefinition(t.agentRoot,t.sandbox),sandboxWorkspaces:t.sandboxWorkspaces.map(e=>({logicalPath:e.logicalPath,rootEntries:[...e.rootEntries],sourceId:e.sourceId,sourcePath:e.sourcePath})),schedules:await Promise.all(t.schedules.map(e=>compileScheduleDefinition(t.agentRoot,e))),skills:f,instructions:t.instructions===void 0?void 0:await compileInstructions(t.agentRoot,t.instructions),tools:s})}export{compileAgentManifest};
@@ -1,8 +1,21 @@
1
1
  import type { SkillSourceRef } from "#discover/manifest.js";
2
- import type { CompiledSkillDefinition } from "#compiler/manifest.js";
2
+ import type { CompiledDynamicSkillDefinition, CompiledSkillDefinition } from "#compiler/manifest.js";
3
+ /**
4
+ * Compiled skill entry produced from one authored `skills/*` file.
5
+ *
6
+ * Either a real skill definition or a dynamic skill resolver that
7
+ * produces skills at runtime.
8
+ */
9
+ export type CompiledSkillEntry = {
10
+ readonly kind: "skill";
11
+ readonly definition: CompiledSkillDefinition;
12
+ } | {
13
+ readonly kind: "dynamic-skill";
14
+ readonly definition: CompiledDynamicSkillDefinition;
15
+ };
3
16
  /**
4
17
  * Compiles one authored skill source (markdown, module, or skill
5
18
  * package directory) into the normalized shape stored on the compiled
6
19
  * agent manifest.
7
20
  */
8
- export declare function compileSkillSource(agentRoot: string, source: SkillSourceRef): Promise<CompiledSkillDefinition>;
21
+ export declare function compileSkillSource(agentRoot: string, source: SkillSourceRef): Promise<CompiledSkillEntry>;
@@ -1 +1 @@
1
- import{stripLogicalPathExtension}from"#discover/filesystem.js";import{normalizeSkillDefinition}from"#internal/authored-definition/core.js";import{loadModuleBackedDefinition}from"#compiler/normalize-helpers.js";async function compileSkillSource(t,n){if(n.sourceKind===`skill-package`)return compileSkillPackageSource(n);let r=n.sourceKind===`markdown`?normalizeSkillDefinition(n.definition,`Expected the compiled skill definition at "${n.logicalPath}" to match the public Ash shape.`):normalizeSkillDefinition(await loadModuleBackedDefinition({agentRoot:t,kind:`skill`,source:n}),`Expected the skill export "${n.exportName??`default`}" from "${n.logicalPath}" to match the public Ash shape.`);return{description:r.description,files:r.files,license:r.license,logicalPath:n.logicalPath,markdown:r.markdown,metadata:r.metadata===void 0?void 0:{...r.metadata},name:stripLogicalPathExtension(n.logicalPath).replace(/^skills\//,``),sourceId:n.sourceId,sourceKind:n.sourceKind}}function compileSkillPackageSource(e){return{assetsPath:e.assetsPath,description:e.description,license:e.license,logicalPath:e.logicalPath,markdown:e.markdown,metadata:e.metadata===void 0?void 0:{...e.metadata},name:e.name,referencesPath:e.referencesPath,rootPath:e.rootPath,scriptsPath:e.scriptsPath,skillId:e.skillId,skillFilePath:e.skillFilePath,sourceId:e.sourceId,sourceKind:`skill-package`}}export{compileSkillSource};
1
+ import{stripLogicalPathExtension}from"#discover/filesystem.js";import{normalizeSkillDefinition}from"#internal/authored-definition/core.js";import{loadModuleBackedDefinition}from"#compiler/normalize-helpers.js";import{isDynamicSentinel}from"#shared/dynamic-tool-definition.js";async function compileSkillSource(r,i){if(i.sourceKind===`skill-package`)return{kind:`skill`,definition:compileSkillPackageSource(i)};if(i.sourceKind===`markdown`){let n=normalizeSkillDefinition(i.definition,`Expected the compiled skill definition at "${i.logicalPath}" to match the public Ash shape.`);return{kind:`skill`,definition:{description:n.description,files:n.files,license:n.license,logicalPath:i.logicalPath,markdown:n.markdown,metadata:n.metadata===void 0?void 0:{...n.metadata},name:stripLogicalPathExtension(i.logicalPath).replace(/^skills\//,``),sourceId:i.sourceId,sourceKind:i.sourceKind}}}let a=await loadModuleBackedDefinition({agentRoot:r,kind:`skill`,source:i});if(isDynamicSentinel(a)){let t=stripLogicalPathExtension(i.logicalPath).replace(/^skills\//,``);return{kind:`dynamic-skill`,definition:{eventNames:Object.keys(a.events),exportName:i.exportName,logicalPath:i.logicalPath,slug:t,sourceId:i.sourceId,sourceKind:`module`}}}let o=normalizeSkillDefinition(a,`Expected the skill export "${i.exportName??`default`}" from "${i.logicalPath}" to match the public Ash shape.`);return{kind:`skill`,definition:{description:o.description,files:o.files,license:o.license,logicalPath:i.logicalPath,markdown:o.markdown,metadata:o.metadata===void 0?void 0:{...o.metadata},name:stripLogicalPathExtension(i.logicalPath).replace(/^skills\//,``),sourceId:i.sourceId,sourceKind:i.sourceKind}}}function compileSkillPackageSource(e){return{assetsPath:e.assetsPath,description:e.description,license:e.license,logicalPath:e.logicalPath,markdown:e.markdown,metadata:e.metadata===void 0?void 0:{...e.metadata},name:e.name,referencesPath:e.referencesPath,rootPath:e.rootPath,scriptsPath:e.scriptsPath,skillId:e.skillId,skillFilePath:e.skillFilePath,sourceId:e.sourceId,sourceKind:`skill-package`}}export{compileSkillSource};
@@ -1 +1 @@
1
- import{stripLogicalPathExtension}from"#discover/filesystem.js";import{loadModuleBackedDefinition}from"#compiler/normalize-helpers.js";import{normalizeToolDefinition}from"#internal/authored-definition/schema-backed.js";async function compileToolEntry(e,t){let n=normalizeToolDefinition(await loadModuleBackedDefinition({agentRoot:e,kind:`tool`,source:t}),`Expected the tool export "${t.exportName??`default`}" from "${t.logicalPath}" to match the public Ash shape.`),r=stripLogicalPathExtension(t.logicalPath).replace(/^tools\//,``).replaceAll(`/`,`-`);return n.kind===`disabled`?{kind:`disabled`,name:r}:n.kind===`dynamic-tool`?{kind:`dynamic-tool`,definition:{eventNames:[...n.eventNames],exportName:t.exportName,identity:n.identity,logicalPath:t.logicalPath,slug:r,sourceId:t.sourceId,sourceKind:`module`}}:{kind:`tool`,definition:{description:n.definition.description,exportName:t.exportName,inputSchema:n.definition.inputSchema??null,logicalPath:t.logicalPath,name:r,sourceId:t.sourceId,sourceKind:`module`}}}export{compileToolEntry};
1
+ import{stripLogicalPathExtension}from"#discover/filesystem.js";import{loadModuleBackedDefinition}from"#compiler/normalize-helpers.js";import{normalizeToolDefinition}from"#internal/authored-definition/schema-backed.js";async function compileToolEntry(e,t){let n=normalizeToolDefinition(await loadModuleBackedDefinition({agentRoot:e,kind:`tool`,source:t}),`Expected the tool export "${t.exportName??`default`}" from "${t.logicalPath}" to match the public Ash shape.`),r=stripLogicalPathExtension(t.logicalPath).replace(/^tools\//,``).replaceAll(`/`,`-`);return n.kind===`disabled`?{kind:`disabled`,name:r}:n.kind===`dynamic-tool`?{kind:`dynamic-tool`,definition:{eventNames:[...n.eventNames],exportName:t.exportName,logicalPath:t.logicalPath,slug:r,sourceId:t.sourceId,sourceKind:`module`}}:{kind:`tool`,definition:{description:n.definition.description,exportName:t.exportName,inputSchema:n.definition.inputSchema??null,logicalPath:t.logicalPath,name:r,sourceId:t.sourceId,sourceKind:`module`}}}export{compileToolEntry};
@@ -0,0 +1,23 @@
1
+ import type { ModelMessage } from "ai";
2
+ import type { HandleMessageStreamEvent } from "#protocol/message.js";
3
+ import type { ResolvedDynamicSkillResolver } from "#runtime/types.js";
4
+ import type { ContextContainer } from "#context/container.js";
5
+ import { ContextKey } from "#context/key.js";
6
+ /**
7
+ * Virtual (non-serialized) pending skill announcement text. Set by
8
+ * {@link dispatchDynamicSkillEvent} when skills are materialized. Read
9
+ * by the tool-loop to inject the announcement into model context.
10
+ */
11
+ export declare const PendingSkillAnnouncementKey: ContextKey<string>;
12
+ /**
13
+ * Dispatches a stream event to dynamic skill resolvers. On a matching
14
+ * event: runs handlers, materializes resolved skills to the sandbox,
15
+ * cleans up removed skills, and stores a pending announcement for the
16
+ * tool-loop to inject.
17
+ */
18
+ export declare function dispatchDynamicSkillEvent(input: {
19
+ readonly ctx: ContextContainer;
20
+ readonly resolvers: readonly ResolvedDynamicSkillResolver[];
21
+ readonly event: HandleMessageStreamEvent;
22
+ readonly messages: readonly ModelMessage[];
23
+ }): Promise<void>;
@@ -0,0 +1 @@
1
+ import{createLogger}from"#internal/logging.js";import{getAdapterKind}from"#channel/adapter.js";import{AuthKey,ContinuationTokenKey,DynamicSkillManifestKey,InitiatorAuthKey,SandboxKey,SessionIdKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{ALLOWED_DYNAMIC_TOOL_EVENTS}from"#shared/dynamic-tool-definition.js";import{normalizeSkillPackage,writeSkillPackageToSandbox}from"#shared/skill-package.js";import{ContextKey}from"#context/key.js";import{formatAvailableSkillsSection}from"#execution/skills/instructions.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";const log=createLogger(`dynamic-skills`),WORKSPACE_SKILLS_PREFIX=`/workspace/skills/`;function buildResolveContext(e,i){let o=e.get(SessionIdKey)??``,c=e.get(AuthKey)??null,l=e.get(InitiatorAuthKey)??null,u=e.get(ChannelKey),d=e.get(ContinuationTokenKey);return{session:{id:o,auth:{current:c,initiator:l}},channel:{kind:u===void 0?void 0:getAdapterKind(u),continuationToken:d},messages:i}}function qualifyDynamicSkillNames(e,t,n){let r=Object.keys(n),i=[];if(r.length===0)return i;if(t||r.length===1)return i.push({name:e,entryKey:r[0],entry:n[r[0]]}),i;for(let t of r)i.push({name:`${e}__${t}`,entryKey:t,entry:n[t]});return i}function isSkillEntry(e){return typeof e==`object`&&!!e&&typeof e.markdown==`string`&&typeof e.description==`string`}const PendingSkillAnnouncementKey=new ContextKey(`ash.pendingSkillAnnouncement`);async function dispatchDynamicSkillEvent(e){let{ctx:t,resolvers:n,event:r,messages:a}=e;if(!ALLOWED_DYNAMIC_TOOL_EVENTS.has(r.type))return;let s=n.filter(e=>e.eventNames.includes(r.type));if(s.length===0)return;let f=buildResolveContext(t,a),p=new Set(t.require(BundleKey).resolvedAgent.skills.map(e=>e.name)),m=t.get(DynamicSkillManifestKey)??{},h={...m},g=[],_=await Promise.allSettled(s.map(async e=>{let t=e.events[r.type];if(t===void 0)return null;let n=await t(r,f);if(n==null)return{resolver:e,entries:null};let i,a;return isSkillEntry(n)?(i={_single:n},a=!0):(i=n,a=!1),{resolver:e,entries:i,isSingle:a}})),v=await t.require(SandboxKey).get();for(let e of _){if(e.status===`rejected`){log.error(`Dynamic skill resolver (${r.type}) threw — skipping.`,{error:toErrorMessage(e.reason)});continue}if(e.value===null)continue;let{resolver:t,entries:n,isSingle:i}=e.value,a=m[t.slug]??[];if(n===null){if(a.length>0&&v!==null)for(let e of a)await v.run({command:`rm -rf ${WORKSPACE_SKILLS_PREFIX}${e}`});h[t.slug]=[];continue}let o=qualifyDynamicSkillNames(t.slug,i,n),s=new Set(o.map(e=>e.name));for(let{name:e}of o)if(p.has(e))throw Error(`Dynamic skill "${e}" from resolver "${t.slug}" conflicts with an authored skill.`);if(v!==null)for(let e of a)s.has(e)||await v.run({command:`rm -rf ${WORKSPACE_SKILLS_PREFIX}${e}`});if(v!==null)for(let{name:e,entry:t}of o){let n=normalizeSkillPackage({...t,name:e});await writeSkillPackageToSandbox({sandbox:v,skill:n}),g.push(n)}h[t.slug]=[...s]}if(t.set(DynamicSkillManifestKey,h),g.length>0){let e=formatAvailableSkillsSection(g);e!==null&&t.set(PendingSkillAnnouncementKey,e)}}export{PendingSkillAnnouncementKey,dispatchDynamicSkillEvent};
@@ -1,24 +1,9 @@
1
+ import { type ModelMessage } from "ai";
1
2
  import type { HarnessToolDefinition } from "#harness/execute-tool.js";
3
+ import type { HandleMessageStreamEvent } from "#protocol/message.js";
2
4
  import type { ResolvedDynamicToolResolver } from "#runtime/types.js";
3
- import type { AlsContext } from "#context/container.js";
5
+ import type { ContextContainer } from "#context/container.js";
4
6
  import type { DurableDynamicToolMetadata } from "#context/keys.js";
5
- type ReadableContext = Pick<AlsContext, "get">;
6
- interface WritableContext extends ReadableContext {
7
- set<T>(key: import("#context/key.js").ContextKey<T>, value: T): T;
8
- }
9
- /**
10
- * Calls session/turn-scoped resolvers and produces both live tool
11
- * definitions (for the current step) and durable metadata (for
12
- * replay on subsequent steps).
13
- *
14
- * Resolvers run concurrently via `Promise.allSettled` — each
15
- * resolver's I/O (database calls, API fetches) overlaps with the
16
- * others. A single resolver throwing does not block the rest.
17
- */
18
- export declare function resolveAndStoreDynamicSessionTools(ctx: ReadableContext & WritableContext, resolvers: readonly ResolvedDynamicToolResolver[], eventName?: string): Promise<{
19
- readonly tools: readonly HarnessToolDefinition[];
20
- readonly metadata: readonly DurableDynamicToolMetadata[];
21
- }>;
22
7
  /**
23
8
  * Reconstructs tool definitions from durable metadata using
24
9
  * registered step functions. No resolver re-invocation — the
@@ -27,9 +12,20 @@ export declare function resolveAndStoreDynamicSessionTools(ctx: ReadableContext
27
12
  */
28
13
  export declare function replayDynamicSessionTools(metadata: readonly DurableDynamicToolMetadata[], _resolvers: readonly ResolvedDynamicToolResolver[]): readonly HarnessToolDefinition[];
29
14
  /**
30
- * Resolves step-scoped dynamic tools. Called before every model call.
31
- * No caching — each step gets a fresh resolution. Resolvers run
32
- * concurrently.
15
+ * Unified dynamic tool event dispatch. Called by `handleEvent` for
16
+ * every stream event. Two phases:
17
+ *
18
+ * 1. **Build phase**: reconstruct tools from durable metadata when
19
+ * the virtual key is empty (workflow step boundary crossed).
20
+ * 2. **Resolve phase**: run resolver handlers for the current event,
21
+ * capture closures as durable metadata, produce live tools.
22
+ *
23
+ * The tool-loop reads {@link DynamicToolsKey} right before each model
24
+ * call. Events update it; the tool-loop picks up whatever is current.
33
25
  */
34
- export declare function resolveDynamicStepTools(ctx: ReadableContext, resolvers: readonly ResolvedDynamicToolResolver[]): Promise<readonly HarnessToolDefinition[]>;
35
- export {};
26
+ export declare function dispatchDynamicToolEvent(input: {
27
+ readonly ctx: ContextContainer;
28
+ readonly resolvers: readonly ResolvedDynamicToolResolver[];
29
+ readonly event: HandleMessageStreamEvent;
30
+ readonly messages: readonly ModelMessage[];
31
+ }): Promise<void>;
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{AuthKey,ContinuationTokenKey,DynamicToolResolverCacheKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{jsonSchema,zodSchema}from"ai";import{normalizeJsonSchemaDefinition}from"#internal/json-schema.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{getAdapterKind}from"#channel/adapter.js";const log=createLogger(`dynamic-tools`);function buildResolveContext(e,o,s){let c=e.get(SessionIdKey)??``,l=e.get(AuthKey)??null,u=e.get(InitiatorAuthKey)??null,d=e.get(ChannelKey),f=e.get(ContinuationTokenKey);return{session:{id:c,auth:{current:l,initiator:u}},channel:{kind:d===void 0?void 0:getAdapterKind(d),continuationToken:f},async __cache(t,n){let i=`${o}:${t}`,a=e.get(DynamicToolResolverCacheKey)??{};if(i in a)return a[i];let c=await n();if(s){let e={...a,[i]:c};s.set(DynamicToolResolverCacheKey,e)}return c}}}function toHarnessToolDefinition(e,t){return{description:t.description,execute:e=>t.execute(e,buildCallbackContext()),inputSchema:convertInputSchema(t.inputSchema),name:e}}function convertInputSchema(e){return typeof e==`object`&&e&&`~standard`in e?zodSchema(e):jsonSchema(e)}function qualifyDynamicToolNames(e,t,n){let r=Object.keys(n),i=[];if(r.length===0)return i;if(t===`single`)return i.push({name:e,entryKey:r[0],entry:n[r[0]]}),i;for(let t of r)i.push({name:`${e}__${t}`,entryKey:t,entry:n[t]});return i}async function resolveAndStoreDynamicSessionTools(e,t,n=`session.started`){let r=t.filter(e=>e.eventNames.includes(n));if(r.length===0)return{tools:[],metadata:[]};let i={type:n,data:{}},a=await Promise.allSettled(r.map(async t=>{let r=t.events[n];if(r===void 0)return null;let a=await r(i,buildResolveContext(e,t.slug,e));return a==null?null:{resolver:t,result:a}})),s=[],c=[];for(let e of a){if(e.status===`rejected`){log.error(`Dynamic tool resolver (${n}) threw — skipping.`,{error:toErrorMessage(e.reason)});continue}if(e.value===null)continue;let{resolver:t,result:r}=e.value,i=qualifyDynamicToolNames(t.slug,t.identity,r);for(let{name:e,entryKey:n,entry:r}of i){s.push(toHarnessToolDefinition(e,r));let i=`__executeStepFn`in r?r.__executeStepFn:void 0,a=`__closureVars`in r?r.__closureVars:void 0;c.push({name:e,description:r.description,inputSchema:normalizeJsonSchemaDefinition(r.inputSchema),resolverSlug:t.slug,entryKey:n,executeStepFnName:i?.stepId,closureVars:a===void 0?void 0:safeSerialize(a)})}}return{tools:s,metadata:c}}function replayDynamicSessionTools(e,t){let n=[];for(let t of e){if(!t.executeStepFnName||!t.closureVars){log.warn(`Dynamic tool "${t.name}" has no registered step function — skipping on this step. The bundler transform may not have processed this tool file.`);continue}let e=lookupStepFunction(t.executeStepFnName);if(!e){log.warn(`Dynamic tool "${t.name}" references step function "${t.executeStepFnName}" which is not registered — skipping on this step.`);continue}n.push({description:t.description,execute:n=>e(t.closureVars,n,buildCallbackContext()),inputSchema:jsonSchema(t.inputSchema),name:t.name})}return n}function lookupStepFunction(e){try{let t=globalThis[Symbol.for(`@workflow/core//registeredSteps`)];return t===void 0?null:t.get(e)||null}catch{return null}}function safeSerialize(e){try{return JSON.parse(JSON.stringify(e))}catch{return{}}}async function resolveDynamicStepTools(e,t){let n=t.filter(e=>e.eventNames.includes(`step.started`));if(n.length===0)return[];let r={type:`step.started`,data:{}},i=await Promise.allSettled(n.map(async t=>{let n=t.events[`step.started`];if(n===void 0)return null;let i=await n(r,buildResolveContext(e,t.slug));return i==null?null:{resolver:t,result:i}})),a=[];for(let e of i){if(e.status===`rejected`){log.error(`Dynamic tool resolver (step.started) threw — skipping.`,{error:toErrorMessage(e.reason)});continue}if(e.value===null)continue;let{resolver:t,result:n}=e.value,r=qualifyDynamicToolNames(t.slug,t.identity,n);for(let{name:e,entry:t}of r)a.push(toHarnessToolDefinition(e,t))}return a}export{replayDynamicSessionTools,resolveAndStoreDynamicSessionTools,resolveDynamicStepTools};
1
+ import{createLogger}from"#internal/logging.js";import{getAdapterKind}from"#channel/adapter.js";import{AuthKey,ContinuationTokenKey,DynamicSessionToolMetadataKey,DynamicToolsKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{ALLOWED_DYNAMIC_TOOL_EVENTS,isBrandedToolEntry}from"#shared/dynamic-tool-definition.js";import{ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{jsonSchema,zodSchema}from"ai";import{normalizeJsonSchemaDefinition}from"#internal/json-schema.js";import{buildCallbackContext}from"#context/build-callback-context.js";const log=createLogger(`dynamic-tools`);function buildResolveContext(e,i){let a=e.get(SessionIdKey)??``,c=e.get(AuthKey)??null,l=e.get(InitiatorAuthKey)??null,u=e.get(ChannelKey),f=e.get(ContinuationTokenKey);return{session:{id:a,auth:{current:c,initiator:l}},channel:{kind:u===void 0?void 0:getAdapterKind(u),continuationToken:f},messages:i}}function toHarnessToolDefinition(e,t){return{description:t.description,execute:e=>t.execute(e,buildCallbackContext()),inputSchema:convertInputSchema(t.inputSchema),name:e,...t.toModelOutput===void 0?{}:{toModelOutput:t.toModelOutput}}}function convertInputSchema(e){return typeof e==`object`&&e&&`~standard`in e?zodSchema(e):jsonSchema(e)}function qualifyDynamicToolNames(e,t,n){let r=Object.keys(n),i=[];if(r.length===0)return i;if(t)return i.push({name:e,entryKey:r[0],entry:n[r[0]]}),i;for(let t of r)i.push({name:`${e}__${t}`,entryKey:t,entry:n[t]});return i}function replayDynamicSessionTools(e,t){let n=[];for(let t of e){if(!t.executeStepFnName||!t.closureVars){log.warn(`Dynamic tool "${t.name}" has no registered step function — skipping on this step. The bundler transform may not have processed this tool file.`);continue}let e=lookupStepFunction(t.executeStepFnName);if(!e){log.warn(`Dynamic tool "${t.name}" references step function "${t.executeStepFnName}" which is not registered — skipping on this step.`);continue}n.push({description:t.description,execute:n=>e(t.closureVars,n,buildCallbackContext()),inputSchema:jsonSchema(t.inputSchema),name:t.name})}return n}function lookupStepFunction(e){try{let t=globalThis[Symbol.for(`@workflow/core//registeredSteps`)];return t===void 0?null:t.get(e)||null}catch{return null}}function safeSerialize(e){try{return JSON.parse(JSON.stringify(e))}catch{return{}}}function matchesAnySlug(e,t){for(let n of t)if(e===n||e.startsWith(`${n}__`))return!0;return!1}async function resolveToolsFromEvent(e,t,n,r){let a=await Promise.allSettled(t.map(async t=>{let i=t.events[n.type];if(i===void 0)return null;let a=await i(n,buildResolveContext(e,r));if(a==null)return null;let o,s;return isBrandedToolEntry(a)?(o={_single:a},s=!0):(o=a,s=!1),{resolver:t,entries:o,isSingle:s}})),o=[],s=[];for(let e of a){if(e.status===`rejected`){log.error(`Dynamic tool resolver (${n.type}) threw — skipping.`,{error:toErrorMessage(e.reason)});continue}if(e.value===null)continue;let{resolver:t,entries:r,isSingle:i}=e.value,a=qualifyDynamicToolNames(t.slug,i,r);for(let{name:e,entryKey:n,entry:r}of a){o.push(toHarnessToolDefinition(e,r));let i=`__executeStepFn`in r?r.__executeStepFn:void 0,a=`__closureVars`in r?r.__closureVars:void 0;s.push({name:e,description:r.description,inputSchema:normalizeJsonSchemaDefinition(r.inputSchema),resolverSlug:t.slug,entryKey:n,executeStepFnName:i?.stepId,closureVars:a===void 0?void 0:safeSerialize(a)})}}if(s.length>0){let t=e.get(DynamicSessionToolMetadataKey)??[],n=new Set(s.map(e=>e.resolverSlug)),r=t.filter(e=>!n.has(e.resolverSlug));e.set(DynamicSessionToolMetadataKey,[...r,...s])}return o}async function dispatchDynamicToolEvent(e){let{ctx:t,resolvers:n,event:r,messages:o}=e;if(t.get(DynamicToolsKey)===void 0){let e=t.get(DynamicSessionToolMetadataKey);if(e!==void 0&&e.length>0){let r=replayDynamicSessionTools(e,n);r.length>0&&t.setVirtualContext(DynamicToolsKey,[...r])}}if(!ALLOWED_DYNAMIC_TOOL_EVENTS.has(r.type))return;let s=n.filter(e=>e.eventNames.includes(r.type));if(s.length===0)return;let c=await resolveToolsFromEvent(t,s,r,o);if(c.length===0)return;let u=new Set(s.map(e=>e.slug)),d=(t.get(DynamicToolsKey)??[]).filter(e=>!matchesAnySlug(e.name,u));t.setVirtualContext(DynamicToolsKey,[...d,...c])}export{dispatchDynamicToolEvent,replayDynamicSessionTools};
@@ -5,8 +5,7 @@ import type { RuntimeHookRegistry } from "#runtime/hooks/registry.js";
5
5
  import type { ContextContainer } from "./container.js";
6
6
  /**
7
7
  * Outcome of {@link dispatchHookLifecycle}. `proceed` carries the
8
- * input augmented with merged `modelContext` and any hook-contributed
9
- * skill announcements on the session. `turn-failed` means a
8
+ * input augmented with merged `modelContext`. `turn-failed` means a
10
9
  * `lifecycle.turn` hook threw; the recoverable `turn.failed` cascade
11
10
  * has already been emitted.
12
11
  */
@@ -36,10 +35,9 @@ export interface DispatchHookLifecycleInput {
36
35
  * runs so a thrown hook does not retry. A throw re-propagates and
37
36
  * the runtime escalates to terminal `session.failed`.
38
37
  * - `lifecycle.turn` runs once per fresh delivery. Each hook may
39
- * return `{ modelContext, skills }`; model-context contributions
40
- * are concatenated in registry order, skills are materialized into
41
- * the sandbox. A thrown hook emits the recoverable `turn.failed`
42
- * cascade and returns `kind: "turn-failed"`.
38
+ * return `{ modelContext }`; model-context contributions are
39
+ * concatenated in registry order. A thrown hook emits the recoverable
40
+ * `turn.failed` cascade and returns `kind: "turn-failed"`.
43
41
  */
44
42
  export declare function dispatchHookLifecycle(input: DispatchHookLifecycleInput): Promise<HookLifecycleOutcome>;
45
43
  /**
@@ -1 +1 @@
1
- import{ContinuationTokenKey,DynamicSessionToolMetadataKey,DynamicSessionToolsKey,SandboxKey,SessionPreparedKey}from"./keys.js";import{createLogger}from"#internal/logging.js";import{toErrorMessage}from"#shared/errors.js";import{normalizeSkillPackage,writeSkillPackageToSandbox}from"#shared/skill-package.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{getAdapterKind}from"#channel/adapter.js";import{emitRecoverableFailedTurn,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{formatAvailableSkillsSection}from"#execution/skills/instructions.js";import{replayDynamicSessionTools,resolveAndStoreDynamicSessionTools}from"#context/dynamic-tool-lifecycle.js";const log=createLogger(`hooks.lifecycle`);async function dispatchHookLifecycle(e){let{ctx:r,registry:a,emit:s}=e,c=getHarnessEmissionState(e.session.state),l=buildHookContext(r),u=[],d=e.session;if(a.session.length>0&&r.get(SessionPreparedKey)!==!0){r.set(SessionPreparedKey,!0);let e=[];for(let t of a.session){let n=await t.handler(l);n?.modelContext!==void 0&&n.modelContext.length>0&&u.push(...n.modelContext),e.push(...normalizeLifecycleSkillResults(r,n))}d=await materializeLifecycleSkills(r,d,e)}let f=r.require(BundleKey).resolvedAgent.dynamicToolResolvers??[];if(f.some(e=>e.eventNames.includes(`session.started`))){let e=r.get(DynamicSessionToolMetadataKey);if(e===void 0){let{tools:e,metadata:i}=await resolveAndStoreDynamicSessionTools(r,f);i.length>0&&r.set(DynamicSessionToolMetadataKey,i),e.length>0&&r.setVirtualContext(DynamicSessionToolsKey,e)}else if(e.length>0){let t=replayDynamicSessionTools(e,f);r.setVirtualContext(DynamicSessionToolsKey,[...t])}}let p=!1,m=c;try{let e=[];for(let t of a.turn){let n=await t.handler(l);n?.modelContext!==void 0&&n.modelContext.length>0&&u.push(...n.modelContext),e.push(...normalizeLifecycleSkillResults(r,n))}d=await materializeLifecycleSkills(r,d,e)}catch(t){let n=toErrorMessage(t);try{p||=(m=await emitTurnPreamble(s,{message:e.input.message},c,e.runtimeIdentity),!0);let t=await emitRecoverableFailedTurn(s,m,{code:`HOOK_TURN_FAILED`,message:n});return{kind:`turn-failed`,message:n,nextSession:setHarnessEmissionState(d,t)}}catch(e){throw log.error(`Event hook threw while emitting the turn.failed cascade for a lifecycle.turn failure — escalating to session.failed.`,{error:toErrorMessage(e)}),e}}if(f.some(e=>e.eventNames.includes(`turn.started`))){let{tools:e}=await resolveAndStoreDynamicSessionTools(r,f,`turn.started`),t=new Set(f.filter(e=>e.eventNames.includes(`turn.started`)).map(e=>e.slug)),i=(r.get(DynamicSessionToolsKey)??[]).filter(e=>{for(let n of t)if(e.name===n||e.name.startsWith(`${n}__`))return!1;return!0});r.setVirtualContext(DynamicSessionToolsKey,[...i,...e])}let h=e.input.modelContext??[],g=h.length===0?u:[...h,...u];return{kind:`proceed`,input:g.length>0?{...e.input,modelContext:g}:e.input,nextSession:d}}function normalizeLifecycleSkillResults(e,t){if(t?.skills===void 0||t.skills.length===0)return[];let n=new Set(e.require(BundleKey).resolvedAgent.skills.map(e=>e.name)),r=new Map;for(let e of t.skills){let t=normalizeSkillPackage(e);if(n.has(t.name))throw Error(`Hook-contributed skill "${t.name}" conflicts with an authored skill.`);r.set(t.name,t)}return[...r.values()]}async function materializeLifecycleSkills(e,t,n){if(n.length===0)return t;let i=new Map(n.map(e=>[e.name,e])),a=await e.require(SandboxKey).get();if(a===null)throw Error(`Dynamic skills require a sandbox for the current agent.`);for(let e of i.values())await writeSkillPackageToSandbox({sandbox:a,skill:e});let o=formatAvailableSkillsSection([...i.values()]);return o===null?t:{...t,history:[...t.history,{role:`system`,content:o}]}}async function dispatchStreamEventHooks(e){let t=e.registry.streamEventsByType.get(e.event.type)??[],n=e.registry.streamEventsWildcard;if(t.length===0&&n.length===0)return;let r=buildHookContext(e.ctx);for(let n of t)await n.handler(e.event,r);for(let t of n)await t.handler(e.event,r)}function buildHookContext(t){let n=t.require(BundleKey),r=t.get(ChannelKey),i=t.get(ContinuationTokenKey),a=r===void 0?void 0:getAdapterKind(r);return{...buildCallbackContext(),agent:{name:n.resolvedAgent.config.name??`agent`,nodeId:n.nodeId},channel:{kind:a,continuationToken:i}}}async function runHookLifecycleStep(e,t){let n=await dispatchHookLifecycle(e);return n.kind===`turn-failed`?{next:e.mode===`conversation`?null:{done:!0,output:n.message},session:n.nextSession}:t(n.nextSession,n.input)}export{dispatchHookLifecycle,dispatchStreamEventHooks,runHookLifecycleStep};
1
+ import{ContinuationTokenKey,SessionPreparedKey}from"./keys.js";import{createLogger}from"#internal/logging.js";import{getAdapterKind}from"#channel/adapter.js";import{toErrorMessage}from"#shared/errors.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{emitRecoverableFailedTurn,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";const log=createLogger(`hooks.lifecycle`);async function dispatchHookLifecycle(e){let{ctx:n,registry:r,emit:a}=e,o=getHarnessEmissionState(e.session.state),s=buildHookContext(n),u=[],d=e.session;if(r.session.length>0&&n.get(SessionPreparedKey)!==!0){n.set(SessionPreparedKey,!0);for(let e of r.session){let t=await e.handler(s);t?.modelContext!==void 0&&t.modelContext.length>0&&u.push(...t.modelContext)}}let f=!1,p=o;try{for(let e of r.turn){let t=await e.handler(s);t?.modelContext!==void 0&&t.modelContext.length>0&&u.push(...t.modelContext)}}catch(t){let n=toErrorMessage(t);try{return f||=(p=await emitTurnPreamble(a,{message:e.input.message},o,e.runtimeIdentity),!0),{kind:`turn-failed`,message:n,nextSession:setHarnessEmissionState(d,await emitRecoverableFailedTurn(a,p,{code:`HOOK_TURN_FAILED`,message:n}))}}catch(e){throw log.error(`Event hook threw while emitting the turn.failed cascade for a lifecycle.turn failure — escalating to session.failed.`,{error:toErrorMessage(e)}),e}}let m=e.input.modelContext??[],h=m.length===0?u:[...m,...u];return{kind:`proceed`,input:h.length>0?{...e.input,modelContext:h}:e.input,nextSession:d}}async function dispatchStreamEventHooks(e){let t=e.registry.streamEventsByType.get(e.event.type)??[],n=e.registry.streamEventsWildcard;if(t.length===0&&n.length===0)return;let r=buildHookContext(e.ctx);for(let n of t)await n.handler(e.event,r);for(let t of n)await t.handler(e.event,r)}function buildHookContext(t){let n=t.require(BundleKey),i=t.get(ChannelKey),c=t.get(ContinuationTokenKey),l=i===void 0?void 0:getAdapterKind(i);return{...buildCallbackContext(),agent:{name:n.resolvedAgent.config.name??`agent`,nodeId:n.nodeId},channel:{kind:l,continuationToken:c}}}async function runHookLifecycleStep(e,t){let n=await dispatchHookLifecycle(e);return n.kind===`turn-failed`?{next:e.mode===`conversation`?null:{done:!0,output:n.message},session:n.nextSession}:t(n.nextSession,n.input)}export{dispatchHookLifecycle,dispatchStreamEventHooks,runHookLifecycleStep};
@@ -3,7 +3,7 @@
3
3
  * tier. Codec-carrying keys (`ChannelKey`, `BundleKey`) live in
4
4
  * `#runtime/sessions/runtime-context-keys.ts`.
5
5
  */
6
- import type { SessionAuthContext, SessionCallback, SessionCapabilities, SessionParent, SessionTurn } from "#channel/types.js";
6
+ import type { ChannelInstrumentationProjection, SessionAuthContext, SessionCallback, SessionCapabilities, SessionParent, SessionTurn } from "#channel/types.js";
7
7
  import { ContextKey } from "#context/key.js";
8
8
  import type { SandboxAccess } from "#sandbox/state.js";
9
9
  import type { RunMode } from "#shared/run-mode.js";
@@ -32,6 +32,7 @@ export declare const AuthKey: ContextKey<SessionAuthContext | null>;
32
32
  export declare const InitiatorAuthKey: ContextKey<SessionAuthContext | null>;
33
33
  export declare const SessionIdKey: ContextKey<string>;
34
34
  export declare const ContinuationTokenKey: ContextKey<string>;
35
+ export declare const ChannelInstrumentationKey: ContextKey<ChannelInstrumentationProjection>;
35
36
  export declare const ModeKey: ContextKey<RunMode>;
36
37
  export declare const ParentSessionKey: ContextKey<SessionParent>;
37
38
  /**
@@ -56,12 +57,11 @@ export declare const SessionPreparedKey: ContextKey<boolean>;
56
57
  export declare const SessionKey: ContextKey<Session>;
57
58
  export declare const SandboxKey: ContextKey<SandboxAccess>;
58
59
  /**
59
- * Virtual (non-serialized) live dynamic tool definitions for the
60
- * current step. Rebuilt per workflow step — either from live resolver
61
- * results (first step) or from durable metadata with lazy execute
62
- * wrappers (subsequent steps).
60
+ * Virtual (non-serialized) live dynamic tool definitions. Updated by
61
+ * {@link dispatchDynamicToolEvent} whenever a subscribed stream event
62
+ * fires. Read by the tool-loop when building the effective toolset.
63
63
  */
64
- export declare const DynamicSessionToolsKey: ContextKey<import("#harness/execute-tool.js").HarnessToolDefinition[]>;
64
+ export declare const DynamicToolsKey: ContextKey<import("#harness/execute-tool.js").HarnessToolDefinition[]>;
65
65
  /**
66
66
  * Durable (serialized) metadata for session-scoped dynamic tools.
67
67
  * Set on the first step when resolvers run. Read on subsequent steps
@@ -88,7 +88,8 @@ export interface DurableDynamicToolMetadata {
88
88
  }
89
89
  export declare const DynamicSessionToolMetadataKey: ContextKey<readonly DurableDynamicToolMetadata[]>;
90
90
  /**
91
- * Durable cache for resolver I/O results. Keyed by resolver slug +
92
- * await index. Populated on first resolver run, read on replay.
91
+ * Durable map from resolver slug to the qualified skill names it last
92
+ * produced. Used to diff on re-resolution and clean up removed skills
93
+ * from the sandbox.
93
94
  */
94
- export declare const DynamicToolResolverCacheKey: ContextKey<Record<string, unknown>>;
95
+ export declare const DynamicSkillManifestKey: ContextKey<Record<string, readonly string[]>>;
@@ -1 +1 @@
1
- import{ContextKey}from"#context/key.js";const AuthKey=new ContextKey(`ash.auth`),InitiatorAuthKey=new ContextKey(`ash.initiatorAuth`),SessionIdKey=new ContextKey(`ash.sessionId`),ContinuationTokenKey=new ContextKey(`ash.continuationToken`),ModeKey=new ContextKey(`ash.mode`),ParentSessionKey=new ContextKey(`ash.parentSession`),CapabilitiesKey=new ContextKey(`ash.capabilities`),SessionCallbackKey=new ContextKey(`ash.sessionCallback`),SessionPreparedKey=new ContextKey(`ash.sessionPrepared`),SessionKey=new ContextKey(`ash.session`),SandboxKey=new ContextKey(`ash.sandbox`),DynamicSessionToolsKey=new ContextKey(`ash.dynamicSessionTools`),DynamicSessionToolMetadataKey=new ContextKey(`ash.dynamicSessionToolMetadata`),DynamicToolResolverCacheKey=new ContextKey(`ash.dynamicToolResolverCache`);export{AuthKey,CapabilitiesKey,ContinuationTokenKey,DynamicSessionToolMetadataKey,DynamicSessionToolsKey,DynamicToolResolverCacheKey,InitiatorAuthKey,ModeKey,ParentSessionKey,SandboxKey,SessionCallbackKey,SessionIdKey,SessionKey,SessionPreparedKey};
1
+ import{ContextKey}from"#context/key.js";const AuthKey=new ContextKey(`ash.auth`),InitiatorAuthKey=new ContextKey(`ash.initiatorAuth`),SessionIdKey=new ContextKey(`ash.sessionId`),ContinuationTokenKey=new ContextKey(`ash.continuationToken`),ChannelInstrumentationKey=new ContextKey(`ash.channelInstrumentation`),ModeKey=new ContextKey(`ash.mode`),ParentSessionKey=new ContextKey(`ash.parentSession`),CapabilitiesKey=new ContextKey(`ash.capabilities`),SessionCallbackKey=new ContextKey(`ash.sessionCallback`),SessionPreparedKey=new ContextKey(`ash.sessionPrepared`),SessionKey=new ContextKey(`ash.session`),SandboxKey=new ContextKey(`ash.sandbox`),DynamicToolsKey=new ContextKey(`ash.dynamicTools`),DynamicSessionToolMetadataKey=new ContextKey(`ash.dynamicSessionToolMetadata`),DynamicSkillManifestKey=new ContextKey(`ash.dynamicSkillManifest`);export{AuthKey,CapabilitiesKey,ChannelInstrumentationKey,ContinuationTokenKey,DynamicSessionToolMetadataKey,DynamicSkillManifestKey,DynamicToolsKey,InitiatorAuthKey,ModeKey,ParentSessionKey,SandboxKey,SessionCallbackKey,SessionIdKey,SessionKey,SessionPreparedKey};
@@ -1,3 +1,12 @@
1
+ import { ContextKey } from "#context/key.js";
1
2
  import type { ConnectionRegistry } from "#runtime/connections/types.js";
2
3
  import type { FrameworkContextProvider } from "#context/provider.js";
4
+ /**
5
+ * Context key for the per-session connection registry.
6
+ *
7
+ * Created as a derived key (no codec) because the registry holds live
8
+ * client instances that cannot be serialized across step boundaries.
9
+ * The `connectionProvider` reconstructs it each step.
10
+ */
11
+ export declare const ConnectionRegistryKey: ContextKey<ConnectionRegistry>;
3
12
  export declare const connectionProvider: FrameworkContextProvider<ConnectionRegistry>;
@@ -1 +1 @@
1
- import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{ConnectionRegistryImpl}from"#runtime/connections/registry.js";import{ConnectionRegistryKey}from"#runtime/framework-tools/connection-search.js";import{getActiveRuntimeNode}from"#context/node.js";const connectionProvider={key:ConnectionRegistryKey,create(e,t){if(e.get(BundleKey)===void 0)return;let n=getActiveRuntimeNode(e).agent?.connections;if(!(!n||n.length===0))return{value:new ConnectionRegistryImpl(n)}}};export{connectionProvider};
1
+ import{ContextKey}from"#context/key.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{ConnectionRegistryImpl}from"#runtime/connections/registry.js";import{getActiveRuntimeNode}from"#context/node.js";const ConnectionRegistryKey=new ContextKey(`ash.connectionRegistry`),connectionProvider={key:ConnectionRegistryKey,create(e,t){if(e.get(BundleKey)===void 0)return;let n=getActiveRuntimeNode(e).agent?.connections;if(!(!n||n.length===0))return{value:new ConnectionRegistryImpl(n)}}};export{ConnectionRegistryKey,connectionProvider};
@@ -1 +1 @@
1
- import{SandboxKey,SessionIdKey}from"#context/keys.js";import{contextStorage}from"#context/container.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{getAdapterKind}from"#channel/adapter.js";import{getActiveRuntimeNode}from"#context/node.js";import{ensureSandboxAccess}from"#execution/sandbox/ensure.js";const sandboxProvider={key:SandboxKey,async create(e,r){let i=e.get(BundleKey);if(i===void 0)return;let a=getActiveRuntimeNode(e),o=a.sandboxRegistry,s=e.require(SessionIdKey);return{value:await ensureSandboxAccess({compiledArtifactsSource:i.compiledArtifactsSource,nodeId:a.nodeId,registry:o,runOnSession:async t=>await contextStorage.run(e,t),sessionId:s,state:r.sandboxState??null,tags:{agent:resolveTagAgentName({bundle:i,node:a}),channel:resolveTagChannelKind(e.get(ChannelKey)),sessionId:s}})}},async commit(e,t){let n=await e.captureState();return{...t,sandboxState:n}}};function resolveTagAgentName(e){let t=e.node,n=e.bundle;return t.agent?.config?.name??n.resolvedAgent?.config?.name??t.nodeId??`unknown`}function resolveTagChannelKind(e){return e===void 0?`unknown`:getAdapterKind(e)}export{sandboxProvider};
1
+ import{getAdapterKind}from"#channel/adapter.js";import{SandboxKey,SessionIdKey}from"#context/keys.js";import{contextStorage}from"#context/container.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{getActiveRuntimeNode}from"#context/node.js";import{ensureSandboxAccess}from"#execution/sandbox/ensure.js";const sandboxProvider={key:SandboxKey,async create(e,t){let r=e.get(BundleKey);if(r===void 0)return;let i=getActiveRuntimeNode(e),a=i.sandboxRegistry,o=e.require(SessionIdKey);return{value:await ensureSandboxAccess({compiledArtifactsSource:r.compiledArtifactsSource,nodeId:i.nodeId,registry:a,runOnSession:async t=>await contextStorage.run(e,t),sessionId:o,state:t.sandboxState??null,tags:{agent:resolveTagAgentName({bundle:r,node:i}),channel:resolveTagChannelKind(e.get(ChannelKey)),sessionId:o}})}},async commit(e,t){let n=await e.captureState();return{...t,sandboxState:n}}};function resolveTagAgentName(e){let t=e.node,n=e.bundle;return t.agent?.config?.name??n.resolvedAgent?.config?.name??t.nodeId??`unknown`}function resolveTagChannelKind(t){return t===void 0?`unknown`:getAdapterKind(t)}export{sandboxProvider};