eve 0.84.1 → 0.85.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 -18
- package/dist/src/channel/compiled-channel.d.ts +3 -7
- package/dist/src/channel/cross-channel-receive.d.ts +9 -10
- package/dist/src/channel/cross-channel-receive.js +1 -1
- package/dist/src/channel/schedule.js +1 -1
- package/dist/src/channel/session.d.ts +26 -4
- package/dist/src/channel/session.js +1 -1
- package/dist/src/chunks/{use-eve-agent-DMeP0JOF.js → use-eve-agent-B2jCfcnG.js} +3 -2
- package/dist/src/chunks/{use-eve-agent-DP5Rso9C.js → use-eve-agent-DCLFi26P.js} +3 -2
- package/dist/src/client/client.js +1 -1
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/client/types.d.ts +5 -4
- package/dist/src/compiled/.vendor-stamp.json +1 -1
- package/dist/src/context/keys.d.ts +7 -0
- package/dist/src/context/keys.js +1 -1
- package/dist/src/execution/agent-sessions/context.d.ts +5 -1
- package/dist/src/execution/agent-sessions/context.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/legacy-session/snapshot.d.ts +1 -2
- package/dist/src/execution/legacy-session/snapshot.js +1 -1
- package/dist/src/execution/proxied-deliver-step.js +1 -1
- package/dist/src/execution/public-destination.d.ts +3 -0
- package/dist/src/execution/public-destination.js +1 -1
- package/dist/src/execution/publish-session-events.js +1 -1
- package/dist/src/execution/session/checkpoint-migrations.d.ts +16 -5
- package/dist/src/execution/session/checkpoint-migrations.js +1 -1
- package/dist/src/execution/session/checkpoint-refusal.d.ts +4 -0
- package/dist/src/execution/session/checkpoint-refusal.js +1 -0
- package/dist/src/execution/session/entry.js +1 -1
- package/dist/src/execution/session/handoff-steps.d.ts +7 -1
- package/dist/src/execution/session/handoff-steps.js +1 -1
- package/dist/src/execution/session/imported-conversation.d.ts +2 -0
- package/dist/src/execution/session/imported-conversation.js +1 -0
- package/dist/src/execution/session/interrupted-step.js +1 -1
- package/dist/src/execution/session/pre-v27-checkpoint.d.ts +36 -0
- package/dist/src/execution/session/pre-v27-checkpoint.js +1 -0
- package/dist/src/execution/session/program.d.ts +2 -0
- package/dist/src/execution/session/program.js +1 -1
- package/dist/src/execution/session/turn-step.js +1 -1
- package/dist/src/execution/session-callback-request.js +1 -1
- package/dist/src/execution/tool-auth.js +1 -1
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/tools/channel-to.d.ts +12 -0
- package/dist/src/execution/tools/channel-to.js +1 -0
- package/dist/src/execution/tools/workflow/body.d.ts +3 -0
- package/dist/src/execution/tools/workflow/body.js +1 -1
- package/dist/src/execution/tools/workflow/step-context.d.ts +5 -0
- package/dist/src/execution/tools/workflow/step-execution.js +1 -1
- package/dist/src/execution/tools/workflow/step.js +1 -1
- package/dist/src/execution/workflow-callback-url.d.ts +2 -3
- package/dist/src/execution/workflow-callback-url.js +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/harness/compaction/step.js +1 -1
- package/dist/src/harness/model-call/call.js +1 -1
- package/dist/src/harness/model-call/run.js +1 -1
- package/dist/src/harness/session-machine/transitions.js +1 -1
- package/dist/src/internal/application/stamped-package-version.js +1 -1
- package/dist/src/internal/attachments/limited-read.d.ts +2 -0
- package/dist/src/internal/attachments/limited-read.js +1 -1
- package/dist/src/internal/attachments/url-refs.js +1 -1
- package/dist/src/internal/capability-error.d.ts +3 -0
- package/dist/src/internal/capability-error.js +1 -0
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +1 -1
- package/dist/src/public/channels/discord/discordChannel.js +1 -1
- package/dist/src/public/channels/github/githubChannel.js +1 -1
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/channels/linq/inboundContent.js +1 -1
- package/dist/src/public/channels/slack/answers.d.ts +2 -3
- package/dist/src/public/channels/slack/answers.js +1 -1
- package/dist/src/public/channels/slack/api.d.ts +23 -3
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/channels/slack/app-manifest.d.ts +2 -0
- package/dist/src/public/channels/slack/app-manifest.js +1 -1
- package/dist/src/public/channels/slack/auth.d.ts +2 -1
- package/dist/src/public/channels/slack/auth.js +1 -1
- package/dist/src/public/channels/slack/code-channel.d.ts +42 -0
- package/dist/src/public/channels/slack/code-channel.js +1 -0
- package/dist/src/public/channels/slack/defaults.d.ts +7 -3
- package/dist/src/public/channels/slack/defaults.js +3 -3
- package/dist/src/public/channels/slack/hitl.d.ts +7 -17
- package/dist/src/public/channels/slack/hitl.js +1 -1
- package/dist/src/public/channels/slack/index.d.ts +4 -3
- package/dist/src/public/channels/slack/index.js +1 -1
- package/dist/src/public/channels/slack/interaction-cards.d.ts +0 -2
- package/dist/src/public/channels/slack/interaction-cards.js +1 -1
- package/dist/src/public/channels/slack/interactions.js +1 -1
- package/dist/src/public/channels/slack/open-code-channel.d.ts +30 -0
- package/dist/src/public/channels/slack/open-code-channel.js +1 -0
- package/dist/src/public/channels/slack/private-approval-delivery.d.ts +16 -4
- package/dist/src/public/channels/slack/private-approval-delivery.js +1 -1
- package/dist/src/public/channels/slack/renderers.d.ts +58 -6
- package/dist/src/public/channels/slack/renderers.js +1 -1
- package/dist/src/public/channels/slack/reply-delivery.d.ts +4 -0
- package/dist/src/public/channels/slack/reply-delivery.js +1 -1
- package/dist/src/public/channels/slack/request-card-render.d.ts +45 -0
- package/dist/src/public/channels/slack/request-card-render.js +1 -0
- package/dist/src/public/channels/slack/request-cards.d.ts +35 -0
- package/dist/src/public/channels/slack/request-cards.js +3 -0
- package/dist/src/public/channels/slack/sign-in-cancel.d.ts +3 -5
- package/dist/src/public/channels/slack/sign-in-cancel.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.d.ts +109 -22
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/slack/task-card.d.ts +3 -3
- package/dist/src/public/channels/slack/task-card.js +1 -1
- package/dist/src/public/channels/slack/thread-status.js +1 -1
- package/dist/src/public/channels/teams/api.js +1 -1
- package/dist/src/public/channels/teams/defaults.js +1 -1
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/teams/verify.d.ts +9 -5
- package/dist/src/public/channels/teams/verify.js +1 -1
- package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
- package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
- package/dist/src/public/schedules/subscription.d.ts +10 -1
- package/dist/src/runtime/subagents/workflow.js +1 -1
- package/dist/src/setup/index.d.ts +1 -1
- package/dist/src/setup/primitives/index.d.ts +1 -1
- package/dist/src/setup/primitives/pm/run.d.ts +0 -2
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/shared/channel-definition.d.ts +4 -4
- package/dist/src/subagents/adapter.js +1 -1
- package/dist/src/subagents/parent-notification.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tools/definition.d.ts +21 -0
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/dist/src/tools/workflow-definition.d.ts +4 -4
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/channels/custom.mdx +16 -3
- package/docs/channels/eve.mdx +2 -0
- package/docs/channels/linq.mdx +1 -1
- package/docs/channels/slack.mdx +185 -18
- package/docs/channels/teams.mdx +6 -2
- package/docs/concepts/upgrade-to-v27-events.md +2 -2
- package/docs/experimental/dynamic-schedules.mdx +2 -2
- package/docs/guides/client/overview.mdx +1 -1
- package/docs/guides/remote-agents.md +8 -0
- package/docs/patterns/fork-conversations-into-new-threads.md +159 -0
- package/docs/patterns/meta.json +1 -0
- package/docs/schedules.mdx +1 -1
- package/docs/tools/overview.mdx +34 -0
- package/docs/tools/workflows.mdx +47 -5
- package/package.json +1 -1
- package/dist/src/public/channels/slack/approval-cards.d.ts +0 -25
- package/dist/src/public/channels/slack/approval-cards.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{ContextContainer,contextStorage}from"#context/container.js";import{AuthKey,InitiatorAuthKey,SandboxKey,SessionIdKey,SessionKey}from"#context/keys.js";import{ensureSandboxAccess}from"#execution/sandbox/ensure.js";import{resolveDurableCompiledArtifactsSource}from"#runtime/durable-compiled-artifacts-source.js";import{getStepMetadata}from"#compiled/@workflow/core/index.js";import{resolveWorkflowCallbackBaseUrl}from"#execution/workflow-callback-url.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{isConnectionAuthorizationFailedError}from"#connections/errors.js";import{AuthorizationHookKey,CallbackBaseUrlKey,PendingAuthorizationResultKey,isAuthorizationSignal}from"#harness/authorization.js";import{buildBaseToolContext}from"#context/build-base-tool-context.js";import{createAuthorizationContext}from"#runtime/authorization-context.js";import{completeWorkflowStepAuthorization}from"#execution/tools/workflow/authorization-completion.js";import"#execution/tools/workflow/step-context.js";const log=createLogger(`workflow-step`);function withWorkflowStepAuthorization(e){let wrapped=async function(t){let{args:n,context:r}=t;getStepMetadata();let i=new ContextContainer;i.set(AuthKey,r.session.auth.current),i.set(InitiatorAuthKey,r.session.auth.initiator),i.set(SessionIdKey,r.session.id),i.setVirtualContext(SessionKey,{...r.session,sessionId:r.session.id}),i.set(CallbackBaseUrlKey,resolveWorkflowCallbackBaseUrl(r.baseUrl)),i.setVirtualContext(AuthorizationHookKey,r.token),i.setVirtualContext(PendingAuthorizationResultKey,r.authorizationResults);let a=openStepSandbox(r);return contextStorage.run(i,async()=>{let
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{ContextContainer,contextStorage}from"#context/container.js";import{AuthKey,InitiatorAuthKey,SandboxKey,SessionIdKey,SessionKey}from"#context/keys.js";import{ensureSandboxAccess}from"#execution/sandbox/ensure.js";import{resolveDurableCompiledArtifactsSource}from"#runtime/durable-compiled-artifacts-source.js";import{getStepMetadata}from"#compiled/@workflow/core/index.js";import{resolveWorkflowCallbackBaseUrl}from"#execution/workflow-callback-url.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{isConnectionAuthorizationFailedError}from"#connections/errors.js";import{AuthorizationHookKey,CallbackBaseUrlKey,PendingAuthorizationResultKey,isAuthorizationSignal}from"#harness/authorization.js";import{createToolChannelTo}from"#execution/tools/channel-to.js";import{buildBaseToolContext}from"#context/build-base-tool-context.js";import{createAuthorizationContext}from"#runtime/authorization-context.js";import{completeWorkflowStepAuthorization}from"#execution/tools/workflow/authorization-completion.js";import"#execution/tools/workflow/step-context.js";const log=createLogger(`workflow-step`);function withWorkflowStepAuthorization(e){let wrapped=async function(t){let{args:n,context:r}=t;getStepMetadata();let i=new ContextContainer;i.set(AuthKey,r.session.auth.current),i.set(InitiatorAuthKey,r.session.auth.initiator),i.set(SessionIdKey,r.session.id),i.setVirtualContext(SessionKey,{...r.session,sessionId:r.session.id}),i.set(CallbackBaseUrlKey,resolveWorkflowCallbackBaseUrl(r.baseUrl)),i.setVirtualContext(AuthorizationHookKey,r.token),i.setVirtualContext(PendingAuthorizationResultKey,r.authorizationResults);let a=stepAgentLoader(r),o=openStepSandbox(r,a);return contextStorage.run(i,async()=>{let s=createAuthorizationContext({scope:r.toolName,completeAuthorization:completeWorkflowStepAuthorization}),c=buildBaseToolContext({toolName:r.toolName,options:{abortSignal:r.abortSignal,toolCallId:r.callId}}),l={...c,agent:()=>unavailableInStep(`ctx.agent()`,`Call ctx.agent() in the workflow body.`),ask:()=>unavailableInStep(`ctx.ask()`,`Call ctx.ask() in the workflow body.`),getSandbox:(async e=>{let t=await o.open();if(e!==void 0&&t.environment?.provider!==e.provider)throw fatal(`ctx.getSandbox() in a "use step" function received a sandbox environment the session's sandbox does not use. Pass the environment the agent's sandbox definition opens, or call ctx.getSandbox() without one.`);return i.setVirtualContext(SandboxKey,t),await c.getSandbox()}),getToken:s.getToken,requireAuth:s.requireAuth,channel:r.channel,to:createToolChannelTo({delegated:r.delegated,loadBundle:a})};Object.defineProperty(l,"agents",{get:()=>unavailableInStep(`ctx.agents`,`Read ctx.agents in the workflow body and pass the required serializable metadata into the step.`)});let u;try{u=await s.run(()=>Reflect.apply(e,this,n.map((e,n)=>t.contextIndexes.includes(n)?l:e)))}catch(e){throw isConnectionAuthorizationFailedError(e)&&!e.retryable&&Object.assign(e,{fatal:!0}),e}finally{await o.release()}let d=i.get(PendingAuthorizationResultKey)??[],f=r.authorizationResults.filter(e=>!d.includes(e)).map(e=>e.attemptId);return isAuthorizationSignal(u)?{kind:`authorization-required`,signal:u,authorized:f}:{kind:`result`,output:u,authorized:f}})};return Object.defineProperty(wrapped,"maxRetries",{get:()=>Reflect.get(e,`maxRetries`)}),wrapped}function stepAgentLoader(e){let{bundle:t}=e.sandbox,n=contextStorage.getStore(),resolveSource=()=>resolveDurableCompiledArtifactsSource(t.source);return async()=>await getCompiledRuntimeAgentBundle({compiledArtifactsSource:n===void 0?resolveSource():contextStorage.run(n,resolveSource),nodeId:t.nodeId})}function openStepSandbox(e,t){let{sessionId:n,state:r}=e.sandbox,i,a=!1,open=async()=>{let e=await t(),i=e.graph.root;return await ensureSandboxAccess({compiledArtifactsSource:e.compiledArtifactsSource,nodeId:i.nodeId,ownsSandbox:!1,registry:i.sandboxRegistry,sessionId:n,state:r??null,shutdownTracking:`none`})},openOnce=()=>(i??=open().catch(e=>{throw i=void 0,e}),i);return{async open(){if(a)throw fatal(`ctx.getSandbox() was called after the "use step" function of tool "${e.toolName}" returned. Call it inside the step, which lets go of the sandbox when it ends.`);return{...await openOnce(),delete:()=>unavailableInStep(`sandbox.delete()`,`The step borrows the session's sandbox, and only the session can delete it.`),stop:()=>unavailableInStep(`sandbox.stop()`,`The session's turns may be using the sandbox; eve closes the step's connection when the step ends.`)}},async release(){a=!0;let t=await i?.catch(()=>void 0);try{await t?.release()}catch(t){logError(log,`failed to release a workflow step's sandbox`,t,{sessionId:n,toolName:e.toolName})}}}}function unavailableInStep(e,t){throw fatal(`${e} is unavailable inside a "use step" function. ${t}`)}function fatal(e){return Object.assign(Error(e),{fatal:!0})}export{withWorkflowStepAuthorization};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHook,getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{disposeHook}from"#execution/hook-ownership.js";import{findWorkflowToolRunContext}from"#execution/tools/workflow/ask.js";import{signInInteractionId,signInOpened}from"#harness/interaction-facts.js";function workflowToolStep(e,t){return new Proxy(e,{apply(e,n,r){let i=findWorkflowContextArgument(r);return i===void 0?Reflect.apply(e,n,r):executeAuthorizedStep(t,n,r,i)}})}function findWorkflowContextArgument(e){for(let t of e){let e=findWorkflowToolRunContext(t);if(e!==void 0)return{ctx:t,run:e}}}async function executeAuthorizedStep(e,t,n,r){let{ctx:i,run:a}=r,o=[],s=new Map;for(;;){let r=createHook();try{let c;try{c=await invokeAuthorizedStep({args:n,authorizationResults:o,callbackToken:r.token,ctx:i,execute:e,receiver:t,run:a})}catch(e){throw i.abortSignal.aborted||await reportPendingAsFailed(a,i.abortSignal,s),e}if(await reconcileCompletedAuthorizations(a,i.abortSignal,s,o,c.authorized),c.kind===`result`)return await reportPendingAsFailed(a,i.abortSignal,s),c.output;await collectAuthorizationCallbacks({authorizationResults:o,callback:r,challenges:c.signal.challenges,ctx:i,pending:s,run:a})}finally{await disposeHook(r)}}}async function invokeAuthorizedStep(e){let{args:t,authorizationResults:n,callbackToken:r,ctx:i,execute:a,receiver:o,run:s}=e,c={callId:i.callId,toolName:i.toolName,session:i.session,abortSignal:i.abortSignal,baseUrl:getWorkflowMetadata().url,token:r,authorizationResults:n,sandbox:{bundle:s.agentContext.bundle,sessionId:s.agentContext.sandbox.sessionId,state:s.agentContext.sandbox.state}},l={args:t.map(e=>e===i?null:e),context:c,contextIndexes:t.flatMap((e,t)=>e===i?[t]:[])};return await a.call(o,l)}async function reconcileCompletedAuthorizations(e,t,n,r,i){let a=new Set(i);for(let r of a){let i=n.get(r);i!==void 0&&await reportAuthorization(e,t,i,`accepted`),n.delete(r)}for(let e=r.length-1;e>=0;e--){let t=r[e];t!==void 0&&a.has(t.attemptId)&&r.splice(e,1)}}async function collectAuthorizationCallbacks(e){let{authorizationResults:t,callback:n,challenges:r,ctx:i,pending:a,run:o}=e;for(let e of r){let r=requireAttemptId(e);a.set(r.attemptId,r),await reportAuthorization(o,i.abortSignal,r);try{let e=await waitForCallback(n,r,i.abortSignal);t.push({name:r.name,instanceId:r.instanceId,attemptId:r.attemptId,hookUrl:r.hookUrl,principal:r.principal,resume:r.resume,callback:e})}catch(e){throw i.abortSignal.aborted||await reportAuthorization(o,i.abortSignal,r,`failed`),e}}}function requireAttemptId(e){if(e.attemptId===void 0)throw Error(`Workflow authorization challenge "${e.name}" has no attempt id.`);return e}async function reportPendingAsFailed(e,t,n){for(let r of n.values())await reportAuthorization(e,t,r,`failed`)}async function reportAuthorization(e,t,n,r){let i=runSignIn(e.from,n,r),a=createHook();try{await a.getConflict(),await withAbort(e.owner.send({kind:`request`,from:e.from,replyTo:a.token,request:{kind:`relay`,event:{kind:`subagent-interaction`,callId:e.from.callId,childSessionId:e.from.runId,subagentName:e.from.toolName,events:[i]}}}),t),await withAbort(a,t)}finally{await disposeHook(a)}}async function waitForCallback(e,t,n){let r=e[Symbol.asyncIterator]();for(;;){let e=await withAbort(r.next(),n);if(e.done)throw Error(`Authorization callback closed before sign-in completed.`);let i=readCallback(e.value,t);if(i!==void 0)return i}}async function withAbort(e,t){let abort,n=new Promise((e,n)=>{abort=()=>n(t.reason??Error(`Workflow authorization cancelled.`)),t.addEventListener(`abort`,abort,{once:!0}),t.aborted&&abort()});try{return await Promise.race([e,n])}finally{t.removeEventListener(`abort`,abort)}}function readCallback(e,t){if(typeof e==`object`&&e&&`payloads`in e&&Array.isArray(e.payloads))for(let n of e.payloads){let e=n?.authorizationCallback;if(e?.attemptId!==t.attemptId||e?.connectionName!==t.name)continue;let r=e.callback;if(!(typeof r?.method!=`string`||typeof r.params!=`object`||r.params===null||Array.isArray(r.params))&&Object.values(r.params).every(e=>typeof e==`string`)&&(r.body===void 0||typeof r.body==`string`))return r}}function runSignIn(e,t,n){return n===void 0?{data:signInOpened(t,{prompt:`Sign in to ${t.name} to continue.`,subject:e.taskId===void 0?{turnId:e.turnId}:{taskId:e.taskId}}).data,type:`interaction.opened`}:{data:{interactionId:signInInteractionId(t),outcome:n},type:`interaction.settled`}}export{workflowToolStep};
|
|
1
|
+
import{createHook,getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{disposeHook}from"#execution/hook-ownership.js";import{findWorkflowToolRunContext}from"#execution/tools/workflow/ask.js";import{workflowToolChannel}from"#execution/tools/workflow/body.js";import{signInInteractionId,signInOpened}from"#harness/interaction-facts.js";function workflowToolStep(e,t){return new Proxy(e,{apply(e,n,r){let i=findWorkflowContextArgument(r);return i===void 0?Reflect.apply(e,n,r):executeAuthorizedStep(t,n,r,i)}})}function findWorkflowContextArgument(e){for(let t of e){let e=findWorkflowToolRunContext(t);if(e!==void 0)return{ctx:t,run:e}}}async function executeAuthorizedStep(e,t,n,r){let{ctx:i,run:a}=r,o=[],s=new Map;for(;;){let r=createHook();try{let c;try{c=await invokeAuthorizedStep({args:n,authorizationResults:o,callbackToken:r.token,ctx:i,execute:e,receiver:t,run:a})}catch(e){throw i.abortSignal.aborted||await reportPendingAsFailed(a,i.abortSignal,s),e}if(await reconcileCompletedAuthorizations(a,i.abortSignal,s,o,c.authorized),c.kind===`result`)return await reportPendingAsFailed(a,i.abortSignal,s),c.output;await collectAuthorizationCallbacks({authorizationResults:o,callback:r,challenges:c.signal.challenges,ctx:i,pending:s,run:a})}finally{await disposeHook(r)}}}async function invokeAuthorizedStep(e){let{args:t,authorizationResults:n,callbackToken:r,ctx:i,execute:a,receiver:o,run:s}=e,c={callId:i.callId,toolName:i.toolName,session:i.session,abortSignal:i.abortSignal,baseUrl:getWorkflowMetadata().url,token:r,authorizationResults:n,delegated:s.agentContext.delegated===!0,channel:workflowToolChannel(s.agentContext),sandbox:{bundle:s.agentContext.bundle,sessionId:s.agentContext.sandbox.sessionId,state:s.agentContext.sandbox.state}},l={args:t.map(e=>e===i?null:e),context:c,contextIndexes:t.flatMap((e,t)=>e===i?[t]:[])};return await a.call(o,l)}async function reconcileCompletedAuthorizations(e,t,n,r,i){let a=new Set(i);for(let r of a){let i=n.get(r);i!==void 0&&await reportAuthorization(e,t,i,`accepted`),n.delete(r)}for(let e=r.length-1;e>=0;e--){let t=r[e];t!==void 0&&a.has(t.attemptId)&&r.splice(e,1)}}async function collectAuthorizationCallbacks(e){let{authorizationResults:t,callback:n,challenges:r,ctx:i,pending:a,run:o}=e;for(let e of r){let r=requireAttemptId(e);a.set(r.attemptId,r),await reportAuthorization(o,i.abortSignal,r);try{let e=await waitForCallback(n,r,i.abortSignal);t.push({name:r.name,instanceId:r.instanceId,attemptId:r.attemptId,hookUrl:r.hookUrl,principal:r.principal,resume:r.resume,callback:e})}catch(e){throw i.abortSignal.aborted||await reportAuthorization(o,i.abortSignal,r,`failed`),e}}}function requireAttemptId(e){if(e.attemptId===void 0)throw Error(`Workflow authorization challenge "${e.name}" has no attempt id.`);return e}async function reportPendingAsFailed(e,t,n){for(let r of n.values())await reportAuthorization(e,t,r,`failed`)}async function reportAuthorization(e,t,n,r){let i=runSignIn(e.from,n,r),a=createHook();try{await a.getConflict(),await withAbort(e.owner.send({kind:`request`,from:e.from,replyTo:a.token,request:{kind:`relay`,event:{kind:`subagent-interaction`,callId:e.from.callId,childSessionId:e.from.runId,subagentName:e.from.toolName,events:[i]}}}),t),await withAbort(a,t)}finally{await disposeHook(a)}}async function waitForCallback(e,t,n){let r=e[Symbol.asyncIterator]();for(;;){let e=await withAbort(r.next(),n);if(e.done)throw Error(`Authorization callback closed before sign-in completed.`);let i=readCallback(e.value,t);if(i!==void 0)return i}}async function withAbort(e,t){let abort,n=new Promise((e,n)=>{abort=()=>n(t.reason??Error(`Workflow authorization cancelled.`)),t.addEventListener(`abort`,abort,{once:!0}),t.aborted&&abort()});try{return await Promise.race([e,n])}finally{t.removeEventListener(`abort`,abort)}}function readCallback(e,t){if(typeof e==`object`&&e&&`payloads`in e&&Array.isArray(e.payloads))for(let n of e.payloads){let e=n?.authorizationCallback;if(e?.attemptId!==t.attemptId||e?.connectionName!==t.name)continue;let r=e.callback;if(!(typeof r?.method!=`string`||typeof r.params!=`object`||r.params===null||Array.isArray(r.params))&&Object.values(r.params).every(e=>typeof e==`string`)&&(r.body===void 0||typeof r.body==`string`))return r}}function runSignIn(e,t,n){return n===void 0?{data:signInOpened(t,{prompt:`Sign in to ${t.name} to continue.`,subject:e.taskId===void 0?{turnId:e.turnId}:{taskId:e.taskId}}).data,type:`interaction.opened`}:{data:{interactionId:signInInteractionId(t),outcome:n},type:`interaction.settled`}}export{workflowToolStep};
|
|
@@ -32,8 +32,7 @@ export declare function createBrowserCallbackUrl(baseUrl: string, callbackPath:
|
|
|
32
32
|
/**
|
|
33
33
|
* Builds a framework-owned callback URL for server-to-server delivery.
|
|
34
34
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* protected deployment.
|
|
35
|
+
* The URL carries only the callback's scoped capability. Deployment protection
|
|
36
|
+
* credentials belong to the delivering deployment's trusted-origin transport.
|
|
38
37
|
*/
|
|
39
38
|
export declare function createWorkflowCallbackUrl(baseUrl: string, callbackPath: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{joinEveRoutePath}from"#shared/eve-route-path.js";import{EVE_PUBLIC_ROUTE_PREFIX_ENV,normalizePublicRoutePrefix}from"#shared/public-route-prefix.js";function resolveVercelProductionCallbackBaseUrl(){return process.env.VERCEL_ENV===`production`&&process.env.VERCEL_PROJECT_PRODUCTION_URL?`https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`:null}function resolveWorkflowCallbackBaseUrl(e){let t=process.env.WORKFLOW_LOCAL_BASE_URL?.trim()||void 0,n=(resolveVercelProductionCallbackBaseUrl()??t??e).replace(/\/$/,``),r=normalizePublicRoutePrefix(process.env[EVE_PUBLIC_ROUTE_PREFIX_ENV]);return r===void 0?n:`${n}${r}`}function createBrowserCallbackUrl(e,t){let n=new URL(t,`http://eve.local`),r=new URL(e);return r.pathname=joinEveRoutePath(r.pathname,n.pathname),r.search=n.search,r.toString()}function createWorkflowCallbackUrl(e,t){
|
|
1
|
+
import{joinEveRoutePath}from"#shared/eve-route-path.js";import{EVE_PUBLIC_ROUTE_PREFIX_ENV,normalizePublicRoutePrefix}from"#shared/public-route-prefix.js";function resolveVercelProductionCallbackBaseUrl(){return process.env.VERCEL_ENV===`production`&&process.env.VERCEL_PROJECT_PRODUCTION_URL?`https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`:null}function resolveWorkflowCallbackBaseUrl(e){let t=process.env.WORKFLOW_LOCAL_BASE_URL?.trim()||void 0,n=(resolveVercelProductionCallbackBaseUrl()??t??e).replace(/\/$/,``),r=normalizePublicRoutePrefix(process.env[EVE_PUBLIC_ROUTE_PREFIX_ENV]);return r===void 0?n:`${n}${r}`}function createBrowserCallbackUrl(e,t){let n=new URL(t,`http://eve.local`),r=new URL(e);return r.pathname=joinEveRoutePath(r.pathname,n.pathname),r.search=n.search,r.toString()}function createWorkflowCallbackUrl(e,t){return createBrowserCallbackUrl(e,t)}export{createBrowserCallbackUrl,createWorkflowCallbackUrl,resolveVercelProductionCallbackBaseUrl,resolveWorkflowCallbackBaseUrl};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{validateDeliveryIdempotencyKey}from"#channel/delivery-idempotency.js";import{createChannelDeliveryMetadata}from"#channel/delivery-metadata.js";import{SessionStrandedError,describeStrandedSession}from"#channel/session-stranded-error.js";import{sessionCommandHookToken,sessionInboxHookToken}from"#execution/session-inbox/address.js";import{SessionPredecessorKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{walkCauseChain}from"#shared/errors.js";import{validateToolStubTargets}from"#tool-stubs/validate-targets.js";import{getHookByToken,getRun,getWorld,start}from"#internal/workflow/runtime.js";import{assertSessionHistoryReadable,readSessionEventHistory,readSessionEventStream,readSessionRecordHistory,readSessionRecords,readSessionStreamTailIndex}from"#execution/session-event-stream.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{serializeContext}from"#context/serialize.js";import{AcceptedSessionIdentityError,SessionHandoffPendingError,logicalSessionToken,resolveSessionInbox,resumeSessionInbox}from"#execution/session-inbox/resume.js";import{resolveEffectiveAgentRuntime}from"#execution/effective-agent-config.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{EntityConflictError,HookNotFoundError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{StrandedSessionOwnerError,assertRunnableSessionInbox,assertRunnableSessionOwner,findSessionHookHolder}from"#execution/session-inbox/owner.js";import{initializeSessionInstrumentation}from"#instrumentation/runtime.js";import{EVE_PREWARM_ATTRIBUTE,EVE_VERSION_ATTRIBUTE,buildSessionAttributes,buildSubagentRootAttributes,readParentLineage}from"#execution/eve-workflow-attributes.js";import{endStrandedSession}from"#execution/session-inbox/end-stranded-session.js";import{SESSION_HOOK_HANDOVER_TIMEOUT_MS,waitForSessionHooksRelease}from"#execution/session-inbox/hook-release.js";import{CONNECTION_EVENT_DELIVERY_WORKFLOW_NAME,CONNECTION_EVENT_WORKFLOW_NAME,SESSION_TIMEOUT_WORKFLOW_NAME,WORKFLOW_ENTRY_NAME,WORKFLOW_TOOL_RUN_WORKFLOW_NAME}from"#execution/stable-workflow-names.js";import{readRemoteChildBinding}from"#execution/child-binding.js";import{prewarmWorkflowSession}from"#execution/session-prewarm.js";import{normalizeEveAttributes}from"#runtime/attributes/normalize.js";import{buildRunContext}from"#execution/runtime-context.js";import{buildInvocationAttributes}from"#internal/invocation/metadata.js";import{isAgentTraceContext}from"#tracing/eve/agent-trace-context.js";const EVE_PACKAGE_INFO=resolveInstalledPackageInfo(),STABLE_ID_BASE=EVE_PACKAGE_INFO.name,log=createLogger(`execution.workflow-runtime`),workflowEntryReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_ENTRY_NAME}`},sessionTimeoutWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${SESSION_TIMEOUT_WORKFLOW_NAME}`},workflowToolRunWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_TOOL_RUN_WORKFLOW_NAME}`},connectionEventWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${CONNECTION_EVENT_WORKFLOW_NAME}`},connectionEventDeliveryWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${CONNECTION_EVENT_DELIVERY_WORKFLOW_NAME}`};function createWorkflowRuntime(e){let startSession=async(t,n)=>{validateDeliveryIdempotencyKey(t.idempotencyKey),t.input.message!==void 0&&t.delivery===void 0&&(t={...t,delivery:createChannelDeliveryMetadata({channelKind:t.adapter.kind,channelName:t.channelName??t.adapter.kind,requestId:t.requestId})});let r=t.continuationConflictCommand;r!==void 0&&r.delivery===void 0&&(t={...t,continuationConflictCommand:{...r,delivery:t.delivery}});let i=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:e.compiledArtifactsSource,nodeId:e.nodeId});t.toolStubs!==void 0&&t.toolStubs.rootSessionId===void 0&&validateToolStubTargets(t.toolStubs.rules,i.graph);let a=buildRunContext({agentSessionRuntimeOverrides:e.agentSessionRuntimeOverrides,bundle:i,dynamicSubagentAgentConfig:e.dynamicSubagentAgentConfig,run:t});n!==void 0&&a.set(SessionPredecessorKey,n);let o=resolveEffectiveAgentRuntime(i,a),s=initializeSessionInstrumentation({agentName:o.turnAgent.id,ctx:a}),c=o.limits?.sessionTimeoutMs,l=i.resolvedAgent.config?.experimental?.workflow?.retention??(s.action===`record`&&s.recordInputs&&s.recordOutputs?void 0:0),u=serializeContext(a),d=readParentLineage(u),f={idempotencyKey:t.idempotencyKey,kind:`initial`,input:t.input,ownerDeploymentId:await resolveCurrentWorkflowDeploymentId(),serializedContext:u};t.continuationConflictCommand!==void 0&&(f.continuationConflictCommand=t.continuationConflictCommand),c!==void 0&&(f.sessionTimeoutMs=c),l!==void 0&&(f.retention=l);let p={...d.sessionId===void 0?buildSessionAttributes({serializedContext:u}):buildSubagentRootAttributes({identity:{nodeId:i.nodeId??ROOT_RUNTIME_AGENT_NODE_ID},parentCallId:d.callId,parentSessionId:d.sessionId,parentTurnId:d.turnId,rootSessionId:d.rootSessionId??d.sessionId,serializedContext:u}),[EVE_PREWARM_ATTRIBUTE]:`1`,...t.externalInvocation===void 0?{}:buildInvocationAttributes(t.externalInvocation)},m;try{let e={allowReservedAttributes:!0,attributes:normalizeEveAttributes(p)};l!==void 0&&(e.experimental_retention=l),m=await startWorkflowOnDeployment(workflowEntryReference,[f],f.ownerDeploymentId,e)}catch(e){throw logError(log,`failed to start workflow run`,e,{continuationToken:t.continuationToken}),e}let h=m.runId;if(t.idempotencyKey!==void 0&&t.continuationToken!==void 0){let e=await pollUntil(()=>resolveContinuation(t.continuationToken),SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(e===void 0)throw Error(`Delivery accepted, but its session identity is not ready. Retry with the same idempotencyKey.`);h=e.sessionId}let g,getEvents=()=>(g??=readSessionEventStream(h),g);return{get events(){return getEvents()},sessionId:h,...t.delivery!==void 0&&{deliveryId:t.delivery.deliveryId}}};return{async createSession(e){return await startSession(e)},async dispatchContinuation(e){let{continuationToken:t,successor:n}=e,r=identifyCommand(e.command);try{return await dispatchWorkflowCommand(t,r)}catch(e){if(!(e instanceof StrandedSessionOwnerError))throw e;if(r.kind!==`send`||n===void 0)return await settleStrandedCommand(t,r,e);if((r.payload.answers?.length??0)>0)throw sessionStrandedError(e,`Its pending requests can no longer be answered; send a new message to start a fresh session.`);let i=await endStrandedSession(e,t,`message`);return{sessionId:(await startSession({...n,delivery:r.delivery},{sessionId:i})).sessionId,deliveryId:r.delivery?.deliveryId,status:`accepted`}}},async dispatchSession(e){return await dispatchWorkflowSessionCommand(e)},async getEventStream(e,t){return t?.follow===!1?readSessionEventHistory(e,t.startIndex,t.signal):(await assertFollowableSession(e),readSessionEventStream(e,t?.startIndex,t?.signal))},async getLineStream(e,t){return t?.follow===!1?readSessionRecordHistory(e,t.startIndex):(await assertFollowableSession(e),readSessionRecords(e,t?.startIndex))},async getStreamTailIndex(e){return await readSessionStreamTailIndex(e)},async readChildBinding(e,t){return await readRemoteChildBinding(e,t)},async hasRunnableOwner(e){let t=sessionInboxHookToken(sessionCommandHookToken(e)),n=await findSessionHookHolder(t);if(n===void 0)return!1;try{return await assertRunnableSessionOwner(n),!0}catch(e){if(e instanceof StrandedSessionOwnerError)return!1;throw e}},resolveContinuation}}async function dispatchWorkflowCommand(e,t){if(t.kind===`prewarm`)return typeof e==`string`?{status:`unsupported`}:await prewarmWorkflowSession(e.sessionId,t.targetDeploymentId);let n,r;try{let i=await resumeSessionInbox(e,t);r=i.inbox,n={runId:i.ownerRunId,sessionId:await i.sessionId}}catch(n){if(n instanceof StrandedSessionOwnerError)throw n;let r=t.kind===`send`&&typeof e!=`string`,i={status:`session_not_active`,retryable:!0};if(n instanceof SessionHandoffPendingError){if(r)return i;throw n}if(isInactiveCommandTarget(n))return r&&await isRunActive(e.sessionId)?i:inactiveCommandResult(t);throw logError(log,`failed to dispatch session command`,n,{command:t.kind,token:e}),n}t.kind===`reset`&&await waitForSessionHooksRelease([sessionCommandHookToken(n.sessionId),logicalSessionToken(e)],{ownerRunId:n.runId,sessionId:n.sessionId});let i=activeCommandResult(t,n.sessionId);return i.status===`accepted`?{...i,inbox:r}:i}async function settleStrandedCommand(e,t,n){switch(t.kind){case`reset`:return{previousSessionId:await endStrandedSession(n,e,`reset`,t),status:`reset`};case`send`:case`clear`:throw sessionStrandedError(n);default:return inactiveCommandResult(t)}}async function assertFollowableSession(e){try{await Promise.all([assertRunnableSessionInbox(sessionInboxHookToken(sessionCommandHookToken(e))),assertSessionHistoryReadable(e)])}catch(e){throw e instanceof StrandedSessionOwnerError?sessionStrandedError(e):e}}function sessionStrandedError(e,t){let n=e.eveVersion===void 0?{}:{eveVersion:e.eveVersion};return new SessionStrandedError(n,describeStrandedSession(n,t))}function activeCommandResult(e,t){return e.kind===`reset`?{previousSessionId:t,status:`reset`}:e.kind===`send`&&e.delivery!==void 0?{sessionId:t,status:`accepted`,deliveryId:e.delivery.deliveryId}:{sessionId:t,status:`accepted`}}function inactiveCommandResult(e){return e.kind===`send`?{status:`session_not_active`}:e.kind===`cancel`?{status:`no_active_turn`}:{status:`no_active_session`}}async function dispatchWorkflowSessionCommand(e){let t={sessionId:e.sessionId,inbox:e.inbox},n=identifyCommand(e.command);try{return await dispatchWorkflowCommand(t,n)}catch(e){if(!(e instanceof StrandedSessionOwnerError))throw e;return await settleStrandedCommand(t,n,e)}}async function isRunActive(e){try{let t=await getRun(e).status;return t===`pending`||t===`running`}catch(e){if(isInactiveCommandTarget(e))return!1;throw e}}function isInactiveCommandTarget(e){if(e instanceof AcceptedSessionIdentityError)return!1;if(HookNotFoundError.is(e))return!0;for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t)||RunExpiredError.is(t)||EntityConflictError.is(t))return!0;return!1}async function resolveContinuation(e,t){let n;try{n=await resolveSessionInbox(e)}catch(t){if(HookNotFoundError.is(t))return;throw logError(log,`failed to resolve session by continuation token`,t,{continuationToken:e}),t}if(t?.runnable!==!0)return n;try{await assertRunnableSessionInbox(sessionInboxHookToken(sessionCommandHookToken(n.sessionId)))}catch(e){throw e instanceof StrandedSessionOwnerError?sessionStrandedError(e):e}return n}async function waitForCommandHookOwner(e){let t=await pollUntil(async()=>{try{return normalizeWorkflowHook(await getHookByToken(e))}catch(e){if(!HookNotFoundError.is(e))throw e;return}},SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(t===void 0)throw new HookNotFoundError(e);return t}async function waitForSessionInbox(e){let t=sessionInboxHookToken(sessionCommandHookToken(e)),n=await pollUntil(async()=>await findSessionHookHolder(t)!==void 0||!await hasRunEnded(e)&&void 0,SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(n===void 0)throw Error(`Session "${e}" did not start taking commands within ${SESSION_HOOK_HANDOVER_TIMEOUT_MS/1e3} seconds.`);return n}async function pollUntil(e,t){let n=Date.now()+t;for(let t=20;;t=Math.min(t*2,200)){let r=await e();if(r!==void 0||Date.now()>=n)return r;await new Promise(e=>setTimeout(e,t))}}async function hasRunEnded(e){try{let t=await getRun(e).status;return t!==`pending`&&t!==`running`}catch(e){for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t))return!1;if(isInactiveCommandTarget(e))return!0;throw e}}async function startWorkflowOnCurrentDeployment(e,t,n){return await startWorkflowOnDeployment(e,t,await resolveCurrentWorkflowDeploymentId(),n)}async function startWorkflowOnDeployment(e,t,n,r){return await withWorkflowStartContext(async()=>{if(n.length===0||n===`latest`)throw Error(`Workflow starts require an exact deployment id.`);return await start(e,t,{...r,allowReservedAttributes:!0,attributes:{...r?.attributes,[EVE_VERSION_ATTRIBUTE]:EVE_PACKAGE_INFO.version},deploymentId:n})})}async function resolveCurrentWorkflowDeploymentId(){let e=process.env.VERCEL_DEPLOYMENT_ID?.trim()||await(await getWorld()).getDeploymentId();if(e.length===0||e===`latest`)throw Error(`Workflow runtime could not resolve an exact deployment id.`);return e}async function withWorkflowStartContext(e){let t=context.active(),n=isAgentTraceContext(t)?trace.deleteSpan(t):t;return await context.with(n,e)}function normalizeWorkflowHook(e){if(typeof e!=`object`||!e||!(`runId`in e))throw Error(`Workflow hook did not include a run id.`);let t=e.runId;if(typeof t!=`string`||t.length===0)throw Error(`Workflow hook did not include a run id.`);return{runId:t}}function identifyCommand(e){if(e.kind!==`send`||e.delivery!==void 0)return e;let t=e.caller===void 0?e.schedule===void 0?`http`:`schedule`:`subagent`;return{...e,delivery:createChannelDeliveryMetadata({channelKind:t,channelName:t,requestId:e.requestId})}}export{connectionEventDeliveryWorkflowReference,connectionEventWorkflowReference,createWorkflowRuntime,dispatchWorkflowSessionCommand,hasRunEnded,pollUntil,resolveContinuation,sessionTimeoutWorkflowReference,startWorkflowOnCurrentDeployment,startWorkflowOnDeployment,waitForCommandHookOwner,waitForSessionInbox,workflowEntryReference,workflowToolRunWorkflowReference};
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{validateDeliveryIdempotencyKey}from"#channel/delivery-idempotency.js";import{createChannelDeliveryMetadata}from"#channel/delivery-metadata.js";import{SessionStrandedError,describeStrandedSession}from"#channel/session-stranded-error.js";import{sessionCommandHookToken,sessionInboxHookToken}from"#execution/session-inbox/address.js";import{SessionPredecessorKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{walkCauseChain}from"#shared/errors.js";import{validateToolStubTargets}from"#tool-stubs/validate-targets.js";import{getHookByToken,getRun,getWorld,start}from"#internal/workflow/runtime.js";import{assertSessionHistoryReadable,readSessionEventHistory,readSessionEventStream,readSessionRecordHistory,readSessionRecords,readSessionStreamTailIndex}from"#execution/session-event-stream.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{serializeContext}from"#context/serialize.js";import{AcceptedSessionIdentityError,SessionHandoffPendingError,logicalSessionToken,resolveSessionInbox,resumeSessionInbox}from"#execution/session-inbox/resume.js";import{resolveEffectiveAgentRuntime}from"#execution/effective-agent-config.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{EntityConflictError,HookNotFoundError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{StrandedSessionOwnerError,assertRunnableSessionInbox,assertRunnableSessionOwner,findSessionHookHolder}from"#execution/session-inbox/owner.js";import{initializeSessionInstrumentation}from"#instrumentation/runtime.js";import{EVE_PREWARM_ATTRIBUTE,EVE_VERSION_ATTRIBUTE,buildSessionAttributes,buildSubagentRootAttributes,readParentLineage}from"#execution/eve-workflow-attributes.js";import{endStrandedSession}from"#execution/session-inbox/end-stranded-session.js";import{SESSION_HOOK_HANDOVER_TIMEOUT_MS,waitForSessionHooksRelease}from"#execution/session-inbox/hook-release.js";import{CONNECTION_EVENT_DELIVERY_WORKFLOW_NAME,CONNECTION_EVENT_WORKFLOW_NAME,SESSION_TIMEOUT_WORKFLOW_NAME,WORKFLOW_ENTRY_NAME,WORKFLOW_TOOL_RUN_WORKFLOW_NAME}from"#execution/stable-workflow-names.js";import{readRemoteChildBinding}from"#execution/child-binding.js";import{prewarmWorkflowSession}from"#execution/session-prewarm.js";import{formatCapabilityError}from"#internal/capability-error.js";import{normalizeEveAttributes}from"#runtime/attributes/normalize.js";import{buildRunContext}from"#execution/runtime-context.js";import{buildInvocationAttributes}from"#internal/invocation/metadata.js";import{isAgentTraceContext}from"#tracing/eve/agent-trace-context.js";const EVE_PACKAGE_INFO=resolveInstalledPackageInfo(),STABLE_ID_BASE=EVE_PACKAGE_INFO.name,log=createLogger(`execution.workflow-runtime`),workflowEntryReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_ENTRY_NAME}`},sessionTimeoutWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${SESSION_TIMEOUT_WORKFLOW_NAME}`},workflowToolRunWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_TOOL_RUN_WORKFLOW_NAME}`},connectionEventWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${CONNECTION_EVENT_WORKFLOW_NAME}`},connectionEventDeliveryWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${CONNECTION_EVENT_DELIVERY_WORKFLOW_NAME}`};function createWorkflowRuntime(e){let startSession=async(t,n)=>{validateDeliveryIdempotencyKey(t.idempotencyKey),t.input.message!==void 0&&t.delivery===void 0&&(t={...t,delivery:createChannelDeliveryMetadata({channelKind:t.adapter.kind,channelName:t.channelName??t.adapter.kind,requestId:t.requestId})});let r=t.continuationConflictCommand;r!==void 0&&r.delivery===void 0&&(t={...t,continuationConflictCommand:{...r,delivery:t.delivery}});let i=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:e.compiledArtifactsSource,nodeId:e.nodeId});t.toolStubs!==void 0&&t.toolStubs.rootSessionId===void 0&&validateToolStubTargets(t.toolStubs.rules,i.graph);let a=buildRunContext({agentSessionRuntimeOverrides:e.agentSessionRuntimeOverrides,bundle:i,dynamicSubagentAgentConfig:e.dynamicSubagentAgentConfig,run:t});n!==void 0&&a.set(SessionPredecessorKey,n);let o=resolveEffectiveAgentRuntime(i,a),s=initializeSessionInstrumentation({agentName:o.turnAgent.id,ctx:a}),c=o.limits?.sessionTimeoutMs,l=i.resolvedAgent.config?.experimental?.workflow?.retention??(s.action===`record`&&s.recordInputs&&s.recordOutputs?void 0:0),u=serializeContext(a),d=readParentLineage(u),f={idempotencyKey:t.idempotencyKey,kind:`initial`,input:t.input,ownerDeploymentId:await resolveCurrentWorkflowDeploymentId(),serializedContext:u};t.continuationConflictCommand!==void 0&&(f.continuationConflictCommand=t.continuationConflictCommand),c!==void 0&&(f.sessionTimeoutMs=c),l!==void 0&&(f.retention=l);let p={...d.sessionId===void 0?buildSessionAttributes({serializedContext:u}):buildSubagentRootAttributes({identity:{nodeId:i.nodeId??ROOT_RUNTIME_AGENT_NODE_ID},parentCallId:d.callId,parentSessionId:d.sessionId,parentTurnId:d.turnId,rootSessionId:d.rootSessionId??d.sessionId,serializedContext:u}),[EVE_PREWARM_ATTRIBUTE]:`1`,...t.externalInvocation===void 0?{}:buildInvocationAttributes(t.externalInvocation)},m;try{let e={allowReservedAttributes:!0,attributes:normalizeEveAttributes(p)};l!==void 0&&(e.experimental_retention=l),m=await startWorkflowOnDeployment(workflowEntryReference,[f],f.ownerDeploymentId,e)}catch(e){throw log.error(`failed to start workflow run`,{error:formatCapabilityError(e,[t.continuationToken])}),e}let h=m.runId;if(t.idempotencyKey!==void 0&&t.continuationToken!==void 0){let e=await pollUntil(()=>resolveContinuation(t.continuationToken),SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(e===void 0)throw Error(`Delivery accepted, but its session identity is not ready. Retry with the same idempotencyKey.`);h=e.sessionId}let g,getEvents=()=>(g??=readSessionEventStream(h),g);return{get events(){return getEvents()},sessionId:h,...t.delivery!==void 0&&{deliveryId:t.delivery.deliveryId}}};return{async createSession(e){return await startSession(e)},async dispatchContinuation(e){let{continuationToken:t,successor:n}=e,r=identifyCommand(e.command);try{return await dispatchWorkflowCommand(t,r)}catch(e){if(!(e instanceof StrandedSessionOwnerError))throw e;if(r.kind!==`send`||n===void 0)return await settleStrandedCommand(t,r,e);if((r.payload.answers?.length??0)>0)throw sessionStrandedError(e,`Its pending requests can no longer be answered; send a new message to start a fresh session.`);let i=await endStrandedSession(e,t,`message`);return{sessionId:(await startSession({...n,delivery:r.delivery},{sessionId:i})).sessionId,deliveryId:r.delivery?.deliveryId,status:`accepted`}}},async dispatchSession(e){return await dispatchWorkflowSessionCommand(e)},async getEventStream(e,t){return t?.follow===!1?readSessionEventHistory(e,t.startIndex,t.signal):(await assertFollowableSession(e),readSessionEventStream(e,t?.startIndex,t?.signal))},async getLineStream(e,t){return t?.follow===!1?readSessionRecordHistory(e,t.startIndex):(await assertFollowableSession(e),readSessionRecords(e,t?.startIndex))},async getStreamTailIndex(e){return await readSessionStreamTailIndex(e)},async readChildBinding(e,t){return await readRemoteChildBinding(e,t)},async hasRunnableOwner(e){let t=sessionInboxHookToken(sessionCommandHookToken(e)),n=await findSessionHookHolder(t);if(n===void 0)return!1;try{return await assertRunnableSessionOwner(n),!0}catch(e){if(e instanceof StrandedSessionOwnerError)return!1;throw e}},resolveContinuation}}async function dispatchWorkflowCommand(e,t){if(t.kind===`prewarm`)return typeof e==`string`?{status:`unsupported`}:await prewarmWorkflowSession(e.sessionId,t.targetDeploymentId);let n,r;try{let i=await resumeSessionInbox(e,t);r=i.inbox,n={runId:i.ownerRunId,sessionId:await i.sessionId}}catch(n){if(n instanceof StrandedSessionOwnerError)throw n;let r=t.kind===`send`&&typeof e!=`string`,i={status:`session_not_active`,retryable:!0};if(n instanceof SessionHandoffPendingError){if(r)return i;throw n}if(isInactiveCommandTarget(n))return r&&await isRunActive(e.sessionId)?i:inactiveCommandResult(t);let a=logicalSessionToken(e);throw log.error(`failed to dispatch session command`,{command:t.kind,error:formatCapabilityError(n,[a,sessionInboxHookToken(a)])}),n}t.kind===`reset`&&await waitForSessionHooksRelease([sessionCommandHookToken(n.sessionId),logicalSessionToken(e)],{ownerRunId:n.runId,sessionId:n.sessionId});let i=activeCommandResult(t,n.sessionId);return i.status===`accepted`?{...i,inbox:r}:i}async function settleStrandedCommand(e,t,n){switch(t.kind){case`reset`:return{previousSessionId:await endStrandedSession(n,e,`reset`,t),status:`reset`};case`send`:case`clear`:throw sessionStrandedError(n);default:return inactiveCommandResult(t)}}async function assertFollowableSession(e){try{await Promise.all([assertRunnableSessionInbox(sessionInboxHookToken(sessionCommandHookToken(e))),assertSessionHistoryReadable(e)])}catch(e){throw e instanceof StrandedSessionOwnerError?sessionStrandedError(e):e}}function sessionStrandedError(e,t){let n=e.eveVersion===void 0?{}:{eveVersion:e.eveVersion};return new SessionStrandedError(n,describeStrandedSession(n,t))}function activeCommandResult(e,t){return e.kind===`reset`?{previousSessionId:t,status:`reset`}:e.kind===`send`&&e.delivery!==void 0?{sessionId:t,status:`accepted`,deliveryId:e.delivery.deliveryId}:{sessionId:t,status:`accepted`}}function inactiveCommandResult(e){return e.kind===`send`?{status:`session_not_active`}:e.kind===`cancel`?{status:`no_active_turn`}:{status:`no_active_session`}}async function dispatchWorkflowSessionCommand(e){let t={sessionId:e.sessionId,inbox:e.inbox},n=identifyCommand(e.command);try{return await dispatchWorkflowCommand(t,n)}catch(e){if(!(e instanceof StrandedSessionOwnerError))throw e;return await settleStrandedCommand(t,n,e)}}async function isRunActive(e){try{let t=await getRun(e).status;return t===`pending`||t===`running`}catch(e){if(isInactiveCommandTarget(e))return!1;throw e}}function isInactiveCommandTarget(e){if(e instanceof AcceptedSessionIdentityError)return!1;if(HookNotFoundError.is(e))return!0;for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t)||RunExpiredError.is(t)||EntityConflictError.is(t))return!0;return!1}async function resolveContinuation(e,t){let n;try{n=await resolveSessionInbox(e)}catch(t){if(HookNotFoundError.is(t))return;throw log.error(`failed to resolve session by continuation token`,{error:formatCapabilityError(t,[e])}),t}if(t?.runnable!==!0)return n;try{await assertRunnableSessionInbox(sessionInboxHookToken(sessionCommandHookToken(n.sessionId)))}catch(e){throw e instanceof StrandedSessionOwnerError?sessionStrandedError(e):e}return n}async function waitForCommandHookOwner(e){let t=await pollUntil(async()=>{try{return normalizeWorkflowHook(await getHookByToken(e))}catch(e){if(!HookNotFoundError.is(e))throw e;return}},SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(t===void 0)throw new HookNotFoundError(e);return t}async function waitForSessionInbox(e){let t=sessionInboxHookToken(sessionCommandHookToken(e)),n=await pollUntil(async()=>await findSessionHookHolder(t)!==void 0||!await hasRunEnded(e)&&void 0,SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(n===void 0)throw Error(`Session "${e}" did not start taking commands within ${SESSION_HOOK_HANDOVER_TIMEOUT_MS/1e3} seconds.`);return n}async function pollUntil(e,t){let n=Date.now()+t;for(let t=20;;t=Math.min(t*2,200)){let r=await e();if(r!==void 0||Date.now()>=n)return r;await new Promise(e=>setTimeout(e,t))}}async function hasRunEnded(e){try{let t=await getRun(e).status;return t!==`pending`&&t!==`running`}catch(e){for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t))return!1;if(isInactiveCommandTarget(e))return!0;throw e}}async function startWorkflowOnCurrentDeployment(e,t,n){return await startWorkflowOnDeployment(e,t,await resolveCurrentWorkflowDeploymentId(),n)}async function startWorkflowOnDeployment(e,t,n,r){return await withWorkflowStartContext(async()=>{if(n.length===0||n===`latest`)throw Error(`Workflow starts require an exact deployment id.`);return await start(e,t,{...r,allowReservedAttributes:!0,attributes:{...r?.attributes,[EVE_VERSION_ATTRIBUTE]:EVE_PACKAGE_INFO.version},deploymentId:n})})}async function resolveCurrentWorkflowDeploymentId(){let e=process.env.VERCEL_DEPLOYMENT_ID?.trim()||await(await getWorld()).getDeploymentId();if(e.length===0||e===`latest`)throw Error(`Workflow runtime could not resolve an exact deployment id.`);return e}async function withWorkflowStartContext(e){let t=context.active(),n=isAgentTraceContext(t)?trace.deleteSpan(t):t;return await context.with(n,e)}function normalizeWorkflowHook(e){if(typeof e!=`object`||!e||!(`runId`in e))throw Error(`Workflow hook did not include a run id.`);let t=e.runId;if(typeof t!=`string`||t.length===0)throw Error(`Workflow hook did not include a run id.`);return{runId:t}}function identifyCommand(e){if(e.kind!==`send`||e.delivery!==void 0)return e;let t=e.caller===void 0?e.schedule===void 0?`http`:`schedule`:`subagent`;return{...e,delivery:createChannelDeliveryMetadata({channelKind:t,channelName:t,requestId:e.requestId})}}export{connectionEventDeliveryWorkflowReference,connectionEventWorkflowReference,createWorkflowRuntime,dispatchWorkflowSessionCommand,hasRunEnded,pollUntil,resolveContinuation,sessionTimeoutWorkflowReference,startWorkflowOnCurrentDeployment,startWorkflowOnDeployment,waitForCommandHookOwner,waitForSessionInbox,workflowEntryReference,workflowToolRunWorkflowReference};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{openWork}from"#protocol/session-projection/selectors.js";import{streamText}from"ai";import{createLogger,logError}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{AuthKey,HistoryStateKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{takeCompactionCaptureFailure}from"#reactions/kinds/memory.js";import{addTokenUsage}from"#shared/token-usage-math.js";import{isUserModelMessage,validateHarnessModelMessages}from"#harness/messages.js";import{controlDeliveryFor}from"#harness/session-machine/transitions.js";import{
|
|
1
|
+
import{openWork}from"#protocol/session-projection/selectors.js";import{streamText}from"ai";import{createLogger,logError}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{AuthKey,HistoryStateKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{takeCompactionCaptureFailure}from"#reactions/kinds/memory.js";import{addTokenUsage}from"#shared/token-usage-math.js";import{isUserModelMessage,validateHarnessModelMessages}from"#harness/messages.js";import{controlDeliveryFor}from"#harness/session-machine/transitions.js";import{NO_USAGE,markUsageReported}from"#harness/session-usage.js";import{nextChangeId,nextRunId}from"#protocol/session-projection.js";import{contextStarted,controlAdmitted,deliveryApplied,fact,runRequested,runSettledFacts,runStarted,usageOf}from"#harness/facts.js";import{CompactionOverLimitError}from"#harness/compaction/over-limit-error.js";import{estimateTokens}from"#harness/token-estimate.js";import{compactMessages,getInputTokenCount,shouldCompact,withoutPromptMeasurement}from"#harness/compaction/engine.js";import{requireSessionModelReference}from"#harness/types.js";import{buildGatewayAttributionHeaders,resolveEffectiveRuntimeModel,withGatewayTraceContext}from"#harness/model-call/model.js";import{normalizeModelStreamError}from"#harness/model-call/errors.js";import{runModelCallWithRetries}from"#harness/model-call/retry.js";import{extractGatewayCostUsd,extractTokenUsageDelta,gatewayModelId}from"#harness/model-call/usage.js";import{resolveModelProfile}from"#harness/model-profile.js";import{resolveCallProviderOptions}from"#harness/provider-safety.js";const log=createLogger(`harness.tool-loop`);function assertFixedPartFits(e){let t=e.requestEnvelopeTokens+e.protectedTokens;if(t>=e.threshold)throw new CompactionOverLimitError(`The agent's system prompt, tools, memory and context take ~${Math.round(t)} tokens, over this model's ~${e.threshold}-token compaction limit. Shorten the instructions, remove tools or trim memory.`)}async function compactHistory(e){let{config:t}=e,{projection:n}=e.view(),r=controlDeliveryFor(e.view(),t.controlDelivery),{deliveryId:i}=r,a=nextChangeId(n);if(e.session.history.length===0)return await e.apply([controlAdmitted(r,`compact`),deliveryApplied(i)]),{next:null,session:e.session};let o=validateHarnessModelMessages(e.session.history);await e.apply([controlAdmitted(r,`compact`),contextStarted({cause:{deliveryId:i},changeId:a,kind:`compaction`})],o);let s=nextRunId(e.view().projection),c=`applied`;try{await e.apply([runRequested({changeId:a},s)],o);let n=await resolveEffectiveRuntimeModel({config:t,ctx:e.ctx,session:e.session});e.session=n.session;let r=e.session.agent.compactionModelReference??requireSessionModelReference(e.session);await e.publish(runStarted({attempt:0,modelId:r.id,runId:s}));let i=await maybeCompact({abortSignal:t.abortSignal,auth:e.ctx?.get(AuthKey)??null,betweenTurns:!0,change:{announced:!0,changeId:a,summaryRunId:s},ctx:e.ctx,emissionState:e.position(),force:!0,messages:[...e.session.history],model:n.model,publish:e.publish,view:()=>e.view().projection.view,requestEnvelopeTokens:e.session.compaction.requestEnvelopeTokens,resolveModel:t.resolveModel,runtimeIdentity:t.runtimeIdentity,session:e.session,prepareTelemetry:t=>e.instrumentation?.prepareAttempt({runId:t,attempt:0}).telemetry,traceContextHeaders:e.instrumentation?.gatewayTraceContextHeaders});if(e.session=i.session,i.failure!==void 0)throw i.failure.error}catch(t){c=`failed`;let n=summaryFailed(e.view().projection.view,{changeId:a,error:t});n.length>0&&await e.publish(n),logError(log,`manual session compaction failed`,t,{sessionId:e.session.sessionId})}let l=c===`failed`?`compaction-failed`:void 0;return await e.apply([fact(`delivery.settled`,{deliveryId:i,outcome:c,reason:l})]),{next:null,session:e.session}}function summaryUsageOf(e){let t=e.filter(e=>e!==void 0);if(t.length!==0)return t.reduce((e,t)=>addTokenUsage(e,usageOf(t)),NO_USAGE)}function summaryFailed(e,t){if(e.changes[t.changeId]?.status!==`running`)return[];let n={code:`COMPACTION_FAILED`,message:toErrorMessage(t.error)},r=openWork(e,{changeId:t.changeId}).runs,{spent:i}=t;return[...r.flatMap(({runId:e})=>runSettledFacts({error:n,outcome:`failed`,runId:e,...i?.runId===e&&{usage:i.usage}})),{data:{changeId:t.changeId,error:n,kind:e.changes[t.changeId]?.kind??`compaction`,outcome:`failed`},type:`context.settled`}]}function replaceSessionHistory(e,t){return contextStorage.getStore()?.delete(HistoryStateKey),{...e,history:t,compaction:withoutPromptMeasurement(e.compaction)}}async function maybeCompact(e){try{return await compactOnce(e)}catch(t){let n=summaryFailed(e.view(),{changeId:e.change.changeId,error:t});throw n.length>0&&await e.publish(n),t}}async function compactOnce(e){let{emissionState:t,publish:n}=e,r=e.messages,i=e.session,a=e.promptMessages??r,o=validateHarnessModelMessages(a),s=e.force===!0||shouldCompact(o,i.compaction,e.requestEnvelopeTokens,i.compaction.requestEnvelopeTokens);if(!s)return{compacted:!1,messages:r,session:i};let c=requireSessionModelReference(i),l=i.agent.compactionModelReference??c,u=l===c?e.model:await e.resolveModel(l),d=resolveModelProfile(u),f=resolveCallProviderOptions({auth:e.auth,profile:d,providerOptions:l.providerOptions,session:i}),p={abortSignal:e.abortSignal,headers:buildGatewayAttributionHeaders(d,e.runtimeIdentity),model:withGatewayTraceContext(u,d,e.traceContextHeaders),providerOptions:f,telemetry:e.telemetry&&{...e.telemetry,functionId:`eve.compaction`}},m,h=[],{change:g}=e,_=g.announced===!0,summarize=async r=>{_||(_=!0,await n([runRequested({changeId:g.changeId},g.summaryRunId),runStarted({attempt:0,modelId:gatewayModelId(u)??`unknown`,runId:g.summaryRunId})]));let a=await runModelCallWithRetries(()=>streamCompactionSummary({...p,telemetry:m??p.telemetry,...r}),{sessionId:i.sessionId,turnId:t.turnId},e.abortSignal);if(h.push(a.usage),a.text.trim().length===0)throw Error(`The compaction model returned an empty summary. Finish reason: ${a.finishReason}.`);return a.text};if(g.announced!==!0){let t=getInputTokenCount(o,i.compaction,e.requestEnvelopeTokens,i.compaction.requestEnvelopeTokens);await n(contextStarted({cause:g.cause,changeId:g.changeId,kind:`compaction`,trigger:e.force===!0||t===null?void 0:{inputTokens:t},turnId:g.turnId}),o)}s&&(m=e.prepareTelemetry?.(g.summaryRunId));let v=validateHarnessModelMessages(r),y=e.requestEnvelopeTokens??0,b=Math.max(0,estimateTokens(o)-estimateTokens(v)),x={...i.compaction,threshold:Math.max(1,i.compaction.threshold-y-b),lastKnownInputTokens:i.compaction.lastKnownInputTokens===void 0?void 0:Math.max(0,i.compaction.lastKnownInputTokens-Math.min(i.compaction.requestEnvelopeTokens??0,y))},S=[...v],C=takeCompactionCaptureFailure(e.ctx),w=C===void 0?void 0:{error:C};try{s&&w===void 0&&(assertFixedPartFits({protectedTokens:b,requestEnvelopeTokens:y,threshold:i.compaction.threshold}),S=await compactMessages([...v],x,summarize,e.force===!0,e.requestEnvelopeTokens===void 0?void 0:Math.max(0,getInputTokenCount(o,i.compaction,y,i.compaction.requestEnvelopeTokens)-y-b)))}catch(e){w={error:e}}let T=s?summaryUsageOf(h):void 0;T!==void 0&&e.betweenTurns===!0&&(i=markUsageReported(i,T));let E=g.summaryRunId;if(w!==void 0)return await n(summaryFailed(e.view(),{changeId:g.changeId,error:w.error,...T!==void 0&&{spent:{runId:E,usage:T}}})),{compacted:!1,failure:w,messages:e.messages,session:i};r=validateHarnessModelMessages(S);{let e=h.length>0?runSettledFacts({finishReason:`stop`,outcome:`completed`,runId:E,usage:T}):_?runSettledFacts({outcome:`abandoned`,runId:E}):[];e.push({data:{changeId:g.changeId,kind:`compaction`,outcome:`completed`},type:`context.settled`}),await n(e,r)}return{compacted:!0,messages:r,session:replaceSessionHistory(i,r)}}function compactedTurnInput(e){return e.findLast(e=>isUserModelMessage(e)&&e.kind===`user`)}async function streamCompactionSummary(e){let t=streamText({...e,onError:()=>{}});for await(let e of t.fullStream)if(e.type===`error`)throw normalizeModelStreamError(e.error);let[n,r,i,a]=await Promise.all([t.text,t.finishReason,t.usage,t.providerMetadata]);return{finishReason:r,text:n,usage:extractTokenUsageDelta({costUsd:extractGatewayCostUsd(a),usage:i})}}export{assertFixedPartFits,compactHistory,compactedTurnInput,maybeCompact,replaceSessionHistory};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{modelCallErrorInfo,reportCompactionFailure,reportModelCallFailure}from"./failure.js";import{buildGatewayAttributionHeaders,withGatewayTraceContext}from"./model.js";import{isEmptyModelResponse,recoverModelCall,rethrowNoOutputAsEmptyResponse}from"./recovery.js";import{modelInstructions,requestMessages,withTrailingUserNote}from"./request.js";import{answerSkippedToolCalls,extractToolResultCallIds,withCallResults}from"./response.js";import{ALLOW_RETRY,STOP_RETRY,runModelCallWithRetries}from"./retry.js";import{withUniqueCallIds}from"./unique-call-ids.js";import{prepareModelTools}from"./tools.js";import{extractGatewayCostUsd,extractTokenUsageDelta}from"./usage.js";import{ToolLoopAgent,isStepCount}from"ai";import{createLogger,logError}from"#internal/logging.js";import{AuthKey,HistoryStateKey}from"#context/keys.js";import{REPLY_TOOL_NAME}from"#protocol/reply-tool.js";import{activeTurnId}from"#harness/session-machine/view.js";import{hydrateSandboxAttachments,moveToolResultFilesToUserMessages}from"#harness/attachment-staging.js";import{workingTaskIds}from"#execution/tasks/model-step.js";import{historyCallNames,toEntryStep,toEntryStream}from"#harness/execute-call.js";import{discardAttempt}from"#harness/session-machine/transitions.js";import{summarizeKnownError}from"#harness/semantic-errors/index.js";import{fact,usageOf}from"#harness/facts.js";import{nextChangeId,nextRunId}from"#protocol/session-projection.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{compactedTurnInput,maybeCompact}from"#harness/compaction/step.js";import{CompactionOverLimitError}from"#harness/compaction/over-limit-error.js";import{estimateTokens}from"#harness/token-estimate.js";import{withoutPromptMeasurement}from"#harness/compaction/engine.js";import{requireSessionModelReference}from"#harness/types.js";import{ContentFilteredModelResponseError,EmptyModelResponseError,ModelStreamStalledError}from"#harness/model-call/errors.js";import{resolveModelProfile}from"#harness/model-profile.js";import{interruptStreamOnFailure}from"#harness/interruptible-stream.js";import{NO_INLINE_CALLS,executeInlineCalls}from"#harness/call-executor.js";import{emitStreamContent}from"#harness/emission.js";import{estimateRequestEnvelope}from"#harness/request-envelope.js";import{compactPrompt,projectPrompt,withClientContext}from"#harness/step/prompt.js";import{buildStepHooks,emitStepActions,readGatewayGenerationId}from"#harness/step-hooks.js";const environment=process.env.NODE_ENV??`unknown`,log=createLogger(`harness.tool-loop`),MODEL_OUTPUT_TIMEOUT_MS=6e5;var ModelCaller=class{profile;attributionHeaders;projectedMessages;turnMessages;request;modelMessages=[];requestEnvelopeTokens=0;interruptedUsage;compactionFailure;attemptIndex=0;started;acceptedOutput=!1;step;prompt;input;constructor(e,t,n){this.step=e,this.prompt=t,this.input=n,this.profile=resolveModelProfile(n.model,requireSessionModelReference(e.session).promptCache),this.attributionHeaders=buildGatewayAttributionHeaders(this.profile,e.config.runtimeIdentity),this.projectedMessages=n.projectedMessages,this.turnMessages=n.turnMessages,this.request=this.buildRequest()}async call(){let e={},t={policies:[()=>this.compactionFailure===void 0?ALLOW_RETRY:STOP_RETRY],onRetry:e=>this.prepareRetry(e),sessionId:this.step.session.sessionId,turnId:this.step.position().turnId};for(;;)try{return await runModelCallWithRetries(()=>this.attempt(e),t,this.input.generation.signal)}catch(n){if(this.compactionFailure!==void 0)throw this.compactionFailure.error;throwIfTurnAborted(this.step.config.abortSignal),this.input.generation.check();let r=recoverModelCall(n,e,t);if(r===void 0)throw n;await this.prepareRetry(n),e=r}}async prepareRetry(e){let{step:t}=this,n=t.position().runId,r=this.started;if(this.started=void 0,n!==void 0){if(this.acceptedOutput){await t.apply(discardAttempt(t.view(),{ending:`retried`,runId:n})),this.acceptedOutput=!1,await this.input.newRun();return}r!==void 0&&await t.apply([fact(`model.retried`,{attempt:r,error:modelCallErrorInfo(e),runId:n})])}}async failIfCompactionFailed(){if(this.compactionFailure===void 0)return;let{error:e}=this.compactionFailure;return e instanceof CompactionOverLimitError?reportCompactionFailure(this.step,e):reportModelCallFailure(this.step,e)}async steered(){let{step:e}=this;throwIfTurnAborted(e.config.abortSignal),this.input.generation.end(),e.ctx?.set(HistoryStateKey,this.request.historyState);let t=e.position().runId;return t!==void 0&&await e.apply(discardAttempt(e.view(),{ending:`steered`,runId:t,usage:this.interruptedUsage===void 0?void 0:usageOf(this.interruptedUsage)})),{next:e.runStep,session:{...e.session,history:[...this.request.history]},steered:!0}}clearInterruptedUsage(){this.interruptedUsage=void 0}buildRequest(){return requestMessages(this.step,{catalog:this.input.catalog,messages:this.prompt.messages,pendingApprovalsNote:this.input.pendingApprovalsNote,projectedMessages:this.projectedMessages,turnMessages:this.turnMessages})}instructions(e){return modelInstructions({anthropicCache:this.profile.anthropicCache,extraSystemNote:e,session:this.step.session,systemMessages:this.request.systemMessages})}async prepare(e){let t=await prepareModelTools(this.step,{catalog:this.input.catalog,disabledProviderTools:e.disabledProviderTools,profile:this.profile});return this.request=this.buildRequest(),this.requestEnvelopeTokens=await estimateRequestEnvelope({history:this.projectedMessages,instructions:this.instructions(e.extraSystemNote),messages:withTrailingUserNote(this.request.nonSystemMessages,e.trailingUserNote),tools:t}),t}async compact(e,t){let{step:n,prompt:r}=this,{config:i}=n,a;try{let{projection:e}=n.view();if(a=await maybeCompact({abortSignal:i.abortSignal,auth:n.ctx?.get(AuthKey)??null,change:{changeId:nextChangeId(e),summaryRunId:nextRunId(e),turnId:n.position().turnId},ctx:n.ctx,emissionState:n.position(),messages:[...r.messages],model:this.input.model,promptMessages:withClientContext(r),publish:n.publish,view:()=>n.view().projection.view,requestEnvelopeTokens:this.requestEnvelopeTokens,resolveModel:i.resolveModel,runtimeIdentity:i.runtimeIdentity,session:n.session,prepareTelemetry:e=>n.instrumentation?.prepareAttempt({runId:e,attempt:0,turnId:activeTurnId(n.position())}).telemetry,traceContextHeaders:n.instrumentation?.gatewayTraceContextHeaders}),n.session=a.session,a.failure!==void 0)throw a.failure.error}catch(e){throw this.compactionFailure={error:e},e}if(!a.compacted)return t;compactPrompt(n,r,a.messages);let o=compactedTurnInput(r.messages);return this.turnMessages=o===void 0?this.input.turnMessages:[...this.input.turnMessages,o],n.session={...n.session,compaction:withoutPromptMeasurement(n.session.compaction)},this.projectedMessages=projectPrompt(r),await this.prepare(e)}async attempt(e){let{step:t}=this,{generation:n,model:r}=this.input,i=await this.compact(e,await this.prepare(e)),a=this.attemptIndex++;await this.input.startRun(a),this.started=a,this.requestEnvelopeTokens=Math.max(0,this.requestEnvelopeTokens-(estimateTokens(this.request.history)-estimateTokens(this.prompt.messages))),n.begin(),this.modelMessages=await hydrateSandboxAttachments(this.request.nonSystemMessages),this.profile.filesOutsideToolResults&&(this.modelMessages=moveToolResultFilesToUserMessages(this.modelMessages));let o=this.instructions(e.extraSystemNote),s=t.instrumentation?.resolveRuntimeContext({attempt:a,emissionState:t.position(),environment,modelInput:{instructions:o,messages:this.modelMessages},session:t.session})??{};e.retryReason&&(s[`eve.retry.reason`]=e.retryReason);let c=withTrailingUserNote(this.modelMessages,e.trailingUserNote),l=t.position(),u=t.instrumentation?.prepareAttempt({isFrameworkTool:e=>t.frameworkToolNames.has(e),runId:l.runId,attempt:a,runtimeContext:s,stepIndex:l.stepIndex,turnId:activeTurnId(l)}),d=buildStepHooks({auth:t.ctx?.get(AuthKey)??null,profile:this.profile,session:t.session}),f={headers:this.attributionHeaders,instructions:o,model:withUniqueCallIds(withGatewayTraceContext(r,this.profile,this.step.instrumentation?.gatewayTraceContextHeaders),[...Object.keys(t.view().projection.view.calls),...historyCallNames(c).keys()]),onLanguageModelCallEnd:e=>{n.interrupted||(this.interruptedUsage=extractTokenUsageDelta({costUsd:extractGatewayCostUsd(e.providerMetadata),usage:e.usage}))},onError(e){n.interrupted||summarizeKnownError(e.error)?.tags.includes(`config`)!==!0&&logError(log,`tool-loop stream error`,e.error)},onStepEnd:d.onStepEnd,onStepStart:d.onStepStart,prepareStep:d.prepareStep,reasoning:t.session.agent.modelReference?.reasoning??t.session.agent.reasoning,runtimeContext:s,stopWhen:isStepCount(1),telemetry:u?.telemetry,timeout:{chunkMs:MODEL_OUTPUT_TIMEOUT_MS,firstChunkMs:MODEL_OUTPUT_TIMEOUT_MS},tools:i},p=new ToolLoopAgent(f);try{return await this.stream(p,c,d.stepResult,u?.telemetry)}catch(e){if(n.check(),isAbortError(e)&&!n.signal.aborted)throw new ModelStreamStalledError({cause:e});return rethrowNoOutputAsEmptyResponse(e)}}async stream(e,t,n,r){let{step:i}=this,{catalog:a,generation:o}=this.input,s=new Set([REPLY_TOOL_NAME]),c=await e.stream({abortSignal:o.signal,messages:t}),{invalidInputToolCallIds:l,trailingInlineToolResultParts:u}=await emitStreamContent(async(e,t)=>{this.acceptedOutput=!0,await i.publish(e,t)},i.position(),toEntryStream(interruptStreamOnFailure(c.fullStream,o.signal),a.resolve),{excludedActionToolNames:s,held:i.finalReplyOnly&&workingTaskIds(i.session).length>0,finalReplyOnly:i.finalReplyOnly,tools:a,interruptSignal:o.signal});throwIfTurnAborted(i.config.abortSignal),o.check();let[d,f]=toEntryStep(...await Promise.all([n,c.responseMessages]),a.resolve);assertUsableResponse(d,f,{allowEmptyStop:!i.hasDelegatedCaller,hasInlineResults:u.length>0});let p=await this.runInlineCalls(d,t,{excludedCallIds:l,telemetry:r}),m=answerSkippedToolCalls(d,a,l);return await emitStepActions(i.publish,i.position(),d,m),withCallResults({answers:[...u,...m],calls:p,invalidInputToolCallIds:l,responseMessages:f,stepResult:d})}async runInlineCalls(e,t,n){let{finishReason:r}=e;if(r!==`stop`&&r!==`tool-calls`)return NO_INLINE_CALLS;let{step:i}=this,a=await executeInlineCalls({abortSignal:this.input.generation.signal,approvalMemory:this.input.approvalMemory,beforeExecute:()=>this.input.generation.protectToolExecution(),excludedCallIds:n.excludedCallIds??new Set,messages:t,modelCallId:e.callId,publish:i.publish,telemetry:n.telemetry,toolCalls:e.toolCalls??[],tools:this.input.catalog});return throwIfTurnAborted(i.config.abortSignal),a}};function assertUsableResponse(e,t,n){if(e.finishReason===`content-filter`)throw new ContentFilteredModelResponseError(readGatewayGenerationId(e.providerMetadata));if(!(n.allowEmptyStop&&e.finishReason===`stop`)&&isEmptyModelResponse(e)&&extractToolResultCallIds(t).size===0&&!n.hasInlineResults)throw new EmptyModelResponseError}function isAbortError(e){return e instanceof Error&&(e.name===`AbortError`||e.name===`TimeoutError`)}export{ModelCaller};
|
|
1
|
+
import{modelCallErrorInfo,reportCompactionFailure,reportModelCallFailure}from"./failure.js";import{buildGatewayAttributionHeaders,withGatewayTraceContext}from"./model.js";import{isEmptyModelResponse,recoverModelCall,rethrowNoOutputAsEmptyResponse}from"./recovery.js";import{modelInstructions,requestMessages,withTrailingUserNote}from"./request.js";import{answerSkippedToolCalls,extractToolResultCallIds,withCallResults}from"./response.js";import{ALLOW_RETRY,STOP_RETRY,runModelCallWithRetries}from"./retry.js";import{withUniqueCallIds}from"./unique-call-ids.js";import{prepareModelTools}from"./tools.js";import{extractGatewayCostUsd,extractTokenUsageDelta}from"./usage.js";import{ToolLoopAgent,isStepCount}from"ai";import{createLogger,logError}from"#internal/logging.js";import{AuthKey,HistoryStateKey}from"#context/keys.js";import{REPLY_TOOL_NAME}from"#protocol/reply-tool.js";import{activeTurnId}from"#harness/session-machine/view.js";import{hydrateSandboxAttachments,moveToolResultFilesToUserMessages}from"#harness/attachment-staging.js";import{workingTaskIds}from"#execution/tasks/model-step.js";import{historyCallNames,toEntryStep,toEntryStream}from"#harness/execute-call.js";import{discardAttempt}from"#harness/session-machine/transitions.js";import{summarizeKnownError}from"#harness/semantic-errors/index.js";import{nextChangeId,nextRunId}from"#protocol/session-projection.js";import{fact,usageOf}from"#harness/facts.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{compactedTurnInput,maybeCompact}from"#harness/compaction/step.js";import{CompactionOverLimitError}from"#harness/compaction/over-limit-error.js";import{estimateTokens}from"#harness/token-estimate.js";import{withoutPromptMeasurement}from"#harness/compaction/engine.js";import{requireSessionModelReference}from"#harness/types.js";import{ContentFilteredModelResponseError,EmptyModelResponseError,ModelStreamStalledError}from"#harness/model-call/errors.js";import{resolveModelProfile}from"#harness/model-profile.js";import{interruptStreamOnFailure}from"#harness/interruptible-stream.js";import{NO_INLINE_CALLS,executeInlineCalls}from"#harness/call-executor.js";import{emitStreamContent}from"#harness/emission.js";import{estimateRequestEnvelope}from"#harness/request-envelope.js";import{compactPrompt,projectPrompt,withClientContext}from"#harness/step/prompt.js";import{buildStepHooks,emitStepActions,readGatewayGenerationId}from"#harness/step-hooks.js";const environment=process.env.NODE_ENV??`unknown`,log=createLogger(`harness.tool-loop`),MODEL_OUTPUT_TIMEOUT_MS=6e5;var ModelCaller=class{profile;attributionHeaders;projectedMessages;turnMessages;request;modelMessages=[];requestEnvelopeTokens=0;interruptedUsage;compactionFailure;attemptIndex=0;started;acceptedOutput=!1;step;prompt;input;constructor(e,t,n){this.step=e,this.prompt=t,this.input=n,this.profile=resolveModelProfile(n.model,requireSessionModelReference(e.session).promptCache),this.attributionHeaders=buildGatewayAttributionHeaders(this.profile,e.config.runtimeIdentity),this.projectedMessages=n.projectedMessages,this.turnMessages=n.turnMessages,this.request=this.buildRequest()}async call(){let e={},t={policies:[()=>this.compactionFailure===void 0?ALLOW_RETRY:STOP_RETRY],onRetry:e=>this.prepareRetry(e),sessionId:this.step.session.sessionId,turnId:this.step.position().turnId};for(;;)try{return await runModelCallWithRetries(()=>this.attempt(e),t,this.input.generation.signal)}catch(n){if(this.compactionFailure!==void 0)throw this.compactionFailure.error;throwIfTurnAborted(this.step.config.abortSignal),this.input.generation.check();let r=recoverModelCall(n,e,t);if(r===void 0)throw n;await this.prepareRetry(n),e=r}}async prepareRetry(e){let{step:t}=this,n=t.position().runId,r=this.started;if(this.started=void 0,n!==void 0){if(this.acceptedOutput){await t.apply(discardAttempt(t.view(),{ending:`retried`,runId:n})),this.acceptedOutput=!1,await this.input.newRun();return}r!==void 0&&await t.apply([fact(`model.retried`,{attempt:r,error:modelCallErrorInfo(e),runId:n})])}}async failIfCompactionFailed(){if(this.compactionFailure===void 0)return;let{error:e}=this.compactionFailure;return e instanceof CompactionOverLimitError?reportCompactionFailure(this.step,e):reportModelCallFailure(this.step,e)}async steered(){let{step:e}=this;throwIfTurnAborted(e.config.abortSignal),this.input.generation.end(),e.ctx?.set(HistoryStateKey,this.request.historyState);let t=e.position().runId;return t!==void 0&&await e.apply(discardAttempt(e.view(),{ending:`steered`,runId:t,usage:this.interruptedUsage===void 0?void 0:usageOf(this.interruptedUsage)})),{next:e.runStep,session:{...e.session,history:[...this.request.history]},steered:!0}}clearInterruptedUsage(){this.interruptedUsage=void 0}buildRequest(){return requestMessages(this.step,{catalog:this.input.catalog,messages:this.prompt.messages,pendingApprovalsNote:this.input.pendingApprovalsNote,projectedMessages:this.projectedMessages,turnMessages:this.turnMessages})}instructions(e){return modelInstructions({anthropicCache:this.profile.anthropicCache,extraSystemNote:e,session:this.step.session,systemMessages:this.request.systemMessages})}async prepare(e){let t=await prepareModelTools(this.step,{catalog:this.input.catalog,disabledProviderTools:e.disabledProviderTools,profile:this.profile});return this.request=this.buildRequest(),this.requestEnvelopeTokens=await estimateRequestEnvelope({history:this.projectedMessages,instructions:this.instructions(e.extraSystemNote),messages:withTrailingUserNote(this.request.nonSystemMessages,e.trailingUserNote),tools:t}),t}async compact(e,t){let{step:n,prompt:r}=this,{config:i}=n,a;try{let{projection:e}=n.view();if(a=await maybeCompact({abortSignal:i.abortSignal,auth:n.ctx?.get(AuthKey)??null,change:{changeId:nextChangeId(e),summaryRunId:nextRunId(e),turnId:n.position().turnId},ctx:n.ctx,emissionState:n.position(),messages:[...r.messages],model:this.input.model,promptMessages:withClientContext(r),publish:n.publish,view:()=>n.view().projection.view,requestEnvelopeTokens:this.requestEnvelopeTokens,resolveModel:i.resolveModel,runtimeIdentity:i.runtimeIdentity,session:n.session,prepareTelemetry:e=>n.instrumentation?.prepareAttempt({runId:e,attempt:0,turnId:activeTurnId(n.position())}).telemetry,traceContextHeaders:n.instrumentation?.gatewayTraceContextHeaders}),n.session=a.session,a.failure!==void 0)throw a.failure.error}catch(e){throw this.compactionFailure={error:e},e}if(!a.compacted)return t;compactPrompt(n,r,a.messages);let o=compactedTurnInput(r.messages);return this.turnMessages=o===void 0?this.input.turnMessages:[...this.input.turnMessages,o],n.session={...n.session,compaction:withoutPromptMeasurement(n.session.compaction)},this.projectedMessages=projectPrompt(r),await this.prepare(e)}async attempt(e){let{step:t}=this,{generation:n,model:r}=this.input,i=await this.compact(e,await this.prepare(e)),a=this.attemptIndex++;await this.input.startRun(a),this.started=a,this.requestEnvelopeTokens=Math.max(0,this.requestEnvelopeTokens-(estimateTokens(this.request.history)-estimateTokens(this.prompt.messages))),n.begin(),this.modelMessages=await hydrateSandboxAttachments(this.request.nonSystemMessages),this.profile.filesOutsideToolResults&&(this.modelMessages=moveToolResultFilesToUserMessages(this.modelMessages));let o=this.instructions(e.extraSystemNote),s=t.instrumentation?.resolveRuntimeContext({attempt:a,emissionState:t.position(),environment,modelInput:{instructions:o,messages:this.modelMessages},session:t.session})??{};e.retryReason&&(s[`eve.retry.reason`]=e.retryReason);let c=withTrailingUserNote(this.modelMessages,e.trailingUserNote),l=t.position(),u=t.instrumentation?.prepareAttempt({isFrameworkTool:e=>t.frameworkToolNames.has(e),runId:l.runId,attempt:a,runtimeContext:s,stepIndex:l.stepIndex,turnId:activeTurnId(l)}),d=buildStepHooks({auth:t.ctx?.get(AuthKey)??null,profile:this.profile,session:t.session}),f={headers:this.attributionHeaders,instructions:o,model:withUniqueCallIds(withGatewayTraceContext(r,this.profile,this.step.instrumentation?.gatewayTraceContextHeaders),[...Object.keys(t.view().projection.view.calls),...historyCallNames(c).keys()]),onLanguageModelCallEnd:e=>{n.interrupted||(this.interruptedUsage=extractTokenUsageDelta({costUsd:extractGatewayCostUsd(e.providerMetadata),usage:e.usage}))},onError(e){n.interrupted||summarizeKnownError(e.error)?.tags.includes(`config`)!==!0&&logError(log,`tool-loop stream error`,e.error)},onStepEnd:d.onStepEnd,onStepStart:d.onStepStart,prepareStep:d.prepareStep,reasoning:t.session.agent.modelReference?.reasoning??t.session.agent.reasoning,runtimeContext:s,stopWhen:isStepCount(1),telemetry:u?.telemetry,timeout:{chunkMs:MODEL_OUTPUT_TIMEOUT_MS,firstChunkMs:MODEL_OUTPUT_TIMEOUT_MS},tools:i},p=new ToolLoopAgent(f);try{return await this.stream(p,c,d.stepResult,u?.telemetry)}catch(e){if(n.check(),isAbortError(e)&&!n.signal.aborted)throw new ModelStreamStalledError({cause:e});return rethrowNoOutputAsEmptyResponse(e)}}async stream(e,t,n,r){let{step:i}=this,{catalog:a,generation:o}=this.input,s=new Set([REPLY_TOOL_NAME]),c=await e.stream({abortSignal:o.signal,messages:t}),{invalidInputToolCallIds:l,trailingInlineToolResultParts:u}=await emitStreamContent(async(e,t)=>{this.acceptedOutput=!0,await i.publish(e,t)},i.position(),toEntryStream(interruptStreamOnFailure(c.fullStream,o.signal),a.resolve),{excludedActionToolNames:s,held:i.finalReplyOnly&&workingTaskIds(i.session).length>0,finalReplyOnly:i.finalReplyOnly,tools:a,interruptSignal:o.signal});throwIfTurnAborted(i.config.abortSignal),o.check();let[d,f]=toEntryStep(...await Promise.all([n,c.responseMessages]),a.resolve);assertUsableResponse(d,f,{allowEmptyStop:!i.hasDelegatedCaller,hasInlineResults:u.length>0});let p=await this.runInlineCalls(d,t,{excludedCallIds:l,telemetry:r}),m=answerSkippedToolCalls(d,a,l);return await emitStepActions(i.publish,i.position(),d,m),withCallResults({answers:[...u,...m],calls:p,invalidInputToolCallIds:l,responseMessages:f,stepResult:d})}async runInlineCalls(e,t,n){let{finishReason:r}=e;if(r!==`stop`&&r!==`tool-calls`)return NO_INLINE_CALLS;let{step:i}=this,a=await executeInlineCalls({abortSignal:this.input.generation.signal,approvalMemory:this.input.approvalMemory,beforeExecute:()=>this.input.generation.protectToolExecution(),excludedCallIds:n.excludedCallIds??new Set,messages:t,modelCallId:e.callId,publish:i.publish,telemetry:n.telemetry,toolCalls:e.toolCalls??[],tools:this.input.catalog});return throwIfTurnAborted(i.config.abortSignal),a}};function assertUsableResponse(e,t,n){if(e.finishReason===`content-filter`)throw new ContentFilteredModelResponseError(readGatewayGenerationId(e.providerMetadata));if(!(n.allowEmptyStop&&e.finishReason===`stop`)&&isEmptyModelResponse(e)&&extractToolResultCallIds(t).size===0&&!n.hasInlineResults)throw new EmptyModelResponseError}function isAbortError(e){return e instanceof Error&&(e.name===`AbortError`||e.name===`TimeoutError`)}export{ModelCaller};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{reportModelCallFailure}from"./failure.js";import{resolveEffectiveRuntimeModel}from"./model.js";import{endsTurnTools,frameworkToolNames}from"./tools.js";import{recordModelUsage}from"./usage.js";import{ModelCaller}from"./call.js";import{HistoryStateKey}from"#context/keys.js";import{activeTurnId}from"#harness/session-machine/view.js";import{enforceBudget,humanInputContext}from"#harness/hitl/index.js";import{validateHarnessModelMessages}from"#harness/messages.js";import{
|
|
1
|
+
import{reportModelCallFailure}from"./failure.js";import{resolveEffectiveRuntimeModel}from"./model.js";import{endsTurnTools,frameworkToolNames}from"./tools.js";import{recordModelUsage}from"./usage.js";import{ModelCaller}from"./call.js";import{HistoryStateKey}from"#context/keys.js";import{activeTurnId}from"#harness/session-machine/view.js";import{enforceBudget,humanInputContext}from"#harness/hitl/index.js";import{validateHarnessModelMessages}from"#harness/messages.js";import{nextRunId}from"#protocol/session-projection.js";import{runRequested,runStarted}from"#harness/facts.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{requireSessionModelReference}from"#harness/types.js";import{buildStepCatalog,recordOfferedCatalogTools}from"#execution/catalog/step-catalog.js";import{buildPrompt,previewPrompt,projectPrompt,withClientContext}from"#harness/step/prompt.js";import{handleStepResult}from"#harness/step/after-model.js";import{failBoundaryEvent,failModelSelection,prepareModelCall}from"#harness/step/context.js";async function runModelStep(e,t){let{generation:n}=t,r=await prepareModelCall(e,previewPrompt(e,t.turn));if(r!==void 0)return r;let i=await buildPrompt(e,t.turn),a=await enforceBudget(e,i.messages);if(a!==void 0)return a;let o=await requestRun(e,i);if(`failed`in o)return o.failed;let s=projectPrompt(i),c=!e.hasDelegatedCaller&&e.session.outputSchema===void 0,l=buildStepCatalog({agentTools:e.config.tools,ctx:e.ctx,endsTurn:c,session:e.session});recordOfferedCatalogTools(e.ctx,l),e.frameworkToolNames=frameworkToolNames(l);let{approvalMemory:u,pendingApprovalsNote:d}=humanInputContext(e),f=new ModelCaller(e,i,{approvalMemory:u,catalog:l,generation:n,model:o.model,newRun:async()=>{if(`failed`in await requestRun(e,i))throw Error(`The model run's replacement found no model.`)},startRun:async t=>await startRun(e,t),pendingApprovalsNote:d,projectedMessages:s,turnMessages:t.turn.messages}),p;try{p=await f.call()}catch(t){throwIfTurnAborted(e.config.abortSignal);let r=await f.failIfCompactionFailed();return r===void 0?n.interrupted?f.steered():reportModelCallFailure(e,t):r}await recordModelUsage(e,{model:o.model}),f.clearInterruptedUsage();let m;try{n.check(),m=await handleStepResult(e,{catalog:l,durableModelPromptMessageCount:i.clientContext===void 0||i.clientContext.messages.length===0?f.modelMessages.length:void 0,endsTurnTools:endsTurnTools(l,c),promptMessages:f.request.history,requestEnvelopeTokens:f.requestEnvelopeTokens,result:p})}catch(t){if(throwIfTurnAborted(e.config.abortSignal),n.interrupted)return f.steered();throw t}return e.ctx?.set(HistoryStateKey,f.request.historyState),m}async function requestRun(e,t){let{config:n,ctx:r}=e;try{await e.apply([runRequested({turnId:activeTurnId(e.position())},nextRunId(e.view().projection))],validateHarnessModelMessages(withClientContext(t)))}catch(t){return{failed:await failBoundaryEvent(e,t)}}try{let t=await resolveEffectiveRuntimeModel({config:n,ctx:r,session:e.session});return e.session=t.session,{model:t.model}}catch(t){return{failed:await failModelSelection(e,t)}}}async function startRun(e,t){let n=e.position().runId;if(n===void 0)return;let r=requireSessionModelReference(e.session).id;await e.apply([runStarted({attempt:t,modelId:r,runId:n})])}export{runModelStep};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{activeTurnId,answeredCallIds,turnPosition}from"./view.js";import{isComplete,stepCallIds,suspend,withResult,withoutResults}from"./suspended-steps.js";import{activeTurn,interactionOwner}from"#protocol/session-projection/selectors.js";import{isOpen}from"#protocol/session-projection/tree.js";import{callSettledFrom}from"#harness/call-facts.js";import{contextStarted,controlAdmitted,defined,delegatedUsageFact,deliveryApplied,errorInfoOf,fact,runSettledFacts,sessionEndedFacts,turnSettled}from"#harness/facts.js";import{activeTurnIdOf,nextChangeId,openRunOf}from"#protocol/session-projection.js";import{closeUnder}from"#harness/session-machine/cascade.js";import{interruptedCallResult}from"#harness/interrupted-attempt.js";import{interactionSettled,responseAdmitted,responseSettled,responseSubmitted,signInInteractionId}from"#harness/interaction-facts.js";import{signInAttemptKey}from"#harness/hitl/sign-ins.js";const unchanged=(e,t)=>({events:t,turn:e.turn});function followedTurn(e){let t=e.view.selection;return t===null?null:t?.turnId??e.view.session.latestTurnId??null}function waitingDeliveries(e,t){return t.filter(({deliveryId:t})=>e.view?.deliveries[t]?.status===`admitted`)}function consumed(e,t){return fact(`delivery.consumed`,{deliveryId:e.deliveryId,history:(e.history?.length??0)>0?e.history:void 0,parts:e.parts,turnId:t})}function receive(e,t){let{projection:n}=e,r=turnPosition(n),i=activeTurnId(r),a=waitingDeliveries(n,t.deliveries??[]),o=a[0],s=o===void 0?t.cause??{policy:`system`}:{deliveryId:o.deliveryId},{parent:c,predecessor:l,runtime:u,trace:d}=t,f=[];return r.sessionStarted||f.push(fact(`session.started`,{parent:c,predecessor:l,runtime:u,trace:d})),r.turnId===``&&f.push(fact(`turn.started`,{cause:s,follows:followedTurn(n),trace:d,turnId:i})),f.push(...a.map(e=>consumed(e,i))),unchanged(e,f)}function join(e,t){let{projection:n}=e,r=waitingDeliveries(n,t.deliveries),i=activeTurnIdOf(n);return unchanged(e,i===void 0?r.map(({deliveryId:e})=>deliveryApplied(e)):r.map(e=>consumed(e,i)))}function fail(e,t){let n=e.turn.suspended.filter(e=>(e.approved?.length??0)>0),r=errorInfoOf(t),i=activeTurnIdOf(e.projection),a=i===void 0?void 0:openRunOf(e.projection,i),o=[...a===void 0?[]:runSettledFacts({runId:a,outcome:`failed`,error:r}),...t.terminal===void 0?turnSettled(e.projection,{error:r,outcome:`failed`}):sessionEndedFacts(e.projection,{cause:i===void 0?void 0:{turnId:i},error:r,outcome:`failed`})];return{...commitSteps(e.turn,n,cancelledTranscript),events:o}}function settle(e,t){let n=[],r=[...e.turn.suspended];for(let{part:i,result:a,usage:o}of t.results){let t=r.findIndex(e=>stepCallIds(e).has(i.toolCallId)),s=r[t];if(s===void 0)continue;r[t]=withoutApproved({...s,messages:withResult(s.messages,i)},new Set([i.toolCallId]));let c=a===void 0?void 0:e.projection.view.calls[a.callId];a!==void 0&&c!==void 0&&c.taskId===void 0&&c.status!==`settled`&&(n.push(callSettledFrom(a)),o!==void 0&&n.push(delegatedUsageFact(a.callId,o)))}let i=r.filter(isComplete);return{...commitSteps({...e.turn,suspended:r},i),events:n}}function discardAttempt(e,t){let n=e.projection.view,r={family:`run`,id:t.runId},i=t.ending===`steered`?closeUnder(n,r,`steered`):[];if(!isOpen(n,r))return unchanged(e,i);let a=t.ending===`retried`?{outcome:`abandoned`,runId:t.runId,usage:t.usage}:{finishReason:`other`,outcome:`completed`,runId:t.runId,usage:t.usage};return unchanged(e,[...i,...runSettledFacts(a)])}function suspendStep(e,t){return{events:[],turn:suspend(e.turn,{...t,requests:[]})}}function withoutApproved(e,t){if(e.approved===void 0)return e;let n=e.approved.filter(e=>!t.has(e.call.callId));if(n.length===e.approved.length)return e;let{approved:r,...i}=e;return n.length===0?i:{...i,approved:n}}function runnableCalls(e,t){let n=new Set(e.signIns.map(signInAttemptKey));return(t.approved??[]).filter(e=>(e.signIns??[]).every(e=>!n.has(signInAttemptKey(e))))}function startTask(e,t,n){let r=[];return(n?.has(t.taskId)??e.projection.view.tasks[t.taskId]!==void 0)||(n?.add(t.taskId),r.push({type:`task.started`,data:{taskId:t.taskId,kind:t.kind,name:t.name,startedBy:{callId:t.callId}}})),r.push({type:`call.started`,data:defined({callId:t.callId,taskId:t.taskId,clearedBy:t.clearedBy})}),unchanged(e,r)}function settleTask(e,t){let{outcome:n}=t,r=n.status===`completed`?n.output:void 0,i=t.calls[0]?.callId,a=t.calls.map(({callId:e},t)=>fact(`call.settled`,{callId:e,error:n.status===`failed`?{code:`TASK_FAILED`,message:n.error}:void 0,outcome:n.status===`cancelled`?`interrupted`:n.status,output:t===0?r:void 0,outputOf:t>0&&r!==void 0&&i!==void 0?{callId:i}:void 0,reason:n.status===`cancelled`?n.reason??`task-cancelled`:void 0}));return unchanged(e,a)}function endTask(e,t){let n=e.projection.view.tasks[t.taskId];if(n===void 0||n.status===`ended`)return unchanged(e,[]);let{outcome:r}=t;return unchanged(e,[fact(`task.ended`,{error:r.status===`failed`?{code:`TASK_FAILED`,message:r.error}:void 0,outcome:r.status,reason:r.status===`cancelled`?r.reason??`task-ended`:void 0,taskId:t.taskId})])}function finishRun(e,t){let n=new Set(t.requestIds),r=e.projection.view,i=Object.values(r.interactions).filter(e=>e.status===`open`&&(n.has(e.interactionId)||t.taskId!==void 0&&interactionOwner(r,e).taskId===t.taskId));return unchanged(e,i.map(e=>withdrawInteraction(e.interactionId,`asker-ended`)))}function withdrawInteraction(e,t,n=`withdrawn`){return interactionSettled(e,n,{reason:t})}function relay(e,t){let{payload:n}=t,r=e.projection.view,i=n.route===void 0?void 0:{...n.route,...t.workflowAsk!==void 0&&{workflowAsk:t.workflowAsk},...t.runId!==void 0&&{runId:t.runId}},a=[],o={};for(let e of n.events){let t=e.data.interactionId,s=r.interactions[t];if(e.type===`interaction.opened`||s?.origin!==void 0&&`callId`in s.subject&&s.subject.callId===n.callId)switch(e.type){case`interaction.opened`:if(s!==void 0)break;a.push({data:{...e.data,origin:e.data.origin??{interactionId:t,sessionId:n.childSessionId},subject:{callId:n.callId}},type:`interaction.opened`}),i!==void 0&&e.data.request.kind!==`sign-in`&&(o[t]=i);break;case`interaction.settled`:if(s?.status!==`open`)break;a.push(...mirrorSettled(r,e.data));break;case`response.admitted`:{let t=s===void 0?void 0:forwardedAnswer(r,e.data);t!==void 0&&r.responses[t]?.status===`submitted`&&a.push(responseAdmitted(t));break}case`response.settled`:{let t=s===void 0?void 0:forwardedAnswer(r,e.data);t!==void 0&&e.data.outcome!==`applied`&&a.push(responseSettled(t,e.data.outcome,e.data.reason));break}}}return Object.keys(o).length>0?{...unchanged(e,a),relays:o}:unchanged(e,a)}function mirrorSettled(e,t){let n=Object.values(e.responses).filter(e=>e.interactionId===t.interactionId&&e.status!==`settled`).sort((e,t)=>e.introducedAt-t.introducedAt),r=t.outcome===`accepted`||t.outcome===`declined`||t.outcome===`invalid`?n.at(-1):void 0,i=r===void 0?[]:[responseSettled(r.responseId,`applied`,t.reason)],a=r===void 0?t.cause:{responseId:r.responseId};return i.push(fact(`interaction.settled`,{...t,cause:a})),i}function forwardedAnswer(e,t){let n=Object.values(e.responses).filter(e=>e.interactionId===t.interactionId&&e.status!==`settled`).sort((e,t)=>e.introducedAt-t.introducedAt);return(n.find(e=>t.deliveryId!==void 0&&e.deliveryId===t.deliveryId)??n.at(-1))?.responseId}function routeAnswer(e,t){let n=e.projection.view,r=[],i=new Set;for(let e of t.deliveries){if(n.deliveries[e.deliveryId]!==void 0||i.has(e.deliveryId))continue;i.add(e.deliveryId);let{deliveryId:t,principal:a,source:o}=e;r.push(fact(`delivery.admitted`,{deliveryId:t,principal:a,source:o})),e.consumed!==void 0&&r.push(consumed({deliveryId:t,parts:e.consumed.parts},e.consumed.turnId))}let known=e=>i.has(e)||n.deliveries[e]!==void 0,a=new Map;for(let e of t.forwarded)n.responses[e.responseId]===void 0&&n.interactions[e.interactionId]?.status===`open`&&known(e.deliveryId)&&(a.set(e.responseId,e),r.push(responseSubmitted(e)));for(let{answer:e,outcome:i}of t.decided){let t=n.interactions[e.interactionId];if(t?.status!==`open`)continue;let o=[...Object.values(n.responses).filter(e=>e.interactionId===t.interactionId&&e.status!==`settled`).map(e=>e.responseId),...[...a.values()].filter(e=>e.interactionId===t.interactionId).map(e=>e.responseId)].at(-1);o!==void 0&&r.push(responseSettled(o,`applied`)),r.push(interactionSettled(t.interactionId,i,{cause:o===void 0?void 0:{responseId:o},response:e}))}for(let e of t.deliveries)e.consumed===void 0&&e.continues!==!0&&i.has(e.deliveryId)&&r.push(deliveryApplied(e.deliveryId));return unchanged(e,r)}function matchSignIns(e,t){let n=new Set(t.attemptIds);return{...unchanged(e,[]),signIns:e.signIns.filter(e=>!n.has(signInAttemptKey(e)))}}function callSignIns(e){return e.suspended.flatMap(e=>(e.approved??[]).flatMap(e=>e.signIns??[]))}function awaitSignIns(e,t){let n=stepCallIds(e),r=t.stopped.filter(({call:e})=>n.has(e.callId));if(r.length===0)return e;let i=r.map(({approval:n,call:r,connections:i})=>{let a=e.approved?.find(e=>e.call.callId===r.callId),o=n?.interactionId??a?.interactionId,s=n?.responder??a?.responder;return{call:r,...o!==void 0&&{interactionId:o},...s!==void 0&&{responder:s},signIns:[...a?.signIns??[],...t.challenges.filter(e=>i.includes(e.name))]}}),a=new Set(i.map(e=>e.call.callId));return{...e,messages:withoutResults(e.messages,a),approved:[...(e.approved??[]).filter(e=>!a.has(e.call.callId)),...i]}}function signInCallbackFacts(e,t,n){let r=signInInteractionId(t);if(e.interactions[r]?.status!==`open`)return[];let i=`callback_${r}`,a=`response_${i}`,o=interactionSettled(r,n.outcome,{cause:{responseId:a},...n.reason!==void 0&&{reason:n.reason}});return[{data:{deliveryId:i,source:{callback:`authorization`}},type:`delivery.admitted`},responseSubmitted({deliveryId:i,interactionId:r,responseId:a}),responseSettled(a,`applied`),n.retryable===!1?{...o,data:{...o.data,response:{retryable:!1}}}:o,deliveryApplied(i)]}function callSignInsSettled(e,t,n){let r=e.projection.view,i=n===void 0?{outcome:`accepted`}:{...n,outcome:`failed`};return(t.signIns??[]).flatMap(e=>signInCallbackFacts(r,e,i))}function completeSignIn(e,t){let n=e.projection.view,r=new Set(callSignIns(e.turn).map(signInAttemptKey));return unchanged(e,t.completions.filter(e=>!r.has(signInAttemptKey(e))).flatMap(e=>signInCallbackFacts(n,e,{outcome:`accepted`})))}function controlDeliveryFor(e,t){return t??{deliveryId:`control_${String(e.projection.view.position)}`}}function controlled(e,t,n){if(e===void 0)return n(void 0);let r=n({deliveryId:e.deliveryId});return{...r,events:[controlAdmitted(e,t),...r.events,deliveryApplied(e.deliveryId)]}}const CANCELLED_CALL_RESULT=`The turn was cancelled before this call finished.`;function cancel(e,t={}){let{projection:n}=e,r=activeTurnIdOf(n),i=e.turn.suspended.filter(e=>r!==void 0&&e.event.turnId===r||e.tasks.some(t=>!answeredCallIds(e.messages).has(t.callId))||(e.approved?.length??0)>0),a=new Set(i.flatMap(e=>e.requests.map(e=>e.interactionId))),o=n.view,s=Object.values(o.interactions).filter(t=>t.status===`open`&&(e.relayedRequestIds.has(t.interactionId)||a.has(t.interactionId)||t.request.kind===`budget`)).map(e=>withdrawInteraction(e.interactionId,`Cancelled.`,`interrupted`));s.push(...turnSettled(n,{cause:t.cause,outcome:`cancelled`},activeTurn(o)?.turnId??r),...unreadSettled(e));let{queued:c,...l}=e.turn;return{...commitSteps(l,i,cancelledTranscript),events:s,signIns:[]}}function unreadSettled(e){let t=e.projection.view;return(e.turn.queued?.deliveries??[]).filter(({deliveryId:e})=>t.deliveries[e]?.status===`admitted`).map(({deliveryId:e})=>fact(`delivery.settled`,{deliveryId:e,outcome:`ignored`}))}function cancelledTranscript(e){return stoppedTranscript(e,()=>CANCELLED_CALL_RESULT)}function stopInterruptedSteps(e,t){let n=e.turn.suspended.filter(e=>e.requests.some(e=>t.settledInteractions.has(e.interactionId))||[...stepCallIds(e)].some(e=>t.calls.get(e)?.started===!0));return{...commitSteps(e.turn,n,e=>stoppedTranscript(e,e=>interruptedCallResult(t.calls.get(e)))),events:[]}}function commitSteps(e,t,n=e=>e.messages){let r=new Set(t);return{commit:t.flatMap(n),turn:{...e,suspended:e.suspended.filter(e=>!r.has(e))}}}function stoppedTranscript(e,t){let n=answeredCallIds(e.messages),r=[...e.messages];for(let i of e.messages)if(i.role===`assistant`&&typeof i.content!=`string`)for(let e of i.content)e.type===`tool-call`&&e.providerExecuted!==!0&&(n.has(e.toolCallId)||(r=withResult(r,{output:{type:`text`,value:t(e.toolCallId)},toolCallId:e.toolCallId,toolName:e.toolName,type:`tool-result`})));return r}function clear(e,t={}){let{projection:n}=e,r=nextChangeId(n);return{clearsHistory:!0,signIns:[],events:[...clearedInteractions(e),...turnSettled(n,{cause:t.cause,outcome:`cancelled`}),...unreadSettled(e),contextStarted({cause:t.cause,changeId:r,kind:`clear`}),fact(`context.settled`,{changeId:r,kind:`clear`,outcome:`completed`,selects:null})],turn:{remembered:e.turn.remembered,suspended:[]}}}function clearedInteractions(e){let t=e.projection.view;return Object.values(t.interactions).filter(t=>t.status===`open`&&!e.relayedRequestIds.has(t.interactionId)).map(e=>withdrawInteraction(e.interactionId,`The context was cleared.`,`interrupted`))}export{CANCELLED_CALL_RESULT,awaitSignIns,callSignIns,callSignInsSettled,cancel,clear,completeSignIn,controlDeliveryFor,controlled,discardAttempt,endTask,fail,finishRun,join,matchSignIns,receive,relay,routeAnswer,runnableCalls,settle,settleTask,startTask,stopInterruptedSteps,suspendStep,withoutApproved};
|
|
1
|
+
import{activeTurnId,answeredCallIds,turnPosition}from"./view.js";import{isComplete,stepCallIds,suspend,withResult,withoutResults}from"./suspended-steps.js";import{activeTurn,interactionOwner}from"#protocol/session-projection/selectors.js";import{isOpen}from"#protocol/session-projection/tree.js";import{callSettledFrom}from"#harness/call-facts.js";import{activeTurnIdOf,nextChangeId,openRunOf}from"#protocol/session-projection.js";import{contextStarted,controlAdmitted,defined,delegatedUsageFact,deliveryApplied,errorInfoOf,fact,runSettledFacts,sessionEndedFacts,turnSettled}from"#harness/facts.js";import{closeUnder}from"#harness/session-machine/cascade.js";import{interruptedCallResult}from"#harness/interrupted-attempt.js";import{interactionSettled,responseAdmitted,responseSettled,responseSubmitted,signInInteractionId}from"#harness/interaction-facts.js";import{signInAttemptKey}from"#harness/hitl/sign-ins.js";const unchanged=(e,t)=>({events:t,turn:e.turn});function followedTurn(e){let t=e.view.selection;return t===null?null:t?.turnId??e.view.session.latestTurnId??null}function waitingDeliveries(e,t){return t.filter(({deliveryId:t})=>e.view?.deliveries[t]?.status===`admitted`)}function consumed(e,t){return fact(`delivery.consumed`,{deliveryId:e.deliveryId,history:(e.history?.length??0)>0?e.history:void 0,parts:e.parts,turnId:t})}function receive(e,t){let{projection:n}=e,r=turnPosition(n),i=activeTurnId(r),a=waitingDeliveries(n,t.deliveries??[]),o=a[0],s=o===void 0?t.cause??{policy:`system`}:{deliveryId:o.deliveryId},{parent:c,predecessor:l,runtime:u,trace:d}=t,f=[];return r.sessionStarted||f.push(fact(`session.started`,{parent:c,predecessor:l,runtime:u,trace:d})),r.turnId===``&&f.push(fact(`turn.started`,{cause:s,follows:followedTurn(n),trace:d,turnId:i})),f.push(...a.map(e=>consumed(e,i))),unchanged(e,f)}function join(e,t){let{projection:n}=e,r=waitingDeliveries(n,t.deliveries),i=activeTurnIdOf(n);return unchanged(e,i===void 0?r.map(({deliveryId:e})=>deliveryApplied(e)):r.map(e=>consumed(e,i)))}function fail(e,t){let n=e.turn.suspended.filter(e=>(e.approved?.length??0)>0),r=errorInfoOf(t),i=activeTurnIdOf(e.projection),a=i===void 0?void 0:openRunOf(e.projection,i),o=[...a===void 0?[]:runSettledFacts({runId:a,outcome:`failed`,error:r}),...t.terminal===void 0?turnSettled(e.projection,{error:r,outcome:`failed`}):sessionEndedFacts(e.projection,{cause:i===void 0?void 0:{turnId:i},error:r,outcome:`failed`})];return{...commitSteps(e.turn,n,cancelledTranscript),events:o}}function settle(e,t){let n=[],r=[...e.turn.suspended];for(let{part:i,result:a,usage:o}of t.results){let t=r.findIndex(e=>stepCallIds(e).has(i.toolCallId)),s=r[t];if(s===void 0)continue;r[t]=withoutApproved({...s,messages:withResult(s.messages,i)},new Set([i.toolCallId]));let c=a===void 0?void 0:e.projection.view.calls[a.callId];a!==void 0&&c!==void 0&&c.taskId===void 0&&c.status!==`settled`&&(n.push(callSettledFrom(a)),o!==void 0&&n.push(delegatedUsageFact(a.callId,o)))}let i=r.filter(isComplete);return{...commitSteps({...e.turn,suspended:r},i),events:n}}function discardAttempt(e,t){let n=e.projection.view,r={family:`run`,id:t.runId},i=t.ending===`steered`?closeUnder(n,r,`steered`):[];if(!isOpen(n,r))return unchanged(e,i);let a=t.ending===`retried`?{outcome:`abandoned`,runId:t.runId,usage:t.usage}:{finishReason:`other`,outcome:`completed`,runId:t.runId,usage:t.usage};return unchanged(e,[...i,...runSettledFacts(a)])}function suspendStep(e,t){return{events:[],turn:suspend(e.turn,{...t,requests:[]})}}function withoutApproved(e,t){if(e.approved===void 0)return e;let n=e.approved.filter(e=>!t.has(e.call.callId));if(n.length===e.approved.length)return e;let{approved:r,...i}=e;return n.length===0?i:{...i,approved:n}}function runnableCalls(e,t){let n=new Set(e.signIns.map(signInAttemptKey));return(t.approved??[]).filter(e=>(e.signIns??[]).every(e=>!n.has(signInAttemptKey(e))))}function startTask(e,t,n){let r=[];return(n?.has(t.taskId)??e.projection.view.tasks[t.taskId]!==void 0)||(n?.add(t.taskId),r.push({type:`task.started`,data:{taskId:t.taskId,kind:t.kind,name:t.name,startedBy:{callId:t.callId}}})),r.push({type:`call.started`,data:defined({callId:t.callId,taskId:t.taskId,clearedBy:t.clearedBy})}),unchanged(e,r)}function settleTask(e,t){let{outcome:n}=t,r=n.status===`completed`?n.output:void 0,i=t.calls[0]?.callId,a=t.calls.map(({callId:e},t)=>fact(`call.settled`,{callId:e,error:n.status===`failed`?{code:`TASK_FAILED`,message:n.error}:void 0,outcome:n.status===`cancelled`?`interrupted`:n.status,output:t===0?r:void 0,outputOf:t>0&&r!==void 0&&i!==void 0?{callId:i}:void 0,reason:n.status===`cancelled`?n.reason??`task-cancelled`:void 0}));return unchanged(e,a)}function endTask(e,t){let n=e.projection.view.tasks[t.taskId];if(n===void 0||n.status===`ended`)return unchanged(e,[]);let{outcome:r}=t;return unchanged(e,[fact(`task.ended`,{error:r.status===`failed`?{code:`TASK_FAILED`,message:r.error}:void 0,outcome:r.status,reason:r.status===`cancelled`?r.reason??`task-ended`:void 0,taskId:t.taskId})])}function finishRun(e,t){let n=new Set(t.requestIds),r=e.projection.view,i=Object.values(r.interactions).filter(e=>e.status===`open`&&(n.has(e.interactionId)||t.taskId!==void 0&&interactionOwner(r,e).taskId===t.taskId));return unchanged(e,i.map(e=>withdrawInteraction(e.interactionId,`asker-ended`)))}function withdrawInteraction(e,t,n=`withdrawn`){return interactionSettled(e,n,{reason:t})}function relay(e,t){let{payload:n}=t,r=e.projection.view,i=n.route===void 0?void 0:{...n.route,...t.workflowAsk!==void 0&&{workflowAsk:t.workflowAsk},...t.runId!==void 0&&{runId:t.runId}},a=[],o={};for(let e of n.events){let t=e.data.interactionId,s=r.interactions[t];if(e.type===`interaction.opened`||s?.origin!==void 0&&`callId`in s.subject&&s.subject.callId===n.callId)switch(e.type){case`interaction.opened`:if(s!==void 0)break;a.push({data:{...e.data,origin:e.data.origin??{interactionId:t,sessionId:n.childSessionId},subject:{callId:n.callId}},type:`interaction.opened`}),i!==void 0&&e.data.request.kind!==`sign-in`&&(o[t]=i);break;case`interaction.settled`:if(s?.status!==`open`)break;a.push(...mirrorSettled(r,e.data));break;case`response.admitted`:{let t=s===void 0?void 0:forwardedAnswer(r,e.data);t!==void 0&&r.responses[t]?.status===`submitted`&&a.push(responseAdmitted(t));break}case`response.settled`:{let t=s===void 0?void 0:forwardedAnswer(r,e.data);t!==void 0&&e.data.outcome!==`applied`&&a.push(responseSettled(t,e.data.outcome,e.data.reason));break}}}return Object.keys(o).length>0?{...unchanged(e,a),relays:o}:unchanged(e,a)}function mirrorSettled(e,t){let n=Object.values(e.responses).filter(e=>e.interactionId===t.interactionId&&e.status!==`settled`).sort((e,t)=>e.introducedAt-t.introducedAt),r=t.outcome===`accepted`||t.outcome===`declined`||t.outcome===`invalid`?n.at(-1):void 0,i=r===void 0?[]:[responseSettled(r.responseId,`applied`,t.reason)],a=r===void 0?t.cause:{responseId:r.responseId};return i.push(fact(`interaction.settled`,{...t,cause:a})),i}function forwardedAnswer(e,t){let n=Object.values(e.responses).filter(e=>e.interactionId===t.interactionId&&e.status!==`settled`).sort((e,t)=>e.introducedAt-t.introducedAt);return(n.find(e=>t.deliveryId!==void 0&&e.deliveryId===t.deliveryId)??n.at(-1))?.responseId}function routeAnswer(e,t){let n=e.projection.view,r=[],i=new Set;for(let e of t.deliveries){if(n.deliveries[e.deliveryId]!==void 0||i.has(e.deliveryId))continue;i.add(e.deliveryId);let{deliveryId:t,principal:a,source:o}=e;r.push(fact(`delivery.admitted`,{deliveryId:t,principal:a,source:o})),e.consumed!==void 0&&r.push(consumed({deliveryId:t,parts:e.consumed.parts},e.consumed.turnId))}let known=e=>i.has(e)||n.deliveries[e]!==void 0,a=new Map;for(let e of t.forwarded)n.responses[e.responseId]===void 0&&n.interactions[e.interactionId]?.status===`open`&&known(e.deliveryId)&&(a.set(e.responseId,e),r.push(responseSubmitted(e)));for(let{answer:e,outcome:i}of t.decided){let t=n.interactions[e.interactionId];if(t?.status!==`open`)continue;let o=[...Object.values(n.responses).filter(e=>e.interactionId===t.interactionId&&e.status!==`settled`).map(e=>e.responseId),...[...a.values()].filter(e=>e.interactionId===t.interactionId).map(e=>e.responseId)].at(-1);o!==void 0&&r.push(responseSettled(o,`applied`)),r.push(interactionSettled(t.interactionId,i,{cause:o===void 0?void 0:{responseId:o},response:e}))}for(let e of t.deliveries)e.consumed===void 0&&e.continues!==!0&&i.has(e.deliveryId)&&r.push(deliveryApplied(e.deliveryId));return unchanged(e,r)}function matchSignIns(e,t){let n=new Set(t.attemptIds);return{...unchanged(e,[]),signIns:e.signIns.filter(e=>!n.has(signInAttemptKey(e)))}}function callSignIns(e){return e.suspended.flatMap(e=>(e.approved??[]).flatMap(e=>e.signIns??[]))}function awaitSignIns(e,t){let n=stepCallIds(e),r=t.stopped.filter(({call:e})=>n.has(e.callId));if(r.length===0)return e;let i=r.map(({approval:n,call:r,connections:i})=>{let a=e.approved?.find(e=>e.call.callId===r.callId),o=n?.interactionId??a?.interactionId,s=n?.responder??a?.responder;return{call:r,...o!==void 0&&{interactionId:o},...s!==void 0&&{responder:s},signIns:[...a?.signIns??[],...t.challenges.filter(e=>i.includes(e.name))]}}),a=new Set(i.map(e=>e.call.callId));return{...e,messages:withoutResults(e.messages,a),approved:[...(e.approved??[]).filter(e=>!a.has(e.call.callId)),...i]}}function signInCallbackFacts(e,t,n){let r=signInInteractionId(t);if(e.interactions[r]?.status!==`open`)return[];let i=`callback_${r}`,a=`response_${i}`,o=interactionSettled(r,n.outcome,{cause:{responseId:a},...n.reason!==void 0&&{reason:n.reason}});return[{data:{deliveryId:i,source:{callback:`authorization`}},type:`delivery.admitted`},responseSubmitted({deliveryId:i,interactionId:r,responseId:a}),responseSettled(a,`applied`),n.retryable===!1?{...o,data:{...o.data,response:{retryable:!1}}}:o,deliveryApplied(i)]}function callSignInsSettled(e,t,n){let r=e.projection.view,i=n===void 0?{outcome:`accepted`}:{...n,outcome:`failed`};return(t.signIns??[]).flatMap(e=>signInCallbackFacts(r,e,i))}function completeSignIn(e,t){let n=e.projection.view,r=new Set(callSignIns(e.turn).map(signInAttemptKey));return unchanged(e,t.completions.filter(e=>!r.has(signInAttemptKey(e))).flatMap(e=>signInCallbackFacts(n,e,{outcome:`accepted`})))}function controlDeliveryFor(e,t){return t??{deliveryId:`control_${String(e.projection.view.position)}`}}function controlled(e,t,n){if(e===void 0)return n(void 0);let r=n({deliveryId:e.deliveryId});return{...r,events:[controlAdmitted(e,t),...r.events,deliveryApplied(e.deliveryId)]}}const CANCELLED_CALL_RESULT=`The turn was cancelled before this call finished.`;function cancel(e,t={}){let{projection:n}=e,r=activeTurnIdOf(n),i=e.turn.suspended.filter(e=>r!==void 0&&e.event.turnId===r||e.tasks.some(t=>!answeredCallIds(e.messages).has(t.callId))||(e.approved?.length??0)>0),a=new Set(i.flatMap(e=>e.requests.map(e=>e.interactionId))),o=n.view,s=Object.values(o.interactions).filter(t=>t.status===`open`&&(e.relayedRequestIds.has(t.interactionId)||a.has(t.interactionId)||t.request.kind===`budget`)).map(e=>withdrawInteraction(e.interactionId,`Cancelled.`,`interrupted`));s.push(...turnSettled(n,{cause:t.cause,outcome:`cancelled`},activeTurn(o)?.turnId??r),...unreadSettled(e));let{queued:c,...l}=e.turn;return{...commitSteps(l,i,cancelledTranscript),events:s,signIns:[]}}function unreadSettled(e){let t=e.projection.view;return(e.turn.queued?.deliveries??[]).filter(({deliveryId:e})=>t.deliveries[e]?.status===`admitted`).map(({deliveryId:e})=>fact(`delivery.settled`,{deliveryId:e,outcome:`ignored`}))}function cancelledTranscript(e){return stoppedTranscript(e,()=>CANCELLED_CALL_RESULT)}function stopInterruptedSteps(e,t){let n=e.turn.suspended.filter(e=>e.requests.some(e=>t.settledInteractions.has(e.interactionId))||[...stepCallIds(e)].some(e=>t.calls.get(e)?.started===!0));return{...commitSteps(e.turn,n,e=>stoppedTranscript(e,e=>interruptedCallResult(t.calls.get(e)))),events:[]}}function commitSteps(e,t,n=e=>e.messages){let r=new Set(t);return{commit:t.flatMap(n),turn:{...e,suspended:e.suspended.filter(e=>!r.has(e))}}}function stoppedTranscript(e,t){let n=answeredCallIds(e.messages),r=[...e.messages];for(let i of e.messages)if(i.role===`assistant`&&typeof i.content!=`string`)for(let e of i.content)e.type===`tool-call`&&e.providerExecuted!==!0&&(n.has(e.toolCallId)||(r=withResult(r,{output:{type:`text`,value:t(e.toolCallId)},toolCallId:e.toolCallId,toolName:e.toolName,type:`tool-result`})));return r}function clear(e,t={}){let{projection:n}=e,r=nextChangeId(n);return{clearsHistory:!0,signIns:[],events:[...clearedInteractions(e),...turnSettled(n,{cause:t.cause,outcome:`cancelled`}),...unreadSettled(e),contextStarted({cause:t.cause,changeId:r,kind:`clear`}),fact(`context.settled`,{changeId:r,kind:`clear`,outcome:`completed`,selects:null})],turn:{remembered:e.turn.remembered,suspended:[]}}}function clearedInteractions(e){let t=e.projection.view;return Object.values(t.interactions).filter(t=>t.status===`open`&&!e.relayedRequestIds.has(t.interactionId)).map(e=>withdrawInteraction(e.interactionId,`The context was cleared.`,`interrupted`))}export{CANCELLED_CALL_RESULT,awaitSignIns,callSignIns,callSignInsSettled,cancel,clear,completeSignIn,controlDeliveryFor,controlled,discardAttempt,endTask,fail,finishRun,join,matchSignIns,receive,relay,routeAnswer,runnableCalls,settle,settleTask,startTask,stopInterruptedSteps,suspendStep,withoutApproved};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const STAMPED_PACKAGE_VERSION=`0.
|
|
1
|
+
const STAMPED_PACKAGE_VERSION=`0.85.0`;function readStampedPackageVersion(){return STAMPED_PACKAGE_VERSION.startsWith(`__`)?void 0:STAMPED_PACKAGE_VERSION}export{readStampedPackageVersion};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EveAttachmentError } from "#internal/attachments/errors.js";
|
|
1
2
|
import type { UploadPolicy } from "#public/channels/upload-policy.js";
|
|
2
3
|
/** The byte cap an upload policy sets; a disabled policy accepts nothing. */
|
|
3
4
|
export declare function maxBytesOf(policy: UploadPolicy): number;
|
|
@@ -14,3 +15,4 @@ export declare function readLimitedBytes(response: Pick<Response, "body" | "head
|
|
|
14
15
|
export declare function limitedFetch(fetchImpl: typeof globalThis.fetch, maxBytes: number, adapterKind: string): typeof globalThis.fetch;
|
|
15
16
|
/** Fails a download whose bytes arrived some other way than a `Response`, once they're in hand. */
|
|
16
17
|
export declare function assertWithinLimit(bytes: Uint8Array, maxBytes: number, adapterKind: string): void;
|
|
18
|
+
export declare function overLimit(maxBytes: number, adapterKind: string): EveAttachmentError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EveAttachmentError}from"#internal/attachments/errors.js";function maxBytesOf(e){return e===`disabled`?0:e.maxBytes}async function readLimitedBytes(e,t,n){let r=Number(e.headers.get(`content-length`)??NaN);if(Number.isFinite(r)&&r>t)throw await e.body?.cancel(),overLimit(t,n);if(e.body===null)return Buffer.alloc(0);let i=e.body.getReader(),a=[],o=0;for(;;){let{done:e,value:r}=await i.read();if(e)break;if(o+=r.byteLength,o>t)throw await i.cancel(),overLimit(t,n);a.push(r)}return Buffer.concat(a)}function limitedFetch(e,t,n){return async(r,i)=>{let a=await e(r,i),o=Number(a.headers.get(`content-length`)??NaN);if(Number.isFinite(o)&&o>t)throw await a.body?.cancel(),overLimit(t,n);if(a.body===null)return a;let s=0,c=a.body.pipeThrough(new TransformStream({transform(e,r){s+=e.byteLength,s>t?r.error(overLimit(t,n)):r.enqueue(e)}}));return new Response(c,{headers:a.headers,status:a.status,statusText:a.statusText})}}function assertWithinLimit(e,t,n){if(e.byteLength>t)throw overLimit(t,n)}function overLimit(e,t){return new EveAttachmentError({adapterKind:t,kind:`resolver-threw`,message:`it is over the ${formatMegabytes(e)} upload limit.`})}function formatMegabytes(e){let t=e/1048576;return`${Number.isInteger(t)?t:t.toFixed(1)} MB`}export{assertWithinLimit,limitedFetch,maxBytesOf,readLimitedBytes};
|
|
1
|
+
import{EveAttachmentError}from"#internal/attachments/errors.js";function maxBytesOf(e){return e===`disabled`?0:e.maxBytes}async function readLimitedBytes(e,t,n){let r=Number(e.headers.get(`content-length`)??NaN);if(Number.isFinite(r)&&r>t)throw await e.body?.cancel(),overLimit(t,n);if(e.body===null)return Buffer.alloc(0);let i=e.body.getReader(),a=[],o=0;for(;;){let{done:e,value:r}=await i.read();if(e)break;if(o+=r.byteLength,o>t)throw await i.cancel(),overLimit(t,n);a.push(r)}return Buffer.concat(a)}function limitedFetch(e,t,n){return async(r,i)=>{let a=await e(r,i),o=Number(a.headers.get(`content-length`)??NaN);if(Number.isFinite(o)&&o>t)throw await a.body?.cancel(),overLimit(t,n);if(a.body===null)return a;let s=0,c=a.body.pipeThrough(new TransformStream({transform(e,r){s+=e.byteLength,s>t?r.error(overLimit(t,n)):r.enqueue(e)}}));return new Response(c,{headers:a.headers,status:a.status,statusText:a.statusText})}}function assertWithinLimit(e,t,n){if(e.byteLength>t)throw overLimit(t,n)}function overLimit(e,t){return new EveAttachmentError({adapterKind:t,kind:`resolver-threw`,message:`it is over the ${formatMegabytes(e)} upload limit.`})}function formatMegabytes(e){let t=e/1048576;return`${Number.isInteger(t)?t:t.toFixed(1)} MB`}export{assertWithinLimit,limitedFetch,maxBytesOf,overLimit,readLimitedBytes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SANDBOX_URL_SCHEME}from"#internal/attachments/sandbox-refs.js";const EVE_URL_SCHEME=`eve-url:`;function serializeUrlFilePart(e){return`${EVE_URL_SCHEME}${e.href}`}function isSerializedUrlFilePart(e){return typeof e==`string`&&e.startsWith(EVE_URL_SCHEME)}function deserializeUrlFilePart(e){return new URL(e.slice(8))}const INTERNAL_REF_SCHEMES=[EVE_URL_SCHEME,SANDBOX_URL_SCHEME];function hasInternalRefScheme(e){
|
|
1
|
+
import{SANDBOX_URL_SCHEME}from"#internal/attachments/sandbox-refs.js";import{CHAT_SDK_FILE_PROTOCOL}from"#public/channels/chat-sdk/attachment-refs.js";const EVE_URL_SCHEME=`eve-url:`;function serializeUrlFilePart(e){return`${EVE_URL_SCHEME}${e.href}`}function isSerializedUrlFilePart(e){return typeof e==`string`&&e.startsWith(EVE_URL_SCHEME)}function deserializeUrlFilePart(e){return new URL(e.slice(8))}const INTERNAL_REF_SCHEMES=[EVE_URL_SCHEME,SANDBOX_URL_SCHEME,CHAT_SDK_FILE_PROTOCOL];function hasInternalRefScheme(e){let t=/^\s*([a-z][a-z\d+.-]*:)/i.exec(e)?.[1]?.toLowerCase();return t!==void 0&&INTERNAL_REF_SCHEMES.includes(t)}export{deserializeUrlFilePart,hasInternalRefScheme,isSerializedUrlFilePart,serializeUrlFilePart};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{formatError}from"#internal/logging.js";function formatCapabilityError(e,t){let n=t.filter(e=>e!==void 0&&e.length>0).flatMap(e=>[e,encodeURIComponent(e)]).sort((e,t)=>t.length-e.length);return Object.fromEntries(Object.entries(formatError(e)).map(([e,t])=>[e,typeof t==`string`?n.reduce((e,t)=>e.replaceAll(t,`[redacted]`),t):t]))}export{formatCapabilityError};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{contentPhase}from"#protocol/session-events/catalog.js";import{callLabel}from"#protocol/session-projection/selectors.js";import{createLogger}from"#internal/logging.js";import{parseAnswers}from"#shared/input.js";import{settleSignIn,showSignIn}from"#channel/sign-in.js";import{requestSettlementOf}from"#channel/interaction-prompts.js";import{sessionTables}from"#protocol/session-projection/session-view.js";import{ContextContainer,contextStorage}from"#context/container.js";import{promptQueue}from"#channel/prompt-queue.js";import{failureNotice}from"#public/channels/reply.js";import{GET,POST,defineChannel}from"#public/definitions/channel.js";import{ContextKey}from"#context/key.js";import{DEFAULT_UPLOAD_POLICY}from"#public/channels/upload-policy.js";import{EveAttachmentError}from"#internal/attachments/errors.js";import{assertWithinLimit}from"#internal/attachments/limited-read.js";import{isNotImplemented}from"#public/channels/chat-sdk/notImplemented.js";import{INACTIVE_REQUEST_NOTICE,respondOrRetireInactivePrompt}from"#channel/inactive-prompt.js";import{Chat,Message,ThreadImpl}from"#compiled/chat/index.js";import{chatSdkSignIns}from"#public/channels/chat-sdk/authorization.js";import{parseChatSdkFileRef}from"#public/channels/chat-sdk/attachment-refs.js";import{decodeInputAction,renderInteractions,renderRetiredInputRequest}from"#public/channels/chat-sdk/input-actions.js";import{reportUndeliveredReply,withUndeliveredReplyNote}from"#public/channels/undelivered-reply.js";import{chatSdkInstrumentation}from"#public/channels/chat-sdk/audience.js";const log=createLogger(`chat-sdk.channel`),SURFACE_NAME=`this chat`,ActiveWebhookKey=new ContextKey(`chat-sdk.active-webhook`);function chatSdkChannel(e){let t=new Chat(e),n=e.inputActionPrefix??`eve_input:`,r=e.streaming??!0,i=e.streamingEditIntervalMs??1e3,a={...defaultEvents(n),...e.events};return t.onAction(async r=>{let i=decodeInputAction(r.actionId,n,r.value);if(!i)return;let{thread:a}=r;if(!a)throw Error(`chatSdkChannel input actions require a thread on the Chat SDK action event.`);let o=e.resolveInputAuth?await e.resolveInputAuth(r):null,s=await respondOrRetireInactivePrompt(()=>bridgeRespond(t,[i],{auth:o,thread:a.toJSON()}),{retirePrompt:e=>retireInputCard(a,r.messageId,e)},log);if(s.outcome===`failed`)throw s.error;s.outcome!==`delivered`&&await Promise.all([s.retirement,a.postEphemeral(r.user,{markdown:INACTIVE_REQUEST_NOTICE},{fallbackToDM:!0}).catch(e=>log.error(`inactive prompt notice failed`,{error:e}))])}),{bot:t,channel:defineChannel({turnPolicy:e.turnPolicy,fetchFile:e=>fetchAttachment(t,e),state:initialState(),...chatSdkInstrumentation,context(e){return{bot:t,state:e,streaming:r,streamingEditIntervalMs:i,thread:threadFromState(t,e)}},routes:adapterNames(e.adapters).flatMap(n=>{let r=routeForAdapter(n,e),handler=async(r,i)=>{let a=t.webhooks[n],o=new ContextContainer;return o.setVirtualContext(ActiveWebhookKey,{from:i.from}),contextStorage.run(o,()=>a(r,{...e.webhook,waitUntil(e){i.waitUntil(e)}}))};return[GET(r,handler),POST(r,handler)]}),async receive(e,{from:n}){let r=serializeReceiveTarget(t,e.target);return n(r.id).send(e.message,{auth:e.auth,state:{thread:r}})},deliver(e,t){recordPrincipalUser(t.state,t.session.auth.current,e),recordLatestMessage(t.state,e);let n=resolveInputAnswer(t.state,e);return n===void 0?withUndeliveredReplyNote(t.state,e,SURFACE_NAME):{answers:parseAnswers([n]),context:e.context}},events:a}),send(e,n){return bridgeSend(t,e,n)},respond(e,n){return bridgeRespond(t,e,n)}}}function defaultEvents(e){async function showPrompt(t,n){if(!t.thread)return!1;let r=await t.thread.post(renderInteractions([n],e));r.id&&(t.state.pendingInputCards={...t.state.pendingInputCards,[r.id]:{requests:[n],resolved:{}}})}async function clearAnsweredCards(t,n){let r=n.thread;if(r)for(let[i,a]of Object.entries(n.state.pendingInputCards??{})){let o=t.resolutions.filter(e=>a.requests.some(t=>t.interactionId===e.interactionId));if(o.length===0)continue;let s={...a.resolved,...Object.fromEntries(o.map(e=>[e.interactionId,e]))},{[i]:c,...l}=n.state.pendingInputCards??{};if(n.state.pendingInputCards=a.requests.every(e=>s[e.interactionId]!==void 0)?l:{...l,[i]:{requests:a.requests,resolved:s}},n.state.editSupported!==!1)try{await r.adapter.editMessage(r.id,i,renderInteractions(a.requests,e,s))}catch(e){if(!isNotImplemented(e)){log.warn(`answered input card edit failed`,{error:e,messageId:i});continue}n.state.editSupported=!1}}}return{async"turn.started"(e,{channel:t}){t.state.pendingToolCallMessage=null,clearStream(t.state),await safeStartTyping(t.thread,`Working...`)},async"call.requested"({data:e},{channel:t}){let n=t.state.pendingToolCallMessage;if(t.state.pendingToolCallMessage=null,n){await safeStartTyping(t.thread,truncate(n));return}if(e.capability.kind===`control`)return;let r=callLabel(e);await safeStartTyping(t.thread,truncate(`${r}...`))},async"content.delta"({data:e},{channel:t}){if(!t.thread||!canStream(t))return;let n=t.state.streamPartId===e.partId;if(e.kind===void 0?!n:e.kind!==`text`)return;let r=((n?t.state.streamText:null)??``)+e.delta;if(!r)return;t.state.streamText=r;let i=t.state.anchorMessageId;if(!i||!n){let n=await t.thread.post({markdown:r});t.state.shownText=r,t.state.anchorMessageId=n.id,t.state.streamPartId=e.partId,t.state.lastEditAtMs=Date.now();return}let a=t.state.lastEditAtMs??0;if(!(Date.now()-a<t.streamingEditIntervalMs))try{await editMessage(t.thread,i,r),t.state.shownText=r,t.state.lastEditAtMs=Date.now()}catch(e){if(!isNotImplemented(e))throw e;t.state.editSupported=!1}},async"interaction.opened"(e,t){let{data:n}=e,{channel:r}=t,i=chatSdkSignIns(r);i!==void 0&&await showSignIn(sessionTables(t.view),n.interactionId,i)},async"interaction.settled"(e,t){let{data:n}=e,{channel:r}=t,i=chatSdkSignIns(r);i!==void 0&&await settleSignIn(sessionTables(t.view),n,i);let a=requestSettlementOf(sessionTables(t.view),n);a!==void 0&&await clearAnsweredCards({resolutions:[a]},r)},committed:promptQueue(showPrompt),async"content.completed"({data:e},{channel:t,session:n}){if(e.kind!==`text`)return;let r=typeof e.value==`string`?e.value:``;if(contentPhase(e.phase)===`narration`){if(t.state.pendingToolCallMessage=r?firstNonEmptyLine(r)??null:null,r)try{await finalizeStreamedMessage(t,r,!1)}catch(e){if(!isNotImplemented(e))throw e}else clearStream(t.state);return}if(t.state.pendingToolCallMessage=null,!r){clearStream(t.state);return}try{await finalizeStreamedMessage(t,r,!0)}catch(e){await reportUndeliveredReply({log,name:SURFACE_NAME,post:async e=>t.thread?.post(e),state:t.state},n.turn.id,e)}},async"turn.settled"({data:e},{channel:t}){let n=failureNotice(e,`turn`);n!==void 0&&await t.thread?.post(n)},async"session.ended"({data:e},{channel:t}){let n=failureNotice(e,{restart:`message`});n!==void 0&&await t.thread?.post(n)}}}async function safeStartTyping(e,t){if(e)try{await e.startTyping(t)}catch(e){if(!isNotImplemented(e))throw e}}async function editMessage(e,t,n){await e.adapter.editMessage(e.id,t,{markdown:n})}async function retireInputCard(e,t,n){try{await e.adapter.editMessage(e.id,t,renderRetiredInputRequest(n))}catch(e){if(!isNotImplemented(e))throw e}}async function finalizeStreamedMessage(e,t,n){let{anchorMessageId:r,shownText:i}=e.state;clearStream(e.state);let a=e.thread;if(a){if(!r){n&&await a.post({markdown:t});return}if(i!==t)try{await editMessage(a,r,t)}catch(t){throw isNotImplemented(t)&&(e.state.editSupported=!1),t}}}function canStream(e){return e.streaming&&e.state.editSupported!==!1}function clearStream(e){e.anchorMessageId=null,e.lastEditAtMs=null,e.streamPartId=null,e.streamText=null,e.shownText=null}function firstNonEmptyLine(e){for(let t of e.split(/\r?\n/u)){let e=t.trim();if(e.length>0)return e}}function truncate(e,t=80){return e.length<=t?e:`${e.slice(0,t-1)}\u2026`}async function bridgeSend(e,t,n){let r=activeFrom(`send`),{adapterName:i,auth:a,inputAnswer:o,thread:s,...c}=n,l=serializeThread(e,s,i),u={thread:l};return o!==void 0&&(u.inputAnswer=o),r(l.id).send(t,{...c,auth:a??null,state:u})}async function bridgeRespond(e,t,n){let r=activeFrom(`respond`),{adapterName:i,auth:a,thread:o,...s}=n;return r(serializeThread(e,o,i).id).respond(parseAnswers(t),{...s,auth:a??null})}function recordPrincipalUser(e,t,n){if(t===null)return;let r=(n.state?.thread)?.currentMessage?.author;if(r===void 0||r.isBot===!0||r.isMe)return;let i=e.usersByPrincipal?.[t.principalId];i!==r.userId&&i!==null&&(e.usersByPrincipal={...e.usersByPrincipal,[t.principalId]:i===void 0?r.userId:null})}function recordLatestMessage(e,t){let n=t.state?.thread?.currentMessage;n===void 0||n.author.isMe||(e.latestMessageId=n.id)}function resolveInputAnswer(e,t){let n=t.state?.inputAnswer;if(n===void 0)return;let r=e.pendingInputCards?.[n.messageId],i=r?.requests.find(e=>r.resolved[e.interactionId]===void 0&&e.request.kind!==`sign-in`&&e.request.options?.some(e=>e.id===n.optionId)===!0);return i===void 0?void 0:{optionId:n.optionId,interactionId:i.interactionId}}function activeFrom(e){let t=contextStorage.getStore()?.get(ActiveWebhookKey);if(!t)throw Error(`chatSdkChannel().${e} can only run during a Chat SDK webhook handler for this bridge.`);return t.from}function initialState(){return{pendingAuthMessageIds:{},thread:null}}async function fetchAttachment(e,t){let n=parseChatSdkFileRef(new URL(t));if(n===null)return null;await e.initialize();let r=e.getAdapter(n.adapter).rehydrateAttachment?.(n.attachment);if(r?.fetchData===void 0)throw new EveAttachmentError({adapterKind:`chat-sdk`,kind:`resolver-threw`,message:`the ${n.adapter} adapter can't download it after the webhook returns.`});let i;try{i=await r.fetchData()}catch(e){throw e instanceof EveAttachmentError?e:new EveAttachmentError({adapterKind:`chat-sdk`,cause:e,kind:`resolver-threw`,message:`the ${n.adapter} download failed.`})}let a=Buffer.isBuffer(i)?i:Buffer.from(i);return assertWithinLimit(a,DEFAULT_UPLOAD_POLICY.maxBytes,`chat-sdk`),{bytes:a,mediaType:n.attachment.mimeType}}function threadFromState(e,t){if(!t.thread)return null;try{let n=t.thread;return new ThreadImpl({adapter:e.getAdapter(n.adapterName),channelId:n.channelId,channelVisibility:n.channelVisibility,currentMessage:n.currentMessage?Message.fromJSON(n.currentMessage):void 0,id:n.id,isDM:n.isDM,stateAdapter:e.getState()})}catch(e){return log.warn(`failed to rebuild Chat SDK thread from channel state`,{error:e}),null}}function serializeReceiveTarget(e,t){if(t.thread)return t.thread;if(!t.threadId)throw Error(`chatSdkChannel().receive requires target.thread or target.threadId.`);return serializeThread(e,t.threadId,t.adapterName)}function serializeThread(e,t,n){if(typeof t==`string`){let r=n??inferAdapterName(t),i=e.getAdapter(r);return{_type:`chat:Thread`,adapterName:r,channelId:i.channelIdFromThreadId(t),channelVisibility:i.getChannelVisibility?.(t),id:t,isDM:!1}}return isSerializedThread(t)?t:t.toJSON()}function isSerializedThread(e){return`_type`in e&&e._type===`chat:Thread`}function inferAdapterName(e){let t=e.indexOf(`:`);if(t<=0)throw Error(`chatSdkChannel string thread references require options.adapterName.`);return e.slice(0,t)}function adapterNames(e){return Object.keys(e)}function routeForAdapter(e,t){return t.routes?.[e]||`${(t.route??`/eve/v1`).replace(/\/$/u,``)}/${e}`}export{chatSdkChannel};
|
|
1
|
+
import{contentPhase}from"#protocol/session-events/catalog.js";import{callLabel}from"#protocol/session-projection/selectors.js";import{createLogger}from"#internal/logging.js";import{parseAnswers}from"#shared/input.js";import{settleSignIn,showSignIn}from"#channel/sign-in.js";import{requestSettlementOf}from"#channel/interaction-prompts.js";import{sessionTables}from"#protocol/session-projection/session-view.js";import{ContextContainer,contextStorage}from"#context/container.js";import{promptQueue}from"#channel/prompt-queue.js";import{failureNotice}from"#public/channels/reply.js";import{GET,POST,defineChannel}from"#public/definitions/channel.js";import{ContextKey}from"#context/key.js";import{DEFAULT_UPLOAD_POLICY}from"#public/channels/upload-policy.js";import{EveAttachmentError}from"#internal/attachments/errors.js";import{assertWithinLimit}from"#internal/attachments/limited-read.js";import{parseChatSdkFileRef}from"#public/channels/chat-sdk/attachment-refs.js";import{isNotImplemented}from"#public/channels/chat-sdk/notImplemented.js";import{INACTIVE_REQUEST_NOTICE,respondOrRetireInactivePrompt}from"#channel/inactive-prompt.js";import{Chat,Message,ThreadImpl}from"#compiled/chat/index.js";import{chatSdkSignIns}from"#public/channels/chat-sdk/authorization.js";import{decodeInputAction,renderInteractions,renderRetiredInputRequest}from"#public/channels/chat-sdk/input-actions.js";import{reportUndeliveredReply,withUndeliveredReplyNote}from"#public/channels/undelivered-reply.js";import{chatSdkInstrumentation}from"#public/channels/chat-sdk/audience.js";const log=createLogger(`chat-sdk.channel`),SURFACE_NAME=`this chat`,ActiveWebhookKey=new ContextKey(`chat-sdk.active-webhook`);function chatSdkChannel(e){let t=new Chat(e),n=e.inputActionPrefix??`eve_input:`,r=e.streaming??!0,i=e.streamingEditIntervalMs??1e3,a={...defaultEvents(n),...e.events};return t.onAction(async r=>{let i=decodeInputAction(r.actionId,n,r.value);if(!i)return;let{thread:a}=r;if(!a)throw Error(`chatSdkChannel input actions require a thread on the Chat SDK action event.`);let o=e.resolveInputAuth?await e.resolveInputAuth(r):null,s=await respondOrRetireInactivePrompt(()=>bridgeRespond(t,[i],{auth:o,thread:a.toJSON()}),{retirePrompt:e=>retireInputCard(a,r.messageId,e)},log);if(s.outcome===`failed`)throw s.error;s.outcome!==`delivered`&&await Promise.all([s.retirement,a.postEphemeral(r.user,{markdown:INACTIVE_REQUEST_NOTICE},{fallbackToDM:!0}).catch(e=>log.error(`inactive prompt notice failed`,{error:e}))])}),{bot:t,channel:defineChannel({turnPolicy:e.turnPolicy,fetchFile:e=>fetchAttachment(t,e),state:initialState(),...chatSdkInstrumentation,context(e){return{bot:t,state:e,streaming:r,streamingEditIntervalMs:i,thread:threadFromState(t,e)}},routes:adapterNames(e.adapters).flatMap(n=>{let r=routeForAdapter(n,e),handler=async(r,i)=>{let a=t.webhooks[n],o=new ContextContainer;return o.setVirtualContext(ActiveWebhookKey,{from:i.from}),contextStorage.run(o,()=>a(r,{...e.webhook,waitUntil(e){i.waitUntil(e)}}))};return[GET(r,handler),POST(r,handler)]}),async receive({message:e,target:n,...r},{from:i}){let a=serializeReceiveTarget(t,n);return i(a.id).send(e,{...r,state:{thread:a}})},deliver(e,t){recordPrincipalUser(t.state,t.session.auth.current,e),recordLatestMessage(t.state,e);let n=resolveInputAnswer(t.state,e);return n===void 0?withUndeliveredReplyNote(t.state,e,SURFACE_NAME):{answers:parseAnswers([n]),context:e.context}},events:a}),send(e,n){return bridgeSend(t,e,n)},respond(e,n){return bridgeRespond(t,e,n)}}}function defaultEvents(e){async function showPrompt(t,n){if(!t.thread)return!1;let r=await t.thread.post(renderInteractions([n],e));r.id&&(t.state.pendingInputCards={...t.state.pendingInputCards,[r.id]:{requests:[n],resolved:{}}})}async function clearAnsweredCards(t,n){let r=n.thread;if(r)for(let[i,a]of Object.entries(n.state.pendingInputCards??{})){let o=t.resolutions.filter(e=>a.requests.some(t=>t.interactionId===e.interactionId));if(o.length===0)continue;let s={...a.resolved,...Object.fromEntries(o.map(e=>[e.interactionId,e]))},{[i]:c,...l}=n.state.pendingInputCards??{};if(n.state.pendingInputCards=a.requests.every(e=>s[e.interactionId]!==void 0)?l:{...l,[i]:{requests:a.requests,resolved:s}},n.state.editSupported!==!1)try{await r.adapter.editMessage(r.id,i,renderInteractions(a.requests,e,s))}catch(e){if(!isNotImplemented(e)){log.warn(`answered input card edit failed`,{error:e,messageId:i});continue}n.state.editSupported=!1}}}return{async"turn.started"(e,{channel:t}){t.state.pendingToolCallMessage=null,clearStream(t.state),await safeStartTyping(t.thread,`Working...`)},async"call.requested"({data:e},{channel:t}){let n=t.state.pendingToolCallMessage;if(t.state.pendingToolCallMessage=null,n){await safeStartTyping(t.thread,truncate(n));return}if(e.capability.kind===`control`)return;let r=callLabel(e);await safeStartTyping(t.thread,truncate(`${r}...`))},async"content.delta"({data:e},{channel:t}){if(!t.thread||!canStream(t))return;let n=t.state.streamPartId===e.partId;if(e.kind===void 0?!n:e.kind!==`text`)return;let r=((n?t.state.streamText:null)??``)+e.delta;if(!r)return;t.state.streamText=r;let i=t.state.anchorMessageId;if(!i||!n){let n=await t.thread.post({markdown:r});t.state.shownText=r,t.state.anchorMessageId=n.id,t.state.streamPartId=e.partId,t.state.lastEditAtMs=Date.now();return}let a=t.state.lastEditAtMs??0;if(!(Date.now()-a<t.streamingEditIntervalMs))try{await editMessage(t.thread,i,r),t.state.shownText=r,t.state.lastEditAtMs=Date.now()}catch(e){if(!isNotImplemented(e))throw e;t.state.editSupported=!1}},async"interaction.opened"(e,t){let{data:n}=e,{channel:r}=t,i=chatSdkSignIns(r);i!==void 0&&await showSignIn(sessionTables(t.view),n.interactionId,i)},async"interaction.settled"(e,t){let{data:n}=e,{channel:r}=t,i=chatSdkSignIns(r);i!==void 0&&await settleSignIn(sessionTables(t.view),n,i);let a=requestSettlementOf(sessionTables(t.view),n);a!==void 0&&await clearAnsweredCards({resolutions:[a]},r)},committed:promptQueue(showPrompt),async"content.completed"({data:e},{channel:t,session:n}){if(e.kind!==`text`)return;let r=typeof e.value==`string`?e.value:``;if(contentPhase(e.phase)===`narration`){if(t.state.pendingToolCallMessage=r?firstNonEmptyLine(r)??null:null,r)try{await finalizeStreamedMessage(t,r,!1)}catch(e){if(!isNotImplemented(e))throw e}else clearStream(t.state);return}if(t.state.pendingToolCallMessage=null,!r){clearStream(t.state);return}try{await finalizeStreamedMessage(t,r,!0)}catch(e){await reportUndeliveredReply({log,name:SURFACE_NAME,post:async e=>t.thread?.post(e),state:t.state},n.turn.id,e)}},async"turn.settled"({data:e},{channel:t}){let n=failureNotice(e,`turn`);n!==void 0&&await t.thread?.post(n)},async"session.ended"({data:e},{channel:t}){let n=failureNotice(e,{restart:`message`});n!==void 0&&await t.thread?.post(n)}}}async function safeStartTyping(e,t){if(e)try{await e.startTyping(t)}catch(e){if(!isNotImplemented(e))throw e}}async function editMessage(e,t,n){await e.adapter.editMessage(e.id,t,{markdown:n})}async function retireInputCard(e,t,n){try{await e.adapter.editMessage(e.id,t,renderRetiredInputRequest(n))}catch(e){if(!isNotImplemented(e))throw e}}async function finalizeStreamedMessage(e,t,n){let{anchorMessageId:r,shownText:i}=e.state;clearStream(e.state);let a=e.thread;if(a){if(!r){n&&await a.post({markdown:t});return}if(i!==t)try{await editMessage(a,r,t)}catch(t){throw isNotImplemented(t)&&(e.state.editSupported=!1),t}}}function canStream(e){return e.streaming&&e.state.editSupported!==!1}function clearStream(e){e.anchorMessageId=null,e.lastEditAtMs=null,e.streamPartId=null,e.streamText=null,e.shownText=null}function firstNonEmptyLine(e){for(let t of e.split(/\r?\n/u)){let e=t.trim();if(e.length>0)return e}}function truncate(e,t=80){return e.length<=t?e:`${e.slice(0,t-1)}\u2026`}async function bridgeSend(e,t,n){let r=activeFrom(`send`),{adapterName:i,auth:a,inputAnswer:o,thread:s,...c}=n,l=serializeThread(e,s,i),u={thread:l};return o!==void 0&&(u.inputAnswer=o),r(l.id).send(t,{...c,auth:a??null,state:u})}async function bridgeRespond(e,t,n){let r=activeFrom(`respond`),{adapterName:i,auth:a,thread:o,...s}=n;return r(serializeThread(e,o,i).id).respond(parseAnswers(t),{...s,auth:a??null})}function recordPrincipalUser(e,t,n){if(t===null)return;let r=(n.state?.thread)?.currentMessage?.author;if(r===void 0||r.isBot===!0||r.isMe)return;let i=e.usersByPrincipal?.[t.principalId];i!==r.userId&&i!==null&&(e.usersByPrincipal={...e.usersByPrincipal,[t.principalId]:i===void 0?r.userId:null})}function recordLatestMessage(e,t){let n=t.state?.thread?.currentMessage;n===void 0||n.author.isMe||(e.latestMessageId=n.id)}function resolveInputAnswer(e,t){let n=t.state?.inputAnswer;if(n===void 0)return;let r=e.pendingInputCards?.[n.messageId],i=r?.requests.find(e=>r.resolved[e.interactionId]===void 0&&e.request.kind!==`sign-in`&&e.request.options?.some(e=>e.id===n.optionId)===!0);return i===void 0?void 0:{optionId:n.optionId,interactionId:i.interactionId}}function activeFrom(e){let t=contextStorage.getStore()?.get(ActiveWebhookKey);if(!t)throw Error(`chatSdkChannel().${e} can only run during a Chat SDK webhook handler for this bridge.`);return t.from}function initialState(){return{pendingAuthMessageIds:{},thread:null}}async function fetchAttachment(e,t){let n=parseChatSdkFileRef(new URL(t));if(n===null)return null;await e.initialize();let r=e.getAdapter(n.adapter).rehydrateAttachment?.(n.attachment);if(r?.fetchData===void 0)throw new EveAttachmentError({adapterKind:`chat-sdk`,kind:`resolver-threw`,message:`the ${n.adapter} adapter can't download it after the webhook returns.`});let i;try{i=await r.fetchData()}catch(e){throw e instanceof EveAttachmentError?e:new EveAttachmentError({adapterKind:`chat-sdk`,cause:e,kind:`resolver-threw`,message:`the ${n.adapter} download failed.`})}let a=Buffer.isBuffer(i)?i:Buffer.from(i);return assertWithinLimit(a,DEFAULT_UPLOAD_POLICY.maxBytes,`chat-sdk`),{bytes:a,mediaType:n.attachment.mimeType}}function threadFromState(e,t){if(!t.thread)return null;try{let n=t.thread;return new ThreadImpl({adapter:e.getAdapter(n.adapterName),channelId:n.channelId,channelVisibility:n.channelVisibility,currentMessage:n.currentMessage?Message.fromJSON(n.currentMessage):void 0,id:n.id,isDM:n.isDM,stateAdapter:e.getState()})}catch(e){return log.warn(`failed to rebuild Chat SDK thread from channel state`,{error:e}),null}}function serializeReceiveTarget(e,t){if(t.thread)return t.thread;if(!t.threadId)throw Error(`chatSdkChannel().receive requires target.thread or target.threadId.`);return serializeThread(e,t.threadId,t.adapterName)}function serializeThread(e,t,n){if(typeof t==`string`){let r=n??inferAdapterName(t),i=e.getAdapter(r);return{_type:`chat:Thread`,adapterName:r,channelId:i.channelIdFromThreadId(t),channelVisibility:i.getChannelVisibility?.(t),id:t,isDM:!1}}return isSerializedThread(t)?t:t.toJSON()}function isSerializedThread(e){return`_type`in e&&e._type===`chat:Thread`}function inferAdapterName(e){let t=e.indexOf(`:`);if(t<=0)throw Error(`chatSdkChannel string thread references require options.adapterName.`);return e.slice(0,t)}function adapterNames(e){return Object.keys(e)}function routeForAdapter(e,t){return t.routes?.[e]||`${(t.route??`/eve/v1`).replace(/\/$/u,``)}/${e}`}export{chatSdkChannel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{discordAudience,discordInstrumentationMetadata}from"./audience.js";import{createLogger,logError}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{INACTIVE_REQUEST_NOTICE,respondOrRetireInactivePrompt}from"#channel/inactive-prompt.js";import{buildFreeformModalResponse,deriveComponentAnswers,deriveModalAnswers,isDiscordFreeformComponent}from"#public/channels/discord/hitl.js";import{callDiscordApi,createDiscordFollowupMessage,discordContinuationToken,editDiscordOriginalResponse,resolveDiscordBotToken,sendDiscordChannelMessage,splitDiscordMessageContent,triggerDiscordTypingIndicator}from"#public/channels/discord/api.js";import{answerDiscordAuthorizationReveal,readDiscordAuthorizationReveal}from"#public/channels/discord/authorization.js";import{defaultDiscordAuth,defaultEvents,defaultOnCommand,editDiscordResolvedPrompt}from"#public/channels/discord/defaults.js";import{DISCORD_EPHEMERAL_MESSAGE_FLAG,DISCORD_INTERACTION_RESPONSE_TYPE,DISCORD_INTERACTION_TYPE,commandInteractionMessage,formatDiscordContextBlock,parseDiscordInteraction}from"#public/channels/discord/inbound.js";import{discordDeferredJson,discordJson,discordJsonBody,readMessageContent}from"#public/channels/discord/responses.js";import{createDiscordGatewayRoute}from"#public/channels/discord/messages.js";import{verifyDiscordInbound}from"#public/channels/discord/verifyInbound.js";import{createDiscordFetchFile,discordCommandContent}from"#public/channels/discord/attachments.js";const log=createLogger(`discord.channel`);function discordChannel(e={}){let t=e.onCommand??defaultOnCommand,n=e.onAnswers??(e.onCommand===void 0?acceptAsPresser:dropUnmappedAnswer),r={...defaultEvents,...e.events};return defineChannel({turnPolicy:e.turnPolicy,state:initialDiscordState(),metadata:discordInstrumentationMetadata,audience:({state:e})=>e.audience??`unknown`,fetchFile:createDiscordFetchFile(e.api?.fetch),context(t,n){return rebuildDiscordContext(t,n,e)},routes:[POST(e.route??`/eve/v1/discord`,async(r,{from:i,resolveSession:a,waitUntil:o})=>{let s=await verifyDiscordInbound(r,e.credentials);if(s===null)return new Response(`unauthorized`,{status:401});let c;try{c=parseJsonObject(JSON.parse(s))}catch(e){return log.warn(`inbound Discord body is not valid JSON`,{error:e}),discordJson({content:`invalid request`,ephemeral:!0})}if(c.type===DISCORD_INTERACTION_TYPE.PING)return discordJson({type:DISCORD_INTERACTION_RESPONSE_TYPE.PONG});let l=parseDiscordInteraction(c);return l===null?discordJson({content:`Unsupported Discord interaction.`,ephemeral:!0}):handleInteraction({config:e,interaction:l,onCommand:t,onAnswers:n,from:i,resolveSession:a,waitUntil:o})}),...e.gateway===void 0?[]:[createDiscordGatewayRoute({buildContext:t=>({discord:buildDiscordHandle({config:e,state:t})}),config:e,gateway:e.gateway})]],async receive(t,{from:n}){let r=t.target,i=readNonEmptyString(r.channelId);if(!i)throw Error(`discordChannel().receive requires target.channelId.`);let a=readNonEmptyString(r.conversationId),o=r.initialMessage;if(o!==void 0&&a!==void 0)throw Error("discordChannel().receive: `conversationId` and `initialMessage` are mutually exclusive.");let s=a??``,c=a!==void 0;if(o!==void 0){let t=await buildDiscordHandle({config:e,state:{...initialDiscordState(),channelId:i}}).sendChannelMessage(o);s=t.id,c=t.id.length>0}return n(discordContinuationToken({channelId:i,conversationId:s})).send(t.message,{auth:t.auth,state:{applicationId:null,channelId:i,conversationId:s||null,guildId:null,hasMessageAnchor:c,initialResponseSent:!0,interactionToken:null}})},events:r})}function rebuildDiscordContext(e,t,n){return{discord:buildDiscordHandle({config:n,session:t,state:e}),state:e}}function buildDiscordHandle(e){let t=e.config.api,n=e.state,r=mergeCredentials(e.config.credentials,n);function anchor(t){t.id&&(n.hasMessageAnchor||=(n.conversationId=t.id,!0),n.channelId&&e.session?.continuation?.alias(discordContinuationToken({channelId:n.channelId,conversationId:t.id})))}async function sendViaChannel(e){let i=n.channelId??``;if(!i)throw Error(`discordChannel: missing channel id for outbound message.`);let a=normalizePostInput(e),o=await sendDiscordChannelMessage({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,channelId:i});return anchor(o),o}async function editOriginal(e){let i=n.interactionToken??``;if(!i)throw Error(`discordChannel: missing interaction token for original response edit.`);let a=normalizePostInput(e),o=await editDiscordOriginalResponse({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,interactionToken:i});return n.initialResponseSent=!0,anchor(o),o}async function followup(e){let i=n.interactionToken??``;if(!i)throw Error(`discordChannel: missing interaction token for followup message.`);let a=normalizePostInput(e),o=await createDiscordFollowupMessage({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,interactionToken:i});return anchor(o),o}async function startTyping(){let e=n.channelId??``;if(e)try{await triggerDiscordTypingIndicator({apiBaseUrl:t?.apiBaseUrl,credentials:r,fetch:t?.fetch,channelId:e})}catch(t){logError(log,`Discord typing indicator failed — swallowed`,t,{channelId:e})}}return{applicationId:n.applicationId??void 0,channelId:n.channelId??``,conversationId:n.conversationId??``,guildId:n.guildId??void 0,interactionToken:n.interactionToken??void 0,request(e,n,i){return callDiscordApi({apiBaseUrl:t?.apiBaseUrl,body:n,botToken:i?.botAuth===!0?r.botToken:void 0,fetch:t?.fetch,method:i?.method,path:e})},async post(e){let t=expandPostBodies(normalizePostInput(e)),r;for(let e of t){let t=await postOne({body:e,editOriginal,followup,sendViaChannel,state:n});r===void 0&&(r=t)}return r??{id:``,raw:null}},editOriginalResponse:editOriginal,followup,sendChannelMessage:sendViaChannel,startTyping}}async function postOne(e){if(e.state.interactionToken&&e.state.applicationId)try{return e.state.initialResponseSent?await e.followup(e.body):await e.editOriginal(e.body)}catch(e){log.warn(`Discord interaction-token delivery failed, falling back to channel message`,{error:e})}return e.sendViaChannel(e.body)}async function handleInteraction(e){if(e.interaction.type===DISCORD_INTERACTION_TYPE.MESSAGE_COMPONENT){let t=readDiscordAuthorizationReveal(e.interaction.customId);if(t!==null)return revealAuthorization({...e,interaction:e.interaction,reveal:t})}return e.interaction.type===DISCORD_INTERACTION_TYPE.APPLICATION_COMMAND?handleCommandInteraction({config:e.config,interaction:e.interaction,onCommand:e.onCommand,from:e.from,waitUntil:e.waitUntil}):e.interaction.type===DISCORD_INTERACTION_TYPE.MESSAGE_COMPONENT?handleComponentInteraction({config:e.config,interaction:e.interaction,onAnswers:e.onAnswers,from:e.from,waitUntil:e.waitUntil}):handleModalSubmitInteraction({config:e.config,interaction:e.interaction,onAnswers:e.onAnswers,from:e.from,waitUntil:e.waitUntil})}async function handleCommandInteraction(e){let t=stateFromInteraction(e.interaction,{conversationId:e.interaction.id,hasMessageAnchor:!1,initialResponseSent:!1}),n={discord:buildDiscordHandle({config:e.config,state:t})},r;try{r=await e.onCommand(n,e.interaction)}catch(e){return log.error(`command handler failed`,{error:e}),discordJson({content:`The Discord command handler failed.`,ephemeral:!0})}return r==null?discordJson({content:`Command ignored.`,ephemeral:!0}):(e.waitUntil(dispatchCommand({interaction:e.interaction,result:r,from:e.from,state:t})),discordDeferredJson(r.ephemeral===!0))}function revealAuthorization(e){return e.waitUntil(answerRevealedAuthorization(e)),discordDeferredJson(!0)}async function answerRevealedAuthorization(e){let{interaction:t}=e,n=stateFromInteraction(t,{conversationId:t.messageId,hasMessageAnchor:!0,initialResponseSent:!1}),r=buildDiscordHandle({config:e.config,state:n}),i=null;try{i=(await e.onAnswers({defaultAuth:defaultDiscordAuth(t),discord:r},t))?.auth??null}catch(e){log.error(`Discord sign-in press authorization failed`,{error:e})}let a=await answerDiscordAuthorizationReveal({auth:i,resolveSession:()=>e.resolveSession(discordContinuationToken({channelId:t.channelId,conversationId:t.messageId})),reveal:e.reveal});try{await r.editOriginalResponse(a)}catch(e){log.error(`Discord sign-in reply failed`,{error:e})}}function handleComponentInteraction(e){if(isDiscordFreeformComponent(e.interaction.customId)){let t=readMessageContent(e.interaction.raw);return discordJsonBody(buildFreeformModalResponse({customId:e.interaction.customId,prompt:t}))}let t=deriveComponentAnswers(e.interaction);return t.length>0&&e.waitUntil(dispatchAnswers({config:e.config,onAnswers:e.onAnswers,conversationId:e.interaction.messageId,answers:t,interaction:e.interaction,from:e.from})),discordJsonBody({type:DISCORD_INTERACTION_RESPONSE_TYPE.DEFERRED_UPDATE_MESSAGE})}function handleModalSubmitInteraction(e){let t=deriveModalAnswers(e.interaction);return t.length>0&&e.waitUntil(dispatchAnswers({config:e.config,onAnswers:e.onAnswers,conversationId:e.interaction.messageId??e.interaction.id,answers:t,interaction:e.interaction,from:e.from})),discordJson({content:`Answer received.`,ephemeral:!0})}async function dispatchCommand(e){let t=discordCommandContent(commandInteractionMessage(e.interaction),e.interaction.attachments),n=formatDiscordContextBlock({applicationId:e.interaction.applicationId,channelId:e.interaction.channelId,commandName:e.interaction.commandName,guildId:e.interaction.guildId,interactionId:e.interaction.id,userId:e.interaction.user.id,username:e.interaction.user.username}),r=e.result.context??[];try{await e.from(discordContinuationToken({channelId:e.interaction.channelId,conversationId:e.interaction.id})).send(t,{auth:e.result.auth,context:[n,...r],history:e.result.history,state:e.state,title:e.result.title})}catch(e){log.error(`command delivery failed`,{error:e})}}async function dispatchAnswers(e){let t=stateFromInteraction(e.interaction,{conversationId:e.conversationId,hasMessageAnchor:e.conversationId!==e.interaction.id,initialResponseSent:!0}),n=buildDiscordHandle({config:e.config,state:t}),r;try{r=await e.onAnswers({defaultAuth:defaultDiscordAuth(e.interaction),discord:n},e.interaction)}catch(e){log.error(`input response handler failed`,{error:e});return}if(r===null)return;let{auth:i}=r,a=e.from(discordContinuationToken({channelId:e.interaction.channelId,conversationId:e.conversationId})),o=await respondOrRetireInactivePrompt(()=>a.respond(e.answers,{auth:i}),{retirePrompt:async t=>{let r=e.interaction.messageId,i=readMessageContent(e.interaction.raw);r!==void 0&&i!==void 0&&await editDiscordResolvedPrompt(n,{content:i,messageId:r},t)}},log);o.outcome===`inactive`&&await Promise.all([o.retirement,sendInactiveNotice(n)])}async function sendInactiveNotice(e){try{await e.followup({content:INACTIVE_REQUEST_NOTICE,flags:DISCORD_EPHEMERAL_MESSAGE_FLAG})}catch(e){log.error(`inactive prompt notice failed`,{error:e})}}function acceptAsPresser(e){return{auth:e.defaultAuth}}function dropUnmappedAnswer(){return log.warn(`dropped a Discord input response: onCommand is customized but onAnswers is not; set onAnswers to accept button presses and modal submissions`),null}function stateFromInteraction(e,t){return{audience:discordAudience(e.channelType),applicationId:e.applicationId,...e.channelType!==void 0&&{channelType:e.channelType},channelId:e.channelId,conversationId:t.conversationId,guildId:e.guildId??null,hasMessageAnchor:t.hasMessageAnchor,initialResponseSent:t.initialResponseSent,interactionToken:e.token}}function initialDiscordState(){return{applicationId:null,channelId:null,conversationId:null,guildId:null,hasMessageAnchor:!1,initialResponseSent:!1,interactionToken:null}}function mergeCredentials(e,t){return{applicationId:t.applicationId??e?.applicationId,botToken:e?.botToken??(()=>resolveDiscordBotToken()),publicKey:e?.publicKey,webhookVerifier:e?.webhookVerifier}}function normalizePostInput(e){return typeof e==`string`?{content:e}:e}function expandPostBodies(e){return typeof e.content==`string`?splitDiscordMessageContent(e.content).map((t,n)=>n===0?{...e,content:t}:{allowed_mentions:e.allowed_mentions,content:t}):[e]}export{discordChannel};
|
|
1
|
+
import{discordAudience,discordInstrumentationMetadata}from"./audience.js";import{createLogger,logError}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{parseJsonObject}from"#shared/json.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{INACTIVE_REQUEST_NOTICE,respondOrRetireInactivePrompt}from"#channel/inactive-prompt.js";import{buildFreeformModalResponse,deriveComponentAnswers,deriveModalAnswers,isDiscordFreeformComponent}from"#public/channels/discord/hitl.js";import{callDiscordApi,createDiscordFollowupMessage,discordContinuationToken,editDiscordOriginalResponse,resolveDiscordBotToken,sendDiscordChannelMessage,splitDiscordMessageContent,triggerDiscordTypingIndicator}from"#public/channels/discord/api.js";import{answerDiscordAuthorizationReveal,readDiscordAuthorizationReveal}from"#public/channels/discord/authorization.js";import{defaultDiscordAuth,defaultEvents,defaultOnCommand,editDiscordResolvedPrompt}from"#public/channels/discord/defaults.js";import{DISCORD_EPHEMERAL_MESSAGE_FLAG,DISCORD_INTERACTION_RESPONSE_TYPE,DISCORD_INTERACTION_TYPE,commandInteractionMessage,formatDiscordContextBlock,parseDiscordInteraction}from"#public/channels/discord/inbound.js";import{discordDeferredJson,discordJson,discordJsonBody,readMessageContent}from"#public/channels/discord/responses.js";import{createDiscordGatewayRoute}from"#public/channels/discord/messages.js";import{verifyDiscordInbound}from"#public/channels/discord/verifyInbound.js";import{createDiscordFetchFile,discordCommandContent}from"#public/channels/discord/attachments.js";const log=createLogger(`discord.channel`);function discordChannel(e={}){let t=e.onCommand??defaultOnCommand,n=e.onAnswers??(e.onCommand===void 0?acceptAsPresser:dropUnmappedAnswer),r={...defaultEvents,...e.events};return defineChannel({turnPolicy:e.turnPolicy,state:initialDiscordState(),metadata:discordInstrumentationMetadata,audience:({state:e})=>e.audience??`unknown`,fetchFile:createDiscordFetchFile(e.api?.fetch),context(t,n){return rebuildDiscordContext(t,n,e)},routes:[POST(e.route??`/eve/v1/discord`,async(r,{from:i,resolveSession:a,waitUntil:o})=>{let s=await verifyDiscordInbound(r,e.credentials);if(s===null)return new Response(`unauthorized`,{status:401});let c;try{c=parseJsonObject(JSON.parse(s))}catch(e){return log.warn(`inbound Discord body is not valid JSON`,{error:e}),discordJson({content:`invalid request`,ephemeral:!0})}if(c.type===DISCORD_INTERACTION_TYPE.PING)return discordJson({type:DISCORD_INTERACTION_RESPONSE_TYPE.PONG});let l=parseDiscordInteraction(c);return l===null?discordJson({content:`Unsupported Discord interaction.`,ephemeral:!0}):handleInteraction({config:e,interaction:l,onCommand:t,onAnswers:n,from:i,resolveSession:a,waitUntil:o})}),...e.gateway===void 0?[]:[createDiscordGatewayRoute({buildContext:t=>({discord:buildDiscordHandle({config:e,state:t})}),config:e,gateway:e.gateway})]],async receive({message:t,target:n,...r},{from:i}){let a=n,o=readNonEmptyString(a.channelId);if(!o)throw Error(`discordChannel().receive requires target.channelId.`);let s=readNonEmptyString(a.conversationId),c=a.initialMessage;if(c!==void 0&&s!==void 0)throw Error("discordChannel().receive: `conversationId` and `initialMessage` are mutually exclusive.");let l=s??``,u=s!==void 0;if(c!==void 0){let t=await buildDiscordHandle({config:e,state:{...initialDiscordState(),channelId:o}}).sendChannelMessage(c);l=t.id,u=t.id.length>0}return i(discordContinuationToken({channelId:o,conversationId:l})).send(t,{...r,state:{applicationId:null,channelId:o,conversationId:l||null,guildId:null,hasMessageAnchor:u,initialResponseSent:!0,interactionToken:null}})},events:r})}function rebuildDiscordContext(e,t,n){return{discord:buildDiscordHandle({config:n,session:t,state:e}),state:e}}function buildDiscordHandle(e){let t=e.config.api,n=e.state,r=mergeCredentials(e.config.credentials,n);function anchor(t){t.id&&(n.hasMessageAnchor||=(n.conversationId=t.id,!0),n.channelId&&e.session?.continuation?.alias(discordContinuationToken({channelId:n.channelId,conversationId:t.id})))}async function sendViaChannel(e){let i=n.channelId??``;if(!i)throw Error(`discordChannel: missing channel id for outbound message.`);let a=normalizePostInput(e),o=await sendDiscordChannelMessage({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,channelId:i});return anchor(o),o}async function editOriginal(e){let i=n.interactionToken??``;if(!i)throw Error(`discordChannel: missing interaction token for original response edit.`);let a=normalizePostInput(e),o=await editDiscordOriginalResponse({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,interactionToken:i});return n.initialResponseSent=!0,anchor(o),o}async function followup(e){let i=n.interactionToken??``;if(!i)throw Error(`discordChannel: missing interaction token for followup message.`);let a=normalizePostInput(e),o=await createDiscordFollowupMessage({apiBaseUrl:t?.apiBaseUrl,body:a,credentials:r,fetch:t?.fetch,interactionToken:i});return anchor(o),o}async function startTyping(){let e=n.channelId??``;if(e)try{await triggerDiscordTypingIndicator({apiBaseUrl:t?.apiBaseUrl,credentials:r,fetch:t?.fetch,channelId:e})}catch(t){logError(log,`Discord typing indicator failed — swallowed`,t,{channelId:e})}}return{applicationId:n.applicationId??void 0,channelId:n.channelId??``,conversationId:n.conversationId??``,guildId:n.guildId??void 0,interactionToken:n.interactionToken??void 0,request(e,n,i){return callDiscordApi({apiBaseUrl:t?.apiBaseUrl,body:n,botToken:i?.botAuth===!0?r.botToken:void 0,fetch:t?.fetch,method:i?.method,path:e})},async post(e){let t=expandPostBodies(normalizePostInput(e)),r;for(let e of t){let t=await postOne({body:e,editOriginal,followup,sendViaChannel,state:n});r===void 0&&(r=t)}return r??{id:``,raw:null}},editOriginalResponse:editOriginal,followup,sendChannelMessage:sendViaChannel,startTyping}}async function postOne(e){if(e.state.interactionToken&&e.state.applicationId)try{return e.state.initialResponseSent?await e.followup(e.body):await e.editOriginal(e.body)}catch(e){log.warn(`Discord interaction-token delivery failed, falling back to channel message`,{error:e})}return e.sendViaChannel(e.body)}async function handleInteraction(e){if(e.interaction.type===DISCORD_INTERACTION_TYPE.MESSAGE_COMPONENT){let t=readDiscordAuthorizationReveal(e.interaction.customId);if(t!==null)return revealAuthorization({...e,interaction:e.interaction,reveal:t})}return e.interaction.type===DISCORD_INTERACTION_TYPE.APPLICATION_COMMAND?handleCommandInteraction({config:e.config,interaction:e.interaction,onCommand:e.onCommand,from:e.from,waitUntil:e.waitUntil}):e.interaction.type===DISCORD_INTERACTION_TYPE.MESSAGE_COMPONENT?handleComponentInteraction({config:e.config,interaction:e.interaction,onAnswers:e.onAnswers,from:e.from,waitUntil:e.waitUntil}):handleModalSubmitInteraction({config:e.config,interaction:e.interaction,onAnswers:e.onAnswers,from:e.from,waitUntil:e.waitUntil})}async function handleCommandInteraction(e){let t=stateFromInteraction(e.interaction,{conversationId:e.interaction.id,hasMessageAnchor:!1,initialResponseSent:!1}),n={discord:buildDiscordHandle({config:e.config,state:t})},r;try{r=await e.onCommand(n,e.interaction)}catch(e){return log.error(`command handler failed`,{error:e}),discordJson({content:`The Discord command handler failed.`,ephemeral:!0})}return r==null?discordJson({content:`Command ignored.`,ephemeral:!0}):(e.waitUntil(dispatchCommand({interaction:e.interaction,result:r,from:e.from,state:t})),discordDeferredJson(r.ephemeral===!0))}function revealAuthorization(e){return e.waitUntil(answerRevealedAuthorization(e)),discordDeferredJson(!0)}async function answerRevealedAuthorization(e){let{interaction:t}=e,n=stateFromInteraction(t,{conversationId:t.messageId,hasMessageAnchor:!0,initialResponseSent:!1}),r=buildDiscordHandle({config:e.config,state:n}),i=null;try{i=(await e.onAnswers({defaultAuth:defaultDiscordAuth(t),discord:r},t))?.auth??null}catch(e){log.error(`Discord sign-in press authorization failed`,{error:e})}let a=await answerDiscordAuthorizationReveal({auth:i,resolveSession:()=>e.resolveSession(discordContinuationToken({channelId:t.channelId,conversationId:t.messageId})),reveal:e.reveal});try{await r.editOriginalResponse(a)}catch(e){log.error(`Discord sign-in reply failed`,{error:e})}}function handleComponentInteraction(e){if(isDiscordFreeformComponent(e.interaction.customId)){let t=readMessageContent(e.interaction.raw);return discordJsonBody(buildFreeformModalResponse({customId:e.interaction.customId,prompt:t}))}let t=deriveComponentAnswers(e.interaction);return t.length>0&&e.waitUntil(dispatchAnswers({config:e.config,onAnswers:e.onAnswers,conversationId:e.interaction.messageId,answers:t,interaction:e.interaction,from:e.from})),discordJsonBody({type:DISCORD_INTERACTION_RESPONSE_TYPE.DEFERRED_UPDATE_MESSAGE})}function handleModalSubmitInteraction(e){let t=deriveModalAnswers(e.interaction);return t.length>0&&e.waitUntil(dispatchAnswers({config:e.config,onAnswers:e.onAnswers,conversationId:e.interaction.messageId??e.interaction.id,answers:t,interaction:e.interaction,from:e.from})),discordJson({content:`Answer received.`,ephemeral:!0})}async function dispatchCommand(e){let t=discordCommandContent(commandInteractionMessage(e.interaction),e.interaction.attachments),n=formatDiscordContextBlock({applicationId:e.interaction.applicationId,channelId:e.interaction.channelId,commandName:e.interaction.commandName,guildId:e.interaction.guildId,interactionId:e.interaction.id,userId:e.interaction.user.id,username:e.interaction.user.username}),r=e.result.context??[];try{await e.from(discordContinuationToken({channelId:e.interaction.channelId,conversationId:e.interaction.id})).send(t,{auth:e.result.auth,context:[n,...r],history:e.result.history,state:e.state,title:e.result.title})}catch(e){log.error(`command delivery failed`,{error:e})}}async function dispatchAnswers(e){let t=stateFromInteraction(e.interaction,{conversationId:e.conversationId,hasMessageAnchor:e.conversationId!==e.interaction.id,initialResponseSent:!0}),n=buildDiscordHandle({config:e.config,state:t}),r;try{r=await e.onAnswers({defaultAuth:defaultDiscordAuth(e.interaction),discord:n},e.interaction)}catch(e){log.error(`input response handler failed`,{error:e});return}if(r===null)return;let{auth:i}=r,a=e.from(discordContinuationToken({channelId:e.interaction.channelId,conversationId:e.conversationId})),o=await respondOrRetireInactivePrompt(()=>a.respond(e.answers,{auth:i}),{retirePrompt:async t=>{let r=e.interaction.messageId,i=readMessageContent(e.interaction.raw);r!==void 0&&i!==void 0&&await editDiscordResolvedPrompt(n,{content:i,messageId:r},t)}},log);o.outcome===`inactive`&&await Promise.all([o.retirement,sendInactiveNotice(n)])}async function sendInactiveNotice(e){try{await e.followup({content:INACTIVE_REQUEST_NOTICE,flags:DISCORD_EPHEMERAL_MESSAGE_FLAG})}catch(e){log.error(`inactive prompt notice failed`,{error:e})}}function acceptAsPresser(e){return{auth:e.defaultAuth}}function dropUnmappedAnswer(){return log.warn(`dropped a Discord input response: onCommand is customized but onAnswers is not; set onAnswers to accept button presses and modal submissions`),null}function stateFromInteraction(e,t){return{audience:discordAudience(e.channelType),applicationId:e.applicationId,...e.channelType!==void 0&&{channelType:e.channelType},channelId:e.channelId,conversationId:t.conversationId,guildId:e.guildId??null,hasMessageAnchor:t.hasMessageAnchor,initialResponseSent:t.initialResponseSent,interactionToken:e.token}}function initialDiscordState(){return{applicationId:null,channelId:null,conversationId:null,guildId:null,hasMessageAnchor:!1,initialResponseSent:!1,interactionToken:null}}function mergeCredentials(e,t){return{applicationId:t.applicationId??e?.applicationId,botToken:e?.botToken??(()=>resolveDiscordBotToken()),publicKey:e?.publicKey,webhookVerifier:e?.webhookVerifier}}function normalizePostInput(e){return typeof e==`string`?{content:e}:e}function expandPostBodies(e){return typeof e.content==`string`?splitDiscordMessageContent(e.content).map((t,n)=>n===0?{...e,content:t}:{allowed_mentions:e.allowed_mentions,content:t}):[e]}export{discordChannel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{createGitHubBotNameResolver}from"#public/channels/github/auth.js";import{getGitHubRepository}from"#public/channels/github/api.js";import{parseGitHubWebhookEvent}from"#public/channels/github/inbound.js";import{buildGitHubBinding}from"#public/channels/github/binding.js";import{continuationTokenFromState,conversationFromState,initialGitHubState,stateFromReceiveTarget}from"#public/channels/github/state.js";import{GITHUB_CHANNEL_DEFAULT_ROUTE}from"#public/channels/github/constants.js";import{createDefaultEvents,defaultOnComment}from"#public/channels/github/defaults.js";import{dispatchCheckRun,dispatchCheckSuite,dispatchIssue,dispatchIssueComment,dispatchPullRequest,dispatchPullRequestReviewComment,dispatchWorkflowRun}from"#public/channels/github/dispatch.js";import{verifyGitHubRequest}from"#public/channels/github/verify.js";const log=createLogger(`github.channel`);function githubChannel(e={}){let t=createGitHubBotNameResolver({botName:e.botName,credentials:e.credentials}),n={botName:t},r={...createDefaultEvents({api:e.api,botName:t,credentials:e.credentials,progress:e.progress}),...e.events};return defineChannel({turnPolicy:e.turnPolicy,state:initialGitHubState(),context(t,n){return rebuildGitHubContext(t,n,e)},routes:[POST(e.route??GITHUB_CHANNEL_DEFAULT_ROUTE,async(r,{from:i,waitUntil:a})=>{let o=await verifyInbound(r,e.credentials);if(o===null)return new Response(`unauthorized`,{status:401});let s=missingGitHubWebhookHeaders(r.headers),c;try{c=parseGitHubWebhookEvent({body:o,contentType:r.headers.get(`content-type`)??void 0,headers:r.headers})}catch(e){return log.warn(`inbound GitHub body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return c===null?(s.length>0&&log.warn(`GitHub webhook ignored because standard headers were missing`,{missingHeaders:s}),jsonOk({ignored:!0,ok:!0})):(s.length>0&&log.warn(`GitHub webhook missing standard headers; inferred metadata from payload`,{deliveryId:c.delivery.id,event:c.delivery.event,missingHeaders:s,repository:c.repository.fullName}),c.kind===`ping`?jsonOk({ok:!0}):c.kind===`issue_comment`&&c.action===`created`?(a(dispatchIssueComment({botName:t,config:e,event:c,handler:e.onComment??((e,t)=>defaultOnComment(e,t,n)),from:i})),jsonOk({ok:!0})):c.kind===`pull_request_review_comment`&&c.action===`created`?(a(dispatchPullRequestReviewComment({botName:t,config:e,event:c,handler:e.onComment??((e,t)=>defaultOnComment(e,t,n)),from:i})),jsonOk({ok:!0})):c.kind===`issues`&&e.onIssue!==void 0?(a(dispatchIssue({botName:t,config:e,event:c,handler:e.onIssue,from:i})),jsonOk({ok:!0})):c.kind===`pull_request`&&e.onPullRequest!==void 0?(a(dispatchPullRequest({botName:t,config:e,event:c,handler:e.onPullRequest,from:i})),jsonOk({ok:!0})):c.kind===`check_suite`&&e.onCheckSuite!==void 0?(a(dispatchCheckSuite({botName:t,config:e,event:c,handler:e.onCheckSuite,from:i})),jsonOk({ok:!0})):c.kind===`check_run`&&e.onCheckRun!==void 0?(a(dispatchCheckRun({botName:t,config:e,event:c,handler:e.onCheckRun,from:i})),jsonOk({ok:!0})):c.kind===`workflow_run`&&e.onWorkflowRun!==void 0?(a(dispatchWorkflowRun({botName:t,config:e,event:c,handler:e.onWorkflowRun,from:i})),jsonOk({ok:!0})):jsonOk({ignored:!0,ok:!0}))})],async receive(t,{from:
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{createGitHubBotNameResolver}from"#public/channels/github/auth.js";import{getGitHubRepository}from"#public/channels/github/api.js";import{parseGitHubWebhookEvent}from"#public/channels/github/inbound.js";import{buildGitHubBinding}from"#public/channels/github/binding.js";import{continuationTokenFromState,conversationFromState,initialGitHubState,stateFromReceiveTarget}from"#public/channels/github/state.js";import{GITHUB_CHANNEL_DEFAULT_ROUTE}from"#public/channels/github/constants.js";import{createDefaultEvents,defaultOnComment}from"#public/channels/github/defaults.js";import{dispatchCheckRun,dispatchCheckSuite,dispatchIssue,dispatchIssueComment,dispatchPullRequest,dispatchPullRequestReviewComment,dispatchWorkflowRun}from"#public/channels/github/dispatch.js";import{verifyGitHubRequest}from"#public/channels/github/verify.js";const log=createLogger(`github.channel`);function githubChannel(e={}){let t=createGitHubBotNameResolver({botName:e.botName,credentials:e.credentials}),n={botName:t},r={...createDefaultEvents({api:e.api,botName:t,credentials:e.credentials,progress:e.progress}),...e.events};return defineChannel({turnPolicy:e.turnPolicy,state:initialGitHubState(),context(t,n){return rebuildGitHubContext(t,n,e)},routes:[POST(e.route??GITHUB_CHANNEL_DEFAULT_ROUTE,async(r,{from:i,waitUntil:a})=>{let o=await verifyInbound(r,e.credentials);if(o===null)return new Response(`unauthorized`,{status:401});let s=missingGitHubWebhookHeaders(r.headers),c;try{c=parseGitHubWebhookEvent({body:o,contentType:r.headers.get(`content-type`)??void 0,headers:r.headers})}catch(e){return log.warn(`inbound GitHub body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return c===null?(s.length>0&&log.warn(`GitHub webhook ignored because standard headers were missing`,{missingHeaders:s}),jsonOk({ignored:!0,ok:!0})):(s.length>0&&log.warn(`GitHub webhook missing standard headers; inferred metadata from payload`,{deliveryId:c.delivery.id,event:c.delivery.event,missingHeaders:s,repository:c.repository.fullName}),c.kind===`ping`?jsonOk({ok:!0}):c.kind===`issue_comment`&&c.action===`created`?(a(dispatchIssueComment({botName:t,config:e,event:c,handler:e.onComment??((e,t)=>defaultOnComment(e,t,n)),from:i})),jsonOk({ok:!0})):c.kind===`pull_request_review_comment`&&c.action===`created`?(a(dispatchPullRequestReviewComment({botName:t,config:e,event:c,handler:e.onComment??((e,t)=>defaultOnComment(e,t,n)),from:i})),jsonOk({ok:!0})):c.kind===`issues`&&e.onIssue!==void 0?(a(dispatchIssue({botName:t,config:e,event:c,handler:e.onIssue,from:i})),jsonOk({ok:!0})):c.kind===`pull_request`&&e.onPullRequest!==void 0?(a(dispatchPullRequest({botName:t,config:e,event:c,handler:e.onPullRequest,from:i})),jsonOk({ok:!0})):c.kind===`check_suite`&&e.onCheckSuite!==void 0?(a(dispatchCheckSuite({botName:t,config:e,event:c,handler:e.onCheckSuite,from:i})),jsonOk({ok:!0})):c.kind===`check_run`&&e.onCheckRun!==void 0?(a(dispatchCheckRun({botName:t,config:e,event:c,handler:e.onCheckRun,from:i})),jsonOk({ok:!0})):c.kind===`workflow_run`&&e.onWorkflowRun!==void 0?(a(dispatchWorkflowRun({botName:t,config:e,event:c,handler:e.onWorkflowRun,from:i})),jsonOk({ok:!0})):jsonOk({ignored:!0,ok:!0}))})],async receive({message:t,target:n,...r},{from:i}){let a=n,o=readNonEmptyString(a.owner),s=readNonEmptyString(a.repo);if(o===void 0||s===void 0)throw Error(`githubChannel().receive requires target.owner and target.repo.`);if([a.issueNumber!==void 0,a.pullRequestNumber!==void 0].filter(Boolean).length!==1)throw Error(`githubChannel().receive requires exactly one of issueNumber or pullRequestNumber.`);let c=a.repositoryId??(await getGitHubRepository({api:e.api,credentials:e.credentials,installationId:a.installationId,owner:o,repo:s})).id,l=stateFromReceiveTarget({target:a,owner:o,repo:s,repositoryId:c});if(a.initialMessage!==void 0){let{thread:t}=buildGitHubBinding({config:e,state:l});await t.post(a.initialMessage)}return i(continuationTokenFromState(l)).send(t,{...r,state:l})},events:r})}function rebuildGitHubContext(e,t,n){let r=buildGitHubBinding({config:n,state:e});return{conversation:conversationFromState(e),github:r.github,repository:r.github.repository,state:e,thread:r.thread}}async function verifyInbound(e,t){try{return await verifyGitHubRequest(e,{webhookSecret:t?.webhookSecret,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`github inbound verification failed`,{error:e}),null}}function missingGitHubWebhookHeaders(e){return[`x-github-event`,`x-github-delivery`].filter(t=>{let n=e.get(t);return n===null||n.trim().length===0})}function jsonOk(e){return new Response(JSON.stringify(e),{headers:{"content-type":`application/json; charset=utf-8`},status:200})}export{githubChannel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{isObject,readNonEmptyString}from"#shared/guards.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{createLinearAgentActivity,createLinearAgentSessionOnComment,createLinearAgentSessionOnIssue,listLinearAgentSessionActivities,updateLinearAgentSession}from"#public/channels/linear/api.js";import{createDefaultEvents,defaultOnAgentSession}from"#public/channels/linear/defaults.js";import{formatLinearContextBlock,linearContinuationToken,messageFromLinearAgentSessionEvent,parseLinearWebhookEvent}from"#public/channels/linear/inbound.js";import{LINEAR_CHANNEL_DEFAULT_ROUTE}from"#public/channels/linear/constants.js";import{attachLinearInboundUploads}from"#public/channels/linear/inbound-uploads.js";import{verifyLinearRequest}from"#public/channels/linear/verify.js";const log=createLogger(`linear.channel`);function linearChannel(e={}){let t=e.onAgentSession??defaultOnAgentSession,n={...createDefaultEvents({api:e.api,credentials:e.credentials}),...e.events};return defineChannel({turnPolicy:e.turnPolicy,state:initialLinearState(),metadata(e){return{agentSessionId:e.agentSessionId,commentId:e.commentId??null,issueId:e.issueId??null,issueIdentifier:e.issueIdentifier??null,organizationId:e.organizationId??null}},context(t,n){return rebuildLinearContext(t,n,e)},routes:[POST(e.route??LINEAR_CHANNEL_DEFAULT_ROUTE,async(n,{from:r,waitUntil:i})=>{let a=await verifyInbound(n,e.credentials,e.maxSkewMs);if(a===null)return new Response(`unauthorized`,{status:401});let o;try{o=parseLinearWebhookEvent({body:a,headers:n.headers})}catch(e){return log.warn(`inbound Linear body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return o===null?jsonOk({ignored:!0,ok:!0}):o.kind===`agent_session`?(i(dispatchAgentSession({config:e,event:o,from:r,onAgentSession:t})),jsonOk({ok:!0})):e.onDataWebhook===void 0?jsonOk({ignored:!0,ok:!0}):(i(Promise.resolve(e.onDataWebhook(o))),jsonOk({ok:!0}))})],async receive(t,{from:
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{isObject,readNonEmptyString}from"#shared/guards.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{createLinearAgentActivity,createLinearAgentSessionOnComment,createLinearAgentSessionOnIssue,listLinearAgentSessionActivities,updateLinearAgentSession}from"#public/channels/linear/api.js";import{createDefaultEvents,defaultOnAgentSession}from"#public/channels/linear/defaults.js";import{formatLinearContextBlock,linearContinuationToken,messageFromLinearAgentSessionEvent,parseLinearWebhookEvent}from"#public/channels/linear/inbound.js";import{LINEAR_CHANNEL_DEFAULT_ROUTE}from"#public/channels/linear/constants.js";import{attachLinearInboundUploads}from"#public/channels/linear/inbound-uploads.js";import{verifyLinearRequest}from"#public/channels/linear/verify.js";const log=createLogger(`linear.channel`);function linearChannel(e={}){let t=e.onAgentSession??defaultOnAgentSession,n={...createDefaultEvents({api:e.api,credentials:e.credentials}),...e.events};return defineChannel({turnPolicy:e.turnPolicy,state:initialLinearState(),metadata(e){return{agentSessionId:e.agentSessionId,commentId:e.commentId??null,issueId:e.issueId??null,issueIdentifier:e.issueIdentifier??null,organizationId:e.organizationId??null}},context(t,n){return rebuildLinearContext(t,n,e)},routes:[POST(e.route??LINEAR_CHANNEL_DEFAULT_ROUTE,async(n,{from:r,waitUntil:i})=>{let a=await verifyInbound(n,e.credentials,e.maxSkewMs);if(a===null)return new Response(`unauthorized`,{status:401});let o;try{o=parseLinearWebhookEvent({body:a,headers:n.headers})}catch(e){return log.warn(`inbound Linear body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return o===null?jsonOk({ignored:!0,ok:!0}):o.kind===`agent_session`?(i(dispatchAgentSession({config:e,event:o,from:r,onAgentSession:t})),jsonOk({ok:!0})):e.onDataWebhook===void 0?jsonOk({ignored:!0,ok:!0}):(i(Promise.resolve(e.onDataWebhook(o))),jsonOk({ok:!0}))})],async receive({message:t,target:n,...r},{from:i}){let a=n,o=await resolveReceiveSession(a,e),s=readNonEmptyString(a.initialActivity);return s!==void 0&&await createLinearAgentActivity({api:e.api,credentials:e.credentials,activity:{agentSessionId:o.id,content:{body:s,type:`thought`}}}),i(linearContinuationToken({agentSessionId:o.id})).send(t,{...r,state:stateFromAgentSession(o)})},events:n})}function rebuildLinearContext(e,t,n){return{linear:buildLinearHandle({agentSessionId:e.agentSessionId??``,config:n}),state:e}}function buildLinearHandle(e){return{agentSessionId:e.agentSessionId,createActivity(t,n){return createLinearAgentActivity({api:e.config.api,credentials:e.config.credentials,activity:{agentSessionId:e.agentSessionId,content:t,ephemeral:n?.ephemeral,signal:n?.signal,signalMetadata:n?.signalMetadata}})},listActivities(t){return listLinearAgentSessionActivities({api:e.config.api,credentials:e.config.credentials,agentSessionId:e.agentSessionId,last:t?.last})},updateSession(t){return updateLinearAgentSession({api:e.config.api,credentials:e.config.credentials,id:e.agentSessionId,update:t})}}}async function dispatchAgentSession(e){let{event:t}=e,n={delivery:t.delivery,linear:buildLinearHandle({agentSessionId:t.agentSession.id,config:e.config}),session:t.agentSession},r=await e.onAgentSession(n,t);if(r===null)return;let i=await attachLinearInboundUploads({content:messageFromLinearAgentSessionEvent(t),credentials:e.config.credentials,fetch:e.config.api?.fetch});await e.from(linearContinuationToken({agentSessionId:t.agentSession.id})).send(i,{auth:r.auth,context:[formatLinearContextBlock(t),...t.previousComments,...r.context??[]],history:r.history,state:stateFromAgentSession(t.agentSession),title:r.title})}async function resolveReceiveSession(e,t){if(hasString(e,`agentSessionId`))return{id:e.agentSessionId};if(hasString(e,`issueId`))return createLinearAgentSessionOnIssue({api:t.api,credentials:t.credentials,externalLink:readNonEmptyString(e.externalLink),externalUrls:readExternalUrls(e.externalUrls),issueId:e.issueId});if(hasString(e,`commentId`))return createLinearAgentSessionOnComment({api:t.api,credentials:t.credentials,commentId:e.commentId,externalLink:readNonEmptyString(e.externalLink),externalUrls:readExternalUrls(e.externalUrls)});throw Error(`linearChannel().receive requires target.agentSessionId, issueId, or commentId.`)}function stateFromAgentSession(e){return{agentSessionId:e.id,agentSessionUrl:e.url??null,commentId:e.commentId??null,issueId:e.issueId??e.issue?.id??null,issueIdentifier:e.issue?.identifier??null,issueTitle:e.issue?.title??null,issueUrl:e.issue?.url??null,organizationId:`organizationId`in e?e.organizationId??null:null,pendingToolCallMessage:null,sourceCommentId:e.sourceCommentId??null}}function initialLinearState(){return{agentSessionId:null,agentSessionUrl:null,commentId:null,issueId:null,issueIdentifier:null,issueTitle:null,issueUrl:null,organizationId:null,pendingToolCallMessage:null,sourceCommentId:null}}async function verifyInbound(e,t,n){try{return await verifyLinearRequest(e,{maxSkewMs:n,webhookSecret:t?.webhookSecret,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`linear inbound verification failed`,{error:e}),null}}function hasString(e,t){return typeof e[t]==`string`&&e[t].length>0}function readExternalUrls(e){if(!Array.isArray(e))return;let t=e.filter(e=>isObject(e)&&typeof e.label==`string`&&typeof e.url==`string`);return t.length>0?t:void 0}function jsonOk(e){return new Response(JSON.stringify(e),{headers:{"content-type":`application/json; charset=utf-8`},status:200})}export{linearChannel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DEFAULT_UPLOAD_POLICY}from"#public/channels/upload-policy.js";import{
|
|
1
|
+
import{DEFAULT_UPLOAD_POLICY}from"#public/channels/upload-policy.js";import{ResponseTooLargeError}from"#execution/public-destination.js";import{requestPublicUrl}from"#execution/web-fetch/request.js";import{overLimit}from"#internal/attachments/limited-read.js";import{fetchMessageBestEffort}from"#public/channels/chat-sdk/fetch-message.js";import{messageContentOf}from"#public/channels/chat-sdk/index.js";function linqInboundContent(e){let t=messageContentOf(e);return typeof t==`string`?t.trim().length>0?t:void 0:t.length>0?t:void 0}async function linqQuotedMessage(e,t){let n=t.raw?.reply_to?.message_id;if(typeof n!=`string`||n.length===0)return;let r=await fetchMessageBestEffort(e,t.threadId,n);return r===null?{id:n}:{fromAgent:r.author.isMe,id:n,text:r.text}}function rehydrateLinqAttachment(e){let{url:t}=e;return t?{...e,async fetchData(){try{let e=await requestPublicUrl(t,{headers:{},maxResponseSize:DEFAULT_UPLOAD_POLICY.maxBytes,signal:AbortSignal.timeout(3e4)});if(!e.ok)throw Error(`Linq CDN returned HTTP ${e.status}.`);return Buffer.from(await e.arrayBuffer())}catch(e){throw e instanceof ResponseTooLargeError?overLimit(DEFAULT_UPLOAD_POLICY.maxBytes,`linq`):e}}}:e}export{linqInboundContent,linqQuotedMessage,rehydrateLinqAttachment};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { SlackChannelConfig, SlackAnswerResult, SlackAnswerSubmission } from "#public/channels/slack/slackChannel.js";
|
|
1
|
+
import type { SlackChannelConfig, SlackAnswerResult, SlackAnswerSubmission, SlackSessionTarget } from "#public/channels/slack/slackChannel.js";
|
|
2
2
|
import type { SlackTransportOptions } from "#public/channels/slack/transport.js";
|
|
3
3
|
export declare function authorizeAnswer(input: {
|
|
4
|
-
readonly channelId: string;
|
|
5
4
|
readonly deps: {
|
|
6
5
|
readonly api: SlackTransportOptions | undefined;
|
|
7
6
|
readonly config: SlackChannelConfig;
|
|
@@ -9,6 +8,6 @@ export declare function authorizeAnswer(input: {
|
|
|
9
8
|
};
|
|
10
9
|
readonly installationTeamId: string | null | undefined;
|
|
11
10
|
readonly submission: SlackAnswerSubmission;
|
|
11
|
+
readonly target: SlackSessionTarget;
|
|
12
12
|
readonly teamId: string | null | undefined;
|
|
13
|
-
readonly threadTs: string;
|
|
14
13
|
}): Promise<SlackAnswerResult>;
|