eve 0.16.1 → 0.17.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.
- package/CHANGELOG.md +16 -0
- package/dist/src/harness/types.d.ts +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/schema-backed.js +1 -1
- package/dist/src/internal/workflow/runtime.js +1 -1
- package/dist/src/public/channels/telegram/api.d.ts +3 -0
- package/dist/src/public/channels/telegram/api.js +2 -2
- package/dist/src/public/channels/telegram/inbound.d.ts +2 -0
- package/dist/src/public/channels/telegram/inbound.js +1 -1
- package/dist/src/public/channels/telegram/index.js +1 -1
- package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
- package/dist/src/public/definitions/tool.d.ts +0 -33
- package/dist/src/public/definitions/tool.js +1 -1
- package/dist/src/public/tools/index.d.ts +1 -1
- package/dist/src/public/tools/index.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/docs/channels/telegram.mdx +2 -0
- package/docs/concepts/default-harness.md +0 -10
- package/docs/guides/meta.json +0 -1
- package/docs/guides/remote-agents.md +0 -1
- package/docs/reference/typescript-api.md +26 -26
- package/docs/subagents.mdx +0 -1
- package/package.json +1 -1
- package/docs/guides/dynamic-workflows.md +0 -70
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.17.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 02ed501: Remove the experimental `ExperimentalWorkflow` opt-in marker from the public `eve/tools` API and remove the dynamic Workflow docs. The internal runtime path remains in place for existing compiled manifests, but authored apps can no longer enable the tool through the public API.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 6dc84fc: Keep Telegram proactive private chat sessions keyed to their chat or topic after outbound sends, while group and supergroup proactive sends still anchor to the bot message id.
|
|
12
|
+
|
|
13
|
+
## 0.16.2
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 9580a88: Disable the Workflow SDK turbo first-delivery path for eve. Workflow runs now stay on the fully ordered runtime path instead of the beta turbo mode.
|
|
18
|
+
|
|
3
19
|
## 0.16.1
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -171,7 +171,7 @@ export interface ToolLoopHarnessConfig {
|
|
|
171
171
|
* Exposes the `Workflow` orchestration tool — an isolated JavaScript sandbox
|
|
172
172
|
* whose only callable operations are this agent's subagents and remote
|
|
173
173
|
* agents. Resolved by the runtime from the agent's `workflowEnabled` flag
|
|
174
|
-
*
|
|
174
|
+
* in the compiled manifest.
|
|
175
175
|
* Defaults to `false`.
|
|
176
176
|
*/
|
|
177
177
|
readonly workflow?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire}from"node:module";import{existsSync,readFileSync,realpathSync}from"node:fs";import{basename,dirname,join}from"node:path";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const BUNDLED_FALLBACK_PACKAGE_VERSION=`0.
|
|
1
|
+
import{createRequire}from"node:module";import{existsSync,readFileSync,realpathSync}from"node:fs";import{basename,dirname,join}from"node:path";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const BUNDLED_FALLBACK_PACKAGE_VERSION=`0.17.0`,WORKFLOW_MODULE_ALIASES={"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`};function resolveFallbackPackageVersion(){return BUNDLED_FALLBACK_PACKAGE_VERSION.startsWith(`__`)?`0.0.0`:BUNDLED_FALLBACK_PACKAGE_VERSION}const FALLBACK_PACKAGE_INFO={name:EVE_PACKAGE_NAME,version:resolveFallbackPackageVersion()};function resolveCurrentModulePath(){return typeof __filename==`string`?__filename:resolveCurrentModulePathFromStack()}function resolveCurrentModulePathFromStack(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(e,t)=>t;let e=Error().stack?.[0]?.getFileName();if(typeof e!=`string`||e.length===0)throw Error(`Failed to resolve the current module path from the stack trace.`);return e.startsWith(`file:`)?fileURLToPath(e):e}finally{Error.prepareStackTrace=e}}const require=createRequire(resolveCurrentModulePath());function isBuildOutputPackageRoot(e){return basename(e)===`dist`&&existsSync(join(dirname(e),`package.json`))}function resolvePackageBuildRoot(){let e=dirname(realpathSync(resolveCurrentModulePath()));for(;;){if(isBuildOutputPackageRoot(e))return e;let t=dirname(e);if(t===e)return null;e=t}}function findNearestPackageRoot(e){let n=e;for(;;){if(existsSync(join(n,`package.json`))&&!isBuildOutputPackageRoot(n))return n;let r=dirname(n);if(r===n)throw Error(`Failed to resolve package root from "${e}".`);n=r}}function resolvePackageRoot(){return findNearestPackageRoot(dirname(realpathSync(resolveCurrentModulePath())))}function tryResolvePackageRoot(){try{return resolvePackageRoot()}catch{return}}function rewriteSourceFilePathForBuild(e){return e.replace(/\.[cm]?tsx?$/,`.js`)}function resolvePackageSourceFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),e):join(t,rewriteSourceFilePathForBuild(e))}function resolvePackageSourceDirectoryPath(e){let t=resolvePackageBuildRoot();return join(t===null?resolvePackageRoot():t,e)}function resolvePackageDependencyPath(e){return require.resolve(e)}function resolvePackageCompiledFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),`.generated`,`compiled`,e.replace(/^src\/compiled\//,``)):join(t,e)}function normalizeInstalledPackageInfo(e){let t=e;if(!(typeof t.name!=`string`||typeof t.version!=`string`))return{name:t.name,version:t.version}}function tryReadInstalledPackageInfo(e,t){let r=normalizeInstalledPackageInfo(JSON.parse(readFileSync(e,`utf8`)));if(r?.name===t)return r}function resolveInstalledPackageInfo(){if(cachedPackageInfo)return cachedPackageInfo;let e=tryResolvePackageRoot(),t=e===void 0?void 0:tryReadInstalledPackageInfo(join(e,`package.json`),EVE_PACKAGE_NAME);if(t)return cachedPackageInfo=t,cachedPackageInfo;try{let e=tryReadInstalledPackageInfo(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),EVE_PACKAGE_NAME);if(e)return cachedPackageInfo=e,cachedPackageInfo}catch{}return cachedPackageInfo={...FALLBACK_PACKAGE_INFO},cachedPackageInfo}function readWorkflowVersionFromManifest(e){let t=e;for(let e of[t.devDependencies,t.dependencies,t.peerDependencies]){let t=e?.[`@workflow/core`];if(typeof t==`string`&&t.trim().length>0)return t}}function resolveExpectedWorkflowVersion(){let e=tryResolvePackageRoot();if(e!==void 0)try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(join(e,`package.json`),`utf8`)))}catch{}try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),`utf8`)))}catch{return}}function resolveWorkflowModulePath(e){if(e===`workflow`)return resolvePackageSourceFilePath(`src/internal/workflow/index.ts`);if(e===`workflow/api`||e===`workflow/runtime`)return resolvePackageSourceFilePath(`src/internal/workflow/runtime.ts`);if(e===`workflow/internal/builtins`)return resolvePackageSourceFilePath(`src/internal/workflow/builtins.ts`);let t=WORKFLOW_MODULE_ALIASES[e];return t===void 0?require.resolve(e):resolvePackageCompiledFilePath(t)}export{resolveExpectedWorkflowVersion,resolveInstalledPackageInfo,resolvePackageDependencyPath,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{expectFunction,expectObjectRecord,expectOnlyKnownKeys,expectString}from"#internal/authored-module.js";import{isDynamicSentinel}from"#shared/dynamic-tool-definition.js";import{normalizeJsonSchemaDefinition}from"#internal/json-schema.js";import{isDisabledToolSentinel
|
|
1
|
+
import{expectFunction,expectObjectRecord,expectOnlyKnownKeys,expectString}from"#internal/authored-module.js";import{isDynamicSentinel}from"#shared/dynamic-tool-definition.js";import{normalizeJsonSchemaDefinition}from"#internal/json-schema.js";import{isDisabledToolSentinel}from"#public/definitions/tool.js";function isEnableWorkflowToolSentinel(e){return typeof e==`object`&&!!e&&e.kind===`eve:enable-workflow-tool`}function normalizeToolDefinition(t,n){if(isDynamicSentinel(t))return{kind:`dynamic-tool`,eventNames:Object.keys(t.events)};if(isDisabledToolSentinel(t))return{kind:`disabled`};if(isEnableWorkflowToolSentinel(t))return{kind:`enable-workflow`};let r=expectObjectRecord(t,n);expectOnlyKnownKeys(r,[`auth`,`description`,`execute`,`inputSchema`,`approval`,`outputSchema`,`toModelOutput`],n);let i=r.inputSchema===void 0?null:normalizeJsonSchemaDefinition(r.inputSchema),a=r.outputSchema===void 0?void 0:normalizeJsonSchemaDefinition(r.outputSchema,`output`),o={description:expectString(r.description,n),execute:expectFunction(r.execute,n),inputSchema:i};return a!==void 0&&(o.outputSchema=a),r.approval!==void 0&&expectFunction(r.approval,n),r.toModelOutput!==void 0&&expectFunction(r.toModelOutput,n),r.auth!==void 0&&expectFunction(expectObjectRecord(r.auth,n).getToken,n),{kind:`tool`,definition:o}}export{normalizeToolDefinition};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as workflowRuntime from"#compiled/@workflow/core/runtime.js";export*from"#compiled/@workflow/core/runtime.js";function setWorld(e){workflowRuntime.setWorld(e)}export{setWorld};
|
|
1
|
+
import*as workflowRuntime from"#compiled/@workflow/core/runtime.js";export*from"#compiled/@workflow/core/runtime.js";process.env.WORKFLOW_TURBO=`0`;function setWorld(e){workflowRuntime.setWorld(e)}export{setWorld};
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* exposing a third-party SDK through eve public surfaces.
|
|
6
6
|
*/
|
|
7
7
|
import { type JsonObject } from "#shared/json.js";
|
|
8
|
+
import { type TelegramChatType } from "#public/channels/telegram/inbound.js";
|
|
8
9
|
/** Telegram bot token, materialized directly or from an async secret provider. */
|
|
9
10
|
export type TelegramBotToken = string | (() => string | Promise<string>);
|
|
10
11
|
/** Fetch implementation override for tests or non-standard runtimes. */
|
|
@@ -39,6 +40,8 @@ export interface TelegramMessageResult {
|
|
|
39
40
|
readonly id: string;
|
|
40
41
|
/** Telegram chat id associated with the message, when Telegram returned one. */
|
|
41
42
|
readonly chatId?: string;
|
|
43
|
+
/** Recognized Telegram chat type associated with the message, when returned. */
|
|
44
|
+
readonly chatType?: TelegramChatType;
|
|
42
45
|
/** Telegram's raw JSON response. */
|
|
43
46
|
readonly raw: unknown;
|
|
44
47
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";const TELEGRAM_MESSAGE_TEXT_MAX_LENGTH=4096;function telegramContinuationToken(e){let t=e.messageThreadId===void 0?``:String(e.messageThreadId),n=e.conversationId===void 0?``:String(e.conversationId);return`${String(e.chatId)}:${t}:${n}`}async function resolveTelegramBotToken(e){let t=e??process.env.TELEGRAM_BOT_TOKEN;if(!t)throw Error(`TELEGRAM_BOT_TOKEN is required.`);return typeof t==`function`?await t():t}async function callTelegramApi(e){let n=e.fetch??fetch,r=await resolveTelegramBotToken(e.botToken),i={headers:{"content-type":`application/json; charset=utf-8`},method:`POST`};e.body!==void 0&&(i.body=JSON.stringify(parseJsonObject(e.body)));let a=await n(`${e.apiBaseUrl??`https://api.telegram.org`}/bot${r}/${encodeURIComponent(e.method)}`,i);return{body:await parseResponseBody(a),ok:a.ok,status:a.status}}async function sendTelegramMessage(e){let t=await callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:normalizeTelegramMessageBody(e.body,e.chatId),botToken:e.credentials?.botToken,fetch:e.fetch,method:`sendMessage`});if(!t.ok)throw Error(`Telegram sendMessage failed with HTTP ${t.status}.`);return toTelegramMessageResult(t.body)}async function sendTelegramChatAction(e){return callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:parseJsonObject({action:e.action,chat_id:e.chatId,message_thread_id:e.messageThreadId}),botToken:e.credentials?.botToken,fetch:e.fetch,method:`sendChatAction`})}async function answerTelegramCallbackQuery(e){return callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:parseJsonObject({callback_query_id:e.callbackQueryId,show_alert:e.showAlert,text:e.text}),botToken:e.credentials?.botToken,fetch:e.fetch,method:`answerCallbackQuery`})}async function editTelegramMessageReplyMarkup(e){return callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:parseJsonObject({chat_id:e.chatId,message_id:Number(e.messageId),reply_markup:e.replyMarkup}),botToken:e.credentials?.botToken,fetch:e.fetch,method:`editMessageReplyMarkup`})}async function getTelegramFile(t){let n=await callTelegramApi({apiBaseUrl:t.apiBaseUrl,body:{file_id:t.fileId},botToken:t.credentials?.botToken,fetch:t.fetch,method:`getFile`});if(!n.ok)throw Error(`Telegram getFile failed with HTTP ${n.status}.`);let r=isObject(n.body)?n.body:{},i=isObject(r.result)?r.result:{};if(typeof i.file_path!=`string`||i.file_path.length===0)throw Error(`Telegram getFile response did not include result.file_path.`);return{filePath:i.file_path,raw:n.body}}async function downloadTelegramFile(e){let t=e.fetch??fetch,n=await resolveTelegramBotToken(e.credentials?.botToken);return t(`${e.fileBaseUrl??e.apiBaseUrl??`https://api.telegram.org`}/file/bot${n}/${e.filePath}`)}function splitTelegramMessageText(e){if(e.length<=4096)return[e];let t=[],
|
|
2
|
-
`,TELEGRAM_MESSAGE_TEXT_MAX_LENGTH);e<=0&&(e=
|
|
1
|
+
import{isObject}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{parseTelegramChatType}from"#public/channels/telegram/inbound.js";const TELEGRAM_MESSAGE_TEXT_MAX_LENGTH=4096;function telegramContinuationToken(e){let t=e.messageThreadId===void 0?``:String(e.messageThreadId),n=e.conversationId===void 0?``:String(e.conversationId);return`${String(e.chatId)}:${t}:${n}`}async function resolveTelegramBotToken(e){let t=e??process.env.TELEGRAM_BOT_TOKEN;if(!t)throw Error(`TELEGRAM_BOT_TOKEN is required.`);return typeof t==`function`?await t():t}async function callTelegramApi(e){let n=e.fetch??fetch,r=await resolveTelegramBotToken(e.botToken),i={headers:{"content-type":`application/json; charset=utf-8`},method:`POST`};e.body!==void 0&&(i.body=JSON.stringify(parseJsonObject(e.body)));let a=await n(`${e.apiBaseUrl??`https://api.telegram.org`}/bot${r}/${encodeURIComponent(e.method)}`,i);return{body:await parseResponseBody(a),ok:a.ok,status:a.status}}async function sendTelegramMessage(e){let t=await callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:normalizeTelegramMessageBody(e.body,e.chatId),botToken:e.credentials?.botToken,fetch:e.fetch,method:`sendMessage`});if(!t.ok)throw Error(`Telegram sendMessage failed with HTTP ${t.status}.`);return toTelegramMessageResult(t.body)}async function sendTelegramChatAction(e){return callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:parseJsonObject({action:e.action,chat_id:e.chatId,message_thread_id:e.messageThreadId}),botToken:e.credentials?.botToken,fetch:e.fetch,method:`sendChatAction`})}async function answerTelegramCallbackQuery(e){return callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:parseJsonObject({callback_query_id:e.callbackQueryId,show_alert:e.showAlert,text:e.text}),botToken:e.credentials?.botToken,fetch:e.fetch,method:`answerCallbackQuery`})}async function editTelegramMessageReplyMarkup(e){return callTelegramApi({apiBaseUrl:e.apiBaseUrl,body:parseJsonObject({chat_id:e.chatId,message_id:Number(e.messageId),reply_markup:e.replyMarkup}),botToken:e.credentials?.botToken,fetch:e.fetch,method:`editMessageReplyMarkup`})}async function getTelegramFile(t){let n=await callTelegramApi({apiBaseUrl:t.apiBaseUrl,body:{file_id:t.fileId},botToken:t.credentials?.botToken,fetch:t.fetch,method:`getFile`});if(!n.ok)throw Error(`Telegram getFile failed with HTTP ${n.status}.`);let r=isObject(n.body)?n.body:{},i=isObject(r.result)?r.result:{};if(typeof i.file_path!=`string`||i.file_path.length===0)throw Error(`Telegram getFile response did not include result.file_path.`);return{filePath:i.file_path,raw:n.body}}async function downloadTelegramFile(e){let t=e.fetch??fetch,n=await resolveTelegramBotToken(e.credentials?.botToken);return t(`${e.fileBaseUrl??e.apiBaseUrl??`https://api.telegram.org`}/file/bot${n}/${e.filePath}`)}function splitTelegramMessageText(e){if(e.length<=4096)return[e];let t=[],n=e;for(;n.length>TELEGRAM_MESSAGE_TEXT_MAX_LENGTH;){let e=n.lastIndexOf(`
|
|
2
|
+
`,TELEGRAM_MESSAGE_TEXT_MAX_LENGTH);e<=0&&(e=n.lastIndexOf(` `,TELEGRAM_MESSAGE_TEXT_MAX_LENGTH)),e<=0&&(e=TELEGRAM_MESSAGE_TEXT_MAX_LENGTH),t.push(n.slice(0,e).trimEnd()),n=n.slice(e).trimStart()}return t.push(n),t}function normalizeTelegramMessageBody(e,n){return parseJsonObject({...e,chat_id:n})}function toTelegramMessageResult(t){let r=isObject(t)?t:{},i=isObject(r.result)?r.result:{},a=isObject(i.chat)?i.chat:{};return{chatId:typeof a.id==`number`||typeof a.id==`string`?String(a.id):void 0,chatType:parseTelegramChatType(a.type)??void 0,id:typeof i.message_id==`number`||typeof i.message_id==`string`?String(i.message_id):``,raw:t}}async function parseResponseBody(e){let t=await e.text();if(!t)return null;try{return JSON.parse(t)}catch{return t}}export{TELEGRAM_MESSAGE_TEXT_MAX_LENGTH,answerTelegramCallbackQuery,callTelegramApi,downloadTelegramFile,editTelegramMessageReplyMarkup,getTelegramFile,resolveTelegramBotToken,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken};
|
|
@@ -100,3 +100,5 @@ export declare function parseTelegramUpdate(value: unknown): TelegramUpdate | nu
|
|
|
100
100
|
* user identity fields.
|
|
101
101
|
*/
|
|
102
102
|
export declare function formatTelegramContextBlock(context: TelegramInboundContext): string;
|
|
103
|
+
/** Parses the Telegram chat types eve recognizes from inbound and send responses. */
|
|
104
|
+
export declare function parseTelegramChatType(value: unknown): TelegramChatType | null;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import{isNonEmptyString,isObject}from"#shared/guards.js";function parseTelegramUpdate(e){if(!isObject(e))return null;let n=parseTelegramMessage(e.message);if(n!==null)return{kind:`message`,message:n};let r=parseTelegramCallbackQuery(e.callback_query);return r===null?null:{callbackQuery:r,kind:`callback_query`}}function formatTelegramContextBlock(e){return[`<telegram_context>`,`response_medium: telegram`,`response_instructions: Reply for Telegram in concise plain text. Avoid tables, long code fences, and formatting that depends on Markdown rendering.`,`chat_id: ${e.chatId}`,`chat_type: ${e.chatType}`,...e.chatTitle?[`chat_title: ${e.chatTitle}`]:[],`message_id: ${e.messageId}`,...e.messageThreadId===void 0?[]:[`message_thread_id: ${e.messageThreadId}`],...e.userId?[`user_id: ${e.userId}`]:[],...e.username?[`username: ${e.username}`]:[],...e.botUsername?[`bot_username: ${e.botUsername}`]:[],`</telegram_context>`].join(`
|
|
2
|
-
`)}function parseTelegramMessage(e){if(!isObject(e))return null;let n=parseTelegramChat(e.chat),r=numberLikeToString(e.message_id);return!n||!r?null:{attachments:parseAttachments(e),caption:typeof e.caption==`string`?e.caption:``,chat:n,from:parseTelegramUser(e.from),messageId:r,messageThreadId:typeof e.message_thread_id==`number`?e.message_thread_id:void 0,raw:e,replyToMessage:parseMessageReference(e.reply_to_message),text:typeof e.text==`string`?e.text:``}}function parseTelegramCallbackQuery(n){if(!isObject(n)||!isNonEmptyString(n.id))return null;let r=parseTelegramUser(n.from);return r?{data:typeof n.data==`string`?n.data:void 0,from:r,id:n.id,message:parseMessageReference(n.message),raw:n}:null}function parseMessageReference(e){if(!isObject(e))return;let n=parseTelegramChat(e.chat),r=numberLikeToString(e.message_id);if(!(!n||!r))return{chat:n,from:parseTelegramUser(e.from),messageId:r,messageThreadId:typeof e.message_thread_id==`number`?e.message_thread_id:void 0}}function parseTelegramChat(e){if(!isObject(e))return null;let n=numberLikeToString(e.id),r=
|
|
2
|
+
`)}function parseTelegramMessage(e){if(!isObject(e))return null;let n=parseTelegramChat(e.chat),r=numberLikeToString(e.message_id);return!n||!r?null:{attachments:parseAttachments(e),caption:typeof e.caption==`string`?e.caption:``,chat:n,from:parseTelegramUser(e.from),messageId:r,messageThreadId:typeof e.message_thread_id==`number`?e.message_thread_id:void 0,raw:e,replyToMessage:parseMessageReference(e.reply_to_message),text:typeof e.text==`string`?e.text:``}}function parseTelegramCallbackQuery(n){if(!isObject(n)||!isNonEmptyString(n.id))return null;let r=parseTelegramUser(n.from);return r?{data:typeof n.data==`string`?n.data:void 0,from:r,id:n.id,message:parseMessageReference(n.message),raw:n}:null}function parseMessageReference(e){if(!isObject(e))return;let n=parseTelegramChat(e.chat),r=numberLikeToString(e.message_id);if(!(!n||!r))return{chat:n,from:parseTelegramUser(e.from),messageId:r,messageThreadId:typeof e.message_thread_id==`number`?e.message_thread_id:void 0}}function parseTelegramChat(e){if(!isObject(e))return null;let n=numberLikeToString(e.id),r=parseTelegramChatType(e.type);return!n||!r?null:{id:n,title:typeof e.title==`string`?e.title:void 0,type:r,username:typeof e.username==`string`?e.username:void 0}}function parseTelegramUser(e){if(!isObject(e))return;let n=numberLikeToString(e.id);if(n)return{firstName:typeof e.first_name==`string`?e.first_name:void 0,id:n,isBot:e.is_bot===!0,languageCode:typeof e.language_code==`string`?e.language_code:void 0,lastName:typeof e.last_name==`string`?e.last_name:void 0,username:typeof e.username==`string`?e.username:void 0}}function parseAttachments(e){let t=[],n=parseLargestPhoto(e.photo);n!==null&&t.push(n);let r=parseDocument(e.document);return r!==null&&t.push(r),t}function parseLargestPhoto(e){if(!Array.isArray(e)||e.length===0)return null;let n=e.filter(isObject).map(e=>({fileId:typeof e.file_id==`string`?e.file_id:``,fileUniqueId:typeof e.file_unique_id==`string`?e.file_unique_id:void 0,height:typeof e.height==`number`?e.height:void 0,size:typeof e.file_size==`number`?e.file_size:void 0,width:typeof e.width==`number`?e.width:void 0})).filter(e=>e.fileId.length>0).sort((e,t)=>scorePhoto(t)-scorePhoto(e))[0];return n?{fileId:n.fileId,fileName:`photo.jpg`,fileUniqueId:n.fileUniqueId,height:n.height,kind:`photo`,mediaType:`image/jpeg`,size:n.size,width:n.width}:null}function parseDocument(e){return!isObject(e)||typeof e.file_id!=`string`?null:{fileId:e.file_id,fileName:typeof e.file_name==`string`?e.file_name:void 0,fileUniqueId:typeof e.file_unique_id==`string`?e.file_unique_id:void 0,kind:`document`,mediaType:typeof e.mime_type==`string`?e.mime_type:void 0,size:typeof e.file_size==`number`?e.file_size:void 0}}function scorePhoto(e){return e.size===void 0?(e.width??0)*(e.height??0):e.size}function parseTelegramChatType(e){return e===`channel`||e===`group`||e===`private`||e===`supergroup`?e:null}function numberLikeToString(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}export{formatTelegramContextBlock,parseTelegramChatType,parseTelegramUpdate};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{TELEGRAM_MESSAGE_TEXT_MAX_LENGTH,answerTelegramCallbackQuery,callTelegramApi,downloadTelegramFile,editTelegramMessageReplyMarkup,getTelegramFile,resolveTelegramBotToken,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken}from"#public/channels/telegram/api.js";import{TELEGRAM_CALLBACK_RESPONSE_PREFIX,TELEGRAM_HITL_CALLBACK_PREFIX,TELEGRAM_REPLY_RESPONSE_PREFIX,isTelegramSyntheticResponse,registerTelegramFreeformPrompt,renderTelegramInputRequest,resolveTelegramInputResponses,telegramCallbackInputResponse,telegramReplyInputResponse}from"#public/channels/telegram/hitl.js";import{telegramChannel}from"#public/channels/telegram/telegramChannel.js";import{
|
|
1
|
+
import{formatTelegramContextBlock,parseTelegramUpdate}from"#public/channels/telegram/inbound.js";import{TELEGRAM_MESSAGE_TEXT_MAX_LENGTH,answerTelegramCallbackQuery,callTelegramApi,downloadTelegramFile,editTelegramMessageReplyMarkup,getTelegramFile,resolveTelegramBotToken,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken}from"#public/channels/telegram/api.js";import{TELEGRAM_CALLBACK_RESPONSE_PREFIX,TELEGRAM_HITL_CALLBACK_PREFIX,TELEGRAM_REPLY_RESPONSE_PREFIX,isTelegramSyntheticResponse,registerTelegramFreeformPrompt,renderTelegramInputRequest,resolveTelegramInputResponses,telegramCallbackInputResponse,telegramReplyInputResponse}from"#public/channels/telegram/hitl.js";import{telegramChannel}from"#public/channels/telegram/telegramChannel.js";import{TELEGRAM_FILE_URL_PROTOCOL,buildTelegramTurnMessage,collectTelegramFileParts,createTelegramFetchFile,createTelegramFileUrl}from"#public/channels/telegram/attachments.js";import{defaultTelegramAuth}from"#public/channels/telegram/defaults.js";import{resolveTelegramWebhookSecretToken,verifyTelegramRequest}from"#public/channels/telegram/verify.js";export{TELEGRAM_CALLBACK_RESPONSE_PREFIX,TELEGRAM_FILE_URL_PROTOCOL,TELEGRAM_HITL_CALLBACK_PREFIX,TELEGRAM_MESSAGE_TEXT_MAX_LENGTH,TELEGRAM_REPLY_RESPONSE_PREFIX,answerTelegramCallbackQuery,buildTelegramTurnMessage,callTelegramApi,collectTelegramFileParts,createTelegramFetchFile,createTelegramFileUrl,defaultTelegramAuth,downloadTelegramFile,editTelegramMessageReplyMarkup,formatTelegramContextBlock,getTelegramFile,isTelegramSyntheticResponse,parseTelegramUpdate,registerTelegramFreeformPrompt,renderTelegramInputRequest,resolveTelegramBotToken,resolveTelegramInputResponses,resolveTelegramWebhookSecretToken,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramCallbackInputResponse,telegramChannel,telegramContinuationToken,telegramReplyInputResponse,verifyTelegramRequest};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{isCompiledChannel}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{answerTelegramCallbackQuery,callTelegramApi,editTelegramMessageReplyMarkup,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken}from"#public/channels/telegram/api.js";import{TELEGRAM_HITL_CALLBACK_PREFIX,isTelegramSyntheticResponse,resolveTelegramInputResponses,telegramCallbackInputResponse,telegramReplyInputResponse}from"#public/channels/telegram/hitl.js";import{
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{isCompiledChannel}from"#channel/compiled-channel.js";import{defaultDeliverResult}from"#channel/adapter.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{formatTelegramContextBlock,parseTelegramUpdate}from"#public/channels/telegram/inbound.js";import{answerTelegramCallbackQuery,callTelegramApi,editTelegramMessageReplyMarkup,sendTelegramChatAction,sendTelegramMessage,splitTelegramMessageText,telegramContinuationToken}from"#public/channels/telegram/api.js";import{TELEGRAM_HITL_CALLBACK_PREFIX,isTelegramSyntheticResponse,resolveTelegramInputResponses,telegramCallbackInputResponse,telegramReplyInputResponse}from"#public/channels/telegram/hitl.js";import{buildTelegramTurnMessage,collectTelegramFileParts,createTelegramFetchFile}from"#public/channels/telegram/attachments.js";import{defaultEvents,defaultOnMessage}from"#public/channels/telegram/defaults.js";import{verifyTelegramRequest}from"#public/channels/telegram/verify.js";const log=createLogger(`telegram.channel`);function telegramChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),n=e.onMessage??defaultOnMessage,r={...defaultEvents,...e.events},c=defineChannel({kindHint:`telegram`,state:initialTelegramState(e.botUsername),metadata:e=>({chatId:e.chatId,chatType:e.chatType,triggeringUserId:e.triggeringUserId??null}),fetchFile:createTelegramFetchFile({api:e.api,credentials:e.credentials,policy:t}),context(t,n){return rebuildTelegramContext(t,n,e)},routes:[POST(e.route??`/eve/v1/telegram`,async(r,{send:a,waitUntil:o})=>{let s=await verifyInbound(r,e.credentials);if(s===null)return new Response(`unauthorized`,{status:401});let c;try{c=parseJsonObject(JSON.parse(s))}catch(e){return log.warn(`inbound Telegram body is not valid JSON`,{error:e}),new Response(`ok`)}let u=parseTelegramUpdate(c);return u===null?new Response(`ok`):u.kind===`message`?(o(dispatchMessage({config:e,message:u.message,onMessage:n,send:a,uploadPolicy:t})),new Response(`ok`)):(o(dispatchCallbackQuery({config:e,query:u.callbackQuery,send:a})),new Response(`ok`))})],async receive(t,{send:n}){let r=t.target,i=readChatId(r.chatId);if(i===void 0)throw Error(`telegramChannel().receive requires target.chatId.`);let a=typeof r.messageThreadId==`number`?r.messageThreadId:void 0,o=readOptionalString(r.conversationId),s=r.initialMessage;if(s!==void 0&&o!==void 0)throw Error("telegramChannel().receive: `conversationId` and `initialMessage` are mutually exclusive.");let c={...initialTelegramState(e.botUsername),chatId:i,conversationId:o??null,messageThreadId:a??null};return s!==void 0&&await buildTelegramHandle({config:e,state:c}).sendMessage(s),n(t.message,{auth:t.auth,continuationToken:continuationTokenFromState(c),state:c})},events:r});return attachTelegramDeliver(c),c}function rebuildTelegramContext(e,t,n){return{state:e,telegram:buildTelegramHandle({config:n,session:t,state:e})}}function buildTelegramHandle(e){let n=e.config.api,r=e.state,i=e.config.credentials;function anchor(t){let n=r.chatType??t.chatType??null;r.chatType===null&&t.chatType!==void 0&&(r.chatType=t.chatType),!(!t.id||!shouldAnchorTelegramConversation(n))&&(r.conversationId=t.id,r.chatId&&e.session?.setContinuationToken(telegramContinuationToken({chatId:r.chatId,conversationId:t.id,messageThreadId:r.messageThreadId??void 0})))}async function sendOne(e){let t=r.chatId??``;if(!t)throw Error(`telegramChannel: missing chat id for outbound message.`);let a=await sendTelegramMessage({apiBaseUrl:n?.apiBaseUrl,body:{...e,message_thread_id:e.message_thread_id??r.messageThreadId??void 0},credentials:i,fetch:n?.fetch,fileBaseUrl:n?.fileBaseUrl,chatId:t});return anchor(a),a}return{botUsername:r.botUsername??e.config.botUsername,chatId:r.chatId??``,chatType:r.chatType??void 0,conversationId:r.conversationId??void 0,messageThreadId:r.messageThreadId??void 0,answerCallbackQuery(e){return answerTelegramCallbackQuery({apiBaseUrl:n?.apiBaseUrl,callbackQueryId:e.callbackQueryId,credentials:i,fetch:n?.fetch,showAlert:e.showAlert,text:e.text})},editMessageReplyMarkup(e){let t=r.chatId??``;if(!t)throw Error(`telegramChannel: missing chat id for reply-markup edit.`);return editTelegramMessageReplyMarkup({apiBaseUrl:n?.apiBaseUrl,chatId:t,credentials:i,fetch:n?.fetch,messageId:e.messageId,replyMarkup:e.replyMarkup})},post(e){return postTelegramMessage(e,sendOne)},request(e,t){return callTelegramApi({apiBaseUrl:n?.apiBaseUrl,body:t,botToken:i?.botToken,fetch:n?.fetch,method:e})},sendMessage(e){return postTelegramMessage(e,sendOne)},async startTyping(e=`typing`){let a=r.chatId??``;if(a)try{await sendTelegramChatAction({action:e,apiBaseUrl:n?.apiBaseUrl,chatId:a,credentials:i,fetch:n?.fetch,messageThreadId:r.messageThreadId??void 0})}catch(e){logError(log,`Telegram typing indicator failed — swallowed`,e,{chatId:a})}}}}function shouldAnchorTelegramConversation(e){return e===`group`||e===`supergroup`}async function postTelegramMessage(e,t){let n=typeof e==`string`?{text:e}:e,r=splitTelegramMessageText(n.text),i;for(let[e,a]of r.entries()){let r=await t(e===0?{...n,text:a}:{text:a});i===void 0&&(i=r)}return i??{id:``,raw:null}}async function verifyInbound(e,t){try{return await verifyTelegramRequest(e,{secretToken:t?.webhookVerifier?void 0:t?.webhookSecretToken,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`telegram inbound verification failed`,{error:e}),null}}async function dispatchMessage(e){if(e.message.from?.isBot===!0)return;let t=stateFromMessage(e.message,e.config),n={telegram:buildTelegramHandle({config:e.config,state:t})},r;try{r=await e.onMessage(n,e.message)}catch(e){log.error(`message handler failed`,{error:e});return}if(r==null)return;let i=collectTelegramFileParts(e.message.attachments,e.uploadPolicy),a=buildTelegramTurnMessage(e.message,i),o=formatTelegramContextBlock({botUsername:e.config.botUsername,chatId:e.message.chat.id,chatTitle:e.message.chat.title,chatType:e.message.chat.type,messageId:e.message.messageId,messageThreadId:e.message.messageThreadId,userId:e.message.from?.id,username:e.message.from?.username}),s=r.context??[],l=e.message.text||e.message.caption,u=e.message.replyToMessage?.from?.isBot===!0&&l.trim().length>0?[telegramReplyInputResponse({messageId:e.message.replyToMessage.messageId,text:l})]:void 0;try{await e.send({inputResponses:u,message:a,context:[o,...s]},{auth:r.auth,continuationToken:continuationTokenFromState(t),state:t})}catch(e){log.error(`message delivery failed`,{error:e})}}async function dispatchCallbackQuery(e){let t=stateFromCallbackQuery(e.query,e.config),n={telegram:buildTelegramHandle({config:e.config,state:t})};if(e.query.data?.startsWith(TELEGRAM_HITL_CALLBACK_PREFIX)===!0){try{await n.telegram.answerCallbackQuery({callbackQueryId:e.query.id,text:`Answer received.`})}catch(e){log.warn(`Telegram callback-query acknowledgement failed`,{error:e})}if(!e.query.message||!t.chatId)return;try{await e.send({inputResponses:[telegramCallbackInputResponse(e.query.data)]},{auth:null,continuationToken:continuationTokenFromState(t),state:t})}catch(e){log.error(`callback query delivery failed`,{error:e})}return}if(e.config.onCallbackQuery!==void 0){try{await e.config.onCallbackQuery(n,e.query)}catch(e){log.error(`custom callback-query handler failed`,{error:e})}return}try{await n.telegram.answerCallbackQuery({callbackQueryId:e.query.id,text:`Unsupported action.`})}catch(e){log.warn(`Telegram unsupported callback-query acknowledgement failed`,{error:e})}}function attachTelegramDeliver(e){if(!isCompiledChannel(e))return;let t=e.adapter;t.deliver=(e,t)=>{let n=e.inputResponses??[];if(n.some(isTelegramSyntheticResponse)){let r=resolveTelegramInputResponses(t.state,n);return r.length>0?{inputResponses:r,context:e.context}:e.message===void 0?void 0:{message:e.message,context:e.context}}return defaultDeliverResult(e)}}function stateFromMessage(e,t){let n=e.chat.type===`private`;return{...initialTelegramState(t.botUsername),chatId:e.chat.id,chatType:e.chat.type,conversationId:n?null:conversationIdForMessage(e),messageThreadId:e.messageThreadId??null,triggeringUserId:e.from?.id??null}}function stateFromCallbackQuery(e,t){let n=e.message;if(!n)return{...initialTelegramState(t.botUsername),triggeringUserId:e.from.id};let r=n.chat.type===`private`;return{...initialTelegramState(t.botUsername),chatId:n.chat.id,chatType:n.chat.type,conversationId:r?null:n.messageId,messageThreadId:n.messageThreadId??null,triggeringUserId:e.from.id}}function conversationIdForMessage(e){return e.replyToMessage?.from?.isBot===!0?e.replyToMessage.messageId:e.messageId}function continuationTokenFromState(e){return telegramContinuationToken({chatId:e.chatId??``,conversationId:e.chatType===`private`?void 0:e.conversationId??void 0,messageThreadId:e.messageThreadId??void 0})}function initialTelegramState(e){return{botUsername:e??null,chatId:null,chatType:null,conversationId:null,hitlCallbacks:{},messageThreadId:null,nextHitlCallbackId:0,pendingFreeformReplies:{},triggeringUserId:null}}function readChatId(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}function readOptionalString(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e==`number`&&Number.isFinite(e))return String(e)}export{telegramChannel};
|
|
@@ -209,36 +209,3 @@ export declare function disableTool(): DisabledToolSentinel;
|
|
|
209
209
|
* produced by {@link disableTool}.
|
|
210
210
|
*/
|
|
211
211
|
export declare function isDisabledToolSentinel(value: unknown): value is DisabledToolSentinel;
|
|
212
|
-
/**
|
|
213
|
-
* Marker discriminator written into the {@link ExperimentalWorkflow} opt-in
|
|
214
|
-
* sentinel.
|
|
215
|
-
*/
|
|
216
|
-
declare const ENABLE_WORKFLOW_TOOL_SENTINEL_KIND = "eve:enable-workflow-tool";
|
|
217
|
-
/**
|
|
218
|
-
* Marker value re-exported as the default export of a file in `agent/tools/`
|
|
219
|
-
* (conventionally `agent/tools/workflow.ts`) to enable the framework `Workflow`
|
|
220
|
-
* orchestration tool. The tool is off unless this marker is present,
|
|
221
|
-
* mirroring the {@link disableTool} opt-out in reverse.
|
|
222
|
-
*/
|
|
223
|
-
export interface EnableWorkflowToolSentinel {
|
|
224
|
-
readonly kind: typeof ENABLE_WORKFLOW_TOOL_SENTINEL_KIND;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Opt-in marker for the framework `Workflow` tool, an isolated JavaScript sandbox whose
|
|
228
|
-
* only callable operations are this agent's subagents and remote agents, for
|
|
229
|
-
* orchestrating them from model-authored JavaScript. Re-export it as the
|
|
230
|
-
* default export of `agent/tools/workflow.ts`:
|
|
231
|
-
*
|
|
232
|
-
* ```ts
|
|
233
|
-
* export { ExperimentalWorkflow as default } from "eve/tools";
|
|
234
|
-
* ```
|
|
235
|
-
*
|
|
236
|
-
* The capability is experimental. The resulting model-facing tool is still
|
|
237
|
-
* called `Workflow`.
|
|
238
|
-
*/
|
|
239
|
-
export declare const ExperimentalWorkflow: EnableWorkflowToolSentinel;
|
|
240
|
-
/**
|
|
241
|
-
* Type guard: returns whether `value` is the {@link ExperimentalWorkflow}
|
|
242
|
-
* opt-in sentinel.
|
|
243
|
-
*/
|
|
244
|
-
export declare function isEnableWorkflowToolSentinel(value: unknown): value is EnableWorkflowToolSentinel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DYNAMIC_SENTINEL_KIND,TOOL_BRAND}from"#shared/dynamic-tool-definition.js";import{stampDefinitionKey}from"#public/tool-result-narrowing.js";function defineTool(e){if(e.auth!==void 0)throw Error(`defineTool: The "auth" field is no longer supported. Pass auth providers inline to ctx.getToken(provider) or ctx.requireAuth(provider).`);return Object.assign(e,{[TOOL_BRAND]:!0}),stampDefinitionKey(e,`tool:${e.description}`),e}function defineDynamic(t){let n={kind:DYNAMIC_SENTINEL_KIND,events:t.events};return stampDefinitionKey(n,`dynamic:${Object.keys(t.events).join(`,`)}`),n}const DISABLED_TOOL_SENTINEL_KIND=`eve:disabled-tool`;function disableTool(){return{kind:DISABLED_TOOL_SENTINEL_KIND}}function isDisabledToolSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_TOOL_SENTINEL_KIND}
|
|
1
|
+
import{DYNAMIC_SENTINEL_KIND,TOOL_BRAND}from"#shared/dynamic-tool-definition.js";import{stampDefinitionKey}from"#public/tool-result-narrowing.js";function defineTool(e){if(e.auth!==void 0)throw Error(`defineTool: The "auth" field is no longer supported. Pass auth providers inline to ctx.getToken(provider) or ctx.requireAuth(provider).`);return Object.assign(e,{[TOOL_BRAND]:!0}),stampDefinitionKey(e,`tool:${e.description}`),e}function defineDynamic(t){let n={kind:DYNAMIC_SENTINEL_KIND,events:t.events};return stampDefinitionKey(n,`dynamic:${Object.keys(t.events).join(`,`)}`),n}const DISABLED_TOOL_SENTINEL_KIND=`eve:disabled-tool`;function disableTool(){return{kind:DISABLED_TOOL_SENTINEL_KIND}}function isDisabledToolSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_TOOL_SENTINEL_KIND}export{defineDynamic,defineTool,disableTool,isDisabledToolSentinel};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tool authoring helpers for `agent/tools/*.ts` files.
|
|
3
3
|
*/
|
|
4
|
-
export { type DisabledToolSentinel,
|
|
4
|
+
export { type DisabledToolSentinel, defineDynamic, defineTool, disableTool, isDisabledToolSentinel, type ToolAuthOptions, type ToolAuthProvider, type ToolDefinition, type ToolContext, type ToolModelOutput, } from "#public/definitions/tool.js";
|
|
5
5
|
export type { Approval, ApprovalContext, ApprovalStatus } from "#public/definitions/approval.js";
|
|
6
6
|
export type { DynamicToolEntry, DynamicEvents, DynamicToolEvents, DynamicResolveContext, DynamicSentinel, DynamicToolSet, DynamicToolResult, } from "#shared/dynamic-tool-definition.js";
|
|
7
7
|
export { type SessionContext } from "#public/definitions/callback-context.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{defineDynamic,defineTool,disableTool,isDisabledToolSentinel}from"#public/definitions/tool.js";import{toolResultFrom}from"#public/tool-result-narrowing.js";import{defineBashTool}from"#public/tools/define-bash-tool.js";import{defineGlobTool}from"#public/tools/define-glob-tool.js";import{defineGrepTool}from"#public/tools/define-grep-tool.js";import{defineReadFileTool}from"#public/tools/define-read-file-tool.js";import{defineWriteFileTool}from"#public/tools/define-write-file-tool.js";export{defineBashTool,defineDynamic,defineGlobTool,defineGrepTool,defineReadFileTool,defineTool,defineWriteFileTool,disableTool,isDisabledToolSentinel,toolResultFrom};
|
|
@@ -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.
|
|
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.0`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
|
|
2
2
|
|
|
3
3
|
export default defineAgent({
|
|
4
4
|
model: "__EVE_INIT_MODEL__",
|
|
@@ -53,6 +53,8 @@ Human-in-the-loop (HITL) turns option requests into inline-keyboard buttons and
|
|
|
53
53
|
|
|
54
54
|
Start a session without an inbound message through `receive(telegram, { message, target, auth })` from a schedule `run` handler, or `args.receive(telegram, ...)` from another channel. `target.chatId` is required. Add `messageThreadId` to land in a specific forum topic.
|
|
55
55
|
|
|
56
|
+
Private proactive chats stay keyed to the chat, or to the chat plus `messageThreadId` when you target a topic. Group and supergroup proactive sends anchor to the bot message id returned by Telegram, so replies to different bot messages can resume different sessions in the same chat. If Telegram does not return a recognized chat type for an outbound send, eve keeps the session unanchored instead of guessing.
|
|
57
|
+
|
|
56
58
|
### Attachments
|
|
57
59
|
|
|
58
60
|
Inbound photos and documents are supported. eve fetches them on demand via `getFile`, only when an upload policy allows the type:
|
|
@@ -87,16 +87,6 @@ Three moves shape the harness. The right one depends on whether the model should
|
|
|
87
87
|
- **Disable** when the model should not have the capability at all. A `disableTool()` sentinel removes the built-in, and the model never sees it. Reach for this to lock down `bash` or `web_fetch` in an agent that should not run shell commands or fetch arbitrary URLs.
|
|
88
88
|
- **Author a new tool** when you want a capability the harness does not ship. Give it a fresh slug under `agent/tools/` and it joins the built-ins instead of replacing one. See [Tools](../tools) for the authoring model.
|
|
89
89
|
|
|
90
|
-
## The opt-in `Workflow` tool
|
|
91
|
-
|
|
92
|
-
An experimental `Workflow` tool ships but stays off by default. To turn it on, re-export the opt-in marker from `agent/tools/workflow.ts`:
|
|
93
|
-
|
|
94
|
-
```ts
|
|
95
|
-
export { ExperimentalWorkflow as default } from "eve/tools";
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
With it on, the model can orchestrate the agent's own subagents from model-authored JavaScript, all as one durable step. See [Dynamic workflows](../guides/dynamic-workflows).
|
|
99
|
-
|
|
100
90
|
## What to read next
|
|
101
91
|
|
|
102
92
|
- [Tools](../tools): define your own tools, gate them on approval, and shape their output with `toModelOutput`
|
package/docs/guides/meta.json
CHANGED
|
@@ -60,5 +60,4 @@ Both failure paths surface to the parent as a failed tool result, so the caller
|
|
|
60
60
|
## What to read next
|
|
61
61
|
|
|
62
62
|
- Local delegation and the isolation boundary → [Subagents](../subagents)
|
|
63
|
-
- Have the model orchestrate remote agents programmatically → [Dynamic workflows](./dynamic-workflows)
|
|
64
63
|
- Securing the receiving deployment → [Auth & route protection](./auth-and-route-protection)
|
|
@@ -52,7 +52,7 @@ export default defineTool({
|
|
|
52
52
|
| `mockModel` | `eve/evals` | Deterministic fixture agent models | [Evals](../evals/overview) |
|
|
53
53
|
| `useEveAgent` | `eve/react`, `eve/vue`, `eve/svelte` | frontend | [Frontend](../guides/frontend/overview) |
|
|
54
54
|
|
|
55
|
-
A few non-`define*` helpers round out the set: `disableTool`
|
|
55
|
+
A few non-`define*` helpers round out the set: `disableTool` from `eve/tools` (see [Default harness](../concepts/default-harness)), the route verbs `GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`WS` from `eve/channels`, the approval policies `always`/`once`/`never` from `eve/tools/approval`, and the channel auth helpers `localDev`/`vercelOidc`/`placeholderAuth` from `eve/channels/auth`. To wrap a built-in tool, import its default value from `eve/tools/defaults` (`bash`, `readFile`, `writeFile`, `glob`, `grep`, `webFetch`, `webSearch`, `todo`, `loadSkill`). `AgentReasoningDefinition` is exported from `eve` for the top-level `defineAgent({ reasoning })` setting. `AgentWorkflowDefinition` and `AgentWorkflowWorldDefinition` are exported from `eve` for the `defineAgent({ experimental: { workflow } })` config shape.
|
|
56
56
|
|
|
57
57
|
## Runtime context (`ctx`)
|
|
58
58
|
|
|
@@ -68,31 +68,31 @@ A few non-`define*` helpers round out the set: `disableTool` and `ExperimentalWo
|
|
|
68
68
|
|
|
69
69
|
## Imports at a glance
|
|
70
70
|
|
|
71
|
-
| Import | Holds
|
|
72
|
-
| ----------------------------------------------------------- |
|
|
73
|
-
| `eve` | `defineAgent`, `defineRemoteAgent`, agent config types
|
|
74
|
-
| `eve/tools` | `defineTool`, `defineDynamic`, `disableTool
|
|
75
|
-
| `eve/tools/defaults` | the built-in tools as plain values
|
|
76
|
-
| `eve/tools/approval` | `always`, `once`, `never`
|
|
77
|
-
| `eve/connections` | `defineMcpClientConnection`, `defineOpenAPIConnection`
|
|
78
|
-
| `eve/channels` | `defineChannel`, route verbs
|
|
79
|
-
| `eve/channels/eve` | `eveChannel`
|
|
80
|
-
| `eve/channels/auth` | `localDev`, `vercelOidc`, `placeholderAuth`
|
|
81
|
-
| `eve/channels/{slack,discord,teams,telegram,twilio,github}` | platform channel factories
|
|
82
|
-
| `eve/hooks` | `defineHook`
|
|
83
|
-
| `eve/schedules` | `defineSchedule`
|
|
84
|
-
| `eve/skills` | `defineSkill`, `defineDynamic`
|
|
85
|
-
| `eve/instructions` | `defineInstructions`, `defineDynamic`
|
|
86
|
-
| `eve/context` | `defineState`, session and state types
|
|
87
|
-
| `eve/sandbox` | `defineSandbox`, backends
|
|
88
|
-
| `eve/instrumentation` | `defineInstrumentation`, `isChannel`
|
|
89
|
-
| `eve/evals` | `defineEval`, `defineEvalConfig`, `mockModel`, eval types
|
|
90
|
-
| `eve/evals/expect` | `includes`, `equals`, `matches`, `similarity`
|
|
91
|
-
| `eve/evals/reporters` | `Braintrust`, `JUnit`, `EvalReporter`
|
|
92
|
-
| `eve/evals/loaders` | `loadJson`, `loadYaml`
|
|
93
|
-
| `eve/react`, `eve/vue`, `eve/svelte` | `useEveAgent`
|
|
94
|
-
| `eve/next`, `eve/nuxt`, `eve/sveltekit` | framework bundler plugins
|
|
95
|
-
| [`eve/client`](../guides/client/overview) | `Client`, `ClientSession`
|
|
71
|
+
| Import | Holds |
|
|
72
|
+
| ----------------------------------------------------------- | --------------------------------------------------------- |
|
|
73
|
+
| `eve` | `defineAgent`, `defineRemoteAgent`, agent config types |
|
|
74
|
+
| `eve/tools` | `defineTool`, `defineDynamic`, `disableTool` |
|
|
75
|
+
| `eve/tools/defaults` | the built-in tools as plain values |
|
|
76
|
+
| `eve/tools/approval` | `always`, `once`, `never` |
|
|
77
|
+
| `eve/connections` | `defineMcpClientConnection`, `defineOpenAPIConnection` |
|
|
78
|
+
| `eve/channels` | `defineChannel`, route verbs |
|
|
79
|
+
| `eve/channels/eve` | `eveChannel` |
|
|
80
|
+
| `eve/channels/auth` | `localDev`, `vercelOidc`, `placeholderAuth` |
|
|
81
|
+
| `eve/channels/{slack,discord,teams,telegram,twilio,github}` | platform channel factories |
|
|
82
|
+
| `eve/hooks` | `defineHook` |
|
|
83
|
+
| `eve/schedules` | `defineSchedule` |
|
|
84
|
+
| `eve/skills` | `defineSkill`, `defineDynamic` |
|
|
85
|
+
| `eve/instructions` | `defineInstructions`, `defineDynamic` |
|
|
86
|
+
| `eve/context` | `defineState`, session and state types |
|
|
87
|
+
| `eve/sandbox` | `defineSandbox`, backends |
|
|
88
|
+
| `eve/instrumentation` | `defineInstrumentation`, `isChannel` |
|
|
89
|
+
| `eve/evals` | `defineEval`, `defineEvalConfig`, `mockModel`, eval types |
|
|
90
|
+
| `eve/evals/expect` | `includes`, `equals`, `matches`, `similarity` |
|
|
91
|
+
| `eve/evals/reporters` | `Braintrust`, `JUnit`, `EvalReporter` |
|
|
92
|
+
| `eve/evals/loaders` | `loadJson`, `loadYaml` |
|
|
93
|
+
| `eve/react`, `eve/vue`, `eve/svelte` | `useEveAgent` |
|
|
94
|
+
| `eve/next`, `eve/nuxt`, `eve/sveltekit` | framework bundler plugins |
|
|
95
|
+
| [`eve/client`](../guides/client/overview) | `Client`, `ClientSession` |
|
|
96
96
|
|
|
97
97
|
Exported types ship from the same entrypoint as the helper they describe (for example `ToolDefinition` and `ToolContext` from `eve/tools`). For the exhaustive list, read `packages/eve/src/public/index.ts`.
|
|
98
98
|
|
package/docs/subagents.mdx
CHANGED
|
@@ -99,4 +99,3 @@ Split out a subagent when the task needs a different prompt or specialist role,
|
|
|
99
99
|
## What to read next
|
|
100
100
|
|
|
101
101
|
- [Remote agents](./guides/remote-agents): call another eve deployment as a subagent.
|
|
102
|
-
- [Dynamic workflows](./guides/dynamic-workflows): have the model orchestrate its subagents programmatically (fan-out, map-reduce).
|
package/package.json
CHANGED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Dynamic Workflows"
|
|
3
|
-
description: "The experimental Workflow tool: let the model orchestrate its own subagents from model-authored JavaScript as one durable step."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
The experimental `Workflow` tool lets the model write JavaScript that coordinates the agent's own subagents as a single durable step. The program can run them in sequence, feed one result into the next, fan out over a list, and combine the results. You enable the capability and the model decides and runs the orchestration.
|
|
7
|
-
|
|
8
|
-
A single turn can already call several subagents, and parallel tool calls dispatch concurrently. What a workflow adds is _programmatic_ coordination. The program decides how many subagents to run based on an earlier result, which output feeds which call, and how to combine everything. That is logic the model cannot express as a few one-off calls.
|
|
9
|
-
|
|
10
|
-
## Enable the Workflow tool
|
|
11
|
-
|
|
12
|
-
Re-export the opt-in marker as the default export of `agent/tools/workflow.ts`. The marker name carries the "experimental" warning, but the tool the model actually sees is named `Workflow`.
|
|
13
|
-
|
|
14
|
-
```ts title="agent/tools/workflow.ts"
|
|
15
|
-
export { ExperimentalWorkflow as default } from "eve/tools";
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
Without that file, the `Workflow` tool stays off. It earns its keep only when the agent has subagents (or the built-in `agent`) worth coordinating:
|
|
19
|
-
|
|
20
|
-
```ts title="agent/subagents/analyst/agent.ts"
|
|
21
|
-
import { defineAgent } from "eve";
|
|
22
|
-
|
|
23
|
-
export default defineAgent({
|
|
24
|
-
description: "Analyzes one metric: queries, computes, writes a short finding.",
|
|
25
|
-
model: "anthropic/claude-opus-4.8",
|
|
26
|
-
});
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
When asked for a weekly business review, the model picks the metrics, runs one `analyst` per metric in parallel, and combines the findings. The program below is the kind of JavaScript the model authors. It fans `analyst` out over a runtime-decided list of metrics and merges the results:
|
|
30
|
-
|
|
31
|
-
```js
|
|
32
|
-
const metrics = ["revenue", "signups", "churn"];
|
|
33
|
-
const findings = await Promise.all(
|
|
34
|
-
metrics.map((metric) => tools.analyst({ message: `Summarize last week's ${metric}.` })),
|
|
35
|
-
);
|
|
36
|
-
return findings.join("\n\n");
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Each `tools.analyst(...)` call dispatches a child subagent, so the parent stream records one `subagent.called` per metric and one `subagent.completed` as each finishes:
|
|
40
|
-
|
|
41
|
-
```json
|
|
42
|
-
{ "type": "subagent.called", "data": { "name": "analyst", "toolName": "analyst", "callId": "call_1", "childSessionId": "ses_a1", "sequence": 0 } }
|
|
43
|
-
{ "type": "subagent.called", "data": { "name": "analyst", "toolName": "analyst", "callId": "call_2", "childSessionId": "ses_a2", "sequence": 1 } }
|
|
44
|
-
{ "type": "subagent.called", "data": { "name": "analyst", "toolName": "analyst", "callId": "call_3", "childSessionId": "ses_a3", "sequence": 2 } }
|
|
45
|
-
{ "type": "subagent.completed", "data": { "subagentName": "analyst", "callId": "call_1", "output": "..." } }
|
|
46
|
-
{ "type": "subagent.completed", "data": { "subagentName": "analyst", "callId": "call_2", "output": "..." } }
|
|
47
|
-
{ "type": "subagent.completed", "data": { "subagentName": "analyst", "callId": "call_3", "output": "..." } }
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## What a workflow can orchestrate
|
|
51
|
-
|
|
52
|
-
A workflow reaches only this agent's own agents: the built-in `agent` (a copy of itself), declared [subagents](../subagents), and [remote agents](./remote-agents). That is the whole list. No files, network, shell, skills, or connections. A workflow is a coordination layer over subagents, not a place to do other work. Each call can still request structured output via `outputSchema`, exactly like a direct subagent delegation.
|
|
53
|
-
|
|
54
|
-
## Where the JavaScript runs
|
|
55
|
-
|
|
56
|
-
The orchestration code never touches the agent's process. The runtime hands the program text to a small isolated JavaScript engine (a QuickJS sandbox) and runs it there. Nothing from the host realm crosses in, so there is no `process`, no `globalThis` from the agent, and no `import`/`require`. The program can reach exactly two things, the agent functions bridged in as `tools.<name>` and the ordinary language built-ins.
|
|
57
|
-
|
|
58
|
-
That is an allowlist, not a denylist. The sandbox cannot read files, open a socket, or see an environment variable because those are not present, not because each one is blocked in turn. When the program calls an agent function, that call bridges back out to the runtime, which dispatches it exactly like a direct delegation. The orchestration glue stays inside the sandbox.
|
|
59
|
-
|
|
60
|
-
## Durability, approvals, and observability
|
|
61
|
-
|
|
62
|
-
- **Durable.** The whole orchestration counts as one step. Subagents dispatched together run concurrently, and if a run parks (suspends durably without holding compute; see [Execution model & durability](../concepts/execution-model-and-durability)) on a long-running or human-gated child, it resumes where it left off after a restart.
|
|
63
|
-
- **Approval-safe.** A subagent that needs human approval (HITL, human-in-the-loop) mid-run surfaces its request to the user, and the workflow picks back up once that is answered, same as direct delegation.
|
|
64
|
-
- **Observable.** Every orchestrated subagent emits the usual `subagent.called` / `subagent.completed` events on the parent stream and gets its own child session and stream. The telemetry matches direct delegation, so existing dashboards and cost attribution keep working.
|
|
65
|
-
|
|
66
|
-
## What to read next
|
|
67
|
-
|
|
68
|
-
- Declare the subagents a workflow orchestrates → [Subagents](../subagents)
|
|
69
|
-
- Call another deployment as one of those agents → [Remote agents](./remote-agents)
|
|
70
|
-
- The `agent/tools/` opt-in mechanism → [Default harness](../concepts/default-harness)
|