eve 0.41.0 → 0.43.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 +30 -0
- package/dist/src/channel/channel-operations.d.ts +2 -2
- package/dist/src/channel/channel-operations.js +1 -1
- package/dist/src/channel/forwarded-principal.d.ts +4 -4
- package/dist/src/channel/session.d.ts +2 -2
- package/dist/src/channel/session.js +1 -1
- package/dist/src/cli/dev/tui/tool-presentation.js +1 -1
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/index.js +1 -1
- package/dist/src/compiler/extension-compatibility.d.ts +9 -7
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/manifest.d.ts +3 -0
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/normalize-manifest.js +1 -1
- package/dist/src/compiler/normalize-tool.js +1 -1
- package/dist/src/context/build-dynamic-tools.d.ts +5 -5
- package/dist/src/context/build-dynamic-tools.js +1 -1
- package/dist/src/context/dynamic-subagent-lifecycle.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.d.ts +8 -27
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/context/keys.d.ts +10 -14
- package/dist/src/context/keys.js +1 -1
- package/dist/src/context/provider.d.ts +5 -1
- package/dist/src/context/run-step.d.ts +3 -2
- package/dist/src/context/run-step.js +1 -1
- package/dist/src/execution/agent-handle-dispatch.d.ts +3 -0
- package/dist/src/execution/agent-handle-dispatch.js +1 -1
- package/dist/src/execution/delegation-tool.d.ts +9 -1
- package/dist/src/execution/delegation-tool.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-shared.d.ts +14 -1
- package/dist/src/execution/dispatch-runtime-actions-shared.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/history-view.d.ts +9 -0
- package/dist/src/execution/history-view.js +1 -0
- package/dist/src/execution/next-driver-action.d.ts +33 -1
- package/dist/src/execution/node-step.d.ts +5 -2
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/remote-agent-dispatch.d.ts +2 -0
- package/dist/src/execution/remote-agent-dispatch.js +1 -1
- package/dist/src/execution/session-callback-step.d.ts +2 -2
- package/dist/src/execution/session-callback-step.js +1 -1
- package/dist/src/execution/tasks/child/steps.js +1 -1
- package/dist/src/execution/tasks/child/update.d.ts +2 -2
- package/dist/src/execution/tasks/child/update.js +1 -1
- package/dist/src/execution/tasks/child/workflow.js +1 -1
- package/dist/src/execution/tasks/parent/agent-views.d.ts +2 -1
- package/dist/src/execution/tasks/parent/agent-views.js +1 -1
- package/dist/src/execution/tasks/parent/continuation-dispatch.d.ts +6 -0
- package/dist/src/execution/tasks/parent/continuation-dispatch.js +1 -1
- package/dist/src/execution/tasks/parent/control-shared.d.ts +1 -1
- package/dist/src/execution/tasks/parent/control-shared.js +1 -1
- package/dist/src/execution/tasks/parent/delegate.d.ts +20 -6
- package/dist/src/execution/tasks/parent/delegate.js +1 -1
- package/dist/src/execution/tasks/parent/dispatch-task-step.js +1 -1
- package/dist/src/execution/tasks/parent/dispatch.d.ts +13 -1
- package/dist/src/execution/tasks/parent/dispatch.js +1 -1
- package/dist/src/execution/tasks/parent/hitl-proxy-steps.js +1 -1
- package/dist/src/execution/tasks/parent/tool-execution.d.ts +46 -0
- package/dist/src/execution/tasks/parent/tool-execution.js +1 -0
- package/dist/src/execution/tool-auth.d.ts +12 -3
- package/dist/src/execution/tool-auth.js +1 -1
- package/dist/src/execution/turn-cancellation-control.js +1 -1
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/wire/session-inbox-wire.v1.js +1 -1
- package/dist/src/execution/workflow-steps.d.ts +1 -54
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/advertised-tools.js +1 -1
- package/dist/src/harness/background-tools.d.ts +37 -0
- package/dist/src/harness/background-tools.js +1 -0
- package/dist/src/harness/execute-tool.d.ts +10 -1
- package/dist/src/harness/handles/transitions.d.ts +36 -0
- package/dist/src/harness/handles/transitions.js +1 -1
- package/dist/src/harness/messages.d.ts +2 -0
- package/dist/src/harness/messages.js +1 -1
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/harness/tools.d.ts +5 -1
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/harness/types.d.ts +13 -0
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/schema-backed.js +1 -1
- package/dist/src/internal/authored-module-loader.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-capability-transform-plugin.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.d.ts +13 -0
- package/dist/src/internal/workflow-bundle/dynamic-tool-transform.d.ts +7 -31
- package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +4 -4
- package/dist/src/packages/eve-catalog/src/index.js +1 -1
- package/dist/src/public/channels/discord/hitl.d.ts +3 -3
- package/dist/src/public/channels/discord/hitl.js +1 -1
- package/dist/src/public/channels/eve.d.ts +7 -7
- package/dist/src/public/channels/eve.js +1 -1
- package/dist/src/public/channels/mcp.js +1 -1
- package/dist/src/public/channels/slack/hitl.d.ts +4 -5
- package/dist/src/public/channels/slack/hitl.js +2 -2
- package/dist/src/public/channels/slack/interactions.js +1 -1
- package/dist/src/public/channels/slack/session-operations.d.ts +2 -2
- package/dist/src/public/channels/slack/slackChannel.d.ts +4 -4
- package/dist/src/public/channels/teams/hitl.d.ts +2 -2
- package/dist/src/public/channels/teams/hitl.js +1 -1
- package/dist/src/public/channels/telegram/hitl.d.ts +4 -4
- package/dist/src/public/channels/telegram/hitl.js +1 -1
- package/dist/src/public/definitions/remote-agent.d.ts +7 -5
- package/dist/src/public/definitions/tool.d.ts +23 -0
- package/dist/src/public/definitions/tool.js +1 -1
- package/dist/src/public/tools/approval/approval-helpers.js +1 -1
- package/dist/src/public/tools/index.d.ts +1 -1
- package/dist/src/runtime/framework-tools/ask-question.js +1 -1
- package/dist/src/runtime/framework-tools/connection-search-dynamic.js +2 -2
- package/dist/src/runtime/framework-tools/subagent/local.d.ts +41 -0
- package/dist/src/runtime/framework-tools/subagent/local.js +1 -0
- package/dist/src/runtime/framework-tools/subagent/remote.d.ts +23 -0
- package/dist/src/runtime/framework-tools/subagent/remote.js +1 -0
- package/dist/src/runtime/framework-tools/tasks.d.ts +13 -12
- package/dist/src/runtime/framework-tools/tasks.js +1 -1
- package/dist/src/runtime/input/types.d.ts +19 -1
- package/dist/src/runtime/input/types.js +1 -1
- package/dist/src/runtime/prompt/compose.js +1 -1
- package/dist/src/runtime/resolve-tool.js +1 -1
- package/dist/src/runtime/session-callback-route.js +1 -1
- package/dist/src/setup/integrations/linq/management.d.ts +5 -0
- package/dist/src/setup/integrations/linq/management.js +1 -0
- package/dist/src/setup/integrations/linq/setup.d.ts +5 -1
- package/dist/src/setup/integrations/linq/setup.js +3 -3
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +4 -10
- package/dist/src/setup/scaffold/create/web-template.d.ts +0 -1
- package/dist/src/setup/scaffold/create/web-template.js +1 -1
- package/dist/src/setup/scaffold/update/channels.d.ts +1 -1
- package/dist/src/setup/scaffold/update/channels.js +2 -2
- package/dist/src/setup/scaffold/update/package-json.d.ts +0 -2
- package/dist/src/setup/scaffold/update/package-json.js +1 -1
- package/dist/src/setup/scaffold/workspace-root.d.ts +0 -1
- package/dist/src/setup/scaffold/workspace-root.js +1 -1
- package/dist/src/shared/durable-dynamic-tool-callbacks.d.ts +34 -0
- package/dist/src/shared/durable-dynamic-tool-callbacks.js +1 -0
- package/dist/src/shared/dynamic-tool-definition.d.ts +2 -4
- package/dist/src/shared/empty-delivery.js +1 -1
- package/dist/src/shared/history-view.d.ts +22 -0
- package/dist/src/shared/history-view.js +1 -0
- package/dist/src/shared/json.d.ts +2 -0
- package/dist/src/shared/json.js +1 -1
- package/dist/src/shared/tool-definition.d.ts +4 -1
- package/dist/src/shared/tool-task.d.ts +107 -0
- package/dist/src/shared/tool-task.js +1 -0
- package/dist/src/tasks/delivery-context.d.ts +12 -0
- package/dist/src/tasks/delivery-context.js +17 -0
- package/dist/src/tasks/json.d.ts +25 -10
- package/dist/src/tasks/json.js +1 -1
- package/dist/src/tasks/session-index.d.ts +5 -3
- package/dist/src/tasks/session-index.js +1 -1
- package/dist/src/tasks/transitions.d.ts +40 -5
- package/dist/src/tasks/transitions.js +1 -1
- package/dist/src/tasks/types.d.ts +46 -4
- package/dist/src/tasks/types.js +1 -1
- package/docs/channels/custom.mdx +12 -0
- package/docs/channels/linq.mdx +1 -1
- package/docs/getting-started.mdx +36 -36
- package/docs/guides/auth-and-route-protection.md +6 -2
- package/docs/guides/dynamic-capabilities.md +12 -10
- package/docs/guides/remote-agents.md +10 -2
- package/docs/tools/overview.mdx +19 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import{formatAvailableSkillsSection}from"#execution/skills/instructions.js";import{createWorkspacePromptSection}from"#runtime/workspace/spec.js";import{formatConnectionsSection}from"#runtime/prompt/connections.js";function composeRuntimeBasePrompt(e){return[...createInstructionsPromptBlocks(e.instructions),...createWorkspacePromptBlocks(e.workspaceSpec),...e.toolsAvailable?[`Tool execution
|
|
2
|
-
A single tool or subagent call runs as one serial action. If you call multiple independent tools or subagents in one response, eve treats that batch as parallel work. Only batch work that is independent and does not rely on another call in the same response.`]:[],...e.subagentsAvailable&&e.persistentSubagentSessions?[e.tasksEnabled?"Agent messaging\nSubagent calls start durable background tasks and return immediately with a task receipt. After delegating, continue helping the user or end your turn
|
|
2
|
+
A single tool or subagent call runs as one serial action. If you call multiple independent tools or subagents in one response, eve treats that batch as parallel work. Only batch work that is independent and does not rely on another call in the same response.`]:[],...e.subagentsAvailable&&e.persistentSubagentSessions?[e.tasksEnabled?"Agent messaging\nSubagent calls start durable background tasks and return immediately with a task receipt. After delegating, continue helping the user or end your turn. The task will notify you when it completes, fails, needs input, or sends an update; completion and failure notifications include the task's result. Agents you have already delegated to remain visible in the framework-authored `<agents>` conversation note. `availability=busy` means the listed task still owns that agent session: wait for its notification or use task_cancel with its taskId instead of starting a continuation. `availability=available` means no nonterminal task owns the session, so you may pass agentId to the original subagent tool to continue it. Calling a subagent without agentId always starts a new agent session.":"Agent messaging\nAgents you have already delegated to stay available after they answer. eve injects the current `<agents>` list into the conversation as a note labeled `[Agents]`; it is added automatically by the framework, not written by the user, and never requires a reply. The list is only a record of those existing agents — their `agentId`, name, and latest status. It does not limit which subagent tools you can call: your tool list is the source of truth, and any subagent tool can always be called without `agentId` to start a new agent, including when the `<agents>` list is empty or absent. Pass `agentId` to the same subagent tool only to continue one of those existing agents' sessions."]:[],...createConnectionsPromptBlocks(e.connections),...createSkillsPromptBlocks(e.skills)]}function createInstructionsPromptBlocks(e){let t=(e??[]).filter(e=>e.role===`system`&&e.content.trim().length>0);if(t.length===0)return[];let n=t.length===1?t[0]:void 0;return[`Instructions (${n!==void 0&&!n.sourceId.startsWith(`ext:`)&&!n.sourceId.startsWith(`ext-override:`)?n.name:`instructions`})\n${t.map(e=>e.content).join(`
|
|
3
3
|
|
|
4
4
|
`).trim()}`]}function createWorkspacePromptBlocks(e){if(e===void 0)return[];let n=createWorkspacePromptSection(e);return n===void 0?[]:[n]}function createConnectionsPromptBlocks(e){return!e||e.length===0?[]:[formatConnectionsSection(e)]}function createSkillsPromptBlocks(t){if(!t||t.length===0)return[];let n=formatAvailableSkillsSection(t);return n===null?[]:[n]}export{composeRuntimeBasePrompt};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{isToolSchema,toInputSchema,toOutputSchema}from"#shared/tool-schema.js";import{normalizeApproval}from"#internal/authored-definition/approval.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{registerDefinitionSource,stampDefinitionKey}from"#public/tool-result-narrowing.js";async function resolveToolDefinition(i,o,s){try{let n=expectObjectRecord(await loadResolvedModuleExport({definition:i,kindLabel:`tool`,moduleMap:o,nodeId:s}),describe(i,`to return an object`)),a={kind:`tool`,logicalPath:i.logicalPath,name:i.name},c=`tool-source:${i.sourceId}`;stampDefinitionKey(n,c),registerDefinitionSource(c,a),registerDefinitionSource(`tool:${n.description}`,a);let l=expectFunction(n.execute,describe(i,`to provide an execute function`)),u=isToolSchema(n.inputSchema)?n.inputSchema:toInputSchema(i.inputSchema),d=isToolSchema(n.outputSchema)?n.outputSchema:toOutputSchema(i.outputSchema);return{description:i.description,execute:l,exportName:i.exportName,inputSchema:u,logicalPath:i.logicalPath,name:i.name,outputSchema:d,sourceId:i.sourceId,sourceKind:`module`,...extractOptionalHooks(n,i)}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to attach the tool execute function from "${i.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:i.logicalPath,sourceId:i.sourceId})}}function extractOptionalHooks(t,n){let r={};return t.approval!==void 0&&(r.approval=normalizeApproval(t.approval,describe(n,`to provide a valid approval definition`))),t.toModelOutput!==void 0&&(r.toModelOutput=expectFunction(t.toModelOutput,describe(n,`to provide a toModelOutput function`))),r}function describe(e,t){return`Expected the tool export "${e.exportName??`default`}" from "${e.logicalPath}" ${t}.`}export{resolveToolDefinition};
|
|
1
|
+
import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{isToolSchema,toInputSchema,toOutputSchema}from"#shared/tool-schema.js";import{normalizeApproval}from"#internal/authored-definition/approval.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{registerDefinitionSource,stampDefinitionKey}from"#public/tool-result-narrowing.js";async function resolveToolDefinition(i,o,s){try{let n=expectObjectRecord(await loadResolvedModuleExport({definition:i,kindLabel:`tool`,moduleMap:o,nodeId:s}),describe(i,`to return an object`)),a={kind:`tool`,logicalPath:i.logicalPath,name:i.name},c=`tool-source:${i.sourceId}`;stampDefinitionKey(n,c),registerDefinitionSource(c,a),registerDefinitionSource(`tool:${n.description}`,a);let l=expectFunction(n.execute,describe(i,`to provide an execute function`)),u=isToolSchema(n.inputSchema)?n.inputSchema:toInputSchema(i.inputSchema),d=isToolSchema(n.outputSchema)?n.outputSchema:toOutputSchema(i.outputSchema);return{description:i.description,execute:l,execution:i.execution,exportName:i.exportName,inputSchema:u,logicalPath:i.logicalPath,name:i.name,outputSchema:d,sourceId:i.sourceId,sourceKind:`module`,...extractOptionalHooks(n,i)}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to attach the tool execute function from "${i.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:i.logicalPath,sourceId:i.sourceId})}}function extractOptionalHooks(t,n){let r={};return t.approval!==void 0&&(r.approval=normalizeApproval(t.approval,describe(n,`to provide a valid approval definition`))),t.toModelOutput!==void 0&&(r.toModelOutput=expectFunction(t.toModelOutput,describe(n,`to provide a toModelOutput function`))),r}function describe(e,t){return`Expected the tool export "${e.exportName??`default`}" from "${e.logicalPath}" ${t}.`}export{resolveToolDefinition};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{isInputRequest}from"#runtime/input/types.js";import{z}from"#compiled/zod/index.js";import{EVE_CALLBACK_ROUTE_PATTERN}from"#protocol/routes.js";import{jsonValueSchema}from"#shared/json-schemas.js";import{REMOTE_AGENT_FAILED}from"#harness/agent-handle-errors.js";import{readTaskIdFromInboxToken}from"#tasks/task-id.js";import{resumeHook}from"#internal/workflow/runtime.js";import{tokenUsageSchema}from"#shared/token-usage.js";import{agentTurnOutcomeSchema}from"#shared/agent-turn-outcome.js";const HTTP_SESSION_CALLBACK_CHANNEL_NAME_PREFIX=`eve/v1/callback`,HANDLED_METHODS=[`POST`],ZERO_TOKEN_USAGE={cacheReadTokens:0,cacheWriteTokens:0,inputTokens:0,outputTokens:0},eventCoordinateSchema=z.number().int().nonnegative(),authorizationChallengeSchema=z.looseObject({displayName:z.string().optional(),expiresAt:z.string().optional(),instructions:z.string().optional(),url:z.string().optional(),userCode:z.string().optional()}),taskInputEventSchema=z.looseObject({requests:z.array(jsonValueSchema.refine(isInputRequest)).min(1),sequence:eventCoordinateSchema,stepIndex:eventCoordinateSchema,turnId:z.string()}),taskAuthorizationEventSchema=z.discriminatedUnion(`type`,[z.looseObject({data:z.looseObject({attemptId:z.string().optional(),authorization:authorizationChallengeSchema.optional(),description:z.string(),name:z.string(),sequence:eventCoordinateSchema,stepIndex:eventCoordinateSchema,turnId:z.string(),webhookUrl:z.string().optional()}),type:z.literal(`authorization.required`)}),z.looseObject({data:z.looseObject({attemptId:z.string().optional(),authorization:authorizationChallengeSchema.optional(),name:z.string(),outcome:z.enum([`authorized`,`declined`,`failed`,`timed-out`]),reason:z.string().optional(),sequence:eventCoordinateSchema,stepIndex:eventCoordinateSchema,turnId:z.string()}),type:z.literal(`authorization.completed`)})]),taskEventCallbackSchema=z.discriminatedUnion(`kind`,[z.object({callId:z.string(),childContinuationToken:z.string(),childSessionId:z.string(),event:taskInputEventSchema,kind:z.literal(`task.input-requested`),subagentName:z.string(),taskId:z.string()}),z.object({callId:z.string(),childContinuationToken:z.string(),childSessionId:z.string(),event:taskAuthorizationEventSchema,kind:z.literal(`task.authorization`),subagentName:z.string(),taskId:z.string()})]),taskTurnStartedCallbackSchema=z.object({kind:z.literal(`turn.started`),sessionId:z.string().min(1),taskId:z.string().min(1),turnId:z.string().min(1)}),taskUpdateCallbackSchema=z.object({callId:z.string().min(1),kind:z.literal(`task.update`),message:z.string().min(1),taskId:z.string().min(1),updateEpoch:z.string().min(1),updateIndex:eventCoordinateSchema}),sessionResultCallbackSchema=z.discriminatedUnion(`kind`,[z.object({callId:z.string().min(1),kind:z.literal(`session.completed`),output:jsonValueSchema.optional(),subagentName:z.string().min(1),usage:z.unknown().optional()}),z.object({callId:z.string().min(1),error:jsonValueSchema.optional(),kind:z.literal(`session.failed`),subagentName:z.string().min(1),usage:z.unknown().optional()}),z.object({callId:z.string().min(1),kind:z.literal(`turn.completed`),outcome:agentTurnOutcomeSchema,output:jsonValueSchema.optional(),subagentName:z.string().min(1)}),z.object({callId:z.string().min(1),error:jsonValueSchema,kind:z.literal(`turn.failed`),outcome:agentTurnOutcomeSchema,subagentName:z.string().min(1)})]);function getSessionCallbackChannelDefinitions(){return HANDLED_METHODS.map(e=>buildCallbackChannelDefinition(e))}function getSessionCallbackChannelNames(){return new Set(HANDLED_METHODS.map(channelNameForMethod))}function buildCallbackChannelDefinition(e){let t=channelNameForMethod(e);return{name:t,method:e,urlPath:EVE_CALLBACK_ROUTE_PATTERN,fetch:handleSessionCallbackRequest,logicalPath:`framework://channels/${t}`,sourceId:`eve:framework:session-callback-${e.toLowerCase()}`,sourceKind:`module`}}function channelNameForMethod(e){return`${HTTP_SESSION_CALLBACK_CHANNEL_NAME_PREFIX}/${e.toLowerCase()}`}async function handleSessionCallbackRequest(e,t){let n=t.params.token;if(typeof n!=`string`||n.length===0)return Response.json({error:`Missing callback token.`,ok:!1},{status:400});let r;try{r=await e.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}let i=projectTaskEvent(r,n);if(i instanceof Response)return i;if(i!==void 0){try{await resumeHook(n,i)}catch{return Response.json({error:`Session callback not pending.`,ok:!1},{status:404})}return Response.json({ok:!0},{status:202})}let a=projectTaskUpdate(r,n);if(a instanceof Response)return a;if(a!==void 0){try{await resumeHook(n,a)}catch{return Response.json({error:`Session callback not pending.`,ok:!1},{status:404})}return Response.json({ok:!0},{status:202})}let o=projectTaskTurnStarted(r,n);if(o instanceof Response)return o;if(o!==void 0){try{await resumeHook(n,o)}catch{return Response.json({error:`Session callback not pending.`,ok:!1},{status:404})}return Response.json({ok:!0},{status:202})}let s=projectSessionCallbackResult(r);if(s instanceof Response)return s;try{await resumeHook(n,{kind:`runtime-action-result`,results:[s]})}catch{return Response.json({error:`Session callback not pending.`,ok:!1},{status:404})}return Response.json({ok:!0},{status:202})}function callbackKind(e){if(!(typeof e!=`object`||!e))return Reflect.get(e,`kind`)}function projectTaskEvent(e,t){let n=callbackKind(e);if(n!==`task.input-requested`&&n!==`task.authorization`)return;let r=taskEventCallbackSchema.safeParse(e);if(!r.success)return Response.json({error:`Invalid task event callback.`,ok:!1},{status:400});let i=r.data,a=rejectMismatchedTaskToken(t,i.taskId);return a===void 0?i.kind===`task.input-requested`?{callId:i.callId,childContinuationToken:i.childContinuationToken,childSessionId:i.childSessionId,event:i.event,kind:`subagent-input-request`,subagentName:i.subagentName}:{callId:i.callId,childSessionId:i.childSessionId,event:i.event,kind:`authorization-event`,subagentName:i.subagentName}:a}function projectTaskTurnStarted(e,t){if(callbackKind(e)!==`turn.started`)return;let n=taskTurnStartedCallbackSchema.safeParse(e);if(!n.success)return Response.json({error:`Invalid task turn-start callback.`,ok:!1},{status:400});let r=rejectMismatchedTaskToken(t,n.data.taskId);return r===void 0?{childSessionId:n.data.sessionId,childTurnId:n.data.turnId,kind:`turn-started`,taskId:n.data.taskId}:r}function projectTaskUpdate(e,t){if(callbackKind(e)!==`task.update`)return;let n=taskUpdateCallbackSchema.safeParse(e);if(!n.success)return Response.json({error:`Invalid task update callback.`,ok:!1},{status:400});let r=rejectMismatchedTaskToken(t,n.data.taskId);return r===void 0?{callId:n.data.callId,kind:`task-update`,message:n.data.message,updateEpoch:n.data.updateEpoch,updateIndex:n.data.updateIndex}:r}function rejectMismatchedTaskToken(e,t){return readTaskIdFromInboxToken(e)===t?void 0:Response.json({error:`Task callback token mismatch.`,ok:!1},{status:403})}function projectSessionCallbackResult(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let t=callbackKind(e);if(t!==`session.completed`&&t!==`session.failed`&&t!==`turn.completed`&&t!==`turn.failed`)return Response.json({error:`Unsupported callback kind.`,ok:!1},{status:400});let n=sessionResultCallbackSchema.safeParse(e);if(!n.success)return Response.json({error:`Invalid session result callback.`,ok:!1},{status:400});let r=n.data;if(r.kind===`session.completed`){let e=r.output??``,t=parseCallbackUsage(r.usage),n={callId:r.callId,kind:`subagent-result`,origin:`child`,outcome:{kind:`terminal`,result:{kind:`succeeded`,output:e},usageDelta:t??ZERO_TOKEN_USAGE},output:e,subagentName:r.subagentName};return t===void 0?n:{...n,usage:t}}if(r.kind===`session.failed`){let e=r.error===void 0?{code:REMOTE_AGENT_FAILED,message:`Remote agent failed.`}:r.error,t=parseCallbackUsage(r.usage);return{callId:r.callId,isError:!0,kind:`subagent-result`,origin:`child`,outcome:{kind:`terminal`,result:{error:e,kind:`failed`},usageDelta:t??ZERO_TOKEN_USAGE},output:e,subagentName:r.subagentName}}return r.kind===`turn.completed`?{callId:r.callId,kind:`subagent-result`,origin:`child`,outcome:r.outcome,output:r.output??``,subagentName:r.subagentName,usage:r.outcome.usageDelta}:{callId:r.callId,isError:!0,kind:`subagent-result`,origin:`child`,outcome:r.outcome,output:r.error,subagentName:r.subagentName}}function parseCallbackUsage(e){if(e===void 0)return;let t=tokenUsageSchema.safeParse(e);return t.success?t.data:void 0}export{HTTP_SESSION_CALLBACK_CHANNEL_NAME_PREFIX,getSessionCallbackChannelDefinitions,getSessionCallbackChannelNames,handleSessionCallbackRequest};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z}from"#compiled/zod/index.js";const PhoneNumbersSchema=z.object({phone_numbers:z.array(z.object({phone_number:z.string().min(1)}))}),defaultDeps={fetch};async function listLinqPhoneNumbers(e,t,n=defaultDeps){let r=await n.fetch(`https://api.linqapp.com/api/partner/v3/phone_numbers`,{headers:{accept:`application/json`,authorization:`Bearer ${e}`},signal:t});if(!r.ok)throw Error(`Could not fetch Linq phone numbers (${r.status}). Confirm the partner API token is valid.`);let i=PhoneNumbersSchema.safeParse(await r.json());if(!i.success)throw Error(`Linq returned invalid phone number data.`);let a=i.data.phone_numbers.map(({phone_number:e})=>e);if(a.length===0)throw Error(`No phone numbers are assigned to this Linq partner API token.`);return a}export{listLinqPhoneNumbers};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { VercelProjectReference } from "#setup/project-resolution.js";
|
|
2
2
|
import { type LinqExistingAccountCredentials } from "./connect.js";
|
|
3
|
+
import { listLinqPhoneNumbers } from "./management.js";
|
|
3
4
|
import { type SetupApplyContext, type SetupPrepareContext } from "../types.js";
|
|
5
|
+
export interface LinqSetupDeps {
|
|
6
|
+
listPhoneNumbers: typeof listLinqPhoneNumbers;
|
|
7
|
+
}
|
|
4
8
|
interface LinqSetupPlan {
|
|
5
9
|
credentials: "connect" | "portable";
|
|
6
10
|
connectorSlug?: string;
|
|
@@ -9,7 +13,7 @@ interface LinqSetupPlan {
|
|
|
9
13
|
apiKey?: string;
|
|
10
14
|
signingSecret?: string;
|
|
11
15
|
}
|
|
12
|
-
export declare function prepareLinqSetup(context: SetupPrepareContext): Promise<LinqSetupPlan>;
|
|
16
|
+
export declare function prepareLinqSetup(context: SetupPrepareContext, deps?: LinqSetupDeps): Promise<LinqSetupPlan>;
|
|
13
17
|
export declare function applyLinqSetup(plan: LinqSetupPlan, context: SetupApplyContext): Promise<{
|
|
14
18
|
facts: {
|
|
15
19
|
label: string;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import{defineSetupIntegration}from"../types.js";import{provisionLinqConnector}from"./connect.js";import{join}from"node:path";import{deriveSlackConnectorSlug}from"#setup/scaffold/index.js";import{select,text}from"#setup/ask.js";import{writeTextFile}from"#setup/scaffold/files.js";import{appendEnv}from"#setup/append-env.js";
|
|
1
|
+
import{defineSetupIntegration}from"../types.js";import{provisionLinqConnector}from"./connect.js";import{listLinqPhoneNumbers}from"./management.js";import{join}from"node:path";import{deriveSlackConnectorSlug}from"#setup/scaffold/index.js";import{select,text}from"#setup/ask.js";import{writeTextFile}from"#setup/scaffold/files.js";import{appendEnv}from"#setup/append-env.js";const defaultDeps={listPhoneNumbers:listLinqPhoneNumbers};function connectTemplate(e){return`import { connectLinqCredentials } from "@vercel/connect/eve";
|
|
2
2
|
import { linqChannel } from "eve/channels/linq";
|
|
3
3
|
|
|
4
4
|
export default linqChannel({
|
|
5
5
|
credentials: connectLinqCredentials(${JSON.stringify(e)}),
|
|
6
6
|
});
|
|
7
|
-
`}async function prepareLinqSetup(e){let
|
|
7
|
+
`}async function prepareLinqSetup(e,t=defaultDeps){let n=await e.asker.ask(select({key:`linq-credentials`,message:`How would you like to configure Linq?`,options:[{id:`connect`,value:`connect`,label:`Set up Vercel Connect`,hint:`Provision a managed Linq line`},{id:`portable`,value:`portable`,label:`Use portable credentials`,hint:`Register the webhook in Linq`}],recommended:e.environment.vercel.kind===`available`?`connect`:`portable`,required:!0}));if(n===`connect`){if(e.environment.vercel.kind===`unavailable`)throw Error("Vercel Connect requires an authenticated Vercel CLI. Run `vercel login`, then retry Linq setup.");let r=await e.resolveVercelProject(`Linq`),s=await e.asker.ask(text({key:`linq-connector-name`,message:`Name your Linq agent`,recommended:await deriveSlackConnectorSlug(e.appRoot),required:!0}));if(await e.asker.ask(select({key:`linq-account`,message:`Which Linq account would you like to use?`,options:[{id:`new`,value:`new`,label:`Create a new Linq account`,hint:`Provision a new managed Linq line`},{id:`existing`,value:`existing`,label:`Use an existing Linq account`,hint:`Connect a Linq partner API token and select agent phone numbers`}],recommended:`new`,required:!0}))===`new`)return{credentials:n,connectorSlug:s.trim(),project:r};let c=await e.asker.ask(text({key:`linq-existing-api-token`,message:`Linq partner API token`,required:!0,sensitive:!0,environment:`LINQ_API_KEY`})),l=await t.listPhoneNumbers(c.trim(),e.signal),u=await e.asker.askMany({key:`linq-existing-phone-numbers`,message:`Choose your agent's phone numbers`,options:l.map(e=>({id:e,value:e,label:e})),detected:l,requireSelection:!0,required:!0});return{credentials:n,connectorSlug:s.trim(),existingAccount:{apiToken:c.trim(),phoneNumbers:u},project:r}}let r=await e.asker.ask(text({key:`linq-api-key`,message:`Linq API key`,required:!0,sensitive:!0,environment:`LINQ_API_KEY`})),s=await e.asker.ask(text({key:`linq-signing-secret`,message:`Linq webhook signing secret`,required:!0,sensitive:!0,environment:`LINQ_WEBHOOK_SECRET`}));return{credentials:n,apiKey:r.trim(),signingSecret:s.trim()}}async function applyLinqSetup(e,n){let i=join(n.appRoot,`agent/channels/linq.ts`),a;if(e.credentials===`connect`){let r={log:n.presenter.log,project:e.project,projectRoot:n.appRoot,slug:e.connectorSlug,signal:n.signal};e.existingAccount!==void 0&&(r.existingAccount=e.existingAccount);let o=await provisionLinqConnector(r);a=o.phoneNumber,await writeTextFile(i,connectTemplate(o.uid),{force:n.force}),a!==void 0&&n.presenter.note(a,`Text your agent`,{tone:`success`})}else await appendEnv(join(n.appRoot,`.env.local`),{LINQ_API_KEY:e.apiKey,LINQ_WEBHOOK_SECRET:e.signingSecret}),await writeTextFile(i,`import { linqChannel } from "eve/channels/linq";
|
|
8
8
|
|
|
9
9
|
export default linqChannel({
|
|
10
10
|
credentials: {
|
|
@@ -12,4 +12,4 @@ export default linqChannel({
|
|
|
12
12
|
signingSecret: process.env.LINQ_WEBHOOK_SECRET!,
|
|
13
13
|
},
|
|
14
14
|
});
|
|
15
|
-
`,{force:
|
|
15
|
+
`,{force:n.force}),n.presenter.nextSteps([`Deploy the agent, then create a Linq webhook subscription for https://<your-host>/eve/v1/linq with message.received, reaction.added, and reaction.removed events.`]);return n.presenter.log.success(`Scaffolded channel: linq`),{facts:a===void 0?[]:[{label:`Agent phone number`,value:a,kind:`phone`}],deploymentRequired:!0}}const LINQ_SETUP=defineSetupIntegration({kind:`linq`,label:`Linq`,hint:`iMessage and SMS through Linq`,prepare:prepareLinqSetup,apply:applyLinqSetup});export{LINQ_SETUP,applyLinqSetup,prepareLinqSetup};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"../update/package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{agentTemplateFiles,formatEveDependencySpecifier,resolveEvePackageContract}from"./project.js";import{readFile}from"node:fs/promises";import{join}from"node:path";const DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`];function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function hasDeclaredDependency(e,t){if(!isJsonObject(e))return!1;for(let n of DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function addAgentToProject(i){let a=i.packageManager??`pnpm`,o=join(i.projectRoot,`package.json`);if(!await pathExists(o))throw Error(`Cannot add an eve agent to "${i.projectRoot}" because it has no package.json. Run \`eve init <name>\` to create a new project instead.`);let s;try{s=JSON.parse(await readFile(o,`utf8`))}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`Cannot add an eve agent because "${o}" is not valid JSON. No files were changed. Fix the file, then retry eve init. ${t}`)}let c=agentTemplateFiles(i.model,i.reasoning),l=[];for(let t of Object.keys(c))await pathExists(join(i.projectRoot,t))&&l.push(t);if(l.length===0&&await pathExists(join(i.projectRoot,`agent`))&&l.push(`agent/`),l.length>0)throw Error(`Cannot add an eve agent to "${i.projectRoot}" because it already has: ${l.join(`, `)}.`);let u=resolveEvePackageContract(i.evePackage),d=resolveVersionToken(`aiPackageVersion`,i.aiPackageVersion??`^7.0.58`),f=resolveVersionToken(`connectPackageVersion`,i.connectPackageVersion??`0.4.3`),p=resolveVersionToken(`zodPackageVersion`,i.zodPackageVersion??`4.4.3`),m=[];for(let[e,n]of Object.entries(c)){let r=join(i.projectRoot,e);await writeTextFile(r,n),m.push(r)}let h={"@vercel/connect":f,ai:d,eve:formatEveDependencySpecifier(u.version),zod:p},g={};for(let[e,t]of Object.entries(h))hasDeclaredDependency(s,e)||(g[e]=t);let _={};Object.keys(g).length>0&&(_.dependencies=g),isPackageManagerWorkspaceMember(a,i.projectRoot)||(_.nodeEngineRequirement=u.nodeEngine);let v=await patchPackageJson(o,_),y=await patchWorkspaceRootPackageJson(a,i.projectRoot,{
|
|
1
|
+
import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"../update/package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{agentTemplateFiles,formatEveDependencySpecifier,resolveEvePackageContract}from"./project.js";import{readFile}from"node:fs/promises";import{join}from"node:path";const DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`];function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function hasDeclaredDependency(e,t){if(!isJsonObject(e))return!1;for(let n of DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function addAgentToProject(i){let a=i.packageManager??`pnpm`,o=join(i.projectRoot,`package.json`);if(!await pathExists(o))throw Error(`Cannot add an eve agent to "${i.projectRoot}" because it has no package.json. Run \`eve init <name>\` to create a new project instead.`);let s;try{s=JSON.parse(await readFile(o,`utf8`))}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`Cannot add an eve agent because "${o}" is not valid JSON. No files were changed. Fix the file, then retry eve init. ${t}`)}let c=agentTemplateFiles(i.model,i.reasoning),l=[];for(let t of Object.keys(c))await pathExists(join(i.projectRoot,t))&&l.push(t);if(l.length===0&&await pathExists(join(i.projectRoot,`agent`))&&l.push(`agent/`),l.length>0)throw Error(`Cannot add an eve agent to "${i.projectRoot}" because it already has: ${l.join(`, `)}.`);let u=resolveEvePackageContract(i.evePackage),d=resolveVersionToken(`aiPackageVersion`,i.aiPackageVersion??`^7.0.58`),f=resolveVersionToken(`connectPackageVersion`,i.connectPackageVersion??`0.4.3`),p=resolveVersionToken(`zodPackageVersion`,i.zodPackageVersion??`4.4.3`),m=[];for(let[e,n]of Object.entries(c)){let r=join(i.projectRoot,e);await writeTextFile(r,n),m.push(r)}let h={"@vercel/connect":f,ai:d,eve:formatEveDependencySpecifier(u.version),zod:p},g={};for(let[e,t]of Object.entries(h))hasDeclaredDependency(s,e)||(g[e]=t);let _={};Object.keys(g).length>0&&(_.dependencies=g),isPackageManagerWorkspaceMember(a,i.projectRoot)||(_.nodeEngineRequirement=u.nodeEngine);let v=await patchPackageJson(o,_),y=await patchWorkspaceRootPackageJson(a,i.projectRoot,{nodeEngineRequirement:u.nodeEngine}),b=y.nodeEngineOverride??v.nodeEngineOverride,x=await applyPackageManagerWorkspaceConfiguration({packageManager:a,projectRoot:i.projectRoot});return{filesWritten:m,dependenciesAdded:Object.keys(g).sort(),nodeEngineOverride:b,configurationFilesChanged:[...v.changed?[o]:[],...y.changed&&y.path!==void 0?[y.path]:[],...x.filesWritten]}}export{addAgentToProject};
|
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.58`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.3`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.
|
|
1
|
+
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.58`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.3`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.43.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,t){return{"agent/agent.ts":renderAgentTemplate(e,t),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,n){let r=parseChatGptModelSelection(e);return r===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(n)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(r)}),\n${reasoningTemplateLine(n)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,n){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(n.model)!==void 0?renderAgentTemplate(n.model,n.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,n.appName).replaceAll(`__EVE_INIT_MODEL__`,n.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(n.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(n.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(n.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(n.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,n.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,n.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,n.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,n.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,n.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,n.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__",
|
|
5
5
|
__EVE_INIT_REASONING__});
|
|
6
|
-
`;function
|
|
7
|
-
"overrides": {
|
|
8
|
-
"ai": "__EVE_INIT_AI_SDK_VERSION__"
|
|
9
|
-
}`;case`yarn`:return`,
|
|
10
|
-
"resolutions": {
|
|
11
|
-
"ai": "__EVE_INIT_AI_SDK_VERSION__"
|
|
12
|
-
}`;case`pnpm`:return``;default:return e}}function packageJsonTemplate(e){return`{
|
|
6
|
+
`;function packageJsonTemplate(e){return`{
|
|
13
7
|
"name": "__EVE_INIT_APP_NAME__",
|
|
14
8
|
"version": "0.0.0",
|
|
15
9
|
"type": "module",
|
|
@@ -32,7 +26,7 @@ __EVE_INIT_REASONING__});
|
|
|
32
26
|
"devDependencies": {
|
|
33
27
|
"@types/node": "__EVE_INIT_TYPES_NODE_VERSION__",
|
|
34
28
|
"typescript": "__EVE_INIT_TYPESCRIPT_VERSION__"
|
|
35
|
-
}${e
|
|
29
|
+
}${e?ROOT_ONLY_PACKAGE_JSON_TEMPLATE_SUFFIX:``}
|
|
36
30
|
}
|
|
37
31
|
`}const ROOT_ONLY_PACKAGE_JSON_TEMPLATE_SUFFIX=`,
|
|
38
32
|
"engines": {
|
|
@@ -86,4 +80,4 @@ __EVE_INIT_REASONING__ modelOptions: {
|
|
|
86
80
|
},
|
|
87
81
|
},
|
|
88
82
|
});
|
|
89
|
-
`:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(
|
|
83
|
+
`:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(e.includeRootOnlyPackageJsonFields)}}async function assertCanCreateInPlace(e,t){if(!await pathExists(e))return;let n=blockingCreateInPlaceEntries(await readdir(e));if(n.length>0&&!t){let e=n.slice(0,5).join(`, `),t=n.length>5?`, and ${n.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${e}${t}. Use an empty directory.`)}}async function scaffoldBaseProject(t){let n=resolve(t.targetDirectory??process.cwd(),t.projectName),i=t.projectName===`.`,c=t.overwriteExisting??!1,l=t.byokProvider??!1,u=t.packageManager??`pnpm`,d=resolveEvePackageContract(t.evePackage),f=pinnedNodeEngineMajor(d.nodeEngine),p=resolve(t.workspaceProbeDirectory??n),m=isPackageManagerWorkspaceMember(u,p);if(i)await assertCanCreateInPlace(n,c);else if(await pathExists(n))throw Error(`Cannot create project because "${n}" already exists.`);let h={appName:basename(n),model:t.model,reasoning:t.reasoning,eveVersion:d.version,aiPackageVersion:resolveVersionToken(`aiPackageVersion`,t.aiPackageVersion??`^7.0.58`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,t.connectPackageVersion??`0.4.3`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,t.zodPackageVersion??`4.4.3`),typescriptPackageVersion:resolveVersionToken(`typescriptPackageVersion`,t.typescriptPackageVersion??`7.0.2`),nodeTypesVersion:f,nodeEngine:f};await mkdir(n,{recursive:!0});for(let[e,a]of Object.entries(templateFiles({byokProvider:l,includeRootOnlyPackageJsonFields:!m}))){let o=`${n}/${e}`,s=await pathExists(o);await writeTextFile(o,renderTemplate(a,h),{force:i&&c}),s&&await t.onOverwriteFile?.(o)}return await applyPackageManagerWorkspaceConfiguration({packageManager:u,projectRoot:n,workspaceProbeRoot:p,onWorkspaceRootMutation:t.onWorkspaceRootMutation}),await patchWorkspaceRootPackageJson(u,p,{nodeEngineRequirement:d.nodeEngine,onWorkspaceRootMutation:t.onWorkspaceRootMutation}),n}async function isEveProject(e){for(let t of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(e,`agent`,`agent${t}`)),!0}catch{}return!1}export{CURRENT_DIRECTORY_PROJECT_NAME,DEFAULT_AI_PACKAGE_VERSION,DEFAULT_CONNECT_PACKAGE_VERSION,DEFAULT_EVE_PACKAGE_CONTRACT,DEFAULT_ZOD_PACKAGE_VERSION,ROOT_ONLY_PACKAGE_JSON_TEMPLATE_SUFFIX,agentTemplateFiles,byokProviderEnvVar,formatEveDependencySpecifier,isEveProject,modelProviderSlug,resolveEvePackageContract,scaffoldBaseProject};
|
|
@@ -65,7 +65,6 @@ export declare const WEB_APP_TEMPLATE_PACKAGE_JSON: {
|
|
|
65
65
|
readonly "@streamdown/math": "1.0.2";
|
|
66
66
|
readonly "@streamdown/mermaid": "1.0.2";
|
|
67
67
|
readonly "@tailwindcss/postcss": "4.3.0";
|
|
68
|
-
readonly ai: "^7.0.38";
|
|
69
68
|
readonly "class-variance-authority": "0.7.1";
|
|
70
69
|
readonly clsx: "2.1.1";
|
|
71
70
|
readonly cmdk: "1.1.1";
|
|
@@ -5235,4 +5235,4 @@ export const auth = betterAuth({
|
|
|
5235
5235
|
},
|
|
5236
5236
|
},
|
|
5237
5237
|
});
|
|
5238
|
-
`},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`,
|
|
5238
|
+
`},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`,"class-variance-authority":`0.7.1`,clsx:`2.1.1`,cmdk:`1.1.1`,"lucide-react":`1.16.0`,motion:`12.40.0`,nanoid:`5.1.11`,next:`16.3.0-preview.6`,"radix-ui":`1.4.3`,react:`19.2.6`,"react-dom":`19.2.6`,shiki:`4.1.0`,streamdown:`2.5.0`,"tailwind-merge":`3.6.0`,tailwindcss:`4.3.0`,"use-stick-to-bottom":`1.1.4`,zod:`4.4.3`},devDependencies:{"@types/node":`26`,"@types/react":`19.2.15`,"@types/react-dom":`19.2.3`,typescript:`6.0.3`}};export{WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES,WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON};
|
|
@@ -103,7 +103,7 @@ export interface EnsureChannelOptions {
|
|
|
103
103
|
/** When false, Web Chat leaves Vercel Services config unwritten for preview-only scaffolds. */
|
|
104
104
|
configureVercelServices?: boolean;
|
|
105
105
|
onWorkspaceRootMutation?: (mutation: WorkspaceRootMutation) => void | Promise<void>;
|
|
106
|
-
/**
|
|
106
|
+
/** Web Chat files and dependencies are already installed by a registry item. */
|
|
107
107
|
skipDependencyMutation?: boolean;
|
|
108
108
|
}
|
|
109
109
|
export declare function ensureChannel(options: EnsureChannelOptions): Promise<ChannelMutationResult>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import{appendEnv}from"../../append-env.js";import{pinnedNodeEngineMajor}from"../../node-engine.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"./package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES,WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import{resolveEvePackageContract}from"../create/project.js";import{resolveWebPackageVersions}from"./web-options.js";import{readFile,readdir,unlink,writeFile}from"node:fs/promises";import{basename,join,resolve}from"node:path";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,NEXT_PACKAGE_NAME=`next`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH);function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readPackageJsonObject(e){if(!await pathExists(e))return;let t=JSON.parse(await readFile(e,`utf8`));return isJsonObject(t)?t:void 0}async function readDependencyVersion(e,t){let n=await readPackageJsonObject(e);if(n===void 0||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){let n=await readPackageJsonObject(e);return n!==void 0&&packageJsonHasDependency(n,t)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),NEXT_PACKAGE_NAME)}const VERCEL_HOST_FRAMEWORK_PRESETS={"@sveltejs/kit":`sveltekit`,[NEXT_PACKAGE_NAME]:`nextjs`,nuxt:`nuxtjs`,nuxt3:`nuxtjs`,"nuxt-edge":`nuxtjs`,"nuxt-nightly":`nuxtjs`};async function resolveVercelHostFrameworkPreset(e){let t=await readPackageJsonObject(join(e,`package.json`));if(t!==void 0){for(let[e,n]of Object.entries(VERCEL_HOST_FRAMEWORK_PRESETS))if(packageJsonHasDependency(t,e))return n}}async function hasVercelHostFramework(e){return await resolveVercelHostFrameworkPreset(e)!==void 0}async function ensurePackageDependency(e,t,n){return!await pathExists(e)||await readDependencyVersion(e,t)===n?[]:(await patchPackageJson(e,{dependencies:{[t]:n}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(e,n,r,a,c,d=!0,f){let h=join(e,`package.json`);if(!await pathExists(h))return{mutations:[]};let g=resolveEvePackageContract(a.evePackage),_=pinnedNodeEngineMajor(g.nodeEngine),v={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,a.aiPackageVersion),eve:formatEveDependencySpecifier(g.version),next:resolveVersionToken(`nextPackageVersion`,a.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,a.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,a.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,a.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,a.zodPackageVersion),...f===`sign-in-with-vercel`?{"better-auth":resolveVersionToken(`betterAuthPackageVersion`,a.betterAuthPackageVersion)}:{}},y={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":_,"@types/react":resolveVersionToken(`typesReactPackageVersion`,a.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,a.typesReactDomPackageVersion),typescript:`6.0.3`},b=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts,x=isPackageManagerWorkspaceMember(n,r),S={scripts:b};d&&(S.dependencies=v,S.devDependencies=y),x||(S.nodeEngineRequirement=g.nodeEngine);let C=await patchPackageJson(h,S),w=(await patchWorkspaceRootPackageJson(n,r,{
|
|
1
|
+
import{appendEnv}from"../../append-env.js";import{pinnedNodeEngineMajor}from"../../node-engine.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"./package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES,WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import{resolveEvePackageContract}from"../create/project.js";import{resolveWebPackageVersions}from"./web-options.js";import{readFile,readdir,unlink,writeFile}from"node:fs/promises";import{basename,join,resolve}from"node:path";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,NEXT_PACKAGE_NAME=`next`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH);function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readPackageJsonObject(e){if(!await pathExists(e))return;let t=JSON.parse(await readFile(e,`utf8`));return isJsonObject(t)?t:void 0}async function readDependencyVersion(e,t){let n=await readPackageJsonObject(e);if(n===void 0||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){let n=await readPackageJsonObject(e);return n!==void 0&&packageJsonHasDependency(n,t)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),NEXT_PACKAGE_NAME)}const VERCEL_HOST_FRAMEWORK_PRESETS={"@sveltejs/kit":`sveltekit`,[NEXT_PACKAGE_NAME]:`nextjs`,nuxt:`nuxtjs`,nuxt3:`nuxtjs`,"nuxt-edge":`nuxtjs`,"nuxt-nightly":`nuxtjs`};async function resolveVercelHostFrameworkPreset(e){let t=await readPackageJsonObject(join(e,`package.json`));if(t!==void 0){for(let[e,n]of Object.entries(VERCEL_HOST_FRAMEWORK_PRESETS))if(packageJsonHasDependency(t,e))return n}}async function hasVercelHostFramework(e){return await resolveVercelHostFrameworkPreset(e)!==void 0}async function ensurePackageDependency(e,t,n){return!await pathExists(e)||await readDependencyVersion(e,t)===n?[]:(await patchPackageJson(e,{dependencies:{[t]:n}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(e,n,r,a,c,d=!0,f){let h=join(e,`package.json`);if(!await pathExists(h))return{mutations:[]};let g=resolveEvePackageContract(a.evePackage),_=pinnedNodeEngineMajor(g.nodeEngine),v={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,a.aiPackageVersion),eve:formatEveDependencySpecifier(g.version),next:resolveVersionToken(`nextPackageVersion`,a.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,a.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,a.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,a.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,a.zodPackageVersion),...f===`sign-in-with-vercel`?{"better-auth":resolveVersionToken(`betterAuthPackageVersion`,a.betterAuthPackageVersion)}:{}},y={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":_,"@types/react":resolveVersionToken(`typesReactPackageVersion`,a.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,a.typesReactDomPackageVersion),typescript:`6.0.3`},b=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts,x=isPackageManagerWorkspaceMember(n,r),S={scripts:b};d&&(S.dependencies=v,S.devDependencies=y),x||(S.nodeEngineRequirement=g.nodeEngine);let C=await patchPackageJson(h,S),w=(await patchWorkspaceRootPackageJson(n,r,{nodeEngineRequirement:g.nodeEngine,onWorkspaceRootMutation:c})).nodeEngineOverride??C.nodeEngineOverride;return{mutations:[{path:h,dependencies:d?Object.keys(v):[],devDependencies:d?Object.keys(y):[],scripts:Object.keys(b)}],nodeEngineOverride:w}}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackConnectTemplate(e){if(!e.startsWith(`slack/`)||e.length===6)throw Error(`Invalid Slack connector UID "${e}".`);return`import { connectSlackCredentials } from "@vercel/connect/eve";
|
|
2
2
|
import { slackChannel } from "eve/channels/slack";
|
|
3
3
|
|
|
4
4
|
export default slackChannel({
|
|
5
5
|
credentials: connectSlackCredentials(${JSON.stringify(e)}),
|
|
6
6
|
});
|
|
7
|
-
`}const SLACK_ENV_EXAMPLE_VALUES={SLACK_BOT_TOKEN:``,SLACK_SIGNING_SECRET:``};function renderWebAppTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t).replaceAll(`__EVE_INIT_WITH_EVE_OPTIONS__`,``)}async function ensureWebVercelJson(e){return await pathExists(e)?`skipped`:(await writeTextFile(e,`${JSON.stringify({$schema:`https://openapi.vercel.sh/vercel.json`},null,2)}\n`,{force:!0}),`written`)}async function findCompetingNextConfigFiles(e){let t=[];for(let n of WEB_COMPETING_NEXT_CONFIG_PATHS){let r=join(e,n);await pathExists(r)&&t.push(r)}return t}async function ensureChannel(e){switch(e.kind){case`slack`:return ensureSlackChannel({...e,kind:`slack`});case`web`:return ensureWebChannel({...e,kind:`web`})}}async function ensureWebChannel(e){let t=join(e.projectRoot,`package.json`),n=await pathExists(join(e.projectRoot,`app/page.tsx`));if(!e.force&&await isNextJsProject(e.projectRoot))return{kind:`web`,action:`skipped`,skipReason:`nextjs-project`,filesWritten:[],filesSkipped:[t],packageJsonUpdated:[]};let r=resolveWebPackageVersions(e.webPackageVersions,e.webAuthentication),o=e.packageManager??`pnpm`,s=resolve(e.workspaceProbeDirectory??e.projectRoot),l=await patchWebPackageJson(e.projectRoot,o,s,r,e.onWorkspaceRootMutation,!e.skipDependencyMutation,e.webAuthentication),u=[],p=[],m=[],g=[],_=basename(resolve(e.projectRoot));if(e.configureVercelServices??!0){let t=join(e.projectRoot,`vercel.json`);await ensureWebVercelJson(t)===`written`?u.push(t):g.push(t)}let v=await applyPackageManagerWorkspaceConfiguration({packageManager:o,projectRoot:e.projectRoot,workspaceProbeRoot:s,onWorkspaceRootMutation:e.onWorkspaceRootMutation});if(u.push(...v.filesWritten),g.push(...v.filesSkipped),!e.skipDependencyMutation){let t={...WEB_APP_TEMPLATE_FILES,...e.webAuthentication===`sign-in-with-vercel`?WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES:{}};for(let[n,r]of Object.entries(t)){let t=join(e.projectRoot,n);if(n===`agent/channels/eve.ts`&&!e.force&&await pathExists(t)){g.push(t);continue}let o=await pathExists(t);await writeTextFile(t,renderWebAppTemplate(r,_),{force:!0}),u.push(t),o&&p.push(t)}}m.push(...await findCompetingNextConfigFiles(e.projectRoot));let y=[...new Set(u)],S=[...new Set(g)].filter(e=>!y.includes(e)),C={kind:`web`,action:n?`overwritten`:`created`,filesWritten:y,filesSkipped:S,packageJsonUpdated:l.mutations};return p.length>0&&(C.filesOverwritten=p),m.length>0&&(C.competingNextConfigFiles=m),l.nodeEngineOverride!==void 0&&(C.nodeEngineOverride=l.nodeEngineOverride),C}async function ensureSlackChannel(t){let n=join(t.projectRoot,`agent/channels/slack.ts`),r=await pathExists(n);if(!t.force&&r)return{kind:`slack`,action:`skipped`,filesWritten:[],filesSkipped:[n],packageJsonUpdated:[]};let s=t.slackCredentials??`vercel-connect`,c=t.slackConnectorSlug??await deriveSlackConnectorSlug(t.projectRoot),l,u=[],d=[n],f=[],p;if(s===`vercel-connect`){if(!t.skipDependencyMutation){let e=resolveVersionToken(`connectPackageVersion`,t.connectPackageVersion??`0.4.3`);u=await ensurePackageDependency(join(t.projectRoot,`package.json`),`@vercel/connect`,e)}l=buildSlackConnectTemplate(t.slackConnectorUid??`slack/${c}`)}else{l=`import { slackChannel } from "eve/channels/slack";
|
|
7
|
+
`}const SLACK_ENV_EXAMPLE_VALUES={SLACK_BOT_TOKEN:``,SLACK_SIGNING_SECRET:``};function renderWebAppTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t).replaceAll(`__EVE_INIT_WITH_EVE_OPTIONS__`,``)}async function ensureWebVercelJson(e){return await pathExists(e)?`skipped`:(await writeTextFile(e,`${JSON.stringify({$schema:`https://openapi.vercel.sh/vercel.json`},null,2)}\n`,{force:!0}),`written`)}async function findCompetingNextConfigFiles(e){let t=[];for(let n of WEB_COMPETING_NEXT_CONFIG_PATHS){let r=join(e,n);await pathExists(r)&&t.push(r)}return t}async function ensureChannel(e){switch(e.kind){case`slack`:return ensureSlackChannel({...e,kind:`slack`});case`web`:return ensureWebChannel({...e,kind:`web`})}}async function ensureWebChannel(e){let t=join(e.projectRoot,`package.json`),n=await pathExists(join(e.projectRoot,`app/page.tsx`));if(!e.force&&!e.skipDependencyMutation&&await isNextJsProject(e.projectRoot))return{kind:`web`,action:`skipped`,skipReason:`nextjs-project`,filesWritten:[],filesSkipped:[t],packageJsonUpdated:[]};let r=resolveWebPackageVersions(e.webPackageVersions,e.webAuthentication),o=e.packageManager??`pnpm`,s=resolve(e.workspaceProbeDirectory??e.projectRoot),l=await patchWebPackageJson(e.projectRoot,o,s,r,e.onWorkspaceRootMutation,!e.skipDependencyMutation,e.webAuthentication),u=[],p=[],m=[],g=[],_=basename(resolve(e.projectRoot));if(e.configureVercelServices??!0){let t=join(e.projectRoot,`vercel.json`);await ensureWebVercelJson(t)===`written`?u.push(t):g.push(t)}let v=await applyPackageManagerWorkspaceConfiguration({packageManager:o,projectRoot:e.projectRoot,workspaceProbeRoot:s,onWorkspaceRootMutation:e.onWorkspaceRootMutation});if(u.push(...v.filesWritten),g.push(...v.filesSkipped),!e.skipDependencyMutation){let t={...WEB_APP_TEMPLATE_FILES,...e.webAuthentication===`sign-in-with-vercel`?WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES:{}};for(let[n,r]of Object.entries(t)){let t=join(e.projectRoot,n);if(n===`agent/channels/eve.ts`&&!e.force&&await pathExists(t)){g.push(t);continue}let o=await pathExists(t);await writeTextFile(t,renderWebAppTemplate(r,_),{force:!0}),u.push(t),o&&p.push(t)}}m.push(...await findCompetingNextConfigFiles(e.projectRoot));let y=[...new Set(u)],S=[...new Set(g)].filter(e=>!y.includes(e)),C={kind:`web`,action:n?`overwritten`:`created`,filesWritten:y,filesSkipped:S,packageJsonUpdated:l.mutations};return p.length>0&&(C.filesOverwritten=p),m.length>0&&(C.competingNextConfigFiles=m),l.nodeEngineOverride!==void 0&&(C.nodeEngineOverride=l.nodeEngineOverride),C}async function ensureSlackChannel(t){let n=join(t.projectRoot,`agent/channels/slack.ts`),r=await pathExists(n);if(!t.force&&r)return{kind:`slack`,action:`skipped`,filesWritten:[],filesSkipped:[n],packageJsonUpdated:[]};let s=t.slackCredentials??`vercel-connect`,c=t.slackConnectorSlug??await deriveSlackConnectorSlug(t.projectRoot),l,u=[],d=[n],f=[],p;if(s===`vercel-connect`){if(!t.skipDependencyMutation){let e=resolveVersionToken(`connectPackageVersion`,t.connectPackageVersion??`0.4.3`);u=await ensurePackageDependency(join(t.projectRoot,`package.json`),`@vercel/connect`,e)}l=buildSlackConnectTemplate(t.slackConnectorUid??`slack/${c}`)}else{l=`import { slackChannel } from "eve/channels/slack";
|
|
8
8
|
|
|
9
9
|
export default slackChannel();
|
|
10
10
|
`;let n=join(t.projectRoot,`.env.example`);p={path:n,...await pathExists(n)?{content:await readFile(n,`utf8`)}:{}},(await appendEnv(n,SLACK_ENV_EXAMPLE_VALUES)).written.length>0?d.push(n):f.push(n)}try{await writeTextFile(n,l,{force:t.force})}catch(e){throw p!==void 0&&(p.content===void 0?await unlink(p.path):await writeFile(p.path,p.content,`utf8`)),e}let m={kind:`slack`,action:r?`overwritten`:`created`,filesWritten:d,filesSkipped:f,packageJsonUpdated:u,slackConnectorSlug:c};return r&&(m.filesOverwritten=[n]),m}async function listAuthoredChannels(e){let t=join(e,`channels`),i;try{i=await readdir(t,{withFileTypes:!0})}catch(e){if(e.code===`ENOENT`)return[];throw e}let a=[];for(let e of i){if(e.isFile()){let t=getSupportedModuleBaseName(e.name);t!==null&&a.push(t);continue}if(e.isDirectory())try{(await readdir(join(t,e.name))).some(e=>matchesSupportedModuleBaseName(e,`connection`))&&a.push(e.name)}catch{}}return a.sort()}export{DEFAULT_SLACK_CONNECTOR_SLUG,SLACK_CHANNEL_DEFAULT_ROUTE,deriveSlackConnectorSlug,ensureChannel,hasVercelHostFramework,isNextJsProject,listAuthoredChannels,normalizeSlackConnectorSlug,resolveVercelHostFrameworkPreset};
|
|
@@ -2,8 +2,6 @@ import { type NodeEngineOverride } from "../../node-engine.js";
|
|
|
2
2
|
export interface PackageJsonPatch {
|
|
3
3
|
dependencies?: Record<string, string>;
|
|
4
4
|
devDependencies?: Record<string, string>;
|
|
5
|
-
overrides?: Record<string, string>;
|
|
6
|
-
resolutions?: Record<string, string>;
|
|
7
5
|
scripts?: Record<string, string>;
|
|
8
6
|
/**
|
|
9
7
|
* eve's required Node.js range (e.g. `">=24"`). When the target's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{reconcileNodeEngine}from"../../node-engine.js";import{readFile,writeFile}from"node:fs/promises";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function patchPackageJson(r,i){let a=await readFile(r,`utf8`),o=JSON.parse(a),s=!1,c;if(i.dependencies!==void 0&&(o.dependencies={...o.dependencies,...i.dependencies},s=!0),i.devDependencies!==void 0&&(o.devDependencies={...o.devDependencies,...i.devDependencies},s=!0),i.
|
|
1
|
+
import{reconcileNodeEngine}from"../../node-engine.js";import{readFile,writeFile}from"node:fs/promises";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function patchPackageJson(r,i){let a=await readFile(r,`utf8`),o=JSON.parse(a),s=!1,c;if(i.dependencies!==void 0&&(o.dependencies={...o.dependencies,...i.dependencies},s=!0),i.devDependencies!==void 0&&(o.devDependencies={...o.devDependencies,...i.devDependencies},s=!0),i.scripts!==void 0&&(o.scripts={...o.scripts,...i.scripts},s=!0),i.nodeEngineRequirement!==void 0){let t=isJsonObject(o.engines)?o.engines:{},n=reconcileNodeEngine(t.node,i.nodeEngineRequirement);(n.kind===`added`||n.kind===`overridden`)&&(o.engines={...t,node:n.next},s=!0),n.kind===`overridden`&&(c=n)}return s&&await writeFile(r,`${JSON.stringify(o,null,2)}\n`,`utf8`),{changed:s,nodeEngineOverride:c}}export{patchPackageJson};
|
|
@@ -13,7 +13,6 @@ export interface WorkspaceRootPackageJsonPatchResult extends PackageJsonPatchRes
|
|
|
13
13
|
export declare function isPackageManagerWorkspaceMember(packageManager: PackageManagerKind, projectRoot: string): boolean;
|
|
14
14
|
/** Applies root-only package.json fields to an ancestor workspace package.json. */
|
|
15
15
|
export declare function patchWorkspaceRootPackageJson(packageManager: PackageManagerKind, projectRoot: string, input: {
|
|
16
|
-
readonly aiPackageVersion?: string;
|
|
17
16
|
readonly nodeEngineRequirement?: string;
|
|
18
17
|
readonly onWorkspaceRootMutation?: (mutation: WorkspaceRootMutation) => void | Promise<void>;
|
|
19
18
|
}): Promise<WorkspaceRootPackageJsonPatchResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isPathInside,workspacePatternForProject,workspacePatternsClaimProject}from"./workspace-glob.js";import{ensurePnpmWorkspaceIncludesProject,findAncestorPnpmWorkspaceRoot}from"../primitives/pm/pnpm.js";import{getPackageManagerStrategy}from"../primitives/pm/index.js";import{patchPackageJson}from"./update/package-json.js";import{readFile,writeFile}from"node:fs/promises";import{dirname,join,resolve}from"node:path";import{existsSync,readFileSync}from"node:fs";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function packageJsonWorkspacePatterns(e){let t=e.workspaces;return Array.isArray(t)?t.filter(e=>typeof e==`string`):!isJsonObject(t)||!Array.isArray(t.packages)?[]:t.packages.filter(e=>typeof e==`string`)}function readPackageJsonWorkspacePatterns(e){let t=JSON.parse(readFileSync(e,`utf8`));if(!isJsonObject(t))return;let n=packageJsonWorkspacePatterns(t);return n.length===0?void 0:n}function findAncestorPackageJsonWorkspaceRoot(e){let t=dirname(resolve(e));for(;;){let e=join(t,`package.json`);if(existsSync(e))try{if(readPackageJsonWorkspacePatterns(e)!==void 0)return t}catch{}let n=dirname(t);if(n===t)return;t=n}}function findClaimingPackageJsonWorkspaceRoot(e){let t=findAncestorPackageJsonWorkspaceRoot(e);if(t===void 0)return;let r;try{r=readPackageJsonWorkspacePatterns(join(t,`package.json`))}catch{return}return r!==void 0&&workspacePatternsClaimProject(r,t,e)?t:void 0}function findPackageManagerWorkspaceRoot(e,t){switch(e){case`pnpm`:return findAncestorPnpmWorkspaceRoot(t);case`bun`:case`npm`:case`yarn`:return findAncestorPackageJsonWorkspaceRoot(t)}}function isPackageManagerWorkspaceMember(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n!==void 0&&resolve(n)!==resolve(t)}function workspaceRootPackageJsonPath(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n===void 0?void 0:join(n,`package.json`)}async function ensurePackageJsonWorkspaceIncludesProject(e){let n=findAncestorPackageJsonWorkspaceRoot(e);if(n===void 0||resolve(n)===resolve(e)||findClaimingPackageJsonWorkspaceRoot(e)===n)return;let r=join(n,`package.json`),i=JSON.parse(await readFile(r,`utf8`)),a=workspacePatternForProject(n,e);if(Array.isArray(i.workspaces))i.workspaces=[...i.workspaces,a];else if(isJsonObject(i.workspaces)&&Array.isArray(i.workspaces.packages))i.workspaces={...i.workspaces,packages:[...i.workspaces.packages,a]};else return;return await writeFile(r,`${JSON.stringify(i,null,2)}\n`,`utf8`),r}async function ensurePackageManagerWorkspaceIncludesProject(e,t){switch(e){case`pnpm`:{let e=findAncestorPnpmWorkspaceRoot(t);return e===void 0?void 0:await ensurePnpmWorkspaceIncludesProject(t)===`written`?join(e,`pnpm-workspace.yaml`):void 0}case`bun`:case`npm`:case`yarn`:return ensurePackageJsonWorkspaceIncludesProject(t)}}
|
|
1
|
+
import{isPathInside,workspacePatternForProject,workspacePatternsClaimProject}from"./workspace-glob.js";import{ensurePnpmWorkspaceIncludesProject,findAncestorPnpmWorkspaceRoot}from"../primitives/pm/pnpm.js";import{getPackageManagerStrategy}from"../primitives/pm/index.js";import{patchPackageJson}from"./update/package-json.js";import{readFile,writeFile}from"node:fs/promises";import{dirname,join,resolve}from"node:path";import{existsSync,readFileSync}from"node:fs";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function packageJsonWorkspacePatterns(e){let t=e.workspaces;return Array.isArray(t)?t.filter(e=>typeof e==`string`):!isJsonObject(t)||!Array.isArray(t.packages)?[]:t.packages.filter(e=>typeof e==`string`)}function readPackageJsonWorkspacePatterns(e){let t=JSON.parse(readFileSync(e,`utf8`));if(!isJsonObject(t))return;let n=packageJsonWorkspacePatterns(t);return n.length===0?void 0:n}function findAncestorPackageJsonWorkspaceRoot(e){let t=dirname(resolve(e));for(;;){let e=join(t,`package.json`);if(existsSync(e))try{if(readPackageJsonWorkspacePatterns(e)!==void 0)return t}catch{}let n=dirname(t);if(n===t)return;t=n}}function findClaimingPackageJsonWorkspaceRoot(e){let t=findAncestorPackageJsonWorkspaceRoot(e);if(t===void 0)return;let r;try{r=readPackageJsonWorkspacePatterns(join(t,`package.json`))}catch{return}return r!==void 0&&workspacePatternsClaimProject(r,t,e)?t:void 0}function findPackageManagerWorkspaceRoot(e,t){switch(e){case`pnpm`:return findAncestorPnpmWorkspaceRoot(t);case`bun`:case`npm`:case`yarn`:return findAncestorPackageJsonWorkspaceRoot(t)}}function isPackageManagerWorkspaceMember(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n!==void 0&&resolve(n)!==resolve(t)}function workspaceRootPackageJsonPath(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n===void 0?void 0:join(n,`package.json`)}async function ensurePackageJsonWorkspaceIncludesProject(e){let n=findAncestorPackageJsonWorkspaceRoot(e);if(n===void 0||resolve(n)===resolve(e)||findClaimingPackageJsonWorkspaceRoot(e)===n)return;let r=join(n,`package.json`),i=JSON.parse(await readFile(r,`utf8`)),a=workspacePatternForProject(n,e);if(Array.isArray(i.workspaces))i.workspaces=[...i.workspaces,a];else if(isJsonObject(i.workspaces)&&Array.isArray(i.workspaces.packages))i.workspaces={...i.workspaces,packages:[...i.workspaces.packages,a]};else return;return await writeFile(r,`${JSON.stringify(i,null,2)}\n`,`utf8`),r}async function ensurePackageManagerWorkspaceIncludesProject(e,t){switch(e){case`pnpm`:{let e=findAncestorPnpmWorkspaceRoot(t);return e===void 0?void 0:await ensurePnpmWorkspaceIncludesProject(t)===`written`?join(e,`pnpm-workspace.yaml`):void 0}case`bun`:case`npm`:case`yarn`:return ensurePackageJsonWorkspaceIncludesProject(t)}}async function patchWorkspaceRootPackageJson(e,t,n){if(!isPackageManagerWorkspaceMember(e,t))return{changed:!1};let r=workspaceRootPackageJsonPath(e,t);if(r===void 0||!existsSync(r))return{changed:!1};let i=await patchPackageJson(r,{nodeEngineRequirement:n.nodeEngineRequirement});return i.changed&&await n.onWorkspaceRootMutation?.({kind:`package-json`,nodeEngineOverride:i.nodeEngineOverride,path:r}),{...i,path:r}}async function applyPackageManagerWorkspaceConfiguration(t){let n=resolve(t.workspaceProbeRoot??t.projectRoot),r=t.packageManager===`pnpm`?void 0:await ensurePackageManagerWorkspaceIncludesProject(t.packageManager,n),i=await getPackageManagerStrategy(t.packageManager).applyProjectConfiguration(t.projectRoot,{workspaceProbeRoot:n}),o=[...r===void 0?[]:[r],...i.filesWritten],s=[...i.filesSkipped];for(let n of o)isPathInside(t.projectRoot,n)||await t.onWorkspaceRootMutation?.({kind:`workspace-config`,path:n});return{filesSkipped:s,filesWritten:o}}export{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Approval } from "#public/definitions/approval.js";
|
|
2
|
+
import type { JsonObject } from "#shared/json.js";
|
|
3
|
+
export interface DurableDynamicCallbackReference {
|
|
4
|
+
readonly stepId: string;
|
|
5
|
+
readonly closure: JsonObject;
|
|
6
|
+
}
|
|
7
|
+
export interface DurableDynamicToolCallbacks {
|
|
8
|
+
readonly execute: DurableDynamicCallbackReference;
|
|
9
|
+
readonly approvalRequest?: DurableDynamicCallbackReference;
|
|
10
|
+
readonly approvalResponse?: DurableDynamicCallbackReference;
|
|
11
|
+
readonly toModelOutput?: DurableDynamicCallbackReference;
|
|
12
|
+
}
|
|
13
|
+
export declare const DURABLE_DYNAMIC_TOOL_CALLBACKS: unique symbol;
|
|
14
|
+
type Callback = (...args: never[]) => unknown;
|
|
15
|
+
/** Registers one module-stable replay entry point. Re-registration replaces the same code-owned id. */
|
|
16
|
+
export declare function registerDurableDynamicCallback<TArgs extends unknown[], TResult>(stepId: string, callback: (closure: JsonObject, ...args: TArgs) => TResult): void;
|
|
17
|
+
/** Marks a live callback with the descriptor needed to reconstruct it after a cold start. */
|
|
18
|
+
export declare function stampDurableDynamicCallback<TCallback extends Callback>(callback: TCallback, reference: DurableDynamicCallbackReference): TCallback;
|
|
19
|
+
/** Creates a live callback backed by the same registered function used during durable replay. */
|
|
20
|
+
export declare function createDurableDynamicCallback<TArgs extends unknown[], TResult>(input: {
|
|
21
|
+
readonly closure: JsonObject;
|
|
22
|
+
readonly callback: (closure: JsonObject, ...args: TArgs) => TResult;
|
|
23
|
+
readonly stepId: string;
|
|
24
|
+
}): (...args: TArgs) => TResult;
|
|
25
|
+
export declare function readDurableDynamicCallback(callback: unknown): DurableDynamicCallbackReference | undefined;
|
|
26
|
+
/** Copies phase-specific callback descriptors onto a branded tool definition. */
|
|
27
|
+
export declare function stampDurableDynamicToolCallbacks(definition: object, callbacks: Partial<DurableDynamicToolCallbacks>): void;
|
|
28
|
+
export declare function collectDurableDynamicToolCallbacks(input: {
|
|
29
|
+
readonly approval?: Approval<never>;
|
|
30
|
+
readonly execute: Callback;
|
|
31
|
+
readonly toModelOutput?: Callback;
|
|
32
|
+
}): Partial<DurableDynamicToolCallbacks>;
|
|
33
|
+
export declare function readDurableDynamicToolCallbacks(definition: object): Partial<DurableDynamicToolCallbacks> | undefined;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{resolveApprovalPolicy}from"#public/definitions/approval.js";const DURABLE_CALLBACK_REFERENCE=Symbol.for(`eve:durable-dynamic-callback`),DURABLE_DYNAMIC_TOOL_CALLBACKS=Symbol.for(`eve:durable-dynamic-tool-callbacks`),STEP_REGISTRY=Symbol.for(`@workflow/core//registeredSteps`);function getStepRegistry(){let e=globalThis,t=e[STEP_REGISTRY];if(t!==void 0)return t;let n=new Map;return e[STEP_REGISTRY]=n,n}function registerDurableDynamicCallback(e,t){if(e.length===0)throw Error(`A durable dynamic callback step id cannot be empty.`);getStepRegistry().set(e,t)}function stampDurableDynamicCallback(e,n){return Object.defineProperty(e,DURABLE_CALLBACK_REFERENCE,{configurable:!0,value:n}),e}function createDurableDynamicCallback(e){return registerDurableDynamicCallback(e.stepId,e.callback),stampDurableDynamicCallback((...t)=>e.callback(e.closure,...t),{closure:e.closure,stepId:e.stepId})}function readDurableDynamicCallback(e){if(typeof e==`function`)return Reflect.get(e,DURABLE_CALLBACK_REFERENCE)}function stampDurableDynamicToolCallbacks(e,t){Object.defineProperty(e,DURABLE_DYNAMIC_TOOL_CALLBACKS,{configurable:!0,value:t})}function collectDurableDynamicToolCallbacks(t){let n=t.approval===void 0?void 0:readDurableDynamicCallback(resolveApprovalPolicy(t.approval)),r=t.approval===void 0||typeof t.approval==`function`?void 0:readDurableDynamicCallback(t.approval.response),i=readDurableDynamicCallback(t.execute),a=readDurableDynamicCallback(t.toModelOutput),o={};return i!==void 0&&(o.execute=i),n!==void 0&&(o.approvalRequest=n),r!==void 0&&(o.approvalResponse=r),a!==void 0&&(o.toModelOutput=a),o}function readDurableDynamicToolCallbacks(e){return e[DURABLE_DYNAMIC_TOOL_CALLBACKS]}export{DURABLE_DYNAMIC_TOOL_CALLBACKS,collectDurableDynamicToolCallbacks,createDurableDynamicCallback,readDurableDynamicCallback,readDurableDynamicToolCallbacks,registerDurableDynamicCallback,stampDurableDynamicCallback,stampDurableDynamicToolCallbacks};
|
|
@@ -63,10 +63,8 @@ export interface DynamicToolEntry<TInput = Record<string, unknown>, TOutput = an
|
|
|
63
63
|
/**
|
|
64
64
|
* Optional per-call approval gate, mirroring the authored-tool
|
|
65
65
|
* `approval` contract: return `"user-approval"` to require user approval
|
|
66
|
-
* before the call executes.
|
|
67
|
-
*
|
|
68
|
-
* session/turn-scoped tools replay from durable metadata and cannot
|
|
69
|
-
* carry a function across replay.
|
|
66
|
+
* before the call executes. Dynamic approval request and response callbacks
|
|
67
|
+
* use the same durable descriptor boundary as `execute` and `toModelOutput`.
|
|
70
68
|
*/
|
|
71
69
|
readonly approval?: Approval;
|
|
72
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const EMPTY_DELIVERY_SENTINEL=`<eve-empty-delivery/>`,CONDITIONAL_DELIVERY_INSTRUCTION=`Conditional delivery\nOnly when the current task explicitly makes delivery conditional and there is nothing new to report, reply with exactly ${EMPTY_DELIVERY_SENTINEL} and no other text. This includes results already delivered or incorporated into an earlier response; do not send an acknowledgement of that redundancy. Do not use this marker for ordinary conversations, after input or approval responses, or to omit commentary from a response that still needs delivery. Never return an empty response; use the marker to intentionally deliver nothing.`;function hasEmptyDeliverySentinel(e){return e?.includes(`<eve-empty-delivery/>`)
|
|
1
|
+
const EMPTY_DELIVERY_SENTINEL=`<eve-empty-delivery/>`,CONDITIONAL_DELIVERY_INSTRUCTION=`Conditional delivery\nOnly when the current task explicitly makes delivery conditional and there is nothing new to report, reply with exactly ${EMPTY_DELIVERY_SENTINEL} and no other text. This includes results already delivered or incorporated into an earlier response; do not send an acknowledgement of that redundancy. Do not use this marker for ordinary conversations, after input or approval responses, or to omit commentary from a response that still needs delivery. Never return an empty response; use the marker to intentionally deliver nothing.`;function hasEmptyDeliverySentinel(e){return e?.includes(`<eve-empty-delivery/>`)===!0||e?.includes(`<eve-empty-delivery/>`)===!0}export{CONDITIONAL_DELIVERY_INSTRUCTION,EMPTY_DELIVERY_SENTINEL,hasEmptyDeliverySentinel};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ModelMessage } from "ai";
|
|
2
|
+
export interface HistoryViewProjectionInput {
|
|
3
|
+
readonly messages: readonly ModelMessage[];
|
|
4
|
+
readonly state: Readonly<Record<string, unknown>> | undefined;
|
|
5
|
+
}
|
|
6
|
+
export type HistoryViewProjector = (input: HistoryViewProjectionInput) => readonly ModelMessage[];
|
|
7
|
+
export interface PreparedHistoryView {
|
|
8
|
+
readonly messages: readonly ModelMessage[];
|
|
9
|
+
readonly sourceMessages: readonly ModelMessage[];
|
|
10
|
+
readonly sourceState: Readonly<Record<string, unknown>> | undefined;
|
|
11
|
+
}
|
|
12
|
+
export declare const identityHistoryViewProjector: HistoryViewProjector;
|
|
13
|
+
export declare function createHistoryViewPreparer(input?: {
|
|
14
|
+
readonly previous?: PreparedHistoryView;
|
|
15
|
+
readonly projector?: HistoryViewProjector;
|
|
16
|
+
}): (messages: readonly ModelMessage[], state: Readonly<Record<string, unknown>> | undefined) => PreparedHistoryView;
|
|
17
|
+
export declare function prepareHistoryView(input: {
|
|
18
|
+
readonly messages: readonly ModelMessage[];
|
|
19
|
+
readonly previous?: PreparedHistoryView;
|
|
20
|
+
readonly projector?: HistoryViewProjector;
|
|
21
|
+
readonly state?: Readonly<Record<string, unknown>>;
|
|
22
|
+
}): PreparedHistoryView;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const identityHistoryViewProjector=({messages:e})=>e;function createHistoryViewPreparer(e){let t=e?.previous;return(n,r)=>(t=prepareHistoryView({messages:n,previous:t,projector:e?.projector,state:r}),t)}function prepareHistoryView(e){return e.previous?.sourceMessages===e.messages&&e.previous.sourceState===e.state?e.previous:{messages:(e.projector??identityHistoryViewProjector)({messages:e.messages,state:e.state}),sourceMessages:e.messages,sourceState:e.state}}export{createHistoryViewPreparer,identityHistoryViewProjector,prepareHistoryView};
|
|
@@ -16,6 +16,8 @@ export interface JsonObject {
|
|
|
16
16
|
* JSON-serializable values that can safely cross workflow and step boundaries.
|
|
17
17
|
*/
|
|
18
18
|
export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
|
|
19
|
+
/** Compares two already-validated JSON structures by value. */
|
|
20
|
+
export declare function jsonValuesEqual(left: unknown, right: unknown): boolean;
|
|
19
21
|
/**
|
|
20
22
|
* Returns the normalized JSON value for one runtime payload.
|
|
21
23
|
*
|
package/dist/src/shared/json.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const INVALID_JSON_VALUE_CANDIDATE=Symbol(`invalid-json-value-candidate`);function parseJsonValue(t){let n=normalizeJsonValueCandidate(t);if(n===INVALID_JSON_VALUE_CANDIDATE)throw TypeError(`Expected a JSON-serializable value.`);return n}function parseJsonObject(e){let t=parseJsonValue(e);if(!isJsonObjectValue(t))throw TypeError(`Expected a JSON-serializable object.`);return t}function normalizeJsonValueCandidate(t,n=new WeakSet){if(t===null||typeof t==`boolean`||typeof t==`string`)return t;if(typeof t==`number`)return Number.isFinite(t)?t:INVALID_JSON_VALUE_CANDIDATE;if(Array.isArray(t)){let r=[];for(let i of t){let t=normalizeJsonValueCandidate(i,n);if(t===INVALID_JSON_VALUE_CANDIDATE)return INVALID_JSON_VALUE_CANDIDATE;r.push(t)}return r}if(typeof t!=`object`||t===void 0||!isPlainObject(t)||n.has(t))return INVALID_JSON_VALUE_CANDIDATE;n.add(t);let r={};for(let[i,a]of Object.entries(t)){if(a===void 0)continue;let t=normalizeJsonValueCandidate(a,n);if(t===INVALID_JSON_VALUE_CANDIDATE)return INVALID_JSON_VALUE_CANDIDATE;r[i]=t}return n.delete(t),r}function isJsonObjectValue(e){return e!==null&&!Array.isArray(e)&&typeof e==`object`}function isPlainObject(e){let t=Object.getPrototypeOf(e);return t===null||t===Object.prototype}export{isJsonObjectValue,parseJsonObject,parseJsonValue};
|
|
1
|
+
function jsonValuesEqual(e,t){if(e===t)return!0;if(Array.isArray(e)||Array.isArray(t))return Array.isArray(e)&&Array.isArray(t)&&e.length===t.length&&e.every((e,n)=>jsonValuesEqual(e,t[n]));if(e===null||t===null||typeof e!=`object`||typeof t!=`object`)return!1;let n=Object.entries(e),r=t;return n.length===Object.keys(r).length&&n.every(([e,t])=>Object.hasOwn(r,e)&&jsonValuesEqual(t,r[e]))}const INVALID_JSON_VALUE_CANDIDATE=Symbol(`invalid-json-value-candidate`);function parseJsonValue(t){let n=normalizeJsonValueCandidate(t);if(n===INVALID_JSON_VALUE_CANDIDATE)throw TypeError(`Expected a JSON-serializable value.`);return n}function parseJsonObject(e){let t=parseJsonValue(e);if(!isJsonObjectValue(t))throw TypeError(`Expected a JSON-serializable object.`);return t}function normalizeJsonValueCandidate(t,n=new WeakSet){if(t===null||typeof t==`boolean`||typeof t==`string`)return t;if(typeof t==`number`)return Number.isFinite(t)?t:INVALID_JSON_VALUE_CANDIDATE;if(Array.isArray(t)){let r=[];for(let i of t){let t=normalizeJsonValueCandidate(i,n);if(t===INVALID_JSON_VALUE_CANDIDATE)return INVALID_JSON_VALUE_CANDIDATE;r.push(t)}return r}if(typeof t!=`object`||t===void 0||!isPlainObject(t)||n.has(t))return INVALID_JSON_VALUE_CANDIDATE;n.add(t);let r={};for(let[i,a]of Object.entries(t)){if(a===void 0)continue;let t=normalizeJsonValueCandidate(a,n);if(t===INVALID_JSON_VALUE_CANDIDATE)return INVALID_JSON_VALUE_CANDIDATE;r[i]=t}return n.delete(t),r}function isJsonObjectValue(e){return e!==null&&!Array.isArray(e)&&typeof e==`object`}function isPlainObject(e){let t=Object.getPrototypeOf(e);return t===null||t===Object.prototype}export{isJsonObjectValue,jsonValuesEqual,parseJsonObject,parseJsonValue};
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import type { ToolExecutionOptions } from "ai";
|
|
2
2
|
import type { StandardJSONSchemaV1, StandardSchemaV1 } from "#compiled/@standard-schema/spec/index.js";
|
|
3
3
|
import type { JsonObject } from "#shared/json.js";
|
|
4
|
+
import type { TaskExec } from "#shared/tool-task.js";
|
|
4
5
|
/**
|
|
5
6
|
* Options forwarded from the AI SDK to the tool's {@link ToolDefinition.execute}
|
|
6
7
|
* function. These are the same options the SDK passes to every tool call.
|
|
7
8
|
*/
|
|
8
9
|
export type ToolExecuteOptions = Omit<ToolExecutionOptions<unknown>, "context">;
|
|
9
|
-
export type ToolExecuteFn<TInput = unknown, TOutput = unknown> = (input: TInput, options: ToolExecuteOptions) => Promise<TOutput> | TOutput | AsyncIterable<TOutput>;
|
|
10
|
+
export type ToolExecuteFn<TInput = unknown, TOutput = unknown> = (input: TInput, options: ToolExecuteOptions, task?: TaskExec) => Promise<TOutput> | TOutput | AsyncIterable<TOutput>;
|
|
11
|
+
export type ToolExecution = "background";
|
|
10
12
|
interface ToolDefinitionBase {
|
|
11
13
|
readonly description: string;
|
|
14
|
+
readonly execution?: ToolExecution;
|
|
12
15
|
}
|
|
13
16
|
/**
|
|
14
17
|
* Internal/compiled tool definition shape. Carries `name` because the
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { BackgroundTask } from "#execution/tasks/parent/delegate.js";
|
|
2
|
+
import type { BackgroundToolCall } from "#harness/background-tools.js";
|
|
3
|
+
import type { HarnessSession } from "#harness/types.js";
|
|
4
|
+
import type { JsonObject, JsonValue } from "#shared/json.js";
|
|
5
|
+
declare const TASK_DELEGATED_KIND = "eve:task-delegated";
|
|
6
|
+
/** Private address an executor uses to report lifecycle changes to its owning task. */
|
|
7
|
+
export interface TaskBinding {
|
|
8
|
+
readonly taskId: string;
|
|
9
|
+
readonly token: string;
|
|
10
|
+
readonly url?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Opaque, task-private address used to control an external executor. `data`
|
|
14
|
+
* means nothing to the task layer beyond deep equality (replay idempotency);
|
|
15
|
+
* only the executor `kind` that wrote it may parse it (e.g. cancel routing).
|
|
16
|
+
*/
|
|
17
|
+
export interface TaskExecutorBinding {
|
|
18
|
+
readonly kind: string;
|
|
19
|
+
readonly data: JsonObject;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* What the model sees as this call's tool output when work is delegated: the
|
|
23
|
+
* author-supplied data plus `status: "working"` and the `taskId` it can poll
|
|
24
|
+
* or cancel. It acknowledges delegation — it is not the task's result, which
|
|
25
|
+
* arrives later through task completion.
|
|
26
|
+
*/
|
|
27
|
+
export type TaskReceipt<TData extends JsonObject = JsonObject> = TData & {
|
|
28
|
+
readonly status: "working";
|
|
29
|
+
readonly taskId: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Sentinel returned by a background tool after an external executor accepts
|
|
33
|
+
* responsibility for the task. Returning it ends `execute`; it does not
|
|
34
|
+
* complete the durable task.
|
|
35
|
+
*/
|
|
36
|
+
export interface TaskDelegated<TData extends JsonObject = JsonObject> {
|
|
37
|
+
readonly kind: typeof TASK_DELEGATED_KIND;
|
|
38
|
+
readonly executor: TaskExecutorBinding;
|
|
39
|
+
readonly receipt: TaskReceipt<TData>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Commands an in-process executor may report to its task via
|
|
43
|
+
* {@link TaskExec.send}. Deliberately narrower than the task run's full
|
|
44
|
+
* command surface — bind, ready, and input routing stay runtime-owned.
|
|
45
|
+
*/
|
|
46
|
+
export type TaskSendCommand = {
|
|
47
|
+
readonly kind: "update";
|
|
48
|
+
readonly message: string;
|
|
49
|
+
} | {
|
|
50
|
+
readonly kind: "complete";
|
|
51
|
+
readonly data: JsonValue;
|
|
52
|
+
} | {
|
|
53
|
+
readonly kind: "fail";
|
|
54
|
+
readonly data: JsonValue;
|
|
55
|
+
} | {
|
|
56
|
+
readonly kind: "cancel";
|
|
57
|
+
};
|
|
58
|
+
/** Task capability passed only to tools declared with `execution: "background"`. */
|
|
59
|
+
export interface TaskExec {
|
|
60
|
+
/**
|
|
61
|
+
* The sibling background calls admitted in the same step. The only view a
|
|
62
|
+
* tool has of what launched alongside it, for enforcing batch-wide
|
|
63
|
+
* invariants before delegating.
|
|
64
|
+
*/
|
|
65
|
+
readonly batch: readonly BackgroundToolCall[];
|
|
66
|
+
/**
|
|
67
|
+
* The task-private address for reporting lifecycle changes back to this
|
|
68
|
+
* task. Hand it to the external executor so completion routes to the task
|
|
69
|
+
* directly instead of through the (already finished) tool call.
|
|
70
|
+
*/
|
|
71
|
+
readonly binding: TaskBinding;
|
|
72
|
+
/**
|
|
73
|
+
* Snapshot of the harness session at step start, for reading context.
|
|
74
|
+
* Mutating it changes nothing durable: session writes belong to the
|
|
75
|
+
* runtime, keyed off the executor binding at step commit.
|
|
76
|
+
*/
|
|
77
|
+
readonly session: HarnessSession;
|
|
78
|
+
/**
|
|
79
|
+
* Delivers progress or a terminal command to this task's inbox from the same
|
|
80
|
+
* process, for executors that outlive `execute` in-memory (e.g. a callback firing
|
|
81
|
+
* after delegation). Call it only after `execute` returned `delegated(...)`
|
|
82
|
+
* — the runtime settles non-delegated returns itself, and a second terminal
|
|
83
|
+
* command is refused. Not restart-safe: an in-process callback dies with
|
|
84
|
+
* the process; the persisted executor binding remains the durable
|
|
85
|
+
* cancellation path. Throws when the task no longer accepts commands
|
|
86
|
+
* (already terminal).
|
|
87
|
+
*/
|
|
88
|
+
readonly send: (command: TaskSendCommand) => Promise<void>;
|
|
89
|
+
/** The durable task backing this call; its identity outlives `execute`. */
|
|
90
|
+
readonly task: BackgroundTask;
|
|
91
|
+
/**
|
|
92
|
+
* Builds the `TaskDelegated` sentinel to return from `execute`. Centralizes
|
|
93
|
+
* receipt stamping so every receipt carries this task's `taskId` and
|
|
94
|
+
* `status: "working"` — tools cannot mint receipts for tasks they don't own.
|
|
95
|
+
*/
|
|
96
|
+
delegated<TData extends JsonObject>(input: {
|
|
97
|
+
readonly executor: TaskExecutorBinding;
|
|
98
|
+
readonly receipt: TData;
|
|
99
|
+
}): TaskDelegated<TData>;
|
|
100
|
+
}
|
|
101
|
+
export declare function createTaskDelegated<TData extends JsonObject>(input: {
|
|
102
|
+
readonly binding: TaskBinding;
|
|
103
|
+
readonly executor: TaskExecutorBinding;
|
|
104
|
+
readonly receipt: TData;
|
|
105
|
+
}): TaskDelegated<TData>;
|
|
106
|
+
export declare function isTaskDelegated(value: unknown): value is TaskDelegated;
|
|
107
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const TASK_DELEGATED_KIND=`eve:task-delegated`;function createTaskDelegated(e){return{executor:e.executor,kind:TASK_DELEGATED_KIND,receipt:{...e.receipt,status:`working`,taskId:e.binding.taskId}}}function isTaskDelegated(e){return typeof e==`object`&&!!e&&`kind`in e&&e.kind===TASK_DELEGATED_KIND}export{createTaskDelegated,isTaskDelegated};
|