eve 0.27.12 → 0.28.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 (157) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/src/channel/adapter.d.ts +5 -5
  3. package/dist/src/channel/session.d.ts +2 -2
  4. package/dist/src/channel/types.d.ts +10 -6
  5. package/dist/src/chunks/{use-eve-agent-CsSQOKnp.js → use-eve-agent-CZkX_ZTT.js} +90 -1
  6. package/dist/src/chunks/{use-eve-agent-CWYe-vqE.js → use-eve-agent-hdPX68_i.js} +90 -1
  7. package/dist/src/cli/commands/channels.js +1 -1
  8. package/dist/src/cli/commands/integration-setup.js +1 -1
  9. package/dist/src/cli/commands/register-registry-commands.js +1 -1
  10. package/dist/src/cli/commands/registry-setup-command.d.ts +5 -3
  11. package/dist/src/cli/commands/registry-setup-command.js +1 -1
  12. package/dist/src/cli/commands/registry.d.ts +9 -3
  13. package/dist/src/cli/commands/registry.js +1 -1
  14. package/dist/src/cli/dev/tui/runner.js +1 -1
  15. package/dist/src/cli/dev/tui/subagent-pump.d.ts +8 -2
  16. package/dist/src/cli/dev/tui/subagent-pump.js +1 -1
  17. package/dist/src/cli/invoke/result.d.ts +15 -0
  18. package/dist/src/cli/invoke/result.js +1 -1
  19. package/dist/src/client/eve-agent-store.d.ts +7 -4
  20. package/dist/src/client/eve-agent-store.js +1 -1
  21. package/dist/src/client/index.d.ts +3 -3
  22. package/dist/src/client/index.js +1 -1
  23. package/dist/src/client/message-action-parts.js +1 -1
  24. package/dist/src/client/message-reducer-types.d.ts +5 -3
  25. package/dist/src/client/message-response.d.ts +4 -4
  26. package/dist/src/client/ndjson.d.ts +3 -3
  27. package/dist/src/client/open-stream.d.ts +2 -2
  28. package/dist/src/client/output-schema.d.ts +2 -2
  29. package/dist/src/client/reducer.d.ts +2 -2
  30. package/dist/src/client/session-utils.d.ts +5 -5
  31. package/dist/src/client/session.d.ts +2 -2
  32. package/dist/src/client/types.d.ts +2 -2
  33. package/dist/src/compiler/compile-from-memory.d.ts +1 -0
  34. package/dist/src/compiler/extension-compatibility.d.ts +8 -8
  35. package/dist/src/compiler/extension-compatibility.js +1 -1
  36. package/dist/src/compiler/manifest.d.ts +2 -2
  37. package/dist/src/compiler/manifest.js +1 -1
  38. package/dist/src/compiler/normalize-agent-config.js +1 -1
  39. package/dist/src/context/dynamic-instruction-lifecycle.d.ts +2 -2
  40. package/dist/src/context/dynamic-model-lifecycle.d.ts +2 -2
  41. package/dist/src/context/dynamic-skill-lifecycle.d.ts +2 -2
  42. package/dist/src/context/dynamic-tool-lifecycle.d.ts +2 -2
  43. package/dist/src/context/hook-lifecycle.d.ts +2 -2
  44. package/dist/src/evals/assertions/run.d.ts +3 -3
  45. package/dist/src/evals/match.d.ts +4 -4
  46. package/dist/src/evals/runner/derive-run-facts.d.ts +2 -2
  47. package/dist/src/evals/session.d.ts +3 -3
  48. package/dist/src/evals/types.d.ts +12 -12
  49. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  50. package/dist/src/execution/route-child-delivery.d.ts +4 -3
  51. package/dist/src/execution/route-child-delivery.js +1 -1
  52. package/dist/src/execution/session-delivery-hook.d.ts +1 -0
  53. package/dist/src/execution/session-delivery-hook.js +1 -1
  54. package/dist/src/execution/session-timeout-control.d.ts +9 -0
  55. package/dist/src/execution/session-timeout-control.js +1 -0
  56. package/dist/src/execution/session-timeout-steps.d.ts +13 -0
  57. package/dist/src/execution/session-timeout-steps.js +1 -0
  58. package/dist/src/execution/session-timeout-workflow.d.ts +6 -0
  59. package/dist/src/execution/session-timeout-workflow.js +1 -0
  60. package/dist/src/execution/session-timeout.d.ts +2 -0
  61. package/dist/src/execution/session-timeout.js +1 -0
  62. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  63. package/dist/src/execution/subagent-event-proxy-step.js +1 -1
  64. package/dist/src/execution/subagent-hitl-proxy.d.ts +5 -1
  65. package/dist/src/execution/subagent-hitl-proxy.js +1 -1
  66. package/dist/src/execution/terminal-session-completion-step.d.ts +5 -0
  67. package/dist/src/execution/terminal-session-completion-step.js +1 -0
  68. package/dist/src/execution/terminal-session-failure-step.js +1 -1
  69. package/dist/src/execution/turn-workflow.js +1 -1
  70. package/dist/src/execution/workflow-entry.d.ts +1 -0
  71. package/dist/src/execution/workflow-entry.js +1 -1
  72. package/dist/src/execution/workflow-runtime.d.ts +4 -0
  73. package/dist/src/execution/workflow-runtime.js +1 -1
  74. package/dist/src/execution/workflow-steps.d.ts +5 -2
  75. package/dist/src/execution/workflow-steps.js +1 -1
  76. package/dist/src/harness/agent-otel-provider.js +1 -1
  77. package/dist/src/harness/ai-sdk-hook-bridge.js +1 -1
  78. package/dist/src/harness/input-extraction.js +1 -1
  79. package/dist/src/harness/input-request-class.d.ts +23 -0
  80. package/dist/src/harness/input-request-class.js +1 -0
  81. package/dist/src/harness/input-requests.d.ts +20 -9
  82. package/dist/src/harness/input-requests.js +1 -1
  83. package/dist/src/harness/instrumentation-lifecycle.d.ts +12 -1
  84. package/dist/src/harness/proxy-input-requests.d.ts +10 -4
  85. package/dist/src/harness/proxy-input-requests.js +1 -1
  86. package/dist/src/harness/session-limit-continuation.d.ts +0 -11
  87. package/dist/src/harness/session-limit-continuation.js +1 -1
  88. package/dist/src/harness/session-limit-enforcement.d.ts +3 -2
  89. package/dist/src/harness/session-limit-enforcement.js +1 -1
  90. package/dist/src/harness/session-token-limits.d.ts +41 -0
  91. package/dist/src/harness/session-token-limits.js +1 -0
  92. package/dist/src/harness/stale-input-responses.js +1 -1
  93. package/dist/src/harness/subagent-token-budget.d.ts +6 -4
  94. package/dist/src/harness/subagent-token-budget.js +1 -1
  95. package/dist/src/harness/tool-loop.js +1 -1
  96. package/dist/src/harness/turn-tag-state.d.ts +26 -17
  97. package/dist/src/harness/turn-tag-state.js +1 -1
  98. package/dist/src/harness/types.d.ts +4 -4
  99. package/dist/src/harness/workflow-lifecycle.d.ts +2 -2
  100. package/dist/src/internal/application/package.js +1 -1
  101. package/dist/src/internal/authored-definition/core.js +1 -1
  102. package/dist/src/internal/node-esm-compat-banner.js +1 -1
  103. package/dist/src/internal/workflow-bundle/workflow-core-shim.d.ts +1 -1
  104. package/dist/src/internal/workflow-bundle/workflow-core-shim.js +1 -1
  105. package/dist/src/protocol/event-dedupe.d.ts +25 -0
  106. package/dist/src/protocol/event-dedupe.js +1 -0
  107. package/dist/src/protocol/event-id.d.ts +16 -0
  108. package/dist/src/protocol/event-id.js +1 -0
  109. package/dist/src/protocol/message.d.ts +39 -23
  110. package/dist/src/protocol/message.js +2 -2
  111. package/dist/src/public/channels/discord/discordChannel.d.ts +3 -3
  112. package/dist/src/public/channels/github/githubChannel.d.ts +3 -3
  113. package/dist/src/public/channels/linear/defaults.js +4 -2
  114. package/dist/src/public/channels/linear/linearChannel.d.ts +3 -3
  115. package/dist/src/public/channels/slack/hitl.js +1 -1
  116. package/dist/src/public/channels/slack/slackChannel.d.ts +3 -3
  117. package/dist/src/public/channels/teams/hitl.js +1 -1
  118. package/dist/src/public/channels/teams/teamsChannel.d.ts +3 -3
  119. package/dist/src/public/channels/telegram/telegramChannel.d.ts +3 -3
  120. package/dist/src/public/channels/twilio/twilioChannel.d.ts +3 -3
  121. package/dist/src/public/definitions/channel.d.ts +4 -4
  122. package/dist/src/public/definitions/hook.d.ts +2 -2
  123. package/dist/src/react/use-eve-agent.d.ts +3 -2
  124. package/dist/src/runtime/framework-tools/ask-question.js +1 -1
  125. package/dist/src/runtime/hooks/registry.d.ts +2 -2
  126. package/dist/src/runtime/input/types.d.ts +19 -4
  127. package/dist/src/runtime/input/types.js +1 -1
  128. package/dist/src/runtime/resolve-agent.js +1 -1
  129. package/dist/src/runtime/types.d.ts +2 -2
  130. package/dist/src/setup/scaffold/create/project.js +1 -1
  131. package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
  132. package/dist/src/setup/scaffold/create/web-template.js +2 -2
  133. package/dist/src/shared/agent-definition.d.ts +12 -0
  134. package/dist/src/shared/dynamic-tool-definition.d.ts +2 -2
  135. package/dist/src/shared/ulid.d.ts +39 -0
  136. package/dist/src/shared/ulid.js +1 -0
  137. package/dist/src/svelte/index.js +1 -1
  138. package/dist/src/svelte/use-eve-agent.d.ts +4 -4
  139. package/dist/src/svelte/use-eve-agent.js +1 -1
  140. package/dist/src/vue/index.js +1 -1
  141. package/dist/src/vue/use-eve-agent.d.ts +4 -4
  142. package/dist/src/vue/use-eve-agent.js +1 -1
  143. package/docs/agent-config.md +28 -16
  144. package/docs/channels/linear.mdx +4 -0
  145. package/docs/concepts/execution-model-and-durability.mdx +1 -1
  146. package/docs/concepts/sessions-runs-and-streaming.md +61 -0
  147. package/docs/extensions.md +3 -1
  148. package/docs/guides/client/streaming.mdx +9 -3
  149. package/docs/guides/frontend/overview.mdx +4 -2
  150. package/docs/guides/frontend/use-eve-agent-svelte.mdx +1 -1
  151. package/docs/guides/frontend/use-eve-agent-vue.mdx +10 -10
  152. package/docs/guides/hooks.md +40 -2
  153. package/docs/guides/instrumentation.md +4 -0
  154. package/docs/install-integrations.mdx +76 -1
  155. package/docs/reference/cli.md +3 -0
  156. package/docs/tools/human-in-the-loop.md +5 -0
  157. package/package.json +1 -1
@@ -2,13 +2,13 @@ import type { DiscordInstrumentationMetadata } from "#public/channels/discord/in
2
2
  import type { SessionAuthContext } from "#channel/types.js";
3
3
  import type { SessionContext } from "#public/definitions/callback-context.js";
4
4
  import type { ChannelSessionOps } from "#public/definitions/channel.js";
5
- import type { HandleMessageStreamEvent } from "#protocol/message.js";
5
+ import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
6
6
  import { type DiscordApiOptions, type DiscordApiResponse, type DiscordCredentials, type DiscordMessageBody, type DiscordPostedMessage } from "#public/channels/discord/api.js";
7
7
  import { type DiscordCommandInteraction } from "#public/channels/discord/inbound.js";
8
8
  import { type DiscordWebhookVerifier } from "#public/channels/discord/verify.js";
9
9
  import { type JsonObject } from "#shared/json.js";
10
10
  import { type Channel } from "#public/definitions/channel.js";
11
- type EventData<T extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
11
+ type EventData<T extends UnstampedMessageStreamEvent["type"]> = Extract<UnstampedMessageStreamEvent, {
12
12
  type: T;
13
13
  }> extends {
14
14
  data: infer D;
@@ -66,7 +66,7 @@ export type DiscordCommandResult = {
66
66
  } | null;
67
67
  /** Sync or async {@link DiscordCommandResult}. */
68
68
  export type DiscordCommandResultOrPromise = DiscordCommandResult | Promise<DiscordCommandResult>;
69
- type DiscordEventHandler<T extends HandleMessageStreamEvent["type"]> = (data: EventData<T>, channel: DiscordEventContext, ctx: SessionContext) => void | Promise<void>;
69
+ type DiscordEventHandler<T extends UnstampedMessageStreamEvent["type"]> = (data: EventData<T>, channel: DiscordEventContext, ctx: SessionContext) => void | Promise<void>;
70
70
  type DiscordSessionFailedHandler = (data: EventData<"session.failed">, channel: DiscordEventContext) => void | Promise<void>;
71
71
  /** Per-event handlers for `discordChannel({ events })`. Supplied handlers override built-in defaults per key; unspecified events keep their defaults. `session.failed` receives only `(data, channel)`; every other handler also gets the session `ctx`. */
72
72
  export interface DiscordChannelEvents {
@@ -1,7 +1,7 @@
1
1
  import type { SessionAuthContext } from "#channel/types.js";
2
2
  import type { SessionContext } from "#public/definitions/callback-context.js";
3
3
  import type { ChannelSessionOps } from "#public/definitions/channel.js";
4
- import type { HandleMessageStreamEvent } from "#protocol/message.js";
4
+ import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
5
5
  import { type GitHubHandle, type GitHubThread } from "#public/channels/github/binding.js";
6
6
  import { type GitHubApiOptions } from "#public/channels/github/api.js";
7
7
  import type { GitHubChannelCredentials } from "#public/channels/github/auth.js";
@@ -9,7 +9,7 @@ import { type GitHubCheckRunEvent, type GitHubCheckSuiteEvent, type GitHubCommen
9
9
  import { type GitHubChannelState } from "#public/channels/github/state.js";
10
10
  import type { GitHubPullRequestContextConfig } from "#public/channels/github/pr-context.js";
11
11
  import { type Channel } from "#public/definitions/channel.js";
12
- type EventData<T extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
12
+ type EventData<T extends UnstampedMessageStreamEvent["type"]> = Extract<UnstampedMessageStreamEvent, {
13
13
  type: T;
14
14
  }> extends {
15
15
  data: infer D;
@@ -67,7 +67,7 @@ export type GitHubInboundResult = {
67
67
  * promise for one.
68
68
  */
69
69
  export type GitHubInboundResultOrPromise = GitHubInboundResult | Promise<GitHubInboundResult>;
70
- type GitHubEventHandler<T extends HandleMessageStreamEvent["type"]> = (data: EventData<T>, channel: GitHubEventContext, ctx: SessionContext) => void | Promise<void>;
70
+ type GitHubEventHandler<T extends UnstampedMessageStreamEvent["type"]> = (data: EventData<T>, channel: GitHubEventContext, ctx: SessionContext) => void | Promise<void>;
71
71
  type GitHubSessionFailedHandler = (data: EventData<"session.failed">, channel: GitHubEventContext) => void | Promise<void>;
72
72
  /**
73
73
  * Event handlers for `githubChannel({ events })`. The channel installs built-in
@@ -1,3 +1,5 @@
1
- import{extractErrorId,formatErrorHint}from"#internal/logging.js";import{createLinearAgentActivity}from"#public/channels/linear/api.js";import{linearInputRequestSignal,renderLinearInputRequests}from"#public/channels/linear/hitl.js";function defaultLinearAuth(e){let t=e.agentActivity?.user??e.agentSession.creator,n=e.agentActivity?.userId??e.agentSession.creatorId??t?.id??`unknown`,r={action:e.action,agent_session_id:e.agentSession.id,organization_id:e.organizationId??e.agentSession.organizationId??``};if(e.delivery.id!==void 0&&(r.delivery_id=e.delivery.id),e.agentSession.issueId!==void 0&&e.agentSession.issueId!==null&&(r.issue_id=e.agentSession.issueId),e.agentSession.issue?.identifier!==void 0&&(r.issue_identifier=e.agentSession.issue.identifier),t!==void 0){let e=linearUserLabel(t);e!==void 0&&(r.user=e)}return{attributes:r,authenticator:`linear-agent-webhook`,issuer:e.organizationId?`linear:${e.organizationId}`:`linear`,principalId:`linear:${n}`,principalType:`user`,subject:n}}function defaultOnAgentSession(e,t){return t.action!==`created`&&t.action!==`prompted`?null:{auth:defaultLinearAuth(t)}}function createDefaultEvents(n={}){return{async"turn.started"(e,t,r){t.state.pendingToolCallMessage=null,await postActivity(t,n,{body:`Working on this.`,type:`thought`},{ephemeral:!0})},async"actions.requested"(e,t,r){let i=t.state.pendingToolCallMessage;if(t.state.pendingToolCallMessage=null,i){await postActivity(t,n,{body:i,type:`thought`},{ephemeral:!0});return}if(e.actions.length!==0){if(e.actions.length>1){await postActivity(t,n,{action:`Running`,parameter:e.actions.map(actionLabel).join(`, `),type:`action`},{ephemeral:!0});return}for(let r of e.actions)await postActivity(t,n,{action:actionLabel(r),parameter:actionParameter(r),type:`action`},{ephemeral:!0})}},async"input.requested"(e,t,a){let o=linearInputRequestSignal(e.requests);await postActivity(t,n,{body:renderLinearInputRequests(e.requests),type:`elicitation`},o)},async"message.completed"(e,t,r){if(e.finishReason===`tool-calls`){t.state.pendingToolCallMessage=e.message?firstNonEmptyLine(e.message)??null:null;return}t.state.pendingToolCallMessage=null,e.message&&await postActivity(t,n,{body:e.message,type:`response`})},async"session.failed"(r,i){let a=formatErrorHint(r),o=extractErrorId(r.details);await postActivity(i,n,{body:[`This session could not recover from an error${a}.`,``,`Start a new Linear agent session to continue.`,...o?[``,`Error id: ${o}`]:[]].join(`
1
+ import{extractErrorId,formatErrorHint}from"#internal/logging.js";import{createLinearAgentActivity}from"#public/channels/linear/api.js";import{linearInputRequestSignal,renderLinearInputRequests}from"#public/channels/linear/hitl.js";function defaultLinearAuth(e){let t=e.agentActivity?.user??e.agentSession.creator,n=e.agentActivity?.userId??e.agentSession.creatorId??t?.id??`unknown`,r={action:e.action,agent_session_id:e.agentSession.id,organization_id:e.organizationId??e.agentSession.organizationId??``};if(e.delivery.id!==void 0&&(r.delivery_id=e.delivery.id),e.agentSession.issueId!==void 0&&e.agentSession.issueId!==null&&(r.issue_id=e.agentSession.issueId),e.agentSession.issue?.identifier!==void 0&&(r.issue_identifier=e.agentSession.issue.identifier),t!==void 0){let e=linearUserLabel(t);e!==void 0&&(r.user=e)}return{attributes:r,authenticator:`linear-agent-webhook`,issuer:e.organizationId?`linear:${e.organizationId}`:`linear`,principalId:`linear:${n}`,principalType:`user`,subject:n}}function defaultOnAgentSession(e,t){return t.action!==`created`&&t.action!==`prompted`?null:{auth:defaultLinearAuth(t)}}function createDefaultEvents(n={}){return{async"turn.started"(e,t,r){t.state.pendingToolCallMessage=null,await postActivity(t,n,{body:`Working on this.`,type:`thought`},{ephemeral:!0})},async"actions.requested"(e,t,r){let i=t.state.pendingToolCallMessage;if(t.state.pendingToolCallMessage=null,i){await postActivity(t,n,{body:i,type:`thought`},{ephemeral:!0});return}if(e.actions.length!==0){if(e.actions.length>1){await postActivity(t,n,{action:`Running`,parameter:e.actions.map(actionLabel).join(`, `),type:`action`},{ephemeral:!0});return}for(let r of e.actions)await postActivity(t,n,{action:actionLabel(r),parameter:actionParameter(r),type:`action`},{ephemeral:!0})}},async"input.requested"(e,t,a){let o=linearInputRequestSignal(e.requests);await postActivity(t,n,{body:renderLinearInputRequests(e.requests),type:`elicitation`},o)},async"authorization.required"(e,t,r){let i=authorizationDisplayName(e.name,e.authorization?.displayName),a=e.authorization?.url,o=linearUserId(r),s;if(a!==void 0){let e={providerName:i,url:a};o!==void 0&&(e.userId=o),s={signal:`auth`,signalMetadata:e}}await postActivity(t,n,{body:authorizationRequiredBody({displayName:i,instructions:e.authorization?.instructions,userCode:e.authorization?.userCode}),type:`elicitation`},s)},async"authorization.completed"(e,t,r){let i=authorizationDisplayName(e.name,e.authorization?.displayName);if(e.outcome===`authorized`){await postActivity(t,n,{body:`Connected to ${i}. Resuming.`,type:`thought`},{ephemeral:!0});return}let a=e.reason===void 0?``:` (${e.reason})`;await postActivity(t,n,{body:`${i} authorization ${formatAuthorizationOutcome(e.outcome)}${a}.`,type:`thought`})},async"message.completed"(e,t,r){if(e.finishReason===`tool-calls`){t.state.pendingToolCallMessage=e.message?firstNonEmptyLine(e.message)??null:null;return}t.state.pendingToolCallMessage=null,e.message&&await postActivity(t,n,{body:e.message,type:`response`})},async"session.failed"(r,i){let a=formatErrorHint(r),o=extractErrorId(r.details);await postActivity(i,n,{body:[`This session could not recover from an error${a}.`,``,`Start a new Linear agent session to continue.`,...o?[``,`Error id: ${o}`]:[]].join(`
2
2
  `),type:`error`})},async"turn.failed"(r,i,a){let o=formatErrorHint(r),s=extractErrorId(r.details);await postActivity(i,n,{body:[`I hit an error while handling your request${o}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...s?[``,`Error id: ${s}`]:[]].join(`
3
- `),type:`error`})}}}function postActivity(e,t,r,i={}){return createLinearAgentActivity({api:t.api,credentials:t.credentials,activity:{agentSessionId:requireAgentSessionId(e.state.agentSessionId),content:r,ephemeral:i.ephemeral,signal:i.signal,signalMetadata:i.signalMetadata}})}function requireAgentSessionId(e){if(e===null)throw Error(`linearChannel: cannot post Agent Activity without an Agent Session id.`);return e}function linearUserLabel(e){return e.displayName??e.name??e.email}function firstNonEmptyLine(e){for(let t of e.split(/\r?\n/u)){let e=t.trim();if(e.length>0)return e}}function actionLabel(e){return e.kind===`tool-call`&&e.toolName?e.toolName:e.kind}function actionParameter(e){if(e.description)return e.description;if(e.name)return e.name;if(e.input!==void 0)try{return JSON.stringify(e.input)}catch{return``}return``}export{createDefaultEvents,defaultLinearAuth,defaultOnAgentSession};
3
+ `),type:`error`})}}}function postActivity(e,t,r,i={}){return createLinearAgentActivity({api:t.api,credentials:t.credentials,activity:{agentSessionId:requireAgentSessionId(e.state.agentSessionId),content:r,ephemeral:i.ephemeral,signal:i.signal,signalMetadata:i.signalMetadata}})}function requireAgentSessionId(e){if(e===null)throw Error(`linearChannel: cannot post Agent Activity without an Agent Session id.`);return e}function linearUserLabel(e){return e.displayName??e.name??e.email}function authorizationDisplayName(e,t){return t===void 0?e.length===0?e:e.charAt(0).toUpperCase()+e.slice(1):t}function authorizationRequiredBody(e){return[`Authorization required for ${e.displayName}.`,e.instructions,e.userCode===void 0?void 0:`Code: ${e.userCode}`].filter(e=>e!==void 0&&e.length>0).join(`
4
+
5
+ `)}function linearUserId(e){let t=e.session.auth.current;return t?.authenticator===`linear-agent-webhook`?t.subject:void 0}function formatAuthorizationOutcome(e){return e===`timed-out`?`timed out`:e}function firstNonEmptyLine(e){for(let t of e.split(/\r?\n/u)){let e=t.trim();if(e.length>0)return e}}function actionLabel(e){return e.kind===`tool-call`&&e.toolName?e.toolName:e.kind}function actionParameter(e){if(e.description)return e.description;if(e.name)return e.name;if(e.input!==void 0)try{return JSON.stringify(e.input)}catch{return``}return``}export{createDefaultEvents,defaultLinearAuth,defaultOnAgentSession};
@@ -1,12 +1,12 @@
1
1
  import type { SessionAuthContext } from "#channel/types.js";
2
- import type { HandleMessageStreamEvent } from "#protocol/message.js";
2
+ import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
3
3
  import { createLinearAgentActivity, listLinearAgentSessionActivities, updateLinearAgentSession, type LinearApiOptions } from "#public/channels/linear/api.js";
4
4
  import type { LinearChannelCredentials } from "#public/channels/linear/auth.js";
5
5
  import { type LinearAgentSessionEvent, type LinearAgentSessionRef, type LinearDataWebhookEvent, type LinearDelivery } from "#public/channels/linear/inbound.js";
6
6
  import type { SessionContext } from "#public/definitions/callback-context.js";
7
7
  import { type Channel, type ChannelSessionOps } from "#public/definitions/channel.js";
8
8
  import type { JsonObject } from "#shared/json.js";
9
- type EventData<T extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
9
+ type EventData<T extends UnstampedMessageStreamEvent["type"]> = Extract<UnstampedMessageStreamEvent, {
10
10
  type: T;
11
11
  }> extends {
12
12
  data: infer D;
@@ -90,7 +90,7 @@ export interface LinearHandle {
90
90
  readonly success: boolean;
91
91
  }>;
92
92
  }
93
- type LinearEventHandler<T extends HandleMessageStreamEvent["type"]> = (data: EventData<T>, channel: LinearEventContext, ctx: SessionContext) => void | Promise<void>;
93
+ type LinearEventHandler<T extends UnstampedMessageStreamEvent["type"]> = (data: EventData<T>, channel: LinearEventContext, ctx: SessionContext) => void | Promise<void>;
94
94
  type LinearSessionFailedHandler = (data: EventData<"session.failed">, channel: LinearEventContext) => void | Promise<void>;
95
95
  /** Event handlers supported by `linearChannel({ events })`. */
96
96
  export interface LinearChannelEvents {
@@ -1,4 +1,4 @@
1
1
  import{SLACK_SECTION_TEXT_MAX_LENGTH,truncateCardBodyText,truncateModalTitle,truncatePlainText,truncateSectionText}from"#public/channels/slack/limits.js";const HITL_ACTION_PREFIX=`eve_input:`,HITL_FREEFORM_ACTION_PREFIX=`eve_input_freeform:`,HITL_FREEFORM_MODAL_CALLBACK_ID=`eve_input_freeform_submit`,HITL_FREEFORM_MODAL_BLOCK_ID=`eve_freeform_block`,HITL_FREEFORM_MODAL_ACTION_ID=`eve_freeform_text`,BUTTON_ACTION_ID_RE=/^(?<requestId>.+):button:\d+$/u,TOOL_INPUT_SUFFIX="\n```";function deriveHitlResponse(e){if(!e.actionId.startsWith(`eve_input:`))return null;let t=e.actionId.slice(10);if(e.selectedOptionValue!==void 0)return t?{optionId:e.selectedOptionValue,requestId:t}:null;if(e.value!==void 0){let n=BUTTON_ACTION_ID_RE.exec(t)?.groups?.requestId;return n?{optionId:e.value,requestId:n}:null}return null}function isHitlAction(e){return e.startsWith(HITL_ACTION_PREFIX)}function renderInputRequestBlocks(e){let t={text:{text:truncateSectionText(e.prompt),type:`mrkdwn`},type:`section`},n=renderInputRequestDetailBlocks(e),r=`${HITL_ACTION_PREFIX}${e.requestId}`,a=e.options,o=e.allowFreeform===!0||!a||a.length===0;if(a&&a.length>0&&e.display===`select`){let e=a.length<=6?{type:`radio_buttons`,action_id:r,options:a.map(buildOption)}:{type:`static_select`,action_id:r,options:a.map(buildOption),placeholder:{type:`plain_text`,text:`Choose an option`}};return[t,...n,{type:`actions`,elements:[e]}]}if(a&&a.length>0){let t=renderInputRequestCardBlock(e,r),n=renderToolInputContainerBlock(e);return n===void 0?[t]:[t,n]}return o?[t,...n,{type:`actions`,elements:[{type:`button`,action_id:`${HITL_FREEFORM_ACTION_PREFIX}${e.requestId}`,text:{type:`plain_text`,text:`Type your answer`},style:`primary`,value:e.requestId}]}]:[t]}function formatInputRequestFallbackText(e){let t=formatToolInputDetails(e);return t===void 0?e.prompt:`${e.prompt}\n${t}`}function buildFreeformModalView(e){let t=e.prompt?truncateModalTitle(e.prompt):`Your answer`,r=e.prompt?[{type:`section`,text:{type:`mrkdwn`,text:truncateSectionText(e.prompt)}}]:[];return{type:`modal`,callback_id:HITL_FREEFORM_MODAL_CALLBACK_ID,private_metadata:JSON.stringify(e.metadata),title:{type:`plain_text`,text:t},submit:{type:`plain_text`,text:`Submit`},close:{type:`plain_text`,text:`Cancel`},blocks:[...r,{type:`input`,block_id:HITL_FREEFORM_MODAL_BLOCK_ID,element:{type:`plain_text_input`,action_id:HITL_FREEFORM_MODAL_ACTION_ID,multiline:!0,placeholder:{type:`plain_text`,text:`Type your answer here...`}},label:{type:`plain_text`,text:`Answer`}}]}}function isFreeformAction(e){return e.startsWith(HITL_FREEFORM_ACTION_PREFIX)}function freeformRequestIdFromActionId(e){if(!isFreeformAction(e))return;let t=e.slice(19);return t.length>0?t:void 0}function buildCardButton(e,t,n){let i={type:`button`,text:{type:`plain_text`,text:truncatePlainText(e.label),emoji:!1},action_id:`${t}:button:${n}`,value:e.id};return(e.style===`primary`||e.style===`danger`)&&(i.style=e.style),i}function buildOption(e){let t={text:{text:truncatePlainText(e.label),type:`plain_text`},value:e.id},n=truncatePlainText(e.description);return n&&n.length>0&&(t.description={text:n,type:`plain_text`}),t}function renderInputRequestCardBlock(e,n){return{type:`card`,body:{type:`mrkdwn`,text:truncateCardBodyText(`*${e.prompt}*`),verbatim:!1},actions:cardButtonOptions(e).map((e,t)=>buildCardButton(e,n,t))}}function cardButtonOptions(e){let t=e.options??[];if(!isApprovalRequest(e))return t.map(toCardButtonOption);let n=t.find(e=>e.id===`approve`),r=t.find(e=>e.id===`deny`);return!n||!r?t.map(toCardButtonOption):[{id:r.id,label:`Deny`},{id:n.id,label:`Allow`,style:`primary`}]}function toCardButtonOption(e){let t={id:e.id,label:e.label};return e.style===`primary`||e.style===`danger`?{...t,style:e.style}:t}function buildAnsweredBlocks(t){let n=[];for(let e of t.promptBlocks)e!=null&&n.push(e);let r=truncateWithEllipsis(t.answerLabel,SLACK_SECTION_TEXT_MAX_LENGTH-20-1);return n.push({type:`section`,text:{type:`mrkdwn`,text:`:white_check_mark: *${r}*`}}),t.userId&&t.userId.length>0&&n.push({type:`context`,elements:[{type:`mrkdwn`,text:`Answered by <@${t.userId}>`}]}),n}function renderInputRequestDetailBlocks(e){let t=formatToolInputDetails(e);return t===void 0?[]:[{type:`section`,text:{type:`mrkdwn`,text:t}}]}function renderToolInputContainerBlock(e){let t=formatToolInputContainerText(e);if(t!==void 0)return{type:`container`,title:{type:`plain_text`,text:`Tool input`},is_collapsible:!0,default_collapsed:!1,child_blocks:[{type:`section`,text:{type:`mrkdwn`,text:t}}]}}function formatToolInputContainerText(t){if(!isApprovalRequest(t))return;let n=JSON.stringify(t.action.input,null,2);return n===`{}`?void 0:`\`\`\`
2
2
  ${truncateWithEllipsis(n,SLACK_SECTION_TEXT_MAX_LENGTH-4-4)}${TOOL_INPUT_SUFFIX}`}function formatToolInputDetails(t){if(!isApprovalRequest(t))return;let n=JSON.stringify(t.action.input,null,2);return n===`{}`?void 0:`*Tool input*
3
3
  \`\`\`
4
- ${truncateWithEllipsis(n,SLACK_SECTION_TEXT_MAX_LENGTH-17-4)}${TOOL_INPUT_SUFFIX}`}function truncateWithEllipsis(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}function isApprovalRequest(e){return e.display===`confirmation`&&e.options?.length===2&&e.options[0]?.id===`approve`&&e.options[1]?.id===`deny`}export{HITL_ACTION_PREFIX,HITL_FREEFORM_ACTION_PREFIX,HITL_FREEFORM_MODAL_ACTION_ID,HITL_FREEFORM_MODAL_BLOCK_ID,HITL_FREEFORM_MODAL_CALLBACK_ID,buildAnsweredBlocks,buildFreeformModalView,deriveHitlResponse,formatInputRequestFallbackText,freeformRequestIdFromActionId,isFreeformAction,isHitlAction,renderInputRequestBlocks};
4
+ ${truncateWithEllipsis(n,SLACK_SECTION_TEXT_MAX_LENGTH-17-4)}${TOOL_INPUT_SUFFIX}`}function truncateWithEllipsis(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}function isApprovalRequest(e){return e.kind===`tool-approval`}export{HITL_ACTION_PREFIX,HITL_FREEFORM_ACTION_PREFIX,HITL_FREEFORM_MODAL_ACTION_ID,HITL_FREEFORM_MODAL_BLOCK_ID,HITL_FREEFORM_MODAL_CALLBACK_ID,buildAnsweredBlocks,buildFreeformModalView,deriveHitlResponse,formatInputRequestFallbackText,freeformRequestIdFromActionId,isFreeformAction,isHitlAction,renderInputRequestBlocks};
@@ -4,14 +4,14 @@ import type { CancelTurnResult, SessionAuthContext } from "#channel/types.js";
4
4
  import type { CardElement } from "#compiled/chat/index.js";
5
5
  import type { SessionContext } from "#public/definitions/callback-context.js";
6
6
  import type { ChannelSessionOps } from "#public/definitions/channel.js";
7
- import type { HandleMessageStreamEvent } from "#protocol/message.js";
7
+ import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
8
8
  import { type SlackBotToken, type SlackHandle, type SlackThread, type SlackWorkspaceHandle } from "#public/channels/slack/api.js";
9
9
  import { type SlackEvent, type SlackEventEnvelope, type SlackMessage } from "#public/channels/slack/inbound.js";
10
10
  import { type LoadThreadContextMessagesOptions } from "#public/channels/slack/thread.js";
11
11
  import { type UploadPolicyInput } from "#public/channels/upload-policy.js";
12
12
  import { type SlackWebhookVerifier } from "#public/channels/slack/verify.js";
13
13
  import { type Channel, type ResetResult } from "#public/definitions/channel.js";
14
- type EventData<T extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
14
+ type EventData<T extends UnstampedMessageStreamEvent["type"]> = Extract<UnstampedMessageStreamEvent, {
15
15
  type: T;
16
16
  }> extends {
17
17
  data: infer D;
@@ -46,7 +46,7 @@ export interface SlackEventContext extends SlackChannelContext, ChannelSessionOp
46
46
  }
47
47
  export type { SlackApiResponse, SlackBotToken, SlackHandle, SlackThread, SlackWorkspaceHandle, } from "#public/channels/slack/api.js";
48
48
  export type { SlackWebhookVerifier } from "#public/channels/slack/verify.js";
49
- type SlackEventHandler<T extends HandleMessageStreamEvent["type"]> = (data: EventData<T>, channel: SlackEventContext, ctx: SessionContext) => void | Promise<void>;
49
+ type SlackEventHandler<T extends UnstampedMessageStreamEvent["type"]> = (data: EventData<T>, channel: SlackEventContext, ctx: SessionContext) => void | Promise<void>;
50
50
  /**
51
51
  * Delivery surface handed to `authorization.required` overrides. The
52
52
  * connection challenge is a credential: anyone who completes the sign-in
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{TEAMS_ADAPTIVE_CARD_ACTION_LIMIT,TEAMS_ADAPTIVE_CARD_ACTION_TITLE_MAX_LENGTH,TEAMS_ADAPTIVE_CARD_CHOICE_TITLE_MAX_LENGTH,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH}from"#public/channels/teams/limits.js";const TEAMS_ADAPTIVE_CARD_CONTENT_TYPE=`application/vnd.microsoft.card.adaptive`,TEAMS_HITL_DATA_KEY=`eve_input`,TEAMS_HITL_CHOICE_INPUT_ID=`eve_option`,TEAMS_HITL_FREEFORM_INPUT_ID=`eve_freeform_text`;function renderInputRequestMessage(e,t={}){let n=formatApprovalInput(e),r=n?truncate(n,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH):null;return{attachments:[renderInputRequestAttachment(e,t)],text:r?`${e.prompt}\n\nTool input:\n${r}`:e.prompt}}function renderInputRequestAttachment(e,n={}){let r=formatApprovalInput(e);return{content:parseJsonObject({$schema:`http://adaptivecards.io/schemas/adaptive-card.json`,actions:renderActions(e,n.replyToActivityId),body:[{text:truncate(e.prompt,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH),type:`TextBlock`,wrap:!0},...r?[{fontType:`Monospace`,text:truncate(r,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH),type:`TextBlock`,wrap:!0}]:[],...renderInputs(e)],type:`AdaptiveCard`,version:n.adaptiveCardVersion??`1.5`}),contentType:TEAMS_ADAPTIVE_CARD_CONTENT_TYPE}}function renderAnsweredInputRequestMessage(e){return{attachments:[{content:parseJsonObject({$schema:`http://adaptivecards.io/schemas/adaptive-card.json`,body:[{text:truncate(e.prompt,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH),type:`TextBlock`,wrap:!0},{color:`good`,text:e.label?`Answered: ${e.label}`:`Answered`,type:`TextBlock`,wrap:!0}],type:`AdaptiveCard`,version:`1.5`}),contentType:TEAMS_ADAPTIVE_CARD_CONTENT_TYPE}],text:e.label?`Answered: ${e.label}`:`Answered`}}function isTeamsInputResponseActivity(e){return deriveTeamsInputResponses(e).length>0}function deriveTeamsInputResponses(e){let t=readActivityValue(e);if(!t)return[];let n=readHitlPayload(t);if(!n)return[];let r=typeof n.requestId==`string`?n.requestId:``;if(!r)return[];let i=typeof n.optionId==`string`?n.optionId:typeof t.eve_option==`string`?t[TEAMS_HITL_CHOICE_INPUT_ID]:void 0,a=typeof t.eve_freeform_text==`string`?t[TEAMS_HITL_FREEFORM_INPUT_ID]:void 0;return i===void 0?a===void 0?[{requestId:r}]:[{requestId:r,text:a}]:[{optionId:i,requestId:r}]}function readTeamsInputReplyToActivityId(e){let t=readActivityValue(e);if(!t)return null;let n=readHitlPayload(t);return n&&typeof n.replyToActivityId==`string`?n.replyToActivityId:null}function teamsInvokeResponse(e={}){return{statusCode:e.statusCode??200,type:`application/vnd.microsoft.activity.message`,value:e.message??`Answer received.`}}function renderInputs(e){return e.display===`select`&&e.options&&e.options.length>0?[{choices:e.options.map(e=>({title:truncate(e.label,TEAMS_ADAPTIVE_CARD_CHOICE_TITLE_MAX_LENGTH),value:e.id})),id:TEAMS_HITL_CHOICE_INPUT_ID,isMultiSelect:!1,style:`compact`,type:`Input.ChoiceSet`}]:e.allowFreeform===!0||!e.options||e.options.length===0?[{id:TEAMS_HITL_FREEFORM_INPUT_ID,isMultiline:!0,placeholder:`Type your answer`,type:`Input.Text`}]:[]}function renderActions(e,t){let payload=n=>{let r={requestId:e.requestId};return t!==void 0&&(r.replyToActivityId=t),n!==void 0&&(r.optionId=n),r},i=e.options;return i&&i.length>0&&e.display!==`select`?i.slice(0,TEAMS_ADAPTIVE_CARD_ACTION_LIMIT).map(e=>({data:{[TEAMS_HITL_DATA_KEY]:payload(e.id)},title:truncate(e.label,TEAMS_ADAPTIVE_CARD_ACTION_TITLE_MAX_LENGTH),type:`Action.Submit`})):[{data:{[TEAMS_HITL_DATA_KEY]:payload()},title:`Submit`,type:`Action.Submit`}]}function readActivityValue(e){return e.type===`message`?readMessageValue(e):e.type===`invoke`?readInvokeValue(e):null}function readMessageValue(e){return e.value??null}function readInvokeValue(t){let n=t.value;if(!n)return null;let r=isObject(n.action)?n.action:null;return(r&&isObject(r.data)?r.data:null)??n}function readHitlPayload(t){let n=t[TEAMS_HITL_DATA_KEY];if(isObject(n))return n;let r=isObject(t.action)?t.action:null,i=(r&&isObject(r.data)?r.data:null)?.[TEAMS_HITL_DATA_KEY];return isObject(i)?i:null}function formatApprovalInput(e){if(e.display!==`confirmation`||e.options?.length!==2||e.options[0]?.id!==`approve`||e.options[1]?.id!==`deny`)return null;let t=JSON.stringify(e.action.input,null,2);return t===`{}`?null:t}function truncate(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}export{TEAMS_ADAPTIVE_CARD_CONTENT_TYPE,TEAMS_HITL_CHOICE_INPUT_ID,TEAMS_HITL_DATA_KEY,TEAMS_HITL_FREEFORM_INPUT_ID,deriveTeamsInputResponses,isTeamsInputResponseActivity,readTeamsInputReplyToActivityId,renderAnsweredInputRequestMessage,renderInputRequestAttachment,renderInputRequestMessage,teamsInvokeResponse};
1
+ import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{TEAMS_ADAPTIVE_CARD_ACTION_LIMIT,TEAMS_ADAPTIVE_CARD_ACTION_TITLE_MAX_LENGTH,TEAMS_ADAPTIVE_CARD_CHOICE_TITLE_MAX_LENGTH,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH}from"#public/channels/teams/limits.js";const TEAMS_ADAPTIVE_CARD_CONTENT_TYPE=`application/vnd.microsoft.card.adaptive`,TEAMS_HITL_DATA_KEY=`eve_input`,TEAMS_HITL_CHOICE_INPUT_ID=`eve_option`,TEAMS_HITL_FREEFORM_INPUT_ID=`eve_freeform_text`;function renderInputRequestMessage(e,t={}){let n=formatApprovalInput(e),r=n?truncate(n,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH):null;return{attachments:[renderInputRequestAttachment(e,t)],text:r?`${e.prompt}\n\nTool input:\n${r}`:e.prompt}}function renderInputRequestAttachment(e,n={}){let r=formatApprovalInput(e);return{content:parseJsonObject({$schema:`http://adaptivecards.io/schemas/adaptive-card.json`,actions:renderActions(e,n.replyToActivityId),body:[{text:truncate(e.prompt,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH),type:`TextBlock`,wrap:!0},...r?[{fontType:`Monospace`,text:truncate(r,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH),type:`TextBlock`,wrap:!0}]:[],...renderInputs(e)],type:`AdaptiveCard`,version:n.adaptiveCardVersion??`1.5`}),contentType:TEAMS_ADAPTIVE_CARD_CONTENT_TYPE}}function renderAnsweredInputRequestMessage(e){return{attachments:[{content:parseJsonObject({$schema:`http://adaptivecards.io/schemas/adaptive-card.json`,body:[{text:truncate(e.prompt,TEAMS_ADAPTIVE_CARD_TEXT_MAX_LENGTH),type:`TextBlock`,wrap:!0},{color:`good`,text:e.label?`Answered: ${e.label}`:`Answered`,type:`TextBlock`,wrap:!0}],type:`AdaptiveCard`,version:`1.5`}),contentType:TEAMS_ADAPTIVE_CARD_CONTENT_TYPE}],text:e.label?`Answered: ${e.label}`:`Answered`}}function isTeamsInputResponseActivity(e){return deriveTeamsInputResponses(e).length>0}function deriveTeamsInputResponses(e){let t=readActivityValue(e);if(!t)return[];let n=readHitlPayload(t);if(!n)return[];let r=typeof n.requestId==`string`?n.requestId:``;if(!r)return[];let i=typeof n.optionId==`string`?n.optionId:typeof t.eve_option==`string`?t[TEAMS_HITL_CHOICE_INPUT_ID]:void 0,a=typeof t.eve_freeform_text==`string`?t[TEAMS_HITL_FREEFORM_INPUT_ID]:void 0;return i===void 0?a===void 0?[{requestId:r}]:[{requestId:r,text:a}]:[{optionId:i,requestId:r}]}function readTeamsInputReplyToActivityId(e){let t=readActivityValue(e);if(!t)return null;let n=readHitlPayload(t);return n&&typeof n.replyToActivityId==`string`?n.replyToActivityId:null}function teamsInvokeResponse(e={}){return{statusCode:e.statusCode??200,type:`application/vnd.microsoft.activity.message`,value:e.message??`Answer received.`}}function renderInputs(e){return e.display===`select`&&e.options&&e.options.length>0?[{choices:e.options.map(e=>({title:truncate(e.label,TEAMS_ADAPTIVE_CARD_CHOICE_TITLE_MAX_LENGTH),value:e.id})),id:TEAMS_HITL_CHOICE_INPUT_ID,isMultiSelect:!1,style:`compact`,type:`Input.ChoiceSet`}]:e.allowFreeform===!0||!e.options||e.options.length===0?[{id:TEAMS_HITL_FREEFORM_INPUT_ID,isMultiline:!0,placeholder:`Type your answer`,type:`Input.Text`}]:[]}function renderActions(e,t){let payload=n=>{let r={requestId:e.requestId};return t!==void 0&&(r.replyToActivityId=t),n!==void 0&&(r.optionId=n),r},i=e.options;return i&&i.length>0&&e.display!==`select`?i.slice(0,TEAMS_ADAPTIVE_CARD_ACTION_LIMIT).map(e=>({data:{[TEAMS_HITL_DATA_KEY]:payload(e.id)},title:truncate(e.label,TEAMS_ADAPTIVE_CARD_ACTION_TITLE_MAX_LENGTH),type:`Action.Submit`})):[{data:{[TEAMS_HITL_DATA_KEY]:payload()},title:`Submit`,type:`Action.Submit`}]}function readActivityValue(e){return e.type===`message`?readMessageValue(e):e.type===`invoke`?readInvokeValue(e):null}function readMessageValue(e){return e.value??null}function readInvokeValue(t){let n=t.value;if(!n)return null;let r=isObject(n.action)?n.action:null;return(r&&isObject(r.data)?r.data:null)??n}function readHitlPayload(t){let n=t[TEAMS_HITL_DATA_KEY];if(isObject(n))return n;let r=isObject(t.action)?t.action:null,i=(r&&isObject(r.data)?r.data:null)?.[TEAMS_HITL_DATA_KEY];return isObject(i)?i:null}function formatApprovalInput(e){if(e.kind!==`tool-approval`)return null;let t=JSON.stringify(e.action.input,null,2);return t===`{}`?null:t}function truncate(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}export{TEAMS_ADAPTIVE_CARD_CONTENT_TYPE,TEAMS_HITL_CHOICE_INPUT_ID,TEAMS_HITL_DATA_KEY,TEAMS_HITL_FREEFORM_INPUT_ID,deriveTeamsInputResponses,isTeamsInputResponseActivity,readTeamsInputReplyToActivityId,renderAnsweredInputRequestMessage,renderInputRequestAttachment,renderInputRequestMessage,teamsInvokeResponse};
@@ -2,14 +2,14 @@ import type { TeamsInstrumentationMetadata } from "#public/channels/teams/index.
2
2
  import type { SessionAuthContext } from "#channel/types.js";
3
3
  import type { SessionContext } from "#public/definitions/callback-context.js";
4
4
  import type { ChannelSessionOps } from "#public/definitions/channel.js";
5
- import type { HandleMessageStreamEvent } from "#protocol/message.js";
5
+ import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
6
6
  import { type TeamsFilesConfig } from "#public/channels/teams/attachments.js";
7
7
  import { type TeamsApiOptions, type TeamsApiResponse, type TeamsChannelAccount, type TeamsCredentials, type TeamsMention, type TeamsMessageBody, type TeamsOutboundActivity, type TeamsPostedActivity } from "#public/channels/teams/api.js";
8
8
  import { type TeamsInvokeActivity, type TeamsMessageActivity } from "#public/channels/teams/inbound.js";
9
9
  import { type TeamsWebhookVerifier } from "#public/channels/teams/verify.js";
10
10
  import { type JsonObject } from "#shared/json.js";
11
11
  import { type Channel } from "#public/definitions/channel.js";
12
- type EventData<T extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
12
+ type EventData<T extends UnstampedMessageStreamEvent["type"]> = Extract<UnstampedMessageStreamEvent, {
13
13
  type: T;
14
14
  }> extends {
15
15
  data: infer D;
@@ -92,7 +92,7 @@ export type TeamsInputResponseResult = {
92
92
  export type TeamsInvokeResult = Record<string, unknown> | Response | null | undefined;
93
93
  /** Sync or async {@link TeamsInvokeResult}. */
94
94
  export type TeamsInvokeResultOrPromise = TeamsInvokeResult | Promise<TeamsInvokeResult>;
95
- type TeamsEventHandler<T extends HandleMessageStreamEvent["type"]> = (data: EventData<T>, channel: TeamsEventContext, ctx: SessionContext) => void | Promise<void>;
95
+ type TeamsEventHandler<T extends UnstampedMessageStreamEvent["type"]> = (data: EventData<T>, channel: TeamsEventContext, ctx: SessionContext) => void | Promise<void>;
96
96
  type TeamsSessionFailedHandler = (data: EventData<"session.failed">, channel: TeamsEventContext) => void | Promise<void>;
97
97
  /** Event handlers supported by `teamsChannel({ events })`. */
98
98
  export interface TeamsChannelEvents {
@@ -2,7 +2,7 @@ import type { TelegramInstrumentationMetadata } from "#public/channels/telegram/
2
2
  import type { SessionAuthContext } from "#channel/types.js";
3
3
  import type { SessionContext } from "#public/definitions/callback-context.js";
4
4
  import type { ChannelSessionOps } from "#public/definitions/channel.js";
5
- import type { HandleMessageStreamEvent } from "#protocol/message.js";
5
+ import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
6
6
  import { type TelegramApiOptions, type TelegramApiResponse, type TelegramCredentials, type TelegramMessageBody, type TelegramMessageResult } from "#public/channels/telegram/api.js";
7
7
  import { type TelegramHitlState } from "#public/channels/telegram/hitl.js";
8
8
  import { type TelegramCallbackQuery, type TelegramChatType, type TelegramMessage } from "#public/channels/telegram/inbound.js";
@@ -10,7 +10,7 @@ import { type UploadPolicyInput } from "#public/channels/upload-policy.js";
10
10
  import { type TelegramWebhookSecretToken, type TelegramWebhookVerifier } from "#public/channels/telegram/verify.js";
11
11
  import { type Channel } from "#public/definitions/channel.js";
12
12
  import { type JsonObject } from "#shared/json.js";
13
- type EventData<T extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
13
+ type EventData<T extends UnstampedMessageStreamEvent["type"]> = Extract<UnstampedMessageStreamEvent, {
14
14
  type: T;
15
15
  }> extends {
16
16
  data: infer D;
@@ -61,7 +61,7 @@ export type TelegramInboundResult = {
61
61
  } | null;
62
62
  /** Sync or async {@link TelegramInboundResult}. */
63
63
  export type TelegramInboundResultOrPromise = TelegramInboundResult | Promise<TelegramInboundResult>;
64
- type TelegramEventHandler<T extends HandleMessageStreamEvent["type"]> = (data: EventData<T>, channel: TelegramEventContext, ctx: SessionContext) => void | Promise<void>;
64
+ type TelegramEventHandler<T extends UnstampedMessageStreamEvent["type"]> = (data: EventData<T>, channel: TelegramEventContext, ctx: SessionContext) => void | Promise<void>;
65
65
  type TelegramSessionFailedHandler = (data: EventData<"session.failed">, channel: TelegramEventContext) => void | Promise<void>;
66
66
  /** Per-event handlers for `telegramChannel({ events })`. Each entry overrides the built-in default (handlers merge over {@link defaultEvents}). `session.failed` receives `(data, channel)`; all others also receive the {@link SessionContext}. */
67
67
  export interface TelegramChannelEvents {
@@ -1,12 +1,12 @@
1
1
  import type { SessionAuthContext } from "#channel/types.js";
2
2
  import type { SessionContext } from "#public/definitions/callback-context.js";
3
3
  import type { ChannelSessionOps } from "#public/definitions/channel.js";
4
- import type { HandleMessageStreamEvent } from "#protocol/message.js";
4
+ import type { UnstampedMessageStreamEvent } from "#protocol/message.js";
5
5
  import { type TwilioApiOptions, type TwilioApiResponse, type TwilioCredentials } from "#public/channels/twilio/api.js";
6
6
  import { type TwilioTextMessage, type TwilioVoiceCall, type TwilioVoiceTranscription } from "#public/channels/twilio/inbound.js";
7
7
  import { type TwilioAuthToken, type TwilioWebhookUrl } from "#public/channels/twilio/verify.js";
8
8
  import { type Channel } from "#public/definitions/channel.js";
9
- type EventData<T extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
9
+ type EventData<T extends UnstampedMessageStreamEvent["type"]> = Extract<UnstampedMessageStreamEvent, {
10
10
  type: T;
11
11
  }> extends {
12
12
  data: infer D;
@@ -82,7 +82,7 @@ export interface TwilioVoiceResult {
82
82
  }
83
83
  /** Sync or async {@link TwilioVoiceResult}. */
84
84
  export type TwilioVoiceResultOrPromise = TwilioVoiceResult | null | undefined | Promise<TwilioVoiceResult | null | undefined>;
85
- type TwilioEventHandler<T extends HandleMessageStreamEvent["type"]> = (data: EventData<T>, channel: TwilioEventContext, ctx: SessionContext) => void | Promise<void>;
85
+ type TwilioEventHandler<T extends UnstampedMessageStreamEvent["type"]> = (data: EventData<T>, channel: TwilioEventContext, ctx: SessionContext) => void | Promise<void>;
86
86
  type TwilioSessionFailedHandler = (data: EventData<"session.failed">, channel: TwilioEventContext) => void | Promise<void>;
87
87
  /** Event handlers supported by `twilioChannel({ events })`. */
88
88
  export interface TwilioChannelEvents {
@@ -4,7 +4,7 @@ import type { TypedReceiveTarget } from "#channel/receive-target.js";
4
4
  import type { RouteDefinition, SendFn } from "#channel/routes.js";
5
5
  import type { Session } from "#channel/session.js";
6
6
  import type { CancelTurnInput, CancelTurnResult, DeliverInput, GetEventStreamOptions, RunHandle, RunInput } from "#channel/types.js";
7
- import type { HandleMessageStreamEvent } from "#protocol/message.js";
7
+ import type { UnstampedMessageStreamEvent, MessageStreamEvent } from "#protocol/message.js";
8
8
  import type { SessionContext } from "#public/definitions/callback-context.js";
9
9
  import type { GenericChannelDefinition, GenericReceiveInput } from "#shared/channel-definition.js";
10
10
  declare const CHANNEL_METADATA_TYPE: unique symbol;
@@ -120,7 +120,7 @@ export interface Agent {
120
120
  * at the latest event). The framework HTTP session-stream route forwards
121
121
  * the `startIndex` query parameter unchanged.
122
122
  */
123
- getEventStream(sessionId: string, options?: GetEventStreamOptions): Promise<ReadableStream<HandleMessageStreamEvent>>;
123
+ getEventStream(sessionId: string, options?: GetEventStreamOptions): Promise<ReadableStream<MessageStreamEvent>>;
124
124
  }
125
125
  /**
126
126
  * Marker discriminator written into every {@link DisabledRouteSentinel}.
@@ -146,7 +146,7 @@ export declare function disableRoute(): DisabledRouteSentinel;
146
146
  * produced by {@link disableRoute}.
147
147
  */
148
148
  export declare function isDisabledRouteSentinel(value: unknown): value is DisabledRouteSentinel;
149
- type EventData<T extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
149
+ type EventData<T extends UnstampedMessageStreamEvent["type"]> = Extract<UnstampedMessageStreamEvent, {
150
150
  type: T;
151
151
  }> extends {
152
152
  data: infer D;
@@ -163,7 +163,7 @@ export interface ChannelSessionOps {
163
163
  * {@link ChannelSessionOps}.
164
164
  */
165
165
  export type ChannelContext<TCtx> = TCtx & ChannelSessionOps;
166
- type ChannelEventHandler<T extends HandleMessageStreamEvent["type"], TCtx> = (data: EventData<T>, channel: ChannelContext<TCtx>, ctx: SessionContext) => void | Promise<void>;
166
+ type ChannelEventHandler<T extends UnstampedMessageStreamEvent["type"], TCtx> = (data: EventData<T>, channel: ChannelContext<TCtx>, ctx: SessionContext) => void | Promise<void>;
167
167
  type ChannelSessionFailedHandler<TCtx> = (data: EventData<"session.failed">, channel: ChannelContext<TCtx>) => void | Promise<void>;
168
168
  /**
169
169
  * Optional handlers keyed by session lifecycle event name. Each handler receives
@@ -1,7 +1,7 @@
1
- import type { HandleMessageStreamEvent } from "../../protocol/message.js";
1
+ import type { MessageStreamEvent } from "../../protocol/message.js";
2
2
  import type { SessionContext } from "./callback-context.js";
3
3
  import type { ExactDefinition } from "./exact.js";
4
- type ProtocolEvent<TType extends HandleMessageStreamEvent["type"]> = Extract<HandleMessageStreamEvent, {
4
+ type ProtocolEvent<TType extends MessageStreamEvent["type"]> = Extract<MessageStreamEvent, {
5
5
  type: TType;
6
6
  }>;
7
7
  /**
@@ -2,7 +2,7 @@ import { type EveAgentStoreCallbacks, type EveAgentStoreSnapshot, type EveAgentS
2
2
  import type { EveAgentReducer } from "#client/reducer.js";
3
3
  import type { ClientSession } from "#client/session.js";
4
4
  import { type EveMessageData } from "#client/message-reducer.js";
5
- import type { HandleMessageStreamEvent } from "#protocol/message.js";
5
+ import type { MessageStreamEvent } from "#protocol/message.js";
6
6
  import type { ClientAuth, HeadersValue, SendTurnPayload, SessionState } from "#client/types.js";
7
7
  export type { PrepareSend };
8
8
  /**
@@ -61,7 +61,8 @@ export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData>
61
61
  * @default ""
62
62
  */
63
63
  readonly host?: string;
64
- readonly initialEvents?: readonly HandleMessageStreamEvent[];
64
+ /** Ordered prefix of the session stream used to rehydrate projected state. */
65
+ readonly initialEvents?: readonly MessageStreamEvent[];
65
66
  readonly initialSession?: SessionState;
66
67
  /**
67
68
  * Project submitted user messages before eve confirms them with a
@@ -1 +1 @@
1
- import{z}from"#compiled/zod/index.js";import{inputRequestSchema}from"#runtime/input/types.js";const ASK_QUESTION_TOOL_NAME=`ask_question`,ASK_QUESTION_INPUT_SCHEMA=inputRequestSchema.omit({action:!0,display:!0,requestId:!0}),ASK_QUESTION_OUTPUT_SCHEMA=z.object({optionId:z.string().optional(),status:z.enum([`answered`,`ignored`]),text:z.string().optional()}).strict(),ASK_QUESTION_TOOL_DEFINITION={description:`Ask the user a question and wait for their response before continuing. Use this when you need clarification or a choice from the user.`,inputSchema:ASK_QUESTION_INPUT_SCHEMA,logicalPath:`eve:framework/ask-question`,name:ASK_QUESTION_TOOL_NAME,outputSchema:ASK_QUESTION_OUTPUT_SCHEMA,sourceId:`eve:ask-question-tool`,sourceKind:`module`};export{ASK_QUESTION_INPUT_SCHEMA,ASK_QUESTION_OUTPUT_SCHEMA,ASK_QUESTION_TOOL_DEFINITION,ASK_QUESTION_TOOL_NAME};
1
+ import{z}from"#compiled/zod/index.js";import{inputRequestSchema}from"#runtime/input/types.js";const ASK_QUESTION_TOOL_NAME=`ask_question`,ASK_QUESTION_INPUT_SCHEMA=inputRequestSchema.omit({action:!0,display:!0,kind:!0,requestId:!0}),ASK_QUESTION_OUTPUT_SCHEMA=z.object({optionId:z.string().optional(),status:z.enum([`answered`,`ignored`]),text:z.string().optional()}).strict(),ASK_QUESTION_TOOL_DEFINITION={description:`Ask the user a question and wait for their response before continuing. Use this when you need clarification or a choice from the user.`,inputSchema:ASK_QUESTION_INPUT_SCHEMA,logicalPath:`eve:framework/ask-question`,name:ASK_QUESTION_TOOL_NAME,outputSchema:ASK_QUESTION_OUTPUT_SCHEMA,sourceId:`eve:ask-question-tool`,sourceKind:`module`};export{ASK_QUESTION_INPUT_SCHEMA,ASK_QUESTION_OUTPUT_SCHEMA,ASK_QUESTION_TOOL_DEFINITION,ASK_QUESTION_TOOL_NAME};
@@ -1,4 +1,4 @@
1
- import type { HandleMessageStreamEvent } from "#protocol/message.js";
1
+ import type { MessageStreamEvent } from "#protocol/message.js";
2
2
  import type { StreamEventHook } from "../../public/definitions/hook.js";
3
3
  import type { ResolvedHookDefinition } from "../types.js";
4
4
  /**
@@ -9,7 +9,7 @@ import type { ResolvedHookDefinition } from "../types.js";
9
9
  */
10
10
  interface RuntimeStreamEventHookEntry {
11
11
  readonly slug: string;
12
- readonly handler: StreamEventHook<HandleMessageStreamEvent>;
12
+ readonly handler: StreamEventHook<MessageStreamEvent>;
13
13
  readonly eventType: string;
14
14
  }
15
15
  /**
@@ -20,11 +20,21 @@ export declare const inputOptionSchema: z.ZodObject<{
20
20
  }>>;
21
21
  }, z.core.$strict>;
22
22
  /**
23
- * Unified input request surfaced to the client when the agent needs
24
- * user input before continuing.
23
+ * Framework-owned source of an input request.
25
24
  *
26
- * Tool approvals and questions share this shape. Approvals are requests
27
- * with two options (`"approve"` / `"deny"`) and `display: "confirmation"`.
25
+ * Consumers use this discriminator for behavior. The action tool name and
26
+ * request id are presentation and identity fields, not request semantics.
27
+ */
28
+ export type InputRequestKind = z.infer<typeof inputRequestKindSchema>;
29
+ /** Zod schema for the framework-owned source of an input request. */
30
+ export declare const inputRequestKindSchema: z.ZodEnum<{
31
+ question: "question";
32
+ "session-limit": "session-limit";
33
+ "tool-approval": "tool-approval";
34
+ }>;
35
+ /**
36
+ * Unified input request surfaced to the client when the agent needs user
37
+ * input before continuing.
28
38
  */
29
39
  export type InputRequest = z.infer<typeof inputRequestSchema>;
30
40
  /**
@@ -43,6 +53,11 @@ export declare const inputRequestSchema: z.ZodObject<{
43
53
  select: "select";
44
54
  text: "text";
45
55
  }>>;
56
+ kind: z.ZodEnum<{
57
+ question: "question";
58
+ "session-limit": "session-limit";
59
+ "tool-approval": "tool-approval";
60
+ }>;
46
61
  options: z.ZodOptional<z.ZodArray<z.ZodObject<{
47
62
  description: z.ZodOptional<z.ZodString>;
48
63
  id: z.ZodString;
@@ -1 +1 @@
1
- import{z}from"#compiled/zod/index.js";import{runtimeToolCallActionRequestSchema}from"#runtime/actions/types.js";const inputOptionSchema=z.object({description:z.string().describe(`Optional additional context for this option.`).optional(),id:z.string().describe(`Stable identifier for the option.`),label:z.string().describe(`User-facing label for the option.`),style:z.enum([`primary`,`danger`,`default`]).describe(`Visual treatment hint for the option.`).optional()}).strict(),inputRequestSchema=z.object({action:runtimeToolCallActionRequestSchema,allowFreeform:z.boolean().describe(`Whether the user may answer with freeform text instead of selecting one of the provided options.`).optional(),display:z.enum([`confirmation`,`select`,`text`]).describe(`Rendering hint: the channel uses this to pick a UX treatment.`).optional(),options:z.array(inputOptionSchema).describe(`Selectable answer options to present to the user.`).optional(),prompt:z.string().describe(`The prompt to present to the user.`),requestId:z.string().describe(`Stable identifier for this request.`)}).strict(),inputResponseSchema=z.object({optionId:z.string().optional(),requestId:z.string(),text:z.string().optional()}).strict();function isInputRequest(e){return inputRequestSchema.safeParse(e).success}function isInputResponse(e){return inputResponseSchema.safeParse(e).success}export{inputOptionSchema,inputRequestSchema,inputResponseSchema,isInputRequest,isInputResponse};
1
+ import{z}from"#compiled/zod/index.js";import{runtimeToolCallActionRequestSchema}from"#runtime/actions/types.js";const inputOptionSchema=z.object({description:z.string().describe(`Optional additional context for this option.`).optional(),id:z.string().describe(`Stable identifier for the option.`),label:z.string().describe(`User-facing label for the option.`),style:z.enum([`primary`,`danger`,`default`]).describe(`Visual treatment hint for the option.`).optional()}).strict(),inputRequestKindSchema=z.enum([`question`,`session-limit`,`tool-approval`]),inputRequestSchema=z.object({action:runtimeToolCallActionRequestSchema,allowFreeform:z.boolean().describe(`Whether the user may answer with freeform text instead of selecting one of the provided options.`).optional(),display:z.enum([`confirmation`,`select`,`text`]).describe(`Rendering hint: the channel uses this to pick a UX treatment.`).optional(),kind:inputRequestKindSchema.describe(`Framework-owned request source used to resolve, route, and render the response.`),options:z.array(inputOptionSchema).describe(`Selectable answer options to present to the user.`).optional(),prompt:z.string().describe(`The prompt to present to the user.`),requestId:z.string().describe(`Stable identifier for this request.`)}).strict(),inputResponseSchema=z.object({optionId:z.string().optional(),requestId:z.string(),text:z.string().optional()}).strict();function isInputRequest(e){return inputRequestSchema.safeParse(e).success}function isInputResponse(e){return inputResponseSchema.safeParse(e).success}export{inputOptionSchema,inputRequestKindSchema,inputRequestSchema,inputResponseSchema,isInputRequest,isInputResponse};
@@ -1 +1 @@
1
- import{ResolveAgentError,createResolvedModuleSourceRef}from"#runtime/resolve-helpers.js";import{resolveChannelDefinition}from"#runtime/resolve-channel.js";import{resolveConnectionDefinition}from"#runtime/resolve-connection.js";import{resolveHookDefinition}from"#runtime/resolve-hook.js";import{resolveSandboxDefinition}from"#runtime/resolve-sandbox.js";import{resolveDynamicInstructionsDefinition}from"#runtime/resolve-dynamic-instructions.js";import{resolveDynamicSkillDefinition}from"#runtime/resolve-dynamic-skill.js";import{resolveDynamicToolDefinition}from"#runtime/resolve-dynamic-tool.js";import{resolveToolDefinition}from"#runtime/resolve-tool.js";async function resolveAgent(e){let t=e.manifest.skills.map(e=>({...e,metadata:e.metadata===void 0?void 0:{...e.metadata}})),r=[],i=[];for(let t of e.manifest.channels){if(t.kind===`disabled`){i.push(t.name);continue}r.push(await resolveChannelDefinition(t,e.moduleMap,e.nodeId))}let a=await Promise.all(e.manifest.tools.map(t=>resolveToolDefinition(t,e.moduleMap,e.nodeId))),o=await Promise.all((e.manifest.dynamicInstructions??[]).map(t=>resolveDynamicInstructionsDefinition(t,e.moduleMap,e.nodeId))),s=await Promise.all((e.manifest.dynamicSkills??[]).map(t=>resolveDynamicSkillDefinition(t,e.moduleMap,e.nodeId))),c=await Promise.all(e.manifest.dynamicTools.map(t=>resolveDynamicToolDefinition(t,e.moduleMap,e.nodeId))),l=await Promise.all(e.manifest.hooks.map(t=>resolveHookDefinition(t,e.moduleMap,e.nodeId))),u=await Promise.all(e.manifest.connections.map(t=>resolveConnectionDefinition(t,e.moduleMap,e.nodeId))),d=e.manifest.sandbox===null?null:await resolveSandboxDefinition(e.manifest.sandbox,e.moduleMap,e.nodeId),f=createResolvedInstructionsDefinition(e.manifest.instructions),p=e.manifest.workspaceResourceRoot,m={channels:r,config:createResolvedAgentConfig(e.manifest),connections:u,disabledFrameworkChannels:i,disabledFrameworkTools:[...e.manifest.disabledFrameworkTools],workflowTool:e.manifest.workflowTool===void 0?void 0:{maxSubagents:e.manifest.workflowTool.maxSubagents},dynamicInstructionsResolvers:o,dynamicSkillResolvers:s,dynamicToolResolvers:c,hooks:l,metadata:{agentRoot:e.manifest.agentRoot,appRoot:e.manifest.appRoot,diagnosticsSummary:e.manifest.diagnosticsSummary},sandbox:d,workspaceResourceRoot:p,skills:t,tools:a,workspaceSpec:{rootEntries:[...p.rootEntries]}};return f===void 0?m:{...m,instructions:f}}function createResolvedInstructionsDefinition(e){if(e!==void 0)return{name:e.name,logicalPath:e.logicalPath,markdown:e.markdown,sourceId:e.sourceId,sourceKind:e.sourceKind}}function createResolvedAgentConfig(e){let n={model:e.config.model.source===void 0?{id:e.config.model.id,contextWindowTokens:e.config.model.contextWindowTokens,providerOptions:e.config.model.providerOptions}:{contextWindowTokens:e.config.model.contextWindowTokens,id:e.config.model.id,providerOptions:e.config.model.providerOptions,source:{exportName:e.config.model.source.exportName,sourceKind:`module`,logicalPath:e.config.model.source.logicalPath,sourceId:e.config.model.source.sourceId}},name:e.config.name};if(e.config.compaction!==void 0){let t={};e.config.compaction.model!==void 0&&(t.model=e.config.compaction.model.source===void 0?{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions}:{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions,source:{exportName:e.config.compaction.model.source.exportName,sourceKind:`module`,logicalPath:e.config.compaction.model.source.logicalPath,sourceId:e.config.compaction.model.source.sourceId}}),e.config.compaction.thresholdPercent!==void 0&&(t.thresholdPercent=e.config.compaction.thresholdPercent),n.compaction=t}return e.config.dynamicModel!==void 0&&(n.dynamicModel={...createResolvedModuleSourceRef(e.config.dynamicModel),eventNames:[...e.config.dynamicModel.eventNames]}),e.config.experimental!==void 0&&(n.experimental={workflow:e.config.experimental.workflow===void 0?void 0:{world:e.config.experimental.workflow.world}}),e.config.outputSchema!==void 0&&(n.outputSchema=e.config.outputSchema),e.config.reasoning!==void 0&&(n.reasoning=e.config.reasoning),e.config.source!==void 0&&(n.source=createResolvedModuleSourceRef(e.config.source)),e.config.limits!==void 0&&(n.limits={maxInputTokensPerSession:e.config.limits.maxInputTokensPerSession,maxOutputTokensPerSession:e.config.limits.maxOutputTokensPerSession}),n}export{ResolveAgentError,resolveAgent};
1
+ import{ResolveAgentError,createResolvedModuleSourceRef}from"#runtime/resolve-helpers.js";import{resolveChannelDefinition}from"#runtime/resolve-channel.js";import{resolveConnectionDefinition}from"#runtime/resolve-connection.js";import{resolveHookDefinition}from"#runtime/resolve-hook.js";import{resolveSandboxDefinition}from"#runtime/resolve-sandbox.js";import{resolveDynamicInstructionsDefinition}from"#runtime/resolve-dynamic-instructions.js";import{resolveDynamicSkillDefinition}from"#runtime/resolve-dynamic-skill.js";import{resolveDynamicToolDefinition}from"#runtime/resolve-dynamic-tool.js";import{resolveToolDefinition}from"#runtime/resolve-tool.js";async function resolveAgent(e){let t=e.manifest.skills.map(e=>({...e,metadata:e.metadata===void 0?void 0:{...e.metadata}})),r=[],i=[];for(let t of e.manifest.channels){if(t.kind===`disabled`){i.push(t.name);continue}r.push(await resolveChannelDefinition(t,e.moduleMap,e.nodeId))}let a=await Promise.all(e.manifest.tools.map(t=>resolveToolDefinition(t,e.moduleMap,e.nodeId))),o=await Promise.all((e.manifest.dynamicInstructions??[]).map(t=>resolveDynamicInstructionsDefinition(t,e.moduleMap,e.nodeId))),s=await Promise.all((e.manifest.dynamicSkills??[]).map(t=>resolveDynamicSkillDefinition(t,e.moduleMap,e.nodeId))),c=await Promise.all(e.manifest.dynamicTools.map(t=>resolveDynamicToolDefinition(t,e.moduleMap,e.nodeId))),l=await Promise.all(e.manifest.hooks.map(t=>resolveHookDefinition(t,e.moduleMap,e.nodeId))),u=await Promise.all(e.manifest.connections.map(t=>resolveConnectionDefinition(t,e.moduleMap,e.nodeId))),d=e.manifest.sandbox===null?null:await resolveSandboxDefinition(e.manifest.sandbox,e.moduleMap,e.nodeId),f=createResolvedInstructionsDefinition(e.manifest.instructions),p=e.manifest.workspaceResourceRoot,m={channels:r,config:createResolvedAgentConfig(e.manifest),connections:u,disabledFrameworkChannels:i,disabledFrameworkTools:[...e.manifest.disabledFrameworkTools],workflowTool:e.manifest.workflowTool===void 0?void 0:{maxSubagents:e.manifest.workflowTool.maxSubagents},dynamicInstructionsResolvers:o,dynamicSkillResolvers:s,dynamicToolResolvers:c,hooks:l,metadata:{agentRoot:e.manifest.agentRoot,appRoot:e.manifest.appRoot,diagnosticsSummary:e.manifest.diagnosticsSummary},sandbox:d,workspaceResourceRoot:p,skills:t,tools:a,workspaceSpec:{rootEntries:[...p.rootEntries]}};return f===void 0?m:{...m,instructions:f}}function createResolvedInstructionsDefinition(e){if(e!==void 0)return{name:e.name,logicalPath:e.logicalPath,markdown:e.markdown,sourceId:e.sourceId,sourceKind:e.sourceKind}}function createResolvedAgentConfig(e){let n={model:e.config.model.source===void 0?{id:e.config.model.id,contextWindowTokens:e.config.model.contextWindowTokens,providerOptions:e.config.model.providerOptions}:{contextWindowTokens:e.config.model.contextWindowTokens,id:e.config.model.id,providerOptions:e.config.model.providerOptions,source:{exportName:e.config.model.source.exportName,sourceKind:`module`,logicalPath:e.config.model.source.logicalPath,sourceId:e.config.model.source.sourceId}},name:e.config.name};if(e.config.compaction!==void 0){let t={};e.config.compaction.model!==void 0&&(t.model=e.config.compaction.model.source===void 0?{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions}:{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions,source:{exportName:e.config.compaction.model.source.exportName,sourceKind:`module`,logicalPath:e.config.compaction.model.source.logicalPath,sourceId:e.config.compaction.model.source.sourceId}}),e.config.compaction.thresholdPercent!==void 0&&(t.thresholdPercent=e.config.compaction.thresholdPercent),n.compaction=t}return e.config.dynamicModel!==void 0&&(n.dynamicModel={...createResolvedModuleSourceRef(e.config.dynamicModel),eventNames:[...e.config.dynamicModel.eventNames]}),e.config.experimental!==void 0&&(n.experimental={workflow:e.config.experimental.workflow===void 0?void 0:{world:e.config.experimental.workflow.world}}),e.config.outputSchema!==void 0&&(n.outputSchema=e.config.outputSchema),e.config.reasoning!==void 0&&(n.reasoning=e.config.reasoning),e.config.source!==void 0&&(n.source=createResolvedModuleSourceRef(e.config.source)),e.config.limits!==void 0&&(n.limits={maxInputTokensPerSession:e.config.limits.maxInputTokensPerSession,maxOutputTokensPerSession:e.config.limits.maxOutputTokensPerSession,sessionTimeoutMs:e.config.limits.sessionTimeoutMs}),n}export{ResolveAgentError,resolveAgent};
@@ -3,7 +3,7 @@ import type { CompiledChannel } from "#channel/compiled-channel.js";
3
3
  import type { NormalizedChannelCorsOptions } from "#channel/cors.js";
4
4
  import type { HeadersValue } from "#client/types.js";
5
5
  import type { DiscoverDiagnosticsSummary } from "#discover/diagnostics.js";
6
- import type { HandleMessageStreamEvent } from "#protocol/message.js";
6
+ import type { MessageStreamEvent } from "#protocol/message.js";
7
7
  import type { ChannelRouteMethod, RouteContext } from "#public/definitions/channel.js";
8
8
  import type { RouteHandler, WebSocketRouteHandler } from "#channel/routes.js";
9
9
  import type { OutboundAuthFn } from "#public/agents/auth.js";
@@ -178,7 +178,7 @@ export interface ResolvedHookDefinition extends ResolvedModuleSourceRef {
178
178
  * wildcard if declared. Unknown keys are accepted at resolve time
179
179
  * and ignored at dispatch time.
180
180
  */
181
- readonly events: Readonly<Record<string, StreamEventHook<HandleMessageStreamEvent>>>;
181
+ readonly events: Readonly<Record<string, StreamEventHook<MessageStreamEvent>>>;
182
182
  }
183
183
  /**
184
184
  * Runtime-owned authored channel definition resolved from the compiled
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.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{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.38`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.27.12`,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){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.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{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.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{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.38`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.28.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){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.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__",
@@ -1,6 +1,6 @@
1
1
  export declare const WEB_APP_TEMPLATE_FILES: {
2
2
  readonly "agent/channels/eve.ts": 'import { eveChannel } from "eve/channels/eve";\nimport { localDev, placeholderAuth, vercelOidc } from "eve/channels/auth";\n\nexport default eveChannel({\n auth: [\n // Lets the eve TUI and your Vercel deployments reach the deployed agent.\n vercelOidc(),\n // Open on localhost for `eve dev` and the REPL; ignored in production.\n localDev(),\n // This placeholder will not allow browser requests in production.\n // Replace it with your app\'s auth provider, like Auth.js or Clerk,\n // or use none() for a public demo.\n placeholderAuth(),\n ],\n});\n';
3
- readonly "app/_components/agent-chat.tsx": '"use client";\n\nimport type { UserContent } from "ai";\nimport { Client, type HandleMessageStreamEvent } from "eve/client";\nimport { useEveAgent } from "eve/react";\nimport { AlertCircleIcon } from "lucide-react";\nimport { useCallback, useRef, useState } from "react";\nimport {\n Conversation,\n ConversationContent,\n ConversationScrollButton,\n} from "@/components/ai-elements/conversation";\nimport {\n PromptInput,\n type PromptInputMessage,\n PromptInputSubmit,\n PromptInputTextarea,\n} from "@/components/ai-elements/prompt-input";\nimport { cn } from "@/lib/utils";\nimport { AgentMessage } from "./agent-message";\n\nconst AGENT_NAME = "__EVE_INIT_APP_NAME__";\n\ntype AgentStatus = ReturnType<typeof useEveAgent>["status"];\ntype CancellationState = "idle" | "requested" | "cancelling";\n\ntype Cancellation = {\n requested: boolean;\n sentTurnId?: string;\n turnId?: string;\n};\n\nexport function AgentChat() {\n const [session] = useState(() =>\n new Client({ host: "", preserveCompletedSessions: true }).session(),\n );\n const cancellationRef = useRef<Cancellation>({ requested: false });\n const [cancellationError, setCancellationError] = useState<string>();\n const [cancellationState, setCancellationState] = useState<CancellationState>("idle");\n\n const cancelTurn = useCallback(\n (turnId: string) => {\n const cancellation = cancellationRef.current;\n if (!cancellation.requested || cancellation.sentTurnId === turnId) {\n return;\n }\n\n cancellation.sentTurnId = turnId;\n setCancellationState("cancelling");\n\n void session.cancel({ turnId }).catch((error: unknown) => {\n if (cancellationRef.current !== cancellation) {\n return;\n }\n\n cancellation.requested = false;\n cancellation.sentTurnId = undefined;\n setCancellationError(toErrorMessage(error));\n setCancellationState("idle");\n });\n },\n [session],\n );\n\n const handleEvent = useCallback(\n (event: HandleMessageStreamEvent) => {\n if (event.type !== "turn.started") {\n return;\n }\n\n const cancellation = cancellationRef.current;\n cancellation.turnId = event.data.turnId;\n cancelTurn(event.data.turnId);\n },\n [cancelTurn],\n );\n\n const agent = useEveAgent({ onEvent: handleEvent, session });\n const isBusy = agent.status === "submitted" || agent.status === "streaming";\n const isEmpty = agent.data.messages.length === 0;\n const errorMessage = cancellationError ?? agent.error?.message;\n const submitStatus = isBusy && cancellationState !== "idle" ? "submitted" : agent.status;\n\n const prepareTurn = () => {\n cancellationRef.current = { requested: false };\n setCancellationError(undefined);\n setCancellationState("idle");\n };\n\n const requestCancellation = () => {\n if (!isBusy || cancellationState !== "idle") {\n return;\n }\n\n const cancellation = cancellationRef.current;\n cancellation.requested = true;\n setCancellationError(undefined);\n setCancellationState("requested");\n\n if (cancellation.turnId !== undefined) {\n cancelTurn(cancellation.turnId);\n }\n };\n\n const handleSubmit = async (message: PromptInputMessage) => {\n const text = message.text.trim();\n if ((text.length === 0 && message.files.length === 0) || isBusy) return;\n\n prepareTurn();\n\n if (message.files.length === 0) {\n await agent.send({ message: text });\n return;\n }\n\n const parts: UserContent = [];\n if (text.length > 0) {\n parts.push({ text, type: "text" });\n }\n for (const file of message.files) {\n parts.push({\n data: file.url,\n filename: file.filename,\n mediaType: file.mediaType,\n type: "file",\n });\n }\n\n await agent.send({ message: parts });\n };\n\n const composer = (\n <PromptInput onSubmit={handleSubmit}>\n <PromptInputTextarea placeholder="Send a message…" />\n <PromptInputSubmit onStop={requestCancellation} status={submitStatus} />\n </PromptInput>\n );\n\n return (\n <main className="flex h-dvh flex-col overflow-hidden bg-background text-foreground">\n {isEmpty ? null : (\n <header className="flex h-14 shrink-0 items-center justify-center gap-3 pl-4 pr-2">\n <span className="flex min-w-0 items-center gap-2">\n <span className="truncate text-muted-foreground text-sm">{AGENT_NAME}</span>\n <StatusDot status={agent.status} />\n </span>\n </header>\n )}\n\n {errorMessage ? (\n <div className="mx-auto w-full max-w-3xl shrink-0 px-4 pt-2 sm:px-6">\n <div className="flex items-start gap-3 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2.5 text-sm">\n <AlertCircleIcon className="mt-0.5 size-4 shrink-0 text-destructive" />\n <div>\n <p className="font-medium">Request failed</p>\n <p className="mt-0.5 text-muted-foreground">{errorMessage}</p>\n </div>\n </div>\n </div>\n ) : null}\n\n {isEmpty ? null : (\n <Conversation className="min-h-0 flex-1">\n <ConversationContent className="mx-auto w-full max-w-3xl gap-6 px-4 py-6 sm:px-6">\n {agent.data.messages.map((message, index) => (\n <AgentMessage\n canRespond={!isBusy}\n isStreaming={\n agent.status === "streaming" && index === agent.data.messages.length - 1\n }\n key={message.id}\n message={message}\n onInputResponses={(inputResponses) => {\n prepareTurn();\n return agent.send({ inputResponses });\n }}\n />\n ))}\n </ConversationContent>\n <ConversationScrollButton />\n </Conversation>\n )}\n\n <div\n className={cn(\n "mx-auto w-full px-4 sm:px-6",\n isEmpty\n ? "flex max-w-xl flex-1 flex-col items-center justify-center gap-8 pb-[10vh]"\n : "max-w-3xl shrink-0 pb-6",\n )}\n >\n {isEmpty ? (\n <div className="flex flex-col items-center gap-3 text-center">\n <h1 className="font-medium text-5xl tracking-tighter">{AGENT_NAME}</h1>\n </div>\n ) : null}\n <div className="w-full">{composer}</div>\n </div>\n </main>\n );\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : "Unable to cancel the response.";\n}\n\nfunction StatusDot({ status }: { readonly status: AgentStatus }) {\n const isLive = status === "submitted" || status === "streaming";\n const tone =\n status === "error"\n ? "bg-destructive"\n : isLive\n ? "bg-emerald-500"\n : status === "ready"\n ? "bg-muted-foreground"\n : "bg-muted-foreground/50";\n\n return (\n <span className="relative flex size-1">\n {isLive ? (\n <span\n className={cn(\n "absolute inline-flex size-full animate-ping rounded-full opacity-75",\n tone,\n )}\n />\n ) : null}\n <span className={cn("relative inline-flex size-1 rounded-full transition-colors", tone)} />\n </span>\n );\n}\n';
3
+ readonly "app/_components/agent-chat.tsx": '"use client";\n\nimport type { UserContent } from "ai";\nimport { Client, type MessageStreamEvent } from "eve/client";\nimport { useEveAgent } from "eve/react";\nimport { AlertCircleIcon } from "lucide-react";\nimport { useCallback, useRef, useState } from "react";\nimport {\n Conversation,\n ConversationContent,\n ConversationScrollButton,\n} from "@/components/ai-elements/conversation";\nimport {\n PromptInput,\n type PromptInputMessage,\n PromptInputSubmit,\n PromptInputTextarea,\n} from "@/components/ai-elements/prompt-input";\nimport { cn } from "@/lib/utils";\nimport { AgentMessage } from "./agent-message";\n\nconst AGENT_NAME = "__EVE_INIT_APP_NAME__";\n\ntype AgentStatus = ReturnType<typeof useEveAgent>["status"];\ntype CancellationState = "idle" | "requested" | "cancelling";\n\ntype Cancellation = {\n requested: boolean;\n sentTurnId?: string;\n turnId?: string;\n};\n\nexport function AgentChat() {\n const [session] = useState(() =>\n new Client({ host: "", preserveCompletedSessions: true }).session(),\n );\n const cancellationRef = useRef<Cancellation>({ requested: false });\n const [cancellationError, setCancellationError] = useState<string>();\n const [cancellationState, setCancellationState] = useState<CancellationState>("idle");\n\n const cancelTurn = useCallback(\n (turnId: string) => {\n const cancellation = cancellationRef.current;\n if (!cancellation.requested || cancellation.sentTurnId === turnId) {\n return;\n }\n\n cancellation.sentTurnId = turnId;\n setCancellationState("cancelling");\n\n void session.cancel({ turnId }).catch((error: unknown) => {\n if (cancellationRef.current !== cancellation) {\n return;\n }\n\n cancellation.requested = false;\n cancellation.sentTurnId = undefined;\n setCancellationError(toErrorMessage(error));\n setCancellationState("idle");\n });\n },\n [session],\n );\n\n const handleEvent = useCallback(\n (event: MessageStreamEvent) => {\n if (event.type !== "turn.started") {\n return;\n }\n\n const cancellation = cancellationRef.current;\n cancellation.turnId = event.data.turnId;\n cancelTurn(event.data.turnId);\n },\n [cancelTurn],\n );\n\n const agent = useEveAgent({ onEvent: handleEvent, session });\n const isBusy = agent.status === "submitted" || agent.status === "streaming";\n const isEmpty = agent.data.messages.length === 0;\n const errorMessage = cancellationError ?? agent.error?.message;\n const submitStatus = isBusy && cancellationState !== "idle" ? "submitted" : agent.status;\n\n const prepareTurn = () => {\n cancellationRef.current = { requested: false };\n setCancellationError(undefined);\n setCancellationState("idle");\n };\n\n const requestCancellation = () => {\n if (!isBusy || cancellationState !== "idle") {\n return;\n }\n\n const cancellation = cancellationRef.current;\n cancellation.requested = true;\n setCancellationError(undefined);\n setCancellationState("requested");\n\n if (cancellation.turnId !== undefined) {\n cancelTurn(cancellation.turnId);\n }\n };\n\n const handleSubmit = async (message: PromptInputMessage) => {\n const text = message.text.trim();\n if ((text.length === 0 && message.files.length === 0) || isBusy) return;\n\n prepareTurn();\n\n if (message.files.length === 0) {\n await agent.send({ message: text });\n return;\n }\n\n const parts: UserContent = [];\n if (text.length > 0) {\n parts.push({ text, type: "text" });\n }\n for (const file of message.files) {\n parts.push({\n data: file.url,\n filename: file.filename,\n mediaType: file.mediaType,\n type: "file",\n });\n }\n\n await agent.send({ message: parts });\n };\n\n const composer = (\n <PromptInput onSubmit={handleSubmit}>\n <PromptInputTextarea placeholder="Send a message…" />\n <PromptInputSubmit onStop={requestCancellation} status={submitStatus} />\n </PromptInput>\n );\n\n return (\n <main className="flex h-dvh flex-col overflow-hidden bg-background text-foreground">\n {isEmpty ? null : (\n <header className="flex h-14 shrink-0 items-center justify-center gap-3 pl-4 pr-2">\n <span className="flex min-w-0 items-center gap-2">\n <span className="truncate text-muted-foreground text-sm">{AGENT_NAME}</span>\n <StatusDot status={agent.status} />\n </span>\n </header>\n )}\n\n {errorMessage ? (\n <div className="mx-auto w-full max-w-3xl shrink-0 px-4 pt-2 sm:px-6">\n <div className="flex items-start gap-3 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2.5 text-sm">\n <AlertCircleIcon className="mt-0.5 size-4 shrink-0 text-destructive" />\n <div>\n <p className="font-medium">Request failed</p>\n <p className="mt-0.5 text-muted-foreground">{errorMessage}</p>\n </div>\n </div>\n </div>\n ) : null}\n\n {isEmpty ? null : (\n <Conversation className="min-h-0 flex-1">\n <ConversationContent className="mx-auto w-full max-w-3xl gap-6 px-4 py-6 sm:px-6">\n {agent.data.messages.map((message, index) => (\n <AgentMessage\n canRespond={!isBusy}\n isStreaming={\n agent.status === "streaming" && index === agent.data.messages.length - 1\n }\n key={message.id}\n message={message}\n onInputResponses={(inputResponses) => {\n prepareTurn();\n return agent.send({ inputResponses });\n }}\n />\n ))}\n </ConversationContent>\n <ConversationScrollButton />\n </Conversation>\n )}\n\n <div\n className={cn(\n "mx-auto w-full px-4 sm:px-6",\n isEmpty\n ? "flex max-w-xl flex-1 flex-col items-center justify-center gap-8 pb-[10vh]"\n : "max-w-3xl shrink-0 pb-6",\n )}\n >\n {isEmpty ? (\n <div className="flex flex-col items-center gap-3 text-center">\n <h1 className="font-medium text-5xl tracking-tighter">{AGENT_NAME}</h1>\n </div>\n ) : null}\n <div className="w-full">{composer}</div>\n </div>\n </main>\n );\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : "Unable to cancel the response.";\n}\n\nfunction StatusDot({ status }: { readonly status: AgentStatus }) {\n const isLive = status === "submitted" || status === "streaming";\n const tone =\n status === "error"\n ? "bg-destructive"\n : isLive\n ? "bg-emerald-500"\n : status === "ready"\n ? "bg-muted-foreground"\n : "bg-muted-foreground/50";\n\n return (\n <span className="relative flex size-1">\n {isLive ? (\n <span\n className={cn(\n "absolute inline-flex size-full animate-ping rounded-full opacity-75",\n tone,\n )}\n />\n ) : null}\n <span className={cn("relative inline-flex size-1 rounded-full transition-colors", tone)} />\n </span>\n );\n}\n';
4
4
  readonly "app/_components/agent-message.tsx": '"use client";\n\nimport type {\n EveAuthorizationPart,\n EveDynamicToolPart,\n EveMessage,\n EveMessagePart,\n} from "eve/react";\nimport {\n CheckCircleIcon,\n ExternalLinkIcon,\n FileIcon,\n ImageIcon,\n KeyRoundIcon,\n XCircleIcon,\n} from "lucide-react";\nimport { Message, MessageContent, MessageResponse } from "@/components/ai-elements/message";\nimport { Reasoning, ReasoningContent, ReasoningTrigger } from "@/components/ai-elements/reasoning";\nimport {\n Tool,\n ToolContent,\n ToolHeader,\n ToolInput,\n ToolOutput,\n} from "@/components/ai-elements/tool";\nimport { Button } from "@/components/ui/button";\nimport { cn } from "@/lib/utils";\n\nexport type AgentInputResponse = {\n readonly optionId?: string;\n readonly requestId: string;\n readonly text?: string;\n};\n\ntype EveFilePart = Extract<EveMessagePart, { type: "file" }>;\n\nexport function AgentMessage({\n canRespond,\n isStreaming,\n message,\n onInputResponses,\n}: {\n readonly canRespond: boolean;\n readonly isStreaming: boolean;\n readonly message: EveMessage;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n}) {\n const lastTextIndex = message.parts.reduce(\n (last, part, index) => (part.type === "text" ? index : last),\n -1,\n );\n\n return (\n <Message\n data-optimistic={message.metadata?.optimistic ? "true" : undefined}\n from={message.role}\n >\n <MessageContent>\n {message.parts.map((part, index) => (\n <AgentMessagePart\n canRespond={canRespond}\n key={partKey(part, index)}\n onInputResponses={onInputResponses}\n part={part}\n showCaret={isStreaming && message.role === "assistant" && index === lastTextIndex}\n />\n ))}\n </MessageContent>\n </Message>\n );\n}\n\nfunction AgentMessagePart({\n canRespond,\n onInputResponses,\n part,\n showCaret,\n}: {\n readonly canRespond: boolean;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n readonly part: EveMessagePart;\n readonly showCaret: boolean;\n}) {\n switch (part.type) {\n case "step-start":\n return null;\n case "text":\n return (\n <MessageResponse caret="block" isAnimating={showCaret}>\n {part.text}\n </MessageResponse>\n );\n case "reasoning":\n return (\n <Reasoning defaultOpen isStreaming={part.state === "streaming"}>\n <ReasoningTrigger />\n <ReasoningContent>{part.text}</ReasoningContent>\n </Reasoning>\n );\n case "file":\n return <AttachmentPart part={part} />;\n case "authorization":\n return <AuthorizationPrompt part={part} />;\n case "dynamic-tool":\n return (\n <Tool\n defaultOpen={part.state === "approval-requested" || part.state === "approval-responded"}\n >\n <ToolHeader\n state={part.state}\n title={part.toolName}\n toolName={part.toolName}\n type="dynamic-tool"\n />\n <ToolContent>\n <ToolInput input={part.input} />\n <InputRequestActions\n canRespond={canRespond}\n part={part}\n onInputResponses={onInputResponses}\n />\n <ToolOutput errorText={part.errorText} output={part.output} />\n </ToolContent>\n </Tool>\n );\n }\n}\n\nfunction AttachmentPart({ part }: { readonly part: EveFilePart }) {\n const label = part.filename ?? "Attachment";\n const detail = [part.mediaType, formatBytes(part.size)].filter(Boolean).join(" - ");\n const isImage = part.mediaType.startsWith("image/") && part.url !== undefined;\n const Icon = isImage ? ImageIcon : FileIcon;\n const body = (\n <span className="flex max-w-sm items-center gap-3 rounded-md border bg-background/60 p-2 text-sm">\n {isImage ? (\n <img alt={label} className="size-12 shrink-0 rounded-sm object-cover" src={part.url} />\n ) : (\n <span className="flex size-10 shrink-0 items-center justify-center rounded-sm bg-muted text-muted-foreground">\n <Icon className="size-4" />\n </span>\n )}\n <span className="min-w-0 flex-1">\n <span className="block truncate font-medium">{label}</span>\n {detail ? <span className="block truncate text-muted-foreground">{detail}</span> : null}\n </span>\n {part.url ? <ExternalLinkIcon className="size-4 shrink-0 text-muted-foreground" /> : null}\n </span>\n );\n\n return part.url ? (\n <a href={part.url} rel="noreferrer" target="_blank">\n {body}\n </a>\n ) : (\n body\n );\n}\n\nfunction AuthorizationPrompt({ part }: { readonly part: EveAuthorizationPart }) {\n const isAuthorized = part.state === "completed" && part.outcome === "authorized";\n const isCompleted = part.state === "completed";\n const Icon = isAuthorized ? CheckCircleIcon : isCompleted ? XCircleIcon : KeyRoundIcon;\n const instructions = part.authorization?.instructions;\n const shouldShowInstructions = instructions !== undefined && instructions !== part.description;\n\n return (\n <div\n className={cn(\n "space-y-3 rounded-md border p-3",\n isAuthorized\n ? "border-emerald-500/30 bg-emerald-500/5"\n : isCompleted\n ? "border-destructive/30 bg-destructive/5"\n : "border-blue-500/30 bg-blue-500/5",\n )}\n >\n <div className="flex items-start gap-3">\n <span\n className={cn(\n "mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-full",\n isAuthorized\n ? "bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"\n : isCompleted\n ? "bg-destructive/10 text-destructive"\n : "bg-blue-500/10 text-blue-700 dark:text-blue-300",\n )}\n >\n <Icon className="size-4" />\n </span>\n <div className="min-w-0 flex-1 space-y-2">\n <p className="font-medium text-sm">{authorizationTitle(part)}</p>\n <p className="text-muted-foreground text-sm">{authorizationDescription(part)}</p>\n {shouldShowInstructions ? (\n <p className="text-muted-foreground text-sm">{instructions}</p>\n ) : null}\n {part.state === "required" && part.authorization?.userCode ? (\n <div className="flex flex-wrap items-center gap-2 text-sm">\n <span className="text-muted-foreground">Code</span>\n <code className="rounded-md bg-background px-2 py-1 font-mono">\n {part.authorization.userCode}\n </code>\n </div>\n ) : null}\n {part.state === "required" && part.authorization?.url ? (\n <Button asChild size="sm">\n <a href={part.authorization.url} rel="noreferrer" target="_blank">\n <ExternalLinkIcon className="size-4" />\n Sign in with {part.displayName}\n </a>\n </Button>\n ) : null}\n </div>\n </div>\n </div>\n );\n}\n\nfunction authorizationTitle(part: EveAuthorizationPart): string {\n if (part.state === "required") {\n return `Connect ${part.displayName}`;\n }\n if (part.outcome === "authorized") {\n return `${part.displayName} connected`;\n }\n return `${part.displayName} authorization ${formatAuthorizationOutcome(part.outcome)}`;\n}\n\nfunction authorizationDescription(part: EveAuthorizationPart): string {\n if (part.state === "required") {\n return part.description;\n }\n if (part.outcome === "authorized") {\n return `${part.displayName} connected.`;\n }\n const tail = part.reason !== undefined ? ` (${part.reason})` : "";\n return `${part.displayName} authorization ${formatAuthorizationOutcome(part.outcome)}${tail}.`;\n}\n\nfunction formatAuthorizationOutcome(outcome: NonNullable<EveAuthorizationPart["outcome"]>): string {\n switch (outcome) {\n case "authorized":\n return "authorized";\n case "declined":\n return "declined";\n case "failed":\n return "failed";\n case "timed-out":\n return "timed out";\n }\n}\n\nfunction formatBytes(size: number | undefined): string | undefined {\n if (size === undefined) {\n return undefined;\n }\n if (size < 1024) {\n return `${size} B`;\n }\n if (size < 1024 * 1024) {\n return `${(size / 1024).toFixed(1)} KB`;\n }\n return `${(size / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction InputRequestActions({\n canRespond,\n onInputResponses,\n part,\n}: {\n readonly canRespond: boolean;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n readonly part: EveDynamicToolPart;\n}) {\n const inputRequest = part.toolMetadata?.eve?.inputRequest;\n if (!inputRequest) {\n return null;\n }\n\n const inputResponse = part.toolMetadata?.eve?.inputResponse;\n const selectedOption = inputRequest.options?.find(\n (option) => option.id === inputResponse?.optionId,\n );\n\n return (\n <div className="space-y-3 rounded-md border border-yellow-500/30 bg-yellow-500/5 p-3">\n <p className="text-muted-foreground text-sm">{inputRequest.prompt}</p>\n {inputResponse ? (\n <p className="font-medium text-sm">\n Responded: {selectedOption?.label ?? inputResponse.text ?? inputResponse.optionId}\n </p>\n ) : (\n <div className="flex flex-wrap gap-2">\n {inputRequest.options?.map((option) => (\n <Button\n disabled={!canRespond}\n key={option.id}\n onClick={() => {\n void onInputResponses([\n {\n optionId: option.id,\n requestId: inputRequest.requestId,\n },\n ]);\n }}\n size="sm"\n type="button"\n variant={option.style === "danger" ? "destructive" : "default"}\n >\n {option.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction partKey(part: EveMessagePart, index: number): string {\n switch (part.type) {\n case "authorization":\n return `authorization:${part.turnId}:${part.stepIndex}:${part.name}`;\n case "dynamic-tool":\n return part.toolCallId;\n default:\n return `${part.type}:${index}`;\n }\n}\n';
5
5
  readonly "app/globals.css": '@import "tailwindcss";\n@source "../node_modules/streamdown/dist/*.js";\n\n@theme inline {\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n --font-sans: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif;\n --font-mono: "Geist Mono", "Geist Mono Fallback", ui-monospace, monospace;\n}\n\n:root {\n color-scheme: light;\n /* Soft neutral page with white elevated surfaces so cards/composer pop. */\n --background: oklch(0.971 0 0);\n --foreground: oklch(0.16 0 0);\n --card: oklch(1 0 0);\n --card-foreground: oklch(0.16 0 0);\n --popover: oklch(1 0 0);\n --popover-foreground: oklch(0.16 0 0);\n --primary: oklch(0.19 0 0);\n --primary-foreground: oklch(0.985 0 0);\n --secondary: oklch(0.94 0 0);\n --secondary-foreground: oklch(0.19 0 0);\n --muted: oklch(0.94 0 0);\n --muted-foreground: oklch(0.6 0 0);\n --accent: oklch(0.94 0 0);\n --accent-foreground: oklch(0.19 0 0);\n --destructive: oklch(0.577 0.245 27.325);\n --border: oklch(0.916 0 0);\n --input: oklch(0.916 0 0);\n --ring: oklch(0.708 0 0);\n --radius: 0.625rem;\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n color-scheme: dark;\n --background: oklch(0.145 0 0);\n --foreground: oklch(0.985 0 0);\n --card: oklch(0.205 0 0);\n --card-foreground: oklch(0.985 0 0);\n --popover: oklch(0.205 0 0);\n --popover-foreground: oklch(0.985 0 0);\n --primary: oklch(0.922 0 0);\n --primary-foreground: oklch(0.205 0 0);\n --secondary: oklch(0.269 0 0);\n --secondary-foreground: oklch(0.985 0 0);\n --muted: oklch(0.269 0 0);\n --muted-foreground: oklch(0.708 0 0);\n --accent: oklch(0.269 0 0);\n --accent-foreground: oklch(0.985 0 0);\n --destructive: oklch(0.704 0.191 22.216);\n --border: oklch(1 0 0 / 10%);\n --input: oklch(1 0 0 / 15%);\n --ring: oklch(0.556 0 0);\n }\n}\n\n* {\n border-color: var(--border);\n}\n\nhtml {\n height: 100%;\n}\n\nbody {\n min-height: 100%;\n margin: 0;\n background: var(--background);\n font-family: var(--font-sans);\n}\n\nbutton,\ninput,\ntextarea {\n font: inherit;\n}\n';
6
6
  readonly "app/layout.tsx": 'import type { Metadata } from "next";\nimport { Geist, Geist_Mono } from "next/font/google";\nimport type { ReactNode } from "react";\nimport { TooltipProvider } from "@/components/ui/tooltip";\nimport { cn } from "@/lib/utils";\nimport "./globals.css";\n\nconst sans = Geist({\n variable: "--font-sans",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nconst mono = Geist_Mono({\n variable: "--font-mono",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nexport const metadata: Metadata = {\n title: "__EVE_INIT_APP_NAME__",\n description: "A Next.js starter for eve agents with AI Elements.",\n};\n\nexport default function RootLayout({ children }: { readonly children: ReactNode }) {\n return (\n <html className={cn(sans.variable, mono.variable)} lang="en">\n <body>\n <TooltipProvider>{children}</TooltipProvider>\n </body>\n </html>\n );\n}\n';
@@ -16,7 +16,7 @@ export default eveChannel({
16
16
  `,"app/_components/agent-chat.tsx":`"use client";
17
17
 
18
18
  import type { UserContent } from "ai";
19
- import { Client, type HandleMessageStreamEvent } from "eve/client";
19
+ import { Client, type MessageStreamEvent } from "eve/client";
20
20
  import { useEveAgent } from "eve/react";
21
21
  import { AlertCircleIcon } from "lucide-react";
22
22
  import { useCallback, useRef, useState } from "react";
@@ -78,7 +78,7 @@ export function AgentChat() {
78
78
  );
79
79
 
80
80
  const handleEvent = useCallback(
81
- (event: HandleMessageStreamEvent) => {
81
+ (event: MessageStreamEvent) => {
82
82
  if (event.type !== "turn.started") {
83
83
  return;
84
84
  }
@@ -119,6 +119,18 @@ export interface PublicAgentCompactionDefinition {
119
119
  * Configures framework-owned runtime limits for this agent's runs.
120
120
  */
121
121
  export interface AgentLimitsDefinition {
122
+ /**
123
+ * Maximum lifetime of one durable session, in milliseconds.
124
+ *
125
+ * The deadline starts when the session is created and survives process
126
+ * restarts and redeployments. If it elapses during an active turn, eve lets
127
+ * that turn settle before completing the session normally.
128
+ *
129
+ * `false` disables the timeout.
130
+ *
131
+ * @default 2_592_000_000 (30 days)
132
+ */
133
+ readonly sessionTimeoutMs?: number | false;
122
134
  /**
123
135
  * Maximum provider-reported input tokens accumulated by one durable session.
124
136
  *