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
@@ -0,0 +1,73 @@
1
+ import "#internal/workflow/builtins.js";
2
+ /**
3
+ * Maximum byte size for an attribute value on a workflow run.
4
+ *
5
+ * Local mirror of `ATTRIBUTE_VALUE_MAX_BYTES` from `@workflow/world`
6
+ * (source of truth: `packages/world/src/attributes.ts` in the workflow
7
+ * repo). The value is duplicated rather than imported because
8
+ * `@workflow/core` — the only workflow surface bundled into the
9
+ * workflow body — does not re-export it, and pulling `@workflow/world`
10
+ * into the body bundle would drag in the full zod attribute validator
11
+ * (the same reason `workflow-core-shim.ts` skips runtime validation in
12
+ * its `experimental_setAttributes`).
13
+ *
14
+ * Strings emitted through {@link setAshAttributes} are truncated to this
15
+ * byte count before they reach the runtime so the validator never
16
+ * rejects a tag for length alone.
17
+ *
18
+ * Drift is conservative-by-construction: if workflow LOWERS the limit,
19
+ * over-long values are rejected and `setAshAttributes` swallows the
20
+ * failure (warn-once-per-process) — dashboards see a missing tag, never
21
+ * a broken agent; if workflow RAISES it, titles are merely shorter than
22
+ * necessary. `emit.drift.test.ts` asserts equality against the real
23
+ * `@workflow/world` export (a devDependency) so CI fails loudly the day
24
+ * the constants diverge.
25
+ */
26
+ export declare const ASH_ATTRIBUTE_VALUE_MAX_BYTES = 256;
27
+ /**
28
+ * Attribute value the caller wants to write. `undefined` values are
29
+ * stripped before the runtime call; numbers are stringified; strings
30
+ * are truncated to {@link ASH_ATTRIBUTE_VALUE_MAX_BYTES}.
31
+ */
32
+ export type AshAttributeValue = string | number | undefined;
33
+ /**
34
+ * Truncates a string so its UTF-8 byte length is at most `maxBytes`
35
+ * without splitting a multi-byte character.
36
+ *
37
+ * The workflow runtime measures attribute values in UTF-8 bytes, not
38
+ * code units, so `value.slice(0, maxBytes)` is not safe — a JS string
39
+ * with two-byte characters (e.g. emoji surrogate pairs) can serialize
40
+ * to twice as many bytes as code units. We re-encode the truncated
41
+ * candidate after each drop and shrink one code unit at a time when
42
+ * the candidate's last character straddles the byte budget.
43
+ */
44
+ export declare function truncateForTag(value: string, maxBytes?: number): string;
45
+ /**
46
+ * Writes a batch of Ash-owned attributes to the active workflow run.
47
+ *
48
+ * Reserved-namespace contract:
49
+ * - All keys must use the `$ash.` prefix (the workflow runtime would
50
+ * otherwise reject them as user-space writes into the reserved `$`
51
+ * namespace).
52
+ * - The call always opts in via `{ allowReservedAttributes: true }`
53
+ * on behalf of the framework — authored code never calls this helper
54
+ * directly.
55
+ *
56
+ * Value normalization:
57
+ * - `undefined` entries are dropped so callers can build attribute
58
+ * maps with optional fields (`$ash.subagent` is only present on
59
+ * subagent roots, for example).
60
+ * - Numbers are stringified (the runtime stores all values as strings).
61
+ * - Strings are truncated to {@link ASH_ATTRIBUTE_VALUE_MAX_BYTES} via
62
+ * {@link truncateForTag} so a long free-form value (e.g. `$ash.title`)
63
+ * can never trip the runtime's per-value byte budget.
64
+ *
65
+ * Failure policy: tag writes are observability metadata, not load-bearing
66
+ * state. A failure inside the runtime (transient network, schema bug,
67
+ * missing world adapter) is logged once per process and then swallowed
68
+ * so the Ash session it tagged is unaffected.
69
+ *
70
+ * Must be called from inside a `"use workflow"` or `"use step"` body —
71
+ * the runtime throws a `FatalError` outside those contexts.
72
+ */
73
+ export declare function setAshAttributes(attrs: Record<string, AshAttributeValue>): Promise<void>;
@@ -0,0 +1 @@
1
+ import"#internal/workflow/builtins.js";const ASH_ATTRIBUTE_VALUE_MAX_BYTES=256;let WARNED_ABOUT_TAG_FAILURE=!1;function truncateForTag(e,t=256){if(t<=0)return``;let n=new TextEncoder;if(n.encode(e).length<=t)return e;let r=e.length;for(;r>0;){let i=e.charCodeAt(r-1);if(i>=55296&&i<=56319){--r;continue}let a=e.slice(0,r);if(n.encode(a).length<=t)return a;--r}return``}async function setAshAttributes(e){let n={};for(let[t,r]of Object.entries(e))r!==void 0&&(n[t]=truncateForTag(typeof r==`number`?String(r):r));if(Object.keys(n).length!==0)try{let{experimental_setAttributes:e}=await import(`#compiled/@workflow/core/index.js`);await e(n,{allowReservedAttributes:!0})}catch(e){WARNED_ABOUT_TAG_FAILURE||(WARNED_ABOUT_TAG_FAILURE=!0,console.warn(`[ash] setAshAttributes failed; suppressing further warnings this process.`,{keys:Object.keys(n),error:e.message}))}}export{ASH_ATTRIBUTE_VALUE_MAX_BYTES,setAshAttributes,truncateForTag};
@@ -1 +1 @@
1
- import{getAdapterKind}from"#channel/adapter.js";import{SUBAGENT_ADAPTER}from"#execution/subagent-adapter.js";import{SCHEDULE_ADAPTER}from"#channel/schedule.js";import{HTTP_ADAPTER}from"#channel/http.js";import{RuntimeRegistryError}from"#internal/runtime-registry.js";const FRAMEWORK_ADAPTERS=[HTTP_ADAPTER,SUBAGENT_ADAPTER,SCHEDULE_ADAPTER],ADAPTER_NON_EVENT_FIELDS=new Set([`kind`,`state`,`deliver`,`createAdapterContext`,`fetchFile`]);function createRuntimeAdapterRegistry(e){let t=new Map,n=new Set;for(let e of FRAMEWORK_ADAPTERS){let r=requireAdapterKind(e);n.add(r),t.set(r,e)}for(let r of e.channels){if(r.adapter===void 0)continue;let e={logicalPath:r.logicalPath,sourceId:r.sourceId},i=r.adapter,a=requireAdapterKind(i,e);if(n.has(a)){if(carriesAdapterBehavior(i))throw new RuntimeRegistryError(`adapter`,`Channel adapter kind "${a}" is reserved by the framework. A route-declared adapter may share a framework kind only as a pass-through with no \`deliver\` hook, event handlers, \`attachments\` resolver, or \`createAdapterContext\` factory. Use a custom \`kind\` to add channel-specific behavior.`,{...e,entryName:a});continue}t.set(a,i)}return{adaptersByKind:t}}function deserializeRuntimeAdapter(e,t){let n=t,r=e.adaptersByKind.get(n.kind);if(r===void 0)throw Error(`Unknown adapter kind: "${n.kind}". Declare the adapter on the route that starts this session so the runtime can rehydrate it.`);return{...r,state:n.state}}function requireAdapterKind(t,n){let r=getAdapterKind(t);if(typeof r!=`string`||r.length===0)throw new RuntimeRegistryError(`adapter`,"Adapters must declare a non-empty `kind` field.",{entryName:`unknown`,logicalPath:n?.logicalPath,sourceId:n?.sourceId});return r}function carriesAdapterBehavior(e){if(e.deliver!==void 0||e.fetchFile!==void 0||e.createAdapterContext!==void 0)return!0;for(let[t,n]of Object.entries(e))if(!ADAPTER_NON_EVENT_FIELDS.has(t)&&typeof n==`function`)return!0;return!1}export{createRuntimeAdapterRegistry,deserializeRuntimeAdapter};
1
+ import{getAdapterKind}from"#channel/adapter.js";import{SUBAGENT_ADAPTER}from"#execution/subagent-adapter.js";import{SCHEDULE_ADAPTER}from"#channel/schedule.js";import{HTTP_ADAPTER}from"#channel/http.js";import{RuntimeRegistryError}from"#internal/runtime-registry.js";const FRAMEWORK_ADAPTERS=[HTTP_ADAPTER,SUBAGENT_ADAPTER,SCHEDULE_ADAPTER],ADAPTER_NON_EVENT_FIELDS=new Set([`kind`,`state`,`deliver`,`createAdapterContext`,`fetchFile`,`instrumentation`]);function createRuntimeAdapterRegistry(e){let t=new Map,n=new Set;for(let e of FRAMEWORK_ADAPTERS){let r=requireAdapterKind(e);n.add(r),t.set(r,e)}for(let r of e.channels){if(r.adapter===void 0)continue;let e={logicalPath:r.logicalPath,sourceId:r.sourceId},i=r.adapter,a=requireAdapterKind(i,e);if(n.has(a)){if(carriesAdapterBehavior(i))throw new RuntimeRegistryError(`adapter`,`Channel adapter kind "${a}" is reserved by the framework. A route-declared adapter may share a framework kind only as a pass-through with no \`deliver\` hook, event handlers, \`attachments\` resolver, or \`createAdapterContext\` factory. Use a custom \`kind\` to add channel-specific behavior.`,{...e,entryName:a});continue}t.set(a,i)}return{adaptersByKind:t}}function deserializeRuntimeAdapter(e,t){let n=t,r=e.adaptersByKind.get(n.kind);if(r===void 0)throw Error(`Unknown adapter kind: "${n.kind}". Declare the adapter on the route that starts this session so the runtime can rehydrate it.`);return{...r,state:n.state}}function requireAdapterKind(t,n){let r=getAdapterKind(t);if(typeof r!=`string`||r.length===0)throw new RuntimeRegistryError(`adapter`,"Adapters must declare a non-empty `kind` field.",{entryName:`unknown`,logicalPath:n?.logicalPath,sourceId:n?.sourceId});return r}function carriesAdapterBehavior(e){if(e.deliver!==void 0||e.fetchFile!==void 0||e.createAdapterContext!==void 0)return!0;for(let[t,n]of Object.entries(e))if(!ADAPTER_NON_EVENT_FIELDS.has(t)&&typeof n==`function`)return!0;return!1}export{createRuntimeAdapterRegistry,deserializeRuntimeAdapter};
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";import{contextStorage}from"#context/container.js";import{principalKey,resolveConnectionPrincipal}from"#runtime/connections/principal.js";import{createMCPClient}from"#compiled/@ai-sdk/mcp/index.js";import{readCachedToken,writeCachedToken}from"#runtime/connections/authorization-tokens.js";var McpConnectionClient=class{#e;#t;#n;#r;#i;constructor(e){this.#i=e}async connect(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#a();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#a(){let e=await resolveHeaders(this.#i),t=this.#i.url;try{return await createMCPClient({transport:{type:`http`,url:t,headers:e}})}catch(n){if(!isMcpHttpFallbackRetryableError(n))throw n;return await createMCPClient({transport:{type:`sse`,url:t,headers:e}})}}async getToolMetadata(){return(await this.#o()).metadata}async getTools(){return(await this.#o()).tools}async executeTool(e,t){let{tools:n}=await this.#o(),r=n[e];if(r?.execute===void 0)throw Error(`Tool "${e}" not found in connection "${this.#i.connectionName}".`);return r.execute(t,{})}async#o(){if(this.#r!==void 0)return this.#r;if(this.#n!==void 0)return this.#n;this.#n=this.#s();try{return this.#r=await this.#n,this.#r}catch(e){throw this.#n=void 0,e}}async#s(){let e=await this.connect(),t=await e.listTools(),n=this.#i.tools,r=n===void 0?t.tools:t.tools.filter(e=>passesToolFilter(e.name,n)),i=e.toolsFromDefinitions({tools:r});return{metadata:r.map(e=>({annotations:e.annotations,description:e.description??``,inputSchema:e.inputSchema??{},name:e.name})),tools:i}}async close(){this.#t!==void 0&&(await this.#t.close(),this.#t=void 0),this.#e=void 0,this.#n=void 0,this.#r=void 0}};function isMcpHttpFallbackRetryableError(e){let t=readHttpStatus(e);return t===400||t===404||t===405}function readHttpStatus(t){for(let n of walkErrorChain(t)){if(!isObject(n))continue;let t=readStatusField(n);if(t!==void 0)return t;let r=n.response;if(isObject(r)){let e=readStatusField(r);if(e!==void 0)return e}if(typeof n.message==`string`){let e=/\bHTTP\s+(\d{3})\b/u.exec(n.message);if(e?.[1]!==void 0)return Number(e[1])}}}function readStatusField(e){if(typeof e.status==`number`)return e.status;if(typeof e.statusCode==`number`)return e.statusCode}function*walkErrorChain(t){let n=t,r=new Set;for(;n!=null&&!r.has(n);){if(r.add(n),yield n,!isObject(n)||!(`cause`in n))return;n=n.cause}}function passesToolFilter(e,t){return t===void 0?!0:`allow`in t?t.allow.includes(e):!t.block.includes(e)}async function resolveHeaders(e){let t={};if(e.authorization!==void 0&&(t.Authorization=`Bearer ${(await resolveToken(e)).token}`),e.headers!==void 0){let n=await resolveHeadersDefinition(e.headers);for(let[r,i]of Object.entries(n)){if(e.authorization!==void 0&&r.toLowerCase()===`authorization`)throw Error(`Connection "${e.connectionName}" headers must not include an "Authorization" key when "authorization" is also provided.`);t[r]=i}}return t}async function resolveToken(e){if(e.authorization===void 0)throw Error(`Connection "${e.connectionName}" does not define authorization.`);let i=contextStorage.getStore(),a=resolveConnectionPrincipal(e.connectionName,e.authorization,i),o={url:e.url};if(i===void 0)return await e.authorization.getToken({principal:a,connection:o});let s=principalKey(a),c=readCachedToken(i,e.connectionName,s);if(c!==void 0)return c;let l=await e.authorization.getToken({principal:a,connection:o});return writeCachedToken(i,e.connectionName,s,l),l}async function resolveHeadersDefinition(e){if(typeof e==`function`)return await e();let t={},n=Object.entries(e);for(let[e,r]of n)t[e]=await resolveHeaderValue(r);return t}async function resolveHeaderValue(e){return typeof e==`function`?await e():await e}export{McpConnectionClient,passesToolFilter,resolveHeaders};
1
+ import{isObject}from"#shared/guards.js";import{contextStorage}from"#context/container.js";import{createMCPClient}from"#compiled/@ai-sdk/mcp/index.js";import{readCachedToken,writeCachedToken}from"#runtime/connections/authorization-tokens.js";import{principalKey,resolveConnectionPrincipal}from"#runtime/connections/principal.js";var McpConnectionClient=class{#e;#t;#n;#r;#i;constructor(e){this.#i=e}async connect(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#a();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#a(){let e=await resolveHeaders(this.#i),t=this.#i.url;try{return await createMCPClient({transport:{type:`http`,url:t,headers:e}})}catch(r){if(!isMcpHttpFallbackRetryableError(r))throw r;return await createMCPClient({transport:{type:`sse`,url:t,headers:e}})}}async getToolMetadata(){return(await this.#o()).metadata}async getTools(){return(await this.#o()).tools}async executeTool(e,t){let{tools:n}=await this.#o(),r=n[e];if(r?.execute===void 0)throw Error(`Tool "${e}" not found in connection "${this.#i.connectionName}".`);return r.execute(t,{})}async#o(){if(this.#r!==void 0)return this.#r;if(this.#n!==void 0)return this.#n;this.#n=this.#s();try{return this.#r=await this.#n,this.#r}catch(e){throw this.#n=void 0,e}}async#s(){let e=await this.connect(),t=await e.listTools(),n=this.#i.tools,r=n===void 0?t.tools:t.tools.filter(e=>passesToolFilter(e.name,n)),i=e.toolsFromDefinitions({tools:r});return{metadata:r.map(e=>({annotations:e.annotations,description:e.description??``,inputSchema:e.inputSchema??{},name:e.name})),tools:i}}async close(){this.#t!==void 0&&(await this.#t.close(),this.#t=void 0),this.#e=void 0,this.#n=void 0,this.#r=void 0}};function isMcpHttpFallbackRetryableError(e){let t=readHttpStatus(e);return t===400||t===404||t===405}function readHttpStatus(t){for(let n of walkErrorChain(t)){if(!isObject(n))continue;let t=readStatusField(n);if(t!==void 0)return t;let r=n.response;if(isObject(r)){let e=readStatusField(r);if(e!==void 0)return e}if(typeof n.message==`string`){let e=/\bHTTP\s+(\d{3})\b/u.exec(n.message);if(e?.[1]!==void 0)return Number(e[1])}}}function readStatusField(e){if(typeof e.status==`number`)return e.status;if(typeof e.statusCode==`number`)return e.statusCode}function*walkErrorChain(t){let n=t,r=new Set;for(;n!=null&&!r.has(n);){if(r.add(n),yield n,!isObject(n)||!(`cause`in n))return;n=n.cause}}function passesToolFilter(e,t){return t===void 0?!0:`allow`in t?t.allow.includes(e):!t.block.includes(e)}async function resolveHeaders(e){let t={};if(e.authorization!==void 0&&(t.Authorization=`Bearer ${(await resolveToken(e)).token}`),e.headers!==void 0){let n=await resolveHeadersDefinition(e.headers);for(let[r,i]of Object.entries(n)){if(e.authorization!==void 0&&r.toLowerCase()===`authorization`)throw Error(`Connection "${e.connectionName}" headers must not include an "Authorization" key when "authorization" is also provided.`);t[r]=i}}return t}async function resolveToken(e){if(e.authorization===void 0)throw Error(`Connection "${e.connectionName}" does not define authorization.`);let n=contextStorage.getStore(),a=resolveConnectionPrincipal(e.connectionName,e.authorization,n),o={url:e.url};if(n===void 0)return await e.authorization.getToken({principal:a,connection:o});let s=principalKey(a),c=readCachedToken(n,e.connectionName,s);if(c!==void 0)return c;let l=await e.authorization.getToken({principal:a,connection:o});return writeCachedToken(n,e.connectionName,s,l),l}async function resolveHeadersDefinition(e){if(typeof e==`function`)return await e();let t={},n=Object.entries(e);for(let[e,r]of n)t[e]=await resolveHeaderValue(r);return t}async function resolveHeaderValue(e){return typeof e==`function`?await e():await e}export{McpConnectionClient,passesToolFilter,resolveHeaders};
@@ -1,9 +1,11 @@
1
1
  import type { CodeModeInterrupt, CodeModeInterruptExecutionContext, CodeModeInterruptPayload } from "#shared/code-mode.js";
2
+ import type { AuthorizationChallenge } from "#harness/authorization.js";
2
3
  import type { JsonValue } from "#public/types/json.js";
3
4
  export declare const CODE_MODE_CONNECTION_AUTH_INTERRUPT_KIND = "ash.connection-auth";
4
5
  export interface CodeModeConnectionAuthPayload extends CodeModeInterruptPayload {
5
6
  readonly kind: typeof CODE_MODE_CONNECTION_AUTH_INTERRUPT_KIND;
6
7
  readonly args: JsonValue;
8
+ readonly challenges?: readonly AuthorizationChallenge[];
7
9
  readonly connectionName: string;
8
10
  readonly toolName: string;
9
11
  }
@@ -0,0 +1,34 @@
1
+ import type { ResolvedDynamicToolResolver } from "#runtime/types.js";
2
+ import type { DynamicToolEvents } from "#shared/dynamic-tool-definition.js";
3
+ import type { ModelMessage } from "ai";
4
+ interface ConnectionSearchResultItem {
5
+ readonly connection: string;
6
+ readonly description: string;
7
+ readonly error?: string;
8
+ readonly inputSchema?: Record<string, unknown>;
9
+ readonly needsAuthorization?: boolean;
10
+ readonly tool?: string;
11
+ readonly qualifiedName?: string;
12
+ }
13
+ /**
14
+ * Extracts connection search results from conversation history.
15
+ * Scans tool-result messages for `connection_search` results and
16
+ * returns deduplicated tool metadata (latest result wins per qualifiedName).
17
+ */
18
+ export declare function extractDiscoveredTools(messages: readonly ModelMessage[]): ConnectionSearchResultItem[];
19
+ /**
20
+ * Creates the connection search dynamic tool resolver events.
21
+ *
22
+ * The resolver subscribes to `step.started` so it re-derives the tool
23
+ * set from conversation history on every step. After compaction, old
24
+ * `connection_search` results disappear from messages and discovered
25
+ * tools naturally drop from the toolset — no `onCompact` hook needed.
26
+ */
27
+ export declare function createConnectionSearchEvents(): DynamicToolEvents;
28
+ /**
29
+ * Creates a `ResolvedDynamicToolResolver` for the framework connection
30
+ * search tool. Used by graph resolution to register alongside authored
31
+ * dynamic tool resolvers.
32
+ */
33
+ export declare function createConnectionSearchResolver(): ResolvedDynamicToolResolver;
34
+ export {};
@@ -0,0 +1 @@
1
+ import{createLogger}from"#internal/logging.js";import{loadContext}from"#context/container.js";import{ContextKey}from"#context/key.js";import{ConnectionRegistryKey}from"#context/providers/connection.js";import{getAuthorizationResult,getHookUrl,requestAuthorization}from"#harness/authorization.js";import{supportsInteractiveAuthorization}from"#runtime/connections/types.js";import{isConnectionAuthorizationFailedError,isConnectionAuthorizationRequiredError}from"#public/connections/errors.js";import{writeCachedToken}from"#runtime/connections/authorization-tokens.js";import{principalKey,resolveConnectionPrincipal}from"#runtime/connections/principal.js";const logger=createLogger(`framework.connection-search-dynamic`),ConnectionSearchResultsKey=new ContextKey(`ash.connectionSearchResults`);function qualifiedConnectionToolName(e,t){return`${e}__${t}`}function tokenize(e){return e.toLowerCase().split(/[\s_\-./]+/).filter(e=>e.length>1)}function scoreMatch(e,t){let n=tokenize(t.name),r=tokenize(t.description),i=0;for(let t of e){for(let e of n)(e.includes(t)||t.includes(e))&&(i+=3);for(let e of r)(e.includes(t)||t.includes(e))&&(i+=1)}return i}function resolveInteractiveAuth(e,t){let n=e.getConnections().find(e=>e.connectionName===t);if(n?.authorization&&supportsInteractiveAuthorization(n.authorization))return n.authorization}async function completePendingAuthorizations(e){let n=loadContext();for(let t of e.getConnections()){let r=getAuthorizationResult(t.connectionName);if(!r)continue;let a=resolveInteractiveAuth(e,t.connectionName);if(!a)continue;let o=resolveConnectionPrincipal(t.connectionName,a),s=await a.completeAuthorization({callbackUrl:r.hookUrl,connection:{url:t.url??``},principal:o,request:r.callback,state:r.state});writeCachedToken(n,t.connectionName,principalKey(o),s)}}async function executeConnectionSearch(e){let n=loadContext(),i=n.get(ConnectionRegistryKey);if(i===void 0)return[];await completePendingAuthorizations(i);let s=e.limit??10,l=tokenize(e.keywords),u=[],p=[],m=e.connection!==void 0&&e.connection!==``?i.getConnections().filter(t=>t.connectionName===e.connection):i.getConnections(),h=[];for(let e of m){let t;try{t=await i.getClient(e.connectionName).getToolMetadata()}catch(t){if(isConnectionAuthorizationRequiredError(t)){let t=resolveInteractiveAuth(i,e.connectionName);if(t){let n=getHookUrl(e.connectionName);if(n){let r=resolveConnectionPrincipal(e.connectionName,t);try{let{challenge:i,state:a}=await t.startAuthorization({callbackUrl:n,connection:{url:e.url??``},principal:r});h.push({name:e.connectionName,challenge:i,hookUrl:n,state:a})}catch(t){logger.warn(`startAuthorization failed`,{connection:e.connectionName,error:t instanceof Error?t:Error(String(t))})}}}p.push({connection:e.connectionName,description:e.description,needsAuthorization:!0});continue}if(isConnectionAuthorizationFailedError(t)){logger.warn(`connection authorization failed`,{connection:e.connectionName,reason:t.reason,retryable:t.retryable,error:t}),p.push({connection:e.connectionName,description:e.description,error:`Authorization failed for ${e.connectionName}: ${t.message}`});continue}let n=t instanceof Error?t.message:`unknown error`;logger.warn(`failed to load connection tools`,{connection:e.connectionName,error:t instanceof Error?t:Error(n)}),p.push({connection:e.connectionName,description:e.description,error:`Failed to load tools for "${e.connectionName}": ${n}`});continue}for(let n of t){let t=scoreMatch(l,n);t>0&&u.push({item:{connection:e.connectionName,description:n.description,inputSchema:n.inputSchema,qualifiedName:`connection__${qualifiedConnectionToolName(e.connectionName,n.name)}`,tool:n.name},score:t})}}if(h.length>0)return requestAuthorization(h);u.sort((e,t)=>t.score-e.score);let g=u.slice(0,s).map(e=>e.item);if(g.length>0){let e=[...g,...p],t=n.get(ConnectionSearchResultsKey)??[],r=new Map(t.map(e=>[e.qualifiedName,e]));for(let e of g)e.qualifiedName&&r.set(e.qualifiedName,e);return n.set(ConnectionSearchResultsKey,[...r.values()]),e}return m.map(e=>p.find(t=>t.connection===e.connectionName)||{connection:e.connectionName,description:e.description})}function extractDiscoveredTools(e){let t=new Map;for(let n of e){if(n.role!==`tool`)continue;let e=n.content;for(let n of e){if(n.type!==`tool-result`||n.toolName!==`connection__search`)continue;let e=n.output;if(e==null)continue;let r=typeof e==`object`&&`type`in e&&`value`in e?e.value:e;if(Array.isArray(r))for(let e of r)e.tool&&e.qualifiedName&&t.set(e.qualifiedName,e)}}return[...t.values()]}function createConnectionSearchEvents(){return{"step.started":async(e,n)=>{let c=loadContext().get(ConnectionRegistryKey);if(!c||c.getConnections().length===0)return null;let d=c.getConnections().map(e=>e.connectionName),p=extractDiscoveredTools(n.messages),m=loadContext().get(ConnectionSearchResultsKey)??[],h=new Map;for(let e of m)e.qualifiedName&&h.set(e.qualifiedName,e);for(let e of p)e.qualifiedName&&h.set(e.qualifiedName,e);let g=[...h.values()],_={};_.search={description:`Search for tools across your connections. Discovered tools become directly callable by their qualified name (e.g. \`connection__linear__list_issues\`) in your next response. Available connections: ${d.join(`, `)}.`,inputSchema:{type:`object`,additionalProperties:!1,properties:{keywords:{description:`Search keywords and expanded aliases. Distill intent into keywords; avoid stop words like 'a', 'the', 'in'.`,type:`string`},connection:{description:`Optional: limit search to a specific connection name.`,type:`string`},limit:{description:`Max results to return. Default 10.`,type:`number`}},required:[`keywords`]},async execute(e){return executeConnectionSearch(e)}};for(let e of g){let n=e.connection,c=e.tool;_[qualifiedConnectionToolName(n,c)]={description:e.description,inputSchema:e.inputSchema??{type:`object`},async execute(e){let d=loadContext().get(ConnectionRegistryKey),f=d.getConnections().find(e=>e.connectionName===n),p=f?.authorization&&supportsInteractiveAuthorization(f.authorization)?f.authorization:void 0;if(p){let e=getAuthorizationResult(n);if(e){let r=loadContext(),i=resolveConnectionPrincipal(n,p),a=await p.completeAuthorization({callbackUrl:e.hookUrl,connection:{url:f?.url??``},principal:i,request:e.callback,state:e.state});writeCachedToken(r,n,principalKey(i),a)}}try{let t=(await d.getClient(n).getTools())[c];if(!t?.execute)throw Error(`Connection tool "${qualifiedConnectionToolName(n,c)}" has no execute function.`);return t.execute(e,{})}catch(e){if(!isConnectionAuthorizationRequiredError(e)||!p)throw e;let t=getHookUrl(n);if(!t)throw e;let r=resolveConnectionPrincipal(n,p),{challenge:i,state:s}=await p.startAuthorization({callbackUrl:t,connection:{url:f?.url??``},principal:r});return requestAuthorization([{name:n,challenge:i,hookUrl:t,state:s}])}}}}return _}}}function createConnectionSearchResolver(){let e=createConnectionSearchEvents();return{slug:`connection`,eventNames:Object.keys(e),events:e,sourceId:`ash:connection-search-dynamic`,sourceKind:`module`,logicalPath:`ash:framework/connection-search-dynamic`}}export{createConnectionSearchEvents,createConnectionSearchResolver,extractDiscoveredTools};
@@ -1,17 +1,19 @@
1
- export { ConnectionRegistryKey } from "#runtime/framework-tools/connection-search.js";
1
+ export { ConnectionRegistryKey } from "#context/providers/connection.js";
2
2
  export type { ReadFileStamp, ReadFileState } from "#runtime/framework-tools/file-state.js";
3
3
  export { ReadFileStateKey } from "#runtime/framework-tools/file-state.js";
4
4
  export type { TodoItem, TodoState } from "#runtime/framework-tools/todo.js";
5
5
  export { TodoStateKey } from "#runtime/framework-tools/todo.js";
6
6
  import type { ResolvedToolDefinition } from "#runtime/types.js";
7
- interface FrameworkToolConfig {
8
- readonly hasConnections: boolean;
9
- }
10
7
  /**
11
8
  * Returns framework-owned tool definitions registered in the tool registry
12
9
  * alongside authored tools during graph resolution.
10
+ *
11
+ * `connection_search` is no longer in this list — it is registered as a
12
+ * framework dynamic tool resolver in the graph resolution path.
13
13
  */
14
- export declare function getFrameworkToolDefinitions(config: FrameworkToolConfig): readonly ResolvedToolDefinition[];
14
+ export declare function getFrameworkToolDefinitions(_config?: {
15
+ readonly hasConnections?: boolean;
16
+ }): readonly ResolvedToolDefinition[];
15
17
  /**
16
18
  * Returns the names of every framework-provided tool the framework knows
17
19
  * about, regardless of whether the current agent gates any of them on
@@ -1 +1 @@
1
- import{CONNECTION_SEARCH_TOOL_DEFINITION,ConnectionRegistryKey}from"#runtime/framework-tools/connection-search.js";import{ReadFileStateKey}from"#runtime/framework-tools/file-state.js";import{ASK_QUESTION_TOOL_DEFINITION}from"#runtime/framework-tools/ask-question.js";import{WEB_SEARCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-search.js";import{BASH_TOOL_DEFINITION}from"#runtime/framework-tools/bash.js";import{GLOB_TOOL_DEFINITION}from"#runtime/framework-tools/glob.js";import{GREP_TOOL_DEFINITION}from"#runtime/framework-tools/grep.js";import{READ_FILE_TOOL_DEFINITION}from"#runtime/framework-tools/read-file.js";import{SKILL_TOOL_DEFINITION}from"#runtime/framework-tools/skill.js";import{TODO_TOOL_DEFINITION,TodoStateKey}from"#runtime/framework-tools/todo.js";import{WEB_FETCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-fetch.js";import{WRITE_FILE_TOOL_DEFINITION}from"#runtime/framework-tools/write-file.js";const ALL_FRAMEWORK_TOOLS=[ASK_QUESTION_TOOL_DEFINITION,BASH_TOOL_DEFINITION,GLOB_TOOL_DEFINITION,GREP_TOOL_DEFINITION,READ_FILE_TOOL_DEFINITION,WRITE_FILE_TOOL_DEFINITION,TODO_TOOL_DEFINITION,WEB_FETCH_TOOL_DEFINITION,WEB_SEARCH_TOOL_DEFINITION,SKILL_TOOL_DEFINITION,CONNECTION_SEARCH_TOOL_DEFINITION],CONDITIONAL_TOOLS=new Map([[CONNECTION_SEARCH_TOOL_DEFINITION,e=>e.hasConnections]]);function getFrameworkToolDefinitions(e){return ALL_FRAMEWORK_TOOLS.filter(t=>{let n=CONDITIONAL_TOOLS.get(t);return n===void 0||n(e)})}function getAllFrameworkToolNames(){return new Set(ALL_FRAMEWORK_TOOLS.map(e=>e.name))}export{ConnectionRegistryKey,ReadFileStateKey,TodoStateKey,getAllFrameworkToolNames,getFrameworkToolDefinitions};
1
+ import{ConnectionRegistryKey}from"#context/providers/connection.js";import{ReadFileStateKey}from"#runtime/framework-tools/file-state.js";import{ASK_QUESTION_TOOL_DEFINITION}from"#runtime/framework-tools/ask-question.js";import{WEB_SEARCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-search.js";import{BASH_TOOL_DEFINITION}from"#runtime/framework-tools/bash.js";import{GLOB_TOOL_DEFINITION}from"#runtime/framework-tools/glob.js";import{GREP_TOOL_DEFINITION}from"#runtime/framework-tools/grep.js";import{READ_FILE_TOOL_DEFINITION}from"#runtime/framework-tools/read-file.js";import{SKILL_TOOL_DEFINITION}from"#runtime/framework-tools/skill.js";import{TODO_TOOL_DEFINITION,TodoStateKey}from"#runtime/framework-tools/todo.js";import{WEB_FETCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-fetch.js";import{WRITE_FILE_TOOL_DEFINITION}from"#runtime/framework-tools/write-file.js";const ALL_FRAMEWORK_TOOLS=[ASK_QUESTION_TOOL_DEFINITION,BASH_TOOL_DEFINITION,GLOB_TOOL_DEFINITION,GREP_TOOL_DEFINITION,READ_FILE_TOOL_DEFINITION,WRITE_FILE_TOOL_DEFINITION,TODO_TOOL_DEFINITION,WEB_FETCH_TOOL_DEFINITION,WEB_SEARCH_TOOL_DEFINITION,SKILL_TOOL_DEFINITION];function getFrameworkToolDefinitions(e){return ALL_FRAMEWORK_TOOLS}function getAllFrameworkToolNames(){return new Set(ALL_FRAMEWORK_TOOLS.map(e=>e.name))}export{ConnectionRegistryKey,ReadFileStateKey,TodoStateKey,getAllFrameworkToolNames,getFrameworkToolDefinitions};
@@ -1,2 +1,2 @@
1
- import{CONNECTION_SEARCH_TOOL_DEFINITION}from"#runtime/framework-tools/connection-search.js";function formatConnectionsSection(t){let n=CONNECTION_SEARCH_TOOL_DEFINITION.name;return[`## Connections`,``,`You have direct access to the following external services through connected MCP servers.`,`When the user's request relates to any of these services, use them instead of web search or general knowledge.`,``,`Available connections:`,...t.map(e=>`- ${e.connectionName}: ${e.description}`),``,`Use ${n} to discover specific tools within a connection. Discovered tools become directly callable by their qualified name (e.g. linear__list_issues) in your next response.`].join(`
1
+ function formatConnectionsSection(e){return[`## Connections`,``,`You have direct access to the following external services through connected MCP servers.`,`When the user's request relates to any of these services, use them instead of web search or general knowledge.`,``,`Available connections:`,...e.map(e=>`- ${e.connectionName}: ${e.description}`),``,`Use connection__search to discover specific tools within a connection. Discovered tools become directly callable by their qualified name (e.g. connection__linear__list_issues) in your next response.`].join(`
2
2
  `)}export{formatConnectionsSection};
@@ -1 +1 @@
1
- import{expectObjectRecord}from"#internal/authored-module.js";import{ROOT_COMPILED_AGENT_NODE_ID}from"#compiler/manifest.js";import{CONNECTION_SEARCH_TOOL_DEFINITION}from"#runtime/framework-tools/connection-search.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.js";import{createRuntimeToolRegistry}from"#runtime/tools/registry.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{getAllFrameworkChannelNames,getFrameworkChannelDefinitions}from"#runtime/framework-channels/index.js";import{resolveAgent}from"#runtime/resolve-agent.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{createResolvedRuntimeTurnAgent}from"#runtime/agent/bootstrap.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{getAllFrameworkToolNames,getFrameworkToolDefinitions}from"#runtime/framework-tools/index.js";import{createRuntimeHookRegistry}from"#runtime/hooks/registry.js";import{createRuntimeSandboxRegistry}from"#runtime/sandbox/registry.js";import{createRuntimeSubagentRegistry}from"#runtime/subagents/registry.js";var ResolveRuntimeAgentGraphError=class extends Error{logicalPath;nodeId;sourceId;constructor(e,t={}){super(e),this.name=`ResolveRuntimeAgentGraphError`,t.logicalPath!==void 0&&(this.logicalPath=t.logicalPath),t.nodeId!==void 0&&(this.nodeId=t.nodeId),t.sourceId!==void 0&&(this.sourceId=t.sourceId)}};async function resolveRuntimeAgentGraph(e){let n=new Map,r=createChildNodeIdsByParentNodeId(e.manifest),i=new Map(e.manifest.subagents.map(e=>[e.nodeId,e]));return{nodesByNodeId:n,root:await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:r,manifest:e.manifest,moduleMap:e.moduleMap,nodeId:ROOT_COMPILED_AGENT_NODE_ID,nodesByNodeId:n,subagentNodesById:i})}}async function resolveRuntimeAgentNode(e){let t=toRuntimeNodeId(e.nodeId);if(e.nodesByNodeId.has(t))throw new ResolveRuntimeAgentGraphError(`Found multiple runtime agent nodes for node id "${t}".`,{nodeId:t,sourceId:e.sourceId});let n=await resolveAgent({manifest:e.manifest,moduleMap:e.moduleMap,nodeId:e.nodeId}),a=n.connections.length>0,o=getFrameworkToolDefinitions({hasConnections:a}),s=a?enrichConnectionSearchDescription(o,n.connections):o,c=new Set(s.map(e=>e.name)),l=getAllFrameworkToolNames(),u=new Set(n.tools.map(e=>e.name));for(let r of n.disabledFrameworkTools)if(!l.has(r))throw new ResolveRuntimeAgentGraphError(`agent/tools/${r}.ts exports disableTool() but "${r}" is not a framework tool. Rename the file to one of: ${[...l].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let d=new Set(n.disabledFrameworkTools),f=await createRuntimeToolRegistry({tools:[...s.filter(e=>!u.has(e.name)&&!d.has(e.name)),...n.tools]},{reservedToolNames:[CODE_MODE_TOOL_NAME,...c.has(LOAD_SKILL_TOOL_NAME)||u.has(LOAD_SKILL_TOOL_NAME)?[]:[LOAD_SKILL_TOOL_NAME]]}),p=new Set(n.channels.map(e=>e.name)),m=getAllFrameworkChannelNames();for(let r of n.disabledFrameworkChannels)if(!m.has(r))throw new ResolveRuntimeAgentGraphError(`agent/channels/${r}.ts exports disableRoute() but "${r}" is not a framework channel. Rename the file to one of: ${[...m].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let h=new Set(n.disabledFrameworkChannels),g=[...getFrameworkChannelDefinitions().filter(e=>!p.has(e.name)&&!h.has(e.name)),...n.channels],_=createRuntimeSandboxRegistry({authoredSandbox:n.sandbox,workspaceResourceRoot:n.workspaceResourceRoot}),v=createRuntimeSubagentRegistry({reservedToolNames:[LOAD_SKILL_TOOL_NAME,...f.preparedTools.map(e=>e.name)],subagents:await resolveRuntimeSubagents({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.manifest,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,parentNodeId:e.nodeId,subagentNodesById:e.subagentNodesById})}),y={agent:n,channels:g,hookRegistry:createRuntimeHookRegistry(n.hooks),nodeId:t,sandboxRegistry:_,sourceId:e.sourceId,subagentRegistry:v,toolRegistry:f,turnAgent:createResolvedRuntimeTurnAgent({agent:n,nodeId:t,tools:[...f.preparedTools,...v.preparedTools]})};return e.nodesByNodeId.set(t,y),y}async function resolveRuntimeSubagents(e){let t=[],n=e.childNodeIdsByParentNodeId.get(e.parentNodeId)??[];for(let r of n){let n=e.subagentNodesById.get(r);if(n===void 0)throw new ResolveRuntimeAgentGraphError(`Missing compiled subagent node "${r}" while resolving runtime subagents.`,{nodeId:toRuntimeNodeId(e.parentNodeId),sourceId:r});t.push(await resolveRuntimeSubagent({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,sourceRef:n,subagentNodesById:e.subagentNodesById}))}for(let n of e.manifest.remoteAgents)t.push(await resolveRuntimeRemoteAgent({moduleMap:e.moduleMap,nodeScopeId:e.parentNodeId,sourceRef:n}));return t}async function resolveRuntimeSubagent(e){let t={description:e.sourceRef.description,kind:`subagent`,logicalPath:e.sourceRef.logicalPath,name:e.sourceRef.name,nodeId:toRuntimeNodeId(e.sourceRef.nodeId),sourceId:e.sourceRef.sourceId,sourceKind:`module`};return await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.sourceRef.agent,moduleMap:e.moduleMap,nodeId:e.sourceRef.nodeId,nodesByNodeId:e.nodesByNodeId,sourceId:e.sourceRef.sourceId,subagentNodesById:e.subagentNodesById}),t}async function resolveRuntimeRemoteAgent(t){let n=expectObjectRecord(await loadResolvedModuleExport({definition:t.sourceRef,kindLabel:`remote agent`,moduleMap:t.moduleMap,nodeId:t.nodeScopeId}),`Expected remote agent source "${t.sourceRef.logicalPath}" to export an object.`),r={description:t.sourceRef.description,kind:`remote`,logicalPath:t.sourceRef.logicalPath,name:t.sourceRef.name,nodeId:toRuntimeNodeId(t.sourceRef.nodeId),path:t.sourceRef.path,sourceId:t.sourceRef.sourceId,sourceKind:`module`,url:t.sourceRef.url};typeof n.auth==`function`&&(r.auth=n.auth);let i=resolveRemoteAgentHeaders(n.headers);return i!==void 0&&(r.headers=i),r}function resolveRemoteAgentHeaders(e){if(e===void 0)return;if(typeof e==`function`)return e;if(typeof e!=`object`||!e||Array.isArray(e))return;let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function createChildNodeIdsByParentNodeId(e){let t=new Map;for(let n of e.subagentEdges){let e=t.get(n.parentNodeId);if(e===void 0){t.set(n.parentNodeId,[n.childNodeId]);continue}e.push(n.childNodeId)}return t}function toRuntimeNodeId(e){return e===ROOT_COMPILED_AGENT_NODE_ID?ROOT_RUNTIME_AGENT_NODE_ID:e}function getConnectionSearchName(){return CONNECTION_SEARCH_TOOL_DEFINITION.name}function enrichConnectionSearchDescription(e,t){let n=t.map(e=>e.connectionName).join(`, `);return e.map(e=>e.name===getConnectionSearchName()?{...e,description:`${e.description} Available connections: ${n}.`}:e)}export{resolveRuntimeAgentGraph};
1
+ import{expectObjectRecord}from"#internal/authored-module.js";import{ROOT_COMPILED_AGENT_NODE_ID}from"#compiler/manifest.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.js";import{createRuntimeToolRegistry}from"#runtime/tools/registry.js";import{getAllFrameworkChannelNames,getFrameworkChannelDefinitions}from"#runtime/framework-channels/index.js";import{resolveAgent}from"#runtime/resolve-agent.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{createResolvedRuntimeTurnAgent}from"#runtime/agent/bootstrap.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{createConnectionSearchResolver}from"#runtime/framework-tools/connection-search-dynamic.js";import{getAllFrameworkToolNames,getFrameworkToolDefinitions}from"#runtime/framework-tools/index.js";import{createRuntimeHookRegistry}from"#runtime/hooks/registry.js";import{createRuntimeSandboxRegistry}from"#runtime/sandbox/registry.js";import{createRuntimeSubagentRegistry}from"#runtime/subagents/registry.js";var ResolveRuntimeAgentGraphError=class extends Error{logicalPath;nodeId;sourceId;constructor(e,t={}){super(e),this.name=`ResolveRuntimeAgentGraphError`,t.logicalPath!==void 0&&(this.logicalPath=t.logicalPath),t.nodeId!==void 0&&(this.nodeId=t.nodeId),t.sourceId!==void 0&&(this.sourceId=t.sourceId)}};async function resolveRuntimeAgentGraph(e){let n=new Map,r=createChildNodeIdsByParentNodeId(e.manifest),i=new Map(e.manifest.subagents.map(e=>[e.nodeId,e]));return{nodesByNodeId:n,root:await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:r,manifest:e.manifest,moduleMap:e.moduleMap,nodeId:ROOT_COMPILED_AGENT_NODE_ID,nodesByNodeId:n,subagentNodesById:i})}}async function resolveRuntimeAgentNode(e){let t=toRuntimeNodeId(e.nodeId);if(e.nodesByNodeId.has(t))throw new ResolveRuntimeAgentGraphError(`Found multiple runtime agent nodes for node id "${t}".`,{nodeId:t,sourceId:e.sourceId});let n=await resolveAgent({manifest:e.manifest,moduleMap:e.moduleMap,nodeId:e.nodeId}),a=n.connections.length>0,o=getFrameworkToolDefinitions({hasConnections:a}),s=new Set(o.map(e=>e.name)),c=getAllFrameworkToolNames(),l=new Set(n.tools.map(e=>e.name));for(let r of n.disabledFrameworkTools)if(!c.has(r))throw new ResolveRuntimeAgentGraphError(`agent/tools/${r}.ts exports disableTool() but "${r}" is not a framework tool. Rename the file to one of: ${[...c].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let u=new Set(n.disabledFrameworkTools),d=await createRuntimeToolRegistry({tools:[...o.filter(e=>!l.has(e.name)&&!u.has(e.name)),...n.tools]},{reservedToolNames:[CODE_MODE_TOOL_NAME,...s.has(LOAD_SKILL_TOOL_NAME)||l.has(LOAD_SKILL_TOOL_NAME)?[]:[LOAD_SKILL_TOOL_NAME]]}),f=new Set(n.channels.map(e=>e.name)),p=getAllFrameworkChannelNames();for(let r of n.disabledFrameworkChannels)if(!p.has(r))throw new ResolveRuntimeAgentGraphError(`agent/channels/${r}.ts exports disableRoute() but "${r}" is not a framework channel. Rename the file to one of: ${[...p].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let m=new Set(n.disabledFrameworkChannels),h=[...getFrameworkChannelDefinitions().filter(e=>!f.has(e.name)&&!m.has(e.name)),...n.channels],g=createRuntimeSandboxRegistry({authoredSandbox:n.sandbox,workspaceResourceRoot:n.workspaceResourceRoot}),_=createRuntimeSubagentRegistry({reservedToolNames:[LOAD_SKILL_TOOL_NAME,...d.preparedTools.map(e=>e.name)],subagents:await resolveRuntimeSubagents({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.manifest,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,parentNodeId:e.nodeId,subagentNodesById:e.subagentNodesById})}),v=a?{...n,dynamicToolResolvers:[...n.dynamicToolResolvers,createConnectionSearchResolver()]}:n,y={agent:v,channels:h,hookRegistry:createRuntimeHookRegistry(v.hooks),nodeId:t,sandboxRegistry:g,sourceId:e.sourceId,subagentRegistry:_,toolRegistry:d,turnAgent:createResolvedRuntimeTurnAgent({agent:v,nodeId:t,tools:[...d.preparedTools,..._.preparedTools]})};return e.nodesByNodeId.set(t,y),y}async function resolveRuntimeSubagents(e){let t=[],n=e.childNodeIdsByParentNodeId.get(e.parentNodeId)??[];for(let r of n){let n=e.subagentNodesById.get(r);if(n===void 0)throw new ResolveRuntimeAgentGraphError(`Missing compiled subagent node "${r}" while resolving runtime subagents.`,{nodeId:toRuntimeNodeId(e.parentNodeId),sourceId:r});t.push(await resolveRuntimeSubagent({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,sourceRef:n,subagentNodesById:e.subagentNodesById}))}for(let n of e.manifest.remoteAgents)t.push(await resolveRuntimeRemoteAgent({moduleMap:e.moduleMap,nodeScopeId:e.parentNodeId,sourceRef:n}));return t}async function resolveRuntimeSubagent(e){let t={description:e.sourceRef.description,kind:`subagent`,logicalPath:e.sourceRef.logicalPath,name:e.sourceRef.name,nodeId:toRuntimeNodeId(e.sourceRef.nodeId),sourceId:e.sourceRef.sourceId,sourceKind:`module`};return await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.sourceRef.agent,moduleMap:e.moduleMap,nodeId:e.sourceRef.nodeId,nodesByNodeId:e.nodesByNodeId,sourceId:e.sourceRef.sourceId,subagentNodesById:e.subagentNodesById}),t}async function resolveRuntimeRemoteAgent(t){let n=expectObjectRecord(await loadResolvedModuleExport({definition:t.sourceRef,kindLabel:`remote agent`,moduleMap:t.moduleMap,nodeId:t.nodeScopeId}),`Expected remote agent source "${t.sourceRef.logicalPath}" to export an object.`),r={description:t.sourceRef.description,kind:`remote`,logicalPath:t.sourceRef.logicalPath,name:t.sourceRef.name,nodeId:toRuntimeNodeId(t.sourceRef.nodeId),path:t.sourceRef.path,sourceId:t.sourceRef.sourceId,sourceKind:`module`,url:t.sourceRef.url};typeof n.auth==`function`&&(r.auth=n.auth);let i=resolveRemoteAgentHeaders(n.headers);return i!==void 0&&(r.headers=i),r}function resolveRemoteAgentHeaders(e){if(e===void 0)return;if(typeof e==`function`)return e;if(typeof e!=`object`||!e||Array.isArray(e))return;let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function createChildNodeIdsByParentNodeId(e){let t=new Map;for(let n of e.subagentEdges){let e=t.get(n.parentNodeId);if(e===void 0){t.set(n.parentNodeId,[n.childNodeId]);continue}e.push(n.childNodeId)}return t}function toRuntimeNodeId(e){return e===ROOT_COMPILED_AGENT_NODE_ID?ROOT_RUNTIME_AGENT_NODE_ID:e}export{resolveRuntimeAgentGraph};
@@ -1 +1 @@
1
- import{ResolveAgentError,createResolvedModuleSourceRef}from"#runtime/resolve-helpers.js";import{resolveChannelDefinition}from"#runtime/resolve-channel.js";import{resolveConnectionDefinition}from"#runtime/resolve-connection.js";import{resolveHookDefinition}from"#runtime/resolve-hook.js";import{resolveSandboxDefinition}from"#runtime/resolve-sandbox.js";import{resolveDynamicToolDefinition}from"#runtime/resolve-dynamic-tool.js";import{resolveToolDefinition}from"#runtime/resolve-tool.js";async function resolveAgent(e){let t=e.manifest.skills.map(e=>({...e,metadata:e.metadata===void 0?void 0:{...e.metadata}})),r=[],i=[];for(let t of e.manifest.channels){if(t.kind===`disabled`){i.push(t.name);continue}r.push(await resolveChannelDefinition(t,e.moduleMap,e.nodeId))}let a=await Promise.all(e.manifest.tools.map(t=>resolveToolDefinition(t,e.moduleMap,e.nodeId))),o=await Promise.all(e.manifest.dynamicTools.map(t=>resolveDynamicToolDefinition(t,e.moduleMap,e.nodeId))),s=await Promise.all(e.manifest.hooks.map(t=>resolveHookDefinition(t,e.moduleMap,e.nodeId))),c=await Promise.all(e.manifest.connections.map(t=>resolveConnectionDefinition(t,e.moduleMap,e.nodeId))),l=e.manifest.sandbox===null?null:await resolveSandboxDefinition(e.manifest.sandbox,e.moduleMap,e.nodeId),u=createResolvedInstructions(e.manifest.instructions),d=e.manifest.workspaceResourceRoot,f={channels:r,config:createResolvedAgentConfig(e.manifest),connections:c,disabledFrameworkChannels:i,disabledFrameworkTools:[...e.manifest.disabledFrameworkTools],dynamicToolResolvers:o,hooks:s,metadata:{agentRoot:e.manifest.agentRoot,appRoot:e.manifest.appRoot,diagnosticsSummary:e.manifest.diagnosticsSummary},sandbox:l,workspaceResourceRoot:d,skills:t,tools:a,workspaceSpec:{rootEntries:[...d.rootEntries]}};return u===void 0?f:{...f,instructions:u}}function createResolvedInstructions(e){if(e!==void 0)return{name:e.name,logicalPath:e.logicalPath,markdown:e.markdown,sourceId:e.sourceId,sourceKind:e.sourceKind}}function createResolvedAgentConfig(e){let n={model:e.config.model.source===void 0?{id:e.config.model.id,contextWindowTokens:e.config.model.contextWindowTokens,providerOptions:e.config.model.providerOptions}:{contextWindowTokens:e.config.model.contextWindowTokens,id:e.config.model.id,providerOptions:e.config.model.providerOptions,source:{exportName:e.config.model.source.exportName,sourceKind:`module`,logicalPath:e.config.model.source.logicalPath,sourceId:e.config.model.source.sourceId}},name:e.config.name};if(e.config.compaction!==void 0){let t={};e.config.compaction.model!==void 0&&(t.model=e.config.compaction.model.source===void 0?{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions}:{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions,source:{exportName:e.config.compaction.model.source.exportName,sourceKind:`module`,logicalPath:e.config.compaction.model.source.logicalPath,sourceId:e.config.compaction.model.source.sourceId}}),e.config.compaction.thresholdPercent!==void 0&&(t.thresholdPercent=e.config.compaction.thresholdPercent),n.compaction=t}return e.config.experimental!==void 0&&(n.experimental={codeMode:e.config.experimental.codeMode}),e.config.source!==void 0&&(n.source=createResolvedModuleSourceRef(e.config.source)),n}export{ResolveAgentError,resolveAgent};
1
+ import{ResolveAgentError,createResolvedModuleSourceRef}from"#runtime/resolve-helpers.js";import{resolveChannelDefinition}from"#runtime/resolve-channel.js";import{resolveConnectionDefinition}from"#runtime/resolve-connection.js";import{resolveHookDefinition}from"#runtime/resolve-hook.js";import{resolveSandboxDefinition}from"#runtime/resolve-sandbox.js";import{resolveDynamicSkillDefinition}from"#runtime/resolve-dynamic-skill.js";import{resolveDynamicToolDefinition}from"#runtime/resolve-dynamic-tool.js";import{resolveToolDefinition}from"#runtime/resolve-tool.js";async function resolveAgent(e){let t=e.manifest.skills.map(e=>({...e,metadata:e.metadata===void 0?void 0:{...e.metadata}})),r=[],i=[];for(let t of e.manifest.channels){if(t.kind===`disabled`){i.push(t.name);continue}r.push(await resolveChannelDefinition(t,e.moduleMap,e.nodeId))}let a=await Promise.all(e.manifest.tools.map(t=>resolveToolDefinition(t,e.moduleMap,e.nodeId))),o=await Promise.all((e.manifest.dynamicSkills??[]).map(t=>resolveDynamicSkillDefinition(t,e.moduleMap,e.nodeId))),s=await Promise.all(e.manifest.dynamicTools.map(t=>resolveDynamicToolDefinition(t,e.moduleMap,e.nodeId))),c=await Promise.all(e.manifest.hooks.map(t=>resolveHookDefinition(t,e.moduleMap,e.nodeId))),l=await Promise.all(e.manifest.connections.map(t=>resolveConnectionDefinition(t,e.moduleMap,e.nodeId))),u=e.manifest.sandbox===null?null:await resolveSandboxDefinition(e.manifest.sandbox,e.moduleMap,e.nodeId),d=createResolvedInstructions(e.manifest.instructions),f=e.manifest.workspaceResourceRoot,p={channels:r,config:createResolvedAgentConfig(e.manifest),connections:l,disabledFrameworkChannels:i,disabledFrameworkTools:[...e.manifest.disabledFrameworkTools],dynamicSkillResolvers:o,dynamicToolResolvers:s,hooks:c,metadata:{agentRoot:e.manifest.agentRoot,appRoot:e.manifest.appRoot,diagnosticsSummary:e.manifest.diagnosticsSummary},sandbox:u,workspaceResourceRoot:f,skills:t,tools:a,workspaceSpec:{rootEntries:[...f.rootEntries]}};return d===void 0?p:{...p,instructions:d}}function createResolvedInstructions(e){if(e!==void 0)return{name:e.name,logicalPath:e.logicalPath,markdown:e.markdown,sourceId:e.sourceId,sourceKind:e.sourceKind}}function createResolvedAgentConfig(e){let n={model:e.config.model.source===void 0?{id:e.config.model.id,contextWindowTokens:e.config.model.contextWindowTokens,providerOptions:e.config.model.providerOptions}:{contextWindowTokens:e.config.model.contextWindowTokens,id:e.config.model.id,providerOptions:e.config.model.providerOptions,source:{exportName:e.config.model.source.exportName,sourceKind:`module`,logicalPath:e.config.model.source.logicalPath,sourceId:e.config.model.source.sourceId}},name:e.config.name};if(e.config.compaction!==void 0){let t={};e.config.compaction.model!==void 0&&(t.model=e.config.compaction.model.source===void 0?{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions}:{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions,source:{exportName:e.config.compaction.model.source.exportName,sourceKind:`module`,logicalPath:e.config.compaction.model.source.logicalPath,sourceId:e.config.compaction.model.source.sourceId}}),e.config.compaction.thresholdPercent!==void 0&&(t.thresholdPercent=e.config.compaction.thresholdPercent),n.compaction=t}return e.config.experimental!==void 0&&(n.experimental={codeMode:e.config.experimental.codeMode}),e.config.source!==void 0&&(n.source=createResolvedModuleSourceRef(e.config.source)),n}export{ResolveAgentError,resolveAgent};
@@ -0,0 +1,8 @@
1
+ import type { CompiledDynamicSkillDefinition } from "#compiler/manifest.js";
2
+ import type { CompiledModuleMap } from "#compiler/module-map.js";
3
+ import type { ResolvedDynamicSkillResolver } from "#runtime/types.js";
4
+ /**
5
+ * Resolves one compiled dynamic skill entry into a runtime-owned resolver
6
+ * with live event handler functions reattached from the authored module.
7
+ */
8
+ export declare function resolveDynamicSkillDefinition(definition: CompiledDynamicSkillDefinition, moduleMap: CompiledModuleMap, nodeId: string | undefined): Promise<ResolvedDynamicSkillResolver>;
@@ -0,0 +1 @@
1
+ import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";async function resolveDynamicSkillDefinition(i,a,o){try{let n=expectObjectRecord(expectObjectRecord(await loadResolvedModuleExport({definition:i,kindLabel:`dynamic-skill`,moduleMap:a,nodeId:o}),describe(i,`to return an object`)).events,describe(i,`to provide an events object`)),r={};for(let t of i.eventNames)r[t]=expectFunction(n[t],describe(i,`to provide a handler for event "${t}"`));return{eventNames:[...i.eventNames],events:r,exportName:i.exportName,logicalPath:i.logicalPath,slug:i.slug,sourceId:i.sourceId,sourceKind:`module`}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to resolve dynamic skill from "${i.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:i.logicalPath,sourceId:i.sourceId})}}function describe(e,t){return`Expected the dynamic skill export "${e.exportName??`default`}" from "${e.logicalPath}" ${t}.`}export{resolveDynamicSkillDefinition};
@@ -1 +1 @@
1
- import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{registerDefinitionSource,stampDefinitionKey}from"#public/tool-result-narrowing.js";async function resolveDynamicToolDefinition(i,a,o){try{let n=expectObjectRecord(await loadResolvedModuleExport({definition:i,kindLabel:`dynamic-tool`,moduleMap:a,nodeId:o}),describe(i,`to return an object`)),r=expectObjectRecord(n.events,describe(i,`to provide an events object`)),s={};for(let t of i.eventNames)s[t]=expectFunction(r[t],describe(i,`to provide a handler for event "${t}"`));let c=`dynamic-tool-source:${i.sourceId}`;return stampDefinitionKey(n,c),registerDefinitionSource(c,{kind:`tool`,logicalPath:i.logicalPath,name:i.slug}),{eventNames:[...i.eventNames],events:s,exportName:i.exportName,identity:i.identity,logicalPath:i.logicalPath,slug:i.slug,sourceId:i.sourceId,sourceKind:`module`}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to resolve dynamic tool from "${i.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:i.logicalPath,sourceId:i.sourceId})}}function describe(e,t){return`Expected the dynamic tool export "${e.exportName??`default`}" from "${e.logicalPath}" ${t}.`}export{resolveDynamicToolDefinition};
1
+ import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{registerDefinitionSource,stampDefinitionKey}from"#public/tool-result-narrowing.js";async function resolveDynamicToolDefinition(i,a,o){try{let n=expectObjectRecord(await loadResolvedModuleExport({definition:i,kindLabel:`dynamic-tool`,moduleMap:a,nodeId:o}),describe(i,`to return an object`)),r=expectObjectRecord(n.events,describe(i,`to provide an events object`)),s={};for(let t of i.eventNames)s[t]=expectFunction(r[t],describe(i,`to provide a handler for event "${t}"`));let c=`dynamic-tool-source:${i.sourceId}`;return stampDefinitionKey(n,c),registerDefinitionSource(c,{kind:`tool`,logicalPath:i.logicalPath,name:i.slug}),{eventNames:[...i.eventNames],events:s,exportName:i.exportName,logicalPath:i.logicalPath,slug:i.slug,sourceId:i.sourceId,sourceKind:`module`}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to resolve dynamic tool from "${i.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:i.logicalPath,sourceId:i.sourceId})}}function describe(e,t){return`Expected the dynamic tool export "${e.exportName??`default`}" from "${e.logicalPath}" ${t}.`}export{resolveDynamicToolDefinition};
@@ -1 +1 @@
1
- import{getRuntimeCompiledArtifactsCacheKey}from"#runtime/compiled-artifacts-source.js";import{getResolvedRuntimeAgentNode}from"#runtime/graph.js";import{loadCompiledManifest}from"#runtime/loaders/manifest.js";import{resolveRuntimeAgentGraph}from"#runtime/resolve-agent-graph.js";import{pathToFileURL}from"node:url";import{loadCompiledModuleMap}from"#runtime/loaders/module-map.js";import{getActiveRuntimeSession}from"#runtime/sessions/runtime-session.js";import{resolveRuntimeCompiledArtifactsVersionedCacheKey}from"#runtime/cache-key.js";import{createRuntimeAdapterRegistry}from"#runtime/channels/registry.js";const isCacheDisabled=process.env.ASH_DISABLE_AGENT_CACHE===`1`;async function loadFullBundle(e){let[t,i]=await Promise.all([loadCompiledManifest({compiledArtifactsSource:e}),loadRuntimeCompiledModuleMap(e)]),a=await resolveRuntimeAgentGraph({manifest:t,moduleMap:i}),o=a.root;return{adapterRegistry:createRuntimeAdapterRegistry({channels:collectResolvedChannels(a)}),compiledArtifactsSource:e,graph:a,hookRegistry:o.hookRegistry,moduleMap:i,resolvedAgent:o.agent,subagentRegistry:o.subagentRegistry,toolRegistry:o.toolRegistry,turnAgent:o.turnAgent}}async function loadRuntimeCompiledModuleMap(e){return e.kind===`disk`&&e.moduleMapLoaderPath!==void 0?await loadAuthoredSourceCompiledModuleMap(e):await loadCompiledModuleMap({compiledArtifactsSource:e})}async function loadAuthoredSourceCompiledModuleMap(e){if(e.moduleMapLoaderPath===void 0)throw Error(`Authored-source module map loading requires "moduleMapLoaderPath" in the compiled artifacts source.`);return await(await import(pathToFileURL(e.moduleMapLoaderPath).href)).loadCompiledModuleMapFromAuthoredSource({compiledArtifactsSource:e})}async function getOrLoadFullBundle(t){if(isCacheDisabled)return loadFullBundle(t);let n=getActiveRuntimeSession(),r=getRuntimeCompiledArtifactsCacheKey(t),i=await resolveRuntimeCompiledArtifactsVersionedCacheKey(t),a=n.bundleCacheKeyBySourceKey.get(r);a!==void 0&&a!==i&&n.bundleCache.delete(a),n.bundleCacheKeyBySourceKey.set(r,i);let s=n.bundleCache.get(i);if(s!==void 0)return s;let c=loadFullBundle(t).catch(e=>{throw n.bundleCache.delete(i),n.bundleCacheKeyBySourceKey.get(r)===i&&n.bundleCacheKeyBySourceKey.delete(r),e});return n.bundleCache.set(i,c),c}async function getCompiledRuntimeAgentBundle(e){let n=await getOrLoadFullBundle(e.compiledArtifactsSource);if(e.nodeId===void 0)return n;let r=getResolvedRuntimeAgentNode(n.graph,e.nodeId);return{adapterRegistry:n.adapterRegistry,compiledArtifactsSource:n.compiledArtifactsSource,graph:{nodesByNodeId:n.graph.nodesByNodeId,root:r},hookRegistry:r.hookRegistry,moduleMap:n.moduleMap,nodeId:e.nodeId,resolvedAgent:r.agent,subagentRegistry:r.subagentRegistry,toolRegistry:r.toolRegistry,turnAgent:r.turnAgent}}function clearCompiledRuntimeAgentBundleCache(){let e=getActiveRuntimeSession();e.bundleCache.clear(),e.bundleCacheKeyBySourceKey.clear()}function collectResolvedChannels(e){let t=new Map;for(let n of e.nodesByNodeId.values())for(let e of n.channels)t.set(`${e.sourceId}:${e.name}`,e);return[...t.values()]}export{clearCompiledRuntimeAgentBundleCache,getCompiledRuntimeAgentBundle};
1
+ import{getResolvedRuntimeAgentNode}from"#runtime/graph.js";import{getRuntimeCompiledArtifactsCacheKey}from"#runtime/compiled-artifacts-source.js";import{loadCompiledManifest}from"#runtime/loaders/manifest.js";import{resolveRuntimeAgentGraph}from"#runtime/resolve-agent-graph.js";import{pathToFileURL}from"node:url";import{loadCompiledModuleMap}from"#runtime/loaders/module-map.js";import{getActiveRuntimeSession}from"#runtime/sessions/runtime-session.js";import{resolveRuntimeCompiledArtifactsVersionedCacheKey}from"#runtime/cache-key.js";import{createRuntimeAdapterRegistry}from"#runtime/channels/registry.js";const isCacheDisabled=process.env.ASH_DISABLE_AGENT_CACHE===`1`;async function loadFullBundle(e){let[t,i]=await Promise.all([loadCompiledManifest({compiledArtifactsSource:e}),loadRuntimeCompiledModuleMap(e)]),a=await resolveRuntimeAgentGraph({manifest:t,moduleMap:i}),o=a.root;return{adapterRegistry:createRuntimeAdapterRegistry({channels:collectResolvedChannels(a)}),compiledArtifactsSource:e,graph:a,hookRegistry:o.hookRegistry,moduleMap:i,resolvedAgent:o.agent,subagentRegistry:o.subagentRegistry,toolRegistry:o.toolRegistry,turnAgent:o.turnAgent}}async function loadRuntimeCompiledModuleMap(e){return e.kind===`disk`&&e.moduleMapLoaderPath!==void 0?await loadAuthoredSourceCompiledModuleMap(e):await loadCompiledModuleMap({compiledArtifactsSource:e})}async function loadAuthoredSourceCompiledModuleMap(e){if(e.moduleMapLoaderPath===void 0)throw Error(`Authored-source module map loading requires "moduleMapLoaderPath" in the compiled artifacts source.`);return await(await import(pathToFileURL(e.moduleMapLoaderPath).href)).loadCompiledModuleMapFromAuthoredSource({compiledArtifactsSource:e})}async function getOrLoadFullBundle(e){if(isCacheDisabled)return loadFullBundle(e);let n=getActiveRuntimeSession(),r=getRuntimeCompiledArtifactsCacheKey(e),i=await resolveRuntimeCompiledArtifactsVersionedCacheKey(e),a=n.bundleCacheKeyBySourceKey.get(r);a!==void 0&&a!==i&&n.bundleCache.delete(a),n.bundleCacheKeyBySourceKey.set(r,i);let s=n.bundleCache.get(i);if(s!==void 0)return s;let c=loadFullBundle(e).catch(e=>{throw n.bundleCache.delete(i),n.bundleCacheKeyBySourceKey.get(r)===i&&n.bundleCacheKeyBySourceKey.delete(r),e});return n.bundleCache.set(i,c),c}async function getCompiledRuntimeAgentBundle(t){let n=await getOrLoadFullBundle(t.compiledArtifactsSource);if(t.nodeId===void 0)return n;let r=getResolvedRuntimeAgentNode(n.graph,t.nodeId);return{adapterRegistry:n.adapterRegistry,compiledArtifactsSource:n.compiledArtifactsSource,graph:{nodesByNodeId:n.graph.nodesByNodeId,root:r},hookRegistry:r.hookRegistry,moduleMap:n.moduleMap,nodeId:t.nodeId,resolvedAgent:r.agent,subagentRegistry:r.subagentRegistry,toolRegistry:r.toolRegistry,turnAgent:r.turnAgent}}function clearCompiledRuntimeAgentBundleCache(){let e=getActiveRuntimeSession();e.bundleCache.clear(),e.bundleCacheKeyBySourceKey.clear()}function collectResolvedChannels(e){let t=new Map;for(let n of e.nodesByNodeId.values())for(let e of n.channels)t.set(`${e.sourceId}:${e.name}`,e);return[...t.values()]}export{clearCompiledRuntimeAgentBundleCache,getCompiledRuntimeAgentBundle};
@@ -1 +1 @@
1
- import{ContextKey}from"#context/key.js";import{getAdapterKind}from"#channel/adapter.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{deserializeRuntimeAdapter}from"#runtime/channels/registry.js";const ChannelKey=new ContextKey(`ash.channel`,{codec:{serialize(e){return{kind:getAdapterKind(e),state:e.state?{...e.state}:{}}},deserialize(e,t){let n=t.get(BundleKey);if(n===void 0)throw Error(`Cannot deserialize "ash.channel" before "ash.bundle". The runtime bundle must be present in context.`);return deserializeRuntimeAdapter(n.adapterRegistry,e)}}}),BundleKey=new ContextKey(`ash.bundle`,{codec:{serialize:e=>({nodeId:e.nodeId,source:e.compiledArtifactsSource}),deserialize:e=>{let{source:t,nodeId:r}=e;return getCompiledRuntimeAgentBundle({compiledArtifactsSource:t,nodeId:r})}}});export{BundleKey,ChannelKey};
1
+ import{getAdapterKind}from"#channel/adapter.js";import{ContextKey}from"#context/key.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{deserializeRuntimeAdapter}from"#runtime/channels/registry.js";const ChannelKey=new ContextKey(`ash.channel`,{codec:{serialize(t){return{kind:getAdapterKind(t),state:t.state?{...t.state}:{}}},deserialize(e,t){let n=t.get(BundleKey);if(n===void 0)throw Error(`Cannot deserialize "ash.channel" before "ash.bundle". The runtime bundle must be present in context.`);return deserializeRuntimeAdapter(n.adapterRegistry,e)}}}),BundleKey=new ContextKey(`ash.bundle`,{codec:{serialize:e=>({nodeId:e.nodeId,source:e.compiledArtifactsSource}),deserialize:e=>{let{source:t,nodeId:r}=e;return getCompiledRuntimeAgentBundle({compiledArtifactsSource:t,nodeId:r})}}});export{BundleKey,ChannelKey};
@@ -255,13 +255,21 @@ interface ResolvedAgentMetadata {
255
255
  readonly diagnosticsSummary: DiscoverDiagnosticsSummary;
256
256
  }
257
257
  /**
258
- * Runtime resolver for dynamic tools declared via `defineTools({ events })`
259
- * or `defineTool({ events })`. Carries the live event handler functions
260
- * loaded from the compiled module.
258
+ * Runtime resolver for dynamic tools declared via `defineDynamic({ events })`.
259
+ * Carries the live event handler functions loaded from the compiled module.
261
260
  */
262
261
  export interface ResolvedDynamicToolResolver extends Readonly<ModuleSourceRef> {
263
262
  readonly slug: string;
264
- readonly identity: "single" | "multi";
263
+ readonly eventNames: readonly string[];
264
+ readonly events: Readonly<Record<string, (event: unknown, ctx: unknown) => unknown | Promise<unknown>>>;
265
+ }
266
+ /**
267
+ * Runtime resolver for dynamic skills declared via `defineDynamic({ events })`
268
+ * in `agent/skills/`. Carries the live event handler functions loaded from the
269
+ * compiled module.
270
+ */
271
+ export interface ResolvedDynamicSkillResolver extends Readonly<ModuleSourceRef> {
272
+ readonly slug: string;
265
273
  readonly eventNames: readonly string[];
266
274
  readonly events: Readonly<Record<string, (event: unknown, ctx: unknown) => unknown | Promise<unknown>>>;
267
275
  }
@@ -286,6 +294,7 @@ export interface ResolvedAgent {
286
294
  * filter the framework default tool set.
287
295
  */
288
296
  readonly disabledFrameworkTools: readonly string[];
297
+ readonly dynamicSkillResolvers: readonly ResolvedDynamicSkillResolver[];
289
298
  readonly dynamicToolResolvers: readonly ResolvedDynamicToolResolver[];
290
299
  readonly metadata: ResolvedAgentMetadata;
291
300
  /**
@@ -1,22 +1,25 @@
1
- import type { PublicToolInputSchema } from "#shared/tool-definition.js";
1
+ import type { ModelMessage } from "ai";
2
+ import type { PublicToolInputSchema, ToolModelOutput } from "#shared/tool-definition.js";
2
3
  import type { SessionContext } from "#public/definitions/callback-context.js";
3
4
  import type { SessionAuth } from "#context/keys.js";
5
+ import type { HandleMessageStreamEvent } from "#protocol/message.js";
4
6
  type ToolContext = SessionContext;
5
7
  /**
6
- * Event names supported by dynamic tool resolvers. Initially
7
- * `"session.started"` and `"step.started"`; more events can be
8
- * added by expanding this union.
8
+ * Subset of stream event types allowed for dynamic tool resolvers.
9
+ * The dispatch architecture supports any event — this extract
10
+ * restricts the public API surface until more events are validated.
9
11
  */
10
- export type DynamicToolEventName = "session.started" | "turn.started" | "step.started";
12
+ export type DynamicToolEventName = Extract<HandleMessageStreamEvent["type"], "session.started" | "turn.started" | "step.started">;
13
+ export declare const ALLOWED_DYNAMIC_TOOL_EVENTS: ReadonlySet<string>;
11
14
  /**
12
- * Context passed to a dynamic tool resolver's event handler.
15
+ * Context passed to a dynamic resolver's event handler (tools and skills).
13
16
  *
14
17
  * Provides read-only access to session identity, auth, and channel
15
18
  * metadata. State access is not exposed here — resolvers read state
16
19
  * through `defineState` handles or via the session context available
17
20
  * inside tool `execute` functions.
18
21
  */
19
- export interface DynamicToolResolveContext {
22
+ export interface DynamicResolveContext {
20
23
  readonly session: {
21
24
  readonly id: string;
22
25
  readonly auth: SessionAuth;
@@ -25,108 +28,82 @@ export interface DynamicToolResolveContext {
25
28
  readonly kind?: string;
26
29
  readonly continuationToken?: string;
27
30
  };
28
- /**
29
- * Compiler-injected durable cache for resolver I/O results.
30
- *
31
- * First call (per session): executes `fn`, stores the serializable
32
- * result durably, returns it.
33
- * Replay (subsequent workflow steps): returns the cached result
34
- * without calling `fn`.
35
- *
36
- * The cached value must be JSON-serializable. Non-serializable
37
- * values cause a runtime error on first cache write.
38
- *
39
- * @internal Injected by the `ash:dynamic-tool-await-cache` bundler
40
- * transform. Not intended for direct author use.
41
- */
42
- __cache<T>(key: string, fn: () => T | Promise<T>): Promise<T>;
31
+ readonly messages: readonly ModelMessage[];
43
32
  }
44
33
  /**
45
34
  * A single tool entry within a resolved dynamic tool set.
46
35
  *
47
- * Identity comes from the entry's Record key there is no `name`
48
- * field. For `defineTools`, the runtime tool name is always
49
- * `slug__key`. For `defineTool`, it is the file slug alone.
36
+ * Identity comes from context: when the resolver handler returns a
37
+ * single entry, the tool is named after the file slug. When the
38
+ * handler returns a `Record<string, DynamicToolEntry>`, each entry
39
+ * is named `slug__key`.
50
40
  *
51
41
  * `TInput` defaults to `Record<string, unknown>` but is inferred
52
- * automatically when `inputSchema` is a Standard Schema (e.g. Zod):
53
- *
54
- * ```ts
55
- * {
56
- * inputSchema: z.object({ city: z.string() }),
57
- * async execute(input) { return fetchWeather(input.city); },
58
- * }
59
- * ```
60
- *
61
- * When `inputSchema` is a plain JSON object, annotate `execute`
62
- * explicitly:
63
- *
64
- * ```ts
65
- * {
66
- * inputSchema: { type: "object", properties: { city: { type: "string" } } },
67
- * async execute(input: { city: string }) { return fetchWeather(input.city); },
68
- * }
69
- * ```
42
+ * automatically when `inputSchema` is a Standard Schema (e.g. Zod)
43
+ * via the `defineTool` wrapper.
70
44
  */
71
- export interface DynamicToolEntry<TInput = Record<string, unknown>, TOutput = unknown> {
72
- /** @internal Stamp set by `tool()` — raw object literals are rejected. */
73
- readonly __brand: "ash:tool";
45
+ export interface DynamicToolEntry<TInput = Record<string, unknown>, TOutput = any> {
74
46
  readonly description: string;
75
47
  readonly inputSchema: PublicToolInputSchema<TInput>;
76
48
  execute(input: TInput, ctx: ToolContext): TOutput | Promise<TOutput>;
49
+ readonly toModelOutput?: (output: TOutput) => ToolModelOutput | Promise<ToolModelOutput>;
77
50
  }
78
51
  /**
79
52
  * A resolved tool set: keys are entry identifiers, values are tool
80
- * entries produced by the {@link tool} helper. Uses `any` for the
81
- * type params so entries with different schemas are assignable to
82
- * the same Record — `tool()` captures the per-entry types before
53
+ * entries produced by {@link defineTool}. Uses `any` for the type
54
+ * params so entries with different schemas are assignable to the
55
+ * same Record — `defineTool()` captures the per-entry types before
83
56
  * they reach this widened container.
84
57
  */
85
58
  export type DynamicToolSet = Readonly<Record<string, DynamicToolEntry<any, any>>>;
86
59
  /**
87
- * Event handler map for dynamic tool definitions. Each key is a
88
- * supported event name; each value is a resolver function that
89
- * receives the stream event and resolve context, and returns a
90
- * record of tool entries or `null`.
91
- *
92
- * The handler return type is `DynamicToolSet` — using
93
- * `DynamicToolEntry<any, any>` so per-entry Zod schemas infer
94
- * their own `execute(input)` type without being widened.
60
+ * Return type for a `defineDynamic` event handler. Each handler can
61
+ * return a single tool entry (named after the file slug), a map of
62
+ * entries (named `slug__key`), or `null` to produce no tools.
63
+ */
64
+ export type DynamicToolResult = DynamicToolEntry<any, any> | DynamicToolSet | null;
65
+ /**
66
+ * Event handler map for `defineDynamic`. Each key is a supported
67
+ * event name; each value is a resolver function that receives the
68
+ * stream event and resolve context, and returns a single tool entry,
69
+ * a record of tool entries, or `null`.
95
70
  */
96
71
  export type DynamicToolEvents = {
97
- readonly [K in DynamicToolEventName]?: (event: unknown, ctx: DynamicToolResolveContext) => DynamicToolSet | null | Promise<DynamicToolSet | null>;
72
+ readonly [K in DynamicToolEventName]?: (event: unknown, ctx: DynamicResolveContext) => DynamicToolResult | Promise<DynamicToolResult>;
98
73
  };
99
74
  /**
100
- * Event handler map for a singular dynamic tool. Each handler returns
101
- * a single tool entry or `null`.
75
+ * Base event handler map accepted by `defineDynamic`. Intentionally
76
+ * wide the slot directory (tools/ vs skills/) determines what the
77
+ * handlers must return, validated at runtime by the respective
78
+ * resolver. This type exists so `defineDynamic` can accept both
79
+ * tool-returning and skill-returning handlers.
102
80
  */
103
- export type DynamicSingleToolEvents = {
104
- readonly [K in DynamicToolEventName]?: (event: unknown, ctx: DynamicToolResolveContext) => DynamicToolEntry | null | Promise<DynamicToolEntry | null>;
81
+ export type DynamicEvents = {
82
+ readonly [K in DynamicToolEventName]?: (event: unknown, ctx: DynamicResolveContext) => unknown | Promise<unknown>;
105
83
  };
106
84
  /**
107
- * Marker discriminator for a `defineTools({ events })` export.
85
+ * Marker discriminator for a `defineDynamic({ events })` export.
108
86
  */
109
- export declare const DYNAMIC_TOOLS_SENTINEL_KIND: "ash:dynamic-tools";
87
+ export declare const DYNAMIC_SENTINEL_KIND: "ash:dynamic";
110
88
  /**
111
- * Marker discriminator for a `defineTool({ events })` export.
89
+ * Runtime shape of a `defineDynamic({ events })` export, stamped
90
+ * with a sentinel kind so the compiler/normalizer can detect it.
112
91
  */
113
- export declare const DYNAMIC_TOOL_SENTINEL_KIND: "ash:dynamic-tool";
92
+ export interface DynamicSentinel {
93
+ readonly kind: typeof DYNAMIC_SENTINEL_KIND;
94
+ readonly events: DynamicEvents;
95
+ }
96
+ export declare function isDynamicSentinel(value: unknown): value is DynamicSentinel;
114
97
  /**
115
- * Runtime shape of a `defineTools({ events })` export, stamped with a
116
- * sentinel kind so the compiler/normalizer can detect it.
98
+ * Symbol-based brand stamped by `defineTool` on every entry. Invisible
99
+ * in IntelliSense but checked at runtime to enforce the wrapper and
100
+ * to distinguish a single entry from a map of entries.
117
101
  */
118
- export interface DynamicToolsSentinel {
119
- readonly kind: typeof DYNAMIC_TOOLS_SENTINEL_KIND;
120
- readonly events: DynamicToolEvents;
121
- }
102
+ export declare const TOOL_BRAND: unique symbol;
122
103
  /**
123
- * Runtime shape of a `defineTool({ events })` export, stamped with a
124
- * sentinel kind so the compiler/normalizer can detect it.
104
+ * Returns true if `value` was stamped by `defineTool` (has the brand
105
+ * symbol). Used to detect single entry vs map of entries, and to
106
+ * validate that entries are properly wrapped.
125
107
  */
126
- export interface DynamicToolSentinel {
127
- readonly kind: typeof DYNAMIC_TOOL_SENTINEL_KIND;
128
- readonly events: DynamicSingleToolEvents;
129
- }
130
- export declare function isDynamicToolsSentinel(value: unknown): value is DynamicToolsSentinel;
131
- export declare function isDynamicToolSentinel(value: unknown): value is DynamicToolSentinel;
108
+ export declare function isBrandedToolEntry(value: unknown): boolean;
132
109
  export {};
@@ -1 +1 @@
1
- const DYNAMIC_TOOLS_SENTINEL_KIND=`ash:dynamic-tools`,DYNAMIC_TOOL_SENTINEL_KIND=`ash:dynamic-tool`;function isDynamicToolsSentinel(e){return typeof e==`object`&&!!e&&e.kind===`ash:dynamic-tools`}function isDynamicToolSentinel(e){return typeof e==`object`&&!!e&&e.kind===`ash:dynamic-tool`}export{DYNAMIC_TOOLS_SENTINEL_KIND,DYNAMIC_TOOL_SENTINEL_KIND,isDynamicToolSentinel,isDynamicToolsSentinel};
1
+ const ALLOWED_DYNAMIC_TOOL_EVENTS=new Set([`session.started`,`turn.started`,`step.started`]),DYNAMIC_SENTINEL_KIND=`ash:dynamic`;function isDynamicSentinel(e){return typeof e==`object`&&!!e&&e.kind===`ash:dynamic`}const TOOL_BRAND=Symbol.for(`ash:tool-brand`);function isBrandedToolEntry(e){return typeof e==`object`&&!!e&&e[TOOL_BRAND]===!0}export{ALLOWED_DYNAMIC_TOOL_EVENTS,DYNAMIC_SENTINEL_KIND,TOOL_BRAND,isBrandedToolEntry,isDynamicSentinel};
@@ -29,3 +29,17 @@ export declare function isObject(value: unknown): value is Record<string, unknow
29
29
  * meaningful value by display or correlation logic.
30
30
  */
31
31
  export declare function isNonEmptyString(value: unknown): value is string;
32
+ /**
33
+ * Returns `true` when `value` is a thenable — an object with a `then`
34
+ * function. Used to reject async instrumentation metadata projectors
35
+ * that accidentally return a Promise instead of a plain record.
36
+ */
37
+ export declare function isThenable(value: unknown): value is PromiseLike<unknown>;
38
+ /**
39
+ * Returns `true` when `value` is a plain object record — `{}`,
40
+ * `Object.create(null)`, or an object whose prototype is
41
+ * `Object.prototype`. Class instances, `Map`, `Date`, and other
42
+ * exotic objects are excluded even though `isObject` would accept
43
+ * them.
44
+ */
45
+ export declare function isPlainRecord(value: unknown): value is Record<string, unknown>;
@@ -1 +1 @@
1
- function isObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function isNonEmptyString(e){return typeof e==`string`&&e.length>0}export{isNonEmptyString,isObject};
1
+ function isObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function isNonEmptyString(e){return typeof e==`string`&&e.length>0}function isThenable(e){return isObject(e)&&typeof e.then==`function`}function isPlainRecord(e){if(!isObject(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}export{isNonEmptyString,isObject,isPlainRecord,isThenable};
@@ -4,8 +4,8 @@
4
4
  */
5
5
  export type SkillFileContent = string | Uint8Array;
6
6
  /**
7
- * Public skill package content shared by TypeScript-authored skills and
8
- * runtime hook contributions.
7
+ * Public skill package content for authored skills and dynamic skill
8
+ * resolvers.
9
9
  */
10
10
  export interface SkillPackageDefinition {
11
11
  readonly description: string;
@@ -15,8 +15,9 @@ export interface SkillPackageDefinition {
15
15
  readonly files?: Readonly<Record<string, SkillFileContent>>;
16
16
  }
17
17
  /**
18
- * Runtime-contributed skill package. Hook-created skills do not have an
19
- * authored file path, so they carry their name explicitly.
18
+ * Skill package with an explicit name. Used by compiled skill entries
19
+ * (where the name is path-derived) and by dynamic skill resolvers
20
+ * (where the name is qualified from the resolver slug + entry key).
20
21
  */
21
22
  export interface NamedSkillDefinition extends SkillPackageDefinition {
22
23
  readonly name: string;