eve 0.80.1 → 0.81.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 (105) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/src/channel/channel-address.d.ts +1 -0
  3. package/dist/src/channel/channel-address.js +1 -1
  4. package/dist/src/channel/inactive-prompt.d.ts +46 -0
  5. package/dist/src/channel/inactive-prompt.js +1 -0
  6. package/dist/src/channel/principal-identity.d.ts +2 -0
  7. package/dist/src/channel/principal-identity.js +1 -1
  8. package/dist/src/channel/session-not-active-error.d.ts +16 -0
  9. package/dist/src/channel/session-not-active-error.js +1 -0
  10. package/dist/src/chunks/{use-eve-agent-Vsl-S0yI.js → use-eve-agent-Bp6nbhfV.js} +6 -0
  11. package/dist/src/chunks/{use-eve-agent-Ch-Q-s12.js → use-eve-agent-DLkjJIm3.js} +6 -0
  12. package/dist/src/compiled/.vendor-stamp.json +1 -1
  13. package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
  14. package/dist/src/compiler/extension-compatibility.d.ts +18 -18
  15. package/dist/src/compiler/extension-compatibility.js +1 -1
  16. package/dist/src/context/provider.d.ts +5 -0
  17. package/dist/src/context/providers/connection.js +1 -1
  18. package/dist/src/context/run-step.js +1 -1
  19. package/dist/src/eve-channel/support.js +1 -1
  20. package/dist/src/execution/agent-sessions/steps.js +1 -1
  21. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  22. package/dist/src/execution/sandbox/bindings/vercel-lookup.d.ts +6 -0
  23. package/dist/src/execution/sandbox/bindings/vercel-lookup.js +1 -1
  24. package/dist/src/execution/sandbox/bindings/vercel.js +2 -2
  25. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  26. package/dist/src/execution/workflow-runtime.js +1 -1
  27. package/dist/src/extensions/code/extension/extension.d.ts +2 -0
  28. package/dist/src/extensions/code/extension/extension.js +1 -1
  29. package/dist/src/extensions/git/extension/extension.d.ts +3 -0
  30. package/dist/src/extensions/git/extension/extension.js +1 -1
  31. package/dist/src/extensions/git/extension/lib/attribution.d.ts +22 -0
  32. package/dist/src/extensions/git/extension/lib/attribution.js +4 -0
  33. package/dist/src/extensions/git/extension/lib/gh-tool.js +1 -1
  34. package/dist/src/extensions/git/extension/lib/github-shell.d.ts +13 -1
  35. package/dist/src/extensions/git/extension/lib/github-shell.js +1 -1
  36. package/dist/src/extensions/git/extension/lib/sandbox.d.ts +1 -1
  37. package/dist/src/harness/authorization-event-fields.d.ts +3 -0
  38. package/dist/src/harness/authorization-event-fields.js +1 -1
  39. package/dist/src/harness/hitl/approvals.d.ts +9 -9
  40. package/dist/src/harness/hitl/approvals.js +1 -1
  41. package/dist/src/harness/hitl/approved-calls.d.ts +4 -4
  42. package/dist/src/harness/hitl/approved-calls.js +1 -1
  43. package/dist/src/harness/hitl/candidates.d.ts +7 -1
  44. package/dist/src/harness/hitl/candidates.js +1 -1
  45. package/dist/src/harness/hitl/coordinator.d.ts +2 -2
  46. package/dist/src/harness/hitl/coordinator.js +1 -1
  47. package/dist/src/harness/hitl/index.d.ts +2 -2
  48. package/dist/src/harness/hitl/index.js +1 -1
  49. package/dist/src/harness/hitl/intake.js +1 -1
  50. package/dist/src/harness/hitl/sign-ins.d.ts +10 -0
  51. package/dist/src/harness/hitl/sign-ins.js +1 -1
  52. package/dist/src/harness/inline-tool-authorization.d.ts +10 -11
  53. package/dist/src/harness/inline-tool-authorization.js +1 -1
  54. package/dist/src/harness/session-machine/current.d.ts +5 -0
  55. package/dist/src/harness/session-machine/current.js +1 -1
  56. package/dist/src/harness/session-machine/state.d.ts +15 -3
  57. package/dist/src/harness/session-machine/transitions.d.ts +23 -5
  58. package/dist/src/harness/session-machine/transitions.js +1 -1
  59. package/dist/src/harness/step/after-model.js +1 -1
  60. package/dist/src/internal/application/stamped-package-version.js +1 -1
  61. package/dist/src/internal/authored-definition/source-identity.js +1 -1
  62. package/dist/src/protocol/message.d.ts +30 -0
  63. package/dist/src/protocol/message.js +1 -1
  64. package/dist/src/protocol/session-projection.d.ts +8 -1
  65. package/dist/src/protocol/session-projection.js +1 -1
  66. package/dist/src/public/channels/auth.js +1 -1
  67. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +1 -1
  68. package/dist/src/public/channels/chat-sdk/input-actions.d.ts +5 -0
  69. package/dist/src/public/channels/chat-sdk/input-actions.js +2 -2
  70. package/dist/src/public/channels/discord/defaults.d.ts +6 -1
  71. package/dist/src/public/channels/discord/defaults.js +2 -2
  72. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  73. package/dist/src/public/channels/slack/approval-cards.js +2 -2
  74. package/dist/src/public/channels/slack/interaction-cards.d.ts +19 -6
  75. package/dist/src/public/channels/slack/interaction-cards.js +1 -1
  76. package/dist/src/public/channels/slack/interactions.js +1 -1
  77. package/dist/src/public/channels/teams/hitl.d.ts +7 -0
  78. package/dist/src/public/channels/teams/hitl.js +1 -1
  79. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  80. package/dist/src/public/channels/telegram/hitl.d.ts +2 -0
  81. package/dist/src/public/channels/telegram/hitl.js +2 -2
  82. package/dist/src/public/channels/telegram/inbound.d.ts +2 -0
  83. package/dist/src/public/channels/telegram/inbound.js +1 -1
  84. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  85. package/dist/src/public/definitions/channel.js +1 -1
  86. package/dist/src/runtime/connections/mcp-client.d.ts +1 -1
  87. package/dist/src/runtime/connections/mcp-client.js +1 -1
  88. package/dist/src/runtime/connections/registry-types.d.ts +4 -1
  89. package/dist/src/runtime/connections/registry.d.ts +3 -2
  90. package/dist/src/runtime/connections/scoped-authorization.js +1 -1
  91. package/dist/src/setup/scaffold/create/project.js +1 -1
  92. package/dist/src/svelte/index.js +1 -1
  93. package/dist/src/svelte/use-eve-agent.js +1 -1
  94. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  95. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  96. package/dist/src/vue/index.js +1 -1
  97. package/dist/src/vue/use-eve-agent.js +1 -1
  98. package/docs/channels/slack.mdx +2 -0
  99. package/docs/channels/teams.mdx +1 -1
  100. package/docs/channels/telegram.mdx +1 -1
  101. package/docs/code-extension.mdx +20 -6
  102. package/docs/connections/mcp.mdx +4 -0
  103. package/docs/connections/overview.mdx +2 -2
  104. package/docs/evals/assertions.mdx +21 -0
  105. package/package.json +1 -1
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-Ch-Q-s12.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-DLkjJIm3.js";
2
2
 
3
3
  export { useEveAgent };
@@ -1 +1 @@
1
- async function executeAskQuestionTool(e,t){"use workflow";return toAskQuestionOutput(await t.ask(toAskQuestionRequest(e)))}function toAskQuestionRequest(e){let t=e.options?.map(e=>({description:e.description,id:e.label,label:e.label}));return{allowFreeform:!0,display:t===void 0?`text`:`select`,prompt:e.question,...t!==void 0&&{options:t}}}function toAskQuestionOutput(e){switch(e.status){case`answered`:return{answer:e.optionId??e.text??``,status:`answered`};case`cancelled`:return{interrupted:!0};case`unavailable`:return{status:`unavailable`}}}executeAskQuestionTool.workflowId=`workflow//eve@0.80.1//executeAskQuestionTool`;export{executeAskQuestionTool,toAskQuestionOutput,toAskQuestionRequest};
1
+ async function executeAskQuestionTool(e,t){"use workflow";return toAskQuestionOutput(await t.ask(toAskQuestionRequest(e)))}function toAskQuestionRequest(e){let t=e.options?.map(e=>({description:e.description,id:e.label,label:e.label}));return{allowFreeform:!0,display:t===void 0?`text`:`select`,prompt:e.question,...t!==void 0&&{options:t}}}function toAskQuestionOutput(e){switch(e.status){case`answered`:return{answer:e.optionId??e.text??``,status:`answered`};case`cancelled`:return{interrupted:!0};case`unavailable`:return{status:`unavailable`}}}executeAskQuestionTool.workflowId=`workflow//eve@0.81.0//executeAskQuestionTool`;export{executeAskQuestionTool,toAskQuestionOutput,toAskQuestionRequest};
@@ -1 +1 @@
1
- import{sleep}from"#compiled/@workflow/core/index.js";async function executeSleepTool(e,t){"use workflow";if(t.abortSignal.aborted)return{interrupted:!0};let n=new Promise(e=>t.abortSignal.addEventListener(`abort`,()=>e(`interrupted`),{once:!0})),r=sleep(Math.ceil(e.seconds*1e3)).then(()=>`elapsed`);return await Promise.race([r,n])===`elapsed`?{waitedSeconds:e.seconds}:{interrupted:!0}}executeSleepTool.workflowId=`workflow//eve@0.80.1//executeSleepTool`;export{executeSleepTool};
1
+ import{sleep}from"#compiled/@workflow/core/index.js";async function executeSleepTool(e,t){"use workflow";if(t.abortSignal.aborted)return{interrupted:!0};let n=new Promise(e=>t.abortSignal.addEventListener(`abort`,()=>e(`interrupted`),{once:!0})),r=sleep(Math.ceil(e.seconds*1e3)).then(()=>`elapsed`);return await Promise.race([r,n])===`elapsed`?{waitedSeconds:e.seconds}:{interrupted:!0}}executeSleepTool.workflowId=`workflow//eve@0.81.0//executeSleepTool`;export{executeSleepTool};
@@ -1,4 +1,4 @@
1
- import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-Vsl-S0yI.js";
1
+ import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-Bp6nbhfV.js";
2
2
 
3
3
  //#region src/client/tool-call-state.ts
4
4
  function toolCallState(conversation, callId, options = {}) {
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-Vsl-S0yI.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-Bp6nbhfV.js";
2
2
 
3
3
  export { useEveAgent };
@@ -645,6 +645,8 @@ The callback receives the `InputRequest` and current `SessionContext`, so it can
645
645
 
646
646
  When a tool approval resolves, eve retires the messages it posted for it. The card loses its buttons and shows the answer and who gave it, the separate tool-input post is deleted, and a direct-message request's `Waiting on approval` note in the thread changes to the outcome. This also happens when the approval ends without a click, for example when the person replies in the thread instead, in which case the card reads `No longer needed`.
647
647
 
648
+ A click on any request whose session is no longer active, for example because its run was cancelled outside eve, can never be answered. eve removes the card's buttons, marks it `No longer active`, and tells the person who clicked, in an ephemeral message, to send a new message.
649
+
648
650
  A renderer's `input.requested` handler can extend delivery and then hand the requests on to eve with `next()`. For example, an application can add non-sensitive context to the Slack thread before eve renders the actionable controls. The configured `approvalChannel` still sends sensitive reviews to a DM and keeps ordinary requests in the thread:
649
651
 
650
652
  ```ts title="agent/channels/slack.ts"
@@ -85,7 +85,7 @@ A human-in-the-loop (HITL) `input.requested` event renders as an Adaptive Card.
85
85
 
86
86
  By default, submissions use the Teams identity of the user who clicked the card. If you customize `onMessage` for an allowlist, configure the same policy in `onInputResponse`; eve otherwise rejects HITL submissions rather than bypassing the message gate.
87
87
 
88
- When a tool approval settles, eve replaces its Adaptive Card with the outcome and responder name. A response rejected by an approval policy leaves the shared card unchanged.
88
+ When a tool approval settles, eve replaces its Adaptive Card with the outcome and responder name. A response rejected by an approval policy leaves the shared card unchanged. A submission to a card whose session is no longer active, for example because its run was cancelled outside eve, replaces the card with its prompt and `No longer active`, and the invoke response tells the person who submitted to send a new message.
89
89
 
90
90
  ### Connection sign-ins
91
91
 
@@ -49,7 +49,7 @@ The default `message.completed` handler sends plain text via `sendMessage`. It p
49
49
 
50
50
  ### Human-in-the-loop (HITL)
51
51
 
52
- Human-in-the-loop (HITL) turns option requests into inline-keyboard buttons and freeform requests into `ForceReply`. Telegram caps `callback_data` at 64 bytes, so eve keeps compact callback ids in channel state instead. It acknowledges its own callbacks with `answerCallbackQuery`; anything it doesn't recognize goes to `onCallbackQuery`.
52
+ Human-in-the-loop (HITL) turns option requests into inline-keyboard buttons and freeform requests into `ForceReply`. Telegram caps `callback_data` at 64 bytes, so eve keeps compact callback ids in channel state instead. It acknowledges its own callbacks with `answerCallbackQuery`; anything it doesn't recognize goes to `onCallbackQuery`. A press on a prompt whose session is no longer active replaces the keyboard with `No longer active`, and the acknowledgement tells the person to send a new message.
53
53
 
54
54
  A text reply to a bot message is sent as a normal message, with the replied-to message id in `state.replyToBotMessageId`. When that id matches a pending `ForceReply` prompt, the channel's `deliver` hook turns the reply into the answer. Otherwise the reply reaches the agent as a message, and starts a new session when none owns the thread.
55
55
 
@@ -98,12 +98,13 @@ export default git({});
98
98
 
99
99
  Configure `github` to broker GitHub access through Connect instead. The extension then adds the authenticated `git__gh` tool, tells the agent to use it for every authenticated GitHub operation, and switches `git__pr` to `gh-signed-commit` for repositories that require verified signatures.
100
100
 
101
- | Option | Required | Effect |
102
- | ------------------ | ------------- | ------------------------------------------------------------------------------------------ |
103
- | `github.connector` | With `github` | Connector that mints a GitHub token |
104
- | `github.org` | With `github` | Organization whose repositories the `gh` tool can access |
105
- | `github.broker` | With `github` | `broker(sandbox, rules)` callback that installs, then removes, the GitHub credential rules |
106
- | `github.authorize` | No | `authorize({ auth, repository, token })` callback that allows or denies each `gh` tool invocation |
101
+ | Option | Required | Effect |
102
+ | -------------------- | ------------- | ------------------------------------------------------------------------------------------------- |
103
+ | `github.connector` | With `github` | Connector that mints a GitHub token |
104
+ | `github.org` | With `github` | Organization whose repositories the `gh` tool can access |
105
+ | `github.broker` | With `github` | `broker(sandbox, rules)` callback that installs, then removes, the GitHub credential rules |
106
+ | `github.authorize` | No | `authorize({ auth, repository, token })` callback that allows or denies each `gh` tool invocation |
107
+ | `github.attribution` | No | `attribution(ctx)` callback that returns the `{ name, email }` co-author for this turn |
107
108
 
108
109
  The `gh` tool requests a token scoped to exactly one repository in `github.org` for each invocation. The sandbox process receives a placeholder `GH_TOKEN`, and the firewall exchanges it on matching GitHub requests. Your `github.broker` callback receives the header-transform rules for the command, then `null` to remove the lease. The callback must preserve your other network rules. GitHub authentication has no command-delivery option.
109
110
 
@@ -134,6 +135,19 @@ export default git({
134
135
  });
135
136
  ```
136
137
 
138
+ Commits made by the `gh` tool are authored by the GitHub App. To credit the person a turn works for, return them from `github.attribution`. The callback receives the tool's context, so it can read the verified caller from `ctx.session.auth.current` or resolve their linked accounts with `ctx.getToken`. The `gh` tool then ends every `gh-signed-commit` message, and every `gh pr create` body passed with `--body` or `--body-file`, with `Co-authored-by: <name> <email>`. Return `null` to publish without a co-author. `Co-authored-by` lines the agent writes itself are kept, and the trailer joins their block so they still count. Pull requests created without a body flag, such as with `--fill` or `--template`, and other paths, such as `gh api`, are not attributed.
139
+
140
+ ```ts
141
+ git({
142
+ github: {
143
+ connector: "github",
144
+ org: "acme",
145
+ broker,
146
+ attribution: (ctx) => coAuthorFor(ctx.session.auth.current),
147
+ },
148
+ });
149
+ ```
150
+
137
151
  ### Migrate from `code({ github })`
138
152
 
139
153
  `code({ github })` is deprecated. While it is set, the code extension still contributes `code__gh`, its GitHub instructions, and the signed-commit `code__pr` skill. Without it, the code extension contributes no GitHub tool, instructions, or pull request skill. Move the `github` option to `git({ github })`, and import `gh` and the GitHub sandbox helpers from `eve/extensions/git/tools` and `eve/extensions/git/sandbox`.
@@ -53,6 +53,10 @@ eve asks the user to sign in only when the MCP server asks for it. When a connec
53
53
 
54
54
  After the user signs in, the turn resumes and the model makes the call again. eve reconnects with the token and reloads the tool list, which may now include tools the server hides from anonymous callers. A connection that already has a token sends it on every request, as before.
55
55
 
56
+ eve resolves credentials before each MCP HTTP request, including requests on an existing client. When the cached token's `expiresAt` has passed, eve calls the token provider again. If the server rejects a bearer with HTTP `401`, eve evicts the cached token, asks the provider for another token, and retries the request once before asking for sign-in.
57
+
58
+ Eviction clears eve's cached access token and calls the provider's optional `evict` hook. The provider controls whether it retains a refresh grant for silent renewal. Missing grants and rejected replacement tokens still use the normal authorization flow; HTTP `403` permission failures do not trigger token refresh or retries.
59
+
56
60
  A server that leaves protected tools out of its anonymous `tools/list` never triggers sign-in, because the model cannot find those tools. Servers that support anonymous use should list every tool and refuse the protected calls.
57
61
 
58
62
  ## Static tokens and headers
@@ -99,7 +99,7 @@ export default defineMcpClientConnection({
99
99
  });
100
100
  ```
101
101
 
102
- If the token has a known TTL, set `expiresAt` (milliseconds since epoch) and eve refreshes ahead of time rather than waiting for a `401`.
102
+ If the token has a known TTL, set `expiresAt` (milliseconds since epoch). Once it expires, eve calls `getToken` again before the next request, including requests on an existing MCP client.
103
103
 
104
104
  When `getToken` is the only auth, `credentialOwner` defaults to `"app"`: one shared credential keyed across all sessions. Set `credentialOwner: "user"` when each end-user carries their own token.
105
105
 
@@ -332,7 +332,7 @@ channels fall back to title-casing the connection name when neither is set.
332
332
  Two error classes drive the consent flow. Throw them from `getToken` or `completeAuthorization`; both are exported from `eve/connections`.
333
333
 
334
334
  - `ConnectionAuthorizationRequiredError(connectionName)`: the user must authorize. Throw it from `getToken` to emit `authorization.required` and kick off the flow.
335
- - `ConnectionAuthorizationFailedError(connectionName, { reason?, retryable? })`: authorization failed. `reason` is a stable machine-readable code (e.g. `"access_denied"`) that shows up on the `authorization.completed` event and the failed tool result. `retryable` defaults to `true`; set it to `false` for terminal cases like user denial so the runtime stops re-prompting.
335
+ - `ConnectionAuthorizationFailedError(connectionName, { reason?, retryable? })`: authorization failed. `reason` is a stable machine-readable code (e.g. `"access_denied"`) that shows up on the `authorization.completed` event and the failed tool result. `retryable` defaults to `true`; set it to `false` for terminal cases like user denial. The `authorization.completed` event then carries `retryable: false`, and a later tool call in the same turn that needs the same grant for the same principal fails with that failure instead of asking the user to sign in again. The next turn asks again.
336
336
 
337
337
  ```ts
338
338
  import { ConnectionAuthorizationFailedError } from "eve/connections";
@@ -187,6 +187,27 @@ t.eventsSatisfy("assistant reply includes the marker", (events) =>
187
187
  );
188
188
  ```
189
189
 
190
+ ### Assert and score reasoning
191
+
192
+ When the provider exposes reasoning, eve captures each completed block as a `reasoning.completed` event. Assert on its text with `turn.event(...)`, or join the blocks and pass them to a judge:
193
+
194
+ ```ts
195
+ turn.event("reasoning.completed", {
196
+ data: { reasoning: /checks? the units/i },
197
+ });
198
+
199
+ const reasoning = turn.events
200
+ .filter((event) => event.type === "reasoning.completed")
201
+ .map((event) => event.data.reasoning)
202
+ .join("\n\n");
203
+
204
+ t.judge("The reasoning checks its assumptions before concluding.", {
205
+ on: reasoning,
206
+ }).atLeast(0.8);
207
+ ```
208
+
209
+ A provider that does not expose reasoning emits no `reasoning.completed` event, so the `turn.event` gate fails and the judge grades an empty string. Reasoning the provider keeps hidden cannot be graded. The default judge input and `session.transcript` exclude reasoning, which is why the example passes it with `on`.
210
+
190
211
  ## Required preconditions
191
212
 
192
213
  Recorded assertions never throw and are not awaitable. When later control flow depends on a value, use `await t.require(value, assertion)`. It records a gate, returns the original value when it passes, and stops the test body without adding a duplicate execution error when it fails:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.80.1",
3
+ "version": "0.81.0",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [