eve 0.18.2 → 0.20.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 (129) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/src/cli/dev/tui/setup-selection-input.js +1 -1
  3. package/dist/src/cli/dev/tui/stream-format.d.ts +4 -0
  4. package/dist/src/cli/dev/tui/stream-format.js +1 -1
  5. package/dist/src/cli/dev/tui/terminal-renderer.js +1 -1
  6. package/dist/src/cli/dev/tui/test/mock-terminal.d.ts +2 -0
  7. package/dist/src/cli/dev/tui/test/mock-terminal.js +1 -1
  8. package/dist/src/compiled/.vendor-stamp.json +2 -1
  9. package/dist/src/compiled/@chat-adapter/slack/index.js +29 -32
  10. package/dist/src/compiled/@chat-adapter/twilio/LICENSE +9 -0
  11. package/dist/src/compiled/@chat-adapter/twilio/api.d.ts +108 -0
  12. package/dist/src/compiled/@chat-adapter/twilio/api.js +1 -0
  13. package/dist/src/compiled/@chat-adapter/twilio/format.d.ts +12 -0
  14. package/dist/src/compiled/@chat-adapter/twilio/format.js +1 -0
  15. package/dist/src/compiled/@chat-adapter/twilio/index.d.ts +84 -0
  16. package/dist/src/compiled/@chat-adapter/twilio/index.js +1 -0
  17. package/dist/src/compiled/@chat-adapter/twilio/voice.d.ts +44 -0
  18. package/dist/src/compiled/@chat-adapter/twilio/voice.js +1 -0
  19. package/dist/src/compiled/@chat-adapter/twilio/webhook.d.ts +18 -0
  20. package/dist/src/compiled/@chat-adapter/twilio/webhook.js +1 -0
  21. package/dist/src/compiled/_chunks/node/chunk-5OX2R7AJ-CxVV-owP.js +1 -0
  22. package/dist/src/compiled/_chunks/node/chunk-PFJ2G64A-B79fSABi.js +1 -0
  23. package/dist/src/compiled/_chunks/node/chunk-QZV7YRVM-Dzw4WEBv.js +1 -0
  24. package/dist/src/compiled/_chunks/node/dist-RHRJZ03Q.js +4 -0
  25. package/dist/src/context/build-base-tool-context.d.ts +9 -0
  26. package/dist/src/context/build-base-tool-context.js +1 -0
  27. package/dist/src/context/build-dynamic-tools.js +1 -1
  28. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  29. package/dist/src/evals/cli/eval.js +4 -1
  30. package/dist/src/evals/runner/discover.d.ts +10 -0
  31. package/dist/src/evals/runner/discover.js +1 -1
  32. package/dist/src/execution/durable-session-migrations/turn-workflow.d.ts +2 -0
  33. package/dist/src/execution/node-step.d.ts +2 -0
  34. package/dist/src/execution/node-step.js +1 -1
  35. package/dist/src/execution/sandbox/abort-bound-session.d.ts +6 -0
  36. package/dist/src/execution/sandbox/abort-bound-session.js +1 -0
  37. package/dist/src/execution/sandbox/active-handles.d.ts +29 -0
  38. package/dist/src/execution/sandbox/active-handles.js +1 -0
  39. package/dist/src/execution/sandbox/bindings/docker.d.ts +2 -2
  40. package/dist/src/execution/sandbox/bindings/docker.js +1 -1
  41. package/dist/src/execution/sandbox/bindings/just-bash-runtime.js +1 -1
  42. package/dist/src/execution/sandbox/bindings/microsandbox-lifecycle.js +1 -1
  43. package/dist/src/execution/sandbox/bindings/microsandbox-provider-state.d.ts +11 -0
  44. package/dist/src/execution/sandbox/bindings/microsandbox-provider-state.js +1 -0
  45. package/dist/src/execution/sandbox/bindings/microsandbox-runtime.d.ts +7 -4
  46. package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
  47. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  48. package/dist/src/execution/sandbox/ensure.js +1 -1
  49. package/dist/src/execution/sandbox/require-sandbox.d.ts +3 -1
  50. package/dist/src/execution/sandbox/require-sandbox.js +1 -1
  51. package/dist/src/execution/tool-auth.d.ts +2 -1
  52. package/dist/src/execution/tool-auth.js +1 -1
  53. package/dist/src/execution/web-fetch/tool.d.ts +6 -1
  54. package/dist/src/execution/web-fetch/tool.js +1 -1
  55. package/dist/src/execution/workflow-steps.js +1 -1
  56. package/dist/src/harness/action-result-helpers.d.ts +11 -1
  57. package/dist/src/harness/action-result-helpers.js +1 -1
  58. package/dist/src/harness/attachment-staging.js +1 -1
  59. package/dist/src/harness/compaction.d.ts +1 -1
  60. package/dist/src/harness/compaction.js +1 -1
  61. package/dist/src/harness/emission.d.ts +1 -0
  62. package/dist/src/harness/emission.js +1 -1
  63. package/dist/src/harness/execute-tool.d.ts +2 -1
  64. package/dist/src/harness/model-call-error.js +1 -1
  65. package/dist/src/harness/step-hooks.d.ts +1 -1
  66. package/dist/src/harness/step-hooks.js +1 -1
  67. package/dist/src/harness/tool-loop.js +1 -1
  68. package/dist/src/harness/tools.d.ts +2 -3
  69. package/dist/src/harness/tools.js +1 -1
  70. package/dist/src/harness/turn-cancellation.d.ts +8 -0
  71. package/dist/src/harness/turn-cancellation.js +1 -0
  72. package/dist/src/harness/turn-tag-state.d.ts +2 -0
  73. package/dist/src/harness/turn-tag-state.js +1 -1
  74. package/dist/src/harness/types.d.ts +2 -0
  75. package/dist/src/internal/application/package.js +1 -1
  76. package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
  77. package/dist/src/internal/nitro/host/configure-nitro-routes.js +1 -1
  78. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  79. package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
  80. package/dist/src/internal/nitro/host/sandbox-shutdown-plugin.d.ts +40 -0
  81. package/dist/src/internal/nitro/host/sandbox-shutdown-plugin.js +1 -0
  82. package/dist/src/internal/nitro/host/start-production-server.js +1 -1
  83. package/dist/src/internal/nitro/routes/index.d.ts +7 -2
  84. package/dist/src/internal/nitro/routes/index.js +78 -48
  85. package/dist/src/protocol/message.d.ts +14 -2
  86. package/dist/src/protocol/message.js +2 -2
  87. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +141 -0
  88. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +3 -0
  89. package/dist/src/public/channels/chat-sdk/index.d.ts +1 -0
  90. package/dist/src/public/channels/chat-sdk/index.js +1 -0
  91. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  92. package/dist/src/public/channels/index.d.ts +2 -0
  93. package/dist/src/public/channels/slack/api.js +1 -1
  94. package/dist/src/public/channels/twilio/api.d.ts +8 -29
  95. package/dist/src/public/channels/twilio/api.js +1 -1
  96. package/dist/src/public/channels/twilio/inbound.d.ts +10 -19
  97. package/dist/src/public/channels/twilio/inbound.js +2 -2
  98. package/dist/src/public/channels/twilio/routing.d.ts +13 -0
  99. package/dist/src/public/channels/twilio/routing.js +1 -0
  100. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  101. package/dist/src/public/channels/twilio/twiml.d.ts +5 -36
  102. package/dist/src/public/channels/twilio/twiml.js +1 -1
  103. package/dist/src/public/channels/twilio/verify.d.ts +12 -33
  104. package/dist/src/public/channels/twilio/verify.js +1 -1
  105. package/dist/src/public/definitions/approval.d.ts +4 -1
  106. package/dist/src/public/definitions/tool.d.ts +7 -0
  107. package/dist/src/public/tools/internal.d.ts +3 -2
  108. package/dist/src/public/tools/internal.js +1 -1
  109. package/dist/src/runtime/connections/mcp-client.d.ts +2 -2
  110. package/dist/src/runtime/connections/mcp-client.js +1 -1
  111. package/dist/src/runtime/connections/openapi-client.d.ts +2 -2
  112. package/dist/src/runtime/connections/openapi-client.js +1 -1
  113. package/dist/src/runtime/connections/types.d.ts +6 -1
  114. package/dist/src/runtime/framework-tools/bash.js +1 -1
  115. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
  116. package/dist/src/runtime/framework-tools/glob.js +1 -1
  117. package/dist/src/runtime/framework-tools/grep.js +1 -1
  118. package/dist/src/runtime/framework-tools/read-file.js +1 -1
  119. package/dist/src/runtime/framework-tools/web-fetch.js +1 -1
  120. package/dist/src/runtime/framework-tools/write-file.js +1 -1
  121. package/dist/src/sandbox/state.d.ts +0 -1
  122. package/dist/src/setup/scaffold/create/project.js +1 -1
  123. package/dist/src/shared/dynamic-tool-definition.d.ts +4 -1
  124. package/dist/src/shared/sandbox-backend.d.ts +7 -1
  125. package/dist/src/shared/tool-definition.d.ts +1 -1
  126. package/docs/sandbox.mdx +3 -1
  127. package/docs/tools/human-in-the-loop.md +1 -1
  128. package/docs/tools/overview.mdx +2 -0
  129. package/package.json +7 -1
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vercel, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,108 @@
1
+ type TwilioCredential = string | (() => Promise<string> | string);
2
+ type TwilioFetch = typeof fetch;
3
+ interface TwilioCredentials {
4
+ accountSid?: TwilioCredential;
5
+ authToken?: TwilioCredential;
6
+ }
7
+ type TwilioFormValue = boolean | number | readonly string[] | string | null | undefined;
8
+ type TwilioFormFields = Readonly<Record<string, TwilioFormValue>>;
9
+ interface TwilioApiOptions {
10
+ apiBaseUrl?: string;
11
+ apiUrl?: string;
12
+ credentials?: TwilioCredentials;
13
+ fetch?: TwilioFetch;
14
+ }
15
+ interface TwilioApiResponse {
16
+ body: unknown;
17
+ ok: boolean;
18
+ status: number;
19
+ }
20
+ interface TwilioMessageResource {
21
+ account_sid?: string;
22
+ body?: string | null;
23
+ date_created?: string | null;
24
+ date_sent?: string | null;
25
+ date_updated?: string | null;
26
+ direction?: string;
27
+ error_code?: number | null;
28
+ error_message?: string | null;
29
+ from?: string | null;
30
+ messaging_service_sid?: string | null;
31
+ num_media?: string;
32
+ sid: string;
33
+ status?: string;
34
+ to?: string | null;
35
+ uri?: string;
36
+ }
37
+ interface TwilioCallResource {
38
+ account_sid?: string;
39
+ answered_by?: string | null;
40
+ caller_name?: string | null;
41
+ date_created?: string | null;
42
+ date_updated?: string | null;
43
+ direction?: string;
44
+ duration?: string | null;
45
+ end_time?: string | null;
46
+ from?: string | null;
47
+ parent_call_sid?: string | null;
48
+ sid: string;
49
+ start_time?: string | null;
50
+ status?: string;
51
+ to?: string | null;
52
+ uri?: string;
53
+ }
54
+ interface SendTwilioMessageOptions extends TwilioApiOptions {
55
+ body?: string;
56
+ from?: string;
57
+ mediaUrl?: readonly string[] | string;
58
+ messagingServiceSid?: string;
59
+ statusCallbackUrl?: string;
60
+ to: string;
61
+ }
62
+ interface FetchTwilioMessageOptions extends TwilioApiOptions {
63
+ messageSid: string;
64
+ }
65
+ interface DeleteTwilioMessageOptions extends TwilioApiOptions {
66
+ messageSid: string;
67
+ }
68
+ interface UpdateTwilioCallOptions extends TwilioApiOptions {
69
+ callSid: string;
70
+ method?: "GET" | "POST";
71
+ status?: "canceled" | "completed";
72
+ twiml?: string;
73
+ url?: string;
74
+ }
75
+ interface FetchTwilioMediaOptions extends TwilioApiOptions {
76
+ url: string;
77
+ }
78
+ interface ListTwilioMessagesOptions extends TwilioApiOptions {
79
+ from?: string;
80
+ limit?: number;
81
+ pageSize?: number;
82
+ to?: string;
83
+ }
84
+ interface CallTwilioApiOptions extends TwilioApiOptions {
85
+ body?: TwilioFormFields | URLSearchParams;
86
+ method?: "DELETE" | "GET" | "POST";
87
+ path: string;
88
+ search?: TwilioFormFields | URLSearchParams;
89
+ }
90
+ declare class TwilioApiError extends Error {
91
+ body: unknown;
92
+ status: number;
93
+ constructor(message: string, options: {
94
+ body: unknown;
95
+ status: number;
96
+ });
97
+ }
98
+ declare function resolveTwilioCredential(value: TwilioCredential | undefined, envName: string): Promise<string>;
99
+ declare function callTwilioApi(pathOrOptions: CallTwilioApiOptions | string, options?: Omit<CallTwilioApiOptions, "path">): Promise<TwilioApiResponse>;
100
+ declare function sendTwilioMessage(options: SendTwilioMessageOptions): Promise<TwilioMessageResource>;
101
+ declare function fetchTwilioMessage(options: FetchTwilioMessageOptions): Promise<TwilioMessageResource>;
102
+ declare function deleteTwilioMessage(options: DeleteTwilioMessageOptions): Promise<void>;
103
+ declare function updateTwilioCall(options: UpdateTwilioCallOptions): Promise<TwilioCallResource>;
104
+ declare function fetchTwilioMedia(options: FetchTwilioMediaOptions): Promise<ArrayBuffer>;
105
+ declare function listTwilioMessages(options?: ListTwilioMessagesOptions): Promise<TwilioMessageResource[]>;
106
+ declare function encodeTwilioForm(fields: TwilioFormFields): URLSearchParams;
107
+
108
+ export { type CallTwilioApiOptions, type DeleteTwilioMessageOptions, type FetchTwilioMediaOptions, type FetchTwilioMessageOptions, type ListTwilioMessagesOptions, type SendTwilioMessageOptions, TwilioApiError, type TwilioApiOptions, type TwilioApiResponse, type TwilioCallResource, type TwilioCredential, type TwilioCredentials, type TwilioFetch, type TwilioFormFields, type TwilioFormValue, type TwilioMessageResource, type UpdateTwilioCallOptions, callTwilioApi, deleteTwilioMessage, encodeTwilioForm, fetchTwilioMedia, fetchTwilioMessage, listTwilioMessages, resolveTwilioCredential, sendTwilioMessage, updateTwilioCall };
@@ -0,0 +1 @@
1
+ import{a as e,c as t,i as n,l as r,n as i,o as a,r as o,s,t as c,u as l}from"../../_chunks/node/chunk-5OX2R7AJ-CxVV-owP.js";export{c as TwilioApiError,i as callTwilioApi,o as deleteTwilioMessage,n as encodeTwilioForm,e as fetchTwilioMedia,a as fetchTwilioMessage,s as listTwilioMessages,t as resolveTwilioCredential,r as sendTwilioMessage,l as updateTwilioCall};
@@ -0,0 +1,12 @@
1
+ declare const TWILIO_MESSAGE_LIMIT = 1600;
2
+ interface TwilioTextOptions {
3
+ limit?: number;
4
+ }
5
+ interface TwilioTextResult {
6
+ text: string;
7
+ truncated: boolean;
8
+ }
9
+ declare function truncateTwilioText(text: string, options?: TwilioTextOptions): TwilioTextResult;
10
+ declare function twilioTextOrPlaceholder(text: string): string;
11
+
12
+ export { TWILIO_MESSAGE_LIMIT, type TwilioTextOptions, type TwilioTextResult, truncateTwilioText, twilioTextOrPlaceholder };
@@ -0,0 +1 @@
1
+ import{n as e,r as t,t as n}from"../../_chunks/node/chunk-PFJ2G64A-B79fSABi.js";export{n as TWILIO_MESSAGE_LIMIT,e as truncateTwilioText,t as twilioTextOrPlaceholder};
@@ -0,0 +1,84 @@
1
+ import { BaseFormatConverter, Root, AdapterPostableMessage, Logger, CardElement, Adapter, ChatInstance, WebhookOptions, RawMessage, Message, FetchOptions, FetchResult, ThreadInfo, UserInfo, FormattedContent, Attachment } from '#compiled/chat/index.js';
2
+ import { TwilioMessageResource, TwilioCredential, TwilioFetch, TwilioApiOptions } from './api.js';
3
+ import { k as TwilioWebhookPayload, l as TwilioWebhookUrl, n as TwilioWebhookVerifier, b as TwilioMediaPayload } from './types-ConmTsdR.js';
4
+
5
+ declare class TwilioFormatConverter extends BaseFormatConverter {
6
+ toAst(text: string): Root;
7
+ fromAst(ast: Root): string;
8
+ renderPostable(message: AdapterPostableMessage): string;
9
+ }
10
+
11
+ interface TwilioThreadId {
12
+ recipient: string;
13
+ sender: string;
14
+ }
15
+ interface TwilioAdapterConfig {
16
+ accountSid?: TwilioCredential;
17
+ apiUrl?: string;
18
+ authToken?: TwilioCredential;
19
+ fetch?: TwilioFetch;
20
+ logger?: Logger;
21
+ messagingServiceSid?: string;
22
+ phoneNumber?: string;
23
+ statusCallbackUrl?: string;
24
+ userName?: string;
25
+ webhookUrl?: TwilioWebhookUrl;
26
+ webhookVerifier?: TwilioWebhookVerifier;
27
+ }
28
+ type TwilioRawMessage = TwilioMessageResource | TwilioWebhookPayload;
29
+
30
+ declare function cardToTwilioText(card: CardElement): string;
31
+
32
+ declare class TwilioAdapter implements Adapter<TwilioThreadId, TwilioRawMessage> {
33
+ readonly name = "twilio";
34
+ readonly lockScope: "channel";
35
+ readonly persistThreadHistory = true;
36
+ readonly userName: string;
37
+ protected chat: ChatInstance | null;
38
+ protected readonly accountSid?: TwilioAdapterConfig["accountSid"];
39
+ protected readonly apiUrl?: string;
40
+ protected readonly authToken?: TwilioAdapterConfig["authToken"];
41
+ protected readonly fetch?: TwilioAdapterConfig["fetch"];
42
+ protected readonly formatConverter: TwilioFormatConverter;
43
+ protected readonly logger: Logger;
44
+ protected readonly messagingServiceSid?: string;
45
+ protected readonly phoneNumber?: string;
46
+ protected readonly statusCallbackUrl?: string;
47
+ protected readonly webhookUrl?: TwilioAdapterConfig["webhookUrl"];
48
+ protected readonly webhookVerifier?: TwilioAdapterConfig["webhookVerifier"];
49
+ constructor(config?: TwilioAdapterConfig);
50
+ initialize(chat: ChatInstance): Promise<void>;
51
+ handleWebhook(request: Request, options?: WebhookOptions): Promise<Response>;
52
+ postMessage(threadId: string, message: AdapterPostableMessage): Promise<RawMessage<TwilioRawMessage>>;
53
+ editMessage(): Promise<RawMessage<TwilioRawMessage>>;
54
+ deleteMessage(_threadId: string, messageId: string): Promise<void>;
55
+ addReaction(): Promise<void>;
56
+ removeReaction(): Promise<void>;
57
+ startTyping(): Promise<void>;
58
+ parseMessage(raw: TwilioRawMessage): Message<TwilioRawMessage>;
59
+ fetchMessage(threadId: string, messageId: string): Promise<Message<TwilioRawMessage> | null>;
60
+ fetchMessages(threadId: string, options?: FetchOptions): Promise<FetchResult<TwilioRawMessage>>;
61
+ fetchThread(threadId: string): Promise<ThreadInfo>;
62
+ getUser(userId: string): Promise<UserInfo | null>;
63
+ openDM(userId: string): Promise<string>;
64
+ isDM(threadId: string): boolean;
65
+ channelIdFromThreadId(threadId: string): string;
66
+ encodeThreadId(platformData: TwilioThreadId): string;
67
+ decodeThreadId(threadId: string): TwilioThreadId;
68
+ renderFormatted(content: FormattedContent): string;
69
+ rehydrateAttachment(attachment: Attachment): Attachment;
70
+ protected parseTwilioTextPayload(raw: TwilioWebhookPayload & {
71
+ kind: "text";
72
+ }, threadId: string): Message<TwilioRawMessage>;
73
+ protected parseTwilioResource(raw: TwilioMessageResource, fallbackThread: TwilioThreadId | undefined): Message<TwilioRawMessage>;
74
+ protected renderPostableText(message: AdapterPostableMessage): string;
75
+ protected mediaUrls(message: AdapterPostableMessage): string[];
76
+ protected twilioAttachment(media: TwilioMediaPayload): Attachment;
77
+ protected apiOptions(): TwilioApiOptions;
78
+ protected defaultSender(): string;
79
+ protected author(userId: string, isMe: boolean): Message["author"];
80
+ protected threadIdForResource(raw: TwilioMessageResource, fallback: TwilioThreadId): string;
81
+ }
82
+ declare function createTwilioAdapter(config?: TwilioAdapterConfig): TwilioAdapter;
83
+
84
+ export { TwilioAdapter, type TwilioAdapterConfig, TwilioFormatConverter, type TwilioRawMessage, type TwilioThreadId, cardToTwilioText, createTwilioAdapter };
@@ -0,0 +1 @@
1
+ import{At as e,Dt as t,Nt as n,S as r,et as i,l as a,vt as o,wt as s,y as c}from"../../_chunks/node/dist-W8yle6rh.js";import{a as l,d as u,f as d,i as f,u as p}from"../../_chunks/node/dist-RHRJZ03Q.js";import{n as m,r as h,t as g}from"../../_chunks/node/chunk-PFJ2G64A-B79fSABi.js";import{a as _,l as v,o as y,r as b,s as x}from"../../_chunks/node/chunk-5OX2R7AJ-CxVV-owP.js";import{a as S,n as C,r as w}from"../../_chunks/node/chunk-QZV7YRVM-Dzw4WEBv.js";function T(e){return l(e).replace(/\*/g,``)}var E=class extends i{toAst(e){return s(e)}fromAst(r){return t(n(structuredClone(r),t=>o(t)?{type:`code`,value:e(t)}:t)).trim()}renderPostable(e){return typeof e==`string`?e:`raw`in e?e.raw:`markdown`in e?this.fromMarkdown(e.markdown):`ast`in e?this.fromAst(e.ast):super.renderPostable(e)}};function D(e){return`twilio:${encodeURIComponent(e.sender)}:${encodeURIComponent(e.recipient)}`}function O(e){let[t,n,r]=e.split(`:`);if(t!==`twilio`||!n||!r)throw new f(`twilio`,`Invalid Twilio thread ID: ${e}`);return{recipient:decodeURIComponent(r),sender:decodeURIComponent(n)}}function k(e){let t=O(e);return`twilio:${encodeURIComponent(t.sender)}`}function A(){return new Response(`<Response></Response>`,{headers:{"content-type":`application/xml`},status:200})}function j(e){return e.startsWith(`MG`)?{messagingServiceSid:e}:{from:e}}function M(e){return e?.startsWith(`image/`)?`image`:e?.startsWith(`video/`)?`video`:e?.startsWith(`audio/`)?`audio`:`file`}var N=class{name=`twilio`;lockScope=`channel`;persistThreadHistory=!0;userName;chat=null;accountSid;apiUrl;authToken;fetch;formatConverter=new E;logger;messagingServiceSid;phoneNumber;statusCallbackUrl;webhookUrl;webhookVerifier;constructor(e={}){this.accountSid=e.accountSid,this.apiUrl=e.apiUrl,this.authToken=e.authToken,this.fetch=e.fetch,this.logger=e.logger??new a(`info`).child(`twilio`),this.messagingServiceSid=e.messagingServiceSid??process.env.TWILIO_MESSAGING_SERVICE_SID,this.phoneNumber=e.phoneNumber??process.env.TWILIO_PHONE_NUMBER,this.statusCallbackUrl=e.statusCallbackUrl,this.userName=e.userName??`bot`,this.webhookUrl=e.webhookUrl,this.webhookVerifier=e.webhookVerifier}async initialize(e){this.chat=e,this.logger.info(`Twilio adapter initialized`,{messagingServiceSid:this.messagingServiceSid,phoneNumber:this.phoneNumber})}async handleWebhook(e,t){let n;try{n=await S(e,{authToken:this.authToken,webhookUrl:this.webhookUrl,webhookVerifier:this.webhookVerifier})}catch(e){if(e instanceof w)return new Response(`Invalid signature`,{status:401});if(e instanceof C)return new Response(`Invalid webhook`,{status:400});throw e}if(n.kind!==`text`||!this.chat)return A();let r=this.encodeThreadId({recipient:n.from,sender:n.to}),i=this.parseTwilioTextPayload(n,r);return this.chat.processMessage(this,r,i,t),A()}async postMessage(e,t){let n=this.decodeThreadId(e),r=this.renderPostableText(t),i=this.mediaUrls(t);if(!r&&i.length===0)throw new f(`twilio`,`Message text cannot be empty`);let a=await v({...this.apiOptions(),body:r||i.length===0?h(r):void 0,mediaUrl:i,statusCallbackUrl:this.statusCallbackUrl,to:n.recipient,...j(n.sender)});return{id:a.sid,raw:a,threadId:this.threadIdForResource(a,n)}}async editMessage(){throw new r(`Twilio does not support editing sent messages`,`editMessage`)}async deleteMessage(e,t){await b({...this.apiOptions(),messageSid:t})}async addReaction(){throw new r(`Twilio does not support message reactions`,`addReaction`)}async removeReaction(){throw new r(`Twilio does not support message reactions`,`removeReaction`)}async startTyping(){}parseMessage(e){if(F(e)){if(e.kind!==`text`)throw new f(`twilio`,`Cannot parse unsupported webhook`);return this.parseTwilioTextPayload(e,this.encodeThreadId({recipient:e.from,sender:e.to}))}return this.parseTwilioResource(e,void 0)}async fetchMessage(e,t){let n=this.decodeThreadId(e);try{let e=await y({...this.apiOptions(),messageSid:t});return this.parseTwilioResource(e,n)}catch{return null}}async fetchMessages(e,t={}){let n=this.decodeThreadId(e),r=t.limit??50,[i,a]=await Promise.all([x({...this.apiOptions(),from:n.sender,limit:r,to:n.recipient}),x({...this.apiOptions(),from:n.recipient,limit:r,to:n.sender})]);return{messages:[...i,...a].map(e=>this.parseTwilioResource(e,n)).sort((e,t)=>e.metadata.dateSent.getTime()-t.metadata.dateSent.getTime()).slice(-r)}}async fetchThread(e){let t=this.decodeThreadId(e);return{channelId:this.channelIdFromThreadId(e),channelName:t.sender,id:e,isDM:!0,metadata:{...t}}}async getUser(e){return{fullName:e,isBot:!1,userId:e,userName:e}}async openDM(e){return this.encodeThreadId({recipient:e,sender:this.defaultSender()})}isDM(e){return e.startsWith(`twilio:`)}channelIdFromThreadId(e){return k(e)}encodeThreadId(e){return D(e)}decodeThreadId(e){return O(e)}renderFormatted(e){return this.formatConverter.fromAst(e)}rehydrateAttachment(e){let t=e.fetchMetadata?.twilioMediaUrl??e.url;return t?this.twilioAttachment({contentType:e.mimeType,url:t}):e}parseTwilioTextPayload(e,t){return new c({attachments:e.media.map(e=>this.twilioAttachment(e)),author:this.author(e.from,!1),formatted:this.formatConverter.toAst(e.body),id:e.messageSid??`twilio:${Date.now()}`,metadata:{dateSent:new Date,edited:!1},raw:e,text:e.body,threadId:t})}parseTwilioResource(e,t){let n=e.direction?.startsWith(`outbound`)??!1,r=e.from??e.messaging_service_sid??(n?t?.sender:t?.recipient),i=e.to??(n?t?.recipient:t?.sender);if(!(r&&i))throw new f(`twilio`,`Twilio message is missing routing`);let a=e.body??``,o=n?{recipient:t?.recipient??i,sender:t?.sender??r}:{recipient:r,sender:i};return new c({attachments:[],author:this.author(n?o.sender:r,n),formatted:this.formatConverter.toAst(a),id:e.sid,metadata:{dateSent:I(e.date_sent??e.date_created),edited:!1},raw:e,text:a,threadId:this.encodeThreadId(o)})}renderPostableText(e){let t=p(e);return m(t?T(t):this.formatConverter.renderPostable(e),{limit:g}).text}mediaUrls(e){if(u(e).length>0)throw new f(`twilio`,`Twilio adapter supports media attachments by public URL only`);let t=d(e),n=[];for(let e of t){if(typeof e.url!=`string`||e.url.length===0)throw new f(`twilio`,`Twilio adapter supports media attachments by public URL only`);n.push(e.url)}return n}twilioAttachment(e){return{fetchData:async()=>Buffer.from(await _({...this.apiOptions(),url:e.url})),fetchMetadata:{twilioMediaUrl:e.url},mimeType:e.contentType,type:M(e.contentType),url:e.url}}apiOptions(){return{apiUrl:this.apiUrl,credentials:{accountSid:this.accountSid,authToken:this.authToken},fetch:this.fetch}}defaultSender(){let e=this.phoneNumber??this.messagingServiceSid;if(!e)throw new f(`twilio`,`phoneNumber or messagingServiceSid is required`);return e}author(e,t){return{fullName:e,isBot:t,isMe:t,userId:e,userName:e}}threadIdForResource(e,t){return this.parseTwilioResource(e,t).threadId}};function P(e={}){return new N(e)}function F(e){return`kind`in e}function I(e){let t=e?new Date(e):new Date;return Number.isNaN(t.getTime())?new Date:t}export{N as TwilioAdapter,E as TwilioFormatConverter,T as cardToTwilioText,P as createTwilioAdapter};
@@ -0,0 +1,44 @@
1
+ interface TwilioVoiceCallPayload {
2
+ accountSid?: string;
3
+ callSid?: string;
4
+ from: string;
5
+ raw: URLSearchParams;
6
+ to?: string;
7
+ }
8
+ interface TwilioVoiceTranscriptionPayload {
9
+ accountSid?: string;
10
+ callSid?: string;
11
+ confidence?: number;
12
+ final?: boolean;
13
+ from?: string;
14
+ raw: URLSearchParams;
15
+ sequenceId?: string;
16
+ text: string;
17
+ timestamp?: string;
18
+ to?: string;
19
+ track?: string;
20
+ transcriptionEvent?: string;
21
+ transcriptionSid?: string;
22
+ }
23
+ interface TwilioGatherSpeechResponseOptions {
24
+ actionOnEmptyResult?: boolean;
25
+ actionUrl: string;
26
+ hints?: readonly string[] | string;
27
+ language?: string;
28
+ method?: "GET" | "POST";
29
+ profanityFilter?: boolean;
30
+ prompt: string;
31
+ speechModel?: string;
32
+ speechTimeout?: "auto" | string;
33
+ timeoutSeconds?: number;
34
+ voice?: string;
35
+ }
36
+ declare function parseTwilioVoiceCall(params: URLSearchParams): TwilioVoiceCallPayload | null;
37
+ declare function parseTwilioVoiceTranscription(params: URLSearchParams): TwilioVoiceTranscriptionPayload | null;
38
+ declare function emptyTwilioResponse(): Response;
39
+ declare function sayTwilioResponse(message: string): Response;
40
+ declare function gatherSpeechTwilioResponse(options: TwilioGatherSpeechResponseOptions): Response;
41
+ declare function twilioResponse(twiml: string): Response;
42
+ declare function escapeXml(value: string): string;
43
+
44
+ export { type TwilioGatherSpeechResponseOptions, type TwilioVoiceCallPayload, type TwilioVoiceTranscriptionPayload, emptyTwilioResponse, escapeXml, gatherSpeechTwilioResponse, parseTwilioVoiceCall, parseTwilioVoiceTranscription, sayTwilioResponse, twilioResponse };
@@ -0,0 +1 @@
1
+ function e(e){let t=u(e,`From`)??u(e,`Caller`);return t?{accountSid:u(e,`AccountSid`),callSid:u(e,`CallSid`),from:t,raw:e,to:u(e,`To`)??u(e,`Called`)}:null}function t(e){let t=s(u(e,`TranscriptionData`)),n=c(u(e,`Final`));if(n===!1)return null;let r=u(e,`SpeechResult`)??u(e,`TranscriptionText`)??t?.transcript??``;return r.trim().length===0?null:{accountSid:u(e,`AccountSid`),callSid:u(e,`CallSid`),confidence:l(u(e,`Confidence`)??t?.confidence),final:n,from:u(e,`From`)??u(e,`Caller`),raw:e,sequenceId:u(e,`SequenceId`),text:r,timestamp:u(e,`Timestamp`),to:u(e,`To`)??u(e,`Called`),track:u(e,`Track`),transcriptionEvent:u(e,`TranscriptionEvent`),transcriptionSid:u(e,`TranscriptionSid`)}}function n(){return a(`<Response></Response>`)}function r(e){return a(`<Response><Say>${o(e)}</Say></Response>`)}function i(e){let t=typeof e.hints==`string`?e.hints:e.hints?.join(`,`),n=[`input="speech"`,`action="${o(e.actionUrl)}"`,`method="${e.method??`POST`}"`,`actionOnEmptyResult="${e.actionOnEmptyResult===!1?`false`:`true`}"`,e.language?`language="${o(e.language)}"`:void 0,e.speechModel?`speechModel="${o(e.speechModel)}"`:void 0,e.timeoutSeconds===void 0?void 0:`timeout="${e.timeoutSeconds}"`,e.speechTimeout?`speechTimeout="${o(e.speechTimeout)}"`:void 0,t?`hints="${o(t)}"`:void 0,e.profanityFilter===void 0?void 0:`profanityFilter="${e.profanityFilter?`true`:`false`}"`].filter(e=>e!==void 0).join(` `),r=[e.voice?`voice="${o(e.voice)}"`:void 0,e.language?`language="${o(e.language)}"`:void 0].filter(e=>e!==void 0).join(` `);return a(`<Response><Gather ${n}>${r?`<Say ${r}>`:`<Say>`}${o(e.prompt)}</Say></Gather></Response>`)}function a(e){return new Response(e,{headers:{"content-type":`text/xml;charset=UTF-8`},status:200})}function o(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`).replaceAll(`"`,`&quot;`).replaceAll(`'`,`&apos;`)}function s(e){if(!e)return null;try{let t=JSON.parse(e);return{confidence:typeof t.confidence==`number`||typeof t.confidence==`string`?String(t.confidence):void 0,transcript:typeof t.transcript==`string`?t.transcript:void 0}}catch{return null}}function c(e){if(e!==void 0){if(e===`true`)return!0;if(e===`false`)return!1}}function l(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function u(e,t){let n=e.get(t);return n===null||n.length===0?void 0:n}export{n as emptyTwilioResponse,o as escapeXml,i as gatherSpeechTwilioResponse,e as parseTwilioVoiceCall,t as parseTwilioVoiceTranscription,r as sayTwilioResponse,a as twilioResponse};
@@ -0,0 +1,18 @@
1
+ import { k as TwilioWebhookPayload, l as TwilioWebhookUrl, h as TwilioVerifyOptions, g as TwilioVerifiedRequest, c as TwilioReadOptions } from './types-ConmTsdR.js';
2
+ export { T as TwilioHeaderValue, a as TwilioHeaders, b as TwilioMediaPayload, d as TwilioStatusPayload, e as TwilioTextPayload, f as TwilioUnsupportedPayload, i as TwilioWebhookError, j as TwilioWebhookParseError, m as TwilioWebhookVerificationError, n as TwilioWebhookVerifier } from './types-ConmTsdR.js';
3
+ import './api.js';
4
+
5
+ declare function parseTwilioWebhookBody(params: URLSearchParams): TwilioWebhookPayload;
6
+
7
+ declare function verifyTwilioRequest(request: Request, options?: TwilioVerifyOptions): Promise<TwilioVerifiedRequest>;
8
+ declare function signTwilioRequest(input: {
9
+ authToken: string;
10
+ params?: URLSearchParams | null;
11
+ url: string;
12
+ }): Promise<string>;
13
+ declare function twilioSignatureBase(url: string, params?: URLSearchParams | null): string;
14
+ declare function resolveTwilioWebhookUrl(request: Request, webhookUrl: TwilioWebhookUrl | undefined): Promise<string>;
15
+
16
+ declare function readTwilioWebhook(request: Request, options?: TwilioReadOptions): Promise<TwilioWebhookPayload>;
17
+
18
+ export { TwilioReadOptions, TwilioVerifiedRequest, TwilioVerifyOptions, TwilioWebhookPayload, TwilioWebhookUrl, parseTwilioWebhookBody, readTwilioWebhook, resolveTwilioWebhookUrl, signTwilioRequest, twilioSignatureBase, verifyTwilioRequest };
@@ -0,0 +1 @@
1
+ import{a as e,c as t,i as n,l as r,n as i,o as a,r as o,s,t as c}from"../../_chunks/node/chunk-QZV7YRVM-Dzw4WEBv.js";export{c as TwilioWebhookError,i as TwilioWebhookParseError,o as TwilioWebhookVerificationError,n as parseTwilioWebhookBody,e as readTwilioWebhook,a as resolveTwilioWebhookUrl,s as signTwilioRequest,t as twilioSignatureBase,r as verifyTwilioRequest};
@@ -0,0 +1 @@
1
+ var e=class extends Error{body;status;constructor(e,t){super(e),this.name=`TwilioApiError`,this.body=t.body,this.status=t.status}},t=`https://api.twilio.com`;async function n(t,n){let r=t??process.env[n];if(!r)throw new e(`${n} is required`,{body:null,status:0});return typeof r==`function`?await r():r}async function r(r,i={}){let a=typeof r==`string`?{...i,path:r}:r,o=await n(a.credentials?.accountSid,`TWILIO_ACCOUNT_SID`),s=await n(a.credentials?.authToken,`TWILIO_AUTH_TOKEN`),c=new URL(a.path,a.apiUrl??a.apiBaseUrl??t);for(let[e,t]of d(a.search)??[])c.searchParams.append(e,t);let l=d(a.body),u=await(a.fetch??fetch)(c,{body:l,headers:{authorization:f(o,s),...l?{"content-type":`application/x-www-form-urlencoded;charset=UTF-8`}:{}},method:a.method??`POST`}),p=await m(u);if(!u.ok)throw new e(`Twilio API returned HTTP ${u.status}`,{body:p,status:u.status});return{body:p,ok:u.ok,status:u.status}}async function i(e){let t=await n(e.credentials?.accountSid,`TWILIO_ACCOUNT_SID`),i=p(e.mediaUrl);if(!e.body&&i.length===0)throw TypeError(`body or mediaUrl is required`);if(!(e.from||e.messagingServiceSid))throw TypeError(`from or messagingServiceSid is required`);let a=u({Body:e.body,From:e.from,MediaUrl:i,MessagingServiceSid:e.messagingServiceSid,StatusCallback:e.statusCallbackUrl,To:e.to});return(await r(`/2010-04-01/Accounts/${encodeURIComponent(t)}/Messages.json`,{...e,body:a})).body}async function a(e){let t=await n(e.credentials?.accountSid,`TWILIO_ACCOUNT_SID`);return(await r(`/2010-04-01/Accounts/${encodeURIComponent(t)}/Messages/${encodeURIComponent(e.messageSid)}.json`,{...e,method:`GET`})).body}async function o(e){let t=await n(e.credentials?.accountSid,`TWILIO_ACCOUNT_SID`);await r(`/2010-04-01/Accounts/${encodeURIComponent(t)}/Messages/${encodeURIComponent(e.messageSid)}.json`,{...e,method:`DELETE`})}async function s(e){let t=await n(e.credentials?.accountSid,`TWILIO_ACCOUNT_SID`);if(!(e.twiml||e.url||e.status))throw TypeError(`twiml, url, or status is required`);if(e.twiml&&e.url)throw TypeError(`twiml and url are mutually exclusive`);let i=u({Method:e.method,Status:e.status,Twiml:e.twiml,Url:e.url});return(await r(`/2010-04-01/Accounts/${encodeURIComponent(t)}/Calls/${encodeURIComponent(e.callSid)}.json`,{...e,body:i})).body}async function c(t){let r=await n(t.credentials?.accountSid,`TWILIO_ACCOUNT_SID`),i=await n(t.credentials?.authToken,`TWILIO_AUTH_TOKEN`),a=await(t.fetch??fetch)(t.url,{headers:{authorization:f(r,i)},method:`GET`});if(!a.ok)throw new e(`Twilio API returned HTTP ${a.status}`,{body:await m(a),status:a.status});return a.arrayBuffer()}async function l(e={}){let t=await n(e.credentials?.accountSid,`TWILIO_ACCOUNT_SID`),i=u({From:e.from,PageSize:e.pageSize,To:e.to});return((await r(`/2010-04-01/Accounts/${encodeURIComponent(t)}/Messages.json`,{...e,method:`GET`,search:i})).body.messages??[]).slice(0,e.limit)}function u(e){let t=new URLSearchParams;for(let[n,r]of Object.entries(e))if(r!=null){if(Array.isArray(r)){for(let e of r)t.append(n,e);continue}t.set(n,String(r))}return t}function d(e){if(e!==void 0)return e instanceof URLSearchParams?e:u(e)}function f(e,t){return`Basic ${btoa(`${e}:${t}`)}`}function p(e){return e===void 0?[]:typeof e==`string`?[e]:[...e]}async function m(e){let t=await e.text();if(!t)return null;try{return JSON.parse(t)}catch{return t}}export{c as a,n as c,u as i,i as l,r as n,a as o,o as r,l as s,e as t,s as u};
@@ -0,0 +1 @@
1
+ var e=1600;function t(e,t={}){let n=t.limit??1600;if(!Number.isInteger(n)||n<1)throw TypeError(`limit must be a positive integer`);return e.length<=n?{text:e,truncated:!1}:{text:e.slice(0,n),truncated:!0}}function n(e){return e.length>0?e:` `}export{t as n,n as r,e as t};
@@ -0,0 +1 @@
1
+ import{c as e}from"./chunk-5OX2R7AJ-CxVV-owP.js";function t(e){let t=r(e,`MessageStatus`)??r(e,`SmsStatus`),i=r(e,`Body`),a=r(e,`From`),o=r(e,`To`),s=r(e,`MessageSid`)??r(e,`SmsMessageSid`);return t&&!i?{accountSid:r(e,`AccountSid`),from:a,kind:`status`,messageSid:s,messageStatus:t,raw:e,to:o}:a&&o&&(i!==void 0||Number(r(e,`NumMedia`)??0)>0)?{accountSid:r(e,`AccountSid`),body:i??``,from:a,kind:`text`,media:n(e),messageSid:s,raw:e,to:o}:{kind:`unsupported`,raw:e}}function n(e){let t=Number(r(e,`NumMedia`)??0),n=[];for(let i=0;i<t;i++){let t=r(e,`MediaUrl${i}`);t&&n.push({contentType:r(e,`MediaContentType${i}`),url:t})}return n}function r(e,t){let n=e.get(t);return n===null||n.length===0?void 0:n}var i=class extends Error{constructor(e){super(e),this.name=`TwilioWebhookError`}},a=class extends i{constructor(e){super(e),this.name=`TwilioWebhookParseError`}},o=class extends i{constructor(e){super(e),this.name=`TwilioWebhookVerificationError`}};async function s(t,n={}){let r=await t.text();if(n.webhookVerifier){let e=await n.webhookVerifier(t,r);if(!e)throw new o(`Twilio webhook verifier rejected the request`);return{body:typeof e==`string`?e:r,params:d(t,typeof e==`string`?e:r)}}let i=t.headers.get(`x-twilio-signature`);if(!i)throw new o(`Twilio signature header is required`);let a=await e(n.authToken,`TWILIO_AUTH_TOKEN`),s=await u(t,n.webhookUrl),l=d(t,r);if(!p(await c({authToken:a,params:t.method.toUpperCase()===`GET`?null:l,url:s}),i))throw new o(`Twilio signature is invalid`);return{body:r,params:l}}async function c(e){let t=await crypto.subtle.importKey(`raw`,new TextEncoder().encode(e.authToken),{hash:`SHA-1`,name:`HMAC`},!1,[`sign`]);return f(await crypto.subtle.sign(`HMAC`,t,new TextEncoder().encode(l(e.url,e.params))))}function l(e,t){if(!t)return e;let n=e,r=new Map;for(let[e,n]of t){let t=r.get(e)??new Set;t.add(n),r.set(e,t)}for(let e of[...r.keys()].sort())for(let t of[...r.get(e)??[]].sort())n+=`${e}${t}`;return n}async function u(e,t){return typeof t==`function`?t(e):t??e.url}function d(e,t){return e.method.toUpperCase()===`GET`?new URL(e.url).searchParams:new URLSearchParams(t)}function f(e){let t=``,n=new Uint8Array(e);for(let e of n)t+=String.fromCharCode(e);return btoa(t)}function p(e,t){let n=Math.abs(e.length-t.length),r=Math.max(e.length,t.length);for(let i=0;i<r;i++){let r=e.charCodeAt(i)||0,a=t.charCodeAt(i)||0;n+=Number(r!==a)}return n===0}async function m(e,n={}){return t((await s(e,n)).params)}export{m as a,l as c,t as i,s as l,a as n,u as o,o as r,c as s,i as t};
@@ -0,0 +1,4 @@
1
+ import{I as e,K as t,L as n,kt as r}from"./dist-W8yle6rh.js";import i from"crypto";function a(e){return t(e)?e:typeof e==`object`&&e&&`card`in e?e.card:null}function o(e){return typeof e==`object`&&e&&`files`in e?e.files??[]:[]}function s(e){return typeof e==`object`&&e&&`attachments`in e?e.attachments??[]:[]}var c=class extends Error{adapter;code;constructor(e,t,n){super(e),this.name=`AdapterError`,this.adapter=t,this.code=n}},l=class extends c{retryAfter;constructor(e,t){super(`Rate limited by ${e}${t?`, retry after ${t}s`:``}`,e,`RATE_LIMITED`),this.name=`AdapterRateLimitError`,this.retryAfter=t}},u=class extends c{constructor(e,t){super(t||`Authentication failed for ${e}`,e,`AUTH_FAILED`),this.name=`AuthenticationError`}},d=class extends c{constructor(e,t){super(t,e,`VALIDATION_ERROR`),this.name=`ValidationError`}},f=class extends c{originalError;constructor(e,t,n){super(t||`Network error communicating with ${e}`,e,`NETWORK_ERROR`),this.name=`NetworkError`,this.originalError=n}};async function p(e,t){let{platform:n,throwOnUnsupported:r=!0}=t;if(Buffer.isBuffer(e))return e;if(e instanceof ArrayBuffer)return Buffer.from(e);if(e instanceof Blob){let t=await e.arrayBuffer();return Buffer.from(t)}if(r)throw new d(n,`Unsupported file data type`);return null}var m={slack:{primary:`primary`,danger:`danger`},gchat:{primary:`primary`,danger:`danger`},teams:{primary:`positive`,danger:`destructive`},discord:{primary:`primary`,danger:`danger`}};function h(e){return t=>n(t,e)}function g(e,t){if(e)return m[t][e]}function _(e,t={}){let{boldFormat:n=`*`,lineBreak:r=`
2
+ `,platform:i}=t,a=i?h(i):e=>e,o=[];e.title&&o.push(`${n}${a(e.title)}${n}`),e.subtitle&&o.push(a(e.subtitle));for(let t of e.children){let e=v(t,a);e&&o.push(e)}return o.join(r)}function v(t,n){switch(t.type){case`text`:return n(t.content);case`link`:return`${n(t.label)} (${t.url})`;case`fields`:return t.children.map(e=>`${n(e.label)}: ${n(e.value)}`).join(`
3
+ `);case`actions`:return null;case`section`:return t.children.map(e=>v(e,n)).filter(Boolean).join(`
4
+ `);case`table`:return r(t.headers,t.rows);case`divider`:return`---`;default:return e(t)}}var y=`aes-256-gcm`,b=12,x=16,S=/^[0-9a-fA-F]{64}$/;function C(e,t){let n=i.randomBytes(b),r=i.createCipheriv(y,t,n,{authTagLength:x}),a=Buffer.concat([r.update(e,`utf8`),r.final()]),o=r.getAuthTag();return{iv:n.toString(`base64`),data:a.toString(`base64`),tag:o.toString(`base64`)}}function w(e,t){let n=Buffer.from(e.iv,`base64`),r=Buffer.from(e.data,`base64`),a=Buffer.from(e.tag,`base64`),o=i.createDecipheriv(y,t,n,{authTagLength:x});return o.setAuthTag(a),Buffer.concat([o.update(r),o.final()]).toString(`utf8`)}function T(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.iv==`string`&&typeof t.data==`string`&&typeof t.tag==`string`}function E(e){let t=e.trim(),n=S.test(t),r=Buffer.from(t,n?`hex`:`base64`);if(r.length!==32)throw Error(`Encryption key must decode to exactly 32 bytes (received ${r.length}). Use a 64-char hex string or 44-char base64 string.`);return r}export{_ as a,w as c,o as d,s as f,p as h,d as i,C as l,g as m,u as n,h as o,T as p,f as r,E as s,l as t,a as u};
@@ -0,0 +1,9 @@
1
+ import type { SessionContext } from "#public/definitions/callback-context.js";
2
+ import type { ToolExecuteOptions } from "#shared/tool-definition.js";
3
+ /** Base context shared by tool executors. */
4
+ export type BaseToolContext = SessionContext & {
5
+ readonly abortSignal: AbortSignal;
6
+ readonly callId: string;
7
+ };
8
+ /** Builds the base context for one tool execution. */
9
+ export declare function buildBaseToolContext(options: Pick<ToolExecuteOptions, "abortSignal" | "toolCallId">): BaseToolContext;
@@ -0,0 +1 @@
1
+ import{buildCallbackContext}from"#context/build-callback-context.js";import{bindSandboxAbortSignal}from"#execution/sandbox/abort-bound-session.js";function buildBaseToolContext(e){let t=buildCallbackContext(),n=e.abortSignal??new AbortController().signal;return{...t,abortSignal:n,callId:e.toolCallId,getSandbox:async()=>bindSandboxAbortSignal(await t.getSandbox(),n)}}export{buildBaseToolContext};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{LiveStepToolsKey,SessionDynamicToolMetadataKey,TurnDynamicToolMetadataKey}from"#context/keys.js";import{jsonSchema}from"ai";import{buildCallbackContext}from"#context/build-callback-context.js";const log=createLogger(`dynamic-tools`);function lookupStepFunction(e){try{let t=globalThis[Symbol.for(`@workflow/core//registeredSteps`)];return t===void 0?null:t.get(e)||null}catch{return null}}function replayTools(e){let t=[];for(let n of e){if(!n.executeStepFnName||!n.closureVars){log.warn(`Dynamic tool "${n.name}" has no registered step function — skipping on this step. The bundler transform may not have processed this tool file.`);continue}let e=lookupStepFunction(n.executeStepFnName);if(!e){log.warn(`Dynamic tool "${n.name}" references step function "${n.executeStepFnName}" which is not registered — skipping on this step.`);continue}t.push({description:n.description,execute:t=>e(n.closureVars,t,buildCallbackContext()),inputSchema:jsonSchema(n.inputSchema),name:n.name,approval:buildReplayedApproval(n),outputSchema:n.outputSchema===void 0?void 0:jsonSchema(n.outputSchema)})}return t}function buildReplayedApproval(e){if(e.approvalStepFnName===void 0)return;let t=lookupStepFunction(e.approvalStepFnName);return t===null?(log.warn(`Dynamic tool "${e.name}" references approval function "${e.approvalStepFnName}" which is not registered — requiring approval by default.`),()=>`user-approval`):async n=>await t(e.closureVars??{},n)}function buildDynamicTools(e){let r=e.get(LiveStepToolsKey)??[],i=replayTools(e.get(TurnDynamicToolMetadataKey)??[]),a=replayTools(e.get(SessionDynamicToolMetadataKey)??[]);return[...r,...i,...a]}export{buildDynamicTools};
1
+ import{createLogger}from"#internal/logging.js";import{LiveStepToolsKey,SessionDynamicToolMetadataKey,TurnDynamicToolMetadataKey}from"#context/keys.js";import{jsonSchema}from"ai";import{buildBaseToolContext}from"#context/build-base-tool-context.js";const log=createLogger(`dynamic-tools`);function lookupStepFunction(e){try{let t=globalThis[Symbol.for(`@workflow/core//registeredSteps`)];return t===void 0?null:t.get(e)||null}catch{return null}}function replayTools(e){let t=[];for(let n of e){if(!n.executeStepFnName||!n.closureVars){log.warn(`Dynamic tool "${n.name}" has no registered step function — skipping on this step. The bundler transform may not have processed this tool file.`);continue}let e=lookupStepFunction(n.executeStepFnName);if(!e){log.warn(`Dynamic tool "${n.name}" references step function "${n.executeStepFnName}" which is not registered — skipping on this step.`);continue}t.push({description:n.description,execute:(t,r)=>e(n.closureVars,t,buildBaseToolContext(r)),inputSchema:jsonSchema(n.inputSchema),name:n.name,approval:buildReplayedApproval(n),outputSchema:n.outputSchema===void 0?void 0:jsonSchema(n.outputSchema)})}return t}function buildReplayedApproval(e){if(e.approvalStepFnName===void 0)return;let t=lookupStepFunction(e.approvalStepFnName);return t===null?(log.warn(`Dynamic tool "${e.name}" references approval function "${e.approvalStepFnName}" which is not registered — requiring approval by default.`),()=>`user-approval`):async n=>await t(e.closureVars??{},n)}function buildDynamicTools(e){let i=e.get(LiveStepToolsKey)??[],a=replayTools(e.get(TurnDynamicToolMetadataKey)??[]),o=replayTools(e.get(SessionDynamicToolMetadataKey)??[]);return[...i,...a,...o]}export{buildDynamicTools};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{LiveStepToolsKey,SessionDynamicToolMetadataKey,TurnDynamicToolMetadataKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{ALLOWED_DYNAMIC_TOOL_EVENTS,isBrandedToolEntry}from"#shared/dynamic-tool-definition.js";import{jsonSchema,zodSchema}from"ai";import{buildCallbackContext}from"#context/build-callback-context.js";import{buildResolveContext}from"#context/dynamic-resolve-context.js";import{normalizeJsonSchemaDefinition}from"#internal/json-schema.js";const log=createLogger(`dynamic-tools`);function toHarnessToolDefinition(e,t){return{description:t.description,execute:e=>t.execute(e,buildCallbackContext()),inputSchema:convertInputSchema(t.inputSchema),name:e,approval:t.approval,outputSchema:convertOptionalOutputSchema(t.outputSchema),...t.toModelOutput===void 0?{}:{toModelOutput:t.toModelOutput}}}function convertInputSchema(e){return typeof e==`object`&&e&&`~standard`in e?zodSchema(e):jsonSchema(e)}function convertOptionalOutputSchema(e){if(e!==void 0)return typeof e==`object`&&e&&`~standard`in e?zodSchema(e):jsonSchema(e)}function qualifyDynamicToolNames(e,t,n){let r=Object.keys(n),i=[];if(r.length===0)return i;if(t)return i.push({name:e,entryKey:r[0],entry:n[r[0]]}),i;for(let e of r)i.push({name:e,entryKey:e,entry:n[e]});return i}function replayDynamicSessionTools(e,t){let n=[];for(let t of e){if(!t.executeStepFnName||!t.closureVars){log.warn(`Dynamic tool "${t.name}" has no registered step function — skipping on this step. The bundler transform may not have processed this tool file.`);continue}let e=lookupStepFunction(t.executeStepFnName);if(!e){log.warn(`Dynamic tool "${t.name}" references step function "${t.executeStepFnName}" which is not registered — skipping on this step.`);continue}n.push({description:t.description,execute:n=>e(t.closureVars,n,buildCallbackContext()),inputSchema:jsonSchema(t.inputSchema),name:t.name,outputSchema:t.outputSchema===void 0?void 0:jsonSchema(t.outputSchema)})}return n}function getStepRegistry(){let e=Symbol.for(`@workflow/core//registeredSteps`),t=globalThis,n=t[e];return n===void 0&&(n=new Map,t[e]=n),n}function lookupStepFunction(e){try{return getStepRegistry().get(e)||null}catch{return null}}function registerStepFunction(e,t){getStepRegistry().set(e,t)}function safeSerialize(e){try{return JSON.parse(JSON.stringify(e))}catch{return{}}}function durableKeyForEvent(e){switch(e){case`session.started`:return SessionDynamicToolMetadataKey;case`turn.started`:return TurnDynamicToolMetadataKey;default:return}}async function resolveToolsFromEvent(e,t,n,r){let a=await Promise.allSettled(t.map(async t=>{let i=t.events[n.type];if(i===void 0)return null;let a=await i(n,buildResolveContext(e,r));if(a==null)return null;let s,c;return isBrandedToolEntry(a)?(s={_single:a},c=!0):(s=a,c=!1),{resolver:t,entries:s,isSingle:c}})),s=[],c=[],l=new Map;for(let e of a){if(e.status===`rejected`){log.error(`Dynamic tool resolver (${n.type}) threw — skipping.`,{error:toErrorMessage(e.reason)});continue}if(e.value===null)continue;let{resolver:t,entries:r,isSingle:a}=e.value,o=qualifyDynamicToolNames(t.slug,a,r);for(let{name:e,entryKey:r,entry:i}of o){let a=l.get(e);if(a!==void 0&&a!==t.slug)throw Error(`Dynamic tool "${e}" from resolver "${t.slug}" collides with dynamic resolver "${a}". Namespace the map key manually, e.g. "${t.slug}__${e}".`);if(l.set(e,t.slug),c.push(toHarnessToolDefinition(e,i)),n.type===`step.started`)continue;let o=`__executeStepFn`in i?i.__executeStepFn:void 0,u=`__closureVars`in i?i.__closureVars:void 0,f=o?.stepId,p=u===void 0?void 0:safeSerialize(u);if(f===void 0){let e=`eve:framework-dynamic:${t.slug}:${r}`,n=i.execute.bind(i);registerStepFunction(e,(e,t,r)=>n(t,r)),f=e,p={}}let m;if(i.approval!==void 0){m=`eve:dynamic-tool-approval:${t.slug}:${r}`;let e=i.approval.bind(i);registerStepFunction(m,(t,n)=>e(n))}s.push({name:e,description:i.description,inputSchema:normalizeJsonSchemaDefinition(i.inputSchema),outputSchema:i.outputSchema===void 0?void 0:normalizeJsonSchemaDefinition(i.outputSchema,`output`),resolverSlug:t.slug,entryKey:r,executeStepFnName:f,approvalStepFnName:m,closureVars:p})}}return{metadata:s,liveTools:c}}async function dispatchDynamicToolEvent(e){let{ctx:n,resolvers:r,event:i,messages:o}=e;if(!ALLOWED_DYNAMIC_TOOL_EVENTS.has(i.type))return;let s=r.filter(e=>e.eventNames.includes(i.type));if(s.length===0)return;let{metadata:c,liveTools:l}=await resolveToolsFromEvent(n,s,i,o);if(i.type===`step.started`){n.setVirtualContext(LiveStepToolsKey,l);return}let u=durableKeyForEvent(i.type);if(u===void 0)return;let d=new Set(s.map(e=>e.slug)),f=(n.get(u)??[]).filter(e=>!d.has(e.resolverSlug));n.set(u,[...f,...c])}export{dispatchDynamicToolEvent,replayDynamicSessionTools};
1
+ import{createLogger}from"#internal/logging.js";import{LiveStepToolsKey,SessionDynamicToolMetadataKey,TurnDynamicToolMetadataKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{ALLOWED_DYNAMIC_TOOL_EVENTS,isBrandedToolEntry}from"#shared/dynamic-tool-definition.js";import{jsonSchema,zodSchema}from"ai";import{buildBaseToolContext}from"#context/build-base-tool-context.js";import{buildResolveContext}from"#context/dynamic-resolve-context.js";import{normalizeJsonSchemaDefinition}from"#internal/json-schema.js";const log=createLogger(`dynamic-tools`);function toHarnessToolDefinition(e,t){return{description:t.description,execute:(e,n)=>t.execute(e,buildBaseToolContext(n)),inputSchema:convertInputSchema(t.inputSchema),name:e,approval:t.approval,outputSchema:convertOptionalOutputSchema(t.outputSchema),...t.toModelOutput===void 0?{}:{toModelOutput:t.toModelOutput}}}function convertInputSchema(e){return typeof e==`object`&&e&&`~standard`in e?zodSchema(e):jsonSchema(e)}function convertOptionalOutputSchema(e){if(e!==void 0)return typeof e==`object`&&e&&`~standard`in e?zodSchema(e):jsonSchema(e)}function qualifyDynamicToolNames(e,t,n){let r=Object.keys(n),i=[];if(r.length===0)return i;if(t)return i.push({name:e,entryKey:r[0],entry:n[r[0]]}),i;for(let e of r)i.push({name:e,entryKey:e,entry:n[e]});return i}function replayDynamicSessionTools(e,t){let n=[];for(let t of e){if(!t.executeStepFnName||!t.closureVars){log.warn(`Dynamic tool "${t.name}" has no registered step function — skipping on this step. The bundler transform may not have processed this tool file.`);continue}let e=lookupStepFunction(t.executeStepFnName);if(!e){log.warn(`Dynamic tool "${t.name}" references step function "${t.executeStepFnName}" which is not registered — skipping on this step.`);continue}n.push({description:t.description,execute:(n,r)=>e(t.closureVars,n,buildBaseToolContext(r)),inputSchema:jsonSchema(t.inputSchema),name:t.name,outputSchema:t.outputSchema===void 0?void 0:jsonSchema(t.outputSchema)})}return n}function getStepRegistry(){let e=Symbol.for(`@workflow/core//registeredSteps`),t=globalThis,n=t[e];return n===void 0&&(n=new Map,t[e]=n),n}function lookupStepFunction(e){try{return getStepRegistry().get(e)||null}catch{return null}}function registerStepFunction(e,t){getStepRegistry().set(e,t)}function safeSerialize(e){try{return JSON.parse(JSON.stringify(e))}catch{return{}}}function durableKeyForEvent(e){switch(e){case`session.started`:return SessionDynamicToolMetadataKey;case`turn.started`:return TurnDynamicToolMetadataKey;default:return}}async function resolveToolsFromEvent(e,t,n,r){let a=await Promise.allSettled(t.map(async t=>{let i=t.events[n.type];if(i===void 0)return null;let a=await i(n,buildResolveContext(e,r));if(a==null)return null;let s,c;return isBrandedToolEntry(a)?(s={_single:a},c=!0):(s=a,c=!1),{resolver:t,entries:s,isSingle:c}})),s=[],c=[],l=new Map;for(let e of a){if(e.status===`rejected`){log.error(`Dynamic tool resolver (${n.type}) threw — skipping.`,{error:toErrorMessage(e.reason)});continue}if(e.value===null)continue;let{resolver:t,entries:r,isSingle:a}=e.value,o=qualifyDynamicToolNames(t.slug,a,r);for(let{name:e,entryKey:r,entry:i}of o){let a=l.get(e);if(a!==void 0&&a!==t.slug)throw Error(`Dynamic tool "${e}" from resolver "${t.slug}" collides with dynamic resolver "${a}". Namespace the map key manually, e.g. "${t.slug}__${e}".`);if(l.set(e,t.slug),c.push(toHarnessToolDefinition(e,i)),n.type===`step.started`)continue;let o=`__executeStepFn`in i?i.__executeStepFn:void 0,u=`__closureVars`in i?i.__closureVars:void 0,f=o?.stepId,p=u===void 0?void 0:safeSerialize(u);if(f===void 0){let e=`eve:framework-dynamic:${t.slug}:${r}`,n=i.execute.bind(i);registerStepFunction(e,(e,t,r)=>n(t,r)),f=e,p={}}let m;if(i.approval!==void 0){m=`eve:dynamic-tool-approval:${t.slug}:${r}`;let e=i.approval.bind(i);registerStepFunction(m,(t,n)=>e(n))}s.push({name:e,description:i.description,inputSchema:normalizeJsonSchemaDefinition(i.inputSchema),outputSchema:i.outputSchema===void 0?void 0:normalizeJsonSchemaDefinition(i.outputSchema,`output`),resolverSlug:t.slug,entryKey:r,executeStepFnName:f,approvalStepFnName:m,closureVars:p})}}return{metadata:s,liveTools:c}}async function dispatchDynamicToolEvent(e){let{ctx:n,resolvers:r,event:i,messages:o}=e;if(!ALLOWED_DYNAMIC_TOOL_EVENTS.has(i.type))return;let s=r.filter(e=>e.eventNames.includes(i.type));if(s.length===0)return;let{metadata:c,liveTools:l}=await resolveToolsFromEvent(n,s,i,o);if(i.type===`step.started`){n.setVirtualContext(LiveStepToolsKey,l);return}let u=durableKeyForEvent(i.type);if(u===void 0)return;let d=new Set(s.map(e=>e.slug)),f=(n.get(u)??[]).filter(e=>!d.has(e.resolverSlug));n.set(u,[...f,...c])}export{dispatchDynamicToolEvent,replayDynamicSessionTools};
@@ -1 +1,4 @@
1
- import{basename,join}from"node:path";import{readFile}from"node:fs/promises";import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{resolveApplicationRoot}from"#internal/application/paths.js";import{createDevelopmentServer}from"#internal/nitro/host.js";import{createEvalClient}from"#evals/cli/eval-client.js";import{discoverAndImportEvals,discoverEvalConfig}from"#evals/runner/discover.js";import{runEvals}from"#evals/runner/run-evals.js";import{ConsoleReporter}from"#evals/runner/reporters/console.js";import{JUnit}from"#evals/runner/reporters/junit.js";import{resolveEvalTargetHandle}from"#evals/target.js";async function runEvalCommand(e,t,n){let o=resolveApplicationRoot();loadDevelopmentEnvironmentFiles(o);let s=e.length>0?e:void 0,c=await discoverAndImportEvals(o,s);if(c.length===0){s?n.error(`No evals found matching: ${s.join(`, `)}`):n.error(`No evals found. Create files under evals/ with the *.eval.ts extension.`),process.exitCode=2;return}let l=filterEvalsByTag(c,t.tag??[]);if(l.length===0){n.error(`No evals matched the provided tags (${(t.tag??[]).join(`, `)}).`),process.exitCode=2;return}let u,d;try{u=parsePositiveInteger(t.maxConcurrency,`--max-concurrency`),d=parseNonNegativeInteger(t.timeout,`--timeout`)}catch(e){n.error(e instanceof Error?e.message:String(e)),process.exitCode=2;return}if(t.list===!0){printEvalList(l,t.json===!0,n);return}let f;try{f=await discoverEvalConfig(o)}catch(e){n.error(e instanceof Error?e.message:String(e)),process.exitCode=2;return}let p,m,h;try{if(t.url)h=await createEvalClient({kind:`remote`,url:t.url},{workspaceRoot:o}),m=await resolveEvalTargetHandle({client:h,expectedAgentName:await readExpectedAgentName(o),kind:`remote`,url:t.url});else{p=createDevelopmentServer(o,{host:`127.0.0.1`,port:0});let e=await p.start();h=await createEvalClient({kind:`local`,url:e.url}),m=await resolveEvalTargetHandle({client:h,expectedAgentName:await readExpectedAgentName(o),kind:`local`,url:e.url})}let e=t.json===!0?[]:[new ConsoleReporter];t.junit!==void 0&&e.push(JUnit({filePath:t.junit}));let r=await runEvals({evaluations:l,config:f,target:m,client:h,appRoot:o,reporters:e,includeEvalReporters:t.skipReport!==!0,maxConcurrency:u,timeoutMs:d,onEvalLog:t.verbose===!0?(e,t)=>n.log(`[${e}] ${t}`):void 0});t.json&&n.log(JSON.stringify(r,null,2));let i=r.failed>0,a=t.strict===!0&&r.scored>0;(i||a)&&(process.exitCode=1)}finally{p&&await p.close()}let g=typeof process.exitCode==`number`?process.exitCode:0;process.exit(g)}function parsePositiveInteger(e,t){if(e===void 0)return;let n=Number(e);if(!Number.isInteger(n)||n<1)throw Error(`${t} must be a positive integer; got "${e}".`);return n}function parseNonNegativeInteger(e,t){if(e===void 0)return;let n=Number(e);if(!Number.isInteger(n)||n<0)throw Error(`${t} must be a non-negative integer; got "${e}".`);return n}function filterEvalsByTag(e,t){return t.length===0?[...e]:e.filter(e=>e.tags?.some(e=>t.includes(e))??!1)}function printEvalList(e,t,n){if(t){let t=e.map(e=>({id:e.id,description:e.description,tags:e.tags}));n.log(JSON.stringify(t,null,2));return}for(let t of e){let e=t.description===void 0?``:` — ${t.description}`,r=t.tags!==void 0&&t.tags.length>0?` [${t.tags.join(`, `)}]`:``;n.log(`${t.id}${r}${e}`)}}async function readExpectedAgentName(r){try{let i=JSON.parse(await readFile(join(r,`package.json`),`utf8`));return typeof i.name==`string`&&i.name.length>0?i.name:basename(r)}catch{return basename(r)}}export{runEvalCommand};
1
+ import{basename,join}from"node:path";import{readFile}from"node:fs/promises";import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{resolveApplicationRoot}from"#internal/application/paths.js";import{createDevelopmentServer}from"#internal/nitro/host.js";import{createEvalClient}from"#evals/cli/eval-client.js";import{discoverAndImportEvals,discoverEvalConfig,findMisplacedEvalDirs}from"#evals/runner/discover.js";import{runEvals}from"#evals/runner/run-evals.js";import{ConsoleReporter}from"#evals/runner/reporters/console.js";import{JUnit}from"#evals/runner/reporters/junit.js";import{resolveEvalTargetHandle}from"#evals/target.js";async function runEvalCommand(e,t,n){let o=resolveApplicationRoot();loadDevelopmentEnvironmentFiles(o);let s=e.length>0?e:void 0,c=await discoverAndImportEvals(o,s);if(c.length===0){let e=await findMisplacedEvalDirs(o);e.length>0?n.error(`No evals found under evals/, but eval files are present inside agent/:
2
+ `+e.map(e=>` - ${e}`).join(`
3
+ `)+`
4
+ eve eval only scans the top-level evals/ directory (a sibling of agent/). Move these files there.`):s?n.error(`No evals found matching: ${s.join(`, `)}`):n.error(`No evals found. Create files under evals/ with the *.eval.ts extension.`),process.exitCode=2;return}let l=filterEvalsByTag(c,t.tag??[]);if(l.length===0){n.error(`No evals matched the provided tags (${(t.tag??[]).join(`, `)}).`),process.exitCode=2;return}let u,d;try{u=parsePositiveInteger(t.maxConcurrency,`--max-concurrency`),d=parseNonNegativeInteger(t.timeout,`--timeout`)}catch(e){n.error(e instanceof Error?e.message:String(e)),process.exitCode=2;return}if(t.list===!0){printEvalList(l,t.json===!0,n);return}let f;try{f=await discoverEvalConfig(o)}catch(e){n.error(e instanceof Error?e.message:String(e)),process.exitCode=2;return}let p,m,h;try{if(t.url)h=await createEvalClient({kind:`remote`,url:t.url},{workspaceRoot:o}),m=await resolveEvalTargetHandle({client:h,expectedAgentName:await readExpectedAgentName(o),kind:`remote`,url:t.url});else{p=createDevelopmentServer(o,{host:`127.0.0.1`,port:0});let e=await p.start();h=await createEvalClient({kind:`local`,url:e.url}),m=await resolveEvalTargetHandle({client:h,expectedAgentName:await readExpectedAgentName(o),kind:`local`,url:e.url})}let e=t.json===!0?[]:[new ConsoleReporter];t.junit!==void 0&&e.push(JUnit({filePath:t.junit}));let r=await runEvals({evaluations:l,config:f,target:m,client:h,appRoot:o,reporters:e,includeEvalReporters:t.skipReport!==!0,maxConcurrency:u,timeoutMs:d,onEvalLog:t.verbose===!0?(e,t)=>n.log(`[${e}] ${t}`):void 0});t.json&&n.log(JSON.stringify(r,null,2));let i=r.failed>0,a=t.strict===!0&&r.scored>0;(i||a)&&(process.exitCode=1)}finally{p&&await p.close()}let g=typeof process.exitCode==`number`?process.exitCode:0;process.exit(g)}function parsePositiveInteger(e,t){if(e===void 0)return;let n=Number(e);if(!Number.isInteger(n)||n<1)throw Error(`${t} must be a positive integer; got "${e}".`);return n}function parseNonNegativeInteger(e,t){if(e===void 0)return;let n=Number(e);if(!Number.isInteger(n)||n<0)throw Error(`${t} must be a non-negative integer; got "${e}".`);return n}function filterEvalsByTag(e,t){return t.length===0?[...e]:e.filter(e=>e.tags?.some(e=>t.includes(e))??!1)}function printEvalList(e,t,n){if(t){let t=e.map(e=>({id:e.id,description:e.description,tags:e.tags}));n.log(JSON.stringify(t,null,2));return}for(let t of e){let e=t.description===void 0?``:` — ${t.description}`,r=t.tags!==void 0&&t.tags.length>0?` [${t.tags.join(`, `)}]`:``;n.log(`${t.id}${r}${e}`)}}async function readExpectedAgentName(r){try{let i=JSON.parse(await readFile(join(r,`package.json`),`utf8`));return typeof i.name==`string`&&i.name.length>0?i.name:basename(r)}catch{return basename(r)}}export{runEvalCommand};
@@ -6,6 +6,16 @@ import type { EveEval, EveEvalConfig } from "#evals/types.js";
6
6
  * Returns absolute paths sorted alphabetically by relative path.
7
7
  */
8
8
  export declare function discoverEvalFiles(appRoot: string): Promise<string[]>;
9
+ /**
10
+ * Finds directories under `<appRoot>/agent/` that directly contain
11
+ * `*.eval.ts` files. Used to produce a clear error when eval files are placed
12
+ * inside the agent tree instead of the top-level `evals/` directory that
13
+ * {@link discoverEvalFiles} scans.
14
+ *
15
+ * Returns app-root-relative, POSIX-normalized directory paths, sorted and
16
+ * de-duplicated. Returns `[]` when `agent/` is absent.
17
+ */
18
+ export declare function findMisplacedEvalDirs(appRoot: string): Promise<string[]>;
9
19
  /**
10
20
  * Returns true when `evalId` matches one of the requested filters. A filter
11
21
  * matches its exact eval id or any eval nested under it, so `"runtime"`
@@ -1 +1 @@
1
- import{join,relative}from"node:path";import{access,readdir}from"node:fs/promises";import{loadAuthoredModuleNamespace}from"#internal/authored-module-loader.js";const EVAL_FILE_SUFFIX=`.eval.ts`,EVAL_CONFIG_FILE=`evals.config.ts`;async function discoverEvalFiles(n){let r=join(n,`evals`),i=[];try{await collectEvalFiles(r,i)}catch(e){if(isNoEntryError(e))return[];throw e}return i.sort((e,n)=>relative(r,e).localeCompare(relative(r,n))),i}function deriveEvalId(n,r){let i=relative(join(n,`evals`),r).split(/[\\/]/u).join(`/`);return i.endsWith(EVAL_FILE_SUFFIX)?i.slice(0,-8):i}function matchesEvalFilter(e,t){return t.length===0?!0:t.some(t=>e===t||e.startsWith(`${t}/`))}async function importEvalFile(e,t){let n=(await loadAuthoredModuleNamespace(t)).default,r=deriveEvalId(e,t);if(isEveEvalDefinition(n))return[{...n,id:r}];if(Array.isArray(n))return n.map((e,n)=>{if(!isEveEvalDefinition(e))throw Error(`Eval file "${t}" exports an array whose entry at index ${n} is not a valid EveEval. Use defineEval() to create every entry.`);return{...e,id:`${r}/${String(n).padStart(4,`0`)}`}});throw Error(`Eval file "${t}" does not export a valid EveEval (or array of EveEvals) as its default export. Use defineEval() to create the eval.`)}async function discoverAndImportEvals(e,t){let n=await discoverEvalFiles(e);if(n.length===0)return[];let r=t??[],i=[],a=new Map;for(let t of n)for(let n of await importEvalFile(e,t)){let e=a.get(n.id);if(e!==void 0)throw Error(`Duplicate eval id "${n.id}" derived from both "${e}" and "${t}".`);a.set(n.id,t),matchesEvalFilter(n.id,r)&&i.push(n)}return i}async function discoverEvalConfig(t){let r=join(t,`evals`,EVAL_CONFIG_FILE);try{await access(r)}catch(e){throw isNoEntryError(e)?Error(`Missing required eval config at evals/${EVAL_CONFIG_FILE}. Create it with defineEvalConfig({}) (optionally \`{ judge: { model } }\` to set the default judge model for \`t.judge.*\` assertions).`):e}let a=(await loadAuthoredModuleNamespace(r)).default;if(!isEveEvalConfig(a))throw Error(`Eval config "evals/${EVAL_CONFIG_FILE}" must default-export a defineEvalConfig() value.`);return a}function isEveEvalConfig(e){return typeof e==`object`&&!!e&&`_tag`in e&&e._tag===`EveEvalConfig`}function isEveEvalDefinition(e){return typeof e==`object`&&!!e&&`_tag`in e&&e._tag===`EveEval`}async function collectEvalFiles(t,n){let i=await readdir(t,{withFileTypes:!0});for(let r of i){let i=join(t,r.name);r.isDirectory()?await collectEvalFiles(i,n):r.isFile()&&r.name.endsWith(EVAL_FILE_SUFFIX)&&n.push(i)}}function isNoEntryError(e){return typeof e==`object`&&!!e&&`code`in e&&e.code===`ENOENT`}export{discoverAndImportEvals,discoverEvalConfig,discoverEvalFiles,importEvalFile,matchesEvalFilter};
1
+ import{join,relative}from"node:path";import{access,readdir}from"node:fs/promises";import{loadAuthoredModuleNamespace}from"#internal/authored-module-loader.js";const EVAL_FILE_SUFFIX=`.eval.ts`,EVAL_CONFIG_FILE=`evals.config.ts`;async function discoverEvalFiles(n){let r=join(n,`evals`),i=[];try{await collectEvalFiles(r,i)}catch(e){if(isNoEntryError(e))return[];throw e}return i.sort((e,n)=>relative(r,e).localeCompare(relative(r,n))),i}async function findMisplacedEvalDirs(t){let n=join(t,`agent`),r=new Set;try{await collectMisplacedEvalDirs(n,t,r)}catch(e){if(isNoEntryError(e))return[];throw e}return[...r].sort((e,t)=>e.localeCompare(t))}function deriveEvalId(n,r){let i=relative(join(n,`evals`),r).split(/[\\/]/u).join(`/`);return i.endsWith(EVAL_FILE_SUFFIX)?i.slice(0,-8):i}function matchesEvalFilter(e,t){return t.length===0?!0:t.some(t=>e===t||e.startsWith(`${t}/`))}async function importEvalFile(e,t){let n=(await loadAuthoredModuleNamespace(t)).default,r=deriveEvalId(e,t);if(isEveEvalDefinition(n))return[{...n,id:r}];if(Array.isArray(n))return n.map((e,n)=>{if(!isEveEvalDefinition(e))throw Error(`Eval file "${t}" exports an array whose entry at index ${n} is not a valid EveEval. Use defineEval() to create every entry.`);return{...e,id:`${r}/${String(n).padStart(4,`0`)}`}});throw Error(`Eval file "${t}" does not export a valid EveEval (or array of EveEvals) as its default export. Use defineEval() to create the eval.`)}async function discoverAndImportEvals(e,t){let n=await discoverEvalFiles(e);if(n.length===0)return[];let r=t??[],i=[],a=new Map;for(let t of n)for(let n of await importEvalFile(e,t)){let e=a.get(n.id);if(e!==void 0)throw Error(`Duplicate eval id "${n.id}" derived from both "${e}" and "${t}".`);a.set(n.id,t),matchesEvalFilter(n.id,r)&&i.push(n)}return i}async function discoverEvalConfig(t){let r=join(t,`evals`,EVAL_CONFIG_FILE);try{await access(r)}catch(e){throw isNoEntryError(e)?Error(`Missing required eval config at evals/${EVAL_CONFIG_FILE}. Create it with defineEvalConfig({}) (optionally \`{ judge: { model } }\` to set the default judge model for \`t.judge.*\` assertions).`):e}let a=(await loadAuthoredModuleNamespace(r)).default;if(!isEveEvalConfig(a))throw Error(`Eval config "evals/${EVAL_CONFIG_FILE}" must default-export a defineEvalConfig() value.`);return a}function isEveEvalConfig(e){return typeof e==`object`&&!!e&&`_tag`in e&&e._tag===`EveEvalConfig`}function isEveEvalDefinition(e){return typeof e==`object`&&!!e&&`_tag`in e&&e._tag===`EveEval`}async function collectEvalFiles(t,n){let i=await readdir(t,{withFileTypes:!0});for(let r of i){let i=join(t,r.name);r.isDirectory()?await collectEvalFiles(i,n):r.isFile()&&r.name.endsWith(EVAL_FILE_SUFFIX)&&n.push(i)}}async function collectMisplacedEvalDirs(n,i,o){let s=await readdir(n,{withFileTypes:!0});for(let r of s)r.isDirectory()?await collectMisplacedEvalDirs(join(n,r.name),i,o):r.isFile()&&r.name.endsWith(EVAL_FILE_SUFFIX)&&o.add(relative(i,n).split(/[\\/]/u).join(`/`))}function isNoEntryError(e){return typeof e==`object`&&!!e&&`code`in e&&e.code===`ENOENT`}export{discoverAndImportEvals,discoverEvalConfig,discoverEvalFiles,findMisplacedEvalDirs,importEvalFile,matchesEvalFilter};
@@ -15,6 +15,8 @@ import type { DurableSessionState } from "#execution/durable-session-store.js";
15
15
  import type { RunMode } from "#shared/run-mode.js";
16
16
  export declare const TURN_WORKFLOW_INPUT_VERSION = 1;
17
17
  export interface TurnStepInput {
18
+ /** Cancellation signal forwarded into the turn step. */
19
+ readonly abortSignal?: AbortSignal;
18
20
  readonly input: HookPayload | undefined;
19
21
  readonly parentWritable: WritableStream<Uint8Array>;
20
22
  readonly serializedContext: Record<string, unknown>;
@@ -18,6 +18,8 @@ export type CreateRuntime = (config: {
18
18
  * Input for building a harness step for one resolved runtime node.
19
19
  */
20
20
  export interface CreateExecutionNodeStepInput {
21
+ /** Cancellation signal forwarded to the tool-loop harness. */
22
+ readonly abortSignal?: AbortSignal;
21
23
  /**
22
24
  * Session-level capabilities propagated from the runtime. The
23
25
  * harness passes this through to `buildToolSet` so `ask_question`
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{jsonSchema}from"ai";import{createToolLoopHarness}from"#harness/tool-loop.js";import{resolveRuntimeModelReference}from"#runtime/agent/resolve-model.js";import{findRegisteredRuntimeTool}from"#runtime/tools/registry.js";import{SUBAGENT_TOOL_INPUT_SCHEMA}from"#runtime/subagents/registry.js";import{preserveFrameworkStateOnCompaction}from"#execution/compaction.js";import{createToolExecuteWithAuth}from"#execution/tool-auth.js";const log=createLogger(`execution.node-step`),BUILT_IN_AGENT_TOOL_DESCRIPTION=[`Delegate a focused subtask to a fresh copy of yourself.`,`Use it to isolate complex work or split a large task into independent pieces.`,"Issue multiple `agent` calls in one response to run a small fixed set in parallel.","Each child has fresh history and state but shares your tools and sandbox, so include essential context in `message` and give parallel writers non-overlapping scopes."].join(` `);function createExecutionNodeStep(e){let t=createRuntimeModelResolver(e.modelResolutionScope),n=createNodeHarnessTools({node:e.node});return createToolLoopHarness({capabilities:e.capabilities,workflow:e.node.agent.workflowEnabled===!0,handleEvent:e.handleEvent,mode:e.mode,onCompaction:preserveFrameworkStateOnCompaction,resolveModel:t,runtimeIdentity:buildRuntimeIdentity(e.node),tools:n})}function buildRuntimeIdentity(e){let n=resolveInstalledPackageInfo(),r={agentId:e.turnAgent.id,agentName:e.agent.config?.name,eveVersion:n.version,modelId:e.turnAgent.model.id},i=process.env.VERCEL_GIT_COMMIT_SHA?.trim(),a=process.env.VERCEL_GIT_COMMIT_REF?.trim(),o=process.env.VERCEL_DEPLOYMENT_CREATED_AT?.trim();return i||a||o?{...r,build:{deployedAt:o||void 0,gitBranch:a||void 0,gitSha:i||void 0}}:r}function createRuntimeModelResolver(e){return t=>resolveRuntimeModelReference(t,e)}function createNodeHarnessTools(e){let t=new Map;for(let n of e.node.turnAgent.tools){let r=resolveHarnessToolDefinition({node:e.node,tool:n});r!==null&&t.set(n.name,r)}return t.has(`agent`)||t.set(`agent`,{description:BUILT_IN_AGENT_TOOL_DESCRIPTION,inputSchema:jsonSchema(SUBAGENT_TOOL_INPUT_SCHEMA),name:`agent`,runtimeAction:{kind:`subagent-call`,nodeId:e.node.nodeId,subagentName:`agent`}}),t}function resolveHarnessToolDefinition(e){if(e.tool.kind===`subagent`)return{description:e.tool.description??``,inputSchema:jsonSchema(e.tool.inputSchema??{}),name:e.tool.name,outputSchema:e.tool.outputSchema===void 0?void 0:jsonSchema(e.tool.outputSchema),runtimeAction:{kind:`subagent-call`,nodeId:e.tool.nodeId,subagentName:e.tool.name}};if(e.tool.kind===`remote`)return{description:e.tool.description??``,inputSchema:jsonSchema(e.tool.inputSchema??{}),name:e.tool.name,outputSchema:e.tool.outputSchema===void 0?void 0:jsonSchema(e.tool.outputSchema),runtimeAction:{kind:`remote-agent-call`,nodeId:e.tool.nodeId,remoteAgentName:e.tool.name,subagentName:e.tool.name}};let t=findRegisteredRuntimeTool(e.node.toolRegistry,e.tool.name);if(t===null)return log.warn(`declared tool is not registered — omitting from toolset`,{toolName:e.tool.name,nodeId:e.node.nodeId}),null;let r=t.definition,i=r.sourceId.startsWith(`eve:`),o=r.execute;return{approvalKey:r.approvalKey,description:r.description,execute:resolveAuthoredExecute({isFrameworkTool:i,rawExecute:o,scope:r.name}),inputSchema:r.inputStandardSchema??jsonSchema(r.inputSchema??{}),name:r.name,approval:r.approval,outputSchema:r.outputStandardSchema??maybeJsonSchema(r.outputSchema),toModelOutput:r.toModelOutput}}function resolveAuthoredExecute(e){let{isFrameworkTool:t,rawExecute:n,scope:r}=e;return n===void 0?void 0:t?n:createToolExecuteWithAuth({execute:n,scope:r})}function maybeJsonSchema(e){return e===void 0?void 0:jsonSchema(e)}export{createExecutionNodeStep,createNodeHarnessTools};
1
+ import{createLogger}from"#internal/logging.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{jsonSchema}from"ai";import{createToolLoopHarness}from"#harness/tool-loop.js";import{resolveRuntimeModelReference}from"#runtime/agent/resolve-model.js";import{findRegisteredRuntimeTool}from"#runtime/tools/registry.js";import{SUBAGENT_TOOL_INPUT_SCHEMA}from"#runtime/subagents/registry.js";import{preserveFrameworkStateOnCompaction}from"#execution/compaction.js";import{createToolExecuteWithAuth}from"#execution/tool-auth.js";const log=createLogger(`execution.node-step`),BUILT_IN_AGENT_TOOL_DESCRIPTION=[`Delegate a focused subtask to a fresh copy of yourself.`,`Use it to isolate complex work or split a large task into independent pieces.`,"Issue multiple `agent` calls in one response to run a small fixed set in parallel.","Each child has fresh history and state but shares your tools and sandbox, so include essential context in `message` and give parallel writers non-overlapping scopes."].join(` `);function createExecutionNodeStep(e){let t=createRuntimeModelResolver(e.modelResolutionScope),n=createNodeHarnessTools({node:e.node});return createToolLoopHarness({abortSignal:e.abortSignal,capabilities:e.capabilities,workflow:e.node.agent.workflowEnabled===!0,handleEvent:e.handleEvent,mode:e.mode,onCompaction:preserveFrameworkStateOnCompaction,resolveModel:t,runtimeIdentity:buildRuntimeIdentity(e.node),tools:n})}function buildRuntimeIdentity(e){let n=resolveInstalledPackageInfo(),r={agentId:e.turnAgent.id,agentName:e.agent.config?.name,eveVersion:n.version,modelId:e.turnAgent.model.id},i=process.env.VERCEL_GIT_COMMIT_SHA?.trim(),a=process.env.VERCEL_GIT_COMMIT_REF?.trim(),o=process.env.VERCEL_DEPLOYMENT_CREATED_AT?.trim();return i||a||o?{...r,build:{deployedAt:o||void 0,gitBranch:a||void 0,gitSha:i||void 0}}:r}function createRuntimeModelResolver(e){return t=>resolveRuntimeModelReference(t,e)}function createNodeHarnessTools(e){let t=new Map;for(let n of e.node.turnAgent.tools){let r=resolveHarnessToolDefinition({node:e.node,tool:n});r!==null&&t.set(n.name,r)}return t.has(`agent`)||t.set(`agent`,{description:BUILT_IN_AGENT_TOOL_DESCRIPTION,inputSchema:jsonSchema(SUBAGENT_TOOL_INPUT_SCHEMA),name:`agent`,runtimeAction:{kind:`subagent-call`,nodeId:e.node.nodeId,subagentName:`agent`}}),t}function resolveHarnessToolDefinition(e){if(e.tool.kind===`subagent`)return{description:e.tool.description??``,inputSchema:jsonSchema(e.tool.inputSchema??{}),name:e.tool.name,outputSchema:e.tool.outputSchema===void 0?void 0:jsonSchema(e.tool.outputSchema),runtimeAction:{kind:`subagent-call`,nodeId:e.tool.nodeId,subagentName:e.tool.name}};if(e.tool.kind===`remote`)return{description:e.tool.description??``,inputSchema:jsonSchema(e.tool.inputSchema??{}),name:e.tool.name,outputSchema:e.tool.outputSchema===void 0?void 0:jsonSchema(e.tool.outputSchema),runtimeAction:{kind:`remote-agent-call`,nodeId:e.tool.nodeId,remoteAgentName:e.tool.name,subagentName:e.tool.name}};let t=findRegisteredRuntimeTool(e.node.toolRegistry,e.tool.name);if(t===null)return log.warn(`declared tool is not registered — omitting from toolset`,{toolName:e.tool.name,nodeId:e.node.nodeId}),null;let r=t.definition,i=r.sourceId.startsWith(`eve:`),o=r.execute;return{approvalKey:r.approvalKey,description:r.description,execute:resolveAuthoredExecute({isFrameworkTool:i,rawExecute:o,scope:r.name}),inputSchema:r.inputStandardSchema??jsonSchema(r.inputSchema??{}),name:r.name,approval:r.approval,outputSchema:r.outputStandardSchema??maybeJsonSchema(r.outputSchema),toModelOutput:r.toModelOutput}}function resolveAuthoredExecute(e){let{isFrameworkTool:t,rawExecute:n,scope:r}=e;return n===void 0?void 0:t?n:createToolExecuteWithAuth({execute:n,scope:r})}function maybeJsonSchema(e){return e===void 0?void 0:jsonSchema(e)}export{createExecutionNodeStep,createNodeHarnessTools};
@@ -0,0 +1,6 @@
1
+ import type { SandboxSession } from "#shared/sandbox-session.js";
2
+ /**
3
+ * Returns a sandbox session that applies `abortSignal` to every operation.
4
+ * Per-call signals are composed with the bound signal.
5
+ */
6
+ export declare function bindSandboxAbortSignal(session: SandboxSession, abortSignal: AbortSignal): SandboxSession;
@@ -0,0 +1 @@
1
+ function bindSandboxAbortSignal(e,t){let compose=e=>e===void 0?t:AbortSignal.any([t,e]);return{...e,run:t=>e.run({...t,abortSignal:compose(t.abortSignal)}),spawn:t=>e.spawn({...t,abortSignal:compose(t.abortSignal)}),readFile:t=>e.readFile({...t,abortSignal:compose(t.abortSignal)}),readBinaryFile:t=>e.readBinaryFile({...t,abortSignal:compose(t.abortSignal)}),readTextFile:t=>e.readTextFile({...t,abortSignal:compose(t.abortSignal)}),writeFile:t=>e.writeFile({...t,abortSignal:compose(t.abortSignal)}),writeBinaryFile:t=>e.writeBinaryFile({...t,abortSignal:compose(t.abortSignal)}),writeTextFile:t=>e.writeTextFile({...t,abortSignal:compose(t.abortSignal)}),removePath:t=>e.removePath({...t,abortSignal:compose(t.abortSignal)})}}export{bindSandboxAbortSignal};
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The slice of `SandboxBackendHandle` the shutdown registry needs.
3
+ * Structural so handles of any session-options generic register without
4
+ * variance friction.
5
+ */
6
+ export interface ShutdownCapableSandboxHandle {
7
+ shutdown(): Promise<void>;
8
+ }
9
+ /**
10
+ * Registers a live sandbox handle for shutdown tracking. A handle
11
+ * created later for the same backend and session key replaces the
12
+ * previous entry.
13
+ */
14
+ export declare function trackActiveSandboxHandle(input: {
15
+ readonly backendName: string;
16
+ readonly handle: ShutdownCapableSandboxHandle;
17
+ readonly sessionKey: string;
18
+ }): void;
19
+ /**
20
+ * Stops every tracked sandbox by calling `shutdown()` on each handle in
21
+ * parallel, then clears the registry. Failures are logged and never
22
+ * thrown so one misbehaving sandbox cannot block server shutdown.
23
+ */
24
+ export declare function shutdownActiveSandboxHandles(input?: {
25
+ readonly log?: (message: string) => void;
26
+ }): Promise<void>;
27
+ /** Returns the number of tracked handles. Exposed for tests and logging. */
28
+ export declare function countActiveSandboxHandles(): number;
29
+ export declare function clearActiveSandboxHandlesForTest(): void;
@@ -0,0 +1 @@
1
+ import{toErrorMessage}from"#shared/errors.js";const activeSandboxHandles=new Map;function createActiveSandboxHandleKey(e,t){return`${e}\0${t}`}function trackActiveSandboxHandle(e){activeSandboxHandles.set(createActiveSandboxHandleKey(e.backendName,e.sessionKey),e.handle)}async function shutdownActiveSandboxHandles(n){let r=[...activeSandboxHandles.entries()];activeSandboxHandles.clear();let i=await Promise.allSettled(r.map(([,e])=>e.shutdown()));for(let[t,a]of i.entries())if(a.status===`rejected`){let i=r[t];n?.log?.(`failed to shut down sandbox "${i?.[0]??`unknown`}": ${toErrorMessage(a.reason)}`)}}function countActiveSandboxHandles(){return activeSandboxHandles.size}function clearActiveSandboxHandlesForTest(){activeSandboxHandles.clear()}export{clearActiveSandboxHandlesForTest,countActiveSandboxHandles,shutdownActiveSandboxHandles,trackActiveSandboxHandle};
@@ -27,7 +27,7 @@ export interface CreateDockerSandboxBackendInput {
27
27
  * container into a reusable template image.
28
28
  * - `create` starts (or restarts) one long-lived container per session
29
29
  * key from the template image. The container's filesystem carries
30
- * session state across reconnects; `dispose` intentionally leaves it
31
- * running so reattach is instant, mirroring the Vercel backend.
30
+ * session state across reconnects, so `shutdown` only stops the
31
+ * container and the next `create` restarts it with state intact.
32
32
  */
33
33
  export declare function createDockerSandboxBackend(input?: CreateDockerSandboxBackendInput): SandboxBackend;
@@ -1 +1 @@
1
- import{randomUUID}from"node:crypto";import{expectDockerSuccess}from"#execution/sandbox/bindings/docker-utils.js";import{markDevelopmentSandboxBackendInitialized}from"#execution/sandbox/development-run.js";import{writeSandboxSeedFiles}from"#execution/sandbox/bindings/local-backend-utils.js";import{assertDockerDaemonAvailable,createDockerCli}from"#execution/sandbox/bindings/docker-cli.js";import{DOCKER_SANDBOX_LABEL,runDockerBaseSetup,startDockerContainer}from"#execution/sandbox/bindings/docker-container.js";import{setDockerNetworkPolicy}from"#execution/sandbox/bindings/docker-network.js";import{createDockerSandboxOptionsHash,resolveDockerSandboxOptions}from"#execution/sandbox/bindings/docker-options.js";import{createDockerInternalSession}from"#execution/sandbox/bindings/docker-session.js";import{DOCKER_TEMPLATE_IMAGE_REPOSITORY,dockerImageExists,dockerTemplateImageReference,ensureDockerBaseImage,pruneDockerSandboxTemplates,resolveDockerTemplateMarkerPath,touchDockerTemplateMarker}from"#execution/sandbox/bindings/docker-templates.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{SandboxTemplateNotProvisionedError}from"#public/definitions/sandbox-backend.js";const DOCKER_BACKEND_NAME=`docker`;function createDockerSandboxBackend(c={}){let l=c.dockerCli??createDockerCli(),u=resolveDockerSandboxOptions(c.createOptions),d=createDockerSandboxOptionsHash(u),f;function ensureDaemon(){return f??=assertDockerDaemonAvailable(l).catch(e=>{throw f=void 0,e}),f}return{name:DOCKER_BACKEND_NAME,async prewarm(n){n.log?.(`checking Docker daemon`),await ensureDaemon();let i={optionsHash:d,templateKey:n.templateKey},a=dockerTemplateImageReference(i),o=resolveDockerTemplateMarkerPath(n.runtimeContext.appRoot,i);if(n.log?.(`checking cached template image "${a}"`),await dockerImageExists(l,a))return n.log?.(`reusing cached template image`),await touchDockerTemplateMarker(o,a),{reused:!0};n.log?.(`checking base image "${u.image}"`),await ensureDockerBaseImage(l,u);let s=`${n.templateKey}-build-${randomUUID().slice(0,8)}`;n.log?.(`starting template build container`),await startDockerContainer({cli:l,containerName:s,image:u.image,initialNetworkPolicy:`allow-all`,options:u,role:`template-build`});try{n.log?.(`preparing base runtime inside container`),await runDockerBaseSetup(l,s),u.networkPolicy!==`allow-all`&&(n.log?.(`applying network policy`),await setDockerNetworkPolicy(l,s,u.networkPolicy));let e=buildSandboxSession(createDockerInternalSession({cli:l,containerName:s,id:n.templateKey}),e=>setDockerNetworkPolicy(l,s,e));n.bootstrap!==void 0&&(n.log?.(`running sandbox bootstrap`),await n.bootstrap({use:async()=>createLoggingSandboxSession({log:n.log,session:e})})),n.seedFiles.length>0&&n.log?.(`writing ${n.seedFiles.length} seed file(s)`),await writeSandboxSeedFiles(e,n.seedFiles),n.log?.(`stopping template build container`),expectDockerSuccess(await l.run([`stop`,`-t`,`0`,s]),`stop template build container "${s}"`),n.log?.(`committing template image "${a}"`),expectDockerSuccess(await l.run([`commit`,`--change`,`LABEL ${DOCKER_SANDBOX_LABEL}=1`,`--change`,`LABEL ${DOCKER_SANDBOX_LABEL}.role=template`,`--change`,`LABEL ${DOCKER_SANDBOX_LABEL}.template-key=${n.templateKey}`,s,a]),`commit sandbox template image "${a}"`),await touchDockerTemplateMarker(o,a)}finally{await l.run([`rm`,`-f`,s]).catch(()=>{})}return{reused:!1}},async create(e){await ensureDaemon(),markDevelopmentSandboxBackendInitialized(DOCKER_BACKEND_NAME);let r=getDockerContainerName(e.existingMetadata)??e.sessionKey,i=await l.run([`container`,`inspect`,`--format`,`{{.State.Running}}`,r]);if(i.exitCode===0)i.stdout.trim()!==`true`&&expectDockerSuccess(await l.run([`start`,r]),`restart sandbox session container "${r}"`);else{let t;if(e.templateKey===null)await ensureDockerBaseImage(l,u),t=u.image;else{let n={optionsHash:d,templateKey:e.templateKey};if(t=dockerTemplateImageReference(n),!await dockerImageExists(l,t))throw new SandboxTemplateNotProvisionedError({backendName:DOCKER_BACKEND_NAME,templateKey:e.templateKey});await touchDockerTemplateMarker(resolveDockerTemplateMarkerPath(e.runtimeContext.appRoot,n),t)}try{await startDockerContainer({cli:l,containerName:r,image:t,initialNetworkPolicy:e.templateKey===null?`allow-all`:u.networkPolicy,options:u,role:`session`,tags:e.tags})}catch(t){throw e.templateKey===null?t:new SandboxTemplateNotProvisionedError({backendName:DOCKER_BACKEND_NAME,templateKey:e.templateKey})}e.templateKey===null&&(await runDockerBaseSetup(l,r),u.networkPolicy!==`allow-all`&&await setDockerNetworkPolicy(l,r,u.networkPolicy))}let a=buildSandboxSession(createDockerInternalSession({cli:l,containerName:r,id:e.sessionKey}),e=>setDockerNetworkPolicy(l,r,e));return{session:a,useSessionFn:async()=>a,async captureState(){return{backendName:DOCKER_BACKEND_NAME,metadata:{containerName:r},sessionKey:e.sessionKey}},async dispose(){}}}}}function getDockerContainerName(e){let t=e?.containerName;return typeof t==`string`?t:void 0}export{DOCKER_BACKEND_NAME,DOCKER_TEMPLATE_IMAGE_REPOSITORY,createDockerSandboxBackend,pruneDockerSandboxTemplates};
1
+ import{randomUUID}from"node:crypto";import{expectDockerSuccess}from"#execution/sandbox/bindings/docker-utils.js";import{markDevelopmentSandboxBackendInitialized}from"#execution/sandbox/development-run.js";import{writeSandboxSeedFiles}from"#execution/sandbox/bindings/local-backend-utils.js";import{assertDockerDaemonAvailable,createDockerCli}from"#execution/sandbox/bindings/docker-cli.js";import{DOCKER_SANDBOX_LABEL,runDockerBaseSetup,startDockerContainer,stopDockerContainerIfRunning}from"#execution/sandbox/bindings/docker-container.js";import{setDockerNetworkPolicy}from"#execution/sandbox/bindings/docker-network.js";import{createDockerSandboxOptionsHash,resolveDockerSandboxOptions}from"#execution/sandbox/bindings/docker-options.js";import{createDockerInternalSession}from"#execution/sandbox/bindings/docker-session.js";import{DOCKER_TEMPLATE_IMAGE_REPOSITORY,dockerImageExists,dockerTemplateImageReference,ensureDockerBaseImage,pruneDockerSandboxTemplates,resolveDockerTemplateMarkerPath,touchDockerTemplateMarker}from"#execution/sandbox/bindings/docker-templates.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{SandboxTemplateNotProvisionedError}from"#public/definitions/sandbox-backend.js";const DOCKER_BACKEND_NAME=`docker`;function createDockerSandboxBackend(c={}){let l=c.dockerCli??createDockerCli(),u=resolveDockerSandboxOptions(c.createOptions),d=createDockerSandboxOptionsHash(u),f;function ensureDaemon(){return f??=assertDockerDaemonAvailable(l).catch(e=>{throw f=void 0,e}),f}return{name:DOCKER_BACKEND_NAME,async prewarm(n){n.log?.(`checking Docker daemon`),await ensureDaemon();let i={optionsHash:d,templateKey:n.templateKey},a=dockerTemplateImageReference(i),o=resolveDockerTemplateMarkerPath(n.runtimeContext.appRoot,i);if(n.log?.(`checking cached template image "${a}"`),await dockerImageExists(l,a))return n.log?.(`reusing cached template image`),await touchDockerTemplateMarker(o,a),{reused:!0};n.log?.(`checking base image "${u.image}"`),await ensureDockerBaseImage(l,u);let s=`${n.templateKey}-build-${randomUUID().slice(0,8)}`;n.log?.(`starting template build container`),await startDockerContainer({cli:l,containerName:s,image:u.image,initialNetworkPolicy:`allow-all`,options:u,role:`template-build`});try{n.log?.(`preparing base runtime inside container`),await runDockerBaseSetup(l,s),u.networkPolicy!==`allow-all`&&(n.log?.(`applying network policy`),await setDockerNetworkPolicy(l,s,u.networkPolicy));let e=buildSandboxSession(createDockerInternalSession({cli:l,containerName:s,id:n.templateKey}),e=>setDockerNetworkPolicy(l,s,e));n.bootstrap!==void 0&&(n.log?.(`running sandbox bootstrap`),await n.bootstrap({use:async()=>createLoggingSandboxSession({log:n.log,session:e})})),n.seedFiles.length>0&&n.log?.(`writing ${n.seedFiles.length} seed file(s)`),await writeSandboxSeedFiles(e,n.seedFiles),n.log?.(`stopping template build container`),expectDockerSuccess(await l.run([`stop`,`-t`,`0`,s]),`stop template build container "${s}"`),n.log?.(`committing template image "${a}"`),expectDockerSuccess(await l.run([`commit`,`--change`,`LABEL ${DOCKER_SANDBOX_LABEL}=1`,`--change`,`LABEL ${DOCKER_SANDBOX_LABEL}.role=template`,`--change`,`LABEL ${DOCKER_SANDBOX_LABEL}.template-key=${n.templateKey}`,s,a]),`commit sandbox template image "${a}"`),await touchDockerTemplateMarker(o,a)}finally{await l.run([`rm`,`-f`,s]).catch(()=>{})}return{reused:!1}},async create(e){await ensureDaemon(),markDevelopmentSandboxBackendInitialized(DOCKER_BACKEND_NAME);let r=getDockerContainerName(e.existingMetadata)??e.sessionKey,i=await l.run([`container`,`inspect`,`--format`,`{{.State.Running}}`,r]);if(i.exitCode===0)i.stdout.trim()!==`true`&&expectDockerSuccess(await l.run([`start`,r]),`restart sandbox session container "${r}"`);else{let t;if(e.templateKey===null)await ensureDockerBaseImage(l,u),t=u.image;else{let n={optionsHash:d,templateKey:e.templateKey};if(t=dockerTemplateImageReference(n),!await dockerImageExists(l,t))throw new SandboxTemplateNotProvisionedError({backendName:DOCKER_BACKEND_NAME,templateKey:e.templateKey});await touchDockerTemplateMarker(resolveDockerTemplateMarkerPath(e.runtimeContext.appRoot,n),t)}try{await startDockerContainer({cli:l,containerName:r,image:t,initialNetworkPolicy:e.templateKey===null?`allow-all`:u.networkPolicy,options:u,role:`session`,tags:e.tags})}catch(t){throw e.templateKey===null?t:new SandboxTemplateNotProvisionedError({backendName:DOCKER_BACKEND_NAME,templateKey:e.templateKey})}e.templateKey===null&&(await runDockerBaseSetup(l,r),u.networkPolicy!==`allow-all`&&await setDockerNetworkPolicy(l,r,u.networkPolicy))}let a=buildSandboxSession(createDockerInternalSession({cli:l,containerName:r,id:e.sessionKey}),e=>setDockerNetworkPolicy(l,r,e));return{session:a,useSessionFn:async()=>a,async captureState(){return{backendName:DOCKER_BACKEND_NAME,metadata:{containerName:r},sessionKey:e.sessionKey}},async shutdown(){await stopDockerContainerIfRunning(l,r)}}}}}function getDockerContainerName(e){let t=e?.containerName;return typeof t==`string`?t:void 0}export{DOCKER_BACKEND_NAME,DOCKER_TEMPLATE_IMAGE_REPOSITORY,createDockerSandboxBackend,pruneDockerSandboxTemplates};