eve 0.17.1 → 0.17.2
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.
- package/CHANGELOG.md +14 -0
- package/dist/src/channel/types.d.ts +11 -0
- package/dist/src/cli/dev/tui/status-line.d.ts +1 -1
- package/dist/src/compiled/.vendor-stamp.json +1 -1
- package/dist/src/compiled/@chat-adapter/slack/api.d.ts +132 -0
- package/dist/src/compiled/@chat-adapter/slack/api.js +1 -0
- package/dist/src/compiled/@chat-adapter/slack/blocks.js +1 -1
- package/dist/src/compiled/@chat-adapter/slack/format.d.ts +33 -0
- package/dist/src/compiled/@chat-adapter/slack/format.js +1 -0
- package/dist/src/compiled/@chat-adapter/slack/index.js +28 -28
- package/dist/src/compiled/@chat-adapter/slack/types-AntsVifS.d.ts +187 -0
- package/dist/src/compiled/@chat-adapter/slack/webhook.d.ts +10 -0
- package/dist/src/compiled/@chat-adapter/slack/webhook.js +1 -0
- package/dist/src/compiled/_chunks/node/chunk-AYN7QRWH-B__hKQV7.js +1 -0
- package/dist/src/compiled/_chunks/node/chunk-HFKBBKCJ-CWaVIQuL.js +1 -0
- package/dist/src/compiler/manifest.d.ts +2 -2
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/normalize-agent-config.js +1 -1
- package/dist/src/context/keys.d.ts +2 -0
- package/dist/src/context/keys.js +1 -1
- package/dist/src/evals/assertions/run.js +2 -2
- package/dist/src/execution/create-session-step.d.ts +2 -0
- package/dist/src/execution/create-session-step.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/durable-session-store.d.ts +3 -0
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/session.d.ts +6 -1
- package/dist/src/execution/session.js +3 -3
- package/dist/src/execution/subagent-tool.js +1 -1
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/harness/advertised-tools.d.ts +33 -0
- package/dist/src/harness/advertised-tools.js +1 -0
- package/dist/src/harness/subagent-depth.d.ts +17 -0
- package/dist/src/harness/subagent-depth.js +1 -0
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/turn-tag-state.d.ts +30 -22
- package/dist/src/harness/turn-tag-state.js +1 -1
- package/dist/src/harness/types.d.ts +28 -0
- package/dist/src/harness/workflow-continuation-security.d.ts +1 -0
- package/dist/src/harness/workflow-continuation-security.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/core.js +1 -1
- package/dist/src/internal/nitro/host/configure-nitro-routes.js +2 -2
- package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
- package/dist/src/internal/nitro/routes/channel-route-context.d.ts +5 -0
- package/dist/src/internal/nitro/routes/channel-route-context.js +1 -0
- package/dist/src/internal/nitro/routes/info.d.ts +2 -6
- package/dist/src/internal/nitro/routes/info.js +1 -1
- package/dist/src/protocol/routes.d.ts +2 -4
- package/dist/src/public/channels/eve.d.ts +5 -4
- package/dist/src/public/channels/eve.js +1 -1
- package/dist/src/public/channels/slack/api.d.ts +3 -6
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/channels/slack/inbound.d.ts +11 -9
- package/dist/src/public/channels/slack/inbound.js +1 -1
- package/dist/src/public/channels/slack/interactions.d.ts +2 -1
- package/dist/src/public/channels/slack/interactions.js +1 -1
- package/dist/src/public/channels/slack/mrkdwn.d.ts +3 -35
- package/dist/src/public/channels/slack/mrkdwn.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/slack/verify.d.ts +4 -42
- package/dist/src/public/channels/slack/verify.js +1 -1
- package/dist/src/public/definitions/agent.d.ts +1 -1
- package/dist/src/public/index.d.ts +1 -1
- package/dist/src/runtime/resolve-agent.js +1 -1
- package/dist/src/setup/boxes/preflight.js +1 -1
- package/dist/src/setup/boxes/select-model.js +1 -1
- package/dist/src/setup/flows/model.js +1 -1
- package/dist/src/setup/scaffold/create/project.d.ts +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +3 -0
- package/dist/src/setup/scaffold/create/web-template.js +1 -1
- package/dist/src/shared/agent-definition.d.ts +37 -0
- package/dist/src/shared/default-agent-model.d.ts +1 -1
- package/dist/src/shared/default-agent-model.js +1 -1
- package/docs/agent-config.md +35 -8
- package/docs/channels/eve.mdx +3 -2
- package/docs/concepts/sessions-runs-and-streaming.md +2 -2
- package/docs/getting-started.mdx +5 -5
- package/docs/reference/typescript-api.md +1 -1
- package/docs/subagents.mdx +19 -0
- package/package.json +1 -1
- package/dist/src/compiled/_chunks/node/chunk-AYN7QRWH-Csu8sG38.js +0 -1
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Inbound Slack event → harness shaping.
|
|
3
3
|
*
|
|
4
|
-
* The channel calls these helpers on
|
|
5
|
-
*
|
|
4
|
+
* The channel calls these helpers on inbound Slack message events before
|
|
5
|
+
* handing them to the runtime:
|
|
6
6
|
*
|
|
7
|
-
* 1. {@link
|
|
8
|
-
* a channel-owned {@link SlackMessage}
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* 1. {@link slackMessageFromWebhookPayload} converts the shared Chat SDK
|
|
8
|
+
* webhook payload into a channel-owned {@link SlackMessage}. The legacy
|
|
9
|
+
* {@link parseAppMentionEvent} and {@link parseDirectMessageEvent}
|
|
10
|
+
* helpers keep their raw-envelope behavior for direct unit coverage.
|
|
11
11
|
* 2. The channel renders the actor, message, channel, and thread as one
|
|
12
12
|
* attributed model message so speaker identity cannot drift away from
|
|
13
13
|
* the content it describes.
|
|
14
14
|
*/
|
|
15
|
+
import type { SlackAppMentionPayload, SlackDirectMessagePayload } from "#compiled/@chat-adapter/slack/webhook.js";
|
|
15
16
|
/**
|
|
16
17
|
* Author metadata for an inbound Slack message. Channel-owned shape;
|
|
17
18
|
* does not depend on the chat SDK's `Author` interface.
|
|
@@ -39,9 +40,9 @@ export interface SlackAttachment {
|
|
|
39
40
|
/**
|
|
40
41
|
* Channel-owned representation of one inbound Slack message.
|
|
41
42
|
*
|
|
42
|
-
* Returned
|
|
43
|
-
*
|
|
44
|
-
*
|
|
43
|
+
* Returned for the triggering Slack event. Replaces the chat SDK
|
|
44
|
+
* `Message` type in the public callback surface (e.g.
|
|
45
|
+
* `onAppMention(ctx, message)`).
|
|
45
46
|
*/
|
|
46
47
|
export interface SlackMessage {
|
|
47
48
|
/** The original Slack text (mrkdwn). */
|
|
@@ -99,6 +100,7 @@ export declare function parseAppMentionEvent(envelope: SlackEventCallback): Slac
|
|
|
99
100
|
* bot's own DM replies from re-triggering the handler.
|
|
100
101
|
*/
|
|
101
102
|
export declare function parseDirectMessageEvent(envelope: SlackEventCallback): SlackMessage | null;
|
|
103
|
+
export declare function slackMessageFromWebhookPayload(payload: SlackAppMentionPayload | SlackDirectMessagePayload): SlackMessage | null;
|
|
102
104
|
/**
|
|
103
105
|
* Verified inbound identity used to attribute a model-visible Slack message.
|
|
104
106
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{slackMrkdwnToGfm}from"#public/channels/slack/mrkdwn.js";function parseAppMentionEvent(e){if(e.type!==`event_callback`)return null;let t=e.event;return!t||t.type!==`app_mention`?null:buildSlackMessage(t,e.team_id)}function parseDirectMessageEvent(e){if(e.type!==`event_callback`)return null;let t=e.event;if(!t||t.type!==`message`)return null;let n=t;return n.channel_type!==`im`||typeof n.subtype==`string`&&n.subtype.length>0&&n.subtype!==`file_share`||typeof n.bot_id==`string`&&n.bot_id.length>0?null:buildSlackMessage(n,e.team_id)}function buildSlackMessage(t,n){let r=typeof t.channel==`string`?t.channel:``,i=typeof t.ts==`string`?t.ts:``;if(!r||!i)return null;let a=typeof t.text==`string`?t.text:``,o=typeof t.thread_ts==`string`?t.thread_ts:i,s=typeof n==`string`?n:void 0;return{text:a,markdown:slackMrkdwnToGfm(a),ts:i,threadTs:o,channelId:r,teamId:s,author:parseAuthor(t),attachments:parseAttachments(t.files),raw:t}}function parseAuthor(e){let t=typeof e.user==`string`?e.user:``;if(t)return{userId:t,userName:typeof e.username==`string`?e.username:void 0,fullName:void 0,isBot:typeof e.bot_id==`string`&&e.bot_id.length>0,isMe:!1}}function parseAttachments(e){return Array.isArray(e)?e.map(toAttachment):[]}function toAttachment(e){let t=typeof e.mimetype==`string`?e.mimetype:void 0,n=typeof e.url_private==`string`?e.url_private:void 0;return{id:typeof e.id==`string`?e.id:``,type:inferAttachmentType(t),url:n,name:typeof e.name==`string`?e.name:void 0,mimeType:t,size:typeof e.size==`number`?e.size:void 0}}function inferAttachmentType(e){return e===void 0?`file`:e.startsWith(`image/`)?`image`:e.startsWith(`video/`)?`video`:e.startsWith(`audio/`)?`audio`:`file`}export{parseAppMentionEvent,parseDirectMessageEvent};
|
|
1
|
+
import{slackMrkdwnToGfm}from"#public/channels/slack/mrkdwn.js";function parseAppMentionEvent(e){if(e.type!==`event_callback`)return null;let t=e.event;return!t||t.type!==`app_mention`?null:buildSlackMessage(t,e.team_id)}function parseDirectMessageEvent(e){if(e.type!==`event_callback`)return null;let t=e.event;if(!t||t.type!==`message`)return null;let n=t;return n.channel_type!==`im`||typeof n.subtype==`string`&&n.subtype.length>0&&n.subtype!==`file_share`||typeof n.bot_id==`string`&&n.bot_id.length>0?null:buildSlackMessage(n,e.team_id)}function slackMessageFromWebhookPayload(t){return t.kind===`direct_message`&&(typeof t.subtype==`string`&&t.subtype.length>0&&t.subtype!==`file_share`||typeof t.botId==`string`&&t.botId.length>0)||!t.channelId||!t.ts?null:{text:t.text,markdown:slackMrkdwnToGfm(t.text),ts:t.ts,threadTs:t.threadTs,channelId:t.channelId,teamId:t.teamId,author:parsePayloadAuthor(t),attachments:parsePayloadAttachments(t.files),raw:t.raw}}function buildSlackMessage(t,n){let r=typeof t.channel==`string`?t.channel:``,i=typeof t.ts==`string`?t.ts:``;if(!r||!i)return null;let a=typeof t.text==`string`?t.text:``,o=typeof t.thread_ts==`string`?t.thread_ts:i,s=typeof n==`string`?n:void 0;return{text:a,markdown:slackMrkdwnToGfm(a),ts:i,threadTs:o,channelId:r,teamId:s,author:parseAuthor(t),attachments:parseAttachments(t.files),raw:t}}function parseAuthor(e){let t=typeof e.user==`string`?e.user:``;if(t)return{userId:t,userName:typeof e.username==`string`?e.username:void 0,fullName:void 0,isBot:typeof e.bot_id==`string`&&e.bot_id.length>0,isMe:!1}}function parseAttachments(e){return Array.isArray(e)?e.map(toAttachment):[]}function toAttachment(e){let t=typeof e.mimetype==`string`?e.mimetype:void 0,n=typeof e.url_private==`string`?e.url_private:void 0;return{id:typeof e.id==`string`?e.id:``,type:inferAttachmentType(t),url:n,name:typeof e.name==`string`?e.name:void 0,mimeType:t,size:typeof e.size==`number`?e.size:void 0}}function toPayloadAttachment(e){return{id:e.id,type:e.type,url:e.url,name:e.name,mimeType:e.mimeType,size:e.size}}function inferAttachmentType(e){return e===void 0?`file`:e.startsWith(`image/`)?`image`:e.startsWith(`video/`)?`video`:e.startsWith(`audio/`)?`audio`:`file`}function parsePayloadAuthor(e){if(!e.userId)return;let t=e.raw;return{userId:e.userId,userName:typeof t.username==`string`?t.username:void 0,fullName:void 0,isBot:typeof t.bot_id==`string`&&t.bot_id.length>0,isMe:!1}}function parsePayloadAttachments(e){return Array.isArray(e)?e.map(toPayloadAttachment):[]}export{parseAppMentionEvent,parseDirectMessageEvent,slackMessageFromWebhookPayload};
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* `onInteraction` callback. Always returns `Response("ok")` — followup
|
|
17
17
|
* work runs under `waitUntil` so the webhook ACK is immediate.
|
|
18
18
|
*/
|
|
19
|
+
import { type SlackBlockActionsPayload } from "#compiled/@chat-adapter/slack/webhook.js";
|
|
19
20
|
import type { SlackChannelConfig, SlackChannelState, SlackInteractionAction } from "#public/channels/slack/slackChannel.js";
|
|
20
21
|
import type { SendFn } from "#public/definitions/defineChannel.js";
|
|
21
22
|
/**
|
|
@@ -39,7 +40,7 @@ interface ParsedBlockActionsPayload {
|
|
|
39
40
|
* Returns `null` for payloads that don't carry the channel/thread
|
|
40
41
|
* metadata the handler needs.
|
|
41
42
|
*/
|
|
42
|
-
export declare function parseBlockActionsPayload(body: Record<string, unknown>): ParsedBlockActionsPayload | null;
|
|
43
|
+
export declare function parseBlockActionsPayload(body: Record<string, unknown> | SlackBlockActionsPayload): ParsedBlockActionsPayload | null;
|
|
43
44
|
/**
|
|
44
45
|
* Channel-supplied dependencies for {@link handleInteractionPost}.
|
|
45
46
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{buildSlackBinding,resolveSlackBotToken,slackContinuationToken}from"#public/channels/slack/api.js";import{buildSlackAuthContext}from"#public/channels/slack/auth.js";import{HITL_FREEFORM_MODAL_ACTION_ID,HITL_FREEFORM_MODAL_BLOCK_ID,HITL_FREEFORM_MODAL_CALLBACK_ID,buildAnsweredBlocks,buildFreeformModalView,deriveHitlResponse,freeformRequestIdFromActionId,isFreeformAction,isHitlAction}from"#public/channels/slack/hitl.js";const log=createLogger(`slack.interactions`);function parseBlockActionsPayload(e){let t=e.actions;if(!Array.isArray(
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{buildSlackBinding,resolveSlackBotToken,slackContinuationToken}from"#public/channels/slack/api.js";import{buildSlackAuthContext}from"#public/channels/slack/auth.js";import{HITL_FREEFORM_MODAL_ACTION_ID,HITL_FREEFORM_MODAL_BLOCK_ID,HITL_FREEFORM_MODAL_CALLBACK_ID,buildAnsweredBlocks,buildFreeformModalView,deriveHitlResponse,freeformRequestIdFromActionId,isFreeformAction,isHitlAction}from"#public/channels/slack/hitl.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";const log=createLogger(`slack.interactions`);function parseBlockActionsPayload(e){if(isSharedBlockActionsPayload(e))return parseSharedBlockActionsPayload(e);let t=e,n=t.actions;if(!Array.isArray(n))return null;let r=t.channel?.id,i=t.message,a=i?.thread_ts??i?.ts;if(!r||!a)return null;let o=t.team,s=t.user,c=o?.id??s.team_id,l={id:s.id,username:s.username,name:s.name},u=i?.blocks??[];return{actions:n.map(e=>({actionId:String(e.action_id??``),value:e.value==null?void 0:String(e.value),blockId:e.block_id==null?void 0:String(e.block_id),selectedOptionValue:extractSelectedOptionValue(e),messageTs:i?.ts,label:extractActionLabel(e),user:l})),channelId:r,threadTs:a,teamId:c,messageBlocks:u}}function isSharedBlockActionsPayload(e){return e.kind===`block_actions`&&Array.isArray(e.actions)}function parseSharedBlockActionsPayload(e){return!e.channelId||!e.threadTs?null:{actions:e.actions.map(t=>({actionId:t.actionId,value:t.value,blockId:t.blockId,selectedOptionValue:t.selectedOptionValue,messageTs:e.messageTs,label:t.label,user:{id:t.user?.id??e.userId,username:t.user?.username,name:t.user?.name}})),channelId:e.channelId,threadTs:e.threadTs,teamId:e.teamId,messageBlocks:e.messageBlocks??[]}}function extractSelectedOptionValue(e){let t=e.selected_option;return typeof t?.value==`string`?t.value:void 0}function extractActionLabel(e){let t=e.selected_option?.text?.text;if(typeof t==`string`&&t.length>0)return t;let n=e.text?.text;if(typeof n==`string`&&n.length>0)return n}function findPromptBlock(e){for(let t of e)if(typeof t==`object`&&t&&t.type===`section`)return t}function readPromptTextFromBlocks(e){let t=findPromptBlock(e)?.text?.text;return typeof t==`string`&&t.length>0?t:void 0}async function handleInteractionPost(e,n,a){let o=new Response(`ok`,{status:200}),s;try{s=parseSlackWebhookBody(e,{contentType:`application/x-www-form-urlencoded`})}catch{return log.warn(`failed to parse Slack interaction payload`),o}if(s.kind===`view_submission`)return handleViewSubmission(s,n,a);if(s.kind!==`block_actions`)return o;let c=parseBlockActionsPayload(s);if(!c)return o;let l=c.actions.find(e=>isFreeformAction(e.actionId));if(l)return await openFreeformModal({payload:s.raw,interaction:c,freeformAction:l,deps:a}),o;let d=slackContinuationToken(c.channelId,c.threadTs),p=c.actions.map(deriveHitlResponse).filter(e=>e!==null);if(p.length>0){let e=c.actions[0]?.user;if(!e)return o;n.waitUntil(n.send({inputResponses:p},{auth:buildSlackAuthContext({channelId:c.channelId,teamId:c.teamId,threadTs:c.threadTs,userId:e.id,userName:e.username??e.name}),continuationToken:d,state:{channelId:c.channelId,threadTs:c.threadTs,teamId:c.teamId??null,triggeringUserId:e.id}}).catch(e=>{log.error(`HITL interaction delivery failed`,{error:e})})),n.waitUntil(updateAnsweredHitlCard(c,a).catch(e=>{log.error(`HITL answered-card update failed`,{error:e})}))}let m=a.config.onInteraction;if(m){let e=c.actions.filter(e=>!isHitlAction(e.actionId));if(e.length>0){let{thread:r,slack:i}=buildSlackBinding({botToken:a.config.credentials?.botToken,channelId:c.channelId,threadTs:c.threadTs,teamId:c.teamId}),o={thread:r,slack:i};for(let t of e)n.waitUntil(Promise.resolve(m(t,o)).catch(e=>{log.error(`custom interaction handler failed`,{error:e})}))}}return o}async function openFreeformModal(e){let t=e.payload.trigger_id;if(typeof t!=`string`||t.length===0){log.warn(`freeform button click missing trigger_id — cannot open modal`);return}let i=freeformRequestIdFromActionId(e.freeformAction.actionId)??e.freeformAction.value;if(!i){log.warn(`freeform button click missing requestId`);return}let a=e.freeformAction.messageTs;if(!a){log.warn(`freeform button click missing messageTs`);return}let o=buildFreeformModalView({metadata:{continuationToken:slackContinuationToken(e.interaction.channelId,e.interaction.threadTs),channelId:e.interaction.channelId,threadTs:e.interaction.threadTs,messageTs:a,requestId:i},prompt:readPromptTextFromBlocks(e.interaction.messageBlocks)}),s=await resolveSlackBotToken(e.deps.config.credentials?.botToken),c=await fetch(`https://slack.com/api/views.open`,{method:`POST`,headers:{authorization:`Bearer ${s}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({trigger_id:t,view:o})});c.ok||log.error(`Slack views.open returned non-2xx`,{status:c.status})}async function handleViewSubmission(e,t,n){let r=new Response(null,{status:200});if(e.callbackId!==HITL_FREEFORM_MODAL_CALLBACK_ID)return r;let c;try{c=JSON.parse(e.privateMetadata??``)}catch{return log.warn(`freeform view_submission carries invalid private_metadata`),r}if(!c.continuationToken||!c.requestId||!c.messageTs||!c.channelId||!c.threadTs)return r;let l=e.values?.find(e=>e.blockId===HITL_FREEFORM_MODAL_BLOCK_ID&&e.actionId===HITL_FREEFORM_MODAL_ACTION_ID)?.value??``;if(l.length===0)return r;let u=e.user,d=e.userId,f=u?.teamId??e.teamId??null;return t.waitUntil(t.send({inputResponses:[{requestId:c.requestId,text:l}]},{auth:buildSlackAuthContext({channelId:c.channelId,teamId:f,threadTs:c.threadTs,userId:d,userName:u?.username??u?.name}),continuationToken:c.continuationToken,state:{channelId:c.channelId,threadTs:c.threadTs,teamId:f,triggeringUserId:d}}).catch(e=>{log.error(`freeform answer delivery failed`,{error:e})})),t.waitUntil(updateAnsweredFreeformCard({channelId:c.channelId,messageTs:c.messageTs,answerLabel:l,userId:d??void 0,deps:n}).catch(e=>{log.error(`freeform answered-card update failed`,{error:e})})),r}async function updateAnsweredHitlCard(e,t){let r=e.actions.find(e=>isHitlAction(e.actionId));if(!r||!r.messageTs)return;let i=r.label??r.selectedOptionValue??r.value;if(!i)return;let a=buildAnsweredBlocks({promptBlock:findPromptBlock(e.messageBlocks),answerLabel:i,userId:r.user.id}),o=await resolveSlackBotToken(t.config.credentials?.botToken),s=await fetch(`https://slack.com/api/chat.update`,{method:`POST`,headers:{authorization:`Bearer ${o}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({channel:e.channelId,ts:r.messageTs,blocks:a,text:`Answered: ${i}`})});if(!s.ok)throw Error(`Slack chat.update returned HTTP ${s.status}`)}async function updateAnsweredFreeformCard(e){let t=buildAnsweredBlocks({promptBlock:void 0,answerLabel:e.answerLabel,userId:e.userId}),r=await resolveSlackBotToken(e.deps.config.credentials?.botToken),i=await fetch(`https://slack.com/api/chat.update`,{method:`POST`,headers:{authorization:`Bearer ${r}`,"content-type":`application/json; charset=utf-8`},body:JSON.stringify({channel:e.channelId,ts:e.messageTs,blocks:t,text:`Answered: ${e.answerLabel}`})});if(!i.ok)throw Error(`Slack chat.update returned HTTP ${i.status}`)}export{handleInteractionPost,parseBlockActionsPayload};
|
|
@@ -1,38 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slack mrkdwn ↔ GitHub-flavored markdown converters and the bare
|
|
3
|
-
* `@mention` rewriter used by the outbound post pipeline. These are
|
|
4
|
-
* pure string utilities — no Slack API I/O, no I/O at all — so they
|
|
5
|
-
* live separately from the binding constructor and request shape code
|
|
6
|
-
* in {@link ./api.ts}.
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* Rewrites bare `@USER_ID` tokens (the form Slack apps and humans tend
|
|
10
|
-
* to type) into the `<@USER_ID>` mention syntax Slack actually renders.
|
|
11
|
-
* Anything already wrapped in `<...>` is left untouched.
|
|
12
|
-
*/
|
|
1
|
+
/** Rewrites bare Slack mention tokens into Slack's linked mention syntax. */
|
|
13
2
|
export declare function rewriteBareMentions(text: string): string;
|
|
14
|
-
/**
|
|
15
|
-
* Best-effort GFM → Slack mrkdwn converter used only in contexts that
|
|
16
|
-
* do not support `markdown_text` (e.g. `files.completeUploadExternal`'s
|
|
17
|
-
* `initial_comment` field).
|
|
18
|
-
*
|
|
19
|
-
* The main `{ markdown }` post path sends `markdown_text` directly
|
|
20
|
-
* to `chat.postMessage` and does not go through this converter.
|
|
21
|
-
*/
|
|
3
|
+
/** Converts markdown into Slack mrkdwn for legacy Slack text surfaces. */
|
|
22
4
|
export declare function gfmToSlackMrkdwn(input: string): string;
|
|
23
|
-
/**
|
|
24
|
-
* Best-effort Slack mrkdwn → GFM converter applied to the text of
|
|
25
|
-
* every inbound Slack message before the harness sees it.
|
|
26
|
-
*
|
|
27
|
-
* - `<@U123>` → `@U123`
|
|
28
|
-
* - `<#C123|name>` → `#name` (or `#C123` when no name)
|
|
29
|
-
* - `<!channel>` etc. → `@channel`
|
|
30
|
-
* - `<https://x|label>` → `[label](https://x)`
|
|
31
|
-
* - `<https://x>` → `https://x`
|
|
32
|
-
* - `*bold*` (paired) → `**bold**`
|
|
33
|
-
* - `~strike~` (paired) → `~~strike~~`
|
|
34
|
-
*
|
|
35
|
-
* Inline `_italic_` and code spans pass through unchanged because both
|
|
36
|
-
* formats render them identically.
|
|
37
|
-
*/
|
|
5
|
+
/** Converts inbound Slack mrkdwn into markdown while preserving code spans and fences. */
|
|
38
6
|
export declare function slackMrkdwnToGfm(input: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const BARE_MENTION_RE=/(?<![<\w])@(\w+)/gu;function rewriteBareMentions(
|
|
1
|
+
import{formatSlackLink,linkBareSlackMentions,markdownBoldToSlackMrkdwn,slackMrkdwnToMarkdown}from"#compiled/@chat-adapter/slack/format.js";const BARE_MENTION_RE=/(?<![<\w])@(\w+)/gu;function rewriteBareMentions(e){return linkBareSlackMentions(e).replace(BARE_MENTION_RE,`<@$1>`)}function gfmToSlackMrkdwn(e){return splitCodeFences(e).map(e=>e.kind===`code`?e.text:markdownToSlack(e.text)).join(``)}function slackMrkdwnToGfm(e){return splitCodeFences(e).map(e=>e.kind===`code`?e.text:slackToMarkdown(e.text)).join(``)}function splitCodeFences(e){let t=[],n=/```[\s\S]*?```|`[^`\n]+`/gu,r=0;for(let i of e.matchAll(n)){let n=i.index??0;n>r&&t.push({kind:`text`,text:e.slice(r,n)}),t.push({kind:`code`,text:i[0]}),r=n+i[0].length}return r<e.length&&t.push({kind:`text`,text:e.slice(r)}),t}function markdownToSlack(e){let t=markdownBoldToSlackMrkdwn(e);return t=t.replace(/__([^_\n]+)__/gu,`*$1*`),t=t.replace(/~~([^~\n]+)~~/gu,`~$1~`),t=t.replace(/\[([^\]\n]+)\]\(([^)\s]+)\)/gu,(e,t,n)=>formatMarkdownLink(e,t,n)),t}function slackToMarkdown(e){return slackMrkdwnToMarkdown(e.replace(/<!(channel|here|everyone)>/gu,`@$1`))}function formatMarkdownLink(t,n,r){try{return formatSlackLink(r,n)}catch(e){if(e instanceof TypeError)return t;throw e}}export{gfmToSlackMrkdwn,rewriteBareMentions,slackMrkdwnToGfm};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{markEventHandled}from"./utils.js";import{createLogger,logError}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{buildSlackBinding,slackContinuationToken}from"#public/channels/slack/api.js";import{slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{
|
|
1
|
+
import{markEventHandled}from"./utils.js";import{createLogger,logError}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{buildSlackBinding,slackContinuationToken}from"#public/channels/slack/api.js";import{slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{loadThreadContextMessages}from"#public/channels/slack/thread.js";import{parseSlackWebhookBody}from"#compiled/@chat-adapter/slack/webhook.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{slackMessageFromWebhookPayload}from"#public/channels/slack/inbound.js";import{formatSlackInboundMessage,formatSlackThreadContext}from"#public/channels/slack/model-context.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest as verifySlackRequest$1}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n){let{thread:r,slack:i}=buildSlackBinding({botToken:n?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.setContinuationToken(slackContinuationToken(e.channelId,n))}});return{thread:r,slack:i,state:e}}function slackChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=createSlackFetchFile({botToken:e.credentials?.botToken}),u=e.onAppMention??defaultOnAppMention,d=e.onDirectMessage??defaultOnDirectMessage,f=e.events?.[`authorization.required`],p=e.events?.[`turn.started`]??defaultEvents[`turn.started`],m={...defaultEvents,...e.events,async"turn.started"(e,t,n){let r=slackUserIdFromAuthContext(n.session.auth.current);r!==void 0&&(t.state.triggeringUserId=r),await p(e,t,n)},"input.requested":e.events?.[`input.requested`]??defaultInputRequestedHandler(),"authorization.required":f===void 0?defaultEvents[`authorization.required`]:constrainAuthorizationRequired(f)},h=new Set;return defineChannel({kindHint:`slack`,state:{channelId:null,threadTs:null,teamId:null,triggeringUserId:null,pendingToolCallMessage:null,lastReasoningTypingAtMs:null,lastReasoningTypingStatus:null,pendingAuthMessageTs:{}},fetchFile:n,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},context(t,n){return rebuildSlackContext(t,n,e.credentials)},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(n,{send:r,waitUntil:i})=>{let a=await verifyInbound(n,e.credentials);return a===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(n.headers)?new Response(`ok`):(n.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(a,{send:r,waitUntil:i},{config:e}):handleEventPost({body:a,send:r,waitUntil:i,onAppMention:u,onDirectMessage:d,uploadPolicy:t,threadContext:e.threadContext,handledEvents:h,headers:n.headers,credentials:e.credentials})})],async receive(t,{send:n}){let r=t.target,i=r.channelId;if(!i||typeof i!=`string`)throw Error(`slackChannel().receive requires target.channelId.`);let a=typeof r.threadTs==`string`?r.threadTs:``,s=r.initialMessage;if(s&&a.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let c=a;if(s){let{thread:t}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:i,threadTs:``,teamId:void 0}),n={card:s.card};s.fallbackText!==void 0&&(n.fallbackText=s.fallbackText),c=(await t.post(n)).id}let l=c||crypto.randomUUID();return n(t.message,{auth:t.auth,continuationToken:slackContinuationToken(i,l),state:{channelId:i,threadTs:c||null,teamId:null,triggeringUserId:null}})},events:m})}function constrainAuthorizationRequired(e){return(t,n,r)=>e(t,{postEphemeral:(e,t)=>n.thread.postEphemeral(e,t),postDirectMessage:(e,t)=>n.thread.postDirectMessage(e,t),state:n.state},r)}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??`0`)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(t){let n;try{n=parseSlackWebhookBody(t.body,{headers:t.headers})}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(n.kind===`url_verification`)return new Response(n.challenge,{status:200,headers:{"content-type":`text/plain`}});if(n.kind===`unsupported`||n.kind!==`app_mention`&&n.kind!==`direct_message`)return new Response(`ok`);if(n.eventId){if(t.handledEvents.has(n.eventId))return log.warn(`received a duplicate event`,{event_id:n.eventId,event_time:n.eventTime,retry_num:n.retry?.num??`(null)`,retry_reason:n.retry?.reason??`(null)`}),new Response(`ok`);markEventHandled(n.eventId,t.handledEvents)}let r=slackMessageFromWebhookPayload(n);return r?n.kind===`app_mention`?(t.waitUntil(dispatchInboundMessage({kind:`app_mention`,message:r,handler:t.onAppMention,send:t.send,uploadPolicy:t.uploadPolicy,threadContext:t.threadContext,credentials:t.credentials})),new Response(`ok`)):(n.kind===`direct_message`&&t.waitUntil(dispatchInboundMessage({kind:`direct_message`,message:r,handler:t.onDirectMessage,send:t.send,uploadPolicy:t.uploadPolicy,threadContext:t.threadContext,credentials:t.credentials})),new Response(`ok`)):new Response(`ok`)}async function verifyInbound(e,t){try{return await verifySlackRequest$1(e,{signingSecret:t?.signingSecret??(t?.webhookVerifier?void 0:process.env.SLACK_SIGNING_SECRET),webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`slack inbound verification failed`,{error:e}),null}}async function dispatchInboundMessage(e){let{message:t,kind:r}=e,{thread:i,slack:a}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:t.channelId,threadTs:t.threadTs,teamId:t.teamId}),s={thread:i,slack:a},c;try{c=await e.handler(s,t)}catch(e){logError(log,`${r} handler failed`,e,{channelId:t.channelId});return}if(c!=null)try{let n=formatSlackThreadContext(e.threadContext===void 0?[]:await loadThreadContextMessages(i,t,e.threadContext)),r=await collectInboundFileParts({mention:t,thread:i,policy:e.uploadPolicy}),a={channelId:t.channelId,fullName:t.author?.fullName,teamId:t.teamId,threadTs:t.threadTs,userId:t.author?.userId??``,userName:t.author?.userName},o=formatSlackInboundMessage(a,t),s=buildSlackTurnMessage(n===void 0?o:`${n}\n\n${o}`,r),l=c.context??[];await e.send(l.length===0?{message:s}:{message:s,context:l},{auth:c.auth,continuationToken:slackContinuationToken(t.channelId,t.threadTs),state:{channelId:t.channelId,threadTs:t.threadTs,teamId:t.teamId??null,triggeringUserId:a.userId||null},title:t.markdown})}catch(e){logError(log,`${r} delivery failed`,e,{channelId:t.channelId})}}export{constrainAuthorizationRequired,slackChannel};
|
|
@@ -1,48 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* The native channel replaces `createSlackAdapter`'s built-in HMAC
|
|
5
|
-
* check with a self-contained verifier:
|
|
6
|
-
*
|
|
7
|
-
* 1. If the caller supplied a {@link SlackWebhookVerifier} (e.g.
|
|
8
|
-
* Connect's OIDC-based forwarder), delegate to it.
|
|
9
|
-
* 2. Otherwise, recompute the Slack v0 HMAC and compare with
|
|
10
|
-
* `X-Slack-Signature`. Rejects requests older than five minutes to
|
|
11
|
-
* foil replay attacks.
|
|
12
|
-
*
|
|
13
|
-
* Returns the verified raw body string on success so the caller can
|
|
14
|
-
* parse it without re-reading the request stream.
|
|
15
|
-
*/
|
|
16
|
-
/**
|
|
17
|
-
* Caller-supplied inbound webhook verifier. Used as an alternative to
|
|
18
|
-
* HMAC verification — e.g. Connect supplies a verifier that
|
|
19
|
-
* authenticates Connect-forwarded webhooks with Vercel OIDC instead
|
|
20
|
-
* of Slack's signing secret.
|
|
21
|
-
*
|
|
22
|
-
* Contract (matches the chat SDK's `SlackAdapterConfig.webhookVerifier`):
|
|
23
|
-
*
|
|
24
|
-
* - **Throw / reject** → the channel responds 401 to Slack.
|
|
25
|
-
* - **Return a falsy value** (`null` / `undefined` / `false` / `""` /
|
|
26
|
-
* `0`) → the channel responds 401 to Slack. This lets verifiers
|
|
27
|
-
* signal rejection without throwing — e.g. Connect's `vercelOidc()`
|
|
28
|
-
* returns `null` on a failed OIDC check.
|
|
29
|
-
* - **Return a truthy non-string value** → verification accepted.
|
|
30
|
-
* - **Return a string** → verification accepted, and the string
|
|
31
|
-
* replaces the raw body for downstream parsing. Useful when the
|
|
32
|
-
* verifier canonicalizes or substitutes the verified payload.
|
|
33
|
-
*/
|
|
34
|
-
export type SlackWebhookVerifier = (request: Request, body: string) => unknown | Promise<unknown>;
|
|
1
|
+
import { type SlackWebhookVerifier } from "#compiled/@chat-adapter/slack/webhook.js";
|
|
2
|
+
export type { SlackWebhookVerifier };
|
|
3
|
+
/** Verification inputs for Eve's Slack webhook route. */
|
|
35
4
|
export interface SlackVerifyOptions {
|
|
36
5
|
readonly signingSecret: string | undefined;
|
|
37
6
|
readonly webhookVerifier: SlackWebhookVerifier | undefined;
|
|
38
|
-
/** Max allowed clock skew, in seconds. Defaults to 5 minutes. */
|
|
39
7
|
readonly maxSkewSeconds?: number;
|
|
40
8
|
}
|
|
41
|
-
/**
|
|
42
|
-
* Verifies an inbound Slack webhook and returns its raw body.
|
|
43
|
-
*
|
|
44
|
-
* Throws when neither a signing secret nor a custom verifier is
|
|
45
|
-
* available, when signature/timestamp checks fail, or when the
|
|
46
|
-
* caller-supplied verifier rejects.
|
|
47
|
-
*/
|
|
9
|
+
/** Verifies a Slack request with the Chat SDK webhook primitive. */
|
|
48
10
|
export declare function verifySlackRequest(request: Request, options: SlackVerifyOptions): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{verifySlackRequest as verifySlackRequest$1}from"#compiled/@chat-adapter/slack/webhook.js";async function verifySlackRequest(t,n){if(n.webhookVerifier===void 0&&!n.signingSecret)throw Error(`slackChannel: missing signing secret. Pass credentials.signingSecret, set SLACK_SIGNING_SECRET, or supply credentials.webhookVerifier.`);try{return await verifySlackRequest$1(t,n)}catch(e){throw normalizeSlackWebhookError(e)}}function normalizeSlackWebhookError(e){let t=e instanceof Error?e.message:String(e);return t.includes(`verifier rejected`)?Error(`slackChannel: inbound webhook verifier rejected the request.`):t.includes(`signature headers`)?Error(`slackChannel: inbound request missing Slack signature headers.`):t.includes(`timestamp is invalid`)?Error(`slackChannel: inbound request has malformed timestamp.`):t.includes(`timestamp is too old`)?Error(`slackChannel: inbound request timestamp outside allowed skew.`):t.includes(`signature is invalid`)?Error(`slackChannel: inbound request signature mismatch.`):e instanceof Error?e:Error(t)}export{verifySlackRequest};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PublicAgentDefinition } from "#shared/agent-definition.js";
|
|
2
2
|
import type { ExactDefinition } from "#public/definitions/exact.js";
|
|
3
|
-
export type { AgentModelOptionsDefinition, AgentReasoningDefinition, AgentBuildDefinition, AgentExperimentalDefinition, AgentWorkflowDefinition, AgentWorkflowWorldDefinition, PublicAgentModelDefinition as AgentModelDefinition, PublicAgentCompactionDefinition as AgentCompactionDefinition, } from "#shared/agent-definition.js";
|
|
3
|
+
export type { AgentModelOptionsDefinition, AgentReasoningDefinition, AgentBuildDefinition, AgentExperimentalDefinition, AgentLimitsDefinition, AgentWorkflowDefinition, AgentWorkflowWorldDefinition, PublicAgentModelDefinition as AgentModelDefinition, PublicAgentCompactionDefinition as AgentCompactionDefinition, } from "#shared/agent-definition.js";
|
|
4
4
|
/**
|
|
5
5
|
* Additive public agent configuration authored in `agent.ts`.
|
|
6
6
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Core agent authoring helpers for `agent/agent.ts`.
|
|
3
3
|
*/
|
|
4
|
-
export { type AgentCompactionDefinition, type AgentDefinition, type AgentExperimentalDefinition, type AgentModelDefinition, type AgentModelOptionsDefinition, type AgentReasoningDefinition, type AgentWorkflowDefinition, type AgentWorkflowWorldDefinition, defineAgent, } from "#public/definitions/agent.js";
|
|
4
|
+
export { type AgentCompactionDefinition, type AgentDefinition, type AgentExperimentalDefinition, type AgentLimitsDefinition, type AgentModelDefinition, type AgentModelOptionsDefinition, type AgentReasoningDefinition, type AgentWorkflowDefinition, type AgentWorkflowWorldDefinition, defineAgent, } from "#public/definitions/agent.js";
|
|
5
5
|
export { type RemoteAgentDefinition, type RemoteAgentDefinitionInput, defineRemoteAgent, } from "#public/definitions/remote-agent.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ResolveAgentError,createResolvedModuleSourceRef}from"#runtime/resolve-helpers.js";import{resolveChannelDefinition}from"#runtime/resolve-channel.js";import{resolveConnectionDefinition}from"#runtime/resolve-connection.js";import{resolveHookDefinition}from"#runtime/resolve-hook.js";import{resolveSandboxDefinition}from"#runtime/resolve-sandbox.js";import{resolveDynamicInstructionsDefinition}from"#runtime/resolve-dynamic-instructions.js";import{resolveDynamicSkillDefinition}from"#runtime/resolve-dynamic-skill.js";import{resolveDynamicToolDefinition}from"#runtime/resolve-dynamic-tool.js";import{resolveToolDefinition}from"#runtime/resolve-tool.js";async function resolveAgent(e){let t=e.manifest.skills.map(e=>({...e,metadata:e.metadata===void 0?void 0:{...e.metadata}})),r=[],i=[];for(let t of e.manifest.channels){if(t.kind===`disabled`){i.push(t.name);continue}r.push(await resolveChannelDefinition(t,e.moduleMap,e.nodeId))}let a=await Promise.all(e.manifest.tools.map(t=>resolveToolDefinition(t,e.moduleMap,e.nodeId))),o=await Promise.all((e.manifest.dynamicInstructions??[]).map(t=>resolveDynamicInstructionsDefinition(t,e.moduleMap,e.nodeId))),s=await Promise.all((e.manifest.dynamicSkills??[]).map(t=>resolveDynamicSkillDefinition(t,e.moduleMap,e.nodeId))),c=await Promise.all(e.manifest.dynamicTools.map(t=>resolveDynamicToolDefinition(t,e.moduleMap,e.nodeId))),l=await Promise.all(e.manifest.hooks.map(t=>resolveHookDefinition(t,e.moduleMap,e.nodeId))),u=await Promise.all(e.manifest.connections.map(t=>resolveConnectionDefinition(t,e.moduleMap,e.nodeId))),d=e.manifest.sandbox===null?null:await resolveSandboxDefinition(e.manifest.sandbox,e.moduleMap,e.nodeId),f=createResolvedInstructions(e.manifest.instructions),p=e.manifest.workspaceResourceRoot,m={channels:r,config:createResolvedAgentConfig(e.manifest),connections:u,disabledFrameworkChannels:i,disabledFrameworkTools:[...e.manifest.disabledFrameworkTools],workflowEnabled:e.manifest.workflowEnabled,dynamicInstructionsResolvers:o,dynamicSkillResolvers:s,dynamicToolResolvers:c,hooks:l,metadata:{agentRoot:e.manifest.agentRoot,appRoot:e.manifest.appRoot,diagnosticsSummary:e.manifest.diagnosticsSummary},sandbox:d,workspaceResourceRoot:p,skills:t,tools:a,workspaceSpec:{rootEntries:[...p.rootEntries]}};return f===void 0?m:{...m,instructions:f}}function createResolvedInstructions(e){if(e!==void 0)return{name:e.name,logicalPath:e.logicalPath,markdown:e.markdown,sourceId:e.sourceId,sourceKind:e.sourceKind}}function createResolvedAgentConfig(e){let n={model:e.config.model.source===void 0?{id:e.config.model.id,contextWindowTokens:e.config.model.contextWindowTokens,providerOptions:e.config.model.providerOptions}:{contextWindowTokens:e.config.model.contextWindowTokens,id:e.config.model.id,providerOptions:e.config.model.providerOptions,source:{exportName:e.config.model.source.exportName,sourceKind:`module`,logicalPath:e.config.model.source.logicalPath,sourceId:e.config.model.source.sourceId}},name:e.config.name};if(e.config.compaction!==void 0){let t={};e.config.compaction.model!==void 0&&(t.model=e.config.compaction.model.source===void 0?{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions}:{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions,source:{exportName:e.config.compaction.model.source.exportName,sourceKind:`module`,logicalPath:e.config.compaction.model.source.logicalPath,sourceId:e.config.compaction.model.source.sourceId}}),e.config.compaction.thresholdPercent!==void 0&&(t.thresholdPercent=e.config.compaction.thresholdPercent),n.compaction=t}return e.config.experimental!==void 0&&(n.experimental={workflow:e.config.experimental.workflow===void 0?void 0:{world:e.config.experimental.workflow.world}}),e.config.outputSchema!==void 0&&(n.outputSchema=e.config.outputSchema),e.config.reasoning!==void 0&&(n.reasoning=e.config.reasoning),e.config.source!==void 0&&(n.source=createResolvedModuleSourceRef(e.config.source)),n}export{ResolveAgentError,resolveAgent};
|
|
1
|
+
import{ResolveAgentError,createResolvedModuleSourceRef}from"#runtime/resolve-helpers.js";import{resolveChannelDefinition}from"#runtime/resolve-channel.js";import{resolveConnectionDefinition}from"#runtime/resolve-connection.js";import{resolveHookDefinition}from"#runtime/resolve-hook.js";import{resolveSandboxDefinition}from"#runtime/resolve-sandbox.js";import{resolveDynamicInstructionsDefinition}from"#runtime/resolve-dynamic-instructions.js";import{resolveDynamicSkillDefinition}from"#runtime/resolve-dynamic-skill.js";import{resolveDynamicToolDefinition}from"#runtime/resolve-dynamic-tool.js";import{resolveToolDefinition}from"#runtime/resolve-tool.js";async function resolveAgent(e){let t=e.manifest.skills.map(e=>({...e,metadata:e.metadata===void 0?void 0:{...e.metadata}})),r=[],i=[];for(let t of e.manifest.channels){if(t.kind===`disabled`){i.push(t.name);continue}r.push(await resolveChannelDefinition(t,e.moduleMap,e.nodeId))}let a=await Promise.all(e.manifest.tools.map(t=>resolveToolDefinition(t,e.moduleMap,e.nodeId))),o=await Promise.all((e.manifest.dynamicInstructions??[]).map(t=>resolveDynamicInstructionsDefinition(t,e.moduleMap,e.nodeId))),s=await Promise.all((e.manifest.dynamicSkills??[]).map(t=>resolveDynamicSkillDefinition(t,e.moduleMap,e.nodeId))),c=await Promise.all(e.manifest.dynamicTools.map(t=>resolveDynamicToolDefinition(t,e.moduleMap,e.nodeId))),l=await Promise.all(e.manifest.hooks.map(t=>resolveHookDefinition(t,e.moduleMap,e.nodeId))),u=await Promise.all(e.manifest.connections.map(t=>resolveConnectionDefinition(t,e.moduleMap,e.nodeId))),d=e.manifest.sandbox===null?null:await resolveSandboxDefinition(e.manifest.sandbox,e.moduleMap,e.nodeId),f=createResolvedInstructions(e.manifest.instructions),p=e.manifest.workspaceResourceRoot,m={channels:r,config:createResolvedAgentConfig(e.manifest),connections:u,disabledFrameworkChannels:i,disabledFrameworkTools:[...e.manifest.disabledFrameworkTools],workflowEnabled:e.manifest.workflowEnabled,dynamicInstructionsResolvers:o,dynamicSkillResolvers:s,dynamicToolResolvers:c,hooks:l,metadata:{agentRoot:e.manifest.agentRoot,appRoot:e.manifest.appRoot,diagnosticsSummary:e.manifest.diagnosticsSummary},sandbox:d,workspaceResourceRoot:p,skills:t,tools:a,workspaceSpec:{rootEntries:[...p.rootEntries]}};return f===void 0?m:{...m,instructions:f}}function createResolvedInstructions(e){if(e!==void 0)return{name:e.name,logicalPath:e.logicalPath,markdown:e.markdown,sourceId:e.sourceId,sourceKind:e.sourceKind}}function createResolvedAgentConfig(e){let n={model:e.config.model.source===void 0?{id:e.config.model.id,contextWindowTokens:e.config.model.contextWindowTokens,providerOptions:e.config.model.providerOptions}:{contextWindowTokens:e.config.model.contextWindowTokens,id:e.config.model.id,providerOptions:e.config.model.providerOptions,source:{exportName:e.config.model.source.exportName,sourceKind:`module`,logicalPath:e.config.model.source.logicalPath,sourceId:e.config.model.source.sourceId}},name:e.config.name};if(e.config.compaction!==void 0){let t={};e.config.compaction.model!==void 0&&(t.model=e.config.compaction.model.source===void 0?{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions}:{contextWindowTokens:e.config.compaction.model.contextWindowTokens,id:e.config.compaction.model.id,providerOptions:e.config.compaction.model.providerOptions,source:{exportName:e.config.compaction.model.source.exportName,sourceKind:`module`,logicalPath:e.config.compaction.model.source.logicalPath,sourceId:e.config.compaction.model.source.sourceId}}),e.config.compaction.thresholdPercent!==void 0&&(t.thresholdPercent=e.config.compaction.thresholdPercent),n.compaction=t}return e.config.experimental!==void 0&&(n.experimental={workflow:e.config.experimental.workflow===void 0?void 0:{world:e.config.experimental.workflow.world}}),e.config.outputSchema!==void 0&&(n.outputSchema=e.config.outputSchema),e.config.reasoning!==void 0&&(n.reasoning=e.config.reasoning),e.config.source!==void 0&&(n.source=createResolvedModuleSourceRef(e.config.source)),e.config.limits!==void 0&&(n.limits={maxSubagentDepth:e.config.limits.maxSubagentDepth,maxInputTokensPerSession:e.config.limits.maxInputTokensPerSession,maxOutputTokensPerSession:e.config.limits.maxOutputTokensPerSession}),n}export{ResolveAgentError,resolveAgent};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fetchGatewayModelIds}from"../gateway-models.js";function preflight(t){let n=t.deps??{fetchGatewayModelIds};return{id:`preflight`,async gather({state:e}){return t.headless?{model:e.modelId.length>0?e.modelId:null}:{model:null}},async perform({input:e}){return e.model!==null&&await validateModel(n,e.model,t.cwd),null},apply(e){return e}}}async function validateModel(e,t,n){let r=await e.fetchGatewayModelIds(n);if(!(r===null||r.has(t)))throw Error(`Model "${t}" is not in the AI Gateway catalog. Pass a model id from https://ai-gateway.vercel.sh/v1/models (e.g. anthropic/claude-sonnet-
|
|
1
|
+
import{fetchGatewayModelIds}from"../gateway-models.js";function preflight(t){let n=t.deps??{fetchGatewayModelIds};return{id:`preflight`,async gather({state:e}){return t.headless?{model:e.modelId.length>0?e.modelId:null}:{model:null}},async perform({input:e}){return e.model!==null&&await validateModel(n,e.model,t.cwd),null},apply(e){return e}}}async function validateModel(e,t,n){let r=await e.fetchGatewayModelIds(n);if(!(r===null||r.has(t)))throw Error(`Model "${t}" is not in the AI Gateway catalog. Pass a model id from https://ai-gateway.vercel.sh/v1/models (e.g. anthropic/claude-sonnet-5).`)}export{preflight};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{select}from"../ask.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";const POPULAR_PROVIDERS=[`anthropic`,`openai`,`google`];function modelOption(e,t,n,r=!0){return{id:e,label:t,value:e,hint:n,featured:r||void 0}}const FEATURED_MODEL_IDS=[DEFAULT_AGENT_MODEL_ID,`anthropic/claude-opus-4.8`,`openai/gpt-5.5`],FALLBACK_MODELS=[modelOption(DEFAULT_AGENT_MODEL_ID,`Claude Sonnet
|
|
1
|
+
import{select}from"../ask.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";const POPULAR_PROVIDERS=[`anthropic`,`openai`,`google`];function modelOption(e,t,n,r=!0){return{id:e,label:t,value:e,hint:n,featured:r||void 0}}const FEATURED_MODEL_IDS=[DEFAULT_AGENT_MODEL_ID,`anthropic/claude-opus-4.8`,`openai/gpt-5.5`],FALLBACK_MODELS=[modelOption(DEFAULT_AGENT_MODEL_ID,`Claude Sonnet 5`,`Anthropic`),modelOption(`anthropic/claude-opus-4.8`,`Claude Opus 4.8`,`Anthropic`),modelOption(`openai/gpt-5.5`,`GPT-5.5`,`OpenAI`),modelOption(`google/gemini-3.5`,`Gemini 3.5`,`Google`,!1)];function providerLabel(e){return e.length===0?``:e.charAt(0).toUpperCase()+e.slice(1)}function providerPriority(e){let t=POPULAR_PROVIDERS.indexOf(e);return t===-1?POPULAR_PROVIDERS.length:t}async function fetchGatewayCatalog(e){let t=new AbortController,n=setTimeout(()=>t.abort(),5e3);try{let n=e===void 0?t.signal:AbortSignal.any([e,t.signal]);return(await(await fetch(`https://ai-gateway.vercel.sh/v1/models`,{signal:n})).json()).data}finally{clearTimeout(n)}}function featuredPriority(e){let t=FEATURED_MODEL_IDS.indexOf(e);return t===-1?FEATURED_MODEL_IDS.length:t}async function buildModelOptions(e,t){try{let n=(await e(t)).filter(e=>e.type===`language`&&(e.tags??[]).includes(`web-search`)).map(e=>{let t=e.id.split(`/`)[0]??``;return{value:e.id,label:e.name,hint:providerLabel(t),provider:t}}).sort((e,t)=>{let n=featuredPriority(e.value)-featuredPriority(t.value);if(n!==0)return n;let r=providerPriority(e.provider)-providerPriority(t.provider);if(r!==0)return r;let i=e.provider.localeCompare(t.provider);return i===0?e.label.localeCompare(t.label):i});return n.length===0?FALLBACK_MODELS:n.map(({value:e,label:t,hint:n})=>({id:e,label:t,value:e,hint:n,featured:FEATURED_MODEL_IDS.includes(e)||void 0}))}catch{return t?.throwIfAborted(),FALLBACK_MODELS}}function selectModel(n){let r=n.deps??{fetchModels:fetchGatewayCatalog};return{id:`select-model`,async gather({signal:i}){let a=n.presetModel;if(a!==void 0&&a.length>0)return a;let o=await buildModelOptions(r.fetchModels,i),s=n.defaultModel!==void 0&&o.some(e=>e.value===n.defaultModel)?n.defaultModel:o.some(e=>e.value===DEFAULT_AGENT_MODEL_ID)?DEFAULT_AGENT_MODEL_ID:o[0]?.value;return n.asker.ask(select({key:`model`,message:`Which model should your agent use?`,options:o,recommended:s,required:!0,search:!0,placeholder:`type to search`}))},async perform({input:e}){return e},apply(e,t){return{...e,modelId:t}}}}export{fetchGatewayCatalog,selectModel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{AI_GATEWAY_API_KEY_ENV_VAR}from"../ai-gateway-api-key.js";import{interactiveAsker}from"../ask.js";import{detectProjectIdentity}from"../project-resolution.js";import{snapshotSetupState}from"../state.js";import{WizardCancelledError}from"../step.js";import{withSpinner}from"../with-spinner.js";import{findEnvFileWithKey}from"../boxes/detect-ai-gateway.js";import{fetchGatewayCatalog,selectModel}from"../boxes/select-model.js";import{runInteractive}from"../runner.js";import{inProjectSetupState,prompterSink}from"./in-project.js";import{runProviderFlow}from"./provider.js";import{join}from"node:path";import{discoverAgent}from"#discover/discover-agent.js";import{inspectApplication}from"#services/inspect-application.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{createCompiledRuntimeModelCatalogLoader}from"#compiler/model-catalog.js";import{createStaticSourceChange}from"#source-change/static-source-change.js";var import_picocolors=__toESM(require_picocolors(),1);const MODEL_MENU_MESSAGE=``;function providerStatusHint(e,t=e=>e){return e.kind===`gateway-project`?`AI Gateway (Linked to ${e.teamName===void 0?t(e.projectName):`${t(e.projectName)} in ${t(e.teamName)}`})`:`AI Gateway (${e.envKey} in ${e.envFile})`}function modelMenuRows(e,t,n,r){let i;r?(i={value:`model`,label:`Change model`,description:`The model your agent uses`},e!==null&&(i.hint=e)):i={value:`model`,label:`Change model`,disabled:!0,description:`Set via an SDK model call in agent.ts; edit the source to change it`};let a;return a=n?.kind===`external`?{disabled:!0,value:`provider`,label:`Change provider`,description:`Disabled in external endpoint mode`}:t.kind===`unset`?{value:`provider`,label:import_picocolors.default.bold(`Configure model access`),hint:import_picocolors.default.yellow(`Not configured`),description:`How your agent reaches the model provider`,accent:`warning`}:{value:`provider`,label:`Change provider`,hint:providerStatusHint(t,import_picocolors.default.bold),description:`How your agent reaches the model provider`},[i,a,{value:`done`,label:`Done`,description:`Return to the prompt`}]}async function detectModelProviderStatus(e,t={}){let[r,a,o]=await Promise.all([detectProjectIdentity(e,t),findEnvFileWithKey(e,AI_GATEWAY_API_KEY_ENV_VAR),findEnvFileWithKey(e,`VERCEL_OIDC_TOKEN`)]);if(r!==void 0){let e={kind:`gateway-project`,projectName:r.projectName};return r.teamName!==void 0&&(e.teamName=r.teamName),e}return a===void 0?o===void 0?{kind:`unset`}:{kind:`gateway-key`,envKey:`VERCEL_OIDC_TOKEN`,envFile:o}:{kind:`gateway-key`,envKey:AI_GATEWAY_API_KEY_ENV_VAR,envFile:a}}async function runModelFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i={readCurrentModel:readCurrentAgentModel,applyModel:changeAgentModel,detectProviderStatus:detectModelProviderStatus,runProviderFlow,...e.deps},detectProvider=(e=!0)=>i.detectProviderStatus(t,e&&r!==void 0?{signal:r}:{}),[{id:a,routing:s,editable:c},l]=await withSpinner(n,`Checking the project…`,()=>Promise.all([i.readCurrentModel(t),detectProvider()]));r?.throwIfAborted();let u,d,f=s?.kind===`external`?{tone:`warning`,text:"`agent.ts` specifies a model provider directly. In-TUI configuration is restricted to AI Gateway endpoints."}:void 0,m=l.kind===`unset`&&s?.kind!==`external`?`provider`:c?`model`:s?.kind===`external`?`done`:`provider`,h=s?.kind!==`external`&&(e.initialStep===`provider`||l.kind===`unset`);for(;;){let e;if(h)h=!1,e=`provider`;else try{e=await n.select({message:``,options:modelMenuRows(a,l,s,c),hintLayout:`stacked`,initialValue:m,notices:f===void 0?[]:[f]})}catch(e){if(!(e instanceof WizardCancelledError))throw e;break}if(e===`done`)break;if(e===`model`){let e=await pickModelFromCatalog({appRoot:t,prompter:n,current:a,signal:r,deps:i.selectModel});if(e===void 0){m=`model`;continue}r?.throwIfAborted(),u=await i.applyModel({appRoot:t,slug:e}),r?.throwIfAborted();break}let p=await i.runProviderFlow({appRoot:t,prompter:n,signal:r});if(p.kind===`cancelled`){if(r?.aborted)return{kind:`cancelled`};m=`provider`;continue}if(p.kind===`external-provider`){if(r?.aborted)return{kind:`cancelled`};m=`done`;continue}l=await withSpinner(n,`Checking the project…`,()=>detectProvider(!1)),d={status:l},p.credential!==void 0&&(d.credential=p.credential);break}if(u===void 0&&d===void 0)return{kind:`cancelled`};let g={kind:`done`};return u!==void 0&&(g.modelMessage=formatApplyModelOutcome(u)),d!==void 0&&(g.providerOutcome=d),g}async function pickModelFromCatalog(e){let{appRoot:t,prompter:n,current:i,signal:o}=e,s=e.deps?.fetchModels??fetchGatewayCatalog,p={asker:interactiveAsker(n),deps:{fetchModels:e=>withSpinner(n,`Loading the model catalog...`,()=>s(e))}};i!==null&&(p.defaultModel=i);let m=await runInteractive([selectModel(p)],inProjectSetupState(t,{kind:`unresolved`}),prompterSink(n),{snapshot:snapshotSetupState,signal:o});return m.kind===`cancelled`?void 0:m.state.modelId}function formatApplyModelOutcome(e){switch(e.kind){case`changed`:return`Model changed to ${import_picocolors.default.bold(e.to)}. Live on your next prompt.`;case`unchanged`:return`Model is already \`${e.model}\`.`;case`rejected`:return e.message}}async function changeAgentModel(e){let{appRoot:t,slug:n}=e,r=await validateModelSlug(t,n);if(r!==null)return{kind:`rejected`,message:r};let{manifest:i}=await discoverAgent({agentRoot:join(t,`agent`),appRoot:t}),a=await createStaticSourceChange(i).updateModelName(n);return a.kind===`bail`?{kind:`rejected`,message:`Couldn't edit ${a.at.logicalPath}: ${a.reason}. Change \`model\` by hand.`}:a.from===a.to?{kind:`unchanged`,model:a.to}:{kind:`changed`,to:a.to}}async function validateModelSlug(e,t){if(!t.includes(`/`))return`\`${t}\` isn't a provider/model id (e.g. anthropic/claude-sonnet-
|
|
1
|
+
import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{AI_GATEWAY_API_KEY_ENV_VAR}from"../ai-gateway-api-key.js";import{interactiveAsker}from"../ask.js";import{detectProjectIdentity}from"../project-resolution.js";import{snapshotSetupState}from"../state.js";import{WizardCancelledError}from"../step.js";import{withSpinner}from"../with-spinner.js";import{findEnvFileWithKey}from"../boxes/detect-ai-gateway.js";import{fetchGatewayCatalog,selectModel}from"../boxes/select-model.js";import{runInteractive}from"../runner.js";import{inProjectSetupState,prompterSink}from"./in-project.js";import{runProviderFlow}from"./provider.js";import{join}from"node:path";import{discoverAgent}from"#discover/discover-agent.js";import{inspectApplication}from"#services/inspect-application.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{createCompiledRuntimeModelCatalogLoader}from"#compiler/model-catalog.js";import{createStaticSourceChange}from"#source-change/static-source-change.js";var import_picocolors=__toESM(require_picocolors(),1);const MODEL_MENU_MESSAGE=``;function providerStatusHint(e,t=e=>e){return e.kind===`gateway-project`?`AI Gateway (Linked to ${e.teamName===void 0?t(e.projectName):`${t(e.projectName)} in ${t(e.teamName)}`})`:`AI Gateway (${e.envKey} in ${e.envFile})`}function modelMenuRows(e,t,n,r){let i;r?(i={value:`model`,label:`Change model`,description:`The model your agent uses`},e!==null&&(i.hint=e)):i={value:`model`,label:`Change model`,disabled:!0,description:`Set via an SDK model call in agent.ts; edit the source to change it`};let a;return a=n?.kind===`external`?{disabled:!0,value:`provider`,label:`Change provider`,description:`Disabled in external endpoint mode`}:t.kind===`unset`?{value:`provider`,label:import_picocolors.default.bold(`Configure model access`),hint:import_picocolors.default.yellow(`Not configured`),description:`How your agent reaches the model provider`,accent:`warning`}:{value:`provider`,label:`Change provider`,hint:providerStatusHint(t,import_picocolors.default.bold),description:`How your agent reaches the model provider`},[i,a,{value:`done`,label:`Done`,description:`Return to the prompt`}]}async function detectModelProviderStatus(e,t={}){let[r,a,o]=await Promise.all([detectProjectIdentity(e,t),findEnvFileWithKey(e,AI_GATEWAY_API_KEY_ENV_VAR),findEnvFileWithKey(e,`VERCEL_OIDC_TOKEN`)]);if(r!==void 0){let e={kind:`gateway-project`,projectName:r.projectName};return r.teamName!==void 0&&(e.teamName=r.teamName),e}return a===void 0?o===void 0?{kind:`unset`}:{kind:`gateway-key`,envKey:`VERCEL_OIDC_TOKEN`,envFile:o}:{kind:`gateway-key`,envKey:AI_GATEWAY_API_KEY_ENV_VAR,envFile:a}}async function runModelFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i={readCurrentModel:readCurrentAgentModel,applyModel:changeAgentModel,detectProviderStatus:detectModelProviderStatus,runProviderFlow,...e.deps},detectProvider=(e=!0)=>i.detectProviderStatus(t,e&&r!==void 0?{signal:r}:{}),[{id:a,routing:s,editable:c},l]=await withSpinner(n,`Checking the project…`,()=>Promise.all([i.readCurrentModel(t),detectProvider()]));r?.throwIfAborted();let u,d,f=s?.kind===`external`?{tone:`warning`,text:"`agent.ts` specifies a model provider directly. In-TUI configuration is restricted to AI Gateway endpoints."}:void 0,m=l.kind===`unset`&&s?.kind!==`external`?`provider`:c?`model`:s?.kind===`external`?`done`:`provider`,h=s?.kind!==`external`&&(e.initialStep===`provider`||l.kind===`unset`);for(;;){let e;if(h)h=!1,e=`provider`;else try{e=await n.select({message:``,options:modelMenuRows(a,l,s,c),hintLayout:`stacked`,initialValue:m,notices:f===void 0?[]:[f]})}catch(e){if(!(e instanceof WizardCancelledError))throw e;break}if(e===`done`)break;if(e===`model`){let e=await pickModelFromCatalog({appRoot:t,prompter:n,current:a,signal:r,deps:i.selectModel});if(e===void 0){m=`model`;continue}r?.throwIfAborted(),u=await i.applyModel({appRoot:t,slug:e}),r?.throwIfAborted();break}let p=await i.runProviderFlow({appRoot:t,prompter:n,signal:r});if(p.kind===`cancelled`){if(r?.aborted)return{kind:`cancelled`};m=`provider`;continue}if(p.kind===`external-provider`){if(r?.aborted)return{kind:`cancelled`};m=`done`;continue}l=await withSpinner(n,`Checking the project…`,()=>detectProvider(!1)),d={status:l},p.credential!==void 0&&(d.credential=p.credential);break}if(u===void 0&&d===void 0)return{kind:`cancelled`};let g={kind:`done`};return u!==void 0&&(g.modelMessage=formatApplyModelOutcome(u)),d!==void 0&&(g.providerOutcome=d),g}async function pickModelFromCatalog(e){let{appRoot:t,prompter:n,current:i,signal:o}=e,s=e.deps?.fetchModels??fetchGatewayCatalog,p={asker:interactiveAsker(n),deps:{fetchModels:e=>withSpinner(n,`Loading the model catalog...`,()=>s(e))}};i!==null&&(p.defaultModel=i);let m=await runInteractive([selectModel(p)],inProjectSetupState(t,{kind:`unresolved`}),prompterSink(n),{snapshot:snapshotSetupState,signal:o});return m.kind===`cancelled`?void 0:m.state.modelId}function formatApplyModelOutcome(e){switch(e.kind){case`changed`:return`Model changed to ${import_picocolors.default.bold(e.to)}. Live on your next prompt.`;case`unchanged`:return`Model is already \`${e.model}\`.`;case`rejected`:return e.message}}async function changeAgentModel(e){let{appRoot:t,slug:n}=e,r=await validateModelSlug(t,n);if(r!==null)return{kind:`rejected`,message:r};let{manifest:i}=await discoverAgent({agentRoot:join(t,`agent`),appRoot:t}),a=await createStaticSourceChange(i).updateModelName(n);return a.kind===`bail`?{kind:`rejected`,message:`Couldn't edit ${a.at.logicalPath}: ${a.reason}. Change \`model\` by hand.`}:a.from===a.to?{kind:`unchanged`,model:a.to}:{kind:`changed`,to:a.to}}async function validateModelSlug(e,t){if(!t.includes(`/`))return`\`${t}\` isn't a provider/model id (e.g. anthropic/claude-sonnet-5).`;let n=createCompiledRuntimeModelCatalogLoader(e);try{if(await n.getModelLimits(formatLanguageModelGatewayId(t))===null)return`I couldn't confirm \`${t}\` in the AI Gateway model catalog, so I didn't change agent.ts.`}catch{return null}return null}async function readCurrentAgentModel(e){try{let{compiledState:t}=await inspectApplication(e),n=t?.manifest.config.model;return{id:n?.id??null,routing:n?.routing??null,editable:n!==void 0&&n.source===void 0}}catch{return{id:null,routing:null,editable:!1}}}async function modelChangeRefusalForUneditableModel(e){let{editable:t,routing:n}=await readCurrentAgentModel(e);return t?null:`Model is set via ${n?.kind===`external`?`the external provider \`${n.provider}\``:`an SDK model call`} in agent.ts, not a string literal; /model can't rewrite it. Edit \`model\` in agent.ts.`}export{MODEL_MENU_MESSAGE,changeAgentModel,detectModelProviderStatus,formatApplyModelOutcome,modelChangeRefusalForUneditableModel,runModelFlow};
|
|
@@ -21,7 +21,7 @@ export declare const DEFAULT_EVE_PACKAGE_CONTRACT: EvePackageContract;
|
|
|
21
21
|
export declare function resolveEvePackageContract(contract?: EvePackageContract): EvePackageContract;
|
|
22
22
|
/**
|
|
23
23
|
* Provider slug a gateway model id routes through: the segment before the
|
|
24
|
-
* first "/" (e.g. `anthropic/claude-sonnet-
|
|
24
|
+
* first "/" (e.g. `anthropic/claude-sonnet-5` → `anthropic`). The slug is
|
|
25
25
|
* injected into generated source, so characters outside the catalog's slug
|
|
26
26
|
* alphabet are dropped; an id without a usable prefix falls back to
|
|
27
27
|
* `anthropic`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.0`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.17.
|
|
1
|
+
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.0`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.17.2`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
|
|
2
2
|
|
|
3
3
|
export default defineAgent({
|
|
4
4
|
model: "__EVE_INIT_MODEL__",
|
|
@@ -39,8 +39,11 @@ export declare const WEB_APP_TEMPLATE_FILES: {
|
|
|
39
39
|
export declare const WEB_APP_TEMPLATE_PACKAGE_JSON: {
|
|
40
40
|
readonly scripts: {
|
|
41
41
|
readonly build: "next build";
|
|
42
|
+
readonly "build:eve": "eve build";
|
|
42
43
|
readonly dev: "next dev";
|
|
44
|
+
readonly "dev:eve": "eve dev";
|
|
43
45
|
readonly start: "next start";
|
|
46
|
+
readonly "start:eve": "eve start";
|
|
44
47
|
readonly typecheck: "tsc --noEmit -p tsconfig.json";
|
|
45
48
|
};
|
|
46
49
|
readonly dependencies: {
|
|
@@ -4798,4 +4798,4 @@ export default config;
|
|
|
4798
4798
|
],
|
|
4799
4799
|
"exclude": ["node_modules"]
|
|
4800
4800
|
}
|
|
4801
|
-
`},WEB_APP_TEMPLATE_PACKAGE_JSON={scripts:{build:`next build`,dev:`next dev`,start:`next start`,typecheck:`tsc --noEmit -p tsconfig.json`},dependencies:{"@radix-ui/react-use-controllable-state":`1.2.2`,"@shikijs/core":`4.1.0`,"@shikijs/engine-javascript":`4.1.0`,"@shikijs/engine-oniguruma":`4.1.0`,"@streamdown/cjk":`1.0.3`,"@streamdown/code":`1.1.1`,"@streamdown/math":`1.0.2`,"@streamdown/mermaid":`1.0.2`,"@tailwindcss/postcss":`4.3.0`,ai:`catalog:`,"class-variance-authority":`0.7.1`,clsx:`2.1.1`,cmdk:`1.1.1`,eve:`workspace:*`,"lucide-react":`1.16.0`,motion:`12.40.0`,nanoid:`5.1.11`,next:`catalog:`,"radix-ui":`1.4.3`,react:`catalog:`,"react-dom":`catalog:`,shiki:`4.1.0`,streamdown:`catalog:`,"tailwind-merge":`3.6.0`,tailwindcss:`4.3.0`,"use-stick-to-bottom":`1.1.4`,zod:`catalog:`},devDependencies:{"@types/node":`catalog:`,"@types/react":`catalog:`,"@types/react-dom":`catalog:`,typescript:`6.0.3`}};export{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON};
|
|
4801
|
+
`},WEB_APP_TEMPLATE_PACKAGE_JSON={scripts:{build:`next build`,"build:eve":`eve build`,dev:`next dev`,"dev:eve":`eve dev`,start:`next start`,"start:eve":`eve start`,typecheck:`tsc --noEmit -p tsconfig.json`},dependencies:{"@radix-ui/react-use-controllable-state":`1.2.2`,"@shikijs/core":`4.1.0`,"@shikijs/engine-javascript":`4.1.0`,"@shikijs/engine-oniguruma":`4.1.0`,"@streamdown/cjk":`1.0.3`,"@streamdown/code":`1.1.1`,"@streamdown/math":`1.0.2`,"@streamdown/mermaid":`1.0.2`,"@tailwindcss/postcss":`4.3.0`,ai:`catalog:`,"class-variance-authority":`0.7.1`,clsx:`2.1.1`,cmdk:`1.1.1`,eve:`workspace:*`,"lucide-react":`1.16.0`,motion:`12.40.0`,nanoid:`5.1.11`,next:`catalog:`,"radix-ui":`1.4.3`,react:`catalog:`,"react-dom":`catalog:`,shiki:`4.1.0`,streamdown:`catalog:`,"tailwind-merge":`3.6.0`,tailwindcss:`4.3.0`,"use-stick-to-bottom":`1.1.4`,zod:`catalog:`},devDependencies:{"@types/node":`catalog:`,"@types/react":`catalog:`,"@types/react-dom":`catalog:`,typescript:`6.0.3`}};export{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON};
|
|
@@ -93,6 +93,38 @@ export interface PublicAgentCompactionDefinition {
|
|
|
93
93
|
*/
|
|
94
94
|
readonly thresholdPercent?: number;
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Configures framework-owned runtime limits for this agent's runs.
|
|
98
|
+
*/
|
|
99
|
+
export interface AgentLimitsDefinition {
|
|
100
|
+
/**
|
|
101
|
+
* Maximum number of delegated child-session levels from the root session.
|
|
102
|
+
*
|
|
103
|
+
* Root sessions are depth 0. A `maxSubagentDepth` of 3 allows child sessions at
|
|
104
|
+
* depths 1, 2, and 3; sessions already at depth 3 cannot delegate again.
|
|
105
|
+
*
|
|
106
|
+
* @default 3
|
|
107
|
+
*/
|
|
108
|
+
readonly maxSubagentDepth?: number;
|
|
109
|
+
/**
|
|
110
|
+
* Maximum provider-reported input tokens accumulated by one durable session.
|
|
111
|
+
*
|
|
112
|
+
* eve checks this before starting each model call. The model call that crosses
|
|
113
|
+
* the limit is allowed to finish because providers only report exact usage
|
|
114
|
+
* after the call completes; later model calls in the same session are blocked.
|
|
115
|
+
*
|
|
116
|
+
* @default 40_000_000 for root sessions; 5_000_000 for delegated subagent sessions
|
|
117
|
+
*/
|
|
118
|
+
readonly maxInputTokensPerSession?: number;
|
|
119
|
+
/**
|
|
120
|
+
* Maximum provider-reported output tokens accumulated by one durable session.
|
|
121
|
+
*
|
|
122
|
+
* eve checks this before starting each model call. The model call that crosses
|
|
123
|
+
* the limit is allowed to finish because providers only report exact usage
|
|
124
|
+
* after the call completes; later model calls in the same session are blocked.
|
|
125
|
+
*/
|
|
126
|
+
readonly maxOutputTokensPerSession?: number;
|
|
127
|
+
}
|
|
96
128
|
/**
|
|
97
129
|
* Experimental, opt-in agent capabilities authored in `agent.ts`.
|
|
98
130
|
*
|
|
@@ -155,6 +187,7 @@ export type InternalAgentDefinition = {
|
|
|
155
187
|
outputSchema?: JsonObject;
|
|
156
188
|
reasoning?: AgentReasoningDefinition;
|
|
157
189
|
source?: ModuleSourceRef;
|
|
190
|
+
limits?: AgentLimitsDefinition;
|
|
158
191
|
};
|
|
159
192
|
/**
|
|
160
193
|
* Shared public definition for an agent.
|
|
@@ -197,6 +230,10 @@ export type PublicAgentDefinition = {
|
|
|
197
230
|
* Support for individual levels depends on the selected model and provider.
|
|
198
231
|
*/
|
|
199
232
|
readonly reasoning?: AgentReasoningDefinition;
|
|
233
|
+
/**
|
|
234
|
+
* Framework-owned runtime limits for this agent's runs.
|
|
235
|
+
*/
|
|
236
|
+
readonly limits?: AgentLimitsDefinition;
|
|
200
237
|
/**
|
|
201
238
|
* Optional structured return type used when this agent runs in task mode
|
|
202
239
|
* (for example as a subagent, schedule, or remote job). Interactive
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
* Model used when an agent does not declare one, baked in by `eve init`, and
|
|
3
3
|
* pre-selected in the setup model picker.
|
|
4
4
|
*/
|
|
5
|
-
export declare const DEFAULT_AGENT_MODEL_ID = "anthropic/claude-sonnet-
|
|
5
|
+
export declare const DEFAULT_AGENT_MODEL_ID = "anthropic/claude-sonnet-5";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const DEFAULT_AGENT_MODEL_ID=`anthropic/claude-sonnet-
|
|
1
|
+
const DEFAULT_AGENT_MODEL_ID=`anthropic/claude-sonnet-5`;export{DEFAULT_AGENT_MODEL_ID};
|
package/docs/agent-config.md
CHANGED
|
@@ -18,7 +18,7 @@ export default defineAgent({
|
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
The root `agent.ts` can be omitted when no runtime config is needed. In that case, eve defaults
|
|
21
|
-
to `anthropic/claude-sonnet-
|
|
21
|
+
to `anthropic/claude-sonnet-5`. When `agent.ts` is present, `model` is required.
|
|
22
22
|
|
|
23
23
|
`model` accepts a gateway model id string, which routes through the [Vercel AI Gateway](https://vercel.com/docs/ai-gateway). To call a provider directly and configure the model in code, pass a provider-authored `LanguageModel`.
|
|
24
24
|
|
|
@@ -75,6 +75,32 @@ export default defineAgent({
|
|
|
75
75
|
|
|
76
76
|
See [Default harness](./concepts/default-harness#compaction) for how the loop applies it.
|
|
77
77
|
|
|
78
|
+
## Runtime limits
|
|
79
|
+
|
|
80
|
+
Use `limits` for framework-owned runtime caps. Session token limits stop the
|
|
81
|
+
current durable session from starting another model call after accumulated
|
|
82
|
+
provider-reported input or output token usage reaches the configured limit:
|
|
83
|
+
|
|
84
|
+
```ts title="agent/agent.ts"
|
|
85
|
+
export default defineAgent({
|
|
86
|
+
model: "anthropic/claude-opus-4.8",
|
|
87
|
+
limits: {
|
|
88
|
+
maxInputTokensPerSession: 200_000,
|
|
89
|
+
maxOutputTokensPerSession: 20_000,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Input and output budgets are checked independently. The model call that crosses
|
|
95
|
+
either limit is allowed to finish because providers only report exact token
|
|
96
|
+
usage after a call completes. Follow-up model calls in the same session fail
|
|
97
|
+
with `SESSION_TOKEN_LIMIT_REACHED`.
|
|
98
|
+
|
|
99
|
+
When `maxInputTokensPerSession` is omitted, eve applies a default input budget:
|
|
100
|
+
`40_000_000` provider-reported input tokens for root sessions and `5_000_000`
|
|
101
|
+
for delegated subagent sessions. `maxOutputTokensPerSession` is unset unless
|
|
102
|
+
configured.
|
|
103
|
+
|
|
78
104
|
## Workflow world
|
|
79
105
|
|
|
80
106
|
By default, eve selects the Workflow SDK world for the host: Vercel Workflow on
|
|
@@ -116,13 +142,14 @@ installed package must stay external in hosted output, list it in
|
|
|
116
142
|
|
|
117
143
|
`defineAgent` takes a few more fields, all optional. For the exported types, see the [TypeScript API](./reference/typescript-api).
|
|
118
144
|
|
|
119
|
-
| Field | Type | Default | Description
|
|
120
|
-
| -------------- | --------------------------------------- | ---------------- |
|
|
121
|
-
| `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls.
|
|
122
|
-
| `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call.
|
|
123
|
-
| `
|
|
124
|
-
| `
|
|
125
|
-
| `
|
|
145
|
+
| Field | Type | Default | Description |
|
|
146
|
+
| -------------- | --------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
147
|
+
| `reasoning` | `AgentReasoningDefinition` | provider default | Provider-agnostic reasoning effort forwarded to the agent's turn model calls. |
|
|
148
|
+
| `modelOptions` | `AgentModelOptionsDefinition` | none | Provider option overrides forwarded to the model call. |
|
|
149
|
+
| `limits` | `AgentLimitsDefinition` | field-specific | Framework-owned runtime limits. `maxSubagentDepth` defaults to `3`; `maxInputTokensPerSession` defaults to `40_000_000` for root sessions and `5_000_000` for delegated subagent sessions; `maxOutputTokensPerSession` is unset unless configured. |
|
|
150
|
+
| `experimental` | `{ workflow?: { world?: string } }` | unset | Opt-in settings that can change or disappear in any release. Treat them as unstable. `workflow.world` selects the Workflow world package backing session state, queues, hooks, and streams on the root agent. |
|
|
151
|
+
| `outputSchema` | Standard Schema or a JSON Schema object | none | Structured return type for task-mode runs (a subagent, schedule, or remote job). Interactive conversation turns ignore it unless the client supplies a per-message schema. |
|
|
152
|
+
| `build` | `{ externalDependencies?: string[] }` | none | Hosted-build packaging controls. `externalDependencies` keeps listed packages external while eve compiles authored modules such as tools and channels, and traces those packages into the hosted output. |
|
|
126
153
|
|
|
127
154
|
`externalDependencies` is a packaging control only. It keeps selected packages as runtime dependencies in the hosted output; it does not authorize, configure, or review any third-party service those packages may call.
|
|
128
155
|
|
package/docs/channels/eve.mdx
CHANGED
|
@@ -18,9 +18,10 @@ export default eveChannel({
|
|
|
18
18
|
|
|
19
19
|
## Routes
|
|
20
20
|
|
|
21
|
-
The
|
|
21
|
+
The application exposes a health route plus eve channel routes that inspect the agent, create sessions, send follow-ups, and stream events:
|
|
22
22
|
|
|
23
23
|
- `GET /eve/v1/health`
|
|
24
|
+
- `GET /eve/v1/info`
|
|
24
25
|
- `POST /eve/v1/session` (start a session)
|
|
25
26
|
- `POST /eve/v1/session/:sessionId` (send a follow-up)
|
|
26
27
|
- `GET /eve/v1/session/:sessionId/stream` (stream events, NDJSON)
|
|
@@ -70,7 +71,7 @@ export default eveChannel({
|
|
|
70
71
|
|
|
71
72
|
## Authentication
|
|
72
73
|
|
|
73
|
-
The `auth` option decides who can call
|
|
74
|
+
The `auth` option decides who can call `/eve/v1/info` and the session routes. The built-in helpers cover development and trusted infrastructure:
|
|
74
75
|
|
|
75
76
|
- `localDev()` accepts requests during local development.
|
|
76
77
|
- `vercelOidc()` lets the local CLI reach a deployed agent, and lets other internal deployments from your team call it.
|