eve 0.46.0 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/src/channel/schedule.d.ts +1 -0
  3. package/dist/src/channel/schedule.js +1 -1
  4. package/dist/src/chunks/{use-eve-agent-DI2j5XK8.js → use-eve-agent-CacMaX4P.js} +91 -43
  5. package/dist/src/chunks/{use-eve-agent-BH7Z6SDu.js → use-eve-agent-kmlFdOBB.js} +91 -43
  6. package/dist/src/cli/commands/info.d.ts +2 -0
  7. package/dist/src/cli/commands/info.js +2 -2
  8. package/dist/src/cli/dev/tui/prompt-commands.d.ts +2 -0
  9. package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
  10. package/dist/src/cli/dev/tui/runner.d.ts +3 -0
  11. package/dist/src/cli/dev/tui/runner.js +1 -1
  12. package/dist/src/client/message-reducer-primitives.d.ts +8 -0
  13. package/dist/src/client/message-reducer-primitives.js +1 -0
  14. package/dist/src/client/message-reducer-types.d.ts +2 -0
  15. package/dist/src/client/message-reducer.js +1 -1
  16. package/dist/src/compiled/.vendor-stamp.json +3 -2
  17. package/dist/src/compiled/@linqapp/chat-sdk-adapter/index.d.ts +2 -1
  18. package/dist/src/compiled/@linqapp/chat-sdk-adapter/index.js +3 -3
  19. package/dist/src/compiled/@vercel/sandbox/index.js +9 -15
  20. package/dist/src/compiled/@vercel/sandbox-delete/LICENSE +201 -0
  21. package/dist/src/compiled/@vercel/sandbox-delete/_async-retry.d.ts +8 -0
  22. package/dist/src/compiled/@vercel/sandbox-delete/_workflow-serde.d.ts +5 -0
  23. package/dist/src/compiled/@vercel/sandbox-delete/api-client/api-client.d.ts +1730 -0
  24. package/dist/src/compiled/@vercel/sandbox-delete/api-client/api-error.d.ts +29 -0
  25. package/dist/src/compiled/@vercel/sandbox-delete/api-client/base-client.d.ts +39 -0
  26. package/dist/src/compiled/@vercel/sandbox-delete/api-client/file-writer.d.ts +66 -0
  27. package/dist/src/compiled/@vercel/sandbox-delete/api-client/index.d.ts +2 -0
  28. package/dist/src/compiled/@vercel/sandbox-delete/api-client/validators.d.ts +907 -0
  29. package/dist/src/compiled/@vercel/sandbox-delete/api-client/with-retry.d.ts +10 -0
  30. package/dist/src/compiled/@vercel/sandbox-delete/auth/error.d.ts +15 -0
  31. package/dist/src/compiled/@vercel/sandbox-delete/auth/file.d.ts +18 -0
  32. package/dist/src/compiled/@vercel/sandbox-delete/auth/index.d.ts +6 -0
  33. package/dist/src/compiled/@vercel/sandbox-delete/auth/oauth.d.ts +111 -0
  34. package/dist/src/compiled/@vercel/sandbox-delete/auth/poll-for-token.d.ts +28 -0
  35. package/dist/src/compiled/@vercel/sandbox-delete/auth/project.d.ts +40 -0
  36. package/dist/src/compiled/@vercel/sandbox-delete/command.d.ts +292 -0
  37. package/dist/src/compiled/@vercel/sandbox-delete/constants.d.ts +15 -0
  38. package/dist/src/compiled/@vercel/sandbox-delete/execution-context.d.ts +116 -0
  39. package/dist/src/compiled/@vercel/sandbox-delete/filesystem.d.ts +258 -0
  40. package/dist/src/compiled/@vercel/sandbox-delete/index.d.ts +13 -0
  41. package/dist/src/compiled/@vercel/sandbox-delete/index.js +9 -0
  42. package/dist/src/compiled/@vercel/sandbox-delete/network-policy.d.ts +169 -0
  43. package/dist/src/compiled/@vercel/sandbox-delete/proxy.d.ts +55 -0
  44. package/dist/src/compiled/@vercel/sandbox-delete/sandbox-user.d.ts +211 -0
  45. package/dist/src/compiled/@vercel/sandbox-delete/sandbox.d.ts +1258 -0
  46. package/dist/src/compiled/@vercel/sandbox-delete/session.d.ts +435 -0
  47. package/dist/src/compiled/@vercel/sandbox-delete/snapshot.d.ts +238 -0
  48. package/dist/src/compiled/@vercel/sandbox-delete/utils/get-credentials.d.ts +21 -0
  49. package/dist/src/compiled/@vercel/sandbox-delete/utils/paginator.d.ts +16 -0
  50. package/dist/src/compiled/@vercel/sandbox-delete/utils/resolveSignal.d.ts +15 -0
  51. package/dist/src/compiled/@vercel/sandbox-delete/utils/sandbox-snapshot.d.ts +11 -0
  52. package/dist/src/compiled/@vercel/sandbox-delete/utils/types.d.ts +11 -0
  53. package/dist/src/compiled/_chunks/node/auth-DpzFWvTn.js +2 -0
  54. package/dist/src/compiled/_chunks/node/auth-QgeX8nBM.js +2 -0
  55. package/dist/src/compiled/_chunks/node/decode_jwt-Col8JOnf.js +7 -0
  56. package/dist/src/compiled/_chunks/node/version-DH6yRy-M.js +1 -0
  57. package/dist/src/compiled/_chunks/node/xdg-app-paths-Bys8q02u.js +1 -0
  58. package/dist/src/compiler/extension-compatibility.d.ts +20 -20
  59. package/dist/src/compiler/extension-compatibility.js +1 -1
  60. package/dist/src/compiler/model-catalog.js +1 -1
  61. package/dist/src/context/build-callback-context.js +1 -1
  62. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  63. package/dist/src/context/keys.d.ts +2 -0
  64. package/dist/src/context/keys.js +1 -1
  65. package/dist/src/context/memory-tools.js +1 -1
  66. package/dist/src/context/providers/sandbox.js +1 -1
  67. package/dist/src/evals/context.js +1 -1
  68. package/dist/src/evals/session-content.d.ts +5 -0
  69. package/dist/src/evals/session-content.js +3 -0
  70. package/dist/src/evals/session.d.ts +1 -0
  71. package/dist/src/evals/session.js +1 -1
  72. package/dist/src/evals/types.d.ts +5 -0
  73. package/dist/src/execution/dispatch-runtime-actions-shared.js +1 -1
  74. package/dist/src/execution/eve-workflow-attributes.d.ts +3 -0
  75. package/dist/src/execution/eve-workflow-attributes.js +1 -1
  76. package/dist/src/execution/runtime-context.js +1 -1
  77. package/dist/src/execution/sandbox/bindings/docker-base-setup.d.ts +4 -4
  78. package/dist/src/execution/sandbox/bindings/docker-base-setup.js +1 -1
  79. package/dist/src/execution/sandbox/bindings/docker-session.d.ts +1 -1
  80. package/dist/src/execution/sandbox/bindings/docker-session.js +1 -1
  81. package/dist/src/execution/sandbox/bindings/docker.js +1 -1
  82. package/dist/src/execution/sandbox/bindings/just-bash-runtime.js +1 -1
  83. package/dist/src/execution/sandbox/bindings/microsandbox-lifecycle.js +1 -1
  84. package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
  85. package/dist/src/execution/sandbox/bindings/vercel-base-runtime.d.ts +4 -0
  86. package/dist/src/execution/sandbox/bindings/vercel-base-runtime.js +2 -2
  87. package/dist/src/execution/sandbox/bindings/vercel-lifecycle.d.ts +8 -0
  88. package/dist/src/execution/sandbox/bindings/vercel-lifecycle.js +1 -0
  89. package/dist/src/execution/sandbox/bindings/vercel-sdk-types.d.ts +3 -0
  90. package/dist/src/execution/sandbox/bindings/vercel.d.ts +2 -1
  91. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  92. package/dist/src/execution/sandbox/ensure.d.ts +2 -0
  93. package/dist/src/execution/sandbox/ensure.js +1 -1
  94. package/dist/src/execution/sandbox/require-sandbox.js +1 -1
  95. package/dist/src/execution/tasks/parent/tool-execution.js +1 -1
  96. package/dist/src/execution/tools/connection-search.js +2 -2
  97. package/dist/src/execution/tools/file-state.js +1 -1
  98. package/dist/src/execution/tools/load-skill.js +1 -1
  99. package/dist/src/execution/tools/subagent/local.js +1 -1
  100. package/dist/src/execution/workflow-steps.js +1 -1
  101. package/dist/src/harness/approval-delivery-coordinator.js +1 -1
  102. package/dist/src/harness/attachment-staging.js +1 -1
  103. package/dist/src/harness/authorization.js +1 -1
  104. package/dist/src/harness/current-messages.d.ts +15 -0
  105. package/dist/src/harness/current-messages.js +1 -0
  106. package/dist/src/harness/emission.d.ts +1 -8
  107. package/dist/src/harness/emission.js +1 -1
  108. package/dist/src/harness/instrumentation/runtime-context.js +1 -1
  109. package/dist/src/harness/instrumentation/state.js +1 -1
  110. package/dist/src/harness/ordered-stream-emitter.js +1 -1
  111. package/dist/src/harness/step-hooks.js +1 -1
  112. package/dist/src/harness/tool-loop.js +2 -2
  113. package/dist/src/harness/tools.js +1 -1
  114. package/dist/src/internal/application/package.js +1 -1
  115. package/dist/src/internal/model-catalog.js +1 -1
  116. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  117. package/dist/src/protocol/message.d.ts +29 -2
  118. package/dist/src/protocol/message.js +2 -2
  119. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
  120. package/dist/src/public/definitions/connections/tool-call.d.ts +2 -0
  121. package/dist/src/public/definitions/hook.d.ts +1 -0
  122. package/dist/src/public/definitions/sandbox-backend.d.ts +1 -1
  123. package/dist/src/public/sandbox/index.d.ts +1 -1
  124. package/dist/src/runtime/agent/resolve-model.js +1 -1
  125. package/dist/src/runtime/connections/mcp-client.d.ts +1 -1
  126. package/dist/src/runtime/connections/mcp-client.js +1 -1
  127. package/dist/src/runtime/connections/openapi-client.d.ts +1 -1
  128. package/dist/src/runtime/connections/openapi-client.js +1 -1
  129. package/dist/src/runtime/connections/principal.js +1 -1
  130. package/dist/src/runtime/connections/provided-arguments.d.ts +1 -0
  131. package/dist/src/runtime/connections/provided-arguments.js +1 -1
  132. package/dist/src/sandbox/state.d.ts +2 -0
  133. package/dist/src/setup/integrations/registry.js +1 -1
  134. package/dist/src/setup/integrations/shopify/setup.d.ts +20 -0
  135. package/dist/src/setup/integrations/shopify/setup.js +1 -0
  136. package/dist/src/setup/integrations/shopify/templates.d.ts +1 -0
  137. package/dist/src/setup/integrations/shopify/templates.js +88 -0
  138. package/dist/src/setup/scaffold/create/project.js +1 -1
  139. package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
  140. package/dist/src/setup/scaffold/create/web-template.js +4 -2
  141. package/dist/src/shared/connection-types.d.ts +3 -1
  142. package/dist/src/shared/sandbox-backend.d.ts +9 -0
  143. package/dist/src/shared/sandbox-definition.d.ts +5 -4
  144. package/dist/src/shared/sandbox-session.d.ts +4 -1
  145. package/dist/src/svelte/index.js +1 -1
  146. package/dist/src/svelte/use-eve-agent.js +1 -1
  147. package/dist/src/tasks/delivery-policy.d.ts +12 -0
  148. package/dist/src/tasks/delivery-policy.js +1 -0
  149. package/dist/src/tracing/agent-trace-context-store.js +1 -1
  150. package/dist/src/vue/index.js +1 -1
  151. package/dist/src/vue/use-eve-agent.js +1 -1
  152. package/docs/concepts/sessions-runs-and-streaming.md +5 -2
  153. package/docs/connections/mcp.mdx +1 -1
  154. package/docs/connections/openapi.mdx +1 -1
  155. package/docs/evals/cases.mdx +11 -2
  156. package/docs/evals/judge.mdx +15 -0
  157. package/docs/evals/overview.mdx +2 -2
  158. package/docs/guides/client/streaming.mdx +18 -15
  159. package/docs/guides/dev-tui.md +2 -1
  160. package/docs/guides/instrumentation.md +1 -0
  161. package/docs/guides/session-context.md +2 -2
  162. package/docs/sandbox.mdx +25 -2
  163. package/docs/schedules.mdx +2 -0
  164. package/docs/tools/overview.mdx +2 -0
  165. package/package.json +3 -2
  166. package/dist/src/compiled/_chunks/node/auth-BaNbsImr.js +0 -2
@@ -12,6 +12,7 @@ type ProtocolEvent<TType extends HandleMessageStreamEvent["type"]> = Extract<Han
12
12
  * until eve exposes them here.
13
13
  */
14
14
  export interface HookEventMap {
15
+ readonly "action.input.appended": ProtocolEvent<"action.input.appended">;
15
16
  readonly "action.partial": ProtocolEvent<"action.partial">;
16
17
  readonly "action.result": ProtocolEvent<"action.result">;
17
18
  readonly "approval.candidate": ProtocolEvent<"approval.candidate">;
@@ -1,4 +1,4 @@
1
- export type { SandboxBackendHandle, SandboxBackendSessionState, SandboxSeedFile, SandboxBackendTags, SandboxBackendRuntimeContext, SandboxBackendCreateInput, SandboxBackendPrewarmInput, SandboxBackendPrewarmResult, SandboxBackend, } from "#shared/sandbox-backend.js";
1
+ export type { SandboxBackendHandle, SandboxBackendSessionState, SandboxDeleteOptions, SandboxSeedFile, SandboxBackendTags, SandboxBackendRuntimeContext, SandboxBackendCreateInput, SandboxBackendPrewarmInput, SandboxBackendPrewarmResult, SandboxBackend, } from "#shared/sandbox-backend.js";
2
2
  /**
3
3
  * Thrown by a backend's `create` when the requested template was never
4
4
  * provisioned. Run `eve build` or call `prewarmAppSandboxes()` before
@@ -3,7 +3,7 @@
3
3
  * `agent/sandbox/sandbox.ts` when paired with a `workspace/` folder).
4
4
  */
5
5
  export { defineSandbox, type SandboxAncestorReference, type SandboxBootstrapContext, type SandboxBootstrapUseFn, type SandboxCommandResult, type SandboxDefinition, type SandboxParentDefinition, type SandboxParentDefinitionContext, type SandboxParentValue, type SandboxProcess, type SandboxReadBinaryFileOptions, type SandboxReadFileOptions, type SandboxReadTextFileOptions, type SandboxRevalidationKeyFn, type SandboxRunOptions, type SandboxSession, type RuntimeSandboxSession, type SandboxSpawnOptions, type SandboxSessionContext, type SandboxSessionUseFn, type SandboxWriteBinaryFileOptions, type SandboxWriteFileOptions, type SandboxWriteTextFileOptions, } from "#public/definitions/sandbox.js";
6
- export type { SandboxBackend, SandboxBackendCreateInput, SandboxBackendHandle, SandboxBackendPrewarmInput, SandboxBackendRuntimeContext, SandboxBackendSessionState, SandboxSeedFile, } from "#public/definitions/sandbox-backend.js";
6
+ export type { SandboxBackend, SandboxBackendCreateInput, SandboxBackendHandle, SandboxBackendPrewarmInput, SandboxBackendRuntimeContext, SandboxBackendSessionState, SandboxDeleteOptions, SandboxSeedFile, } from "#public/definitions/sandbox-backend.js";
7
7
  export type { SandboxNetworkPolicy } from "#shared/sandbox-network-policy.js";
8
8
  export { SandboxTemplateNotProvisionedError } from "#public/definitions/sandbox-backend.js";
9
9
  export { defaultSandbox as defaultBackend, type DefaultSandboxOptions as DefaultBackendOptions, } from "#public/sandbox/backends/default.js";
@@ -1 +1 @@
1
- import{RuntimeModelMetadataCacheKey}from"#context/keys.js";import{normalizeCatalogModelId}from"#internal/model-catalog.js";import{normalizeAgentDefinition}from"#internal/authored-definition/core.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{parseJsonObject}from"#shared/json.js";import{isDynamicModelDefinition}from"#shared/agent-definition.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{resolveBootstrapRuntimeModel}from"#runtime/agent/bootstrap-model.js";import{resolveMockAuthoredRuntimeModel,shouldMockAuthoredRuntimeModels}from"#runtime/agent/mock-model-adapter.js";import{createRuntimeModelCatalog}from"#runtime/agent/model-catalog.js";async function resolveRuntimeModelReference(e,t){let n=resolveBootstrapRuntimeModel(e);if(n!==null)return n;let r=resolveMockAuthoredRuntimeModel(e);return r===null?isSourceBackedRuntimeModelReference(e)?await loadSourceBackedRuntimeModelReference(e,t):e.id:r}async function loadSourceBackedRuntimeModelReference(e,t){if(t===void 0)throw Error(`Expected a compiled module-map scope to resolve the authored runtime model "${e.id}".`);let r=normalizeAgentDefinition(await loadResolvedModuleExport({definition:e.source,kindLabel:`runtime model "${e.id}"`,moduleMap:t.moduleMap,nodeId:t.nodeId}),`Expected the authored agent config export "${e.source.exportName??`default`}" from "${e.source.logicalPath}" to match the public eve shape.`).model;if(r===void 0)throw Error(`Expected the authored agent config export "${e.source.exportName??`default`}" from "${e.source.logicalPath}" to provide a runtime model.`);if(isDynamicModelDefinition(r))throw Error(`Expected the authored agent config export "${e.source.exportName??`default`}" from "${e.source.logicalPath}" to provide a static runtime model.`);return r}function isSourceBackedRuntimeModelReference(e){return e.source!==void 0}async function loadDynamicRuntimeModelDefinition(e){let t=normalizeAgentDefinition(await loadResolvedModuleExport({definition:e.dynamicModel,kindLabel:`dynamic runtime model`,moduleMap:e.scope.moduleMap,nodeId:e.scope.nodeId}),`Expected the authored agent config export "${e.dynamicModel.exportName??`default`}" from "${e.dynamicModel.logicalPath}" to match the public eve shape.`).model;if(!isDynamicModelDefinition(t))throw Error(`Expected the authored agent config export "${e.dynamicModel.exportName??`default`}" from "${e.dynamicModel.logicalPath}" to provide a dynamic model definition.`);return t}async function resolveRuntimeModelSelection(e){if(e.selection===null||e.selection===void 0)throw Error(`Dynamic model resolver returned no model. Every matching dynamic model handler must return a concrete model selection.`);let n=normalizeDynamicModelSelection(e.selection);validateDynamicModelSelection(n);let i=n.modelOptions?.providerOptions===void 0?void 0:parseProviderOptionsRecord(n.modelOptions.providerOptions),a=n.model,o=e.catalog??runtimeModelCatalogForState(e.state);if(typeof a==`string`){let s=formatLanguageModelGatewayId(a),c=await resolveSelectionMetadata({cacheKey:`gateway:${normalizeCatalogModelId(s)}`,catalog:o,contextWindowTokens:n.modelContextWindowTokens,load:e=>e.getByGatewayId(s),modelLabel:s,state:e.state});return{reference:{id:c.resolvedModelId,contextWindowTokens:c.contextWindowTokens,maxOutputTokens:c.maxOutputTokens,providerOptions:i}}}if(validateRuntimeLanguageModel(a),e.durability===`durable`)throw Error(`Dynamic model selection returned a provider object, but durable model selections must be serializable. Return a model id string, or use a "step.started" model resolver.`);let s=formatLanguageModelGatewayId(a),c=a.provider.split(`.`)[0],l=await resolveSelectionMetadata({cacheKey:c===`gateway`?`gateway:${normalizeCatalogModelId(a.modelId)}`:`provider:${a.provider}:${normalizeCatalogModelId(a.modelId)}`,catalog:o,contextWindowTokens:n.modelContextWindowTokens,load:e=>c===`gateway`?e.getByGatewayId(a.modelId):e.getByProviderModelId(a.provider,a.modelId),modelLabel:s,state:e.state});return{model:a,reference:{id:l.resolvedModelId,contextWindowTokens:l.contextWindowTokens,maxOutputTokens:l.maxOutputTokens,providerOptions:i}}}const runtimeModelCatalogsByState=new WeakMap;function runtimeModelCatalogForState(e){let t=runtimeModelCatalogsByState.get(e);if(t!==void 0)return t;let n=createRuntimeModelCatalog();return runtimeModelCatalogsByState.set(e,n),n}async function resolveSelectionMetadata(t){if(t.contextWindowTokens!==void 0)return{contextWindowTokens:t.contextWindowTokens,resolvedModelId:t.modelLabel};let n=Date.now(),r=t.state.get(RuntimeModelMetadataCacheKey)?.[t.cacheKey];if(r!==void 0&&r.expiresAt>n)return r;let i=await t.load(t.catalog);if(i===null)throw Error(`Cannot select model "${t.modelLabel}" because AI Gateway did not provide context window metadata. Return modelContextWindowTokens with this selection for an unlisted or custom model.`);let a={...i,expiresAt:n+864e5};return t.state.set(RuntimeModelMetadataCacheKey,e=>({...Object.fromEntries(Object.entries(e??{}).filter(([,e])=>e.expiresAt>n)),[t.cacheKey]:a})),a}const DYNAMIC_MODEL_SELECTION_KEYS=new Set([`model`,`modelContextWindowTokens`,`modelOptions`]);function validateDynamicModelSelection(e){let t=Object.keys(e).filter(e=>!DYNAMIC_MODEL_SELECTION_KEYS.has(e));if(t.length>0)throw Error(`Dynamic model resolver returned a selection with unknown key(s): ${t.join(`, `)}. Expected { model, modelContextWindowTokens?, modelOptions? }.`);let n=e.modelContextWindowTokens;if(n!==void 0&&(!Number.isInteger(n)||n<=0))throw Error(`Dynamic model resolver returned an invalid modelContextWindowTokens value. Expected a positive integer.`);if(typeof e.model==`string`&&e.model.trim()===``)throw Error(`Dynamic model resolver returned an empty model id.`)}function normalizeDynamicModelSelection(e){return isModelSelectionDefinition(e)?e:{model:e}}function isModelSelectionDefinition(e){return typeof e==`object`&&!!e&&`model`in e&&!isRuntimeLanguageModel(e)}function validateRuntimeLanguageModel(e){if(!isRuntimeLanguageModel(e))throw Error(`Dynamic model resolver returned an invalid model. Return an AI Gateway model id string, an AI SDK language model, or { model, modelContextWindowTokens?, modelOptions? }.`)}function isRuntimeLanguageModel(e){if(typeof e!=`object`||!e)return!1;let t=e;return(t.specificationVersion===`v2`||t.specificationVersion===`v3`||t.specificationVersion===`v4`)&&typeof t.provider==`string`&&typeof t.modelId==`string`&&typeof t.doGenerate==`function`&&typeof t.doStream==`function`}function parseProviderOptionsRecord(e){if(e===void 0)return;let t={};for(let[n,r]of Object.entries(e))t[n]=parseJsonObject(r);return t}export{isRuntimeLanguageModel,loadDynamicRuntimeModelDefinition,resolveRuntimeModelReference,resolveRuntimeModelSelection,shouldMockAuthoredRuntimeModels};
1
+ import{RuntimeModelMetadataCacheKey}from"#context/keys.js";import{normalizeAgentDefinition}from"#internal/authored-definition/core.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{parseJsonObject}from"#shared/json.js";import{isDynamicModelDefinition}from"#shared/agent-definition.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{resolveBootstrapRuntimeModel}from"#runtime/agent/bootstrap-model.js";import{resolveMockAuthoredRuntimeModel,shouldMockAuthoredRuntimeModels}from"#runtime/agent/mock-model-adapter.js";import{createRuntimeModelCatalog}from"#runtime/agent/model-catalog.js";async function resolveRuntimeModelReference(e,t){let n=resolveBootstrapRuntimeModel(e);if(n!==null)return n;let r=resolveMockAuthoredRuntimeModel(e);return r===null?isSourceBackedRuntimeModelReference(e)?await loadSourceBackedRuntimeModelReference(e,t):e.id:r}async function loadSourceBackedRuntimeModelReference(e,n){if(n===void 0)throw Error(`Expected a compiled module-map scope to resolve the authored runtime model "${e.id}".`);let r=normalizeAgentDefinition(await loadResolvedModuleExport({definition:e.source,kindLabel:`runtime model "${e.id}"`,moduleMap:n.moduleMap,nodeId:n.nodeId}),`Expected the authored agent config export "${e.source.exportName??`default`}" from "${e.source.logicalPath}" to match the public eve shape.`).model;if(r===void 0)throw Error(`Expected the authored agent config export "${e.source.exportName??`default`}" from "${e.source.logicalPath}" to provide a runtime model.`);if(isDynamicModelDefinition(r))throw Error(`Expected the authored agent config export "${e.source.exportName??`default`}" from "${e.source.logicalPath}" to provide a static runtime model.`);return r}function isSourceBackedRuntimeModelReference(e){return e.source!==void 0}async function loadDynamicRuntimeModelDefinition(e){let n=normalizeAgentDefinition(await loadResolvedModuleExport({definition:e.dynamicModel,kindLabel:`dynamic runtime model`,moduleMap:e.scope.moduleMap,nodeId:e.scope.nodeId}),`Expected the authored agent config export "${e.dynamicModel.exportName??`default`}" from "${e.dynamicModel.logicalPath}" to match the public eve shape.`).model;if(!isDynamicModelDefinition(n))throw Error(`Expected the authored agent config export "${e.dynamicModel.exportName??`default`}" from "${e.dynamicModel.logicalPath}" to provide a dynamic model definition.`);return n}async function resolveRuntimeModelSelection(e){if(e.selection===null||e.selection===void 0)throw Error(`Dynamic model resolver returned no model. Every matching dynamic model handler must return a concrete model selection.`);let t=normalizeDynamicModelSelection(e.selection);validateDynamicModelSelection(t);let r=t.modelOptions?.providerOptions===void 0?void 0:parseProviderOptionsRecord(t.modelOptions.providerOptions),i=t.model,a=e.catalog??runtimeModelCatalogForState(e.state);if(typeof i==`string`){let o=formatLanguageModelGatewayId(i),s=await resolveSelectionMetadata({cacheKey:`gateway:${o}`,catalog:a,contextWindowTokens:t.modelContextWindowTokens,load:e=>e.getByGatewayId(o),modelLabel:o,state:e.state});return{reference:{id:s.resolvedModelId,contextWindowTokens:s.contextWindowTokens,maxOutputTokens:s.maxOutputTokens,providerOptions:r}}}if(validateRuntimeLanguageModel(i),e.durability===`durable`)throw Error(`Dynamic model selection returned a provider object, but durable model selections must be serializable. Return a model id string, or use a "step.started" model resolver.`);let o=formatLanguageModelGatewayId(i),s=i.provider.split(`.`)[0],c=await resolveSelectionMetadata({cacheKey:s===`gateway`?`gateway:${i.modelId}`:`provider:${i.provider}:${i.modelId}`,catalog:a,contextWindowTokens:t.modelContextWindowTokens,load:e=>s===`gateway`?e.getByGatewayId(i.modelId):e.getByProviderModelId(i.provider,i.modelId),modelLabel:o,state:e.state});return{model:i,reference:{id:c.resolvedModelId,contextWindowTokens:c.contextWindowTokens,maxOutputTokens:c.maxOutputTokens,providerOptions:r}}}const runtimeModelCatalogsByState=new WeakMap;function runtimeModelCatalogForState(e){let t=runtimeModelCatalogsByState.get(e);if(t!==void 0)return t;let n=createRuntimeModelCatalog();return runtimeModelCatalogsByState.set(e,n),n}async function resolveSelectionMetadata(t){if(t.contextWindowTokens!==void 0)return{contextWindowTokens:t.contextWindowTokens,resolvedModelId:t.modelLabel};let n=Date.now(),r=t.state.get(RuntimeModelMetadataCacheKey)?.[t.cacheKey];if(r!==void 0&&r.expiresAt>n)return r;let i=await t.load(t.catalog);if(i===null)throw Error(`Cannot select model "${t.modelLabel}" because AI Gateway did not provide context window metadata. Return modelContextWindowTokens with this selection for an unlisted or custom model.`);let a={...i,expiresAt:n+864e5};return t.state.set(RuntimeModelMetadataCacheKey,e=>({...Object.fromEntries(Object.entries(e??{}).filter(([,e])=>e.expiresAt>n)),[t.cacheKey]:a})),a}const DYNAMIC_MODEL_SELECTION_KEYS=new Set([`model`,`modelContextWindowTokens`,`modelOptions`]);function validateDynamicModelSelection(e){let t=Object.keys(e).filter(e=>!DYNAMIC_MODEL_SELECTION_KEYS.has(e));if(t.length>0)throw Error(`Dynamic model resolver returned a selection with unknown key(s): ${t.join(`, `)}. Expected { model, modelContextWindowTokens?, modelOptions? }.`);let n=e.modelContextWindowTokens;if(n!==void 0&&(!Number.isInteger(n)||n<=0))throw Error(`Dynamic model resolver returned an invalid modelContextWindowTokens value. Expected a positive integer.`);if(typeof e.model==`string`&&e.model.trim()===``)throw Error(`Dynamic model resolver returned an empty model id.`)}function normalizeDynamicModelSelection(e){return isModelSelectionDefinition(e)?e:{model:e}}function isModelSelectionDefinition(e){return typeof e==`object`&&!!e&&`model`in e&&!isRuntimeLanguageModel(e)}function validateRuntimeLanguageModel(e){if(!isRuntimeLanguageModel(e))throw Error(`Dynamic model resolver returned an invalid model. Return an AI Gateway model id string, an AI SDK language model, or { model, modelContextWindowTokens?, modelOptions? }.`)}function isRuntimeLanguageModel(e){if(typeof e!=`object`||!e)return!1;let t=e;return(t.specificationVersion===`v2`||t.specificationVersion===`v3`||t.specificationVersion===`v4`)&&typeof t.provider==`string`&&typeof t.modelId==`string`&&typeof t.doGenerate==`function`&&typeof t.doStream==`function`}function parseProviderOptionsRecord(e){if(e===void 0)return;let t={};for(let[n,i]of Object.entries(e))t[n]=parseJsonObject(i);return t}export{isRuntimeLanguageModel,loadDynamicRuntimeModelDefinition,resolveRuntimeModelReference,resolveRuntimeModelSelection,shouldMockAuthoredRuntimeModels};
@@ -44,7 +44,7 @@ export declare class McpConnectionClient implements ConnectionClient {
44
44
  * so callers re-enter the authorization flow instead of surfacing an
45
45
  * opaque transport error.
46
46
  */
47
- executeTool(toolName: string, args: unknown, options?: ConnectionToolExecuteOptions): Promise<unknown>;
47
+ executeTool(toolName: string, args: unknown, options: ConnectionToolExecuteOptions): Promise<unknown>;
48
48
  close(): Promise<void>;
49
49
  }
50
50
  /**
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{ConnectionAuthorizationRequiredError}from"#connections/errors.js";import{evictScopedToken,resolveScopedToken}from"#runtime/connections/scoped-authorization.js";import{resolveConnectionAuthorization}from"#runtime/connections/resolve-authorization.js";import{createMCPClient}from"#compiled/@ai-sdk/mcp/index.js";import{omitProvidedArgumentsFromSchema,resolveProvidedArguments}from"#runtime/connections/provided-arguments.js";var McpConnectionClient=class{#e;#t;#n;#r;#i;constructor(e){this.#i=e}async connect(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#a();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#a(){let e=await resolveHeaders(this.#i),t=this.#i.url;try{return await createMCPClient({transport:{type:`http`,url:t,headers:e}})}catch(n){if(!isMcpHttpFallbackRetryableError(n))throw n;return await createMCPClient({transport:{type:`sse`,url:t,headers:e}})}}async getToolMetadata(){return(await this.#o()).metadata}async getTools(){return(await this.#o()).tools}async executeTool(e,t,n){try{let{tools:r}=await this.#o(),i=r[e];if(i?.execute===void 0)throw Error(`Tool "${e}" not found in connection "${this.#i.connectionName}".`);let a=await resolveProvidedArguments({args:t,connection:this.#i,toolName:e});return await i.execute(a,{abortSignal:n?.abortSignal})}catch(e){return await this.#l(e)}}async#o(){if(this.#r!==void 0)return this.#r;if(this.#n!==void 0)return this.#n;this.#n=this.#s();try{return this.#r=await this.#n,this.#r}catch(e){throw this.#n=void 0,e}}async#s(){try{return await this.#c()}catch(e){return await this.#l(e)}}async#c(){let e=await this.connect(),t=await e.listTools(),n=this.#i.tools,r=n===void 0?t.tools:t.tools.filter(e=>passesToolFilter(e.name,n)),i=Object.keys(this.#i.toolCall?.providedArguments??{}),a=r.map(e=>({...e,inputSchema:omitProvidedArgumentsFromSchema(e.inputSchema,i)})),o=e.toolsFromDefinitions({tools:a});return{metadata:a.map(e=>({annotations:e.annotations,description:e.description??``,inputSchema:e.inputSchema??{},name:e.name,outputSchema:`outputSchema`in e&&e.outputSchema!==void 0?e.outputSchema:void 0})),tools:o}}async close(){this.#t!==void 0&&(await this.#t.close(),this.#t=void 0),this.#e=void 0,this.#n=void 0,this.#r=void 0}async#l(e){throw isMcpAuthRequiredError(e)?(await this.#u(),await this.close(),new ConnectionAuthorizationRequiredError(this.#i.connectionName,{message:`Connection "${this.#i.connectionName}" requires authorization (the server rejected the token).`})):e}async#u(){let e=await resolveConnectionAuthorization(this.#i);e!==void 0&&await evictScopedToken({authorization:e,connection:{url:this.#i.url},scope:this.#i.connectionName})}};function isMcpAuthRequiredError(e){return readHttpStatus(e)===401}function isMcpHttpFallbackRetryableError(e){let t=readHttpStatus(e);return t===400||t===404||t===405}function readHttpStatus(t){for(let n of walkErrorChain(t)){if(!isObject(n))continue;let t=readStatusField(n);if(t!==void 0)return t;let r=n.response;if(isObject(r)){let e=readStatusField(r);if(e!==void 0)return e}if(typeof n.message==`string`){let e=/\bHTTP\s+(\d{3})\b/u.exec(n.message);if(e?.[1]!==void 0)return Number(e[1])}}}function readStatusField(e){if(typeof e.status==`number`)return e.status;if(typeof e.statusCode==`number`)return e.statusCode}function*walkErrorChain(t){let n=t,r=new Set;for(;n!=null&&!r.has(n);){if(r.add(n),yield n,!isObject(n)||!(`cause`in n))return;n=n.cause}}function passesToolFilter(e,t){return t===void 0?!0:`allow`in t?t.allow.includes(e):!t.block.includes(e)}async function resolveHeaders(e){let n={},r,getCallbackContext=()=>r??=buildCallbackContext(),i=await resolveConnectionAuthorization(e,typeof e.authorization==`function`?getCallbackContext():void 0);if(i!==void 0&&(n.Authorization=`Bearer ${(await resolveToken(e,i)).token}`),e.headers!==void 0){let t=await resolveHeadersDefinition(e.headers,getCallbackContext);for(let[r,a]of Object.entries(t)){if(i!==void 0&&r.toLowerCase()===`authorization`)throw Error(`Connection "${e.connectionName}" headers must not include an "Authorization" key when "authorization" is also provided.`);n[r]=a}}return n}async function resolveToken(e,t){return await resolveScopedToken({authorization:t,connection:{url:e.url},scope:e.connectionName})}async function resolveHeadersDefinition(e,t){if(typeof e==`function`)return{...await e(t())};let n={},r=Object.entries(e);for(let[e,i]of r)n[e]=await resolveHeaderValue(i,t);return n}async function resolveHeaderValue(e,t){return typeof e==`function`?await e(t()):await e}export{McpConnectionClient,isMcpAuthRequiredError,passesToolFilter,resolveHeaders};
1
+ import{isObject}from"#shared/guards.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{ConnectionAuthorizationRequiredError}from"#connections/errors.js";import{evictScopedToken,resolveScopedToken}from"#runtime/connections/scoped-authorization.js";import{resolveConnectionAuthorization}from"#runtime/connections/resolve-authorization.js";import{createMCPClient}from"#compiled/@ai-sdk/mcp/index.js";import{omitProvidedArgumentsFromSchema,resolveProvidedArguments}from"#runtime/connections/provided-arguments.js";var McpConnectionClient=class{#e;#t;#n;#r;#i;constructor(e){this.#i=e}async connect(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#a();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#a(){let e=await resolveHeaders(this.#i),t=this.#i.url;try{return await createMCPClient({transport:{type:`http`,url:t,headers:e}})}catch(n){if(!isMcpHttpFallbackRetryableError(n))throw n;return await createMCPClient({transport:{type:`sse`,url:t,headers:e}})}}async getToolMetadata(){return(await this.#o()).metadata}async getTools(){return(await this.#o()).tools}async executeTool(e,t,n){try{let{tools:r}=await this.#o(),i=r[e];if(i?.execute===void 0)throw Error(`Tool "${e}" not found in connection "${this.#i.connectionName}".`);let a=await resolveProvidedArguments({args:t,callId:n.callId,connection:this.#i,toolName:e});return await i.execute(a,{abortSignal:n.abortSignal})}catch(e){return await this.#l(e)}}async#o(){if(this.#r!==void 0)return this.#r;if(this.#n!==void 0)return this.#n;this.#n=this.#s();try{return this.#r=await this.#n,this.#r}catch(e){throw this.#n=void 0,e}}async#s(){try{return await this.#c()}catch(e){return await this.#l(e)}}async#c(){let e=await this.connect(),t=await e.listTools(),n=this.#i.tools,r=n===void 0?t.tools:t.tools.filter(e=>passesToolFilter(e.name,n)),i=Object.keys(this.#i.toolCall?.providedArguments??{}),a=r.map(e=>({...e,inputSchema:omitProvidedArgumentsFromSchema(e.inputSchema,i)})),o=e.toolsFromDefinitions({tools:a});return{metadata:a.map(e=>({annotations:e.annotations,description:e.description??``,inputSchema:e.inputSchema??{},name:e.name,outputSchema:`outputSchema`in e&&e.outputSchema!==void 0?e.outputSchema:void 0})),tools:o}}async close(){this.#t!==void 0&&(await this.#t.close(),this.#t=void 0),this.#e=void 0,this.#n=void 0,this.#r=void 0}async#l(e){throw isMcpAuthRequiredError(e)?(await this.#u(),await this.close(),new ConnectionAuthorizationRequiredError(this.#i.connectionName,{message:`Connection "${this.#i.connectionName}" requires authorization (the server rejected the token).`})):e}async#u(){let e=await resolveConnectionAuthorization(this.#i);e!==void 0&&await evictScopedToken({authorization:e,connection:{url:this.#i.url},scope:this.#i.connectionName})}};function isMcpAuthRequiredError(e){return readHttpStatus(e)===401}function isMcpHttpFallbackRetryableError(e){let t=readHttpStatus(e);return t===400||t===404||t===405}function readHttpStatus(t){for(let n of walkErrorChain(t)){if(!isObject(n))continue;let t=readStatusField(n);if(t!==void 0)return t;let r=n.response;if(isObject(r)){let e=readStatusField(r);if(e!==void 0)return e}if(typeof n.message==`string`){let e=/\bHTTP\s+(\d{3})\b/u.exec(n.message);if(e?.[1]!==void 0)return Number(e[1])}}}function readStatusField(e){if(typeof e.status==`number`)return e.status;if(typeof e.statusCode==`number`)return e.statusCode}function*walkErrorChain(t){let n=t,r=new Set;for(;n!=null&&!r.has(n);){if(r.add(n),yield n,!isObject(n)||!(`cause`in n))return;n=n.cause}}function passesToolFilter(e,t){return t===void 0?!0:`allow`in t?t.allow.includes(e):!t.block.includes(e)}async function resolveHeaders(e){let n={},r,getCallbackContext=()=>r??=buildCallbackContext(),i=await resolveConnectionAuthorization(e,typeof e.authorization==`function`?getCallbackContext():void 0);if(i!==void 0&&(n.Authorization=`Bearer ${(await resolveToken(e,i)).token}`),e.headers!==void 0){let t=await resolveHeadersDefinition(e.headers,getCallbackContext);for(let[r,a]of Object.entries(t)){if(i!==void 0&&r.toLowerCase()===`authorization`)throw Error(`Connection "${e.connectionName}" headers must not include an "Authorization" key when "authorization" is also provided.`);n[r]=a}}return n}async function resolveToken(e,t){return await resolveScopedToken({authorization:t,connection:{url:e.url},scope:e.connectionName})}async function resolveHeadersDefinition(e,t){if(typeof e==`function`)return{...await e(t())};let n={},r=Object.entries(e);for(let[e,i]of r)n[e]=await resolveHeaderValue(i,t);return n}async function resolveHeaderValue(e,t){return typeof e==`function`?await e(t()):await e}export{McpConnectionClient,isMcpAuthRequiredError,passesToolFilter,resolveHeaders};
@@ -37,7 +37,7 @@ export declare class OpenApiConnectionClient implements ConnectionClient {
37
37
  connect(): Promise<OpenApiToolCache>;
38
38
  getToolMetadata(): Promise<readonly ConnectionToolMetadata[]>;
39
39
  getTools(): Promise<ToolSet>;
40
- executeTool(toolName: string, args: unknown, options?: ConnectionToolExecuteOptions): Promise<OpenApiToolResult>;
40
+ executeTool(toolName: string, args: unknown, options: ConnectionToolExecuteOptions): Promise<OpenApiToolResult>;
41
41
  close(): Promise<void>;
42
42
  }
43
43
  export {};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{isLoopbackHostname}from"#shared/network-address.js";import{isObject}from"#shared/guards.js";import{toInputSchema}from"#tools/schema.js";import{tool}from"ai";import{omitProvidedArgumentsFromSchema,resolveProvidedArguments}from"#runtime/connections/provided-arguments.js";import{passesToolFilter,resolveHeaders}from"#runtime/connections/mcp-client.js";import{HTTP_METHODS,operationDescription,operationName,uniqueName}from"#runtime/connections/openapi-operations.js";import{buildInputSchema,deref,derefSchema,isArray}from"#runtime/connections/openapi-schema.js";import{applySecurity,resolveSecurity}from"#runtime/connections/openapi-security.js";import{extractServerUrl,parseSpecDocument}from"#runtime/connections/openapi-spec.js";const log=createLogger(`runtime.connections.openapi-client`),SWAGGER_PARAMETER_SCHEMA_KEYS=[`default`,`enum`,`exclusiveMaximum`,`exclusiveMinimum`,`format`,`items`,`maximum`,`maxItems`,`maxLength`,`minimum`,`minItems`,`minLength`,`multipleOf`,`pattern`,`type`,`uniqueItems`];var OpenApiConnectionClient=class{#e;#t;#n;constructor(e){this.#n=e}async connect(){return this.#r()}async getToolMetadata(){return(await this.#r()).metadata}async getTools(){return(await this.#r()).tools}async executeTool(e,t,r){let i=await this.#r(),a=i.operations.get(e);if(a===void 0)throw Error(`Tool "${e}" not found in connection "${this.#n.connectionName}".`);return this.#f(a,i.baseUrl,isObject(t)?t:{},{abortSignal:r?.abortSignal})}async close(){this.#e=void 0,this.#t=void 0}async#r(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#i();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#i(){let e=await this.#o(),t=this.#a(e),o=this.#s(e),c=this.#n.tools,l=c===void 0?o:o.filter(e=>passesToolFilter(e.toolName,c)),u=[],d=new Map,f={},p=Object.keys(this.#n.toolCall?.providedArguments??{});for(let e of l){let o=omitProvidedArgumentsFromSchema(e.inputSchema,p),s;try{s=toInputSchema(o)}catch(t){log.warn(`omitting OpenAPI operation with an invalid input schema`,{connectionName:this.#n.connectionName,error:t,toolName:e.toolName});continue}d.set(e.toolName,e),u.push({description:e.description,inputSchema:o,name:e.toolName}),f[e.toolName]=tool({description:e.description,inputSchema:s,execute:async(r,i)=>this.#f(e,t,isObject(r)?r:{},{abortSignal:i?.abortSignal})})}return{metadata:u,operations:d,tools:f,baseUrl:t}}#a(e){let t=this.#n.url,n=typeof t==`string`&&t.trim().length>0?t:extractServerUrl(e,this.#n.spec);if(n===void 0)throw Error(`OpenAPI connection "${this.#n.connectionName}" has no base URL: set "baseUrl" or ensure the document declares an absolute "servers" entry or Swagger "host".`);return assertSecureUrl(n,this.#n.connectionName,`base`),n}async#o(){let e=this.#n.spec;if(e===void 0)throw Error(`OpenAPI connection "${this.#n.connectionName}" is missing its "spec" source.`);if(typeof e!=`string`)return e;assertSecureUrl(e,this.#n.connectionName,`spec`);let t;try{t=await fetch(e,{headers:{accept:`application/json, application/yaml, text/yaml, */*`}})}catch(t){throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${e}": ${String(t)}`)}if(t.redirected&&assertSecureUrl(t.url,this.#n.connectionName,`spec`),!t.ok)throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${e}": HTTP ${t.status}.`);let r=await t.text(),i;try{i=parseSpecDocument(r)}catch(t){throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${e}" could not be parsed as JSON or YAML: ${String(t)}`)}if(!isObject(i))throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${e}" is not an OpenAPI document object.`);return i}#s(e){let t=e.paths;if(!isObject(t))return[];let r=[],i=new Set;for(let[a,o]of Object.entries(t)){if(!isObject(o))continue;let t=isArray(o.parameters)?o.parameters:[];for(let s of HTTP_METHODS){let c=o[s];if(!isObject(c))continue;let l=uniqueName(operationName(c,s,a),i),m=isArray(c.parameters)?c.parameters:[],h=[...t,...m],g=this.#c(e,h),_=this.#l(e,c.requestBody,h);r.push({toolName:l,method:s,pathTemplate:a,description:operationDescription(c),parameters:g,requestBody:_,inputSchema:buildInputSchema(g,_),security:resolveSecurity(e,c)})}}return r}#c(e,t){let r=[];for(let i of t){let t=isObject(i)?deref(e,i):i;if(!isObject(t))continue;let a=t.in;if(a!==`path`&&a!==`query`&&a!==`header`&&a!==`cookie`||typeof t.name!=`string`)continue;let o=this.#u(e,t);r.push({name:t.name,location:a,required:t.required===!0||a===`path`,schema:o,description:typeof t.description==`string`?t.description:void 0})}return r}#l(e,t,r=[]){if(isObject(t)){let r=deref(e,t);if(isObject(r)&&isObject(r.content)){let t=r.content,i=`application/json`in t?`application/json`:Object.keys(t)[0];if(i!==void 0){let a=t[i],o=isObject(a)&&isObject(a.schema)?derefSchema(e,a.schema):{};return{required:r.required===!0,contentType:i,schema:o}}}}return this.#d(e,r)}#u(e,t){if(isObject(t.schema))return derefSchema(e,t.schema);let r={};for(let e of SWAGGER_PARAMETER_SCHEMA_KEYS)t[e]!==void 0&&(r[e]=t[e]);return derefSchema(e,r)}#d(e,t){for(let r of t){let t=isObject(r)?deref(e,r):r;if(!isObject(t)||t.in!==`body`)continue;let i=isObject(t.schema)?derefSchema(e,t.schema):{};return{required:t.required===!0,contentType:`application/json`,schema:i}}}async#f(e,t,n,r){let i=await resolveProvidedArguments({args:n,connection:this.#n,toolName:e.toolName}),a=await resolveHeaders(this.#n),s=e.pathTemplate,l=new URLSearchParams,u=[];for(let t of e.parameters){let e=i[t.name];e!=null&&(t.location===`path`?s=s.replace(`{${t.name}}`,encodeURIComponent(String(e))):t.location===`query`?appendQuery(l,t.name,e):t.location===`cookie`?u.push(`${t.name}=${encodeURIComponent(String(e))}`):a[t.name]=String(e))}if(applySecurity(e.security,this.#n,a,l,u),u.length>0){let e=a.cookie??a.Cookie;delete a.Cookie,a.cookie=[e,...u].filter(e=>!!e).join(`; `)}let d=new URL(joinPath(t,s));d.search=l.toString();let f;e.requestBody!==void 0&&i.body!==void 0&&(f=JSON.stringify(i.body),a[`content-type`]=e.requestBody.contentType);let p=await fetch(d,{method:e.method.toUpperCase(),headers:a,body:f,signal:r?.abortSignal});return{status:p.status,statusText:p.statusText,body:await readResponseBody(p)}}};function appendQuery(e,t,n){if(isArray(n)){for(let r of n)e.append(t,String(r));return}e.append(t,String(n))}function joinPath(e,t){return`${e.endsWith(`/`)?e.slice(0,-1):e}${t.startsWith(`/`)?t:`/${t}`}`}function assertSecureUrl(e,n,r){let i;try{i=new URL(e)}catch{throw Error(`OpenAPI connection "${n}" has an invalid ${r} URL "${e}".`)}if(i.protocol!==`https:`&&!(i.protocol===`http:`&&isLoopbackHostname(i.hostname)))throw Error(`OpenAPI connection "${n}" must use https for its ${r} (got "${i.protocol}//${i.host}").`)}async function readResponseBody(e){let t=await e.text();if(t.length===0)return null;if((e.headers.get(`content-type`)??``).includes(`application/json`))try{return JSON.parse(t)}catch{return t}return t}export{OpenApiConnectionClient};
1
+ import{createLogger}from"#internal/logging.js";import{isLoopbackHostname}from"#shared/network-address.js";import{isObject}from"#shared/guards.js";import{toInputSchema}from"#tools/schema.js";import{tool}from"ai";import{omitProvidedArgumentsFromSchema,resolveProvidedArguments}from"#runtime/connections/provided-arguments.js";import{passesToolFilter,resolveHeaders}from"#runtime/connections/mcp-client.js";import{HTTP_METHODS,operationDescription,operationName,uniqueName}from"#runtime/connections/openapi-operations.js";import{buildInputSchema,deref,derefSchema,isArray}from"#runtime/connections/openapi-schema.js";import{applySecurity,resolveSecurity}from"#runtime/connections/openapi-security.js";import{extractServerUrl,parseSpecDocument}from"#runtime/connections/openapi-spec.js";const log=createLogger(`runtime.connections.openapi-client`),SWAGGER_PARAMETER_SCHEMA_KEYS=[`default`,`enum`,`exclusiveMaximum`,`exclusiveMinimum`,`format`,`items`,`maximum`,`maxItems`,`maxLength`,`minimum`,`minItems`,`minLength`,`multipleOf`,`pattern`,`type`,`uniqueItems`];var OpenApiConnectionClient=class{#e;#t;#n;constructor(e){this.#n=e}async connect(){return this.#r()}async getToolMetadata(){return(await this.#r()).metadata}async getTools(){return(await this.#r()).tools}async executeTool(e,t,r){let i=await this.#r(),a=i.operations.get(e);if(a===void 0)throw Error(`Tool "${e}" not found in connection "${this.#n.connectionName}".`);return this.#f(a,i.baseUrl,isObject(t)?t:{},{abortSignal:r.abortSignal,callId:r.callId})}async close(){this.#e=void 0,this.#t=void 0}async#r(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#i();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#i(){let e=await this.#o(),t=this.#a(e),o=this.#s(e),c=this.#n.tools,l=c===void 0?o:o.filter(e=>passesToolFilter(e.toolName,c)),u=[],d=new Map,f={},p=Object.keys(this.#n.toolCall?.providedArguments??{});for(let e of l){let o=omitProvidedArgumentsFromSchema(e.inputSchema,p),s;try{s=toInputSchema(o)}catch(t){log.warn(`omitting OpenAPI operation with an invalid input schema`,{connectionName:this.#n.connectionName,error:t,toolName:e.toolName});continue}d.set(e.toolName,e),u.push({description:e.description,inputSchema:o,name:e.toolName}),f[e.toolName]=tool({description:e.description,inputSchema:s,execute:async(r,i)=>this.#f(e,t,isObject(r)?r:{},{abortSignal:i?.abortSignal,callId:i.toolCallId})})}return{metadata:u,operations:d,tools:f,baseUrl:t}}#a(e){let t=this.#n.url,n=typeof t==`string`&&t.trim().length>0?t:extractServerUrl(e,this.#n.spec);if(n===void 0)throw Error(`OpenAPI connection "${this.#n.connectionName}" has no base URL: set "baseUrl" or ensure the document declares an absolute "servers" entry or Swagger "host".`);return assertSecureUrl(n,this.#n.connectionName,`base`),n}async#o(){let e=this.#n.spec;if(e===void 0)throw Error(`OpenAPI connection "${this.#n.connectionName}" is missing its "spec" source.`);if(typeof e!=`string`)return e;assertSecureUrl(e,this.#n.connectionName,`spec`);let t;try{t=await fetch(e,{headers:{accept:`application/json, application/yaml, text/yaml, */*`}})}catch(t){throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${e}": ${String(t)}`)}if(t.redirected&&assertSecureUrl(t.url,this.#n.connectionName,`spec`),!t.ok)throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${e}": HTTP ${t.status}.`);let r=await t.text(),i;try{i=parseSpecDocument(r)}catch(t){throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${e}" could not be parsed as JSON or YAML: ${String(t)}`)}if(!isObject(i))throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${e}" is not an OpenAPI document object.`);return i}#s(e){let t=e.paths;if(!isObject(t))return[];let r=[],i=new Set;for(let[a,o]of Object.entries(t)){if(!isObject(o))continue;let t=isArray(o.parameters)?o.parameters:[];for(let s of HTTP_METHODS){let c=o[s];if(!isObject(c))continue;let l=uniqueName(operationName(c,s,a),i),m=isArray(c.parameters)?c.parameters:[],h=[...t,...m],g=this.#c(e,h),_=this.#l(e,c.requestBody,h);r.push({toolName:l,method:s,pathTemplate:a,description:operationDescription(c),parameters:g,requestBody:_,inputSchema:buildInputSchema(g,_),security:resolveSecurity(e,c)})}}return r}#c(e,t){let r=[];for(let i of t){let t=isObject(i)?deref(e,i):i;if(!isObject(t))continue;let a=t.in;if(a!==`path`&&a!==`query`&&a!==`header`&&a!==`cookie`||typeof t.name!=`string`)continue;let o=this.#u(e,t);r.push({name:t.name,location:a,required:t.required===!0||a===`path`,schema:o,description:typeof t.description==`string`?t.description:void 0})}return r}#l(e,t,r=[]){if(isObject(t)){let r=deref(e,t);if(isObject(r)&&isObject(r.content)){let t=r.content,i=`application/json`in t?`application/json`:Object.keys(t)[0];if(i!==void 0){let a=t[i],o=isObject(a)&&isObject(a.schema)?derefSchema(e,a.schema):{};return{required:r.required===!0,contentType:i,schema:o}}}}return this.#d(e,r)}#u(e,t){if(isObject(t.schema))return derefSchema(e,t.schema);let r={};for(let e of SWAGGER_PARAMETER_SCHEMA_KEYS)t[e]!==void 0&&(r[e]=t[e]);return derefSchema(e,r)}#d(e,t){for(let r of t){let t=isObject(r)?deref(e,r):r;if(!isObject(t)||t.in!==`body`)continue;let i=isObject(t.schema)?derefSchema(e,t.schema):{};return{required:t.required===!0,contentType:`application/json`,schema:i}}}async#f(e,t,n,r){let i=await resolveProvidedArguments({args:n,callId:r.callId,connection:this.#n,toolName:e.toolName}),a=await resolveHeaders(this.#n),s=e.pathTemplate,l=new URLSearchParams,u=[];for(let t of e.parameters){let e=i[t.name];e!=null&&(t.location===`path`?s=s.replace(`{${t.name}}`,encodeURIComponent(String(e))):t.location===`query`?appendQuery(l,t.name,e):t.location===`cookie`?u.push(`${t.name}=${encodeURIComponent(String(e))}`):a[t.name]=String(e))}if(applySecurity(e.security,this.#n,a,l,u),u.length>0){let e=a.cookie??a.Cookie;delete a.Cookie,a.cookie=[e,...u].filter(e=>!!e).join(`; `)}let d=new URL(joinPath(t,s));d.search=l.toString();let f;e.requestBody!==void 0&&i.body!==void 0&&(f=JSON.stringify(i.body),a[`content-type`]=e.requestBody.contentType);let p=await fetch(d,{method:e.method.toUpperCase(),headers:a,body:f,signal:r?.abortSignal});return{status:p.status,statusText:p.statusText,body:await readResponseBody(p)}}};function appendQuery(e,t,n){if(isArray(n)){for(let r of n)e.append(t,String(r));return}e.append(t,String(n))}function joinPath(e,t){return`${e.endsWith(`/`)?e.slice(0,-1):e}${t.startsWith(`/`)?t:`/${t}`}`}function assertSecureUrl(e,n,r){let i;try{i=new URL(e)}catch{throw Error(`OpenAPI connection "${n}" has an invalid ${r} URL "${e}".`)}if(i.protocol!==`https:`&&!(i.protocol===`http:`&&isLoopbackHostname(i.hostname)))throw Error(`OpenAPI connection "${n}" must use https for its ${r} (got "${i.protocol}//${i.host}").`)}async function readResponseBody(e){let t=await e.text();if(t.length===0)return null;if((e.headers.get(`content-type`)??``).includes(`application/json`))try{return JSON.parse(t)}catch{return t}return t}export{OpenApiConnectionClient};
@@ -1 +1 @@
1
- import{isVercelOidcIssuer}from"#shared/vercel-project.js";import{AuthKey}from"#context/keys.js";import{contextStorage}from"#context/container.js";import{ConnectionAuthorizationFailedError}from"#connections/errors.js";function principalKey(e){return e.type===`app`?`app`:e.issuer===void 0?`user:${e.id}`:`user:${e.issuer}:${e.id}`}function resolveConnectionPrincipal(e,r,i=contextStorage.getStore()){return resolveConnectionPrincipalFromAuth(e,r,i?.get(AuthKey),i)}function resolveConnectionPrincipalFromAuth(e,t,n,i){if(t.principalType===`app`)return{type:`app`};if(n==null||n.principalType!==`user`)throw new ConnectionAuthorizationFailedError(e,{message:buildUserPrincipalRequiredMessage(e,t,i,n),reason:`principal_required`,retryable:!1});return t.vercelConnect!==void 0&&isVercelDevelopmentUser(n)?{attributes:n.attributes,id:n.subject??n.principalId,type:`user`}:{attributes:n.attributes,id:n.principalId,issuer:n.issuer??n.authenticator,type:`user`}}function isVercelDevelopmentUser(t){return t.authenticator===`oidc`&&isVercelOidcIssuer(t.issuer)&&t.attributes.environment===`development`&&t.subject===t.attributes.user_id}function buildUserPrincipalRequiredMessage(e,t,n,r){let i;return i=n===void 0?`it was invoked outside an eve context, so no authenticated user can be resolved.`:r==null?`the active session has no authenticated user.`:t.vercelConnect!==void 0&&r.authenticator===`local-dev`?`the local request fell back to local development access instead of authenticating a Vercel user. Ensure this directory is linked and the Vercel CLI can mint a Vercel OIDC token, then retry.`:`the active session is scoped to "${r.principalType}", not an authenticated user.`,`Connection "${e}" is user-scoped, but ${i} User-scoped connections require route auth that resolves an authenticated user. If this connection should use credentials shared by the agent instead, configure it as an app-scoped connection.`}export{principalKey,resolveConnectionPrincipal,resolveConnectionPrincipalFromAuth};
1
+ import{isVercelOidcIssuer}from"#shared/vercel-project.js";import{contextStorage}from"#context/container.js";import{AuthKey}from"#context/keys.js";import{ConnectionAuthorizationFailedError}from"#connections/errors.js";function principalKey(e){return e.type===`app`?`app`:e.issuer===void 0?`user:${e.id}`:`user:${e.issuer}:${e.id}`}function resolveConnectionPrincipal(e,r,i=contextStorage.getStore()){return resolveConnectionPrincipalFromAuth(e,r,i?.get(AuthKey),i)}function resolveConnectionPrincipalFromAuth(e,t,n,i){if(t.principalType===`app`)return{type:`app`};if(n==null||n.principalType!==`user`)throw new ConnectionAuthorizationFailedError(e,{message:buildUserPrincipalRequiredMessage(e,t,i,n),reason:`principal_required`,retryable:!1});return t.vercelConnect!==void 0&&isVercelDevelopmentUser(n)?{attributes:n.attributes,id:n.subject??n.principalId,type:`user`}:{attributes:n.attributes,id:n.principalId,issuer:n.issuer??n.authenticator,type:`user`}}function isVercelDevelopmentUser(t){return t.authenticator===`oidc`&&isVercelOidcIssuer(t.issuer)&&t.attributes.environment===`development`&&t.subject===t.attributes.user_id}function buildUserPrincipalRequiredMessage(e,t,n,r){let i;return i=n===void 0?`it was invoked outside an eve context, so no authenticated user can be resolved.`:r==null?`the active session has no authenticated user.`:t.vercelConnect!==void 0&&r.authenticator===`local-dev`?`the local request fell back to local development access instead of authenticating a Vercel user. Ensure this directory is linked and the Vercel CLI can mint a Vercel OIDC token, then retry.`:`the active session is scoped to "${r.principalType}", not an authenticated user.`,`Connection "${e}" is user-scoped, but ${i} User-scoped connections require route auth that resolves an authenticated user. If this connection should use credentials shared by the agent instead, configure it as an app-scoped connection.`}export{principalKey,resolveConnectionPrincipal,resolveConnectionPrincipalFromAuth};
@@ -2,6 +2,7 @@ import type { ResolvedConnectionDefinition } from "#runtime/types.js";
2
2
  /** Resolves and merges application-provided arguments, with application values winning. */
3
3
  export declare function resolveProvidedArguments(input: {
4
4
  readonly args: unknown;
5
+ readonly callId: string;
5
6
  readonly connection: ResolvedConnectionDefinition;
6
7
  readonly toolName: string;
7
8
  }): Promise<Record<string, unknown>>;
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";import{parseJsonValue}from"#shared/json.js";import{buildCallbackContext}from"#context/build-callback-context.js";async function resolveProvidedArguments(r){if(!isObject(r.args))throw Error(`Tool "${r.toolName}" in connection "${r.connection.connectionName}" expected object arguments.`);let i=r.connection.toolCall?.providedArguments;if(i===void 0||Object.keys(i).length===0)return r.args;let a,getContext=()=>a??={...buildCallbackContext(),toolName:r.toolName},o={};for(let[e,n]of Object.entries(i)){let i=typeof n==`function`?await n(getContext()):await n;try{o[e]=parseJsonValue(i)}catch{throw Error(`Connection "${r.connection.connectionName}" provided argument "${e}" must resolve to a JSON-serializable value.`)}}return{...r.args,...o}}function omitProvidedArgumentsFromSchema(t,n){if(n.length===0)return t;let r=new Set(n),i={...t};return isObject(t.properties)&&(i.properties=Object.fromEntries(Object.entries(t.properties).filter(([e])=>!r.has(e)))),Array.isArray(t.required)&&(i.required=t.required.filter(e=>typeof e!=`string`||!r.has(e))),i}export{omitProvidedArgumentsFromSchema,resolveProvidedArguments};
1
+ import{isObject}from"#shared/guards.js";import{parseJsonValue}from"#shared/json.js";import{buildCallbackContext}from"#context/build-callback-context.js";async function resolveProvidedArguments(r){if(!isObject(r.args))throw Error(`Tool "${r.toolName}" in connection "${r.connection.connectionName}" expected object arguments.`);let i=r.connection.toolCall?.providedArguments;if(i===void 0||Object.keys(i).length===0)return r.args;let a,getContext=()=>a??={...buildCallbackContext(),callId:r.callId,toolName:r.toolName},o={};for(let[e,n]of Object.entries(i)){let i=typeof n==`function`?await n(getContext()):await n;try{o[e]=parseJsonValue(i)}catch{throw Error(`Connection "${r.connection.connectionName}" provided argument "${e}" must resolve to a JSON-serializable value.`)}}return{...r.args,...o}}function omitProvidedArgumentsFromSchema(t,n){if(n.length===0)return t;let r=new Set(n),i={...t};return isObject(t.properties)&&(i.properties=Object.fromEntries(Object.entries(t.properties).filter(([e])=>!r.has(e)))),Array.isArray(t.required)&&(i.required=t.required.filter(e=>typeof e!=`string`||!r.has(e))),i}export{omitProvidedArgumentsFromSchema,resolveProvidedArguments};
@@ -1,5 +1,6 @@
1
1
  import type { SandboxSession } from "#public/definitions/sandbox.js";
2
2
  import type { SandboxBackendSessionState } from "#public/definitions/sandbox-backend.js";
3
+ import type { SandboxDeleteOptions } from "#public/definitions/sandbox-backend.js";
3
4
  /**
4
5
  * Serializable sandbox reconnect record stored on the harness session.
5
6
  * Alias for {@link SandboxBackendSessionState} kept at this layer so
@@ -28,6 +29,7 @@ export interface SandboxState {
28
29
  */
29
30
  export interface SandboxAccess {
30
31
  captureState(): Promise<SandboxState>;
32
+ delete?(options?: SandboxDeleteOptions): Promise<void>;
31
33
  get(): Promise<SandboxSession | null>;
32
34
  stop(): Promise<void>;
33
35
  }
@@ -1 +1 @@
1
- import{DISCORD_SETUP}from"./discord/setup.js";import{GITHUB_SETUP}from"./github/setup.js";import{LINEAR_SETUP}from"./linear/setup.js";import{LINQ_SETUP}from"./linq/setup.js";import{PHOTON_SETUP}from"./photon/setup.js";import{SLACK_SETUP}from"./slack/setup.js";import{WEB_SETUP}from"./web/setup.js";import{createSetupContexts,createSetupPresenter}from"./shared/ui.js";const SETUP_INTEGRATIONS=[WEB_SETUP,SLACK_SETUP,DISCORD_SETUP,GITHUB_SETUP,LINEAR_SETUP,LINQ_SETUP,PHOTON_SETUP];function setupIntegration(e){let t=SETUP_INTEGRATIONS.find(t=>t.kind===e);if(t===void 0)throw Error(`Integration setup "${e}" is not available in this version of eve. Upgrade eve and try again.`);return t}export{SETUP_INTEGRATIONS,createSetupContexts,createSetupPresenter,setupIntegration};
1
+ import{DISCORD_SETUP}from"./discord/setup.js";import{GITHUB_SETUP}from"./github/setup.js";import{LINEAR_SETUP}from"./linear/setup.js";import{LINQ_SETUP}from"./linq/setup.js";import{PHOTON_SETUP}from"./photon/setup.js";import{SHOPIFY_SETUP}from"./shopify/setup.js";import{SLACK_SETUP}from"./slack/setup.js";import{WEB_SETUP}from"./web/setup.js";import{createSetupContexts,createSetupPresenter}from"./shared/ui.js";const SETUP_INTEGRATIONS=[WEB_SETUP,SLACK_SETUP,DISCORD_SETUP,GITHUB_SETUP,LINEAR_SETUP,LINQ_SETUP,PHOTON_SETUP,SHOPIFY_SETUP];function setupIntegration(e){let t=SETUP_INTEGRATIONS.find(t=>t.kind===e);if(t===void 0)throw Error(`Integration setup "${e}" is not available in this version of eve. Upgrade eve and try again.`);return t}export{SETUP_INTEGRATIONS,createSetupContexts,createSetupPresenter,setupIntegration};
@@ -0,0 +1,20 @@
1
+ import { appendEnv } from "#setup/append-env.js";
2
+ import { writeTextFile } from "#setup/scaffold/files.js";
3
+ import { type SetupApplyContext, type SetupPrepareContext } from "../types.js";
4
+ export interface ShopifySetupDeps {
5
+ appendEnv: typeof appendEnv;
6
+ writeTextFile: typeof writeTextFile;
7
+ }
8
+ export interface ShopifySetupPlan {
9
+ storeDomain: string;
10
+ }
11
+ export declare function prepareShopifySetup(context: SetupPrepareContext): Promise<ShopifySetupPlan>;
12
+ export declare function applyShopifySetup(plan: ShopifySetupPlan, context: SetupApplyContext, deps?: ShopifySetupDeps): Promise<{
13
+ deploymentRequired: true;
14
+ facts: {
15
+ label: string;
16
+ value: string;
17
+ kind: "text";
18
+ }[];
19
+ }>;
20
+ export declare const SHOPIFY_SETUP: import("../types.js").SetupIntegration;
@@ -0,0 +1 @@
1
+ import{defineSetupIntegration}from"../types.js";import{SHOPIFY_UCP_CHANNEL_TEMPLATE}from"./templates.js";import{join}from"node:path";import{text}from"#setup/ask.js";import{writeTextFile}from"#setup/scaffold/files.js";import{appendEnv}from"#setup/append-env.js";const defaultDeps={appendEnv,writeTextFile};function normalizeStoreDomain(e){return e.trim().replace(/^https?:\/\//i,``).replace(/[/?#].*$/,``)}function validateStoreDomain(e){let t=normalizeStoreDomain(e);try{let e=new URL(`https://${t}`);return t.length>0&&e.hostname.includes(`.`)&&!e.username&&!e.password&&!e.port?null:`Enter a valid Shopify storefront domain.`}catch{return`Enter a valid Shopify storefront domain.`}}async function prepareShopifySetup(e){return{storeDomain:normalizeStoreDomain(await e.asker.ask(text({key:`shopify.store-domain`,message:`Shopify storefront domain`,placeholder:`your-store.myshopify.com`,required:!0,validate:validateStoreDomain})))}}async function applyShopifySetup(e,n,r=defaultDeps){return n.presenter.log.message(`Scaffolding Shopify UCP channel and storefront environment...`),await r.appendEnv(join(n.appRoot,`.env.local`),{SHOPIFY_STORE_DOMAIN:e.storeDomain}),await r.writeTextFile(join(n.appRoot,`agent/channels/ucp.ts`),SHOPIFY_UCP_CHANNEL_TEMPLATE,{force:n.force}),n.presenter.log.success(`Scaffolded channel: ucp`),n.presenter.nextSteps([`Set SHOPIFY_STORE_DOMAIN in .env.local.`,"Shopify cannot reach localhost, so `eve dev` uses Shopify's example agent profile automatically. To test your own profile locally, expose the /.well-known/ucp route with a tool like ngrok."]),{deploymentRequired:!0,facts:[{label:`Store domain`,value:e.storeDomain,kind:`text`}]}}const SHOPIFY_SETUP=defineSetupIntegration({kind:`shopify`,label:`Shopify`,prepare:prepareShopifySetup,apply:applyShopifySetup});export{SHOPIFY_SETUP,applyShopifySetup,prepareShopifySetup};
@@ -0,0 +1 @@
1
+ export declare const SHOPIFY_UCP_CHANNEL_TEMPLATE = "import { defineChannel, GET } from \"eve/channels\";\n\nconst profile = {\n ucp: {\n version: \"2026-04-08\",\n services: {\n \"dev.ucp.shopping\": [\n {\n version: \"2026-04-08\",\n spec: \"https://ucp.dev/2026-04-08/specification/overview\",\n transport: \"mcp\",\n schema: \"https://ucp.dev/2026-04-08/services/shopping/mcp.openrpc.json\",\n },\n ],\n },\n capabilities: {\n \"dev.ucp.shopping.checkout\": [{ version: \"2026-04-08\" }],\n \"dev.ucp.shopping.fulfillment\": [\n {\n version: \"2026-04-08\",\n extends: [\"dev.ucp.shopping.checkout\", \"dev.ucp.shopping.cart\"],\n },\n ],\n \"dev.ucp.shopping.buyer_consent\": [\n {\n version: \"2026-04-08\",\n extends: \"dev.ucp.shopping.checkout\",\n },\n ],\n \"dev.ucp.shopping.discount\": [\n {\n version: \"2026-04-08\",\n extends: [\"dev.ucp.shopping.checkout\", \"dev.ucp.shopping.cart\"],\n },\n ],\n \"dev.ucp.shopping.cart\": [\n {\n version: \"2026-04-08\",\n spec: \"https://ucp.dev/2026-04-08/specification/cart\",\n schema: \"https://ucp.dev/2026-04-08/schemas/shopping/cart.json\",\n },\n ],\n \"dev.ucp.shopping.catalog.search\": [\n {\n version: \"2026-04-08\",\n spec: \"https://ucp.dev/2026-04-08/specification/catalog/search\",\n schema: \"https://ucp.dev/2026-04-08/schemas/shopping/catalog_search.json\",\n },\n ],\n \"dev.ucp.shopping.catalog.lookup\": [\n {\n version: \"2026-04-08\",\n spec: \"https://ucp.dev/2026-04-08/specification/catalog/lookup\",\n schema: \"https://ucp.dev/2026-04-08/schemas/shopping/catalog_lookup.json\",\n },\n ],\n \"dev.shopify.catalog\": [\n {\n version: \"2026-04-08\",\n spec: \"https://shopify.dev/docs/agents/catalog/storefront-catalog\",\n schema: \"https://shopify.dev/ucp/schemas/2026-04-08/shopify_catalog.json\",\n extends: [\n \"dev.ucp.shopping.catalog.lookup\",\n \"dev.ucp.shopping.catalog.search\",\n ],\n },\n ],\n },\n payment_handlers: {},\n },\n};\n\nconst body = JSON.stringify(profile);\n\nexport default defineChannel({\n cors: true,\n routes: [\n GET(\"/.well-known/ucp\", async () => {\n return new Response(body, {\n headers: {\n \"content-type\": \"application/json\",\n \"cache-control\": \"public, max-age=300\",\n },\n });\n }),\n ],\n});\n";
@@ -0,0 +1,88 @@
1
+ const SHOPIFY_UCP_CHANNEL_TEMPLATE=`import { defineChannel, GET } from "eve/channels";
2
+
3
+ const profile = {
4
+ ucp: {
5
+ version: "2026-04-08",
6
+ services: {
7
+ "dev.ucp.shopping": [
8
+ {
9
+ version: "2026-04-08",
10
+ spec: "https://ucp.dev/2026-04-08/specification/overview",
11
+ transport: "mcp",
12
+ schema: "https://ucp.dev/2026-04-08/services/shopping/mcp.openrpc.json",
13
+ },
14
+ ],
15
+ },
16
+ capabilities: {
17
+ "dev.ucp.shopping.checkout": [{ version: "2026-04-08" }],
18
+ "dev.ucp.shopping.fulfillment": [
19
+ {
20
+ version: "2026-04-08",
21
+ extends: ["dev.ucp.shopping.checkout", "dev.ucp.shopping.cart"],
22
+ },
23
+ ],
24
+ "dev.ucp.shopping.buyer_consent": [
25
+ {
26
+ version: "2026-04-08",
27
+ extends: "dev.ucp.shopping.checkout",
28
+ },
29
+ ],
30
+ "dev.ucp.shopping.discount": [
31
+ {
32
+ version: "2026-04-08",
33
+ extends: ["dev.ucp.shopping.checkout", "dev.ucp.shopping.cart"],
34
+ },
35
+ ],
36
+ "dev.ucp.shopping.cart": [
37
+ {
38
+ version: "2026-04-08",
39
+ spec: "https://ucp.dev/2026-04-08/specification/cart",
40
+ schema: "https://ucp.dev/2026-04-08/schemas/shopping/cart.json",
41
+ },
42
+ ],
43
+ "dev.ucp.shopping.catalog.search": [
44
+ {
45
+ version: "2026-04-08",
46
+ spec: "https://ucp.dev/2026-04-08/specification/catalog/search",
47
+ schema: "https://ucp.dev/2026-04-08/schemas/shopping/catalog_search.json",
48
+ },
49
+ ],
50
+ "dev.ucp.shopping.catalog.lookup": [
51
+ {
52
+ version: "2026-04-08",
53
+ spec: "https://ucp.dev/2026-04-08/specification/catalog/lookup",
54
+ schema: "https://ucp.dev/2026-04-08/schemas/shopping/catalog_lookup.json",
55
+ },
56
+ ],
57
+ "dev.shopify.catalog": [
58
+ {
59
+ version: "2026-04-08",
60
+ spec: "https://shopify.dev/docs/agents/catalog/storefront-catalog",
61
+ schema: "https://shopify.dev/ucp/schemas/2026-04-08/shopify_catalog.json",
62
+ extends: [
63
+ "dev.ucp.shopping.catalog.lookup",
64
+ "dev.ucp.shopping.catalog.search",
65
+ ],
66
+ },
67
+ ],
68
+ },
69
+ payment_handlers: {},
70
+ },
71
+ };
72
+
73
+ const body = JSON.stringify(profile);
74
+
75
+ export default defineChannel({
76
+ cors: true,
77
+ routes: [
78
+ GET("/.well-known/ucp", async () => {
79
+ return new Response(body, {
80
+ headers: {
81
+ "content-type": "application/json",
82
+ "cache-control": "public, max-age=300",
83
+ },
84
+ });
85
+ }),
86
+ ],
87
+ });
88
+ `;export{SHOPIFY_UCP_CHANNEL_TEMPLATE};
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.58`,DEFAULT_CONNECT_PACKAGE_VERSION=`1.0.0`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.46.0`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e,t){return{"agent/agent.ts":renderAgentTemplate(e,t),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,n){let r=parseChatGptModelSelection(e);return r===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(n)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(r)}),\n${reasoningTemplateLine(n)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,n){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(n.model)!==void 0?renderAgentTemplate(n.model,n.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,n.appName).replaceAll(`__EVE_INIT_MODEL__`,n.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(n.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(n.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(n.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(n.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,n.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,n.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,n.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,n.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,n.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,n.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.58`,DEFAULT_CONNECT_PACKAGE_VERSION=`1.0.0`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.47.0`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e,t){return{"agent/agent.ts":renderAgentTemplate(e,t),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,n){let r=parseChatGptModelSelection(e);return r===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(n)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(r)}),\n${reasoningTemplateLine(n)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,n){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(n.model)!==void 0?renderAgentTemplate(n.model,n.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,n.appName).replaceAll(`__EVE_INIT_MODEL__`,n.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(n.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(n.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(n.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(n.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,n.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,n.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,n.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,n.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,n.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,n.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
2
2
 
3
3
  export default defineAgent({
4
4
  model: "__EVE_INIT_MODEL__",
@@ -17,7 +17,7 @@ export declare const WEB_APP_TEMPLATE_FILES: {
17
17
  readonly "components/ai-elements/question.tsx": '"use client";\n\nimport type {\n ChangeEvent,\n ComponentProps,\n FormEvent,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactNode,\n} from "react";\n\nimport { Button } from "@/components/ui/button";\nimport { Textarea } from "@/components/ui/textarea";\nimport { cn } from "@/lib/utils";\nimport { createContext, useCallback, useContext, useMemo, useState } from "react";\n\nexport interface QuestionValue {\n selectedValues: readonly string[];\n text: string;\n}\n\nexport interface QuestionResponse {\n selectedValues: readonly string[];\n text?: string;\n}\n\ntype SelectionMode = "multiple" | "single";\n\ninterface QuestionContextValue {\n disabled: boolean;\n selectedValues: readonly string[];\n selectionMode: SelectionMode;\n setText: (text: string) => void;\n text: string;\n toggleValue: (value: string) => void;\n}\n\nconst QuestionContext = createContext<QuestionContextValue | null>(null);\n\nconst useQuestion = () => {\n const context = useContext(QuestionContext);\n\n if (!context) {\n throw new Error("Question components must be used within Question");\n }\n\n return context;\n};\n\nexport type QuestionProps = Omit<ComponentProps<"form">, "defaultValue" | "onSubmit" | "value"> & {\n defaultValue?: QuestionValue;\n disabled?: boolean;\n onSubmit?: (\n response: QuestionResponse,\n event: FormEvent<HTMLFormElement>,\n ) => void | Promise<void>;\n onValueChange?: (value: QuestionValue) => void;\n selectionMode?: SelectionMode;\n value?: QuestionValue;\n};\n\nconst EMPTY_VALUE: QuestionValue = { selectedValues: [], text: "" };\n\nconst getSelectedValues = (\n currentValues: readonly string[],\n optionValue: string,\n selectionMode: SelectionMode,\n): readonly string[] => {\n const isSelected = currentValues.includes(optionValue);\n\n if (selectionMode === "single") {\n return isSelected ? [] : [optionValue];\n }\n\n if (isSelected) {\n return currentValues.filter((item) => item !== optionValue);\n }\n\n return [...currentValues, optionValue];\n};\n\nexport const Question = ({\n children,\n className,\n defaultValue = EMPTY_VALUE,\n disabled = false,\n onSubmit,\n onValueChange,\n selectionMode = "single",\n value: controlledValue,\n ...props\n}: QuestionProps) => {\n const [internalValue, setInternalValue] = useState(defaultValue);\n const value = controlledValue ?? internalValue;\n\n const setValue = useCallback(\n (nextValue: QuestionValue) => {\n if (controlledValue === undefined) {\n setInternalValue(nextValue);\n }\n onValueChange?.(nextValue);\n },\n [controlledValue, onValueChange],\n );\n\n const setText = useCallback(\n (text: string) => {\n setValue({ ...value, text });\n },\n [setValue, value],\n );\n\n const toggleValue = useCallback(\n (optionValue: string) => {\n const selectedValues = getSelectedValues(value.selectedValues, optionValue, selectionMode);\n setValue({ ...value, selectedValues });\n },\n [selectionMode, setValue, value],\n );\n\n const contextValue = useMemo(\n () => ({\n disabled,\n selectedValues: value.selectedValues,\n selectionMode,\n setText,\n text: value.text,\n toggleValue,\n }),\n [disabled, selectionMode, setText, toggleValue, value],\n );\n\n const handleSubmit = useCallback(\n async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (disabled) {\n return;\n }\n\n const text = value.text.trim();\n if (value.selectedValues.length === 0 && text.length === 0) {\n return;\n }\n\n await onSubmit?.(\n {\n selectedValues: value.selectedValues,\n text: text.length > 0 ? text : undefined,\n },\n event,\n );\n },\n [disabled, onSubmit, value],\n );\n\n return (\n <QuestionContext.Provider value={contextValue}>\n <form\n className={cn("space-y-3 rounded-xl border bg-card p-4", className)}\n onSubmit={handleSubmit}\n {...props}\n >\n {children}\n </form>\n </QuestionContext.Provider>\n );\n};\n\nexport type QuestionPromptProps = HTMLAttributes<HTMLParagraphElement>;\n\nexport const QuestionPrompt = ({ className, ...props }: QuestionPromptProps) => (\n <p className={cn("font-medium text-sm leading-snug", className)} {...props} />\n);\n\nexport type QuestionDescriptionProps = HTMLAttributes<HTMLParagraphElement>;\n\nexport const QuestionDescription = ({ className, ...props }: QuestionDescriptionProps) => (\n <p className={cn("text-muted-foreground text-sm", className)} {...props} />\n);\n\nexport type QuestionOptionsProps = HTMLAttributes<HTMLDivElement>;\n\nexport const QuestionOptions = ({ className, ...props }: QuestionOptionsProps) => {\n const { selectionMode } = useQuestion();\n\n return (\n <div\n className={cn("flex flex-wrap gap-1.5", className)}\n role={selectionMode === "single" ? "radiogroup" : "group"}\n {...props}\n />\n );\n};\n\nexport type QuestionOptionProps = Omit<ComponentProps<typeof Button>, "value"> & {\n value: string;\n};\n\nexport const QuestionOption = ({\n children,\n className,\n disabled,\n onClick,\n value,\n variant,\n ...props\n}: QuestionOptionProps) => {\n const question = useQuestion();\n const isSelected = question.selectedValues.includes(value);\n const role = question.selectionMode === "single" ? "radio" : "checkbox";\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n question.toggleValue(value);\n onClick?.(event);\n },\n [onClick, question, value],\n );\n\n return (\n <Button\n aria-checked={isSelected}\n // Selection only changes colors: the border is always present so the\n // layout never shifts when an option is picked.\n className={cn(\n "group/option h-auto whitespace-normal border border-input font-normal shadow-none transition-colors",\n isSelected\n ? "border-foreground/20 bg-accent text-accent-foreground disabled:opacity-100"\n : "text-muted-foreground hover:bg-accent/50 hover:text-foreground",\n className,\n )}\n data-state={isSelected ? "checked" : "unchecked"}\n disabled={question.disabled || disabled}\n onClick={handleClick}\n role={role}\n type="button"\n variant={variant ?? "ghost"}\n {...props}\n >\n {children ?? value}\n </Button>\n );\n};\n\nexport type QuestionInputProps = Omit<ComponentProps<typeof Textarea>, "defaultValue" | "value">;\n\nexport const QuestionInput = ({\n className,\n disabled,\n onChange,\n onKeyDown,\n ...props\n}: QuestionInputProps) => {\n const question = useQuestion();\n const handleChange = useCallback(\n (event: ChangeEvent<HTMLTextAreaElement>) => {\n question.setText(event.currentTarget.value);\n onChange?.(event);\n },\n [onChange, question],\n );\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLTextAreaElement>) => {\n onKeyDown?.(event);\n if (\n event.defaultPrevented ||\n event.key !== "Enter" ||\n event.shiftKey ||\n event.nativeEvent.isComposing\n ) {\n return;\n }\n\n event.preventDefault();\n event.currentTarget.form?.requestSubmit();\n },\n [onKeyDown],\n );\n\n return (\n <Textarea\n className={cn(\n "min-h-16 resize-none rounded-lg text-sm shadow-none focus-visible:border-foreground!",\n className,\n )}\n disabled={question.disabled || disabled}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n value={question.text}\n {...props}\n />\n );\n};\n\nexport type QuestionActionsProps = HTMLAttributes<HTMLDivElement>;\n\nexport const QuestionActions = ({ className, ...props }: QuestionActionsProps) => (\n <div className={cn("flex items-center justify-end gap-2", className)} {...props} />\n);\n\nexport type QuestionSubmitProps = ComponentProps<typeof Button> & {\n children?: ReactNode;\n};\n\nexport const QuestionSubmit = ({\n children = "Submit",\n className,\n disabled,\n size = "sm",\n ...props\n}: QuestionSubmitProps) => {\n const question = useQuestion();\n const hasResponse = question.selectedValues.length > 0 || question.text.trim().length > 0;\n\n return (\n <Button\n className={cn("text-sm! shadow-none", className)}\n disabled={question.disabled || disabled || !hasResponse}\n size={size}\n type="submit"\n {...props}\n >\n {children}\n </Button>\n );\n};\n';
18
18
  readonly "components/ai-elements/reasoning.tsx": '"use client";\n\nimport { useControllableState } from "@radix-ui/react-use-controllable-state";\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";\nimport { cn } from "@/lib/utils";\nimport { cjk } from "@streamdown/cjk";\nimport { code } from "@streamdown/code";\nimport { math } from "@streamdown/math";\nimport { mermaid } from "@streamdown/mermaid";\nimport { BrainIcon, ChevronDownIcon } from "lucide-react";\nimport type { ComponentProps, ReactNode } from "react";\nimport {\n createContext,\n memo,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from "react";\nimport { Streamdown } from "streamdown";\n\nimport { Shimmer } from "./shimmer";\n\ninterface ReasoningContextValue {\n isStreaming: boolean;\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n duration: number | undefined;\n}\n\nconst ReasoningContext = createContext<ReasoningContextValue | null>(null);\n\nexport const useReasoning = () => {\n const context = useContext(ReasoningContext);\n if (!context) {\n throw new Error("Reasoning components must be used within Reasoning");\n }\n return context;\n};\n\nexport type ReasoningProps = ComponentProps<typeof Collapsible> & {\n isStreaming?: boolean;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n duration?: number;\n};\n\nconst MS_IN_S = 1000;\n\nexport const Reasoning = memo(\n ({\n className,\n isStreaming = false,\n open,\n defaultOpen,\n onOpenChange,\n duration: durationProp,\n children,\n ...props\n }: ReasoningProps) => {\n const resolvedDefaultOpen = defaultOpen ?? isStreaming;\n // Track if defaultOpen was explicitly set to false (to prevent auto-open)\n const isExplicitlyClosed = defaultOpen === false;\n\n const [isOpen, setIsOpen] = useControllableState<boolean>({\n defaultProp: resolvedDefaultOpen,\n onChange: onOpenChange,\n prop: open,\n });\n const [duration, setDuration] = useControllableState<number | undefined>({\n defaultProp: undefined,\n prop: durationProp,\n });\n\n const hasEverStreamedRef = useRef(isStreaming);\n const [hasAutoClosed, setHasAutoClosed] = useState(false);\n const startTimeRef = useRef<number | null>(null);\n\n // Track when streaming starts and compute duration\n useEffect(() => {\n if (isStreaming) {\n hasEverStreamedRef.current = true;\n if (startTimeRef.current === null) {\n startTimeRef.current = Date.now();\n }\n } else if (startTimeRef.current !== null) {\n setDuration(Math.ceil((Date.now() - startTimeRef.current) / MS_IN_S));\n startTimeRef.current = null;\n }\n }, [isStreaming, setDuration]);\n\n // Auto-open when streaming starts (unless explicitly closed)\n useEffect(() => {\n if (isStreaming && !isOpen && !isExplicitlyClosed) {\n setIsOpen(true);\n }\n }, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]);\n\n // Auto-close when streaming ends (once only, and only if it ever streamed)\n useEffect(() => {\n if (hasEverStreamedRef.current && !isStreaming && isOpen && !hasAutoClosed) {\n setIsOpen(false);\n setHasAutoClosed(true);\n }\n }, [isStreaming, isOpen, setIsOpen, hasAutoClosed]);\n\n const handleOpenChange = useCallback(\n (newOpen: boolean) => {\n setIsOpen(newOpen);\n },\n [setIsOpen],\n );\n\n const contextValue = useMemo(\n () => ({ duration, isOpen, isStreaming, setIsOpen }),\n [duration, isOpen, isStreaming, setIsOpen],\n );\n\n return (\n <ReasoningContext.Provider value={contextValue}>\n <Collapsible\n className={cn("not-prose mb-4 w-full", className)}\n onOpenChange={handleOpenChange}\n open={isOpen}\n {...props}\n >\n {children}\n </Collapsible>\n </ReasoningContext.Provider>\n );\n },\n);\n\nexport type ReasoningTriggerProps = ComponentProps<typeof CollapsibleTrigger> & {\n getThinkingMessage?: (isStreaming: boolean, duration?: number) => ReactNode;\n};\n\nconst defaultGetThinkingMessage = (isStreaming: boolean, duration?: number) => {\n if (isStreaming || duration === 0) {\n return <Shimmer duration={1}>Thinking...</Shimmer>;\n }\n if (duration === undefined) {\n return <p>Thought for a few seconds</p>;\n }\n return <p>Thought for {duration} seconds</p>;\n};\n\nexport const ReasoningTrigger = memo(\n ({\n className,\n children,\n getThinkingMessage = defaultGetThinkingMessage,\n ...props\n }: ReasoningTriggerProps) => {\n const { isStreaming, isOpen, duration } = useReasoning();\n\n return (\n <CollapsibleTrigger\n className={cn(\n "flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",\n className,\n )}\n {...props}\n >\n {children ?? (\n <>\n <BrainIcon className="size-4" />\n {getThinkingMessage(isStreaming, duration)}\n <ChevronDownIcon\n className={cn("size-4 transition-transform", isOpen ? "rotate-180" : "rotate-0")}\n />\n </>\n )}\n </CollapsibleTrigger>\n );\n },\n);\n\nexport type ReasoningContentProps = ComponentProps<typeof CollapsibleContent> & {\n children: string;\n};\n\nconst streamdownPlugins = { cjk, code, math, mermaid };\n\nexport const ReasoningContent = memo(({ className, children, ...props }: ReasoningContentProps) => (\n <CollapsibleContent\n className={cn(\n "mt-4 text-sm",\n "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",\n className,\n )}\n {...props}\n >\n <Streamdown plugins={streamdownPlugins}>{children}</Streamdown>\n </CollapsibleContent>\n));\n\nReasoning.displayName = "Reasoning";\nReasoningTrigger.displayName = "ReasoningTrigger";\nReasoningContent.displayName = "ReasoningContent";\n';
19
19
  readonly "components/ai-elements/shimmer.tsx": '"use client";\n\nimport { cn } from "@/lib/utils";\nimport type { MotionProps } from "motion/react";\nimport { motion } from "motion/react";\nimport type { CSSProperties, ElementType, JSX } from "react";\nimport { memo, useMemo } from "react";\n\ntype MotionHTMLProps = MotionProps & Record<string, unknown>;\n\n// Cache motion components at module level to avoid creating during render\nconst motionComponentCache = new Map<\n keyof JSX.IntrinsicElements,\n React.ComponentType<MotionHTMLProps>\n>();\n\nconst getMotionComponent = (element: keyof JSX.IntrinsicElements) => {\n let component = motionComponentCache.get(element);\n if (!component) {\n component = motion.create(element);\n motionComponentCache.set(element, component);\n }\n return component;\n};\n\nexport interface TextShimmerProps {\n children: string;\n as?: ElementType;\n className?: string;\n duration?: number;\n spread?: number;\n}\n\nconst ShimmerComponent = ({\n children,\n as: Component = "p",\n className,\n duration = 2,\n spread = 2,\n}: TextShimmerProps) => {\n const MotionComponent = getMotionComponent(Component as keyof JSX.IntrinsicElements);\n\n const dynamicSpread = useMemo(() => (children?.length ?? 0) * spread, [children, spread]);\n\n return (\n <MotionComponent\n animate={{ backgroundPosition: "0% center" }}\n className={cn(\n "relative inline-block bg-[length:250%_100%,auto] bg-clip-text text-transparent",\n "[--bg:linear-gradient(90deg,#0000_calc(50%-var(--spread)),var(--color-background),#0000_calc(50%+var(--spread)))] [background-repeat:no-repeat,padding-box]",\n className,\n )}\n initial={{ backgroundPosition: "100% center" }}\n style={\n {\n "--spread": `${dynamicSpread}px`,\n backgroundImage:\n "var(--bg), linear-gradient(var(--color-muted-foreground), var(--color-muted-foreground))",\n } as CSSProperties\n }\n transition={{\n duration,\n ease: "linear",\n repeat: Number.POSITIVE_INFINITY,\n }}\n >\n {children}\n </MotionComponent>\n );\n};\n\nexport const Shimmer = memo(ShimmerComponent);\n';
20
- readonly "components/ai-elements/tool.tsx": '"use client";\n\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";\nimport { cn } from "@/lib/utils";\nimport type { DynamicToolUIPart, ToolUIPart } from "ai";\nimport { ChevronRightIcon, TerminalIcon, WrenchIcon } from "lucide-react";\nimport type { ComponentProps, ReactNode } from "react";\nimport { isValidElement } from "react";\n\nimport { CodeBlock } from "./code-block";\n\nconst compactCodeBlockClassName =\n "rounded-none border-0 bg-transparent [&_pre]:!bg-transparent [&_pre]:px-3 [&_pre]:pt-2 [&_pre]:pb-3 [&_pre]:text-xs [&_code]:text-xs";\n\nexport type ToolProps = ComponentProps<typeof Collapsible>;\n\nexport const Tool = ({ className, ...props }: ToolProps) => (\n <Collapsible className={cn("group not-prose w-full", className)} {...props} />\n);\n\nexport type ToolPart = ToolUIPart | DynamicToolUIPart;\n\nexport type ToolHeaderProps = {\n title?: string;\n className?: string;\n} & (\n | { type: ToolUIPart["type"]; state: ToolUIPart["state"]; toolName?: never }\n | {\n type: DynamicToolUIPart["type"];\n state: DynamicToolUIPart["state"];\n toolName: string;\n }\n);\n\nconst statusLabels: Record<ToolPart["state"], string> = {\n "approval-requested": "Awaiting Approval",\n "approval-responded": "Responded",\n "input-available": "Running",\n "input-streaming": "Pending",\n "output-available": "Completed",\n "output-denied": "Denied",\n "output-error": "Error",\n};\n\nexport const getStatusIndicator = (status: ToolPart["state"]) =>\n status === "output-available" ? null : (\n <span className={cn("text-sm", status === "output-error" && "text-destructive")}>\n {statusLabels[status]}\n </span>\n );\n\nexport const ToolHeader = ({\n className,\n title,\n type,\n state,\n toolName,\n ...props\n}: ToolHeaderProps) => {\n const derivedName = type === "dynamic-tool" ? toolName : type.split("-").slice(1).join("-");\n const displayName = title ?? derivedName;\n\n return (\n <CollapsibleTrigger\n className={cn(\n "flex w-full items-center gap-2 py-0.5 text-left text-muted-foreground transition-colors hover:text-foreground",\n className,\n )}\n {...props}\n >\n {displayName === "bash" ? (\n <TerminalIcon className="size-4 shrink-0" />\n ) : (\n <WrenchIcon className="size-4 shrink-0" />\n )}\n <span className="text-sm">{displayName}</span>\n {getStatusIndicator(state)}\n <ChevronRightIcon className="size-3.5 shrink-0 transition-transform group-data-[state=open]:rotate-90" />\n </CollapsibleTrigger>\n );\n};\n\nexport type ToolContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const ToolContent = ({ className, ...props }: ToolContentProps) => (\n <CollapsibleContent\n className={cn(\n "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 space-y-4 py-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",\n className,\n )}\n {...props}\n />\n);\n\nexport type BashToolContentProps = ComponentProps<"div"> & {\n input: ToolPart["input"];\n output: ToolPart["output"];\n errorText: ToolPart["errorText"];\n};\n\nexport const BashToolContent = ({\n className,\n input,\n output,\n errorText,\n ...props\n}: BashToolContentProps) => {\n const command = getRecordValue(input, "command");\n const stdout = getRecordValue(output, "stdout") ?? (typeof output === "string" ? output : "");\n const stderr = getRecordValue(output, "stderr") ?? errorText ?? "";\n const exitCode = getRecordValue(output, "exitCode");\n const hasResult = Boolean(stdout || stderr || (typeof exitCode === "number" && exitCode !== 0));\n\n return (\n <div className={cn("space-y-2", className)} {...props}>\n <pre className="overflow-x-auto whitespace-pre-wrap rounded-md bg-muted/50 p-3 font-mono text-xs leading-relaxed">\n <code>\n <span className="text-muted-foreground">$ </span>\n {command ?? "…"}\n </code>\n </pre>\n {hasResult ? (\n <pre className="overflow-x-auto whitespace-pre-wrap rounded-md bg-muted/50 p-3 font-mono text-xs leading-relaxed">\n <code>\n <span className="mb-2 block font-sans text-[10px] text-muted-foreground uppercase tracking-wide">\n Output\n </span>\n {stdout ? <span className="block">{stdout.trimEnd()}</span> : null}\n {stderr ? <span className="block text-destructive">{stderr.trimEnd()}</span> : null}\n {typeof exitCode === "number" && exitCode !== 0 ? (\n <span className="block text-muted-foreground">Exited with code {exitCode}</span>\n ) : null}\n </code>\n </pre>\n ) : null}\n </div>\n );\n};\n\nconst getRecordValue = (value: unknown, key: string): string | number | undefined => {\n if (typeof value !== "object" || value === null || !(key in value)) {\n return undefined;\n }\n\n const property = value[key as keyof typeof value];\n return typeof property === "string" || typeof property === "number" ? property : undefined;\n};\n\nexport type ToolInputProps = ComponentProps<"div"> & {\n input: ToolPart["input"];\n};\n\nexport const ToolInput = ({ className, input, ...props }: ToolInputProps) => (\n <div className={cn("overflow-hidden rounded-md bg-muted/50", className)} {...props}>\n <span className="block px-3 pt-3 font-sans text-[10px] text-muted-foreground uppercase tracking-wide">\n Parameters\n </span>\n <div>\n <CodeBlock\n className={compactCodeBlockClassName}\n code={JSON.stringify(input, null, 2)}\n language="json"\n />\n </div>\n </div>\n);\n\nexport type ToolOutputProps = ComponentProps<"div"> & {\n output: ToolPart["output"];\n errorText: ToolPart["errorText"];\n};\n\nexport const ToolOutput = ({ className, output, errorText, ...props }: ToolOutputProps) => {\n if (!(output || errorText)) {\n return null;\n }\n\n let Output = <div>{output as ReactNode}</div>;\n\n if (typeof output === "object" && !isValidElement(output)) {\n Output = (\n <CodeBlock\n className={compactCodeBlockClassName}\n code={JSON.stringify(output, null, 2)}\n language="json"\n />\n );\n } else if (typeof output === "string") {\n Output = <CodeBlock className={compactCodeBlockClassName} code={output} language="json" />;\n }\n\n return (\n <div\n className={cn(\n "overflow-x-auto rounded-md text-xs [&_table]:w-full",\n errorText ? "bg-destructive/10 text-destructive" : "bg-muted/50 text-foreground",\n className,\n )}\n {...props}\n >\n <span className="block px-3 pt-3 font-sans text-[10px] text-muted-foreground uppercase tracking-wide">\n {errorText ? "Error" : "Result"}\n </span>\n {errorText && <div className="px-3 pt-2 pb-3">{errorText}</div>}\n {Output}\n </div>\n );\n};\n';
20
+ readonly "components/ai-elements/tool.tsx": '"use client";\n\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";\nimport { cn } from "@/lib/utils";\nimport type { DynamicToolUIPart, ToolUIPart } from "ai";\nimport { ChevronRightIcon, TerminalIcon, WrenchIcon } from "lucide-react";\nimport type { ComponentProps, ReactNode } from "react";\nimport { isValidElement } from "react";\n\nimport { CodeBlock } from "./code-block";\n\nconst compactCodeBlockClassName =\n "rounded-none border-0 bg-transparent [&_pre]:!bg-transparent [&_pre]:px-3 [&_pre]:pt-2 [&_pre]:pb-3 [&_pre]:text-xs [&_code]:text-xs";\n\nexport type ToolProps = ComponentProps<typeof Collapsible>;\n\nexport const Tool = ({ className, ...props }: ToolProps) => (\n <Collapsible className={cn("group not-prose w-full", className)} {...props} />\n);\n\nexport type ToolPart = ToolUIPart | DynamicToolUIPart;\n\nexport type ToolHeaderProps = {\n title?: string;\n className?: string;\n} & (\n | { type: ToolUIPart["type"]; state: ToolUIPart["state"]; toolName?: never }\n | {\n type: DynamicToolUIPart["type"];\n state: DynamicToolUIPart["state"];\n toolName: string;\n }\n);\n\nconst statusLabels: Record<ToolPart["state"], string> = {\n "approval-requested": "Awaiting Approval",\n "approval-responded": "Responded",\n "input-available": "Running",\n "input-streaming": "Pending",\n "output-available": "Completed",\n "output-denied": "Denied",\n "output-error": "Error",\n};\n\nexport const getStatusIndicator = (status: ToolPart["state"]) =>\n status === "output-available" ? null : (\n <span className={cn("text-sm", status === "output-error" && "text-destructive")}>\n {statusLabels[status]}\n </span>\n );\n\nexport const ToolHeader = ({\n className,\n title,\n type,\n state,\n toolName,\n ...props\n}: ToolHeaderProps) => {\n const derivedName = type === "dynamic-tool" ? toolName : type.split("-").slice(1).join("-");\n const displayName = title ?? derivedName;\n\n return (\n <CollapsibleTrigger\n className={cn(\n "flex w-full items-center gap-2 py-0.5 text-left text-muted-foreground transition-colors hover:text-foreground",\n className,\n )}\n {...props}\n >\n {displayName === "bash" ? (\n <TerminalIcon className="size-4 shrink-0" />\n ) : (\n <WrenchIcon className="size-4 shrink-0" />\n )}\n <span className="text-sm">{displayName}</span>\n {getStatusIndicator(state)}\n <ChevronRightIcon className="size-3.5 shrink-0 transition-transform group-data-[state=open]:rotate-90" />\n </CollapsibleTrigger>\n );\n};\n\nexport type ToolContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const ToolContent = ({ className, ...props }: ToolContentProps) => (\n <CollapsibleContent\n className={cn(\n "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 space-y-4 py-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",\n className,\n )}\n {...props}\n />\n);\n\nexport type BashToolContentProps = ComponentProps<"div"> & {\n input: ToolPart["input"];\n output: ToolPart["output"];\n errorText: ToolPart["errorText"];\n};\n\nexport const BashToolContent = ({\n className,\n input,\n output,\n errorText,\n ...props\n}: BashToolContentProps) => {\n const command = getRecordValue(input, "command");\n const stdout = getRecordValue(output, "stdout") ?? (typeof output === "string" ? output : "");\n const stderr = getRecordValue(output, "stderr") ?? errorText ?? "";\n const exitCode = getRecordValue(output, "exitCode");\n const hasResult = Boolean(stdout || stderr || (typeof exitCode === "number" && exitCode !== 0));\n\n return (\n <div className={cn("space-y-2", className)} {...props}>\n <pre className="overflow-x-auto whitespace-pre-wrap rounded-md bg-muted/50 p-3 font-mono text-xs leading-relaxed">\n <code>\n <span className="text-muted-foreground">$ </span>\n {command ?? "…"}\n </code>\n </pre>\n {hasResult ? (\n <pre className="overflow-x-auto whitespace-pre-wrap rounded-md bg-muted/50 p-3 font-mono text-xs leading-relaxed">\n <code>\n <span className="mb-2 block font-sans text-[10px] text-muted-foreground uppercase tracking-wide">\n Output\n </span>\n {stdout ? <span className="block">{String(stdout).trimEnd()}</span> : null}\n {stderr ? (\n <span className="block text-destructive">{String(stderr).trimEnd()}</span>\n ) : null}\n {typeof exitCode === "number" && exitCode !== 0 ? (\n <span className="block text-muted-foreground">Exited with code {exitCode}</span>\n ) : null}\n </code>\n </pre>\n ) : null}\n </div>\n );\n};\n\nconst getRecordValue = (value: unknown, key: string): string | number | undefined => {\n if (typeof value !== "object" || value === null || !(key in value)) {\n return undefined;\n }\n\n const property = value[key as keyof typeof value];\n return typeof property === "string" || typeof property === "number" ? property : undefined;\n};\n\nexport type ToolInputProps = ComponentProps<"div"> & {\n input: ToolPart["input"];\n};\n\nexport const ToolInput = ({ className, input, ...props }: ToolInputProps) => (\n <div className={cn("overflow-hidden rounded-md bg-muted/50", className)} {...props}>\n <span className="block px-3 pt-3 font-sans text-[10px] text-muted-foreground uppercase tracking-wide">\n Parameters\n </span>\n <div>\n <CodeBlock\n className={compactCodeBlockClassName}\n code={JSON.stringify(input, null, 2)}\n language="json"\n />\n </div>\n </div>\n);\n\nexport type ToolOutputProps = ComponentProps<"div"> & {\n output: ToolPart["output"];\n errorText: ToolPart["errorText"];\n};\n\nexport const ToolOutput = ({ className, output, errorText, ...props }: ToolOutputProps) => {\n if (!(output || errorText)) {\n return null;\n }\n\n let Output = <div>{output as ReactNode}</div>;\n\n if (typeof output === "object" && !isValidElement(output)) {\n Output = (\n <CodeBlock\n className={compactCodeBlockClassName}\n code={JSON.stringify(output, null, 2)}\n language="json"\n />\n );\n } else if (typeof output === "string") {\n Output = <CodeBlock className={compactCodeBlockClassName} code={output} language="json" />;\n }\n\n return (\n <div\n className={cn(\n "overflow-x-auto rounded-md text-xs [&_table]:w-full",\n errorText ? "bg-destructive/10 text-destructive" : "bg-muted/50 text-foreground",\n className,\n )}\n {...props}\n >\n <span className="block px-3 pt-3 font-sans text-[10px] text-muted-foreground uppercase tracking-wide">\n {errorText ? "Error" : "Result"}\n </span>\n {errorText && <div className="px-3 pt-2 pb-3">{errorText}</div>}\n {Output}\n </div>\n );\n};\n';
21
21
  readonly "components/ui/badge.tsx": 'import * as React from "react";\nimport { cva, type VariantProps } from "class-variance-authority";\nimport { Slot } from "radix-ui";\n\nimport { cn } from "@/lib/utils";\n\nconst badgeVariants = cva(\n "inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3",\n {\n variants: {\n variant: {\n default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90",\n secondary: "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",\n destructive:\n "bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90",\n outline:\n "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",\n ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",\n link: "text-primary underline-offset-4 [a&]:hover:underline",\n },\n },\n defaultVariants: {\n variant: "default",\n },\n },\n);\n\nfunction Badge({\n className,\n variant = "default",\n asChild = false,\n ...props\n}: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot.Root : "span";\n\n return (\n <Comp\n data-slot="badge"\n data-variant={variant}\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nexport { Badge, badgeVariants };\n';
22
22
  readonly "components/ui/button-group.tsx": 'import { cva, type VariantProps } from "class-variance-authority";\nimport { Slot } from "radix-ui";\n\nimport { cn } from "@/lib/utils";\nimport { Separator } from "@/components/ui/separator";\n\nconst buttonGroupVariants = cva(\n "flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*=\'w-\'])]:w-fit [&>input]:flex-1",\n {\n variants: {\n orientation: {\n horizontal:\n "[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",\n vertical:\n "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",\n },\n },\n defaultVariants: {\n orientation: "horizontal",\n },\n },\n);\n\nfunction ButtonGroup({\n className,\n orientation,\n ...props\n}: React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>) {\n return (\n <div\n role="group"\n data-slot="button-group"\n data-orientation={orientation}\n className={cn(buttonGroupVariants({ orientation }), className)}\n {...props}\n />\n );\n}\n\nfunction ButtonGroupText({\n className,\n asChild = false,\n ...props\n}: React.ComponentProps<"div"> & {\n asChild?: boolean;\n}) {\n const Comp = asChild ? Slot.Root : "div";\n\n return (\n <Comp\n className={cn(\n "flex items-center gap-2 rounded-md border bg-muted px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*=\'size-\'])]:size-4",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ButtonGroupSeparator({\n className,\n orientation = "vertical",\n ...props\n}: React.ComponentProps<typeof Separator>) {\n return (\n <Separator\n data-slot="button-group-separator"\n orientation={orientation}\n className={cn(\n "relative m-0! self-stretch bg-input data-[orientation=vertical]:h-auto",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants };\n';
23
23
  readonly "components/ui/button.tsx": 'import * as React from "react";\nimport { cva, type VariantProps } from "class-variance-authority";\nimport { Slot } from "radix-ui";\n\nimport { cn } from "@/lib/utils";\n\nconst buttonVariants = cva(\n "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4",\n {\n variants: {\n variant: {\n default: "bg-primary text-primary-foreground hover:bg-primary/90",\n destructive:\n "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",\n outline:\n "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",\n secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",\n ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",\n link: "text-primary underline-offset-4 hover:underline",\n },\n size: {\n default: "h-9 px-4 py-2 has-[>svg]:px-3",\n xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*=\'size-\'])]:size-3",\n sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",\n lg: "h-10 rounded-md px-6 has-[>svg]:px-4",\n icon: "size-9",\n "icon-xs": "size-6 rounded-md [&_svg:not([class*=\'size-\'])]:size-3",\n "icon-sm": "size-8",\n "icon-lg": "size-10",\n },\n },\n defaultVariants: {\n variant: "default",\n size: "default",\n },\n },\n);\n\nfunction Button({\n className,\n variant = "default",\n size = "default",\n asChild = false,\n ...props\n}: React.ComponentProps<"button"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }) {\n const Comp = asChild ? Slot.Root : "button";\n\n return (\n <Comp\n data-slot="button"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n';
@@ -4319,8 +4319,10 @@ export const BashToolContent = ({
4319
4319
  <span className="mb-2 block font-sans text-[10px] text-muted-foreground uppercase tracking-wide">
4320
4320
  Output
4321
4321
  </span>
4322
- {stdout ? <span className="block">{stdout.trimEnd()}</span> : null}
4323
- {stderr ? <span className="block text-destructive">{stderr.trimEnd()}</span> : null}
4322
+ {stdout ? <span className="block">{String(stdout).trimEnd()}</span> : null}
4323
+ {stderr ? (
4324
+ <span className="block text-destructive">{String(stderr).trimEnd()}</span>
4325
+ ) : null}
4324
4326
  {typeof exitCode === "number" && exitCode !== 0 ? (
4325
4327
  <span className="block text-muted-foreground">Exited with code {exitCode}</span>
4326
4328
  ) : null}
@@ -389,12 +389,14 @@ export interface ConnectionToolMetadata {
389
389
  export interface ConnectionToolExecuteOptions {
390
390
  /** Signal forwarded into the underlying transport. */
391
391
  readonly abortSignal?: AbortSignal;
392
+ /** Replay-stable id of the authored tool call. */
393
+ readonly callId: string;
392
394
  }
393
395
  /** A live client for a single connection. */
394
396
  export interface ConnectionClient {
395
397
  close(): Promise<void>;
396
398
  connect(): Promise<unknown>;
397
- executeTool(toolName: string, args: unknown, options?: ConnectionToolExecuteOptions): Promise<unknown>;
399
+ executeTool(toolName: string, args: unknown, options: ConnectionToolExecuteOptions): Promise<unknown>;
398
400
  getToolMetadata(): Promise<readonly ConnectionToolMetadata[]>;
399
401
  getTools(): Promise<ToolSet>;
400
402
  }
@@ -11,6 +11,11 @@ export interface SandboxBackendHandle<SO = Record<string, never>> {
11
11
  readonly session: SandboxSession;
12
12
  readonly useSessionFn: SandboxSessionUseFn<SO>;
13
13
  captureState(): Promise<SandboxBackendSessionState>;
14
+ /**
15
+ * Permanently deletes this sandbox and its disposable backend state.
16
+ * Reusable or shared template state must not be deleted.
17
+ */
18
+ delete(options?: SandboxDeleteOptions): Promise<void>;
14
19
  /**
15
20
  * Stops the underlying compute at an authored runtime boundary while
16
21
  * preserving any backend state needed to reopen the durable session.
@@ -25,6 +30,10 @@ export interface SandboxBackendHandle<SO = Record<string, never>> {
25
30
  */
26
31
  shutdown(): Promise<void>;
27
32
  }
33
+ /** Options for permanently deleting one sandbox. */
34
+ export interface SandboxDeleteOptions {
35
+ readonly abortSignal?: AbortSignal;
36
+ }
28
37
  /**
29
38
  * Serializable per-sandbox reconnect record stored on the harness session.
30
39
  *
@@ -26,12 +26,13 @@ export interface SandboxBootstrapContext<O = Record<string, never>> {
26
26
  }
27
27
  /**
28
28
  * Argument passed to a sandbox `onSession` hook, invoked once per live
29
- * session. `ctx` is the runtime {@link SessionContext} (session id, auth,
30
- * turn). `use(options?)` opens the live session, applying backend-specific
31
- * `options` (typed by the backend's session-use options `SO`).
29
+ * session. `ctx` contains the active session metadata; sandbox access during
30
+ * initialization goes through `use(options?)`, which opens the live session
31
+ * and applies backend-specific `options` (typed by the backend's session-use
32
+ * options `SO`).
32
33
  */
33
34
  export interface SandboxSessionContext<O = Record<string, never>> {
34
- readonly ctx: SessionContext;
35
+ readonly ctx: Pick<SessionContext, "session">;
35
36
  readonly use: SandboxSessionUseFn<O>;
36
37
  }
37
38
  /**
@@ -1,4 +1,5 @@
1
1
  import type { Experimental_SandboxSession as AiSdkSandbox } from "ai";
2
+ import type { SandboxDeleteOptions } from "#shared/sandbox-backend.js";
2
3
  import type { SandboxNetworkPolicy } from "#shared/sandbox-network-policy.js";
3
4
  /**
4
5
  * Options for running one command in a sandbox. Shape mirrors the AI
@@ -124,9 +125,11 @@ export interface SandboxSession extends Pick<AiSdkSandbox, "run" | "spawn" | "re
124
125
  * `ctx.getSandbox()`.
125
126
  *
126
127
  * Unlike the I/O-only session used during sandbox initialization, this handle
127
- * always exposes a provider-backed `stop()` method.
128
+ * exposes provider-backed lifecycle operations.
128
129
  */
129
130
  export interface RuntimeSandboxSession extends SandboxSession {
131
+ /** Permanently deletes this sandbox and its disposable backend state. */
132
+ delete(options?: SandboxDeleteOptions): Promise<void>;
130
133
  /**
131
134
  * Stops the backing sandbox compute while preserving the durable session.
132
135
  * A later runtime callback reopens the session through its configured
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-BH7Z6SDu.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-kmlFdOBB.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-BH7Z6SDu.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-kmlFdOBB.js";
2
2
 
3
3
  export { useEveAgent };
@@ -0,0 +1,12 @@
1
+ export interface DeliveryPolicy {
2
+ readonly allowsEmptyDelivery: boolean;
3
+ readonly instruction?: string;
4
+ }
5
+ /** Resolves one policy for both model prompting and empty-response recovery. */
6
+ export declare function resolveDeliveryPolicy(input: {
7
+ readonly hasOutputSchema: boolean;
8
+ readonly isChild: boolean;
9
+ readonly isFirstTurn: boolean;
10
+ readonly hasScheduleProvenance: boolean;
11
+ readonly taskDeliveryPhase: "none" | "initiating" | "pending" | "settled" | undefined;
12
+ }): DeliveryPolicy;
@@ -0,0 +1 @@
1
+ import{TASK_DELIVERY_INITIATING_INSTRUCTION,TASK_DELIVERY_PENDING_INSTRUCTION,TASK_DELIVERY_SETTLED_INSTRUCTION}from"#tasks/delivery-context.js";import{CONDITIONAL_DELIVERY_INSTRUCTION}from"#shared/empty-delivery.js";const POLICIES={conditional:{allowsEmptyDelivery:!0,instruction:CONDITIONAL_DELIVERY_INSTRUCTION},initiating:{allowsEmptyDelivery:!1,instruction:TASK_DELIVERY_INITIATING_INSTRUCTION},normal:{allowsEmptyDelivery:!1},pending:{allowsEmptyDelivery:!0,instruction:TASK_DELIVERY_PENDING_INSTRUCTION},settled:{allowsEmptyDelivery:!1,instruction:TASK_DELIVERY_SETTLED_INSTRUCTION}};function resolveDeliveryPolicy(e){return e.hasOutputSchema||e.isChild?POLICIES.normal:e.taskDeliveryPhase===`pending`?POLICIES.pending:e.taskDeliveryPhase===`settled`?POLICIES.settled:e.isFirstTurn&&e.hasScheduleProvenance?POLICIES.conditional:e.taskDeliveryPhase===`initiating`?POLICIES.initiating:POLICIES.normal}export{resolveDeliveryPolicy};