eve 0.22.1 → 0.22.3

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 (184) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/src/chunks/{use-eve-agent-CM24ZUEI.js → use-eve-agent-Cojyfr4X.js} +25 -13
  3. package/dist/src/chunks/{use-eve-agent-CxcKypLZ.js → use-eve-agent-D-S1TPCW.js} +25 -13
  4. package/dist/src/cli/commands/init-repl.d.ts +6 -5
  5. package/dist/src/cli/dev/url.js +1 -1
  6. package/dist/src/client/client-error.d.ts +5 -1
  7. package/dist/src/client/client-error.js +1 -1
  8. package/dist/src/client/client.js +1 -1
  9. package/dist/src/client/open-stream.js +1 -1
  10. package/dist/src/client/session.js +1 -1
  11. package/dist/src/client/types.d.ts +2 -1
  12. package/dist/src/client/url.js +1 -1
  13. package/dist/src/compiled/.vendor-stamp.json +6 -4
  14. package/dist/src/compiled/@workflow/core/create-hook.d.ts +2 -2
  15. package/dist/src/compiled/@workflow/core/events-consumer.d.ts +1 -1
  16. package/dist/src/compiled/@workflow/core/index.js +2 -2
  17. package/dist/src/compiled/@workflow/core/private.js +1 -1
  18. package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +14 -0
  19. package/dist/src/compiled/@workflow/core/runtime/get-world-lazy.d.ts +3 -12
  20. package/dist/src/compiled/@workflow/core/runtime/wait-continuation.d.ts +2 -2
  21. package/dist/src/compiled/@workflow/core/runtime/world-compatibility.d.ts +5 -0
  22. package/dist/src/compiled/@workflow/core/runtime/world-init.d.ts +16 -41
  23. package/dist/src/compiled/@workflow/core/runtime/world-target.d.ts +11 -0
  24. package/dist/src/compiled/@workflow/core/runtime/world.d.ts +21 -9
  25. package/dist/src/compiled/@workflow/core/runtime.d.ts +2 -1
  26. package/dist/src/compiled/@workflow/core/runtime.js +3 -141
  27. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  28. package/dist/src/compiled/@workflow/core/workflow/world-init-stub.d.ts +2 -2
  29. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  30. package/dist/src/compiled/@workflow/errors/index.js +1 -1
  31. package/dist/src/compiled/@workflow/world/analytics.d.ts +182 -0
  32. package/dist/src/compiled/@workflow/world/env-config.d.ts +39 -0
  33. package/dist/src/compiled/@workflow/world/events.d.ts +25 -0
  34. package/dist/src/compiled/@workflow/world/index.d.ts +6 -3
  35. package/dist/src/compiled/@workflow/world/interfaces.d.ts +14 -7
  36. package/dist/src/compiled/@workflow/world/runs.d.ts +9 -1
  37. package/dist/src/compiled/@workflow/world/shared.d.ts +15 -0
  38. package/dist/src/compiled/@workflow/world/steps.d.ts +8 -0
  39. package/dist/src/compiled/@workflow/world-local/LICENSE.md +201 -0
  40. package/dist/src/compiled/@workflow/world-local/index.js +4 -0
  41. package/dist/src/compiled/@workflow/world-vercel/LICENSE.md +201 -0
  42. package/dist/src/compiled/@workflow/world-vercel/index.js +42 -0
  43. package/dist/src/compiled/_chunks/workflow/attribute-changes-BnKD8Y3m.js +20 -0
  44. package/dist/src/compiled/_chunks/workflow/{dist-FLIfyJ4Y.js → dist-CttsoN4D.js} +1 -1
  45. package/dist/src/compiled/_chunks/workflow/dist-DJU_7R9s.js +40 -0
  46. package/dist/src/compiled/_chunks/workflow/dist-DpDDcpTl.js +3 -0
  47. package/dist/src/compiled/_chunks/workflow/resume-hook-DjPY9VGg.js +1 -0
  48. package/dist/src/compiled/_chunks/workflow/run-BSANnUPR.js +1 -0
  49. package/dist/src/compiled/_chunks/workflow/sleep-phozDCW8.js +1 -0
  50. package/dist/src/compiled/_chunks/workflow/token-CaY0nA5J.js +1 -0
  51. package/dist/src/compiled/_chunks/workflow/token-D4VIwGlD.js +1 -0
  52. package/dist/src/compiled/_chunks/workflow/undici-fb54XL8i.js +95 -0
  53. package/dist/src/compiler/manifest.d.ts +40 -2
  54. package/dist/src/compiler/manifest.js +1 -1
  55. package/dist/src/compiler/module-map.js +2 -2
  56. package/dist/src/compiler/normalize-extension.d.ts +68 -0
  57. package/dist/src/compiler/normalize-extension.js +1 -0
  58. package/dist/src/compiler/normalize-manifest.js +2 -2
  59. package/dist/src/compiler/workspace-resources.js +1 -1
  60. package/dist/src/context/dynamic-skill-lifecycle.js +1 -1
  61. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  62. package/dist/src/discover/discover-agent.d.ts +14 -1
  63. package/dist/src/discover/discover-agent.js +1 -1
  64. package/dist/src/discover/extension-specifier.d.ts +15 -0
  65. package/dist/src/discover/extension-specifier.js +1 -0
  66. package/dist/src/discover/extensions.d.ts +109 -0
  67. package/dist/src/discover/extensions.js +1 -0
  68. package/dist/src/discover/filesystem.d.ts +1 -1
  69. package/dist/src/discover/filesystem.js +1 -1
  70. package/dist/src/discover/grammar.d.ts +27 -0
  71. package/dist/src/discover/grammar.js +1 -1
  72. package/dist/src/discover/manifest.d.ts +46 -0
  73. package/dist/src/discover/manifest.js +1 -1
  74. package/dist/src/evals/assertions/run.d.ts +3 -2
  75. package/dist/src/evals/assertions/run.js +2 -2
  76. package/dist/src/evals/index.d.ts +1 -1
  77. package/dist/src/evals/loaders/yaml.js +1 -1
  78. package/dist/src/evals/match.d.ts +11 -6
  79. package/dist/src/execution/sandbox/bindings/microsandbox-network.js +1 -1
  80. package/dist/src/harness/emission.js +1 -1
  81. package/dist/src/harness/model-call-error.d.ts +5 -0
  82. package/dist/src/harness/model-call-error.js +1 -1
  83. package/dist/src/harness/prompt-cache.d.ts +18 -9
  84. package/dist/src/harness/prompt-cache.js +1 -1
  85. package/dist/src/harness/tool-loop.js +1 -1
  86. package/dist/src/internal/application/compiled-artifacts.d.ts +4 -0
  87. package/dist/src/internal/application/compiled-artifacts.js +5 -4
  88. package/dist/src/internal/application/package.d.ts +9 -5
  89. package/dist/src/internal/application/package.js +1 -1
  90. package/dist/src/internal/authored-module-loader.d.ts +14 -0
  91. package/dist/src/internal/authored-module-loader.js +2 -2
  92. package/dist/src/internal/authored-module-map-loader.js +1 -1
  93. package/dist/src/internal/bundler/extension-scope-plugin.d.ts +37 -0
  94. package/dist/src/internal/bundler/extension-scope-plugin.js +3 -0
  95. package/dist/src/internal/helpers/gray-matter.d.ts +25 -0
  96. package/dist/src/internal/helpers/gray-matter.js +1 -0
  97. package/dist/src/internal/helpers/markdown.js +1 -1
  98. package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
  99. package/dist/src/internal/nitro/host/build-application.js +1 -1
  100. package/dist/src/internal/nitro/host/build-extension.d.ts +24 -0
  101. package/dist/src/internal/nitro/host/build-extension.js +4 -0
  102. package/dist/src/internal/nitro/host/configure-nitro-routes.js +2 -2
  103. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  104. package/dist/src/internal/nitro/routes/health.d.ts +3 -3
  105. package/dist/src/internal/workflow/runtime.js +1 -1
  106. package/dist/src/internal/workflow/validate-world.d.ts +16 -0
  107. package/dist/src/internal/workflow/validate-world.js +1 -0
  108. package/dist/src/internal/workflow/world-compatibility.d.ts +1 -12
  109. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/index.js +1 -0
  110. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/parse-name.js +1 -0
  111. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/pluralize.js +1 -0
  112. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/promise.js +1 -0
  113. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/time.js +1 -0
  114. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/workflow-routes.js +1 -0
  115. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.6/node_modules/@workflow/utils/dist/world-target.js +1 -0
  116. package/dist/src/node_modules/.pnpm/ms@2.1.3/node_modules/ms/index.js +1 -0
  117. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  118. package/dist/src/public/channels/slack/action-status.d.ts +19 -0
  119. package/dist/src/public/channels/slack/action-status.js +1 -0
  120. package/dist/src/public/channels/slack/api.js +1 -1
  121. package/dist/src/public/channels/slack/defaults.js +2 -2
  122. package/dist/src/public/channels/slack/index.d.ts +1 -0
  123. package/dist/src/public/channels/slack/index.js +1 -1
  124. package/dist/src/public/channels/slack/mrkdwn.d.ts +0 -2
  125. package/dist/src/public/channels/slack/mrkdwn.js +1 -1
  126. package/dist/src/public/channels/slack/slackChannel.d.ts +1 -1
  127. package/dist/src/public/definitions/extension.d.ts +68 -0
  128. package/dist/src/public/definitions/extension.js +1 -0
  129. package/dist/src/public/extension/index.d.ts +10 -0
  130. package/dist/src/public/extension/index.js +1 -0
  131. package/dist/src/public/next/index.d.ts +9 -9
  132. package/dist/src/public/next/index.js +1 -1
  133. package/dist/src/public/next/vercel-output-config.js +1 -1
  134. package/dist/src/runtime/connections/openapi-client.js +1 -1
  135. package/dist/src/runtime/connections/openapi-spec.js +1 -1
  136. package/dist/src/runtime/resolve-dynamic-skill.js +1 -1
  137. package/dist/src/runtime/resolve-dynamic-tool.js +1 -1
  138. package/dist/src/runtime/types.d.ts +10 -0
  139. package/dist/src/services/dev-client/vercel-auth-error.d.ts +2 -2
  140. package/dist/src/services/dev-client/vercel-auth-error.js +3 -3
  141. package/dist/src/setup/scaffold/create/project.js +4 -4
  142. package/dist/src/svelte/index.js +1 -1
  143. package/dist/src/svelte/use-eve-agent.js +1 -1
  144. package/dist/src/vue/index.js +1 -1
  145. package/dist/src/vue/use-eve-agent.js +1 -1
  146. package/docs/agent-config.md +1 -1
  147. package/docs/channels/custom.mdx +2 -2
  148. package/docs/channels/github.mdx +35 -2
  149. package/docs/channels/linear.mdx +36 -6
  150. package/docs/channels/slack.mdx +5 -3
  151. package/docs/concepts/context-control.md +1 -1
  152. package/docs/concepts/execution-model-and-durability.md +1 -1
  153. package/docs/connections/openapi.mdx +3 -1
  154. package/docs/evals/assertions.mdx +4 -2
  155. package/docs/extensions.md +155 -0
  156. package/docs/guides/client/overview.mdx +1 -1
  157. package/docs/guides/deployment.md +1 -1
  158. package/docs/guides/dev-tui.md +4 -0
  159. package/docs/guides/dynamic-capabilities.md +3 -3
  160. package/docs/guides/frontend/nextjs.mdx +7 -7
  161. package/docs/guides/instrumentation.md +1 -1
  162. package/docs/guides/state.md +3 -3
  163. package/docs/instructions.mdx +1 -1
  164. package/docs/meta.json +1 -0
  165. package/docs/patterns/dynamic-scheduling.md +11 -11
  166. package/docs/patterns/multi-tenant-approvals.md +6 -6
  167. package/docs/patterns/multi-tenant-auth.md +13 -13
  168. package/docs/patterns/multi-tenant-memory.md +9 -9
  169. package/docs/schedules.mdx +1 -1
  170. package/docs/subagents.mdx +2 -0
  171. package/docs/tutorial/guard-the-spend.mdx +2 -2
  172. package/docs/tutorial/query-sample-data.mdx +1 -1
  173. package/docs/tutorial/remember-definitions.mdx +2 -2
  174. package/docs/tutorial/ship-it.mdx +1 -1
  175. package/package.json +12 -5
  176. package/dist/src/compiled/_chunks/workflow/attribute-changes-zAifvEhb.js +0 -59
  177. package/dist/src/compiled/_chunks/workflow/dist-Dxrjttr2.js +0 -3
  178. package/dist/src/compiled/_chunks/workflow/resume-hook-C15uJ2ik.js +0 -1
  179. package/dist/src/compiled/_chunks/workflow/run-BJUPZ0Ni.js +0 -1
  180. package/dist/src/compiled/_chunks/workflow/sleep-C8B-TYir.js +0 -1
  181. package/dist/src/compiled/_chunks/workflow/token-Bm-WLAUB.js +0 -1
  182. package/dist/src/compiled/_chunks/workflow/token-J7YP0s9a.js +0 -1
  183. package/dist/src/internal/workflow/configure-world.d.ts +0 -18
  184. package/dist/src/internal/workflow/configure-world.js +0 -1
@@ -39,6 +39,11 @@ export declare const DISCOVER_HOOKS_DIRECTORY_INVALID = "discover/hooks-director
39
39
  * directory.
40
40
  */
41
41
  export declare const DISCOVER_CHANNELS_DIRECTORY_INVALID = "discover/channels-directory-invalid";
42
+ /**
43
+ * Shared diagnostic emitted when the authored `extensions/` root is not a
44
+ * directory.
45
+ */
46
+ export declare const DISCOVER_EXTENSIONS_DIRECTORY_INVALID = "discover/extensions-directory-invalid";
42
47
  /**
43
48
  * Shared diagnostic emitted when an authored `tools/*.{ts,…}` filename does
44
49
  * not satisfy the model tool-name charset rule.
@@ -70,6 +75,11 @@ export declare const DISCOVER_CHANNEL_NAME_INVALID = "discover/channel-name-inva
70
75
  * directory segment does not satisfy the hook slug charset rule.
71
76
  */
72
77
  export declare const DISCOVER_HOOK_NAME_INVALID = "discover/hook-name-invalid";
78
+ /**
79
+ * Shared diagnostic emitted when an authored `extensions/*.{ts,…}` mount
80
+ * filename does not satisfy the extension namespace charset rule.
81
+ */
82
+ export declare const DISCOVER_EXTENSION_NAME_INVALID = "discover/extension-name-invalid";
73
83
  /**
74
84
  * Tool filename charset. The slug must start with an ASCII letter and may
75
85
  * contain ASCII letters, digits, underscores, and dashes. The 64-character
@@ -98,6 +108,14 @@ export declare const CHANNEL_SLUG_PATTERN: RegExp;
98
108
  * are not allowed — hooks have no URL semantics.
99
109
  */
100
110
  export declare const HOOK_SLUG_PATTERN: RegExp;
111
+ /**
112
+ * Extension mount filename charset. The basename becomes the namespace the
113
+ * consumer's build prefixes onto every contribution (`crm` → `crm__search`),
114
+ * so it uses the same restrictive charset as tool slugs: ASCII letters,
115
+ * digits, underscores, and dashes, starting with a letter, up to 64
116
+ * characters.
117
+ */
118
+ export declare const EXTENSION_SLUG_PATTERN: RegExp;
101
119
  /**
102
120
  * Shared diagnostic emitted when discovery ignores one unsupported directory.
103
121
  */
@@ -182,6 +200,15 @@ export declare function createChannelNameDiagnostic(segment: string, sourcePath:
182
200
  * the runtime never sees a malformed slug.
183
201
  */
184
202
  export declare function createHookNameDiagnostic(segment: string, sourcePath: string): DiscoverDiagnostic | null;
203
+ /**
204
+ * Returns a discovery diagnostic when an extension mount filename violates
205
+ * {@link EXTENSION_SLUG_PATTERN}, or `null` when it satisfies the rule.
206
+ *
207
+ * The mount basename becomes the namespace prefixed onto every contribution
208
+ * the extension composes into the consuming agent, so it must be a legal
209
+ * identifier segment.
210
+ */
211
+ export declare function createExtensionNameDiagnostic(slotName: string, sourcePath: string): DiscoverDiagnostic | null;
185
212
  export { discoverNamedSourceDirectory, type DiscoverNamedSourceDirectoryModuleInput, type DiscoverNamedSourceDirectoryWithMarkdownInput, } from "#discover/named-source-directory.js";
186
213
  /**
187
214
  * Emits shared diagnostics for unsupported root-level directories.
@@ -1 +1 @@
1
- import{join}from"node:path";import{createDiscoverErrorDiagnostic,createDiscoverWarningDiagnostic}from"#discover/diagnostics.js";import{getDirectoryEntryType}from"#discover/filesystem.js";import{createModuleSourceRef}from"#discover/manifest.js";import{collectFlatSlotCandidates}from"#discover/slots.js";import{lowerInstructionsMarkdown}from"#internal/helpers/markdown.js";import{discoverMarkdownSource}from"#discover/markdown.js";import{discoverNamedSourceDirectory,discoverNamedSourceDirectory as discoverNamedSourceDirectory$1}from"#discover/named-source-directory.js";const DISCOVER_MODULE_SLOT_COLLISION=`discover/module-slot-collision`,DISCOVER_REQUIRED_INSTRUCTIONS_MISSING=`discover/required-instructions-missing`,DISCOVER_DEPRECATED_SYSTEM_SLOT=`discover/deprecated-system-slot`,DISCOVER_SLOT_COLLISION=`discover/slot-collision`,DISCOVER_TOOLS_DIRECTORY_INVALID=`discover/tools-directory-invalid`,DISCOVER_HOOKS_DIRECTORY_INVALID=`discover/hooks-directory-invalid`,DISCOVER_CHANNELS_DIRECTORY_INVALID=`discover/channels-directory-invalid`,DISCOVER_TOOL_NAME_INVALID=`discover/tool-name-invalid`,DISCOVER_CONNECTION_NAME_INVALID=`discover/connection-name-invalid`,DISCOVER_SANDBOX_DIRECTORY_INVALID=`discover/sandbox-directory-invalid`,DISCOVER_INSTRUCTIONS_DIRECTORY_INVALID=`discover/instructions-directory-invalid`,DISCOVER_CHANNEL_NAME_INVALID=`discover/channel-name-invalid`,DISCOVER_HOOK_NAME_INVALID=`discover/hook-name-invalid`,TOOL_SLUG_PATTERN=/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/,CONNECTION_SLUG_PATTERN=/^[a-z][a-z0-9-]{0,63}$/,CHANNEL_SLUG_PATTERN=/^(\.?[a-z][a-z0-9-]{0,63}|\[[a-zA-Z][a-zA-Z0-9_]{0,63}\])$/,HOOK_SLUG_PATTERN=/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/,DISCOVER_UNSUPPORTED_DIRECTORY=`discover/unsupported-directory`;async function readSortedDirectoryEntries(e,t){let n=[...await e.readDirectory(t)];return n.sort((e,t)=>e.name.localeCompare(t.name)),n}async function discoverInstructionsSource(r){let i=r.rootEntries.some(e=>e.name===`instructions`&&e.isDirectory()),a=await discoverSlotSource({markdownFileName:`instructions.md`,moduleBaseName:`instructions`,rootEntries:r.rootEntries,rootPath:r.rootPath,slotLabel:`instructions`,source:r.source});if(i){let t=await discoverNamedSourceDirectory$1({allowMarkdown:!0,directoryName:`instructions`,invalidDirectoryCode:DISCOVER_INSTRUCTIONS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(r.rootPath,`instructions`)}" to be a directory of authored instructions.`,markdownLowerer:e=>lowerInstructionsMarkdown(e),recursive:!1,rootEntries:r.rootEntries,rootPath:r.rootPath,source:r.source}),n=[...t.sources];return a.source!==void 0&&n.unshift(a.source),{diagnostics:[...a.diagnostics,...t.diagnostics],instructions:n}}if(a.diagnostics.length>0||a.source!==void 0)return{diagnostics:a.diagnostics,instructions:a.source===void 0?[]:[a.source]};let o=await discoverSlotSource({markdownFileName:`system.md`,moduleBaseName:`system`,rootEntries:r.rootEntries,rootPath:r.rootPath,slotLabel:`system`,source:r.source});if(o.source!==void 0){let t=o.source.sourceKind===`markdown`?`system.md`:o.source.logicalPath;return{diagnostics:[createDiscoverWarningDiagnostic({code:DISCOVER_DEPRECATED_SYSTEM_SLOT,message:`The "${t}" slot is deprecated. Rename it to "${t.replace(/^system/,`instructions`)}" — the runtime still loads the legacy slot for now, but support will be removed in a future release.`,sourcePath:join(r.rootPath,t)}),...o.diagnostics],instructions:[o.source]}}return o.diagnostics.length>0?{diagnostics:o.diagnostics,instructions:[]}:r.required===!1?{diagnostics:[],instructions:[]}:{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_REQUIRED_INSTRUCTIONS_MISSING,message:`Expected authored instructions at "instructions.md", "instructions.ts", "instructions.cts", "instructions.mts", "instructions.js", "instructions.cjs", "instructions.mjs", or "instructions/" directory.`,sourcePath:r.rootPath})],instructions:[]}}async function discoverSlotSource(t){let n=collectFlatSlotCandidates(t.rootEntries,{markdownFileName:t.markdownFileName,moduleBaseName:t.moduleBaseName});if(n.markdownFileName!==void 0&&n.moduleFileNames.length>0)return{diagnostics:[createSlotCollisionDiagnostic(t.rootPath,t.slotLabel,[n.markdownFileName,...n.moduleFileNames])]};if(n.moduleFileNames.length>1)return{diagnostics:[createModuleSlotCollisionDiagnostic(t.rootPath,t.slotLabel,n.moduleFileNames)]};if(n.markdownFileName!==void 0)return{diagnostics:[],source:await discoverMarkdownSource({logicalPath:t.markdownFileName,lower:lowerInstructionsMarkdown,source:t.source,sourcePath:join(t.rootPath,n.markdownFileName)})};let[r]=n.moduleFileNames;return r===void 0?{diagnostics:[]}:{diagnostics:[],source:createModuleSourceRef({logicalPath:r})}}function discoverFlatModuleSource(e){let n=collectFlatSlotCandidates(e.rootEntries,{moduleBaseName:e.slotName});if(n.moduleFileNames.length>1)return{diagnostics:[createModuleSlotCollisionDiagnostic(e.rootPath,e.slotName,n.moduleFileNames)]};let[r]=n.moduleFileNames;return r===void 0?e.missingDiagnostic===void 0?{diagnostics:[]}:{diagnostics:[createDiscoverErrorDiagnostic({code:e.missingDiagnostic.code,message:e.missingDiagnostic.message,sourcePath:e.rootPath})]}:{diagnostics:[],module:createModuleSourceRef({logicalPath:r})}}function createToolNameDiagnostic(e,n){return TOOL_SLUG_PATTERN.test(e)?null:createDiscoverErrorDiagnostic({code:DISCOVER_TOOL_NAME_INVALID,message:`Tool filename "${e}" is not a legal tool name. Expected ASCII letters, digits, underscores, and dashes only, starting with a letter, up to 64 characters.`,sourcePath:n})}function createConnectionNameDiagnostic(e,n){return CONNECTION_SLUG_PATTERN.test(e)?null:createDiscoverErrorDiagnostic({code:DISCOVER_CONNECTION_NAME_INVALID,message:`Connection filename "${e}" is not a legal connection name. Expected lowercase ASCII letters, digits, and dashes only, starting with a letter, up to 64 characters.`,sourcePath:n})}function createChannelNameDiagnostic(e,n){return CHANNEL_SLUG_PATTERN.test(e)?null:createDiscoverErrorDiagnostic({code:DISCOVER_CHANNEL_NAME_INVALID,message:`Channel path segment "${e}" is not a legal channel name. Expected lowercase kebab-case (\`my-channel\`), optionally with a leading dot (\`.well-known\`), or a path parameter form (\`[sessionId]\`).`,sourcePath:n})}function createHookNameDiagnostic(e,n){return HOOK_SLUG_PATTERN.test(e)?null:createDiscoverErrorDiagnostic({code:DISCOVER_HOOK_NAME_INVALID,message:`Hook path segment "${e}" is not a legal hook name. Expected ASCII letters, digits, underscores, and dashes only, starting with a letter, up to 64 characters.`,sourcePath:n})}function createUnsupportedRootDirectoryDiagnostics(t){return t.rootEntries.flatMap(i=>!i.isDirectory()||t.classifyEntry(i.name,getDirectoryEntryType(i))!==`unknown`?[]:[createDiscoverWarningDiagnostic({code:DISCOVER_UNSUPPORTED_DIRECTORY,message:t.createUnsupportedDirectoryMessage(i.name),sourcePath:join(t.rootPath,i.name)})])}function createSlotCollisionDiagnostic(e,n,r){return createDiscoverErrorDiagnostic({code:DISCOVER_SLOT_COLLISION,message:`Found conflicting authored sources for "${n}": ${formatQuotedFileList(r)}.`,sourcePath:e})}function createModuleSlotCollisionDiagnostic(e,n,r){return createDiscoverErrorDiagnostic({code:DISCOVER_MODULE_SLOT_COLLISION,message:`Found multiple authored module sources for "${n}": ${formatQuotedFileList(r)}.`,sourcePath:e})}function formatQuotedFileList(e){return e.map(e=>`"${e}"`).join(`, `)}export{CHANNEL_SLUG_PATTERN,CONNECTION_SLUG_PATTERN,DISCOVER_CHANNELS_DIRECTORY_INVALID,DISCOVER_CHANNEL_NAME_INVALID,DISCOVER_CONNECTION_NAME_INVALID,DISCOVER_DEPRECATED_SYSTEM_SLOT,DISCOVER_HOOKS_DIRECTORY_INVALID,DISCOVER_HOOK_NAME_INVALID,DISCOVER_INSTRUCTIONS_DIRECTORY_INVALID,DISCOVER_MODULE_SLOT_COLLISION,DISCOVER_REQUIRED_INSTRUCTIONS_MISSING,DISCOVER_SANDBOX_DIRECTORY_INVALID,DISCOVER_SLOT_COLLISION,DISCOVER_TOOLS_DIRECTORY_INVALID,DISCOVER_TOOL_NAME_INVALID,DISCOVER_UNSUPPORTED_DIRECTORY,HOOK_SLUG_PATTERN,TOOL_SLUG_PATTERN,createChannelNameDiagnostic,createConnectionNameDiagnostic,createHookNameDiagnostic,createModuleSlotCollisionDiagnostic,createSlotCollisionDiagnostic,createToolNameDiagnostic,createUnsupportedRootDirectoryDiagnostics,discoverFlatModuleSource,discoverInstructionsSource,discoverNamedSourceDirectory,readSortedDirectoryEntries};
1
+ import{join}from"node:path";import{createDiscoverErrorDiagnostic,createDiscoverWarningDiagnostic}from"#discover/diagnostics.js";import{getDirectoryEntryType}from"#discover/filesystem.js";import{createModuleSourceRef}from"#discover/manifest.js";import{collectFlatSlotCandidates}from"#discover/slots.js";import{lowerInstructionsMarkdown}from"#internal/helpers/markdown.js";import{discoverMarkdownSource}from"#discover/markdown.js";import{discoverNamedSourceDirectory,discoverNamedSourceDirectory as discoverNamedSourceDirectory$1}from"#discover/named-source-directory.js";const DISCOVER_MODULE_SLOT_COLLISION=`discover/module-slot-collision`,DISCOVER_REQUIRED_INSTRUCTIONS_MISSING=`discover/required-instructions-missing`,DISCOVER_DEPRECATED_SYSTEM_SLOT=`discover/deprecated-system-slot`,DISCOVER_SLOT_COLLISION=`discover/slot-collision`,DISCOVER_TOOLS_DIRECTORY_INVALID=`discover/tools-directory-invalid`,DISCOVER_HOOKS_DIRECTORY_INVALID=`discover/hooks-directory-invalid`,DISCOVER_CHANNELS_DIRECTORY_INVALID=`discover/channels-directory-invalid`,DISCOVER_EXTENSIONS_DIRECTORY_INVALID=`discover/extensions-directory-invalid`,DISCOVER_TOOL_NAME_INVALID=`discover/tool-name-invalid`,DISCOVER_CONNECTION_NAME_INVALID=`discover/connection-name-invalid`,DISCOVER_SANDBOX_DIRECTORY_INVALID=`discover/sandbox-directory-invalid`,DISCOVER_INSTRUCTIONS_DIRECTORY_INVALID=`discover/instructions-directory-invalid`,DISCOVER_CHANNEL_NAME_INVALID=`discover/channel-name-invalid`,DISCOVER_HOOK_NAME_INVALID=`discover/hook-name-invalid`,DISCOVER_EXTENSION_NAME_INVALID=`discover/extension-name-invalid`,TOOL_SLUG_PATTERN=/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/,CONNECTION_SLUG_PATTERN=/^[a-z][a-z0-9-]{0,63}$/,CHANNEL_SLUG_PATTERN=/^(\.?[a-z][a-z0-9-]{0,63}|\[[a-zA-Z][a-zA-Z0-9_]{0,63}\])$/,HOOK_SLUG_PATTERN=/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/,EXTENSION_SLUG_PATTERN=/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/,DISCOVER_UNSUPPORTED_DIRECTORY=`discover/unsupported-directory`;async function readSortedDirectoryEntries(e,t){let n=[...await e.readDirectory(t)];return n.sort((e,t)=>e.name.localeCompare(t.name)),n}async function discoverInstructionsSource(r){let i=r.rootEntries.some(e=>e.name===`instructions`&&e.isDirectory()),a=await discoverSlotSource({markdownFileName:`instructions.md`,moduleBaseName:`instructions`,rootEntries:r.rootEntries,rootPath:r.rootPath,slotLabel:`instructions`,source:r.source});if(i){let t=await discoverNamedSourceDirectory$1({allowMarkdown:!0,directoryName:`instructions`,invalidDirectoryCode:DISCOVER_INSTRUCTIONS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(r.rootPath,`instructions`)}" to be a directory of authored instructions.`,markdownLowerer:e=>lowerInstructionsMarkdown(e),recursive:!1,rootEntries:r.rootEntries,rootPath:r.rootPath,source:r.source}),n=[...t.sources];return a.source!==void 0&&n.unshift(a.source),{diagnostics:[...a.diagnostics,...t.diagnostics],instructions:n}}if(a.diagnostics.length>0||a.source!==void 0)return{diagnostics:a.diagnostics,instructions:a.source===void 0?[]:[a.source]};let o=await discoverSlotSource({markdownFileName:`system.md`,moduleBaseName:`system`,rootEntries:r.rootEntries,rootPath:r.rootPath,slotLabel:`system`,source:r.source});if(o.source!==void 0){let t=o.source.sourceKind===`markdown`?`system.md`:o.source.logicalPath;return{diagnostics:[createDiscoverWarningDiagnostic({code:DISCOVER_DEPRECATED_SYSTEM_SLOT,message:`The "${t}" slot is deprecated. Rename it to "${t.replace(/^system/,`instructions`)}" — the runtime still loads the legacy slot for now, but support will be removed in a future release.`,sourcePath:join(r.rootPath,t)}),...o.diagnostics],instructions:[o.source]}}return o.diagnostics.length>0?{diagnostics:o.diagnostics,instructions:[]}:r.required===!1?{diagnostics:[],instructions:[]}:{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_REQUIRED_INSTRUCTIONS_MISSING,message:`Expected authored instructions at "instructions.md", "instructions.ts", "instructions.cts", "instructions.mts", "instructions.js", "instructions.cjs", "instructions.mjs", or "instructions/" directory.`,sourcePath:r.rootPath})],instructions:[]}}async function discoverSlotSource(t){let n=collectFlatSlotCandidates(t.rootEntries,{markdownFileName:t.markdownFileName,moduleBaseName:t.moduleBaseName});if(n.markdownFileName!==void 0&&n.moduleFileNames.length>0)return{diagnostics:[createSlotCollisionDiagnostic(t.rootPath,t.slotLabel,[n.markdownFileName,...n.moduleFileNames])]};if(n.moduleFileNames.length>1)return{diagnostics:[createModuleSlotCollisionDiagnostic(t.rootPath,t.slotLabel,n.moduleFileNames)]};if(n.markdownFileName!==void 0)return{diagnostics:[],source:await discoverMarkdownSource({logicalPath:t.markdownFileName,lower:lowerInstructionsMarkdown,source:t.source,sourcePath:join(t.rootPath,n.markdownFileName)})};let[r]=n.moduleFileNames;return r===void 0?{diagnostics:[]}:{diagnostics:[],source:createModuleSourceRef({logicalPath:r})}}function discoverFlatModuleSource(e){let n=collectFlatSlotCandidates(e.rootEntries,{moduleBaseName:e.slotName});if(n.moduleFileNames.length>1)return{diagnostics:[createModuleSlotCollisionDiagnostic(e.rootPath,e.slotName,n.moduleFileNames)]};let[r]=n.moduleFileNames;return r===void 0?e.missingDiagnostic===void 0?{diagnostics:[]}:{diagnostics:[createDiscoverErrorDiagnostic({code:e.missingDiagnostic.code,message:e.missingDiagnostic.message,sourcePath:e.rootPath})]}:{diagnostics:[],module:createModuleSourceRef({logicalPath:r})}}function createToolNameDiagnostic(e,n){return TOOL_SLUG_PATTERN.test(e)?null:createDiscoverErrorDiagnostic({code:DISCOVER_TOOL_NAME_INVALID,message:`Tool filename "${e}" is not a legal tool name. Expected ASCII letters, digits, underscores, and dashes only, starting with a letter, up to 64 characters.`,sourcePath:n})}function createConnectionNameDiagnostic(e,n){return CONNECTION_SLUG_PATTERN.test(e)?null:createDiscoverErrorDiagnostic({code:DISCOVER_CONNECTION_NAME_INVALID,message:`Connection filename "${e}" is not a legal connection name. Expected lowercase ASCII letters, digits, and dashes only, starting with a letter, up to 64 characters.`,sourcePath:n})}function createChannelNameDiagnostic(e,n){return CHANNEL_SLUG_PATTERN.test(e)?null:createDiscoverErrorDiagnostic({code:DISCOVER_CHANNEL_NAME_INVALID,message:`Channel path segment "${e}" is not a legal channel name. Expected lowercase kebab-case (\`my-channel\`), optionally with a leading dot (\`.well-known\`), or a path parameter form (\`[sessionId]\`).`,sourcePath:n})}function createHookNameDiagnostic(e,n){return HOOK_SLUG_PATTERN.test(e)?null:createDiscoverErrorDiagnostic({code:DISCOVER_HOOK_NAME_INVALID,message:`Hook path segment "${e}" is not a legal hook name. Expected ASCII letters, digits, underscores, and dashes only, starting with a letter, up to 64 characters.`,sourcePath:n})}function createExtensionNameDiagnostic(e,n){return EXTENSION_SLUG_PATTERN.test(e)?null:createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_NAME_INVALID,message:`Extension mount filename "${e}" is not a legal extension namespace. Expected ASCII letters, digits, underscores, and dashes only, starting with a letter, up to 64 characters.`,sourcePath:n})}function createUnsupportedRootDirectoryDiagnostics(t){return t.rootEntries.flatMap(i=>!i.isDirectory()||t.classifyEntry(i.name,getDirectoryEntryType(i))!==`unknown`?[]:[createDiscoverWarningDiagnostic({code:DISCOVER_UNSUPPORTED_DIRECTORY,message:t.createUnsupportedDirectoryMessage(i.name),sourcePath:join(t.rootPath,i.name)})])}function createSlotCollisionDiagnostic(e,n,r){return createDiscoverErrorDiagnostic({code:DISCOVER_SLOT_COLLISION,message:`Found conflicting authored sources for "${n}": ${formatQuotedFileList(r)}.`,sourcePath:e})}function createModuleSlotCollisionDiagnostic(e,n,r){return createDiscoverErrorDiagnostic({code:DISCOVER_MODULE_SLOT_COLLISION,message:`Found multiple authored module sources for "${n}": ${formatQuotedFileList(r)}.`,sourcePath:e})}function formatQuotedFileList(e){return e.map(e=>`"${e}"`).join(`, `)}export{CHANNEL_SLUG_PATTERN,CONNECTION_SLUG_PATTERN,DISCOVER_CHANNELS_DIRECTORY_INVALID,DISCOVER_CHANNEL_NAME_INVALID,DISCOVER_CONNECTION_NAME_INVALID,DISCOVER_DEPRECATED_SYSTEM_SLOT,DISCOVER_EXTENSIONS_DIRECTORY_INVALID,DISCOVER_EXTENSION_NAME_INVALID,DISCOVER_HOOKS_DIRECTORY_INVALID,DISCOVER_HOOK_NAME_INVALID,DISCOVER_INSTRUCTIONS_DIRECTORY_INVALID,DISCOVER_MODULE_SLOT_COLLISION,DISCOVER_REQUIRED_INSTRUCTIONS_MISSING,DISCOVER_SANDBOX_DIRECTORY_INVALID,DISCOVER_SLOT_COLLISION,DISCOVER_TOOLS_DIRECTORY_INVALID,DISCOVER_TOOL_NAME_INVALID,DISCOVER_UNSUPPORTED_DIRECTORY,EXTENSION_SLUG_PATTERN,HOOK_SLUG_PATTERN,TOOL_SLUG_PATTERN,createChannelNameDiagnostic,createConnectionNameDiagnostic,createExtensionNameDiagnostic,createHookNameDiagnostic,createModuleSlotCollisionDiagnostic,createSlotCollisionDiagnostic,createToolNameDiagnostic,createUnsupportedRootDirectoryDiagnostics,discoverFlatModuleSource,discoverInstructionsSource,discoverNamedSourceDirectory,readSortedDirectoryEntries};
@@ -106,6 +106,38 @@ export interface SandboxWorkspaceFolderSourceRef {
106
106
  * Package-local helper module preserved by the discovery manifest.
107
107
  */
108
108
  export type LibSourceRef = ModuleSourceRef;
109
+ /**
110
+ * Extension mount source reference preserved by the discovery manifest. Each
111
+ * `agent/extensions/*.ts` file re-exports (and configures) an extension
112
+ * package; the file basename is the mount namespace.
113
+ */
114
+ export type ExtensionSourceRef = ModuleSourceRef;
115
+ /**
116
+ * A mounted extension resolved to its package and discovered agent-shaped
117
+ * source tree. The compiler composes each mount's {@link manifest} into the
118
+ * consuming agent, prefixing contributions with {@link namespace}.
119
+ */
120
+ export interface ResolvedExtensionMount {
121
+ /** Mount namespace derived from the mount filename (e.g. `crm`). */
122
+ readonly namespace: string;
123
+ /** Package specifier the mount imports (e.g. `@acme/crm`). */
124
+ readonly specifier: string;
125
+ /** Package name from the resolved package.json, used to scope state. */
126
+ readonly packageName: string;
127
+ /** Absolute path to the resolved package root. */
128
+ readonly packageRoot: string;
129
+ /** Absolute path to the extension's agent-shaped source root. */
130
+ readonly sourceRoot: string;
131
+ /** Discovered agent-shaped source manifest for the extension. */
132
+ readonly manifest: AgentSourceManifest;
133
+ /**
134
+ * Consumer-authored overrides discovered in the mount directory form
135
+ * (`extensions/<ns>/{tools,connections,…}/`). Composed under the same
136
+ * `<ns>__` namespace as the extension's own contributions but winning on
137
+ * name collision. Absent for the flat file mount form.
138
+ */
139
+ readonly overrides?: AgentSourceManifest;
140
+ }
109
141
  /**
110
142
  * Subagent source reference preserved by the discovery manifest.
111
143
  */
@@ -127,6 +159,18 @@ export interface AgentSourceManifest {
127
159
  connections: ConnectionSourceRef[];
128
160
  configModule?: ModuleSourceRef;
129
161
  diagnosticsSummary: DiscoverDiagnosticsSummary;
162
+ /**
163
+ * Mounted extension source references discovered under `agent/extensions/`.
164
+ * Each entry's logical-path basename is the mount namespace the compiler
165
+ * prefixes onto the extension's composed contributions.
166
+ */
167
+ extensions: ExtensionSourceRef[];
168
+ /**
169
+ * Mounted extensions resolved to their packages and discovered source trees.
170
+ * Populated only for the agent root; extension trees do not mount further
171
+ * extensions (transitive mounting is a non-goal).
172
+ */
173
+ resolvedExtensions: ResolvedExtensionMount[];
130
174
  hooks: ModuleSourceRef[];
131
175
  lib: LibSourceRef[];
132
176
  kind: typeof AGENT_SOURCE_MANIFEST_KIND;
@@ -170,6 +214,8 @@ export interface CreateAgentSourceManifestInput {
170
214
  connections?: readonly ConnectionSourceRef[];
171
215
  configModule?: ModuleSourceRef;
172
216
  diagnostics?: readonly DiscoverDiagnostic[];
217
+ extensions?: readonly ExtensionSourceRef[];
218
+ resolvedExtensions?: readonly ResolvedExtensionMount[];
173
219
  hooks?: readonly ModuleSourceRef[];
174
220
  lib?: readonly LibSourceRef[];
175
221
  /**
@@ -1 +1 @@
1
- import{basename,relative,resolve}from"node:path";import{summarizeDiscoverDiagnostics}from"#discover/diagnostics.js";import{normalizeLogicalPath}from"#discover/filesystem.js";const AGENT_SOURCE_MANIFEST_KIND=`eve-agent-discovery-manifest`,AGENT_SOURCE_MANIFEST_VERSION=12;function createAgentSourceManifest(e){let t=resolve(e.appRoot),i=resolve(e.agentRoot),o={agentId:e.agentId??deriveAgentIdFromRoots(t,i,e.packageName),agentRoot:i,appRoot:t,channels:[...e.channels??[]],connections:[...e.connections??[]],diagnosticsSummary:summarizeDiscoverDiagnostics(e.diagnostics??[]),hooks:[...e.hooks??[]],instructions:[...e.instructions??[]],lib:[...e.lib??[]],kind:AGENT_SOURCE_MANIFEST_KIND,sandbox:e.sandbox??null,sandboxWorkspaces:[...e.sandboxWorkspaces??[]],schedules:[...e.schedules??[]],skills:[...e.skills??[]],tools:[...e.tools??[]],version:12,subagents:[...e.subagents??[]]};return e.configModule!==void 0&&(o.configModule=e.configModule),o}function deriveAgentIdFromRoots(n,r,a){let o=normalizeLogicalPath(relative(n,r));return o===``||o===`.`||o===`agent`?a??basename(n):basename(r)}function createPathDerivedSourceId(e){return normalizeLogicalPath(e)}function createModuleSourceRef(e){let t=normalizeLogicalPath(e.logicalPath),n={sourceKind:`module`,logicalPath:t,sourceId:e.sourceId??createPathDerivedSourceId(t)};return e.exportName!==void 0&&(n.exportName=e.exportName),n}function createConnectionSourceRef(e){return{...createModuleSourceRef(e),connectionName:e.connectionName}}function createLocalSubagentSourceRef(e){let t=normalizeLogicalPath(e.logicalPath);return{entryPath:e.entryPath,logicalPath:t,manifest:e.manifest,rootPath:e.rootPath,sourceId:e.sourceId??createPathDerivedSourceId(t),subagentId:e.subagentId}}function createSkillPackageSourceRef(e){return{assetsPath:e.assetsPath,description:e.description,license:e.license,logicalPath:normalizeLogicalPath(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,skillFilePath:e.skillFilePath,skillId:e.skillId,sourceId:e.sourceId,sourceKind:`skill-package`}}export{AGENT_SOURCE_MANIFEST_KIND,AGENT_SOURCE_MANIFEST_VERSION,createAgentSourceManifest,createConnectionSourceRef,createLocalSubagentSourceRef,createModuleSourceRef,createPathDerivedSourceId,createSkillPackageSourceRef,deriveAgentIdFromRoots};
1
+ import{basename,relative,resolve}from"node:path";import{summarizeDiscoverDiagnostics}from"#discover/diagnostics.js";import{normalizeLogicalPath}from"#discover/filesystem.js";const AGENT_SOURCE_MANIFEST_KIND=`eve-agent-discovery-manifest`,AGENT_SOURCE_MANIFEST_VERSION=12;function createAgentSourceManifest(e){let t=resolve(e.appRoot),i=resolve(e.agentRoot),o={agentId:e.agentId??deriveAgentIdFromRoots(t,i,e.packageName),agentRoot:i,appRoot:t,channels:[...e.channels??[]],connections:[...e.connections??[]],diagnosticsSummary:summarizeDiscoverDiagnostics(e.diagnostics??[]),extensions:[...e.extensions??[]],resolvedExtensions:[...e.resolvedExtensions??[]],hooks:[...e.hooks??[]],instructions:[...e.instructions??[]],lib:[...e.lib??[]],kind:AGENT_SOURCE_MANIFEST_KIND,sandbox:e.sandbox??null,sandboxWorkspaces:[...e.sandboxWorkspaces??[]],schedules:[...e.schedules??[]],skills:[...e.skills??[]],tools:[...e.tools??[]],version:12,subagents:[...e.subagents??[]]};return e.configModule!==void 0&&(o.configModule=e.configModule),o}function deriveAgentIdFromRoots(n,r,a){let o=normalizeLogicalPath(relative(n,r));return o===``||o===`.`||o===`agent`?a??basename(n):basename(r)}function createPathDerivedSourceId(e){return normalizeLogicalPath(e)}function createModuleSourceRef(e){let t=normalizeLogicalPath(e.logicalPath),n={sourceKind:`module`,logicalPath:t,sourceId:e.sourceId??createPathDerivedSourceId(t)};return e.exportName!==void 0&&(n.exportName=e.exportName),n}function createConnectionSourceRef(e){return{...createModuleSourceRef(e),connectionName:e.connectionName}}function createLocalSubagentSourceRef(e){let t=normalizeLogicalPath(e.logicalPath);return{entryPath:e.entryPath,logicalPath:t,manifest:e.manifest,rootPath:e.rootPath,sourceId:e.sourceId??createPathDerivedSourceId(t),subagentId:e.subagentId}}function createSkillPackageSourceRef(e){return{assetsPath:e.assetsPath,description:e.description,license:e.license,logicalPath:normalizeLogicalPath(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,skillFilePath:e.skillFilePath,skillId:e.skillId,sourceId:e.sourceId,sourceKind:`skill-package`}}export{AGENT_SOURCE_MANIFEST_KIND,AGENT_SOURCE_MANIFEST_VERSION,createAgentSourceManifest,createConnectionSourceRef,createLocalSubagentSourceRef,createModuleSourceRef,createPathDerivedSourceId,createSkillPackageSourceRef,deriveAgentIdFromRoots};
@@ -27,7 +27,8 @@ export declare function messageIncludes(token: string | RegExp): RunAssertion;
27
27
  /**
28
28
  * Asserts a completed tool call with `name` happened. Options constrain the
29
29
  * call further: `input` partial-deep-matches, `output` matches the result,
30
- * `status` overrides the lifecycle state, and `count` requires an exact count.
30
+ * `status` overrides the lifecycle state, and `count` constrains the number of
31
+ * matches with either an exact number or a predicate.
31
32
  */
32
33
  export declare function calledTool(name: string, options?: EveEvalToolCallMatchOptions): RunAssertion;
33
34
  /**
@@ -68,7 +69,7 @@ export declare function calledSubagent(name: string, options?: EveEvalSubagentCa
68
69
  * stream. `label` names the assertion in reports.
69
70
  */
70
71
  export declare function eventsSatisfy(label: string, predicate: (events: readonly HandleMessageStreamEvent[]) => boolean): RunAssertion;
71
- /** Asserts a typed stream event exists, optionally with an exact count. */
72
+ /** Asserts a typed stream event exists, optionally constraining its count. */
72
73
  export declare function typedEvent(matcher: EveEvalEventMatch): RunAssertion;
73
74
  /** Asserts no typed stream event matches. */
74
75
  export declare function notEvent(matcher: EveEvalEventMatch): RunAssertion;
@@ -1,2 +1,2 @@
1
- import{deepEquals,eventMatches,subagentCallMatches,testRegExp,toolCallMatches}from"#evals/match.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";const PASS={score:1},fail=(e,t)=>({score:0,message:e,metadata:t});function succeeded(){return{name:`succeeded`,evaluate(e){let t=runFailure(e);return t===void 0?e.derived.parked?fail(`run parked on ${e.derived.inputRequests.length} unanswered input request(s)`):PASS:t}}}function parked(){return{name:`parked`,evaluate(e){let t=runFailure(e);return t===void 0?e.derived.parked?PASS:fail(`expected the run to park on HITL input; it ended "${e.status}" with no pending requests`):t}}}function messageIncludes(e){return{name:`messageIncludes(${String(e)})`,evaluate(t){let n=joinCompletedMessages(t.events);return(typeof e==`string`?n.includes(e):testRegExp(e,n))?PASS:fail(`assistant messages did not include ${String(e)}; got: ${truncate(n)}`)}}}function calledTool(e,t={}){return validateCount(t.count),{name:`calledTool(${e})`,evaluate(n){let r=n.derived.toolCalls.filter(t=>t.name===e),a=r.filter(e=>toolCallMatches(e,t));if(t.count===void 0?a.length>0:a.length===t.count)return{score:1,metadata:{matchingCalls:a.length}};let o=r.length>0?`observed ${e} calls: ${r.map(e=>truncate(JSON.stringify(e.input))).join(`, `)}`:`observed tools: [${n.derived.toolCalls.map(e=>e.name).join(`, `)}]`;return fail(`${t.count===void 0?`expected a matching call to "${e}"`:`expected exactly ${t.count} matching call(s), found ${a.length}`}; ${o}`)}}}function loadedSkill(e,t={}){return{...calledTool(LOAD_SKILL_TOOL_NAME,{...t,input:{skill:e}}),name:`loadedSkill(${e})`}}function notCalledTool(e){return{name:`notCalledTool(${e})`,evaluate(t){let n=t.derived.toolCalls.filter(t=>t.name===e).length;return n===0?PASS:fail(`"${e}" was called ${n} time(s)`)}}}function toolOrder(e){return{name:`toolOrder(${e.join(` → `)})`,evaluate(t){let n=requestedTools(t.events).map(e=>e.name),r=missingOrderedName(e,n);return r===void 0?PASS:fail(`missing "${r.name}" after [${e.slice(0,r.cursor).join(`, `)}]; observed request order: [${n.join(`, `)}]`)}}}function usedNoTools(){return{name:`usedNoTools`,evaluate(e){let t=e.derived.toolCallCount;return t===0?PASS:fail(`expected no tool calls, got ${t}`,{toolCallCount:t})}}}function maxToolCalls(e){return validateCount(e),{name:`maxToolCalls(${e})`,evaluate(t){let n=t.derived.toolCallCount;return n<=e?PASS:fail(`expected at most ${e} tool calls, got ${n}`,{maxAllowed:e,toolCallCount:n})}}}function noFailedActions(){return{name:`noFailedActions`,evaluate(e){let t=e.events.filter(e=>e.type===`action.result`&&(e.data.status===`failed`||e.data.result.isError===!0));if(t.length===0)return PASS;let n=t.map(formatFailedActionResult);return fail(`${t.length} failed action(s): ${n.join(`; `)}`,{failedActions:t.map(e=>({callId:e.data.result.callId,error:e.data.error,kind:e.data.result.kind,output:e.data.result.output,status:e.data.status}))})}}}function calledSubagent(e,t={}){return validateCount(t.count),{name:`calledSubagent(${e})`,evaluate(r){let i=r.derived.subagentCalls.filter(t=>t.name===e),a=i.filter(e=>subagentCallMatches(e,t));return(t.count===void 0?a.length>0:a.length===t.count)?{score:1,metadata:{matchingCalls:a.length}}:i.length===0?fail(`subagent "${e}" was never called; observed: [${r.derived.subagentCalls.map(e=>e.name).join(`, `)}]`,{observedSubagentCalls:r.derived.subagentCalls}):fail(`subagent "${e}" was called but ${a.length} call(s) matched the constraints`,{observedSubagentCalls:i})}}}function eventsSatisfy(e,t){return{name:`eventsSatisfy(${e})`,evaluate(n){return t(n.events)?PASS:fail(`event predicate "${e}" did not hold`)}}}function typedEvent(e){return validateCount(e.count),{name:`event(${e.type})`,evaluate(n){let r=n.events.filter(n=>eventMatches(n,e));return(e.count===void 0?r.length>0:r.length===e.count)?{score:1,metadata:{matchingEvents:r.length}}:fail(`expected ${e.count===void 0?`at least one`:`exactly ${e.count}`} matching ${e.type} event(s), found ${r.length}; observed: [${n.events.map(e=>e.type).join(`, `)}]`)}}}function notEvent(e){return{name:`notEvent(${e.type})`,evaluate(n){let r=n.events.filter(n=>eventMatches(n,e));return r.length===0?PASS:fail(`expected no matching ${e.type} events, found ${r.length}`)}}}function eventOrder(e){for(let t of e)validateCount(t.count);return{name:`eventOrder(${e.map(e=>e.type).join(` → `)})`,evaluate(n){let r=-1;for(let i of e){let e=n.events.flatMap((e,n)=>eventMatches(e,i)?[n]:[]);if(!(i.count===void 0?e.length>0:e.length===i.count))return fail(`expected ${i.count===void 0?`at least one`:`exactly ${i.count}`} matching ${i.type} event(s), found ${e.length}`);let a=e[0];if(a===void 0||a<=r)return fail(`event group ${i.type} did not occur after the previous group`);r=e[e.length-1]??r}return PASS}}}function outputEquals(t){return{name:`outputEquals`,evaluate(n){return deepEquals(n.output,t)?PASS:fail(`output ${truncate(JSON.stringify(n.output))} does not equal expected ${truncate(JSON.stringify(t))}`)}}}function outputMatches(e){return{name:`outputMatches`,async evaluate(t){let n=await e[`~standard`].validate(t.output);return!(`issues`in n)||n.issues===void 0?PASS:fail(`output failed schema validation: ${n.issues.map(e=>e.message).join(`; `)}`)}}}function joinCompletedMessages(e){let t=[];for(let n of e)n.type===`message.completed`&&n.data.message!==null&&t.push(n.data.message);return t.join(`
2
- `)}function failureDetail(e,t){return t===void 0?e:`${e} (code: ${t})`}function formatFailedActionResult(e){let{result:t,status:n}=e.data;return[actionResultLabel(t),`callId=${t.callId}`,`status=${n}`,t.isError===!0?`isError=true`:void 0,e.data.error?.message===void 0?void 0:`error=${e.data.error.message}`,`output=${truncate(formatUnknown(t.output))}`].filter(e=>e!==void 0).join(` `)}function actionResultLabel(e){switch(e.kind){case`tool-result`:return`tool-result:${e.toolName}`;case`subagent-result`:return`subagent-result:${e.subagentName}`;case`load-skill-result`:return e.name===void 0?`load-skill-result`:`load-skill-result:${e.name}`}}function runFailure(e){if(e.status===`failed`)return fail(failureDetail(`run failed`,e.derived.failureCode));let t=e.events.find(e=>e.type===`turn.failed`||e.type===`step.failed`);return t===void 0?void 0:fail(`${t.type} (${t.data.code}): ${t.data.message}`)}function truncate(e,t=200){return e===void 0?`undefined`:e.length<=t?e:`${e.slice(0,t)}…`}function formatUnknown(e){if(e!==void 0){if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}}function validateCount(e){if(e!==void 0&&(!Number.isInteger(e)||e<0))throw TypeError(`Assertion count must be a non-negative integer; received ${e}.`)}function missingOrderedName(e,t){let n=0;for(let r of t)if(r===e[n]&&(n+=1),n===e.length)return;let r=e[n];return r===void 0?void 0:{cursor:n,name:r}}function requestedTools(e){let t=[],n=new Set,append=(e,r)=>{n.has(e)||(n.add(e),t.push({callId:e,name:r}))};for(let t of e)if(t.type===`actions.requested`)for(let e of t.data.actions)e.kind===`tool-call`&&append(e.callId,e.toolName);else if(t.type===`input.requested`)for(let e of t.data.requests){let{action:t}=e;t.kind===`tool-call`&&append(t.callId,t.toolName)}return t}export{calledSubagent,calledTool,eventOrder,eventsSatisfy,loadedSkill,maxToolCalls,messageIncludes,noFailedActions,notCalledTool,notEvent,outputEquals,outputMatches,parked,succeeded,toolOrder,typedEvent,usedNoTools};
1
+ import{deepEquals,eventMatches,subagentCallMatches,testRegExp,toolCallMatches}from"#evals/match.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";const PASS={score:1},fail=(e,t)=>({score:0,message:e,metadata:t});function succeeded(){return{name:`succeeded`,evaluate(e){let t=runFailure(e);return t===void 0?e.derived.parked?fail(`run parked on ${e.derived.inputRequests.length} unanswered input request(s)`):PASS:t}}}function parked(){return{name:`parked`,evaluate(e){let t=runFailure(e);return t===void 0?e.derived.parked?PASS:fail(`expected the run to park on HITL input; it ended "${e.status}" with no pending requests`):t}}}function messageIncludes(e){return{name:`messageIncludes(${String(e)})`,evaluate(t){let n=joinCompletedMessages(t.events);return(typeof e==`string`?n.includes(e):testRegExp(e,n))?PASS:fail(`assistant messages did not include ${String(e)}; got: ${truncate(n)}`)}}}function calledTool(e,t={}){return validateCount(t.count),{name:`calledTool(${e})`,evaluate(n){let r=n.derived.toolCalls.filter(t=>t.name===e),a=r.filter(e=>toolCallMatches(e,t));if(matchesCount(t.count,a.length))return{score:1,metadata:{matchingCalls:a.length}};let o=r.length>0?`observed ${e} calls: ${r.map(e=>truncate(JSON.stringify(e.input))).join(`, `)}`:`observed tools: [${n.derived.toolCalls.map(e=>e.name).join(`, `)}]`,s;return s=t.count===void 0?`expected a matching call to "${e}"`:typeof t.count==`number`?`expected exactly ${t.count} matching call(s), found ${a.length}`:`expected matching call count to satisfy the count predicate, found ${a.length}`,fail(`${s}; ${o}`)}}}function loadedSkill(e,t={}){return{...calledTool(LOAD_SKILL_TOOL_NAME,{...t,input:{skill:e}}),name:`loadedSkill(${e})`}}function notCalledTool(e){return{name:`notCalledTool(${e})`,evaluate(t){let n=t.derived.toolCalls.filter(t=>t.name===e).length;return n===0?PASS:fail(`"${e}" was called ${n} time(s)`)}}}function toolOrder(e){return{name:`toolOrder(${e.join(` → `)})`,evaluate(t){let n=requestedTools(t.events).map(e=>e.name),r=missingOrderedName(e,n);return r===void 0?PASS:fail(`missing "${r.name}" after [${e.slice(0,r.cursor).join(`, `)}]; observed request order: [${n.join(`, `)}]`)}}}function usedNoTools(){return{name:`usedNoTools`,evaluate(e){let t=e.derived.toolCallCount;return t===0?PASS:fail(`expected no tool calls, got ${t}`,{toolCallCount:t})}}}function maxToolCalls(e){return validateCount(e),{name:`maxToolCalls(${e})`,evaluate(t){let n=t.derived.toolCallCount;return n<=e?PASS:fail(`expected at most ${e} tool calls, got ${n}`,{maxAllowed:e,toolCallCount:n})}}}function noFailedActions(){return{name:`noFailedActions`,evaluate(e){let t=e.events.filter(e=>e.type===`action.result`&&(e.data.status===`failed`||e.data.result.isError===!0));if(t.length===0)return PASS;let n=t.map(formatFailedActionResult);return fail(`${t.length} failed action(s): ${n.join(`; `)}`,{failedActions:t.map(e=>({callId:e.data.result.callId,error:e.data.error,kind:e.data.result.kind,output:e.data.result.output,status:e.data.status}))})}}}function calledSubagent(e,t={}){return validateCount(t.count),{name:`calledSubagent(${e})`,evaluate(r){let i=r.derived.subagentCalls.filter(t=>t.name===e),a=i.filter(e=>subagentCallMatches(e,t));return matchesCount(t.count,a.length)?{score:1,metadata:{matchingCalls:a.length}}:i.length===0?fail(`subagent "${e}" was never called; observed: [${r.derived.subagentCalls.map(e=>e.name).join(`, `)}]`,{observedSubagentCalls:r.derived.subagentCalls}):fail(`subagent "${e}" was called but ${a.length} call(s) matched the constraints`,{observedSubagentCalls:i})}}}function eventsSatisfy(e,t){return{name:`eventsSatisfy(${e})`,evaluate(n){return t(n.events)?PASS:fail(`event predicate "${e}" did not hold`)}}}function typedEvent(e){return validateCount(e.count),{name:`event(${e.type})`,evaluate(n){let r=n.events.filter(n=>eventMatches(n,e));return matchesCount(e.count,r.length)?{score:1,metadata:{matchingEvents:r.length}}:fail(`expected ${describeCount(e.count)} matching ${e.type} event(s), found ${r.length}; observed: [${n.events.map(e=>e.type).join(`, `)}]`)}}}function notEvent(e){return{name:`notEvent(${e.type})`,evaluate(n){let r=n.events.filter(n=>eventMatches(n,e));return r.length===0?PASS:fail(`expected no matching ${e.type} events, found ${r.length}`)}}}function eventOrder(e){for(let t of e)validateCount(t.count);return{name:`eventOrder(${e.map(e=>e.type).join(` → `)})`,evaluate(n){let r=-1;for(let i of e){let e=n.events.flatMap((e,n)=>eventMatches(e,i)?[n]:[]);if(!matchesCount(i.count,e.length))return fail(`expected ${describeCount(i.count)} matching ${i.type} event(s), found ${e.length}`);let a=e[0];if(a===void 0||a<=r)return fail(`event group ${i.type} did not occur after the previous group`);r=e[e.length-1]??r}return PASS}}}function outputEquals(t){return{name:`outputEquals`,evaluate(n){return deepEquals(n.output,t)?PASS:fail(`output ${truncate(JSON.stringify(n.output))} does not equal expected ${truncate(JSON.stringify(t))}`)}}}function outputMatches(e){return{name:`outputMatches`,async evaluate(t){let n=await e[`~standard`].validate(t.output);return!(`issues`in n)||n.issues===void 0?PASS:fail(`output failed schema validation: ${n.issues.map(e=>e.message).join(`; `)}`)}}}function joinCompletedMessages(e){let t=[];for(let n of e)n.type===`message.completed`&&n.data.message!==null&&t.push(n.data.message);return t.join(`
2
+ `)}function failureDetail(e,t){return t===void 0?e:`${e} (code: ${t})`}function formatFailedActionResult(e){let{result:t,status:n}=e.data;return[actionResultLabel(t),`callId=${t.callId}`,`status=${n}`,t.isError===!0?`isError=true`:void 0,e.data.error?.message===void 0?void 0:`error=${e.data.error.message}`,`output=${truncate(formatUnknown(t.output))}`].filter(e=>e!==void 0).join(` `)}function actionResultLabel(e){switch(e.kind){case`tool-result`:return`tool-result:${e.toolName}`;case`subagent-result`:return`subagent-result:${e.subagentName}`;case`load-skill-result`:return e.name===void 0?`load-skill-result`:`load-skill-result:${e.name}`}}function runFailure(e){if(e.status===`failed`)return fail(failureDetail(`run failed`,e.derived.failureCode));let t=e.events.find(e=>e.type===`turn.failed`||e.type===`step.failed`);return t===void 0?void 0:fail(`${t.type} (${t.data.code}): ${t.data.message}`)}function truncate(e,t=200){return e===void 0?`undefined`:e.length<=t?e:`${e.slice(0,t)}…`}function formatUnknown(e){if(e!==void 0){if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}}function matchesCount(e,t){return e===void 0?t>0:typeof e==`function`?e(t):t===e}function describeCount(e){return e===void 0?`at least one`:typeof e==`function`?`a count satisfying the predicate`:`exactly ${e}`}function validateCount(e){if(!(e===void 0||typeof e==`function`)&&(typeof e!=`number`||!Number.isInteger(e)||e<0))throw TypeError(`Assertion count must be a non-negative integer or predicate; received ${String(e)}.`)}function missingOrderedName(e,t){let n=0;for(let r of t)if(r===e[n]&&(n+=1),n===e.length)return;let r=e[n];return r===void 0?void 0:{cursor:n,name:r}}function requestedTools(e){let t=[],n=new Set,append=(e,r)=>{n.has(e)||(n.add(e),t.push({callId:e,name:r}))};for(let t of e)if(t.type===`actions.requested`)for(let e of t.data.actions)e.kind===`tool-call`&&append(e.callId,e.toolName);else if(t.type===`input.requested`)for(let e of t.data.requests){let{action:t}=e;t.kind===`tool-call`&&append(t.callId,t.toolName)}return t}export{calledSubagent,calledTool,eventOrder,eventsSatisfy,loadedSkill,maxToolCalls,messageIncludes,noFailedActions,notCalledTool,notEvent,outputEquals,outputMatches,parked,succeeded,toolOrder,typedEvent,usedNoTools};
@@ -4,6 +4,6 @@ export { EveEvalTurnFailedError } from "#evals/session.js";
4
4
  export { mockModel } from "#evals/mock-model.js";
5
5
  export type { RuntimeIdentity } from "#protocol/message.js";
6
6
  export type { InputRequest } from "#runtime/input/types.js";
7
- export type { EveEvalEventMatch, EveEvalInputRequestMatchOptions, EveEvalValueMatcher, EveEvalToolCallMatchOptions, EveEvalSkillLoadMatchOptions, EveEvalSubagentCallMatchOptions, } from "#evals/match.js";
7
+ export type { EveEvalCountMatcher, EveEvalEventMatch, EveEvalInputRequestMatchOptions, EveEvalValueMatcher, EveEvalToolCallMatchOptions, EveEvalSkillLoadMatchOptions, EveEvalSubagentCallMatchOptions, } from "#evals/match.js";
8
8
  export type { Assertion, AssertionHandle, AssertionResult, AssertionSeverity, AutoevalsJudges, EveEvalActionStatus, EveEvalAssertions, EveEvalContext, EveEvalDerivedFacts, EveEvalJudgeConfig, EveEvalRunSummary, EveEvalSession, EveEvalSessionResult, EveEvalScheduleDispatchResult, EveEvalSubagentCall, EveEval, EveEvalConfig, EveEvalConfigInput, EveEvalDefinition, EveEvalInput, EveEvalResult, EveEvalTarget, EveEvalTargetCapabilities, EveEvalTargetHandle, EveEvalTaskResult, EveEvalToolCall, EveEvalTurn, EveEvalVerdict, JudgeContext, JudgeOpts, } from "#evals/types.js";
9
9
  export type { MockModelMessage, MockModelOptions, MockModelRequest, MockModelResponder, MockModelResponse, MockModelTool, MockModelToolCall, MockModelToolResult, MockModelUsage, } from "#evals/mock-model.js";
@@ -1 +1 @@
1
- import{isAbsolute,resolve}from"node:path";import{readFile}from"node:fs/promises";import matter from"#compiled/gray-matter/index.js";async function loadYaml(e){let t=await readFile(isAbsolute(e)?e:resolve(process.cwd(),e),`utf-8`);return matter(t.trimStart().startsWith(`---`)?t:`---\n${t}\n---`).data??{}}export{loadYaml};
1
+ import{isAbsolute,resolve}from"node:path";import{readFile}from"node:fs/promises";import{parseFrontmatter}from"#internal/helpers/gray-matter.js";async function loadYaml(e){let t=await readFile(isAbsolute(e)?e:resolve(process.cwd(),e),`utf-8`);return parseFrontmatter(t.trimStart().startsWith(`---`)?t:`---\n${t}\n---`).data}export{loadYaml};
@@ -15,6 +15,11 @@ import type { EveEvalSubagentCall, EveEvalToolCall } from "#evals/types.js";
15
15
  * - a **function** receives the observed value and returns a boolean verdict
16
16
  */
17
17
  export type EveEvalValueMatcher<T = JsonValue | undefined> = EveEvalDeepMatcher<T>;
18
+ /**
19
+ * Constraint over an observed assertion count. A number requires an exact
20
+ * count; a predicate receives the observed count and returns its verdict.
21
+ */
22
+ export type EveEvalCountMatcher = number | ((count: number) => boolean);
18
23
  type EveEvalDeepMatcher<T> = RegExp | ((value: T) => boolean) | (T extends readonly (infer TEntry)[] ? readonly EveEvalDeepMatcher<TEntry>[] : T extends object ? {
19
24
  readonly [K in keyof T]?: EveEvalDeepMatcher<T[K]>;
20
25
  } : T);
@@ -29,8 +34,8 @@ export interface EveEvalToolCallMatchOptions {
29
34
  readonly output?: EveEvalValueMatcher;
30
35
  /** Required lifecycle outcome. Defaults to `"completed"`. */
31
36
  readonly status?: EveEvalToolCall["status"];
32
- /** Exact number of matching calls required. Defaults to "at least one". */
33
- readonly count?: number;
37
+ /** Constraint over the matching call count. Defaults to "at least one". */
38
+ readonly count?: EveEvalCountMatcher;
34
39
  }
35
40
  /**
36
41
  * Constraints applied to a `load_skill` call by `t.loadedSkill`. Identical to
@@ -48,8 +53,8 @@ export interface EveEvalSubagentCallMatchOptions {
48
53
  readonly output?: EveEvalValueMatcher;
49
54
  /** Required lifecycle outcome. Defaults to `"completed"`. */
50
55
  readonly status?: EveEvalSubagentCall["status"];
51
- /** Exact number of matching delegations required. Defaults to "at least one". */
52
- readonly count?: number;
56
+ /** Constraint over the matching delegation count. Defaults to "at least one". */
57
+ readonly count?: EveEvalCountMatcher;
53
58
  }
54
59
  /** Constraints accepted by `requireInputRequest`. */
55
60
  export interface EveEvalInputRequestMatchOptions {
@@ -74,8 +79,8 @@ export type EveEvalEventMatch<TType extends HandleMessageStreamEvent["type"] = H
74
79
  }> extends {
75
80
  data: infer TData;
76
81
  } ? TData : never>;
77
- /** Exact number of matching events required. Defaults to "at least one". */
78
- readonly count?: number;
82
+ /** Constraint over the matching event count. Defaults to "at least one". */
83
+ readonly count?: EveEvalCountMatcher;
79
84
  } : never;
80
85
  /**
81
86
  * Returns true when the observed value satisfies a matcher (literal, RegExp,
@@ -1 +1 @@
1
- import{createHash}from"node:crypto";function applyMicrosandboxNetwork(e,t){let n=createMicrosandboxNetworkPlan(t);return n.disabled?e.disableNetwork():n.policy===null&&n.transformHeaderRules.length===0?e:e.network(e=>{let t=e.enabled(!0);if(n.policy!==null&&(t=t.policyJson(serializeMicrosandboxNetworkPolicyJson(n.policy))),n.transformHeaderRules.length===0)return t;t=t.trustHostCAs(!0);for(let e of n.transformHeaderRules)for(let[n,r]of Object.entries(e.headers)){let i=e.placeholderHeaders[n];if(i===void 0)continue;let a=createSecretEnvName(e.domain,n,r);t=t.secret(t=>{let n=t.env(a).value(r).placeholder(i).injectHeaders(!0).injectBasicAuth(!0).injectQuery(!1).injectBody(!1).requireTlsIdentity(!0);return n=e.domain===`*`?n.allowAnyHostDangerous(!0):e.domain.startsWith(`*.`)?n.allowHostPattern(e.domain):n.allowHost(e.domain),n})}return t})}function serializeMicrosandboxNetworkPolicyJson(e){let t={default_egress:e.defaultEgress,default_ingress:e.defaultIngress,rules:e.rules.map(e=>({action:e.action,destination:serializeMicrosandboxNetworkDestination(e.destination),direction:e.direction,ports:e.ports,protocols:e.protocols}))};return JSON.stringify(t)}function createMicrosandboxNetworkPlan(e){if(e===void 0||e===`allow-all`)return{disabled:!1,policy:{defaultEgress:`allow`,defaultIngress:`deny`,rules:[]},transformHeaderRules:[]};if(e===`deny-all`)return{disabled:!0,policy:null,transformHeaderRules:[]};let t=[],n=[],r=normalizeAllowEntries(e.allow),i=r.some(e=>e.domain===`*`),a=i?`allow`:`deny`;for(let n of e.subnets?.deny??[])t.push({action:`deny`,destination:{cidr:n,kind:`cidr`},direction:`egress`,ports:[],protocols:[]});for(let n of e.subnets?.allow??[])t.push({action:`allow`,destination:{cidr:n,kind:`cidr`},direction:`egress`,ports:[],protocols:[]});i||t.push({action:`allow`,destination:{kind:`any`},direction:`egress`,ports:[{start:53,end:53}],protocols:[`udp`,`tcp`]});for(let e of r)if(e.domain!==`*`){t.push({action:`allow`,destination:domainToDestination(e.domain),direction:`egress`,ports:[],protocols:[]});for(let t of e.rules)for(let r of normalizeTransforms(t.transform))Object.keys(r.headers).length!==0&&n.push({domain:e.domain,headers:r.headers,match:t.match,placeholderHeaders:createPlaceholderHeaders(e.domain,r.headers)})}return{disabled:!1,policy:{defaultEgress:a,defaultIngress:`deny`,rules:t},transformHeaderRules:n}}function createTransformBrokerEnvironment(e){if(e.transformHeaderRules.length===0)return{};let t=e.transformHeaderRules.flatMap(e=>Object.entries(e.placeholderHeaders).filter(([e])=>e.toLowerCase()===`authorization`).flatMap(([t,n])=>e.domain===`*`||e.domain.startsWith(`*.`)?[]:[{key:`http.https://${e.domain}/.extraheader`,value:`${t}: ${n}`}])),n={};return t.length>0&&(n.GIT_CONFIG_COUNT=String(t.length),t.forEach((e,t)=>{n[`GIT_CONFIG_KEY_${t}`]=e.key,n[`GIT_CONFIG_VALUE_${t}`]=e.value})),{EVE_MICROSANDBOX_NETWORK_TRANSFORMS:Buffer.from(JSON.stringify(e.transformHeaderRules)).toString(`base64`),...n}}function normalizeAllowEntries(e){return e===void 0?[]:Array.isArray(e)?e.map(e=>({domain:e,rules:[]})):Object.entries(e).map(([e,t])=>({domain:e,rules:Array.isArray(t)?t:[]}))}function normalizeTransforms(e){return e===void 0?[]:e.map(e=>({headers:e.headers??{}}))}function domainToDestination(e){return e.startsWith(`*.`)?{kind:`domainSuffix`,suffix:e.slice(2)}:{domain:e,kind:`domain`}}function serializeMicrosandboxNetworkDestination(e){switch(e.kind){case`any`:return`any`;case`cidr`:return{cidr:e.cidr??``};case`domain`:return{domain:e.domain??``};case`domainSuffix`:return{domain_suffix:e.suffix??``};case`group`:return{group:e.group??``};default:throw Error(`Unsupported microsandbox network destination kind.`)}}function createPlaceholderHeaders(e,t){let n={};for(let[r,i]of Object.entries(t))n[r]=`__EVE_MSB_SECRET_${createStableHash(`${e}:${r}:${i}`).slice(0,24)}__`;return n}function createSecretEnvName(e,t,n){return`EVE_MSB_SECRET_${createStableHash(`${e}:${t}:${n}`).slice(0,24).toUpperCase()}`}function createStableHash(t){return createHash(`sha256`).update(t).digest(`hex`)}export{applyMicrosandboxNetwork,createMicrosandboxNetworkPlan,createTransformBrokerEnvironment,serializeMicrosandboxNetworkPolicyJson};
1
+ import{createHash}from"node:crypto";function applyMicrosandboxNetwork(e,t){let n=createMicrosandboxNetworkPlan(t);return n.disabled?e.disableNetwork():n.policy===null&&n.transformHeaderRules.length===0?e:e.network(e=>{let t=e.enabled(!0);if(n.policy!==null&&(t=t.policyJson(serializeMicrosandboxNetworkPolicyJson(n.policy))),n.transformHeaderRules.length===0)return t;t=t.trustHostCAs(!0);for(let e of n.transformHeaderRules)for(let[n,r]of Object.entries(e.headers)){let i=e.placeholderHeaders[n];if(i===void 0)continue;let a=createSecretEnvName(e.domain,n,r);t=t.secret(t=>{let n=t.env(a).value(r).placeholder(i).injectHeaders(!0).injectBasicAuth(!0).injectQuery(!1).injectBody(!1).requireTlsIdentity(!0);return n=e.domain===`*`?n.allowAnyHostDangerous(!0):e.domain.startsWith(`*.`)?n.allowHostPattern(e.domain):n.allowHost(e.domain),n})}return t})}function serializeMicrosandboxNetworkPolicyJson(e){let t={default_egress:e.defaultEgress,default_ingress:e.defaultIngress,rules:e.rules.map(e=>({action:e.action,destination:serializeMicrosandboxNetworkDestination(e.destination),direction:e.direction,ports:e.ports,protocols:e.protocols}))};return JSON.stringify(t)}function createMicrosandboxNetworkPlan(e){if(e===void 0||e===`allow-all`)return{disabled:!1,policy:{defaultEgress:`allow`,defaultIngress:`deny`,rules:[]},transformHeaderRules:[]};if(e===`deny-all`)return{disabled:!0,policy:null,transformHeaderRules:[]};let t=[],n=[],r=normalizeAllowEntries(e.allow),i=r.some(e=>e.domain===`*`),a=i?`allow`:`deny`;for(let n of e.subnets?.deny??[])t.push({action:`deny`,destination:{cidr:n,kind:`cidr`},direction:`egress`,ports:[],protocols:[]});for(let n of e.subnets?.allow??[])t.push({action:`allow`,destination:{cidr:n,kind:`cidr`},direction:`egress`,ports:[],protocols:[]});i||t.push({action:`allow`,destination:{kind:`any`},direction:`egress`,ports:[{start:53,end:53}],protocols:[`udp`,`tcp`]});for(let e of r)if(e.domain!==`*`){t.push({action:`allow`,destination:domainToDestination(e.domain),direction:`egress`,ports:[],protocols:[]});for(let t of e.rules)for(let r of normalizeTransforms(t.transform))Object.keys(r.headers).length!==0&&n.push({domain:e.domain,headers:r.headers,match:t.match,placeholderHeaders:createPlaceholderHeaders(e.domain,r.headers)})}return{disabled:!1,policy:{defaultEgress:a,defaultIngress:`deny`,rules:t},transformHeaderRules:n}}function createTransformBrokerEnvironment(e){if(e.transformHeaderRules.length===0)return{};let t=e.transformHeaderRules.flatMap(e=>Object.entries(e.placeholderHeaders).filter(([e])=>e.toLowerCase()===`authorization`).flatMap(([t,n])=>e.domain===`*`||e.domain.startsWith(`*.`)?[]:[{key:`http.https://${e.domain}/.extraheader`,value:`${t}: ${n}`}])),n={};return t.length>0&&(n.GIT_CONFIG_COUNT=String(t.length),t.forEach((e,t)=>{n[`GIT_CONFIG_KEY_${t}`]=e.key,n[`GIT_CONFIG_VALUE_${t}`]=e.value})),n}function normalizeAllowEntries(e){return e===void 0?[]:Array.isArray(e)?e.map(e=>({domain:e,rules:[]})):Object.entries(e).map(([e,t])=>({domain:e,rules:Array.isArray(t)?t:[]}))}function normalizeTransforms(e){return e===void 0?[]:e.map(e=>({headers:e.headers??{}}))}function domainToDestination(e){return e.startsWith(`*.`)?{kind:`domainSuffix`,suffix:e.slice(2)}:{domain:e,kind:`domain`}}function serializeMicrosandboxNetworkDestination(e){switch(e.kind){case`any`:return`any`;case`cidr`:return{cidr:e.cidr??``};case`domain`:return{domain:e.domain??``};case`domainSuffix`:return{domain_suffix:e.suffix??``};case`group`:return{group:e.group??``};default:throw Error(`Unsupported microsandbox network destination kind.`)}}function createPlaceholderHeaders(e,t){let n={};for(let[r,i]of Object.entries(t))n[r]=`__EVE_MSB_SECRET_${createStableHash(`${e}:${r}:${i}`).slice(0,24)}__`;return n}function createSecretEnvName(e,t,n){return`EVE_MSB_SECRET_${createStableHash(`${e}:${t}:${n}`).slice(0,24).toUpperCase()}`}function createStableHash(t){return createHash(`sha256`).update(t).digest(`hex`)}export{applyMicrosandboxNetwork,createMicrosandboxNetworkPlan,createTransformBrokerEnvironment,serializeMicrosandboxNetworkPolicyJson};
@@ -1 +1 @@
1
- import{toError}from"#shared/errors.js";import{createActionResultEvent,createActionsRequestedEvent,createMessageAppendedEvent,createMessageCompletedEvent,createMessageReceivedEvent,createReasoningAppendedEvent,createReasoningCompletedEvent,createSessionCompletedEvent,createSessionFailedEvent,createSessionStartedEvent,createSessionWaitingEvent,createStepFailedEvent,createStepStartedEvent,createTurnCompletedEvent,createTurnFailedEvent,createTurnStartedEvent}from"#protocol/message.js";import{contextStorage}from"#context/container.js";import{createRuntimeActionRequestFromToolCall,resolveToolCallInputObject}from"#harness/runtime-actions.js";import{isAuthorizationSignal,isPendingAuthorizationToolOutput}from"#harness/authorization.js";import{hasEmptyDeliverySentinel}from"#shared/empty-delivery.js";import{createRuntimeToolResultFromStepResult,createRuntimeToolResultFromToolError,createToolResultMessagePartFromToolError}from"#harness/action-result-helpers.js";import{createInvalidToolCallInputError}from"#harness/tool-call-input-errors.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{createProviderStreamActionBatch}from"#harness/stream-actions.js";const HARNESS_EMISSION_STATE_KEY=`eve.harness.emission`,DEFAULT_EMISSION_STATE={sessionStarted:!1,sequence:0,stepIndex:0,turnId:``};function getHarnessEmissionState(e){return e?.[HARNESS_EMISSION_STATE_KEY]??DEFAULT_EMISSION_STATE}function isHarnessBetweenTurns(e){return getHarnessEmissionState(e.state).turnId===``}function setHarnessEmissionState(e,t){return{...e,state:{...e.state,[HARNESS_EMISSION_STATE_KEY]:t}}}async function emitTurnPreamble(e,t,n,r){let i=`turn_${n.sequence}`;return n.sessionStarted||await e(createSessionStartedEvent({runtime:r})),await e(createTurnStartedEvent({sequence:n.sequence,turnId:i})),t.message!==void 0&&await e(createMessageReceivedEvent({message:t.message,sequence:n.sequence,turnId:i})),{sessionStarted:!0,sequence:n.sequence,stepIndex:0,turnId:i}}async function emitStepStarted(e,t,n){await e(createStepStartedEvent({sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId}),n)}async function emitStepAndTurnFailed(e,t,n){await e(createStepFailedEvent({...n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),await e(createTurnFailedEvent({...n,sequence:t.sequence,turnId:t.turnId}))}async function emitFailedStep(e,t,n){await emitStepAndTurnFailed(e,t,n),await e(createSessionFailedEvent(n))}async function emitRecoverableFailedTurn(e,t,n){return await emitStepAndTurnFailed(e,t,n),await e(createSessionWaitingEvent()),{sessionStarted:t.sessionStarted,sequence:t.sequence+1,stepIndex:0,turnId:``}}function advanceStep(e){return{...e,stepIndex:e.stepIndex+1}}async function emitTurnEpilogue(e,t,n){return await e(createTurnCompletedEvent({sequence:t.sequence,turnId:t.turnId})),n===`conversation`?await e(createSessionWaitingEvent()):await e(createSessionCompletedEvent()),{sessionStarted:t.sessionStarted,sequence:t.sequence+1,stepIndex:0,turnId:``}}function normalizeAssistantStepFinishReason(e){switch(e){case`content-filter`:case`error`:case`length`:case`stop`:case`tool-calls`:return e;default:return`other`}}async function emitStreamContent(a,o,s,c){let l=``,u=``,d=`stop`,f,p=new Set,m=new Set,h=new Set,g=new Set,_=createProviderStreamActionBatch({emitFn:a,state:o}),v=new Set,y=new Set,b=[],x=[],S=[],flushCurrentMessage=async()=>{u.length!==0&&(await a(createMessageCompletedEvent({finishReason:`tool-calls`,message:u,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),u=``)},emitActionRequest=async e=>{m.has(e.callId)||(u.trim().length>0&&await flushCurrentMessage(),m.add(e.callId),await a(createActionsRequestedEvent({actions:[e],sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})))},collectProviderToolCall=async e=>{g.has(e.toolCallId)||(g.add(e.toolCallId),!m.has(e.toolCallId)&&(m.add(e.toolCallId),u.trim().length>0&&await flushCurrentMessage(),_.observe({callId:e.toolCallId,input:resolveToolCallInputObject(e.input,{callId:e.toolCallId,toolName:e.toolName}),kind:`tool-call`,toolName:e.toolName})))},emitActionResult=async e=>{h.has(e.callId)||(h.add(e.callId),await a(createActionResultEvent({result:e,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})))},emitToolCall=async e=>{if(!(c===void 0||e.invalid===!0||c.excludedActionToolNames.has(e.toolName)))try{await emitActionRequest(createRuntimeActionRequestFromToolCall({toolCall:e,tools:c.tools}))}catch(t){if(t instanceof TypeError){let n=createInvalidToolCallInputError({error:t,toolCall:e});y.add(e.toolCallId),u.trim().length>0&&await flushCurrentMessage(),await emitActionResult(createRuntimeToolResultFromToolError(n)),v.add(e.toolCallId),S.push(createToolResultMessagePartFromToolError(n));return}throw t}};for await(let t of s)if(f===void 0)switch(t.type){case`reasoning-delta`:await _.flush(),l+=t.text,await a(createReasoningAppendedEvent({reasoningDelta:t.text,reasoningSoFar:l,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId}));break;case`text-delta`:await _.flush(),l.trim().length>0&&(await a(createReasoningCompletedEvent({reasoning:l,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),l=``),u+=t.text,await a(createMessageAppendedEvent({messageDelta:t.text,messageSoFar:u,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId}));break;case`tool-call`:{let e=t;p.add(e.toolCallId),e.providerExecuted===!0?await collectProviderToolCall(e):(await _.flush(),await emitToolCall(e));break}case`tool-result`:{let e=t;if(e.preliminary===!0)break;if(e.providerExecuted===!0){await collectProviderToolCall({input:`input`in e?e.input:void 0,toolCallId:e.toolCallId,toolName:e.toolName}),await _.flush(),await emitActionResult(createRuntimeToolResultFromStepResult(e));break}if(p.has(t.toolCallId)){if(isInlineAuthorizationToolResult(e))break;m.has(t.toolCallId)&&(await emitActionResult(createRuntimeToolResultFromStepResult(e)),v.add(t.toolCallId));break}if(await _.flush(),await flushCurrentMessage(),isInlineAuthorizationToolResult(e)){v.add(t.toolCallId),b.push(e);break}await emitActionResult(createRuntimeToolResultFromStepResult(e)),v.add(t.toolCallId);let n=e.output;x.push({type:`tool-result`,toolCallId:e.toolCallId,toolName:e.toolName,output:typeof n==`string`?{type:`text`,value:n}:{type:`json`,value:n??null}});break}case`tool-error`:{let e=t;e.providerExecuted===!0?(await collectProviderToolCall(e),await _.flush(),await emitActionResult(createRuntimeToolResultFromToolError(e))):m.has(e.toolCallId)&&(await emitActionResult(createRuntimeToolResultFromToolError(e)),v.add(e.toolCallId),S.push(createToolResultMessagePartFromToolError(e)));break}case`finish-step`:d=normalizeAssistantStepFinishReason(t.finishReason),await _.flush();break;case`error`:f=toError(t.error);break;case`abort`:throw new DOMException(t.reason??`The model stream was aborted.`,`AbortError`);default:break}if(await _.flush(),f!==void 0)throw f;return l.trim().length>0&&await a(createReasoningCompletedEvent({reasoning:l,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),d!==`tool-calls`&&hasEmptyDeliverySentinel(u)?await a(createMessageCompletedEvent({finishReason:d,message:null,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})):u.trim().length>0&&await a(createMessageCompletedEvent({finishReason:d,message:u,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),{emittedActionCallIds:m,handledInlineToolResultCallIds:v,invalidInputToolCallIds:y,inlineAuthorizationResults:b,inlineToolResultParts:x,trailingInlineToolResultParts:S}}function isInlineAuthorizationToolResult(e){if(isPendingAuthorizationToolOutput(e.output))return!0;let t=contextStorage.getStore();if(t===void 0)return!1;let n=readToolInterrupt(t,e.toolCallId);return n!==void 0&&isAuthorizationSignal(n)}export{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,isHarnessBetweenTurns,normalizeAssistantStepFinishReason,setHarnessEmissionState};
1
+ import{normalizeModelStreamError}from"#harness/model-call-error.js";import{createActionResultEvent,createActionsRequestedEvent,createMessageAppendedEvent,createMessageCompletedEvent,createMessageReceivedEvent,createReasoningAppendedEvent,createReasoningCompletedEvent,createSessionCompletedEvent,createSessionFailedEvent,createSessionStartedEvent,createSessionWaitingEvent,createStepFailedEvent,createStepStartedEvent,createTurnCompletedEvent,createTurnFailedEvent,createTurnStartedEvent}from"#protocol/message.js";import{contextStorage}from"#context/container.js";import{createRuntimeActionRequestFromToolCall,resolveToolCallInputObject}from"#harness/runtime-actions.js";import{isAuthorizationSignal,isPendingAuthorizationToolOutput}from"#harness/authorization.js";import{hasEmptyDeliverySentinel}from"#shared/empty-delivery.js";import{createRuntimeToolResultFromStepResult,createRuntimeToolResultFromToolError,createToolResultMessagePartFromToolError}from"#harness/action-result-helpers.js";import{createInvalidToolCallInputError}from"#harness/tool-call-input-errors.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{createProviderStreamActionBatch}from"#harness/stream-actions.js";const HARNESS_EMISSION_STATE_KEY=`eve.harness.emission`,DEFAULT_EMISSION_STATE={sessionStarted:!1,sequence:0,stepIndex:0,turnId:``};function getHarnessEmissionState(e){return e?.[HARNESS_EMISSION_STATE_KEY]??DEFAULT_EMISSION_STATE}function isHarnessBetweenTurns(e){return getHarnessEmissionState(e.state).turnId===``}function setHarnessEmissionState(e,t){return{...e,state:{...e.state,[HARNESS_EMISSION_STATE_KEY]:t}}}async function emitTurnPreamble(e,t,n,r){let i=`turn_${n.sequence}`;return n.sessionStarted||await e(createSessionStartedEvent({runtime:r})),await e(createTurnStartedEvent({sequence:n.sequence,turnId:i})),t.message!==void 0&&await e(createMessageReceivedEvent({message:t.message,sequence:n.sequence,turnId:i})),{sessionStarted:!0,sequence:n.sequence,stepIndex:0,turnId:i}}async function emitStepStarted(e,t,n){await e(createStepStartedEvent({sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId}),n)}async function emitStepAndTurnFailed(e,t,n){await e(createStepFailedEvent({...n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),await e(createTurnFailedEvent({...n,sequence:t.sequence,turnId:t.turnId}))}async function emitFailedStep(e,t,n){await emitStepAndTurnFailed(e,t,n),await e(createSessionFailedEvent(n))}async function emitRecoverableFailedTurn(e,t,n){return await emitStepAndTurnFailed(e,t,n),await e(createSessionWaitingEvent()),{sessionStarted:t.sessionStarted,sequence:t.sequence+1,stepIndex:0,turnId:``}}function advanceStep(e){return{...e,stepIndex:e.stepIndex+1}}async function emitTurnEpilogue(e,t,n){return await e(createTurnCompletedEvent({sequence:t.sequence,turnId:t.turnId})),n===`conversation`?await e(createSessionWaitingEvent()):await e(createSessionCompletedEvent()),{sessionStarted:t.sessionStarted,sequence:t.sequence+1,stepIndex:0,turnId:``}}function normalizeAssistantStepFinishReason(e){switch(e){case`content-filter`:case`error`:case`length`:case`stop`:case`tool-calls`:return e;default:return`other`}}async function emitStreamContent(a,o,s,c){let l=``,u=``,d=`stop`,f,p=new Set,m=new Set,h=new Set,g=new Set,_=createProviderStreamActionBatch({emitFn:a,state:o}),v=new Set,y=new Set,b=[],x=[],S=[],flushCurrentMessage=async()=>{u.length!==0&&(await a(createMessageCompletedEvent({finishReason:`tool-calls`,message:u,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),u=``)},emitActionRequest=async e=>{m.has(e.callId)||(u.trim().length>0&&await flushCurrentMessage(),m.add(e.callId),await a(createActionsRequestedEvent({actions:[e],sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})))},collectProviderToolCall=async e=>{g.has(e.toolCallId)||(g.add(e.toolCallId),!m.has(e.toolCallId)&&(m.add(e.toolCallId),u.trim().length>0&&await flushCurrentMessage(),_.observe({callId:e.toolCallId,input:resolveToolCallInputObject(e.input,{callId:e.toolCallId,toolName:e.toolName}),kind:`tool-call`,toolName:e.toolName})))},emitActionResult=async e=>{h.has(e.callId)||(h.add(e.callId),await a(createActionResultEvent({result:e,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})))},emitToolCall=async e=>{if(!(c===void 0||e.invalid===!0||c.excludedActionToolNames.has(e.toolName)))try{await emitActionRequest(createRuntimeActionRequestFromToolCall({toolCall:e,tools:c.tools}))}catch(t){if(t instanceof TypeError){let n=createInvalidToolCallInputError({error:t,toolCall:e});y.add(e.toolCallId),u.trim().length>0&&await flushCurrentMessage(),await emitActionResult(createRuntimeToolResultFromToolError(n)),v.add(e.toolCallId),S.push(createToolResultMessagePartFromToolError(n));return}throw t}};for await(let t of s)if(f===void 0)switch(t.type){case`reasoning-delta`:await _.flush(),l+=t.text,await a(createReasoningAppendedEvent({reasoningDelta:t.text,reasoningSoFar:l,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId}));break;case`text-delta`:await _.flush(),l.trim().length>0&&(await a(createReasoningCompletedEvent({reasoning:l,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),l=``),u+=t.text,await a(createMessageAppendedEvent({messageDelta:t.text,messageSoFar:u,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId}));break;case`tool-call`:{let e=t;p.add(e.toolCallId),e.providerExecuted===!0?await collectProviderToolCall(e):(await _.flush(),await emitToolCall(e));break}case`tool-result`:{let e=t;if(e.preliminary===!0)break;if(e.providerExecuted===!0){await collectProviderToolCall({input:`input`in e?e.input:void 0,toolCallId:e.toolCallId,toolName:e.toolName}),await _.flush(),await emitActionResult(createRuntimeToolResultFromStepResult(e));break}if(p.has(t.toolCallId)){if(isInlineAuthorizationToolResult(e))break;m.has(t.toolCallId)&&(await emitActionResult(createRuntimeToolResultFromStepResult(e)),v.add(t.toolCallId));break}if(await _.flush(),await flushCurrentMessage(),isInlineAuthorizationToolResult(e)){v.add(t.toolCallId),b.push(e);break}await emitActionResult(createRuntimeToolResultFromStepResult(e)),v.add(t.toolCallId);let n=e.output;x.push({type:`tool-result`,toolCallId:e.toolCallId,toolName:e.toolName,output:typeof n==`string`?{type:`text`,value:n}:{type:`json`,value:n??null}});break}case`tool-error`:{let e=t;e.providerExecuted===!0?(await collectProviderToolCall(e),await _.flush(),await emitActionResult(createRuntimeToolResultFromToolError(e))):m.has(e.toolCallId)&&(await emitActionResult(createRuntimeToolResultFromToolError(e)),v.add(e.toolCallId),S.push(createToolResultMessagePartFromToolError(e)));break}case`finish-step`:d=normalizeAssistantStepFinishReason(t.finishReason),await _.flush();break;case`error`:f=normalizeModelStreamError(t.error);break;case`abort`:throw new DOMException(t.reason??`The model stream was aborted.`,`AbortError`);default:break}if(await _.flush(),f!==void 0)throw f;return l.trim().length>0&&await a(createReasoningCompletedEvent({reasoning:l,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),d!==`tool-calls`&&hasEmptyDeliverySentinel(u)?await a(createMessageCompletedEvent({finishReason:d,message:null,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})):u.trim().length>0&&await a(createMessageCompletedEvent({finishReason:d,message:u,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),{emittedActionCallIds:m,handledInlineToolResultCallIds:v,invalidInputToolCallIds:y,inlineAuthorizationResults:b,inlineToolResultParts:x,trailingInlineToolResultParts:S}}function isInlineAuthorizationToolResult(e){if(isPendingAuthorizationToolOutput(e.output))return!0;let t=contextStorage.getStore();if(t===void 0)return!1;let n=readToolInterrupt(t,e.toolCallId);return n!==void 0&&isAuthorizationSignal(n)}export{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,isHarnessBetweenTurns,normalizeAssistantStepFinishReason,setHarnessEmissionState};
@@ -77,6 +77,11 @@ export declare class EmptyModelResponseError extends Error {
77
77
  cause?: unknown;
78
78
  });
79
79
  }
80
+ /**
81
+ * Coerces a streamed provider failure into an Error while retaining the raw
82
+ * payload so provider discriminators remain visible to error classification.
83
+ */
84
+ export declare function normalizeModelStreamError(raw: unknown): Error;
80
85
  /**
81
86
  * True when the error (or any error in its cause chain) is the AI SDK's
82
87
  * `NoOutputGeneratedError`. Since `ai@7.0.0-canary.169` (vercel/ai#15938)
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";import{isTurnCancellation}from"#harness/turn-cancellation.js";const GATEWAY_AUTHENTICATION_ERROR_NAME=`GatewayAuthenticationError`,GATEWAY_AUTH_FAILURE_SUMMARY_NAME=`AI Gateway authentication failed`,UNSUPPORTED_TOOL_TYPE_REGEX=/tool type ['"]([\w.-]+)['"] is not supported/i;function summarizeKnownModelCallConfigError(e){let t=readErrorName(e),n=readErrorMessage(e);return t===`GatewayAuthenticationError`||/AI Gateway authentication/i.test(n)?/Invalid API key/i.test(n)?{name:GATEWAY_AUTH_FAILURE_SUMMARY_NAME,message:"AI Gateway rejected the provided API key. Update or unset `AI_GATEWAY_API_KEY` (check your shell profile if you did not set it for this project) — manage keys at https://vercel.com/dashboard/ai/api-keys. Unsetting it falls back to OIDC via `eve link`."}:/Invalid OIDC token/i.test(n)?{name:GATEWAY_AUTH_FAILURE_SUMMARY_NAME,message:"AI Gateway rejected the OIDC token. Run `eve link` to refresh `VERCEL_OIDC_TOKEN` in `.env.local`, or set `AI_GATEWAY_API_KEY` — create a key at https://vercel.com/dashboard/ai/api-keys."}:{name:GATEWAY_AUTH_FAILURE_SUMMARY_NAME,message:"AI Gateway received no credentials. Run `eve link` to populate `VERCEL_OIDC_TOKEN`, or set `AI_GATEWAY_API_KEY` — create a key at https://vercel.com/dashboard/ai/api-keys."}:t===`LoadAPIKeyError`||/API key is missing/i.test(n)?{name:`Model provider API key missing`,message:"The model provider could not load an API key. Export the provider's API key environment variable (for example `AI_GATEWAY_API_KEY` or `OPENAI_API_KEY`) and try again."}:null}function summarizeKnownModelCallRequestError(e){if(e instanceof EmptyModelResponseError)return{name:`Empty model response`,message:e.message};let t=readModelCallErrorSignals(e);return t.statusCode===400&&isGatewayErrorSignal(t)?{name:`AI Gateway model request rejected`,message:`AI Gateway rejected the model request before the agent produced a response.`}:null}function extractUnsupportedProviderToolTypes(e){let t=new Set;for(let n of walkCauseChain(e)){collectUnsupportedToolTypesFromValue(readObjectField(n,`data`),t);let e=readStringField(n,`responseBody`);if(e!==void 0)try{collectUnsupportedToolTypesFromValue(JSON.parse(e),t)}catch{let n=UNSUPPORTED_TOOL_TYPE_REGEX.exec(e);n?.[1]!==void 0&&t.add(n[1])}}return[...t]}function collectUnsupportedToolTypesFromValue(t,n){if(t!=null){if(typeof t==`string`){let e=UNSUPPORTED_TOOL_TYPE_REGEX.exec(t);e?.[1]!==void 0&&n.add(e[1]);return}if(Array.isArray(t)){for(let e of t)collectUnsupportedToolTypesFromValue(e,n);return}if(isObject(t))for(let e of Object.values(t))collectUnsupportedToolTypesFromValue(e,n)}}function extractModelCallErrorDetails(e){let t=readModelCallErrorSignals(e),n={};return appendJsonField(n,`gatewayName`,t.gatewayName),appendJsonField(n,`gatewayType`,t.gatewayType),appendJsonField(n,`statusCode`,t.statusCode),appendJsonField(n,`generationId`,t.generationId),appendJsonField(n,`upstreamStatusCode`,t.upstreamStatusCode),appendJsonField(n,`upstreamType`,t.upstreamType),appendJsonField(n,`upstreamMessage`,t.upstreamMessage),appendJsonField(n,`responseBodySnippet`,t.responseBodySnippet),n}function readErrorName(t){if(t instanceof Error||isObject(t)&&typeof t.name==`string`)return t.name}function readErrorMessage(t){return t instanceof Error||isObject(t)&&typeof t.message==`string`?t.message:``}var EmptyModelResponseError=class extends Error{constructor(e){super(`The model did not return a response. Please try again.`,e),this.name=`EmptyModelResponseError`}};function isNoOutputGeneratedError(e){for(let t of walkCauseChain(e))if(readErrorName(t)===`AI_NoOutputGeneratedError`)return!0;return!1}function classifyModelCallError(e){if(isTurnCancellation(e))return`terminal`;if(e instanceof EmptyModelResponseError)return`recoverable`;if(hasRetryableFlag(e))return`retry`;if(summarizeKnownModelCallConfigError(e)!==null)return`terminal`;let n=readModelCallErrorSignals(e);if(isRetryableGatewayType(n.gatewayType)||isRetryableGatewayType(n.upstreamType))return`retry`;if(isTerminalGatewayType(n.gatewayType)||isTerminalGatewayType(n.upstreamType)||n.gatewayName===`GatewayInvalidRequestError`)return`terminal`;let r=n.statusCode;if(r!==void 0){if(r===408||r===409||r===429||r>=500)return`retry`;if(isAmbiguousGatewayInternalBadRequest(n))return`recoverable`;if(r>=400&&r<500)return`terminal`}return isLikelyNetworkError(e)?`retry`:`recoverable`}function hasRetryableFlag(t){for(let n of walkCauseChain(t))if(isObject(n)&&n.isRetryable===!0)return!0;return!1}function isLikelyNetworkError(e){if(!(e instanceof Error))return!1;let t=e.message.toLowerCase();return t.includes(`econnreset`)||t.includes(`etimedout`)||t.includes(`eai_again`)||t.includes(`socket hang up`)||t.includes(`network`)||t.includes(`fetch failed`)?!0:e.cause!==void 0&&e.cause!==e?isLikelyNetworkError(e.cause):!1}function readModelCallErrorSignals(e){let t=findGatewayError(e),n=findUpstreamApiCallError(e),r=readStringField(n,`responseBody`),i=readGatewayErrorBody(n);return{gatewayName:readErrorName(t),gatewayType:readStringField(t,`type`),generationId:readStringField(t,`generationId`)??i?.generationId,responseBodySnippet:r===void 0?void 0:truncateSnippet(r,1e3),statusCode:readStatusCode(t)??readStatusCode(n)??findStatusCode(e),upstreamMessage:i?.message,upstreamStatusCode:readStatusCode(n),upstreamType:i?.type}}function findGatewayError(e){for(let t of walkCauseChain(e)){let e=readErrorName(t),n=readStringField(t,`type`);if(e?.startsWith(`Gateway`)||n?.endsWith(`_error`)||n===`rate_limit_exceeded`)return t}}function findUpstreamApiCallError(e){for(let t of walkCauseChain(e))if(readErrorName(t)===`AI_APICallError`||readStringField(t,`responseBody`)!==void 0||readObjectField(t,`data`)!==void 0||readObjectField(t,`requestBodyValues`)!==void 0)return t}function readGatewayErrorBody(e){let t=readGatewayErrorBodyFromValue(readObjectField(e,`data`));if(t!==void 0)return t;let n=readStringField(e,`responseBody`);if(n!==void 0)try{return readGatewayErrorBodyFromValue(JSON.parse(n))}catch{return}}function readGatewayErrorBodyFromValue(t){if(!isObject(t))return;let n=readObjectField(t,`error`);if(n===void 0)return;let r=readStringField(t,`generationId`),i=readStringField(n,`message`),a=readStringField(n,`type`);return i===void 0&&a===void 0&&r===void 0?void 0:{generationId:r,message:i,type:a}}function readStatusCode(t){if(isObject(t))return typeof t.statusCode==`number`?t.statusCode:void 0}function findStatusCode(e){for(let t of walkCauseChain(e)){let e=readStatusCode(t);if(e!==void 0)return e}}function readStringField(t,n){if(!isObject(t))return;let r=t[n];return typeof r==`string`&&r.length>0?r:void 0}function readObjectField(t,n){if(!isObject(t))return;let r=t[n];return isObject(r)?r:void 0}function isRetryableGatewayType(e){return e===`rate_limit_exceeded`||e===`timeout_error`}function isTerminalGatewayType(e){return e===`authentication_error`||e===`invalid_request_error`||e===`model_not_found`}function isGatewayErrorSignal(e){return e.gatewayName!==void 0||e.gatewayType!==void 0}function isAmbiguousGatewayInternalBadRequest(e){return e.statusCode===400&&(e.gatewayName===`GatewayInternalServerError`||e.gatewayType===`internal_server_error`)&&(e.upstreamType===void 0||e.upstreamType===`internal_server_error`)}function*walkCauseChain(t){let n=new Set,r=t;for(;isObject(r)&&!n.has(r);)n.add(r),yield r,r=r.cause}function appendJsonField(e,t,n){if(typeof n==`string`&&n.length>0){e[t]=n;return}typeof n==`number`&&Number.isFinite(n)&&(e[t]=n)}function truncateSnippet(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}export{EmptyModelResponseError,GATEWAY_AUTHENTICATION_ERROR_NAME,GATEWAY_AUTH_FAILURE_SUMMARY_NAME,classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,isNoOutputGeneratedError,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError};
1
+ import{isObject}from"#shared/guards.js";import{toError}from"#shared/errors.js";import{isTurnCancellation}from"#harness/turn-cancellation.js";const GATEWAY_AUTHENTICATION_ERROR_NAME=`GatewayAuthenticationError`,GATEWAY_AUTH_FAILURE_SUMMARY_NAME=`AI Gateway authentication failed`,UNSUPPORTED_TOOL_TYPE_REGEX=/tool type ['"]([\w.-]+)['"] is not supported/i;function summarizeKnownModelCallConfigError(e){let t=readErrorName(e),n=readErrorMessage(e);return t===`GatewayAuthenticationError`||/AI Gateway authentication/i.test(n)?/Invalid API key/i.test(n)?{name:GATEWAY_AUTH_FAILURE_SUMMARY_NAME,message:"AI Gateway rejected the provided API key. Update or unset `AI_GATEWAY_API_KEY` (check your shell profile if you did not set it for this project) — manage keys at https://vercel.com/dashboard/ai/api-keys. Unsetting it falls back to OIDC via `eve link`."}:/Invalid OIDC token/i.test(n)?{name:GATEWAY_AUTH_FAILURE_SUMMARY_NAME,message:"AI Gateway rejected the OIDC token. Run `eve link` to refresh `VERCEL_OIDC_TOKEN` in `.env.local`, or set `AI_GATEWAY_API_KEY` — create a key at https://vercel.com/dashboard/ai/api-keys."}:{name:GATEWAY_AUTH_FAILURE_SUMMARY_NAME,message:"AI Gateway received no credentials. Run `eve link` to populate `VERCEL_OIDC_TOKEN`, or set `AI_GATEWAY_API_KEY` — create a key at https://vercel.com/dashboard/ai/api-keys."}:t===`LoadAPIKeyError`||/API key is missing/i.test(n)?{name:`Model provider API key missing`,message:"The model provider could not load an API key. Export the provider's API key environment variable (for example `AI_GATEWAY_API_KEY` or `OPENAI_API_KEY`) and try again."}:null}function summarizeKnownModelCallRequestError(e){if(e instanceof EmptyModelResponseError)return{name:`Empty model response`,message:e.message};let t=readModelCallErrorSignals(e);return t.statusCode===400&&isGatewayErrorSignal(t)?{name:`AI Gateway model request rejected`,message:`AI Gateway rejected the model request before the agent produced a response.`}:null}function extractUnsupportedProviderToolTypes(e){let t=new Set;for(let n of walkCauseChain(e)){collectUnsupportedToolTypesFromValue(readObjectField(n,`data`),t);let e=readStringField(n,`responseBody`);if(e!==void 0)try{collectUnsupportedToolTypesFromValue(JSON.parse(e),t)}catch{let n=UNSUPPORTED_TOOL_TYPE_REGEX.exec(e);n?.[1]!==void 0&&t.add(n[1])}}return[...t]}function collectUnsupportedToolTypesFromValue(t,n){if(t!=null){if(typeof t==`string`){let e=UNSUPPORTED_TOOL_TYPE_REGEX.exec(t);e?.[1]!==void 0&&n.add(e[1]);return}if(Array.isArray(t)){for(let e of t)collectUnsupportedToolTypesFromValue(e,n);return}if(isObject(t))for(let e of Object.values(t))collectUnsupportedToolTypesFromValue(e,n)}}function extractModelCallErrorDetails(e){let t=readModelCallErrorSignals(e),n={};return appendJsonField(n,`gatewayName`,t.gatewayName),appendJsonField(n,`gatewayType`,t.gatewayType),appendJsonField(n,`statusCode`,t.statusCode),appendJsonField(n,`generationId`,t.generationId),appendJsonField(n,`upstreamStatusCode`,t.upstreamStatusCode),appendJsonField(n,`upstreamType`,t.upstreamType),appendJsonField(n,`upstreamMessage`,t.upstreamMessage),appendJsonField(n,`responseBodySnippet`,t.responseBodySnippet),n}function readErrorName(t){if(t instanceof Error||isObject(t)&&typeof t.name==`string`)return t.name}function readErrorMessage(t){return t instanceof Error||isObject(t)&&typeof t.message==`string`?t.message:``}var EmptyModelResponseError=class extends Error{constructor(e){super(`The model did not return a response. Please try again.`,e),this.name=`EmptyModelResponseError`}};function normalizeModelStreamError(e){let n=toError(e);return n===e||Object.defineProperty(n,"cause",{configurable:!0,value:e}),n}function isNoOutputGeneratedError(e){for(let t of walkCauseChain(e))if(readErrorName(t)===`AI_NoOutputGeneratedError`)return!0;return!1}function classifyModelCallError(e){if(isTurnCancellation(e))return`terminal`;if(e instanceof EmptyModelResponseError)return`recoverable`;if(hasRetryableFlag(e))return`retry`;if(summarizeKnownModelCallConfigError(e)!==null)return`terminal`;let t=readModelCallErrorSignals(e);if(isRetryableGatewayType(t.gatewayType)||isRetryableGatewayType(t.upstreamType))return`retry`;if(isTerminalGatewayType(t.gatewayType)||isTerminalGatewayType(t.upstreamType)||t.gatewayName===`GatewayInvalidRequestError`)return`terminal`;let r=t.statusCode;if(r!==void 0){if(r===408||r===409||r===429||r>=500)return`retry`;if(isAmbiguousGatewayInternalBadRequest(t))return`recoverable`;if(r>=400&&r<500)return`terminal`}return isLikelyNetworkError(e)?`retry`:`recoverable`}function hasRetryableFlag(t){for(let n of walkCauseChain(t))if(isObject(n)&&n.isRetryable===!0)return!0;return!1}function isLikelyNetworkError(e){if(!(e instanceof Error))return!1;let t=e.message.toLowerCase();return t.includes(`econnreset`)||t.includes(`etimedout`)||t.includes(`eai_again`)||t.includes(`socket hang up`)||t.includes(`network`)||t.includes(`fetch failed`)?!0:e.cause!==void 0&&e.cause!==e?isLikelyNetworkError(e.cause):!1}function readModelCallErrorSignals(e){let t=findGatewayError(e),n=findUpstreamApiCallError(e),r=readStringField(n,`responseBody`),i=readGatewayErrorBody(n);return{gatewayName:readErrorName(t),gatewayType:readStringField(t,`type`),generationId:readStringField(t,`generationId`)??i?.generationId,responseBodySnippet:r===void 0?void 0:truncateSnippet(r,1e3),statusCode:readStatusCode(t)??readStatusCode(n)??findStatusCode(e),upstreamMessage:i?.message,upstreamStatusCode:readStatusCode(n),upstreamType:i?.type}}function findGatewayError(e){for(let t of walkCauseChain(e)){let e=readErrorName(t),n=readStringField(t,`type`);if(e?.startsWith(`Gateway`)||n?.endsWith(`_error`)||n===`rate_limit_exceeded`)return t}}function findUpstreamApiCallError(e){for(let t of walkCauseChain(e))if(readErrorName(t)===`AI_APICallError`||readStringField(t,`responseBody`)!==void 0||readObjectField(t,`data`)!==void 0||readObjectField(t,`requestBodyValues`)!==void 0)return t}function readGatewayErrorBody(e){let t=readGatewayErrorBodyFromValue(readObjectField(e,`data`));if(t!==void 0)return t;let n=readStringField(e,`responseBody`);if(n!==void 0)try{return readGatewayErrorBodyFromValue(JSON.parse(n))}catch{return}}function readGatewayErrorBodyFromValue(t){if(!isObject(t))return;let n=readObjectField(t,`error`);if(n===void 0)return;let r=readStringField(t,`generationId`),i=readStringField(n,`message`),a=readStringField(n,`type`);return i===void 0&&a===void 0&&r===void 0?void 0:{generationId:r,message:i,type:a}}function readStatusCode(t){if(isObject(t))return typeof t.statusCode==`number`?t.statusCode:void 0}function findStatusCode(e){for(let t of walkCauseChain(e)){let e=readStatusCode(t);if(e!==void 0)return e}}function readStringField(t,n){if(!isObject(t))return;let r=t[n];return typeof r==`string`&&r.length>0?r:void 0}function readObjectField(t,n){if(!isObject(t))return;let r=t[n];return isObject(r)?r:void 0}function isRetryableGatewayType(e){return e===`overloaded_error`||e===`rate_limit_exceeded`||e===`timeout_error`}function isTerminalGatewayType(e){return e===`authentication_error`||e===`invalid_request_error`||e===`model_not_found`}function isGatewayErrorSignal(e){return e.gatewayName!==void 0||e.gatewayType!==void 0}function isAmbiguousGatewayInternalBadRequest(e){return e.statusCode===400&&(e.gatewayName===`GatewayInternalServerError`||e.gatewayType===`internal_server_error`)&&(e.upstreamType===void 0||e.upstreamType===`internal_server_error`)}function*walkCauseChain(t){let n=new Set,r=t;for(;isObject(r)&&!n.has(r);)n.add(r),yield r,r=r.cause}function appendJsonField(e,t,n){if(typeof n==`string`&&n.length>0){e[t]=n;return}typeof n==`number`&&Number.isFinite(n)&&(e[t]=n)}function truncateSnippet(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}export{EmptyModelResponseError,GATEWAY_AUTHENTICATION_ERROR_NAME,GATEWAY_AUTH_FAILURE_SUMMARY_NAME,classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,isNoOutputGeneratedError,normalizeModelStreamError,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError};
@@ -68,16 +68,25 @@ export declare function applyLastToolCacheBreakpoint(tools: ToolSet, marker: Ant
68
68
  */
69
69
  export declare function applySystemCacheBreakpoint(instructions: readonly SystemModelMessage[], marker: AnthropicCacheMarker): SystemModelMessage[];
70
70
  /**
71
- * Walks backward through `messages` and attaches the Anthropic cache marker
72
- * to the most recent `assistant` and most recent `user` message. Returns a
73
- * new array; does not mutate the input.
71
+ * Attaches the Anthropic cache marker to the last message in `messages`
72
+ * (whatever its role) and, as a stable mid-history anchor, to the most
73
+ * recent `assistant` message before it. Returns a new array; does not
74
+ * mutate the input.
74
75
  *
75
- * This implements the "automatic cache advancement" pattern: each turn the
76
- * breakpoints move forward, and the prior turn's breakpoints still warm the
77
- * cache prefix, so the new breakpoints just extend the cached region.
76
+ * The final breakpoint must sit on the very last message so that the
77
+ * newest content typically a `tool` message carrying fresh tool
78
+ * results is written to the cache in the same request that pays for
79
+ * it. Placing it any earlier (e.g. on the last assistant message) leaves
80
+ * the trailing tool results outside the cached region: they get billed
81
+ * as uncached input every turn and only enter the cache one request
82
+ * later, capping the effective hit rate near 50%. The AI SDK Anthropic
83
+ * provider maps a message-level marker on a `tool` message to its last
84
+ * tool-result content block.
78
85
  *
79
- * Tool-result messages (`role: "tool"`) are intentionally skipped — the
80
- * adjacent assistant message's cache marker already covers the prefix
81
- * through any preceding tool results.
86
+ * The assistant anchor implements "automatic cache advancement": it
87
+ * guarantees a breakpoint from the prior request survives into the next
88
+ * one, so cache lookups always find the previous prefix even when a step
89
+ * appends more content blocks than Anthropic's backward boundary scan
90
+ * covers.
82
91
  */
83
92
  export declare function applyConversationCacheControl(messages: readonly ModelMessage[], marker: AnthropicCacheMarker): ModelMessage[];
@@ -1 +1 @@
1
- const ANTHROPIC_CACHE_MARKER=Object.freeze({anthropic:Object.freeze({cacheControl:Object.freeze({type:`ephemeral`})})});function detectPromptCachePath(e){return typeof e==`string`?{kind:`gateway-auto`}:(typeof e.provider==`string`?e.provider.toLowerCase():``).includes(`anthropic`)?{kind:`anthropic-direct`}:{kind:`none`}}function getAnthropicCacheMarker(){return ANTHROPIC_CACHE_MARKER}function mergeGatewayAutoCaching(e){let t=e?.gateway!==void 0&&typeof e.gateway==`object`&&e.gateway!==null?e.gateway:void 0,n={...t,caching:t?.caching??`auto`};return{...e,gateway:n}}function applyLastToolCacheBreakpoint(e,t){let n=Object.entries(e);if(n.length===0)return e;let r={};for(let e=0;e<n.length;e++){let[i,a]=n[e];if(e===n.length-1){let e=a.providerOptions!==void 0&&typeof a.providerOptions==`object`?a.providerOptions:void 0;r[i]={...a,providerOptions:{...e,...t}}}else r[i]=a}return r}function applySystemCacheBreakpoint(e,t){if(e.length===0)return[...e];let n=[...e],r=n[n.length-1];return n[n.length-1]={...r,providerOptions:{...r.providerOptions,...t}},n}function applyConversationCacheControl(e,t){if(e.length===0)return[...e];let n=[...e],r=!1,i=!1;for(let e=n.length-1;e>=0&&(!r||!i);e--){let a=n[e];a!==void 0&&(!r&&a.role===`assistant`?(n[e]={...a,providerOptions:{...a.providerOptions,...t}},r=!0):!i&&a.role===`user`&&(n[e]={...a,providerOptions:{...a.providerOptions,...t}},i=!0))}return n}export{applyConversationCacheControl,applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker,mergeGatewayAutoCaching};
1
+ const ANTHROPIC_CACHE_MARKER=Object.freeze({anthropic:Object.freeze({cacheControl:Object.freeze({type:`ephemeral`})})});function detectPromptCachePath(e){return typeof e==`string`?{kind:`gateway-auto`}:(typeof e.provider==`string`?e.provider.toLowerCase():``).includes(`anthropic`)?{kind:`anthropic-direct`}:{kind:`none`}}function getAnthropicCacheMarker(){return ANTHROPIC_CACHE_MARKER}function mergeGatewayAutoCaching(e){let t=e?.gateway!==void 0&&typeof e.gateway==`object`&&e.gateway!==null?e.gateway:void 0,n={...t,caching:t?.caching??`auto`};return{...e,gateway:n}}function applyLastToolCacheBreakpoint(e,t){let n=Object.entries(e);if(n.length===0)return e;let r={};for(let e=0;e<n.length;e++){let[i,a]=n[e];if(e===n.length-1){let e=a.providerOptions!==void 0&&typeof a.providerOptions==`object`?a.providerOptions:void 0;r[i]={...a,providerOptions:{...e,...t}}}else r[i]=a}return r}function applySystemCacheBreakpoint(e,t){if(e.length===0)return[...e];let n=[...e],r=n[n.length-1];return n[n.length-1]={...r,providerOptions:{...r.providerOptions,...t}},n}function applyConversationCacheControl(e,t){if(e.length===0)return[...e];let n=[...e],mark=e=>{let r=n[e];r!==void 0&&(n[e]={...r,providerOptions:{...r.providerOptions,...t}})};mark(n.length-1);for(let e=n.length-2;e>=0;e--)if(n[e]?.role===`assistant`){mark(e);break}return n}export{applyConversationCacheControl,applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker,mergeGatewayAutoCaching};