eve 0.16.0 → 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/src/channel/compiled-channel.d.ts +2 -0
  3. package/dist/src/channel/cors.d.ts +43 -0
  4. package/dist/src/channel/cors.js +1 -0
  5. package/dist/src/cli/dev/tui/agent-info-probe.d.ts +16 -0
  6. package/dist/src/cli/dev/tui/agent-info-probe.js +1 -0
  7. package/dist/src/cli/dev/tui/mcp-connection-status.d.ts +19 -0
  8. package/dist/src/cli/dev/tui/mcp-connection-status.js +1 -0
  9. package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
  10. package/dist/src/cli/dev/tui/remote-connection-probe.js +1 -1
  11. package/dist/src/cli/dev/tui/runner.d.ts +4 -0
  12. package/dist/src/cli/dev/tui/runner.js +1 -1
  13. package/dist/src/cli/dev/tui/setup-commands.d.ts +1 -0
  14. package/dist/src/cli/dev/tui/setup-commands.js +1 -1
  15. package/dist/src/cli/dev/tui/setup-panel.js +1 -1
  16. package/dist/src/cli/dev/tui/tui.js +1 -1
  17. package/dist/src/compiler/manifest.d.ts +8 -2
  18. package/dist/src/compiler/manifest.js +1 -1
  19. package/dist/src/compiler/normalize-channel.js +1 -1
  20. package/dist/src/context/providers/connection-key.d.ts +9 -0
  21. package/dist/src/context/providers/connection-key.js +1 -0
  22. package/dist/src/context/providers/connection.d.ts +1 -9
  23. package/dist/src/context/providers/connection.js +1 -1
  24. package/dist/src/harness/input-requests.d.ts +1 -0
  25. package/dist/src/harness/input-requests.js +1 -1
  26. package/dist/src/harness/tool-loop.js +1 -1
  27. package/dist/src/internal/application/package.js +1 -1
  28. package/dist/src/internal/nitro/host/channel-routes.d.ts +2 -0
  29. package/dist/src/internal/nitro/host/channel-routes.js +5 -3
  30. package/dist/src/internal/nitro/host/start-development-server.js +2 -2
  31. package/dist/src/internal/workflow/runtime.js +1 -1
  32. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  33. package/dist/src/public/channels/eve.d.ts +31 -0
  34. package/dist/src/public/channels/eve.js +1 -1
  35. package/dist/src/public/channels/github/githubChannel.js +1 -1
  36. package/dist/src/public/channels/github/inbound-types.d.ts +189 -0
  37. package/dist/src/public/channels/github/inbound-types.js +1 -0
  38. package/dist/src/public/channels/github/inbound.d.ts +2 -190
  39. package/dist/src/public/channels/github/inbound.js +2 -2
  40. package/dist/src/public/channels/index.d.ts +1 -1
  41. package/dist/src/public/definitions/defineChannel.d.ts +10 -0
  42. package/dist/src/public/definitions/defineChannel.js +1 -1
  43. package/dist/src/runtime/connections/scoped-authorization.d.ts +9 -0
  44. package/dist/src/runtime/connections/scoped-authorization.js +1 -1
  45. package/dist/src/runtime/connections/types.d.ts +4 -4
  46. package/dist/src/runtime/framework-channels/index.js +1 -1
  47. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
  48. package/dist/src/runtime/framework-tools/index.d.ts +1 -1
  49. package/dist/src/runtime/framework-tools/index.js +1 -1
  50. package/dist/src/runtime/framework-tools/skill.js +1 -1
  51. package/dist/src/runtime/resolve-channel.js +1 -1
  52. package/dist/src/runtime/types.d.ts +2 -0
  53. package/dist/src/setup/boxes/select-connections.js +1 -1
  54. package/dist/src/setup/cli/option-row.d.ts +2 -0
  55. package/dist/src/setup/cli/option-row.js +1 -1
  56. package/dist/src/setup/flows/connections.d.ts +1 -0
  57. package/dist/src/setup/flows/connections.js +2 -2
  58. package/dist/src/setup/scaffold/create/project.js +1 -1
  59. package/docs/channels/custom.mdx +19 -0
  60. package/docs/channels/eve.mdx +23 -0
  61. package/docs/concepts/sessions-runs-and-streaming.md +2 -0
  62. package/docs/connections/mcp.mdx +161 -19
  63. package/docs/connections/openapi.mdx +133 -36
  64. package/docs/connections/overview.mdx +4 -4
  65. package/docs/patterns/multi-tenant-approvals.md +4 -0
  66. package/docs/patterns/multi-tenant-auth.md +156 -37
  67. package/docs/tools/human-in-the-loop.md +3 -1
  68. package/package.json +1 -1
@@ -1 +1 @@
1
- import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{isScheduleAppAuth}from"#channel/schedule-auth.js";import{AuthKey,ParentSessionKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{EmptyModelResponseError,classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,isNoOutputGeneratedError,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError}from"#harness/model-call-error.js";import{toErrorMessage}from"#shared/errors.js";import{createActionResultEvent,createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent,createResultCompletedEvent}from"#protocol/message.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{contextStorage}from"#context/container.js";import{ToolLoopAgent,isStepCount}from"ai";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{clearPendingWorkflowInterrupt,getPendingWorkflowInterrupt,setPendingWorkflowInterrupt}from"#harness/workflow-interrupt-state.js";import{getWorkflowRuntimeActionInterrupts,isWorkflowRuntimeActionInterrupt}from"#harness/workflow-runtime-action-state.js";import{isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{resolveAssistantStepText}from"#harness/messages.js";import{buildDynamicInstructionMessages}from"#context/dynamic-instruction-lifecycle.js";import{PendingSkillAnnouncementKey}from"#context/dynamic-skill-lifecycle.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{CONDITIONAL_DELIVERY_INSTRUCTION,EMPTY_DELIVERY_SENTINEL,hasEmptyDeliverySentinel}from"#shared/empty-delivery.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{ASK_QUESTION_TOOL_NAME}from"#runtime/framework-tools/ask-question.js";import{extractQuestionInputRequests,extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker}from"#harness/prompt-cache.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{applyWorkflowTool,buildWorkflowHostTools}from"#harness/workflow-sandbox.js";import{ensureWorkflowContinuationSecurity,getWorkflowContinuationSecurity}from"#harness/workflow-continuation-security.js";import{createWorkflowLifecycle}from"#harness/workflow-lifecycle.js";import{compactMessages,getInputTokenCount,resolveCompactionModel,shouldCompact}from"#harness/compaction.js";import{accumulateTurnUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{setEveAttributes}from"#runtime/attributes/emit.js";import{buildTelemetryRuntimeContext}from"#harness/instrumentation-runtime-context.js";import{getInstrumentationConfig}from"#harness/instrumentation-config.js";import{normalizeProviderToolHistory}from"#harness/provider-tool-history.js";import{extractWorkflowStreamWriteErrorDetails}from"#harness/workflow-stream-error.js";import{ensureOtelIntegration}from"#harness/otel-integration.js";import{resolveFrameworkToolFromUpstreamType}from"#harness/provider-tools.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{buildToolApproval,buildToolSetFromDefinitions,buildToolSetWithProviderTools}from"#harness/tools.js";import{continueWorkflowSandboxInterrupt,getWorkflowSandboxInterrupt,unwrapWorkflowSandboxResult}from"#shared/workflow-sandbox.js";import{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool}from"#runtime/framework-tools/final-output.js";const environment=process.env.NODE_ENV??`unknown`,eveVersion=resolveInstalledPackageInfo().version,log=createLogger(`harness.tool-loop`);function logToolExecutionError(e){e.toolOutput.type===`tool-error`&&logError(log,`tool execution failed`,e.toolOutput.error,{toolName:e.toolCall.toolName,toolCallId:e.toolCall.toolCallId})}function enrichTelemetry(e,t,n){if(e===void 0)return;let r={};for(let e of Object.keys(n??{}))r[e]=!0;return{functionId:e.functionId??t,includeRuntimeContext:r,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function buildGatewayAttributionHeaders(e,t){if(typeof e!=`string`)return;let n=t?.agentName??t?.agentId,r=process.env.VERCEL_PROJECT_PRODUCTION_URL||process.env.VERCEL_URL,i=r?`https://${r}`:void 0;if(!n&&!i)return;let a={};return n&&(a[`x-title`]=n),i&&(a[`http-referer`]=i),a}const TURN_TRACE_STATE_KEY=`eve.harness.turnTrace`;function getTurnTraceState(e){return e.state?.[TURN_TRACE_STATE_KEY]}function setTurnTraceState(e,t){let n={traceId:t.traceId,spanId:t.spanId,traceFlags:t.traceFlags};return{...e,state:{...e.state,[TURN_TRACE_STATE_KEY]:n}}}function resolveStepOtelContext(e,t,n){if(t)return trace.setSpan(context.active(),t);if(e){let e=getTurnTraceState(n);if(e){let t=trace.wrapSpanContext({traceId:e.traceId,spanId:e.spanId,traceFlags:e.traceFlags});return trace.setSpan(context.active(),t)}}}function createToolLoopHarness(t){let n=t.handleEvent,c=getInstrumentationConfig();c!==void 0&&ensureOtelIntegration();let f=c===void 0?void 0:trace.getTracer(`eve`),p=t.runtimeIdentity?.agentName;async function runStep(e,t){let n;if(f&&hasStepInput(t)){let t=c?.functionId??p,r={"eve.version":eveVersion,"eve.environment":environment,"eve.session.id":e.sessionId};t&&(r[`ai.telemetry.functionId`]=t),n=f.startSpan(`ai.eve.turn`,{attributes:r})}let r=resolveStepOtelContext(f,n,e),executeStep=()=>executeStepBody(e,t,n);try{return r?await context.with(r,executeStep):await executeStep()}finally{n?.end()}}async function executeStepBody(f,v,y){let b=f;y&&(b=setTurnTraceState(b,y.spanContext()));let x=getHarnessEmissionState(b.state),S=consumeDeferredStepInput({input:v,session:b});b=S.session;let D=await resolvePendingRuntimeActions({emit:n,session:b,stepInput:S.input});if(D.outcome===`unresolved`)return{next:null,session:D.session};b=D.session;let O=resolvePendingInput({history:D.messages,resolveApprovalKey:resolveApprovalKeyFromTools(t.tools),session:b,stepInput:S.input});if(O.outcome===`unresolved`)return{next:null,session:O.session};if(n&&O.rejectedActions)for(let e of O.rejectedActions.results)await n(createActionResultEvent({rejected:!0,result:e,sequence:O.rejectedActions.event.sequence,stepIndex:O.rejectedActions.event.stepIndex,turnId:O.rejectedActions.event.turnId}));n&&hasStepInput(v)&&(x=await emitTurnPreamble(n,v??{},x,t.runtimeIdentity),b=setHarnessEmissionState(b,x),y&&y.setAttribute(`eve.turn.id`,x.turnId)),b=O.session,t.workflow===!0&&(b=ensureWorkflowContinuationSecurity(b));let k=O.messages;if(S.input?.context!==void 0)for(let e of S.input.context)k.push({content:e,role:`user`});if(S.input?.message!==void 0&&!O.deferredMessage){let e=await stageAttachmentsToSandbox(S.input.message);k.push({content:e,role:`user`})}let A=await t.resolveModel(b.agent.modelReference),j=detectPromptCachePath(A),M=j.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,N=buildGatewayAttributionHeaders(A,t.runtimeIdentity);({messages:k,session:b}=await maybeCompact({emit:n,emissionState:x,headers:N,messages:k,model:A,onCompaction:t.onCompaction,resolveModel:t.resolveModel,session:b,telemetry:enrichTelemetry(c,p)??void 0}));let P=getApprovedTools(b),F=contextStorage.getStore(),I=b.outputSchema===void 0&&F!==void 0&&isScheduleAppAuth(F.get(AuthKey))&&F.get(ParentSessionKey)===void 0,L=await hydrateSandboxAttachments(k),R=[],z=[];for(let e of L)e.role===`system`?R.push(e):z.push(e);if(F!==void 0){R.push(...buildDynamicInstructionMessages(F));let e=F.get(PendingSkillAnnouncementKey);e!==void 0&&e.length>0&&R.push({role:`system`,content:e})}I&&R.push({role:`system`,content:CONDITIONAL_DELIVERY_INSTRUCTION});let B=z,prepareModelCallInput=e=>{let t=e?[{role:`system`,content:e}]:[],n=b.agent.system?[{role:`system`,content:b.agent.system}]:[],r=R.length>0||t.length>0?[...t,...n,...R]:void 0,i=r!==void 0&&M?applySystemCacheBreakpoint(r,M):r??b.agent.system??void 0;return{instructions:i,telemetryRuntimeContext:buildTelemetryRuntimeContext({eveVersion,authored:c,emissionState:x,environment,modelInput:{instructions:i,messages:B},session:b})}},runOneModelCall=async e=>{let{instructions:i,telemetryRuntimeContext:a={}}=e.preparedInput??prepareModelCallInput(e.extraSystemNote);e.retryReason&&(a[`eve.retry.reason`]=e.retryReason);let o=e.trailingUserNote?[...B,{role:`user`,content:e.trailingUserNote}]:B,s=await buildToolSetWithProviderTools({approvedTools:P,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,modelReference:b.agent.modelReference,tools:t.tools});if(F!==void 0){let n=buildDynamicTools(F),r=buildToolSetFromDefinitions({approvedTools:P,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,tools:n});for(let[e,t]of Object.entries(r))s[e]=t}b.outputSchema!==void 0&&(s[FINAL_OUTPUT_TOOL_NAME]=buildFinalOutputTool(b.outputSchema));let u=t.workflow===!0?(await applyWorkflowTool({continuationSecurity:getWorkflowContinuationSecurity(b),harnessTools:t.tools,lifecycle:n===void 0?void 0:createWorkflowLifecycle({emit:n,emissionState:x,tools:t.tools}),tools:s})).modelTools:s,d=M?applyLastToolCacheBreakpoint(u,M):u,f=buildStepHooks({cachePath:j,emit:n,emissionState:x,emitStepStarted:e.suppressStepStartedEmission!==!0,marker:M,session:b}),h=new ToolLoopAgent({headers:N,instructions:i,model:A,onToolExecutionEnd:logToolExecutionError,onError(e){summarizeKnownModelCallConfigError(e.error)===null&&logError(log,`tool-loop stream error`,e.error)},onStepFinish:f.onStepFinish,prepareStep:f.prepareStep,reasoning:b.agent.reasoning,runtimeContext:a,stopWhen:isStepCount(1),telemetry:enrichTelemetry(c,p,a),toolApproval:buildToolApproval(u),tools:d}),executeModelCall=async()=>{if(n){let e=new Set([ASK_QUESTION_TOOL_NAME,FINAL_OUTPUT_TOOL_NAME]),r=await h.stream({messages:o}),{emittedActionCallIds:i,handledInlineToolResultCallIds:a,inlineAuthorizationResults:s,inlineToolResultParts:c}=await emitStreamContent(n,x,r.fullStream,{excludedActionToolNames:e,tools:t.tools}),u=await f.stepResult;if(isEmptyModelResponse(u)&&c.length===0&&s.length===0)throw new EmptyModelResponseError;if(await emitStepActions(n,x,u,{emittedActionCallIds:i,excludedActionToolNames:e,handledInlineToolResultCallIds:a,tools:t.tools}),c.length>0||s.length>0){let e=u.toolResults,t=new Map(e.map(e=>[e.toolCallId,e]));for(let e of s)t.set(e.toolCallId,e);return{content:u.content,finishReason:u.finishReason,response:{...u.response,...c.length>0?{messages:[{role:`tool`,content:[...c]},...u.response.messages]}:{}},text:u.text,toolCalls:u.toolCalls,toolResults:[...t.values()],usage:u.usage}}return u}await h.generate({messages:o});let e=await f.stepResult;if(isEmptyModelResponse(e))throw new EmptyModelResponseError;return e};return runModelCallWithRetries(()=>executeModelCall().catch(rethrowNoOutputAsEmptyResponse),{sessionId:b.sessionId,turnId:x.turnId})},V=prepareModelCallInput();n&&await emitStepStarted(n,x,k);let H=await continuePendingWorkflowInterrupt({childResults:S.input?.runtimeActionResults,config:t,emit:n,emissionState:x,runStep,session:b});if(H!==null)return H;let U;try{U=await runOneModelCall({preparedInput:V,suppressStepStartedEmission:!0})}catch(r){let a=await runModelCallRecoveryPipeline({error:r,stages:[e=>attemptUnsupportedProviderToolRecovery({error:e.error,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId}),e=>attemptEmptyResponseRecovery({emptyDeliveryEnabled:I,error:e.error,retryCallOptions:e.retryCallOptions,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId})]});if(a.outcome===`recovered`)U=a.result;else{let r=a.error;if(y&&recordErrorOnSpan(y,r),!n)throw r;let o=extractWorkflowStreamWriteErrorDetails(r);if(o!==null){let t=createErrorId();return log.error(`workflow stream write failed — parking session for retry by the user`,{...o,errorId:t,error:r,sessionId:b.sessionId,turnId:x.turnId}),x=await emitRecoverableFailedTurn(n,x,{code:`WORKFLOW_STREAM_WRITE_FAILED`,details:{...o,errorId:t},message:toErrorMessage(r)}),{next:null,session:setHarnessEmissionState(b,x)}}let s=classifyModelCallError(r),c=createErrorId(),l=s===`terminal`?summarizeKnownModelCallConfigError(r):null,f=l===null?summarizeKnownModelCallRequestError(r):null,p=l?.message??f?.message??toErrorMessage(r),_=extractModelCallErrorDetails(r),v=buildModelCallFailureDetails({configSummary:l,error:r,errorId:c,modelCallDetails:_,requestSummary:f}),S=buildModelCallFailureLogFields({error:r,errorId:c,modelCallDetails:_,requestSummary:f,sessionId:b.sessionId,turnId:x.turnId});return s===`terminal`?(l===null?log.error(f?.message??`model call failed terminally`,S):log.error(`${l.name}: ${l.message}`,{errorId:c,sessionId:b.sessionId,turnId:x.turnId}),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:{done:!0,output:``},session:b}):t.mode===`task`?(log.error(f?.message??`model call failed; failing the task run`,S),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:{done:!0,isError:!0,output:p},session:b}):(log.error(f?.message??`model call failed — parking session for retry by the user`,S),x=await emitRecoverableFailedTurn(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p}),{next:null,session:setHarnessEmissionState(b,x)})}}let W=accumulateTurnUsage({previous:getTurnUsageState(b.state),turnId:x.turnId,usage:U.usage??{}});b=setTurnUsageState(b,W);let G;try{G=formatLanguageModelGatewayId(A)}catch{G=void 0}return await setEveAttributes({"$eve.model":G,"$eve.input_tokens":W.inputTokens,"$eve.output_tokens":W.outputTokens,"$eve.cache_read_tokens":W.cacheReadTokens,"$eve.cache_write_tokens":W.cacheWriteTokens,"$eve.tool_count":t.tools.size}),handleStepResult({config:t,emit:n,emissionState:x,promptMessages:k,result:U,runStep,session:b})}return runStep}function buildModelCallFailureDetails(e){let{configSummary:t,error:r,errorId:i,modelCallDetails:a,requestSummary:o}=e;return t===null?o===null?{...formatError(r,i),...a}:{errorId:i,message:toErrorMessage(r),name:o.name,...a}:{errorId:i,message:t.message,name:t.name,...a}}function buildModelCallFailureLogFields(e){let t={errorId:e.errorId,sessionId:e.sessionId,turnId:e.turnId};return e.requestSummary===null?{...t,error:e.error}:{...t,details:e.modelCallDetails}}async function runModelCallRecoveryPipeline(e){let t=e.error,n;for(let r of e.stages){let e=await r({error:t,retryCallOptions:n});if(e.outcome===`recovered`)return e;e.outcome===`failed`&&(t=e.error,n=e.retryCallOptions)}return{outcome:`failed`,error:t}}async function attemptUnsupportedProviderToolRecovery(e){let t=extractUnsupportedProviderToolTypes(e.error);if(t.length===0)return{outcome:`skipped`};let n=[];for(let e of t){let t=resolveFrameworkToolFromUpstreamType(e);t!==null&&!n.includes(t)&&n.push(t)}if(n.length===0)return{outcome:`skipped`};log.warn(`disabling unsupported provider tool(s); retrying step once`,{disabled:n,sessionId:e.sessionId,turnId:e.turnId,upstreamTypes:t});let r={disabledProviderTools:new Set(n),extraSystemNote:buildDisabledToolNote(n)};try{return{outcome:`recovered`,result:await e.runOneModelCall({...r,suppressStepStartedEmission:!0})}}catch(e){return{outcome:`failed`,error:e,retryCallOptions:r}}}function buildDisabledToolNote(e){let t=e.join(`, `);return`The following ${e.length===1?`tool is`:`tools are`} not available with the current model and has been removed: ${t}. Proceed using the remaining tools or your training knowledge.`}function isEmptyModelResponse(e){return e.toolCalls.length===0&&e.toolResults.length===0&&resolveAssistantStepText(e.response.messages,e.text)===null}function rethrowNoOutputAsEmptyResponse(e){throw isNoOutputGeneratedError(e)?new EmptyModelResponseError({cause:e}):e}const EMPTY_RESPONSE_NUDGE=`Your previous reply was empty and was not delivered. Answer now from the tool results above; do not re-run tools or mention this notice.`;function buildEmptyResponseNudge(e){return e?`${EMPTY_RESPONSE_NUDGE} If the current task explicitly requires conditional delivery and there is nothing to report, reply with exactly ${EMPTY_DELIVERY_SENTINEL}.`:EMPTY_RESPONSE_NUDGE}async function attemptEmptyResponseRecovery(e){if(!(e.error instanceof EmptyModelResponseError))return{outcome:`skipped`};log.warn(`empty model response; reissuing the model call once`,{sessionId:e.sessionId,turnId:e.turnId});try{return{outcome:`recovered`,result:await e.runOneModelCall({...e.retryCallOptions,retryReason:`empty-response`,suppressStepStartedEmission:!0,trailingUserNote:buildEmptyResponseNudge(e.emptyDeliveryEnabled)})}}catch(t){return{outcome:`failed`,error:t,retryCallOptions:e.retryCallOptions}}}async function handleStepResult(e){let{config:t,emit:n,promptMessages:r,result:i,runStep:a}=e,{emissionState:o,session:s}=e,c=resolveAssistantStepText(i.response.messages,i.text),l=i.finishReason!==`tool-calls`&&i.toolCalls.length===0&&hasEmptyDeliverySentinel(c),u=l?[]:i.response.messages,d=l?null:c,f=new Set;for(let e of[...i.content??[],...i.toolResults??[]])(e.type===`tool-result`||e.type===`tool-error`)&&e.providerExecuted===!0&&f.add(e.toolCallId);let p=normalizeProviderToolHistory({messages:u,providerExecutedOutcomeIds:f}),m=p.messages,h={...s,compaction:createNextCompactionConfig(s.compaction,r,i)};if(t.workflow===!0){let e=await getWorkflowSandboxInterrupt(i,getWorkflowContinuationSecurity(h));if(e!==void 0){if(!isWorkflowRuntimeActionInterrupt(e))throw Error(`Unsupported Workflow interrupt kind "${e.payload.kind}".`);return parkOnWorkflowInterrupt({baseSession:h,emissionState:o,interrupt:e,promptMessages:r,responseMessages:m})}}let g=extractToolApprovalInputRequests({content:i.content??[]}),_=new Set(g.map(e=>e.action.callId)),y=extractQuestionInputRequests({toolCalls:i.toolCalls,excludedCallIds:_}),b=[...g,...y],S=(i.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:t.tools}));if(S.length>0)return{next:null,session:setHarnessEmissionState(setPendingRuntimeActionBatch({actions:S,event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},responseMessages:m,session:{...h,history:[...r]}}),o)};if(b.length>0){let e=setPendingInputBatch({event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},requests:b,responseMessages:m,session:{...h,history:[...r]}});return n&&(await n(createInputRequestedEvent({requests:b,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),t.mode===`conversation`&&(o=await emitTurnEpilogue(n,o,t.mode),e=setHarnessEmissionState(e,o))),{next:null,session:e}}let C=findAuthorizationSignalFromToolResults(i.toolResults);if(C){let{challenges:e}=C;if(n)for(let t of e)await n(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId}));return{next:null,session:setHarnessEmissionState({...h,history:[...r],state:setPendingAuthorization(h.state,{challenges:e})},o)}}let w=m,T=[...r,...w],E={...h,history:T};return!(E.outputSchema!==void 0&&extractFinalOutput(i)!==void 0)&&(w.at(-1)?.role===`tool`||p.outcomeEndsResponse||hasDeferredStepInput(E))?(n&&(o=advanceStep(o),E=setHarnessEmissionState(E,o)),{next:a,session:E}):t.mode===`task`?finishTaskTurn({emissionState:o,emit:n,history:r,result:i,schema:E.outputSchema,session:E,stepOutput:d}):finishConversationTurn({emissionState:o,emit:n,history:r,result:i,schema:E.outputSchema,session:E})}const OUTPUT_SCHEMA_NOT_FULFILLED={code:`OUTPUT_SCHEMA_NOT_FULFILLED`,message:`The agent could not produce a result matching the requested schema.`};function extractFinalOutput(e){return(e.toolCalls??[]).find(e=>e.toolName===FINAL_OUTPUT_TOOL_NAME)?.input}function persistStructuredAssistantTurn(e,t,n){return{...e,history:[...t,{content:JSON.stringify(n),role:`assistant`}],outputSchema:void 0}}async function emitStructuredResult(e,t,n,r){return await e(createResultCompletedEvent({result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),emitTurnEpilogue(e,t,r)}async function finishTaskTurn(e){let{emit:t,history:n,result:r,schema:i,stepOutput:a}=e,{emissionState:o,session:s}=e;if(i===void 0)return t&&(o=await emitTurnEpilogue(t,o,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:a??``},session:s};let c=extractFinalOutput(r);return c===void 0?(t&&await emitFailedStep(t,o,{...OUTPUT_SCHEMA_NOT_FULFILLED,sessionId:s.sessionId}),{next:{done:!0,isError:!0,output:OUTPUT_SCHEMA_NOT_FULFILLED.message},session:s}):(s=persistStructuredAssistantTurn(s,n,c),t&&(o=await emitStructuredResult(t,o,c,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:c},session:s})}async function finishConversationTurn(e){let{emit:t,history:n,result:r,schema:i}=e,{emissionState:a,session:o}=e;if(i===void 0)return t&&(a=await emitTurnEpilogue(t,a,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o};let s=extractFinalOutput(r);return s===void 0?(t&&(a=await emitRecoverableFailedTurn(t,a,OUTPUT_SCHEMA_NOT_FULFILLED),o=setHarnessEmissionState(o,a)),{next:null,session:o}):(o=persistStructuredAssistantTurn(o,n,s),t&&(a=await emitStructuredResult(t,a,s,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o})}async function continuePendingWorkflowInterrupt(e){let t=getPendingWorkflowInterrupt(e.session.state);if(t===void 0)return null;let n=t.interrupt;if(!isWorkflowRuntimeActionInterrupt(n))throw Error(`Unsupported Workflow interrupt kind "${n.payload.kind}".`);let i=e.emit===void 0?void 0:createWorkflowLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools}),a=getWorkflowContinuationSecurity(e.session),o;try{let t=buildWorkflowHostTools({tools:e.config.tools}),r=e.childResults??[],s=n,c=0;for(;;){o=await continueWorkflowSandboxInterrupt({continuationSecurity:a,interrupt:s,lifecycle:i,resolution:r[c]?.output,tools:t});let e=await unwrapWorkflowSandboxResult(o,a);if(e.status!==`interrupted`||!isWorkflowRuntimeActionInterrupt(e.interrupt)||c+1>=r.length)break;let n=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(n===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);c++,s=n}}catch(e){logError(log,`Workflow interrupt continuation failed`,e),o={error:`workflow_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let s=await unwrapWorkflowSandboxResult(o,a),c=s.status===`interrupted`?s.interrupt:s.output,l=replaceWorkflowToolResult([...e.session.history,...t.responseMessages],n.outerToolCallId,c),u=clearPendingWorkflowInterrupt({...e.session,history:l});if(s.status===`interrupted`){if(!isWorkflowRuntimeActionInterrupt(s.interrupt))throw Error(`Unsupported Workflow interrupt kind "${s.interrupt.payload.kind}".`);let t=e.session.history.length,n=l.slice(0,t),r=l.slice(t);return u={...u,history:n},parkOnWorkflowInterrupt({baseSession:u,emissionState:e.emissionState,interrupt:s.interrupt,promptMessages:n,responseMessages:r})}return{next:e.runStep,session:u}}function replaceWorkflowToolResult(e,t,n){if(t===void 0)return[...e];let r=typeof n==`string`?{type:`text`,value:n}:{type:`json`,value:n};return e.map(e=>{if(e.role!==`tool`)return e;let n=e.content.map(e=>e.type!==`tool-result`||e.toolCallId!==t?e:{...e,output:r});return{...e,content:n}})}function parkOnWorkflowInterrupt(e){let t=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(t===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);let n={...e.baseSession,history:[...e.promptMessages]};return{next:null,session:setHarnessEmissionState(setPendingWorkflowInterrupt({interrupt:t,responseMessages:e.responseMessages,session:n}),e.emissionState)}}function createNextCompactionConfig(e,t,n){let r={recentWindowSize:e.recentWindowSize,threshold:e.threshold};return n.usage?.inputTokens!==void 0&&(r.lastKnownInputTokens=n.usage.inputTokens,r.lastKnownPromptMessageCount=t.length),r}async function maybeCompact(e){let{emit:t,emissionState:n}=e,r=e.messages,i=e.session;if(!shouldCompact(r,i.compaction))return{messages:r,session:i};let a=await resolveCompactionModel({compactionModelReference:i.agent.compactionModelReference,model:e.model,modelReference:i.agent.modelReference,resolveModel:e.resolveModel});if(t&&await t(createCompactionRequestedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId,usageInputTokens:getInputTokenCount(r,i.compaction)})),r=await compactMessages(r,a.model,i.compaction,a.providerOptions,e.telemetry,e.headers),e.onCompaction)for(let t of e.onCompaction())r.push(t);return t&&await t(createCompactionCompletedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId})),{messages:r,session:i}}function resolveApprovalKeyFromTools(e){return t=>{let n=e.get(t.action.toolName);if(n?.approvalKey!==void 0)return n.approvalKey(t.action.input)}}async function runModelCallWithRetries(e,t){for(let n=1;;n++)try{return await e()}catch(e){if(n===3||classifyModelCallError(e)!==`retry`)throw e;let r=500*2**(n-1)+Math.floor(Math.random()*250);log.warn(`model call failed transiently — retrying`,{attempt:n,delayMs:r,sessionId:t.sessionId,turnId:t.turnId,error:e}),await new Promise(e=>setTimeout(e,r))}}function findAuthorizationSignalFromToolResults(e){let t=contextStorage.getStore();if(t!==void 0)for(let n of e??[]){let e=readToolInterrupt(t,n.toolCallId);if(e!==void 0&&isAuthorizationSignal(e))return e}for(let t of e??[])if(isAuthorizationSignal(t.output))return t.output}export{createToolLoopHarness};
1
+ import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{isScheduleAppAuth}from"#channel/schedule-auth.js";import{AuthKey,ParentSessionKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{EmptyModelResponseError,classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,isNoOutputGeneratedError,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError}from"#harness/model-call-error.js";import{toErrorMessage}from"#shared/errors.js";import{createActionResultEvent,createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent,createResultCompletedEvent}from"#protocol/message.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{contextStorage}from"#context/container.js";import{ToolLoopAgent,isStepCount}from"ai";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{clearPendingWorkflowInterrupt,getPendingWorkflowInterrupt,setPendingWorkflowInterrupt}from"#harness/workflow-interrupt-state.js";import{getWorkflowRuntimeActionInterrupts,isWorkflowRuntimeActionInterrupt}from"#harness/workflow-runtime-action-state.js";import{isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{resolveAssistantStepText}from"#harness/messages.js";import{buildDynamicInstructionMessages}from"#context/dynamic-instruction-lifecycle.js";import{PendingSkillAnnouncementKey}from"#context/dynamic-skill-lifecycle.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{CONDITIONAL_DELIVERY_INSTRUCTION,EMPTY_DELIVERY_SENTINEL,hasEmptyDeliverySentinel}from"#shared/empty-delivery.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{ASK_QUESTION_TOOL_NAME}from"#runtime/framework-tools/ask-question.js";import{extractQuestionInputRequests,extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker}from"#harness/prompt-cache.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{applyWorkflowTool,buildWorkflowHostTools}from"#harness/workflow-sandbox.js";import{ensureWorkflowContinuationSecurity,getWorkflowContinuationSecurity}from"#harness/workflow-continuation-security.js";import{createWorkflowLifecycle}from"#harness/workflow-lifecycle.js";import{compactMessages,getInputTokenCount,resolveCompactionModel,shouldCompact}from"#harness/compaction.js";import{accumulateTurnUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{setEveAttributes}from"#runtime/attributes/emit.js";import{buildTelemetryRuntimeContext}from"#harness/instrumentation-runtime-context.js";import{getInstrumentationConfig}from"#harness/instrumentation-config.js";import{normalizeProviderToolHistory}from"#harness/provider-tool-history.js";import{extractWorkflowStreamWriteErrorDetails}from"#harness/workflow-stream-error.js";import{ensureOtelIntegration}from"#harness/otel-integration.js";import{resolveFrameworkToolFromUpstreamType}from"#harness/provider-tools.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{buildToolApproval,buildToolSetFromDefinitions,buildToolSetWithProviderTools}from"#harness/tools.js";import{continueWorkflowSandboxInterrupt,getWorkflowSandboxInterrupt,unwrapWorkflowSandboxResult}from"#shared/workflow-sandbox.js";import{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool}from"#runtime/framework-tools/final-output.js";const environment=process.env.NODE_ENV??`unknown`,eveVersion=resolveInstalledPackageInfo().version,log=createLogger(`harness.tool-loop`);function logToolExecutionError(e){e.toolOutput.type===`tool-error`&&logError(log,`tool execution failed`,e.toolOutput.error,{toolName:e.toolCall.toolName,toolCallId:e.toolCall.toolCallId})}function enrichTelemetry(e,t,n){if(e===void 0)return;let r={};for(let e of Object.keys(n??{}))r[e]=!0;return{functionId:e.functionId??t,includeRuntimeContext:r,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function buildGatewayAttributionHeaders(e,t){if(typeof e!=`string`)return;let n=t?.agentName??t?.agentId,r=process.env.VERCEL_PROJECT_PRODUCTION_URL||process.env.VERCEL_URL,i=r?`https://${r}`:void 0;if(!n&&!i)return;let a={};return n&&(a[`x-title`]=n),i&&(a[`http-referer`]=i),a}const TURN_TRACE_STATE_KEY=`eve.harness.turnTrace`;function getTurnTraceState(e){return e.state?.[TURN_TRACE_STATE_KEY]}function setTurnTraceState(e,t){let n={traceId:t.traceId,spanId:t.spanId,traceFlags:t.traceFlags};return{...e,state:{...e.state,[TURN_TRACE_STATE_KEY]:n}}}function resolveStepOtelContext(e,t,n){if(t)return trace.setSpan(context.active(),t);if(e){let e=getTurnTraceState(n);if(e){let t=trace.wrapSpanContext({traceId:e.traceId,spanId:e.spanId,traceFlags:e.traceFlags});return trace.setSpan(context.active(),t)}}}function createToolLoopHarness(t){let n=t.handleEvent,c=getInstrumentationConfig();c!==void 0&&ensureOtelIntegration();let f=c===void 0?void 0:trace.getTracer(`eve`),p=t.runtimeIdentity?.agentName;async function runStep(e,t){let n;if(f&&hasStepInput(t)){let t=c?.functionId??p,r={"eve.version":eveVersion,"eve.environment":environment,"eve.session.id":e.sessionId};t&&(r[`ai.telemetry.functionId`]=t),n=f.startSpan(`ai.eve.turn`,{attributes:r})}let r=resolveStepOtelContext(f,n,e),executeStep=()=>executeStepBody(e,t,n);try{return r?await context.with(r,executeStep):await executeStep()}finally{n?.end()}}async function executeStepBody(f,v,y){let b=f;y&&(b=setTurnTraceState(b,y.spanContext()));let x=getHarnessEmissionState(b.state),S=consumeDeferredStepInput({input:v,session:b});b=S.session;let D=await resolvePendingRuntimeActions({emit:n,session:b,stepInput:S.input});if(D.outcome===`unresolved`)return{next:null,session:D.session};b=D.session;let O=resolvePendingInput({history:D.messages,resolveApprovalKey:resolveApprovalKeyFromTools(t.tools),session:b,stepInput:S.input});if(O.outcome===`unresolved`)return n&&O.deferredMessage===!0&&hasStepInput(v)?(x=await emitTurnPreamble(n,v??{},x,t.runtimeIdentity),x=await emitTurnEpilogue(n,x,t.mode),{next:null,session:setHarnessEmissionState(O.session,x)}):{next:null,session:O.session};if(n&&O.rejectedActions)for(let e of O.rejectedActions.results)await n(createActionResultEvent({rejected:!0,result:e,sequence:O.rejectedActions.event.sequence,stepIndex:O.rejectedActions.event.stepIndex,turnId:O.rejectedActions.event.turnId}));n&&hasStepInput(v)&&(x=await emitTurnPreamble(n,v??{},x,t.runtimeIdentity),b=setHarnessEmissionState(b,x),y&&y.setAttribute(`eve.turn.id`,x.turnId)),b=O.session,t.workflow===!0&&(b=ensureWorkflowContinuationSecurity(b));let k=O.messages;if(S.input?.context!==void 0)for(let e of S.input.context)k.push({content:e,role:`user`});if(S.input?.message!==void 0&&!O.deferredMessage&&!O.consumedMessage){let e=await stageAttachmentsToSandbox(S.input.message);k.push({content:e,role:`user`})}let A=await t.resolveModel(b.agent.modelReference),j=detectPromptCachePath(A),M=j.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,N=buildGatewayAttributionHeaders(A,t.runtimeIdentity);({messages:k,session:b}=await maybeCompact({emit:n,emissionState:x,headers:N,messages:k,model:A,onCompaction:t.onCompaction,resolveModel:t.resolveModel,session:b,telemetry:enrichTelemetry(c,p)??void 0}));let P=getApprovedTools(b),F=contextStorage.getStore(),I=b.outputSchema===void 0&&F!==void 0&&isScheduleAppAuth(F.get(AuthKey))&&F.get(ParentSessionKey)===void 0,L=await hydrateSandboxAttachments(k),R=[],z=[];for(let e of L)e.role===`system`?R.push(e):z.push(e);if(F!==void 0){R.push(...buildDynamicInstructionMessages(F));let e=F.get(PendingSkillAnnouncementKey);e!==void 0&&e.length>0&&R.push({role:`system`,content:e})}I&&R.push({role:`system`,content:CONDITIONAL_DELIVERY_INSTRUCTION});let B=z,prepareModelCallInput=e=>{let t=e?[{role:`system`,content:e}]:[],n=b.agent.system?[{role:`system`,content:b.agent.system}]:[],r=R.length>0||t.length>0?[...t,...n,...R]:void 0,i=r!==void 0&&M?applySystemCacheBreakpoint(r,M):r??b.agent.system??void 0;return{instructions:i,telemetryRuntimeContext:buildTelemetryRuntimeContext({eveVersion,authored:c,emissionState:x,environment,modelInput:{instructions:i,messages:B},session:b})}},runOneModelCall=async e=>{let{instructions:i,telemetryRuntimeContext:a={}}=e.preparedInput??prepareModelCallInput(e.extraSystemNote);e.retryReason&&(a[`eve.retry.reason`]=e.retryReason);let o=e.trailingUserNote?[...B,{role:`user`,content:e.trailingUserNote}]:B,s=await buildToolSetWithProviderTools({approvedTools:P,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,modelReference:b.agent.modelReference,tools:t.tools});if(F!==void 0){let n=buildDynamicTools(F),r=buildToolSetFromDefinitions({approvedTools:P,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,tools:n});for(let[e,t]of Object.entries(r))s[e]=t}b.outputSchema!==void 0&&(s[FINAL_OUTPUT_TOOL_NAME]=buildFinalOutputTool(b.outputSchema));let u=t.workflow===!0?(await applyWorkflowTool({continuationSecurity:getWorkflowContinuationSecurity(b),harnessTools:t.tools,lifecycle:n===void 0?void 0:createWorkflowLifecycle({emit:n,emissionState:x,tools:t.tools}),tools:s})).modelTools:s,d=M?applyLastToolCacheBreakpoint(u,M):u,f=buildStepHooks({cachePath:j,emit:n,emissionState:x,emitStepStarted:e.suppressStepStartedEmission!==!0,marker:M,session:b}),h=new ToolLoopAgent({headers:N,instructions:i,model:A,onToolExecutionEnd:logToolExecutionError,onError(e){summarizeKnownModelCallConfigError(e.error)===null&&logError(log,`tool-loop stream error`,e.error)},onStepFinish:f.onStepFinish,prepareStep:f.prepareStep,reasoning:b.agent.reasoning,runtimeContext:a,stopWhen:isStepCount(1),telemetry:enrichTelemetry(c,p,a),toolApproval:buildToolApproval(u),tools:d}),executeModelCall=async()=>{if(n){let e=new Set([ASK_QUESTION_TOOL_NAME,FINAL_OUTPUT_TOOL_NAME]),r=await h.stream({messages:o}),{emittedActionCallIds:i,handledInlineToolResultCallIds:a,inlineAuthorizationResults:s,inlineToolResultParts:c}=await emitStreamContent(n,x,r.fullStream,{excludedActionToolNames:e,tools:t.tools}),u=await f.stepResult;if(isEmptyModelResponse(u)&&c.length===0&&s.length===0)throw new EmptyModelResponseError;if(await emitStepActions(n,x,u,{emittedActionCallIds:i,excludedActionToolNames:e,handledInlineToolResultCallIds:a,tools:t.tools}),c.length>0||s.length>0){let e=u.toolResults,t=new Map(e.map(e=>[e.toolCallId,e]));for(let e of s)t.set(e.toolCallId,e);return{content:u.content,finishReason:u.finishReason,response:{...u.response,...c.length>0?{messages:[{role:`tool`,content:[...c]},...u.response.messages]}:{}},text:u.text,toolCalls:u.toolCalls,toolResults:[...t.values()],usage:u.usage}}return u}await h.generate({messages:o});let e=await f.stepResult;if(isEmptyModelResponse(e))throw new EmptyModelResponseError;return e};return runModelCallWithRetries(()=>executeModelCall().catch(rethrowNoOutputAsEmptyResponse),{sessionId:b.sessionId,turnId:x.turnId})},V=prepareModelCallInput();n&&await emitStepStarted(n,x,k);let H=await continuePendingWorkflowInterrupt({childResults:S.input?.runtimeActionResults,config:t,emit:n,emissionState:x,runStep,session:b});if(H!==null)return H;let U;try{U=await runOneModelCall({preparedInput:V,suppressStepStartedEmission:!0})}catch(r){let a=await runModelCallRecoveryPipeline({error:r,stages:[e=>attemptUnsupportedProviderToolRecovery({error:e.error,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId}),e=>attemptEmptyResponseRecovery({emptyDeliveryEnabled:I,error:e.error,retryCallOptions:e.retryCallOptions,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId})]});if(a.outcome===`recovered`)U=a.result;else{let r=a.error;if(y&&recordErrorOnSpan(y,r),!n)throw r;let o=extractWorkflowStreamWriteErrorDetails(r);if(o!==null){let t=createErrorId();return log.error(`workflow stream write failed — parking session for retry by the user`,{...o,errorId:t,error:r,sessionId:b.sessionId,turnId:x.turnId}),x=await emitRecoverableFailedTurn(n,x,{code:`WORKFLOW_STREAM_WRITE_FAILED`,details:{...o,errorId:t},message:toErrorMessage(r)}),{next:null,session:setHarnessEmissionState(b,x)}}let s=classifyModelCallError(r),c=createErrorId(),l=s===`terminal`?summarizeKnownModelCallConfigError(r):null,f=l===null?summarizeKnownModelCallRequestError(r):null,p=l?.message??f?.message??toErrorMessage(r),_=extractModelCallErrorDetails(r),v=buildModelCallFailureDetails({configSummary:l,error:r,errorId:c,modelCallDetails:_,requestSummary:f}),S=buildModelCallFailureLogFields({error:r,errorId:c,modelCallDetails:_,requestSummary:f,sessionId:b.sessionId,turnId:x.turnId});return s===`terminal`?(l===null?log.error(f?.message??`model call failed terminally`,S):log.error(`${l.name}: ${l.message}`,{errorId:c,sessionId:b.sessionId,turnId:x.turnId}),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:{done:!0,output:``},session:b}):t.mode===`task`?(log.error(f?.message??`model call failed; failing the task run`,S),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:{done:!0,isError:!0,output:p},session:b}):(log.error(f?.message??`model call failed — parking session for retry by the user`,S),x=await emitRecoverableFailedTurn(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p}),{next:null,session:setHarnessEmissionState(b,x)})}}let W=accumulateTurnUsage({previous:getTurnUsageState(b.state),turnId:x.turnId,usage:U.usage??{}});b=setTurnUsageState(b,W);let G;try{G=formatLanguageModelGatewayId(A)}catch{G=void 0}return await setEveAttributes({"$eve.model":G,"$eve.input_tokens":W.inputTokens,"$eve.output_tokens":W.outputTokens,"$eve.cache_read_tokens":W.cacheReadTokens,"$eve.cache_write_tokens":W.cacheWriteTokens,"$eve.tool_count":t.tools.size}),handleStepResult({config:t,emit:n,emissionState:x,promptMessages:k,result:U,runStep,session:b})}return runStep}function buildModelCallFailureDetails(e){let{configSummary:t,error:r,errorId:i,modelCallDetails:a,requestSummary:o}=e;return t===null?o===null?{...formatError(r,i),...a}:{errorId:i,message:toErrorMessage(r),name:o.name,...a}:{errorId:i,message:t.message,name:t.name,...a}}function buildModelCallFailureLogFields(e){let t={errorId:e.errorId,sessionId:e.sessionId,turnId:e.turnId};return e.requestSummary===null?{...t,error:e.error}:{...t,details:e.modelCallDetails}}async function runModelCallRecoveryPipeline(e){let t=e.error,n;for(let r of e.stages){let e=await r({error:t,retryCallOptions:n});if(e.outcome===`recovered`)return e;e.outcome===`failed`&&(t=e.error,n=e.retryCallOptions)}return{outcome:`failed`,error:t}}async function attemptUnsupportedProviderToolRecovery(e){let t=extractUnsupportedProviderToolTypes(e.error);if(t.length===0)return{outcome:`skipped`};let n=[];for(let e of t){let t=resolveFrameworkToolFromUpstreamType(e);t!==null&&!n.includes(t)&&n.push(t)}if(n.length===0)return{outcome:`skipped`};log.warn(`disabling unsupported provider tool(s); retrying step once`,{disabled:n,sessionId:e.sessionId,turnId:e.turnId,upstreamTypes:t});let r={disabledProviderTools:new Set(n),extraSystemNote:buildDisabledToolNote(n)};try{return{outcome:`recovered`,result:await e.runOneModelCall({...r,suppressStepStartedEmission:!0})}}catch(e){return{outcome:`failed`,error:e,retryCallOptions:r}}}function buildDisabledToolNote(e){let t=e.join(`, `);return`The following ${e.length===1?`tool is`:`tools are`} not available with the current model and has been removed: ${t}. Proceed using the remaining tools or your training knowledge.`}function isEmptyModelResponse(e){return e.toolCalls.length===0&&e.toolResults.length===0&&resolveAssistantStepText(e.response.messages,e.text)===null}function rethrowNoOutputAsEmptyResponse(e){throw isNoOutputGeneratedError(e)?new EmptyModelResponseError({cause:e}):e}const EMPTY_RESPONSE_NUDGE=`Your previous reply was empty and was not delivered. Answer now from the tool results above; do not re-run tools or mention this notice.`;function buildEmptyResponseNudge(e){return e?`${EMPTY_RESPONSE_NUDGE} If the current task explicitly requires conditional delivery and there is nothing to report, reply with exactly ${EMPTY_DELIVERY_SENTINEL}.`:EMPTY_RESPONSE_NUDGE}async function attemptEmptyResponseRecovery(e){if(!(e.error instanceof EmptyModelResponseError))return{outcome:`skipped`};log.warn(`empty model response; reissuing the model call once`,{sessionId:e.sessionId,turnId:e.turnId});try{return{outcome:`recovered`,result:await e.runOneModelCall({...e.retryCallOptions,retryReason:`empty-response`,suppressStepStartedEmission:!0,trailingUserNote:buildEmptyResponseNudge(e.emptyDeliveryEnabled)})}}catch(t){return{outcome:`failed`,error:t,retryCallOptions:e.retryCallOptions}}}async function handleStepResult(e){let{config:t,emit:n,promptMessages:r,result:i,runStep:a}=e,{emissionState:o,session:s}=e,c=resolveAssistantStepText(i.response.messages,i.text),l=i.finishReason!==`tool-calls`&&i.toolCalls.length===0&&hasEmptyDeliverySentinel(c),u=l?[]:i.response.messages,d=l?null:c,f=new Set;for(let e of[...i.content??[],...i.toolResults??[]])(e.type===`tool-result`||e.type===`tool-error`)&&e.providerExecuted===!0&&f.add(e.toolCallId);let p=normalizeProviderToolHistory({messages:u,providerExecutedOutcomeIds:f}),m=p.messages,h={...s,compaction:createNextCompactionConfig(s.compaction,r,i)};if(t.workflow===!0){let e=await getWorkflowSandboxInterrupt(i,getWorkflowContinuationSecurity(h));if(e!==void 0){if(!isWorkflowRuntimeActionInterrupt(e))throw Error(`Unsupported Workflow interrupt kind "${e.payload.kind}".`);return parkOnWorkflowInterrupt({baseSession:h,emissionState:o,interrupt:e,promptMessages:r,responseMessages:m})}}let g=extractToolApprovalInputRequests({content:i.content??[]}),_=new Set(g.map(e=>e.action.callId)),y=extractQuestionInputRequests({toolCalls:i.toolCalls,excludedCallIds:_}),b=[...g,...y],S=(i.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:t.tools}));if(S.length>0)return{next:null,session:setHarnessEmissionState(setPendingRuntimeActionBatch({actions:S,event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},responseMessages:m,session:{...h,history:[...r]}}),o)};if(b.length>0){let e=setPendingInputBatch({event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},requests:b,responseMessages:m,session:{...h,history:[...r]}});return n&&(await n(createInputRequestedEvent({requests:b,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),t.mode===`conversation`&&(o=await emitTurnEpilogue(n,o,t.mode),e=setHarnessEmissionState(e,o))),{next:null,session:e}}let C=findAuthorizationSignalFromToolResults(i.toolResults);if(C){let{challenges:e}=C;if(n)for(let t of e)await n(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId}));return{next:null,session:setHarnessEmissionState({...h,history:[...r],state:setPendingAuthorization(h.state,{challenges:e})},o)}}let w=m,T=[...r,...w],E={...h,history:T};return!(E.outputSchema!==void 0&&extractFinalOutput(i)!==void 0)&&(w.at(-1)?.role===`tool`||p.outcomeEndsResponse||hasDeferredStepInput(E))?(n&&(o=advanceStep(o),E=setHarnessEmissionState(E,o)),{next:a,session:E}):t.mode===`task`?finishTaskTurn({emissionState:o,emit:n,history:r,result:i,schema:E.outputSchema,session:E,stepOutput:d}):finishConversationTurn({emissionState:o,emit:n,history:r,result:i,schema:E.outputSchema,session:E})}const OUTPUT_SCHEMA_NOT_FULFILLED={code:`OUTPUT_SCHEMA_NOT_FULFILLED`,message:`The agent could not produce a result matching the requested schema.`};function extractFinalOutput(e){return(e.toolCalls??[]).find(e=>e.toolName===FINAL_OUTPUT_TOOL_NAME)?.input}function persistStructuredAssistantTurn(e,t,n){return{...e,history:[...t,{content:JSON.stringify(n),role:`assistant`}],outputSchema:void 0}}async function emitStructuredResult(e,t,n,r){return await e(createResultCompletedEvent({result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),emitTurnEpilogue(e,t,r)}async function finishTaskTurn(e){let{emit:t,history:n,result:r,schema:i,stepOutput:a}=e,{emissionState:o,session:s}=e;if(i===void 0)return t&&(o=await emitTurnEpilogue(t,o,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:a??``},session:s};let c=extractFinalOutput(r);return c===void 0?(t&&await emitFailedStep(t,o,{...OUTPUT_SCHEMA_NOT_FULFILLED,sessionId:s.sessionId}),{next:{done:!0,isError:!0,output:OUTPUT_SCHEMA_NOT_FULFILLED.message},session:s}):(s=persistStructuredAssistantTurn(s,n,c),t&&(o=await emitStructuredResult(t,o,c,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:c},session:s})}async function finishConversationTurn(e){let{emit:t,history:n,result:r,schema:i}=e,{emissionState:a,session:o}=e;if(i===void 0)return t&&(a=await emitTurnEpilogue(t,a,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o};let s=extractFinalOutput(r);return s===void 0?(t&&(a=await emitRecoverableFailedTurn(t,a,OUTPUT_SCHEMA_NOT_FULFILLED),o=setHarnessEmissionState(o,a)),{next:null,session:o}):(o=persistStructuredAssistantTurn(o,n,s),t&&(a=await emitStructuredResult(t,a,s,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o})}async function continuePendingWorkflowInterrupt(e){let t=getPendingWorkflowInterrupt(e.session.state);if(t===void 0)return null;let n=t.interrupt;if(!isWorkflowRuntimeActionInterrupt(n))throw Error(`Unsupported Workflow interrupt kind "${n.payload.kind}".`);let i=e.emit===void 0?void 0:createWorkflowLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools}),a=getWorkflowContinuationSecurity(e.session),o;try{let t=buildWorkflowHostTools({tools:e.config.tools}),r=e.childResults??[],s=n,c=0;for(;;){o=await continueWorkflowSandboxInterrupt({continuationSecurity:a,interrupt:s,lifecycle:i,resolution:r[c]?.output,tools:t});let e=await unwrapWorkflowSandboxResult(o,a);if(e.status!==`interrupted`||!isWorkflowRuntimeActionInterrupt(e.interrupt)||c+1>=r.length)break;let n=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(n===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);c++,s=n}}catch(e){logError(log,`Workflow interrupt continuation failed`,e),o={error:`workflow_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let s=await unwrapWorkflowSandboxResult(o,a),c=s.status===`interrupted`?s.interrupt:s.output,l=replaceWorkflowToolResult([...e.session.history,...t.responseMessages],n.outerToolCallId,c),u=clearPendingWorkflowInterrupt({...e.session,history:l});if(s.status===`interrupted`){if(!isWorkflowRuntimeActionInterrupt(s.interrupt))throw Error(`Unsupported Workflow interrupt kind "${s.interrupt.payload.kind}".`);let t=e.session.history.length,n=l.slice(0,t),r=l.slice(t);return u={...u,history:n},parkOnWorkflowInterrupt({baseSession:u,emissionState:e.emissionState,interrupt:s.interrupt,promptMessages:n,responseMessages:r})}return{next:e.runStep,session:u}}function replaceWorkflowToolResult(e,t,n){if(t===void 0)return[...e];let r=typeof n==`string`?{type:`text`,value:n}:{type:`json`,value:n};return e.map(e=>{if(e.role!==`tool`)return e;let n=e.content.map(e=>e.type!==`tool-result`||e.toolCallId!==t?e:{...e,output:r});return{...e,content:n}})}function parkOnWorkflowInterrupt(e){let t=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(t===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);let n={...e.baseSession,history:[...e.promptMessages]};return{next:null,session:setHarnessEmissionState(setPendingWorkflowInterrupt({interrupt:t,responseMessages:e.responseMessages,session:n}),e.emissionState)}}function createNextCompactionConfig(e,t,n){let r={recentWindowSize:e.recentWindowSize,threshold:e.threshold};return n.usage?.inputTokens!==void 0&&(r.lastKnownInputTokens=n.usage.inputTokens,r.lastKnownPromptMessageCount=t.length),r}async function maybeCompact(e){let{emit:t,emissionState:n}=e,r=e.messages,i=e.session;if(!shouldCompact(r,i.compaction))return{messages:r,session:i};let a=await resolveCompactionModel({compactionModelReference:i.agent.compactionModelReference,model:e.model,modelReference:i.agent.modelReference,resolveModel:e.resolveModel});if(t&&await t(createCompactionRequestedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId,usageInputTokens:getInputTokenCount(r,i.compaction)})),r=await compactMessages(r,a.model,i.compaction,a.providerOptions,e.telemetry,e.headers),e.onCompaction)for(let t of e.onCompaction())r.push(t);return t&&await t(createCompactionCompletedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId})),{messages:r,session:i}}function resolveApprovalKeyFromTools(e){return t=>{let n=e.get(t.action.toolName);if(n?.approvalKey!==void 0)return n.approvalKey(t.action.input)}}async function runModelCallWithRetries(e,t){for(let n=1;;n++)try{return await e()}catch(e){if(n===3||classifyModelCallError(e)!==`retry`)throw e;let r=500*2**(n-1)+Math.floor(Math.random()*250);log.warn(`model call failed transiently — retrying`,{attempt:n,delayMs:r,sessionId:t.sessionId,turnId:t.turnId,error:e}),await new Promise(e=>setTimeout(e,r))}}function findAuthorizationSignalFromToolResults(e){let t=contextStorage.getStore();if(t!==void 0)for(let n of e??[]){let e=readToolInterrupt(t,n.toolCallId);if(e!==void 0&&isAuthorizationSignal(e))return e}for(let t of e??[])if(isAuthorizationSignal(t.output))return t.output}export{createToolLoopHarness};
@@ -1 +1 @@
1
- import{createRequire}from"node:module";import{existsSync,readFileSync,realpathSync}from"node:fs";import{basename,dirname,join}from"node:path";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const BUNDLED_FALLBACK_PACKAGE_VERSION=`0.16.0`,WORKFLOW_MODULE_ALIASES={"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`};function resolveFallbackPackageVersion(){return BUNDLED_FALLBACK_PACKAGE_VERSION.startsWith(`__`)?`0.0.0`:BUNDLED_FALLBACK_PACKAGE_VERSION}const FALLBACK_PACKAGE_INFO={name:EVE_PACKAGE_NAME,version:resolveFallbackPackageVersion()};function resolveCurrentModulePath(){return typeof __filename==`string`?__filename:resolveCurrentModulePathFromStack()}function resolveCurrentModulePathFromStack(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(e,t)=>t;let e=Error().stack?.[0]?.getFileName();if(typeof e!=`string`||e.length===0)throw Error(`Failed to resolve the current module path from the stack trace.`);return e.startsWith(`file:`)?fileURLToPath(e):e}finally{Error.prepareStackTrace=e}}const require=createRequire(resolveCurrentModulePath());function isBuildOutputPackageRoot(e){return basename(e)===`dist`&&existsSync(join(dirname(e),`package.json`))}function resolvePackageBuildRoot(){let e=dirname(realpathSync(resolveCurrentModulePath()));for(;;){if(isBuildOutputPackageRoot(e))return e;let t=dirname(e);if(t===e)return null;e=t}}function findNearestPackageRoot(e){let n=e;for(;;){if(existsSync(join(n,`package.json`))&&!isBuildOutputPackageRoot(n))return n;let r=dirname(n);if(r===n)throw Error(`Failed to resolve package root from "${e}".`);n=r}}function resolvePackageRoot(){return findNearestPackageRoot(dirname(realpathSync(resolveCurrentModulePath())))}function tryResolvePackageRoot(){try{return resolvePackageRoot()}catch{return}}function rewriteSourceFilePathForBuild(e){return e.replace(/\.[cm]?tsx?$/,`.js`)}function resolvePackageSourceFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),e):join(t,rewriteSourceFilePathForBuild(e))}function resolvePackageSourceDirectoryPath(e){let t=resolvePackageBuildRoot();return join(t===null?resolvePackageRoot():t,e)}function resolvePackageDependencyPath(e){return require.resolve(e)}function resolvePackageCompiledFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),`.generated`,`compiled`,e.replace(/^src\/compiled\//,``)):join(t,e)}function normalizeInstalledPackageInfo(e){let t=e;if(!(typeof t.name!=`string`||typeof t.version!=`string`))return{name:t.name,version:t.version}}function tryReadInstalledPackageInfo(e,t){let r=normalizeInstalledPackageInfo(JSON.parse(readFileSync(e,`utf8`)));if(r?.name===t)return r}function resolveInstalledPackageInfo(){if(cachedPackageInfo)return cachedPackageInfo;let e=tryResolvePackageRoot(),t=e===void 0?void 0:tryReadInstalledPackageInfo(join(e,`package.json`),EVE_PACKAGE_NAME);if(t)return cachedPackageInfo=t,cachedPackageInfo;try{let e=tryReadInstalledPackageInfo(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),EVE_PACKAGE_NAME);if(e)return cachedPackageInfo=e,cachedPackageInfo}catch{}return cachedPackageInfo={...FALLBACK_PACKAGE_INFO},cachedPackageInfo}function readWorkflowVersionFromManifest(e){let t=e;for(let e of[t.devDependencies,t.dependencies,t.peerDependencies]){let t=e?.[`@workflow/core`];if(typeof t==`string`&&t.trim().length>0)return t}}function resolveExpectedWorkflowVersion(){let e=tryResolvePackageRoot();if(e!==void 0)try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(join(e,`package.json`),`utf8`)))}catch{}try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),`utf8`)))}catch{return}}function resolveWorkflowModulePath(e){if(e===`workflow`)return resolvePackageSourceFilePath(`src/internal/workflow/index.ts`);if(e===`workflow/api`||e===`workflow/runtime`)return resolvePackageSourceFilePath(`src/internal/workflow/runtime.ts`);if(e===`workflow/internal/builtins`)return resolvePackageSourceFilePath(`src/internal/workflow/builtins.ts`);let t=WORKFLOW_MODULE_ALIASES[e];return t===void 0?require.resolve(e):resolvePackageCompiledFilePath(t)}export{resolveExpectedWorkflowVersion,resolveInstalledPackageInfo,resolvePackageDependencyPath,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
1
+ import{createRequire}from"node:module";import{existsSync,readFileSync,realpathSync}from"node:fs";import{basename,dirname,join}from"node:path";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const BUNDLED_FALLBACK_PACKAGE_VERSION=`0.16.2`,WORKFLOW_MODULE_ALIASES={"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`};function resolveFallbackPackageVersion(){return BUNDLED_FALLBACK_PACKAGE_VERSION.startsWith(`__`)?`0.0.0`:BUNDLED_FALLBACK_PACKAGE_VERSION}const FALLBACK_PACKAGE_INFO={name:EVE_PACKAGE_NAME,version:resolveFallbackPackageVersion()};function resolveCurrentModulePath(){return typeof __filename==`string`?__filename:resolveCurrentModulePathFromStack()}function resolveCurrentModulePathFromStack(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(e,t)=>t;let e=Error().stack?.[0]?.getFileName();if(typeof e!=`string`||e.length===0)throw Error(`Failed to resolve the current module path from the stack trace.`);return e.startsWith(`file:`)?fileURLToPath(e):e}finally{Error.prepareStackTrace=e}}const require=createRequire(resolveCurrentModulePath());function isBuildOutputPackageRoot(e){return basename(e)===`dist`&&existsSync(join(dirname(e),`package.json`))}function resolvePackageBuildRoot(){let e=dirname(realpathSync(resolveCurrentModulePath()));for(;;){if(isBuildOutputPackageRoot(e))return e;let t=dirname(e);if(t===e)return null;e=t}}function findNearestPackageRoot(e){let n=e;for(;;){if(existsSync(join(n,`package.json`))&&!isBuildOutputPackageRoot(n))return n;let r=dirname(n);if(r===n)throw Error(`Failed to resolve package root from "${e}".`);n=r}}function resolvePackageRoot(){return findNearestPackageRoot(dirname(realpathSync(resolveCurrentModulePath())))}function tryResolvePackageRoot(){try{return resolvePackageRoot()}catch{return}}function rewriteSourceFilePathForBuild(e){return e.replace(/\.[cm]?tsx?$/,`.js`)}function resolvePackageSourceFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),e):join(t,rewriteSourceFilePathForBuild(e))}function resolvePackageSourceDirectoryPath(e){let t=resolvePackageBuildRoot();return join(t===null?resolvePackageRoot():t,e)}function resolvePackageDependencyPath(e){return require.resolve(e)}function resolvePackageCompiledFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),`.generated`,`compiled`,e.replace(/^src\/compiled\//,``)):join(t,e)}function normalizeInstalledPackageInfo(e){let t=e;if(!(typeof t.name!=`string`||typeof t.version!=`string`))return{name:t.name,version:t.version}}function tryReadInstalledPackageInfo(e,t){let r=normalizeInstalledPackageInfo(JSON.parse(readFileSync(e,`utf8`)));if(r?.name===t)return r}function resolveInstalledPackageInfo(){if(cachedPackageInfo)return cachedPackageInfo;let e=tryResolvePackageRoot(),t=e===void 0?void 0:tryReadInstalledPackageInfo(join(e,`package.json`),EVE_PACKAGE_NAME);if(t)return cachedPackageInfo=t,cachedPackageInfo;try{let e=tryReadInstalledPackageInfo(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),EVE_PACKAGE_NAME);if(e)return cachedPackageInfo=e,cachedPackageInfo}catch{}return cachedPackageInfo={...FALLBACK_PACKAGE_INFO},cachedPackageInfo}function readWorkflowVersionFromManifest(e){let t=e;for(let e of[t.devDependencies,t.dependencies,t.peerDependencies]){let t=e?.[`@workflow/core`];if(typeof t==`string`&&t.trim().length>0)return t}}function resolveExpectedWorkflowVersion(){let e=tryResolvePackageRoot();if(e!==void 0)try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(join(e,`package.json`),`utf8`)))}catch{}try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),`utf8`)))}catch{return}}function resolveWorkflowModulePath(e){if(e===`workflow`)return resolvePackageSourceFilePath(`src/internal/workflow/index.ts`);if(e===`workflow/api`||e===`workflow/runtime`)return resolvePackageSourceFilePath(`src/internal/workflow/runtime.ts`);if(e===`workflow/internal/builtins`)return resolvePackageSourceFilePath(`src/internal/workflow/builtins.ts`);let t=WORKFLOW_MODULE_ALIASES[e];return t===void 0?require.resolve(e):resolvePackageCompiledFilePath(t)}export{resolveExpectedWorkflowVersion,resolveInstalledPackageInfo,resolvePackageDependencyPath,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
@@ -1,4 +1,5 @@
1
1
  import type { Nitro } from "nitro/types";
2
+ import type { NormalizedChannelCorsOptions } from "#channel/cors.js";
2
3
  import type { ChannelRouteMethod } from "#public/definitions/channel.js";
3
4
  import type { NitroArtifactsConfigInput } from "#internal/nitro/host/artifacts-config.js";
4
5
  import type { PreparedApplicationHost } from "#internal/nitro/host/types.js";
@@ -14,6 +15,7 @@ interface ChannelRouteNitro {
14
15
  export interface NitroChannelRouteRegistration {
15
16
  readonly method: ChannelRouteMethod;
16
17
  readonly route: string;
18
+ readonly cors?: NormalizedChannelCorsOptions;
17
19
  }
18
20
  /**
19
21
  * Computes the merged set of channel routes the Nitro host should mount.
@@ -1,3 +1,5 @@
1
- import{resolvePackageDependencyPath,resolvePackageSourceFilePath}from"#internal/application/package.js";import{stringifyEsmImportSpecifier}from"#internal/application/import-specifier.js";import{getAllFrameworkChannelNames,getFrameworkChannelDefinitions}from"#runtime/framework-channels/index.js";import{replaceDevLiveVirtualModules}from"#internal/nitro/host/dev-live-virtual-modules.js";const EVE_CHANNEL_VIRTUAL_ID_PREFIX=`#nitro/virtual/eve-channel/`;function computeChannelRouteRegistrations(e){let t=e.compileResult.manifest.channels,n=new Set,a=[],o=new Set,s=getAllFrameworkChannelNames();for(let e of t){if(e.kind===`disabled`){if(!s.has(e.name))throw Error(`agent/channels/${e.name}.ts exports disableRoute() but "${e.name}" is not a framework channel. Rename the file to one of: ${[...s].sort().join(`, `)}.`);o.add(e.name);continue}n.add(e.name),a.push({method:e.method,route:e.urlPath})}let c=getFrameworkChannelDefinitions().filter(e=>!n.has(e.name)&&!o.has(e.name)).map(e=>({method:e.method,route:e.urlPath})),l=new Set,u=[];for(let e of[...c,...a]){let t=createChannelRouteKey(e);l.has(t)||(l.add(t),u.push(e))}return u}function registerChannelVirtualHandlers(e,t){for(let n of t.registrations)addChannelVirtualHandler(e,{artifactsConfig:t.artifactsConfig,method:n.method,route:n.route})}function syncChannelVirtualHandlers(e,t){if(areChannelRouteRegistrationsEqual(t.previous,t.next))return!1;removeChannelVirtualHandlers(e),registerChannelVirtualHandlers(e,{artifactsConfig:t.artifactsConfig,registrations:t.next});let n={};for(let[t,r]of Object.entries(e.options.virtual))t.startsWith(EVE_CHANNEL_VIRTUAL_ID_PREFIX)&&typeof r==`string`&&(n[t]=r);return replaceDevLiveVirtualModules(e,{entries:n,prefix:EVE_CHANNEL_VIRTUAL_ID_PREFIX})||console.warn("[eve:dev] channel routes changed but the dev bundler's virtual-module map was not captured; restart `eve dev` to mount the new routes."),e.routing.sync(),!0}function createChannelRouteKey(e){return`${e.method.toUpperCase()} ${e.route}`}function addChannelVirtualHandler(r,i){let a=createChannelRouteKey(i),s=`${EVE_CHANNEL_VIRTUAL_ID_PREFIX}${a}`,c=stringifyEsmImportSpecifier(resolvePackageSourceFilePath(`src/internal/nitro/routes/channel-dispatch.ts`)),l=stringifyEsmImportSpecifier(resolvePackageDependencyPath(`nitro`));if(i.method===`WEBSOCKET`){r.options.handlers.push({handler:s,route:i.route}),r.options.virtual[s]=[`import { defineWebSocketHandler } from ${l};`,`import { dispatchChannelWebSocketRequest } from ${c};`,`const config = ${JSON.stringify(i.artifactsConfig)};`,`export default defineWebSocketHandler((event) => dispatchChannelWebSocketRequest(event, ${JSON.stringify(a)}, config));`].join(`
2
- `);return}r.options.handlers.push({handler:s,method:i.method,route:i.route}),r.options.virtual[s]=[`import { dispatchChannelRequest } from ${c};`,`const config = ${JSON.stringify(i.artifactsConfig)};`,`export default (event) => dispatchChannelRequest(event, ${JSON.stringify(a)}, config);`].join(`
3
- `)}function removeChannelVirtualHandlers(e){for(let t=e.options.handlers.length-1;t>=0;--t){let n=e.options.handlers[t];n!==void 0&&isChannelVirtualHandler(n)&&e.options.handlers.splice(t,1)}for(let t of Object.keys(e.options.virtual))t.startsWith(EVE_CHANNEL_VIRTUAL_ID_PREFIX)&&delete e.options.virtual[t]}function isChannelVirtualHandler(e){return e.handler.startsWith(EVE_CHANNEL_VIRTUAL_ID_PREFIX)}function areChannelRouteRegistrationsEqual(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1){let r=e[n],i=t[n];if(r===void 0||i===void 0||r.method!==i.method||r.route!==i.route)return!1}return!0}export{computeChannelRouteRegistrations,registerChannelVirtualHandlers,syncChannelVirtualHandlers};
1
+ import{resolvePackageDependencyPath,resolvePackageSourceFilePath}from"#internal/application/package.js";import{stringifyEsmImportSpecifier}from"#internal/application/import-specifier.js";import{getAllFrameworkChannelNames,getFrameworkChannelDefinitions}from"#runtime/framework-channels/index.js";import{replaceDevLiveVirtualModules}from"#internal/nitro/host/dev-live-virtual-modules.js";const EVE_CHANNEL_VIRTUAL_ID_PREFIX=`#nitro/virtual/eve-channel/`;function computeChannelRouteRegistrations(e){let t=e.compileResult.manifest.channels,n=new Set,a=[],o=new Set,s=getAllFrameworkChannelNames();for(let e of t){if(e.kind===`disabled`){if(!s.has(e.name))throw Error(`agent/channels/${e.name}.ts exports disableRoute() but "${e.name}" is not a framework channel. Rename the file to one of: ${[...s].sort().join(`, `)}.`);o.add(e.name);continue}n.add(e.name),a.push({method:e.method,route:e.urlPath,cors:e.cors})}let c=getFrameworkChannelDefinitions().filter(e=>!n.has(e.name)&&!o.has(e.name)).map(e=>({method:e.method,route:e.urlPath,cors:e.cors})),l=new Set,u=[];for(let e of[...c,...a]){let t=createChannelRouteKey(e);l.has(t)||(l.add(t),u.push(e))}return u}function registerChannelVirtualHandlers(e,t){let n=new Set;for(let r of t.registrations)addChannelVirtualHandler(e,{artifactsConfig:t.artifactsConfig,cors:r.cors,method:r.method,preflightRoutes:n,route:r.route})}function syncChannelVirtualHandlers(e,t){if(areChannelRouteRegistrationsEqual(t.previous,t.next))return!1;removeChannelVirtualHandlers(e),registerChannelVirtualHandlers(e,{artifactsConfig:t.artifactsConfig,registrations:t.next});let n={};for(let[t,r]of Object.entries(e.options.virtual))t.startsWith(EVE_CHANNEL_VIRTUAL_ID_PREFIX)&&typeof r==`string`&&(n[t]=r);return replaceDevLiveVirtualModules(e,{entries:n,prefix:EVE_CHANNEL_VIRTUAL_ID_PREFIX})||console.warn("[eve:dev] channel routes changed but the dev bundler's virtual-module map was not captured; restart `eve dev` to mount the new routes."),e.routing.sync(),!0}function createChannelRouteKey(e){return`${e.method.toUpperCase()} ${e.route}`}function addChannelVirtualHandler(r,i){let a=createChannelRouteKey(i),s=`${EVE_CHANNEL_VIRTUAL_ID_PREFIX}${a}`,c=stringifyEsmImportSpecifier(resolvePackageSourceFilePath(`src/internal/nitro/routes/channel-dispatch.ts`)),l=stringifyEsmImportSpecifier(resolvePackageDependencyPath(`nitro`)),u=stringifyEsmImportSpecifier(resolvePackageDependencyPath(`nitro/h3`));if(i.method===`WEBSOCKET`){r.options.handlers.push({handler:s,route:i.route}),r.options.virtual[s]=[`import { defineWebSocketHandler } from ${l};`,`import { dispatchChannelWebSocketRequest } from ${c};`,`const config = ${JSON.stringify(i.artifactsConfig)};`,`export default defineWebSocketHandler((event) => dispatchChannelWebSocketRequest(event, ${JSON.stringify(a)}, config));`].join(`
2
+ `);return}r.options.handlers.push({handler:s,method:i.method,route:i.route}),i.cors!==void 0&&addChannelCorsPreflightHandler(r,{cors:i.cors,nitroH3ModulePath:u,preflightRoutes:i.preflightRoutes,route:i.route}),r.options.virtual[s]=[...i.cors===void 0?[]:[`import { handleCors } from ${u};`,`const cors = ${JSON.stringify(i.cors)};`],`import { dispatchChannelRequest } from ${c};`,`const config = ${JSON.stringify(i.artifactsConfig)};`,i.cors===void 0?`export default (event) => dispatchChannelRequest(event, ${JSON.stringify(a)}, config);`:[`export default (event) => {`,` const corsResponse = handleCors(event, cors);`,` if (corsResponse !== false) return corsResponse;`,` return dispatchChannelRequest(event, ${JSON.stringify(a)}, config);`,`};`].join(`
3
+ `)].join(`
4
+ `)}function addChannelCorsPreflightHandler(e,t){if(t.preflightRoutes.has(t.route))return;t.preflightRoutes.add(t.route);let n=`${EVE_CHANNEL_VIRTUAL_ID_PREFIX}${`OPTIONS ${t.route}`}`;e.options.handlers.push({handler:n,method:`OPTIONS`,route:t.route}),e.options.virtual[n]=[`import { handleCors } from ${t.nitroH3ModulePath};`,`const cors = ${JSON.stringify(t.cors)};`,`export default (event) => {`,` const corsResponse = handleCors(event, cors);`,` if (corsResponse !== false) return corsResponse;`,` return new Response(null, { status: 204 });`,`};`].join(`
5
+ `)}function removeChannelVirtualHandlers(e){for(let t=e.options.handlers.length-1;t>=0;--t){let n=e.options.handlers[t];n!==void 0&&isChannelVirtualHandler(n)&&e.options.handlers.splice(t,1)}for(let t of Object.keys(e.options.virtual))t.startsWith(EVE_CHANNEL_VIRTUAL_ID_PREFIX)&&delete e.options.virtual[t]}function isChannelVirtualHandler(e){return e.handler.startsWith(EVE_CHANNEL_VIRTUAL_ID_PREFIX)}function areChannelRouteRegistrationsEqual(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1){let r=e[n],i=t[n];if(r===void 0||i===void 0||r.method!==i.method||r.route!==i.route||!areChannelCorsOptionsEqual(r.cors,i.cors))return!1}return!0}function areChannelCorsOptionsEqual(e,t){return JSON.stringify(e)===JSON.stringify(t)}export{computeChannelRouteRegistrations,registerChannelVirtualHandlers,syncChannelVirtualHandlers};
@@ -1,2 +1,2 @@
1
- import{isLoopbackServerUrl}from"#shared/network-address.js";import{detectPackageManager}from"#setup/package-manager.js";import{eveDevArguments}from"#setup/primitives/index.js";import{toErrorMessage}from"#shared/errors.js";import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{startDevelopmentSandboxPrewarmInBackground}from"#execution/sandbox/development-prewarm.js";import{devBootPhase}from"#internal/dev-boot-progress.js";import{resolveDiscoveryProject}from"#discover/project.js";import{EVE_DEV_ENV_FLAG}from"#internal/application/optional-package-install.js";import{EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV,clearInitializedDevelopmentSandboxBackendNames,createDevelopmentSandboxRunId,getInitializedDevelopmentSandboxBackendNames}from"#execution/sandbox/development-run.js";import{pruneDevelopmentRuntimeArtifactsSnapshotsInBackground}from"#internal/nitro/dev-runtime-artifacts.js";import{build,createDevServer,prepare}from"nitro/builder";import{createApplicationNitro}from"#internal/nitro/host/create-application-nitro.js";import{prepareApplicationHost}from"#internal/nitro/host/prepare-application-host.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";import{DevelopmentServerState}from"#internal/nitro/host/dev-server-state.js";import{isEveServerHealthy}from"#shared/eve-server-health.js";import{pruneLocalSandboxTemplatesInBackground,stopDevelopmentSandboxResources}from"#execution/sandbox/bindings/local.js";import{DEFAULT_DEVELOPMENT_SERVER_PORT,MAX_DEVELOPMENT_SERVER_PORT_ATTEMPTS}from"#internal/nitro/host/ports.js";const MAX_ALLOWED_DEVELOPMENT_SERVER_PORT=65535,WORKFLOW_LOCAL_BASE_URL_ENV=`WORKFLOW_LOCAL_BASE_URL`,PORT_ENV=`PORT`,DEFAULT_DEVELOPMENT_SERVER_HOST=`127.0.0.1`,IPV6_WILDCARD_LISTEN_HOSTNAMES=new Set([`[::]`,`::`]);function normalizeDevelopmentServerClientUrl(e){let t=new URL(e);return IPV6_WILDCARD_LISTEN_HOSTNAMES.has(t.hostname)?(t.hostname=`[::1]`,t.toString()):t.hostname===`0.0.0.0`?(t.hostname=DEFAULT_DEVELOPMENT_SERVER_HOST,t.toString()):e}async function isActiveDevelopmentServerForApp(t){try{let n=await new DevelopmentServerState(await resolveDiscoveryProject(t.appRoot)).read();return n===void 0||!isLoopbackServerUrl(n)||!await isEveServerHealthy(n)?!1:new URL(n).origin===new URL(normalizeDevelopmentServerClientUrl(t.serverUrl)).origin}catch{return!1}}function isAddressInUseError(e){return e instanceof Error&&`code`in e&&e.code===`EADDRINUSE`}function resolveDevelopmentServerPort(e){let t=typeof e==`string`?Number(e):e??DEFAULT_DEVELOPMENT_SERVER_PORT;if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid development server port "${String(e)}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function readEnvironmentPort(){let e=process.env[PORT_ENV];if(e===void 0||e.trim()===``)return;let t=Number(e);if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid ${PORT_ENV} environment variable "${e}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}async function detectDevelopmentCommandPackageManager(e){try{return(await detectPackageManager(e)).kind}catch{return`pnpm`}}async function formatDevelopmentServerConnectCommand(e,t){let r=await detectDevelopmentCommandPackageManager(e);return[r,...eveDevArguments(r),t].join(` `)}async function createDevelopmentServerAlreadyRunningError(e,t){let n=await formatDevelopmentServerConnectCommand(e,t);return Error([`A dev server is already running for this eve agent.`,`To connect to the existing instance, run: ${n}`].join(`
2
- `))}function resolveDevelopmentServerPorts(e){let t=resolveDevelopmentServerPort(e.port);if(t===0||!e.retryOnAddressInUse)return[t];let n=[];for(let e=0;e<MAX_DEVELOPMENT_SERVER_PORT_ATTEMPTS;e+=1){let r=t+e;if(r>65535)break;n.push(r)}return n}function installWorkflowLocalQueueEnvironment(e){let t=process.env[WORKFLOW_LOCAL_BASE_URL_ENV],n=process.env[PORT_ENV],r=new URL(normalizeDevelopmentServerClientUrl(e));return process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=r.origin,r.port&&(process.env[PORT_ENV]=r.port),()=>{t===void 0?delete process.env[WORKFLOW_LOCAL_BASE_URL_ENV]:process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=t,n===void 0?delete process.env[PORT_ENV]:process.env[PORT_ENV]=n}}function attachTemporarySocketErrorHandler(e){let onSocketError=()=>{};return e.once(`error`,onSocketError),()=>{e.off(`error`,onSocketError)}}function shouldProxyDevelopmentServerWebSocketUpgrades(e){return e.options.features.websocket===!0||e.options.experimental.websocket===!0}function guardDevelopmentServerWebSocketUpgrades(e,t){let n=t.upgrade.bind(t),r=shouldProxyDevelopmentServerWebSocketUpgrades(e);t.upgrade=async(e,t,i)=>{if(!r){t.destroyed||t.destroy();return}let a=attachTemporarySocketErrorHandler(t);try{await n(e,t,i)}catch{t.destroyed||t.destroy()}finally{a()}}}async function closeDevelopmentServerResources(e){let t=[],attempt=async e=>{try{return await e(),!0}catch(e){return t.push(e),!1}},n=e.authoredSourceWatcher;n!==void 0&&await attempt(()=>n.close());let r=e.devServer,i=r===void 0?!0:await attempt(()=>r.close()),a=e.nitro;return a!==void 0&&await attempt(()=>a.close()),await attempt(()=>stopDevelopmentSandboxResources({backendNames:getInitializedDevelopmentSandboxBackendNames(e.developmentSandboxRunId),devRunId:e.developmentSandboxRunId,log:e=>console.warn(`[eve:dev] ${e}`)})),{errors:t,listenerClosed:i}}function createDevelopmentServerCleanupError(e){if(e.length!==0){if(e.length===1){let t=e[0];return t instanceof Error?t:Error(`Failed to close the development server: ${toErrorMessage(t)}`,{cause:t})}return AggregateError(e,`Multiple development-server resources failed to close.`)}}function createDevelopmentServerStartupCleanupError(e,t){return AggregateError([e,...t],`${toErrorMessage(e)} Cleanup also failed.`,{cause:e})}async function listenForDevelopmentServer(e){let t=resolveDevelopmentServerPorts({port:e.port,retryOnAddressInUse:e.retryOnAddressInUse}),n;for(let r of t){let t=e.devServer.listen({hostname:e.host,port:r,silent:!0});try{return await t.ready(),t}catch(r){if(n=r,await t.close().catch(()=>{}),!isAddressInUseError(r)||!e.retryOnAddressInUse)throw r}}throw Error(`Failed to start Nitro dev server after ${t.length} attempts. Tried ports ${t.join(`, `)}.`,{cause:n})}async function startNitroDevelopmentServer(t,n){process.env[EVE_DEV_ENV_FLAG]??=`1`;let r=await resolveDiscoveryProject(t);loadDevelopmentEnvironmentFiles(r.appRoot);let u=readEnvironmentPort(),p=n.port??u,m=n.host!==void 0||n.port!==void 0||u!==void 0,h=new DevelopmentServerState(r),g=await h.read();if(g!==void 0&&isLoopbackServerUrl(g)&&await isEveServerHealthy(g)){if(n.existing===`attach-if-unconfigured`&&!m)return{handle:{kind:`existing`,appRoot:r.appRoot,url:g},close:void 0};throw await createDevelopmentServerAlreadyRunningError(r.appRoot,g)}let _=process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV],v=createDevelopmentSandboxRunId();process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV]=v;let y,b,x,S;try{let e=await devBootPhase(`compiling agent`,()=>prepareApplicationHost(r.appRoot,{dev:!0}),n.onBootProgress);pruneDevelopmentRuntimeArtifactsSnapshotsInBackground(e.appRoot);let t=resolveNitroCompiledArtifactsSource(createNitroArtifactsConfig({appRoot:e.appRoot,dev:!0}));startDevelopmentSandboxPrewarmInBackground({appRoot:e.appRoot,compiledArtifactsSource:t}),pruneLocalSandboxTemplatesInBackground(e.appRoot);let i=await devBootPhase(`creating dev server`,()=>createApplicationNitro(e,!0),n.onBootProgress);y=i,b=createDevServer(i);let o=b;guardDevelopmentServerWebSocketUpgrades(i,b);let s=n.host??i.options.devServer.hostname??DEFAULT_DEVELOPMENT_SERVER_HOST,c=p===void 0,l=await devBootPhase(`binding port`,()=>listenForDevelopmentServer({devServer:o,host:s,port:p,retryOnAddressInUse:c}),n.onBootProgress);if(!l.url)throw Error(`Nitro dev server did not expose a URL.`);let u=normalizeDevelopmentServerClientUrl(l.url);x=installWorkflowLocalQueueEnvironment(u),await devBootPhase(`building dev bundle`,async()=>{await prepare(i),await build(i)},n.onBootProgress),S=await devBootPhase(`starting file watcher`,async()=>{let{startAuthoredSourceWatcher:t}=await import(`#internal/nitro/host/dev-authored-source-watcher.js`);return t({nitro:i,preparedHost:e})},n.onBootProgress),await h.write(u);let d=x;if(d===void 0)throw Error(`Workflow local queue environment was not initialized.`);let f=S,m=b,g=i,C;return{handle:{kind:`started`,appRoot:r.appRoot,url:u},close:()=>(C??=(async()=>{let e=await closeDevelopmentServerResources({authoredSourceWatcher:f,devServer:m,developmentSandboxRunId:v,nitro:g});e.listenerClosed&&await h.remove().catch(()=>{});try{let t=createDevelopmentServerCleanupError(e.errors);if(t!==void 0)throw t}finally{clearInitializedDevelopmentSandboxBackendNames(v),d(),restoreDevelopmentSandboxRunId(_)}})(),C)}}catch(e){let t=await closeDevelopmentServerResources({authoredSourceWatcher:S,devServer:b,developmentSandboxRunId:v,nitro:y}),n=[...t.errors];throw x?.(),clearInitializedDevelopmentSandboxBackendNames(v),t.listenerClosed&&await h.remove().catch(()=>{}),restoreDevelopmentSandboxRunId(_),n.length>0?createDevelopmentServerStartupCleanupError(e,n):e}}function createDevelopmentServer(e,t={}){let n,r;return{start(){if(n!==void 0)throw Error(`DevelopmentServer.start() was already called.`);return n=startNitroDevelopmentServer(e,t).then(({handle:e,close:t})=>(r=t,e)),n},async close(){n!==void 0&&(await n.catch(()=>void 0),await r?.())}}}function restoreDevelopmentSandboxRunId(e){if(e===void 0){delete process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV];return}process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV]=e}export{createDevelopmentServer,isActiveDevelopmentServerForApp,normalizeDevelopmentServerClientUrl};
1
+ import{EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH}from"#protocol/routes.js";import{isLoopbackServerUrl}from"#shared/network-address.js";import{detectPackageManager}from"#setup/package-manager.js";import{eveDevArguments}from"#setup/primitives/index.js";import{toErrorMessage}from"#shared/errors.js";import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{startDevelopmentSandboxPrewarmInBackground}from"#execution/sandbox/development-prewarm.js";import{devBootPhase}from"#internal/dev-boot-progress.js";import{resolveDiscoveryProject}from"#discover/project.js";import{EVE_DEV_ENV_FLAG}from"#internal/application/optional-package-install.js";import{EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV,clearInitializedDevelopmentSandboxBackendNames,createDevelopmentSandboxRunId,getInitializedDevelopmentSandboxBackendNames}from"#execution/sandbox/development-run.js";import{pruneDevelopmentRuntimeArtifactsSnapshotsInBackground}from"#internal/nitro/dev-runtime-artifacts.js";import{build,createDevServer,prepare}from"nitro/builder";import{createApplicationNitro}from"#internal/nitro/host/create-application-nitro.js";import{prepareApplicationHost}from"#internal/nitro/host/prepare-application-host.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";import{DevelopmentServerState}from"#internal/nitro/host/dev-server-state.js";import{isEveServerHealthy}from"#shared/eve-server-health.js";import{handleDevRuntimeArtifactsRequest}from"#internal/nitro/routes/dev-runtime-artifacts.js";import{pruneLocalSandboxTemplatesInBackground,stopDevelopmentSandboxResources}from"#execution/sandbox/bindings/local.js";import{DEFAULT_DEVELOPMENT_SERVER_PORT,MAX_DEVELOPMENT_SERVER_PORT_ATTEMPTS}from"#internal/nitro/host/ports.js";const MAX_ALLOWED_DEVELOPMENT_SERVER_PORT=65535,WORKFLOW_LOCAL_BASE_URL_ENV=`WORKFLOW_LOCAL_BASE_URL`,PORT_ENV=`PORT`,DEFAULT_DEVELOPMENT_SERVER_HOST=`127.0.0.1`,IPV6_WILDCARD_LISTEN_HOSTNAMES=new Set([`[::]`,`::`]);function normalizeDevelopmentServerClientUrl(e){let t=new URL(e);return IPV6_WILDCARD_LISTEN_HOSTNAMES.has(t.hostname)?(t.hostname=`[::1]`,t.toString()):t.hostname===`0.0.0.0`?(t.hostname=DEFAULT_DEVELOPMENT_SERVER_HOST,t.toString()):e}async function isActiveDevelopmentServerForApp(e){try{let n=await new DevelopmentServerState(await resolveDiscoveryProject(e.appRoot)).read();return n===void 0||!isLoopbackServerUrl(n)||!await isEveServerHealthy(n)?!1:new URL(n).origin===new URL(normalizeDevelopmentServerClientUrl(e.serverUrl)).origin}catch{return!1}}function isAddressInUseError(e){return e instanceof Error&&`code`in e&&e.code===`EADDRINUSE`}function resolveDevelopmentServerPort(e){let t=typeof e==`string`?Number(e):e??DEFAULT_DEVELOPMENT_SERVER_PORT;if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid development server port "${String(e)}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function readEnvironmentPort(){let e=process.env[PORT_ENV];if(e===void 0||e.trim()===``)return;let t=Number(e);if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid ${PORT_ENV} environment variable "${e}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}async function detectDevelopmentCommandPackageManager(e){try{return(await detectPackageManager(e)).kind}catch{return`pnpm`}}async function formatDevelopmentServerConnectCommand(e,t){let n=await detectDevelopmentCommandPackageManager(e);return[n,...eveDevArguments(n),t].join(` `)}async function createDevelopmentServerAlreadyRunningError(e,t){let n=await formatDevelopmentServerConnectCommand(e,t);return Error([`A dev server is already running for this eve agent.`,`To connect to the existing instance, run: ${n}`].join(`
2
+ `))}function resolveDevelopmentServerPorts(e){let t=resolveDevelopmentServerPort(e.port);if(t===0||!e.retryOnAddressInUse)return[t];let n=[];for(let e=0;e<MAX_DEVELOPMENT_SERVER_PORT_ATTEMPTS;e+=1){let r=t+e;if(r>65535)break;n.push(r)}return n}function installWorkflowLocalQueueEnvironment(e){let t=process.env[WORKFLOW_LOCAL_BASE_URL_ENV],n=process.env[PORT_ENV],r=new URL(normalizeDevelopmentServerClientUrl(e));return process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=r.origin,r.port&&(process.env[PORT_ENV]=r.port),()=>{t===void 0?delete process.env[WORKFLOW_LOCAL_BASE_URL_ENV]:process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=t,n===void 0?delete process.env[PORT_ENV]:process.env[PORT_ENV]=n}}function attachTemporarySocketErrorHandler(e){let onSocketError=()=>{};return e.once(`error`,onSocketError),()=>{e.off(`error`,onSocketError)}}function shouldProxyDevelopmentServerWebSocketUpgrades(e){return e.options.features.websocket===!0||e.options.experimental.websocket===!0}function guardDevelopmentServerWebSocketUpgrades(e,t){let n=t.upgrade.bind(t),r=shouldProxyDevelopmentServerWebSocketUpgrades(e);t.upgrade=async(e,t,i)=>{if(!r){t.destroyed||t.destroy();return}let a=attachTemporarySocketErrorHandler(t);try{await n(e,t,i)}catch{t.destroyed||t.destroy()}finally{a()}}}function addDevelopmentRuntimeArtifactsRebuildHandler(t){t.nitro.options.devHandlers.push({route:EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,handler:async e=>{let n=e.node?.req.url??``;return new URL(n,`http://localhost`).searchParams.get(`force`)===`1`?await t.watcher.rebuild():await t.watcher.flush(),handleDevRuntimeArtifactsRequest({appRoot:t.appRoot})}})}async function closeDevelopmentServerResources(e){let t=[],attempt=async e=>{try{return await e(),!0}catch(e){return t.push(e),!1}},n=e.authoredSourceWatcher;n!==void 0&&await attempt(()=>n.close());let r=e.devServer,i=r===void 0?!0:await attempt(()=>r.close()),a=e.nitro;return a!==void 0&&await attempt(()=>a.close()),await attempt(()=>stopDevelopmentSandboxResources({backendNames:getInitializedDevelopmentSandboxBackendNames(e.developmentSandboxRunId),devRunId:e.developmentSandboxRunId,log:e=>console.warn(`[eve:dev] ${e}`)})),{errors:t,listenerClosed:i}}function createDevelopmentServerCleanupError(e){if(e.length!==0){if(e.length===1){let t=e[0];return t instanceof Error?t:Error(`Failed to close the development server: ${toErrorMessage(t)}`,{cause:t})}return AggregateError(e,`Multiple development-server resources failed to close.`)}}function createDevelopmentServerStartupCleanupError(e,t){return AggregateError([e,...t],`${toErrorMessage(e)} Cleanup also failed.`,{cause:e})}async function listenForDevelopmentServer(e){let t=resolveDevelopmentServerPorts({port:e.port,retryOnAddressInUse:e.retryOnAddressInUse}),n;for(let r of t){let t=e.devServer.listen({hostname:e.host,port:r,silent:!0});try{return await t.ready(),t}catch(r){if(n=r,await t.close().catch(()=>{}),!isAddressInUseError(r)||!e.retryOnAddressInUse)throw r}}throw Error(`Failed to start Nitro dev server after ${t.length} attempts. Tried ports ${t.join(`, `)}.`,{cause:n})}async function startNitroDevelopmentServer(e,n){process.env[EVE_DEV_ENV_FLAG]??=`1`;let r=await resolveDiscoveryProject(e);loadDevelopmentEnvironmentFiles(r.appRoot);let i=readEnvironmentPort(),u=n.port??i,p=n.host!==void 0||n.port!==void 0||i!==void 0,m=new DevelopmentServerState(r),h=await m.read();if(h!==void 0&&isLoopbackServerUrl(h)&&await isEveServerHealthy(h)){if(n.existing===`attach-if-unconfigured`&&!p)return{handle:{kind:`existing`,appRoot:r.appRoot,url:h},close:void 0};throw await createDevelopmentServerAlreadyRunningError(r.appRoot,h)}let g=process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV],_=createDevelopmentSandboxRunId();process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV]=_;let v,y,b,x;try{let e=await devBootPhase(`compiling agent`,()=>prepareApplicationHost(r.appRoot,{dev:!0}),n.onBootProgress);pruneDevelopmentRuntimeArtifactsSnapshotsInBackground(e.appRoot);let t=resolveNitroCompiledArtifactsSource(createNitroArtifactsConfig({appRoot:e.appRoot,dev:!0}));startDevelopmentSandboxPrewarmInBackground({appRoot:e.appRoot,compiledArtifactsSource:t}),pruneLocalSandboxTemplatesInBackground(e.appRoot);let i=await devBootPhase(`creating dev server`,()=>createApplicationNitro(e,!0),n.onBootProgress);v=i,y=createDevServer(i);let a=y;guardDevelopmentServerWebSocketUpgrades(i,y);let o=n.host??i.options.devServer.hostname??DEFAULT_DEVELOPMENT_SERVER_HOST,s=u===void 0,c=await devBootPhase(`binding port`,()=>listenForDevelopmentServer({devServer:a,host:o,port:u,retryOnAddressInUse:s}),n.onBootProgress);if(!c.url)throw Error(`Nitro dev server did not expose a URL.`);let l=normalizeDevelopmentServerClientUrl(c.url);b=installWorkflowLocalQueueEnvironment(l),await devBootPhase(`building dev bundle`,async()=>{await prepare(i),await build(i)},n.onBootProgress),x=await devBootPhase(`starting file watcher`,async()=>{let{startAuthoredSourceWatcher:t}=await import(`#internal/nitro/host/dev-authored-source-watcher.js`);return t({nitro:i,preparedHost:e})},n.onBootProgress),addDevelopmentRuntimeArtifactsRebuildHandler({appRoot:r.appRoot,nitro:i,watcher:x}),await m.write(l);let d=b;if(d===void 0)throw Error(`Workflow local queue environment was not initialized.`);let f=x,p=y,h=i,S;return{handle:{kind:`started`,appRoot:r.appRoot,url:l},close:()=>(S??=(async()=>{let e=await closeDevelopmentServerResources({authoredSourceWatcher:f,devServer:p,developmentSandboxRunId:_,nitro:h});e.listenerClosed&&await m.remove().catch(()=>{});try{let t=createDevelopmentServerCleanupError(e.errors);if(t!==void 0)throw t}finally{clearInitializedDevelopmentSandboxBackendNames(_),d(),restoreDevelopmentSandboxRunId(g)}})(),S)}}catch(e){let t=await closeDevelopmentServerResources({authoredSourceWatcher:x,devServer:y,developmentSandboxRunId:_,nitro:v}),n=[...t.errors];throw b?.(),clearInitializedDevelopmentSandboxBackendNames(_),t.listenerClosed&&await m.remove().catch(()=>{}),restoreDevelopmentSandboxRunId(g),n.length>0?createDevelopmentServerStartupCleanupError(e,n):e}}function createDevelopmentServer(e,t={}){let n,r;return{start(){if(n!==void 0)throw Error(`DevelopmentServer.start() was already called.`);return n=startNitroDevelopmentServer(e,t).then(({handle:e,close:t})=>(r=t,e)),n},async close(){n!==void 0&&(await n.catch(()=>void 0),await r?.())}}}function restoreDevelopmentSandboxRunId(e){if(e===void 0){delete process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV];return}process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV]=e}export{createDevelopmentServer,isActiveDevelopmentServerForApp,normalizeDevelopmentServerClientUrl};
@@ -1 +1 @@
1
- import*as workflowRuntime from"#compiled/@workflow/core/runtime.js";export*from"#compiled/@workflow/core/runtime.js";function setWorld(e){workflowRuntime.setWorld(e)}export{setWorld};
1
+ import*as workflowRuntime from"#compiled/@workflow/core/runtime.js";export*from"#compiled/@workflow/core/runtime.js";process.env.WORKFLOW_TURBO=`0`;function setWorld(e){workflowRuntime.setWorld(e)}export{setWorld};
@@ -1 +1 @@
1
- function connectionProtocols(e){return[e.mcp?`mcp`:null,e.openapi?`openapi`:null].filter(e=>e!==null)}const INTEGRATIONS=[{slug:`slack`,name:`Slack`,kind:`channel`,tagline:`Mention your agent in channels and DMs, with Connect-managed auth.`,surfaces:{scaffoldable:!0,gallery:!0}},{slug:`discord`,name:`Discord`,kind:`channel`,tagline:`Run your agent as a Discord bot across servers and threads.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`teams`,name:`Microsoft Teams`,kind:`channel`,tagline:`Bring your agent into Teams chats and channels.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`telegram`,name:`Telegram`,kind:`channel`,tagline:`Connect your agent to a Telegram bot for 1:1 and group chats.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`twilio`,name:`Twilio`,kind:`channel`,tagline:`Reach users over SMS and WhatsApp through Twilio.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`github`,name:`GitHub`,kind:`channel`,tagline:`Drive your agent from issues, pull requests, and comments.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`linear-agent`,name:`Linear Agent`,kind:`channel`,tagline:`Delegate Linear issues and comments to your agent through Linear's Agent Sessions.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`eve`,name:`eve Web Chat`,kind:`channel`,tagline:`Embed a first-party web chat UI backed by your agent.`,surfaces:{scaffoldable:!0,gallery:!0}},{slug:`linear`,name:`Linear`,kind:`connection`,tagline:`Issues, projects, cycles, and comments via Linear's MCP server.`,surfaces:{scaffoldable:!0,gallery:!0},connection:{description:`Linear workspace: issues, projects, cycles, and comments.`,mcp:{url:`https://mcp.linear.app/sse`}}},{slug:`notion`,name:`Notion`,kind:`connection`,tagline:`Search and edit Notion pages and databases over MCP or OpenAPI.`,surfaces:{scaffoldable:!0,gallery:!0},connection:{description:`Notion workspace: search and edit pages and databases.`,mcp:{url:`https://mcp.notion.com/mcp`},openapi:{spec:`https://developers.notion.com/openapi.json`,baseUrl:`https://api.notion.com`,headers:{"Notion-Version":`2022-06-28`}}}},{slug:`datadog`,name:`Datadog`,kind:`connection`,tagline:`Query metrics, monitors, and logs through Datadog's MCP server.`,surfaces:{scaffoldable:!0,gallery:!0},connection:{description:`Datadog: query metrics, monitors, logs, and incidents.`,mcp:{url:`https://mcp.datadoghq.com/api/mcp`}}},{slug:`honeycomb`,name:`Honeycomb`,kind:`connection`,tagline:`Explore traces and run queries through Honeycomb's MCP server.`,surfaces:{scaffoldable:!0,gallery:!0},connection:{description:`Honeycomb: explore traces, run queries, and inspect datasets.`,mcp:{url:`https://mcp.honeycomb.io/mcp`}}}];new Map(INTEGRATIONS.map(e=>[e.slug,e]));function integrationsByKind(t){return INTEGRATIONS.filter(e=>e.kind===t)}function connectionEntries(){return integrationsByKind(`connection`)}function channelEntries(){return integrationsByKind(`channel`)}export{channelEntries,connectionEntries,connectionProtocols};
1
+ function connectionProtocols(e){return[e.mcp?`mcp`:null,e.openapi?`openapi`:null].filter(e=>e!==null)}const INTEGRATIONS=[{slug:`slack`,name:`Slack`,kind:`channel`,tagline:`Mention your agent in channels and DMs, with Connect-managed auth.`,surfaces:{scaffoldable:!0,gallery:!0}},{slug:`discord`,name:`Discord`,kind:`channel`,tagline:`Run your agent as a Discord bot across servers and threads.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`teams`,name:`Microsoft Teams`,kind:`channel`,tagline:`Bring your agent into Teams chats and channels.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`telegram`,name:`Telegram`,kind:`channel`,tagline:`Connect your agent to a Telegram bot for 1:1 and group chats.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`twilio`,name:`Twilio`,kind:`channel`,tagline:`Reach users over SMS and WhatsApp through Twilio.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`github`,name:`GitHub`,kind:`channel`,tagline:`Drive your agent from issues, pull requests, and comments.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`linear-agent`,name:`Linear Agent`,kind:`channel`,tagline:`Delegate Linear issues and comments to your agent through Linear's Agent Sessions.`,surfaces:{scaffoldable:!1,gallery:!0}},{slug:`eve`,name:`eve Web Chat`,kind:`channel`,tagline:`Embed a first-party web chat UI backed by your agent.`,surfaces:{scaffoldable:!0,gallery:!0}},{slug:`linear`,name:`Linear`,kind:`connection`,tagline:`Issues, projects, cycles, and comments via Linear's MCP server.`,surfaces:{scaffoldable:!0,gallery:!0},connection:{description:`Linear workspace: issues, projects, cycles, and comments.`,mcp:{url:`https://mcp.linear.app/mcp`}}},{slug:`notion`,name:`Notion`,kind:`connection`,tagline:`Search and edit Notion pages and databases over MCP or OpenAPI.`,surfaces:{scaffoldable:!0,gallery:!0},connection:{description:`Notion workspace: search and edit pages and databases.`,mcp:{url:`https://mcp.notion.com/mcp`},openapi:{spec:`https://developers.notion.com/openapi.json`,baseUrl:`https://api.notion.com`,headers:{"Notion-Version":`2022-06-28`}}}},{slug:`datadog`,name:`Datadog`,kind:`connection`,tagline:`Query metrics, monitors, and logs through Datadog's MCP server.`,surfaces:{scaffoldable:!0,gallery:!0},connection:{description:`Datadog: query metrics, monitors, logs, and incidents.`,mcp:{url:`https://mcp.datadoghq.com/api/mcp`}}},{slug:`honeycomb`,name:`Honeycomb`,kind:`connection`,tagline:`Explore traces and run queries through Honeycomb's MCP server.`,surfaces:{scaffoldable:!0,gallery:!0},connection:{description:`Honeycomb: explore traces, run queries, and inspect datasets.`,mcp:{url:`https://mcp.honeycomb.io/mcp`}}}];new Map(INTEGRATIONS.map(e=>[e.slug,e]));function integrationsByKind(t){return INTEGRATIONS.filter(e=>e.kind===t)}function connectionEntries(){return integrationsByKind(`connection`)}function channelEntries(){return integrationsByKind(`channel`)}export{channelEntries,connectionEntries,connectionProtocols};
@@ -3,6 +3,7 @@ import type { SessionAuthContext } from "#channel/types.js";
3
3
  import { type AuthFn } from "#public/channels/auth.js";
4
4
  import { type UploadPolicyInput } from "#public/channels/upload-policy.js";
5
5
  import { type Channel, type ChannelEvents, type ChannelSessionOps } from "#public/definitions/defineChannel.js";
6
+ import type { ChannelMethod } from "#public/definitions/channel.js";
6
7
  /**
7
8
  * Event-handler channel context exposed by `eveChannel({ events })`. The default eve HTTP channel
8
9
  * has no platform-specific state, so handlers receive session continuation operations plus the `SessionContext` third arg from {@link ChannelEvents}.
@@ -10,6 +11,30 @@ import { type Channel, type ChannelEvents, type ChannelSessionOps } from "#publi
10
11
  export type EveEventContext = ChannelSessionOps;
11
12
  /** Runtime stream-event handlers supported by `eveChannel({ events })`. */
12
13
  export type EveChannelEvents = ChannelEvents<EveEventContext>;
14
+ export interface EveChannelCorsOptions {
15
+ /**
16
+ * Allowed request origin. Pass a single origin string, an exact-origin list,
17
+ * `"null"`, or `"*"`. Omit for `"*"`.
18
+ */
19
+ readonly origin?: "*" | "null" | string | readonly string[];
20
+ /** Methods emitted on preflight responses. Omit for `"*"`. */
21
+ readonly methods?: "*" | readonly ChannelMethod[];
22
+ /** Request headers emitted on preflight responses. Omit for `"*"`. */
23
+ readonly allowedHeaders?: "*" | readonly string[];
24
+ /** Response headers exposed to browser callers. Omit for `"*"`. */
25
+ readonly exposedHeaders?: "*" | readonly string[];
26
+ /** Whether to emit `access-control-allow-credentials: true`. */
27
+ readonly credentials?: boolean;
28
+ /** Max age, in seconds, emitted on preflight responses. */
29
+ readonly maxAge?: number | false;
30
+ /** Preflight response status code. Defaults to 204. */
31
+ readonly preflightStatus?: number;
32
+ }
33
+ /**
34
+ * Higher-level CORS policy for the default eve HTTP channel. Pass `true` for
35
+ * fully permissive browser access, or pass an options object to narrow it.
36
+ */
37
+ export type EveChannelCors = boolean | EveChannelCorsOptions;
13
38
  /** Low-level eve HTTP handle exposed to `eveChannel({ onMessage })`. */
14
39
  export interface EveHandle {
15
40
  /** Route-auth result for the request; `onMessage` chooses session auth by returning `{ auth }`. */
@@ -53,6 +78,12 @@ export interface EveChannelInput {
53
78
  * types); `"disabled"` rejects every attachment; a partial config is merged onto the default. Violations reject with 413 (too large) or 415 (bad type).
54
79
  */
55
80
  readonly uploadPolicy?: UploadPolicyInput;
81
+ /**
82
+ * Browser CORS policy for the eve HTTP routes. Omit or pass `false` to leave
83
+ * CORS untouched, pass `true` for fully permissive CORS, or pass an options
84
+ * object to narrow the policy.
85
+ */
86
+ readonly cors?: EveChannelCors;
56
87
  /**
57
88
  * Pre-dispatch hook for inbound eve HTTP messages. Runs after route auth and body
58
89
  * parsing, before runtime dispatch.
@@ -1,2 +1,2 @@
1
- import{createLogger,logError}from"#internal/logging.js";import{hasInternalRefScheme}from"#internal/attachments/url-refs.js";import{EVE_MESSAGE_STREAM_CONTENT_TYPE,EVE_MESSAGE_STREAM_FORMAT,EVE_MESSAGE_STREAM_VERSION,EVE_SESSION_ID_HEADER,EVE_STREAM_FORMAT_HEADER,EVE_STREAM_VERSION_HEADER}from"#protocol/message.js";import{isInputResponse}from"#runtime/input/types.js";import{parseJsonObject}from"#shared/json.js";import"ai";import{parseSessionCallback}from"#channel/session-callback.js";import{routeAuth}from"#public/channels/auth.js";import{GET,POST,defineChannel}from"#public/definitions/defineChannel.js";import{collectUploadPolicyViolations,formatUploadPolicyViolation,mergeUploadPolicy}from"#public/channels/upload-policy.js";const log=createLogger(`eve.channel`);function defaultEveAuth(e){return e.eve.caller}function eveChannel(e){let t=mergeUploadPolicy(e.uploadPolicy);return defineChannel({routes:[POST(`/eve/v1/session`,async(n,{send:r})=>{let i=await routeAuth(n,e.auth);if(i instanceof Response)return i;let a=i,o;try{o=await n.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof o!=`object`||!o)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let s=parseCreateBody(o);if(s instanceof Response)return s;let c=checkUploadPolicy(s,t);if(c!==null)return c;let l=await resolveOnMessage({auth:a,config:e,message:s.message,request:n});if(l instanceof Response)return l;if(!l.dispatch)return droppedMessageResponse();let u=`eve:${crypto.randomUUID()}`,d=await r(createSendPayload(s,mergeContext(s.context,l.context)),{auth:l.auth,callback:s.callback,continuationToken:u,mode:s.mode});return Response.json({continuationToken:d.continuationToken,ok:!0,sessionId:d.id},{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:d.id},status:202})}),POST(`/eve/v1/session/:sessionId`,async(n,{send:r,getSession:i,params:a})=>{let o=await routeAuth(n,e.auth);if(o instanceof Response)return o;let s=o,c=a.sessionId;if(!c)return Response.json({error:`Missing session id.`,ok:!1},{status:400});try{i(c)}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}let l;try{l=await n.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof l!=`object`||!l)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let u=parseContinueBody(l);if(u instanceof Response)return u;let d=checkUploadPolicy(u,t);if(d!==null)return d;let f=u.context,p=s;if(u.message!==void 0){let t=await resolveOnMessage({auth:s,config:e,message:u.message,request:n,sessionId:c});if(t instanceof Response)return t;if(!t.dispatch)return droppedMessageResponse();f=mergeContext(u.context,t.context),p=t.auth}let m=await r({inputResponses:u.inputResponses,message:u.message,context:f,outputSchema:u.outputSchema},{auth:p,continuationToken:u.continuationToken});return Response.json({ok:!0,sessionId:m.id},{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:m.id},status:200})}),GET(`/eve/v1/session/:sessionId/stream`,async(t,{getSession:n,params:c})=>{let l=await routeAuth(t,e.auth);if(l instanceof Response)return l;let u=c.sessionId;if(!u)return Response.json({error:`Missing session id.`,ok:!1},{status:400});let d=parseStartIndex(t);if(d instanceof Response)return d;try{let e=serializeAsNdjson(await n(u).getEventStream({startIndex:d}));return new Response(e,{headers:{"cache-control":`no-store, no-transform`,"content-type":EVE_MESSAGE_STREAM_CONTENT_TYPE,"x-accel-buffering":`no`,[EVE_SESSION_ID_HEADER]:u,[EVE_STREAM_FORMAT_HEADER]:EVE_MESSAGE_STREAM_FORMAT,[EVE_STREAM_VERSION_HEADER]:EVE_MESSAGE_STREAM_VERSION}})}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}})],events:e.events})}async function resolveOnMessage(e){let n=e.config.onMessage??defaultOnMessage,r;try{r=await n({eve:e.sessionId===void 0?{caller:e.auth,request:e.request}:{caller:e.auth,request:e.request,sessionId:e.sessionId}},e.message)}catch(n){let r=logError(log,`onMessage handler failed`,n,{sessionId:e.sessionId});return Response.json({error:`onMessage handler failed.`,errorId:r,ok:!1},{status:500})}return r==null?{dispatch:!1}:r.context===void 0?{auth:r.auth,dispatch:!0}:{auth:r.auth,context:r.context,dispatch:!0}}function defaultOnMessage(e){return{auth:defaultEveAuth(e)}}function droppedMessageResponse(){return new Response(null,{headers:{"cache-control":`no-store`},status:204})}function parseCreateBody(e){let t=parseMessageField(e.message);if(t instanceof Response)return t;let n=parseClientContextField(e.clientContext);if(n instanceof Response)return n;let r=parseCallbackField(e.callback);if(r instanceof Response)return r;let i=parseModeField(e.mode);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:t===void 0?Response.json({error:`Missing or empty 'message' field.`,ok:!1},{status:400}):{callback:r,message:t,mode:i,context:n,outputSchema:a}}function parseContinueBody(e){let t=typeof e.continuationToken==`string`&&e.continuationToken.length>0?e.continuationToken:void 0;if(t===void 0)return Response.json({error:`Missing or empty 'continuationToken' field.`,ok:!1},{status:400});let n=parseMessageField(e.message);if(n instanceof Response)return n;let r=parseInputResponses(e.inputResponses);if(r instanceof Response)return r;let i=parseClientContextField(e.clientContext);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:n===void 0&&r===void 0?Response.json({error:`Expected a non-empty 'message', a non-empty 'inputResponses' array, or both.`,ok:!1},{status:400}):{message:n,continuationToken:t,inputResponses:r,context:i,outputSchema:a}}function createSendPayload(e,t=e.context){if(t===void 0&&e.outputSchema===void 0)return e.message;let n={message:e.message};return t!==void 0&&(n.context=t),e.outputSchema!==void 0&&(n.outputSchema=e.outputSchema),n}function parseOutputSchemaField(e){if(e!==void 0)try{return parseJsonObject(e)}catch{return Response.json({error:`Expected 'outputSchema' to be a JSON-serializable object.`,ok:!1},{status:400})}}function parseCallbackField(e){if(e===void 0)return;let t=parseSessionCallback(e);return t.ok?t.callback:Response.json({error:t.message,ok:!1},{status:400})}function parseModeField(e){if(e!==void 0)return e===`conversation`||e===`task`?e:Response.json({error:`Expected 'mode' to be either 'conversation' or 'task'.`,ok:!1},{status:400})}function parseMessageField(e){if(e===void 0)return;if(typeof e==`string`)return e.length>0?e:void 0;if(!Array.isArray(e))return Response.json({error:`Expected 'message' to be a string or an array of text/file parts.`,ok:!1},{status:400});if(e.length===0)return;let t=[];for(let n of e){let e=parseMessagePart(n);if(e instanceof Response)return e;t.push(e)}return t}function parseMessagePart(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected each message part to be an object.`,ok:!1},{status:400});let t=e;if(t.type===`text`)return typeof t.text!=`string`||t.text.length===0?Response.json({error:`Text parts require a non-empty 'text' string.`,ok:!1},{status:400}):{type:`text`,text:t.text};if(t.type===`file`){if(typeof t.mediaType!=`string`||t.mediaType.length===0)return Response.json({error:`File parts require a non-empty 'mediaType' string.`,ok:!1},{status:400});if(typeof t.data!=`string`)return Response.json({error:`File parts require a 'data' string (base64, data URL, or URL).`,ok:!1},{status:400});if(hasInternalRefScheme(t.data))return Response.json({error:`File part 'data' must not use a framework-internal ref scheme.`,ok:!1},{status:400});let e={type:`file`,mediaType:t.mediaType,data:t.data};return typeof t.filename==`string`&&t.filename.length>0&&(e.filename=t.filename),e}return Response.json({error:`Unsupported message part type "${String(t.type)}". Use 'text' or 'file'.`,ok:!1},{status:400})}function checkUploadPolicy(e,t){if(!e.message)return null;let n=collectUploadPolicyViolations(e.message,t);if(n.length===0)return null;let[r]=n;if(!r)return null;let i=r.kind===`too-large`?413:415;return Response.json({error:formatUploadPolicyViolation(r),ok:!1,violations:n.map(e=>e.kind===`too-large`?{byteLength:e.byteLength,filename:e.filename,kind:e.kind,limit:e.limit,mediaType:e.mediaType}:{allowedMediaTypes:e.allowedMediaTypes,filename:e.filename,kind:e.kind,mediaType:e.mediaType})},{status:i})}function parseInputResponses(e){if(e===void 0)return;if(!Array.isArray(e)||e.length===0)return Response.json({error:`Expected 'inputResponses' to be a non-empty array.`,ok:!1},{status:400});let t=e.filter(isInputResponse);return t.length===e.length?t:Response.json({error:`Expected every 'inputResponses' entry to match the HITL response schema.`,ok:!1},{status:400})}function mergeContext(e,t){return e===void 0?t:t===void 0?e:[...e,...t]}function parseClientContextField(e){if(e!==void 0){if(typeof e==`string`)return e.length>0?[toClientContextMessage(e)]:void 0;if(Array.isArray(e))return e.length===0?void 0:e.every(e=>typeof e==`string`&&e.length>0)?e.map(e=>toClientContextMessage(e)):Response.json({error:`Expected 'clientContext' array entries to be non-empty strings.`,ok:!1},{status:400});if(typeof e!=`object`||!e)return Response.json({error:`Expected 'clientContext' to be a string, string array, or JSON object.`,ok:!1},{status:400});try{let t=parseJsonObject(e);return[toClientContextMessage(JSON.stringify(t))]}catch{return Response.json({error:`Expected 'clientContext' to be a JSON-serializable object.`,ok:!1},{status:400})}}}function toClientContextMessage(e){return`Client context:
1
+ import{createLogger,logError}from"#internal/logging.js";import{hasInternalRefScheme}from"#internal/attachments/url-refs.js";import{EVE_MESSAGE_STREAM_CONTENT_TYPE,EVE_MESSAGE_STREAM_FORMAT,EVE_MESSAGE_STREAM_VERSION,EVE_SESSION_ID_HEADER,EVE_STREAM_FORMAT_HEADER,EVE_STREAM_VERSION_HEADER}from"#protocol/message.js";import{isInputResponse}from"#runtime/input/types.js";import{parseJsonObject}from"#shared/json.js";import"ai";import{parseSessionCallback}from"#channel/session-callback.js";import{routeAuth}from"#public/channels/auth.js";import{GET,POST,defineChannel}from"#public/definitions/defineChannel.js";import{collectUploadPolicyViolations,formatUploadPolicyViolation,mergeUploadPolicy}from"#public/channels/upload-policy.js";const log=createLogger(`eve.channel`);function defaultEveAuth(e){return e.eve.caller}function eveChannel(e){let t=mergeUploadPolicy(e.uploadPolicy);return defineChannel({cors:normalizeEveCors(e.cors),routes:[POST(`/eve/v1/session`,async(n,{send:r})=>{let i=await routeAuth(n,e.auth);if(i instanceof Response)return i;let a=i,o;try{o=await n.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof o!=`object`||!o)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let s=parseCreateBody(o);if(s instanceof Response)return s;let c=checkUploadPolicy(s,t);if(c!==null)return c;let l=await resolveOnMessage({auth:a,config:e,message:s.message,request:n});if(l instanceof Response)return l;if(!l.dispatch)return droppedMessageResponse();let u=`eve:${crypto.randomUUID()}`,d=await r(createSendPayload(s,mergeContext(s.context,l.context)),{auth:l.auth,callback:s.callback,continuationToken:u,mode:s.mode});return Response.json({continuationToken:d.continuationToken,ok:!0,sessionId:d.id},{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:d.id},status:202})}),POST(`/eve/v1/session/:sessionId`,async(n,{send:r,getSession:i,params:a})=>{let o=await routeAuth(n,e.auth);if(o instanceof Response)return o;let s=o,c=a.sessionId;if(!c)return Response.json({error:`Missing session id.`,ok:!1},{status:400});try{i(c)}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}let l;try{l=await n.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof l!=`object`||!l)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let u=parseContinueBody(l);if(u instanceof Response)return u;let d=checkUploadPolicy(u,t);if(d!==null)return d;let f=u.context,p=s;if(u.message!==void 0){let t=await resolveOnMessage({auth:s,config:e,message:u.message,request:n,sessionId:c});if(t instanceof Response)return t;if(!t.dispatch)return droppedMessageResponse();f=mergeContext(u.context,t.context),p=t.auth}let m=await r({inputResponses:u.inputResponses,message:u.message,context:f,outputSchema:u.outputSchema},{auth:p,continuationToken:u.continuationToken});return Response.json({ok:!0,sessionId:m.id},{headers:{"cache-control":`no-store`,[EVE_SESSION_ID_HEADER]:m.id},status:200})}),GET(`/eve/v1/session/:sessionId/stream`,async(t,{getSession:n,params:c})=>{let l=await routeAuth(t,e.auth);if(l instanceof Response)return l;let u=c.sessionId;if(!u)return Response.json({error:`Missing session id.`,ok:!1},{status:400});let d=parseStartIndex(t);if(d instanceof Response)return d;try{let e=serializeAsNdjson(await n(u).getEventStream({startIndex:d}));return new Response(e,{headers:{"cache-control":`no-store, no-transform`,"content-type":EVE_MESSAGE_STREAM_CONTENT_TYPE,"x-accel-buffering":`no`,[EVE_SESSION_ID_HEADER]:u,[EVE_STREAM_FORMAT_HEADER]:EVE_MESSAGE_STREAM_FORMAT,[EVE_STREAM_VERSION_HEADER]:EVE_MESSAGE_STREAM_VERSION}})}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}})],events:e.events})}function normalizeEveCors(e){if(e===void 0||e===!1)return!1;if(e===!0)return!0;let t={};return e.origin!==void 0&&(t.origin=normalizeEveCorsOrigin(e.origin)),e.methods!==void 0&&(t.methods=e.methods),e.allowedHeaders!==void 0&&(t.allowHeaders=e.allowedHeaders),e.exposedHeaders!==void 0&&(t.exposeHeaders=e.exposedHeaders),e.credentials!==void 0&&(t.credentials=e.credentials),e.maxAge!==void 0&&(t.maxAge=e.maxAge),e.preflightStatus!==void 0&&(t.preflight={statusCode:e.preflightStatus}),t}function normalizeEveCorsOrigin(e){return e===`*`||e===`null`?e:typeof e==`string`?[e]:e}async function resolveOnMessage(e){let n=e.config.onMessage??defaultOnMessage,r;try{r=await n({eve:e.sessionId===void 0?{caller:e.auth,request:e.request}:{caller:e.auth,request:e.request,sessionId:e.sessionId}},e.message)}catch(n){let r=logError(log,`onMessage handler failed`,n,{sessionId:e.sessionId});return Response.json({error:`onMessage handler failed.`,errorId:r,ok:!1},{status:500})}return r==null?{dispatch:!1}:r.context===void 0?{auth:r.auth,dispatch:!0}:{auth:r.auth,context:r.context,dispatch:!0}}function defaultOnMessage(e){return{auth:defaultEveAuth(e)}}function droppedMessageResponse(){return new Response(null,{headers:{"cache-control":`no-store`},status:204})}function parseCreateBody(e){let t=parseMessageField(e.message);if(t instanceof Response)return t;let n=parseClientContextField(e.clientContext);if(n instanceof Response)return n;let r=parseCallbackField(e.callback);if(r instanceof Response)return r;let i=parseModeField(e.mode);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:t===void 0?Response.json({error:`Missing or empty 'message' field.`,ok:!1},{status:400}):{callback:r,message:t,mode:i,context:n,outputSchema:a}}function parseContinueBody(e){let t=typeof e.continuationToken==`string`&&e.continuationToken.length>0?e.continuationToken:void 0;if(t===void 0)return Response.json({error:`Missing or empty 'continuationToken' field.`,ok:!1},{status:400});let n=parseMessageField(e.message);if(n instanceof Response)return n;let r=parseInputResponses(e.inputResponses);if(r instanceof Response)return r;let i=parseClientContextField(e.clientContext);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:n===void 0&&r===void 0?Response.json({error:`Expected a non-empty 'message', a non-empty 'inputResponses' array, or both.`,ok:!1},{status:400}):{message:n,continuationToken:t,inputResponses:r,context:i,outputSchema:a}}function createSendPayload(e,t=e.context){if(t===void 0&&e.outputSchema===void 0)return e.message;let n={message:e.message};return t!==void 0&&(n.context=t),e.outputSchema!==void 0&&(n.outputSchema=e.outputSchema),n}function parseOutputSchemaField(e){if(e!==void 0)try{return parseJsonObject(e)}catch{return Response.json({error:`Expected 'outputSchema' to be a JSON-serializable object.`,ok:!1},{status:400})}}function parseCallbackField(e){if(e===void 0)return;let t=parseSessionCallback(e);return t.ok?t.callback:Response.json({error:t.message,ok:!1},{status:400})}function parseModeField(e){if(e!==void 0)return e===`conversation`||e===`task`?e:Response.json({error:`Expected 'mode' to be either 'conversation' or 'task'.`,ok:!1},{status:400})}function parseMessageField(e){if(e===void 0)return;if(typeof e==`string`)return e.length>0?e:void 0;if(!Array.isArray(e))return Response.json({error:`Expected 'message' to be a string or an array of text/file parts.`,ok:!1},{status:400});if(e.length===0)return;let t=[];for(let n of e){let e=parseMessagePart(n);if(e instanceof Response)return e;t.push(e)}return t}function parseMessagePart(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected each message part to be an object.`,ok:!1},{status:400});let t=e;if(t.type===`text`)return typeof t.text!=`string`||t.text.length===0?Response.json({error:`Text parts require a non-empty 'text' string.`,ok:!1},{status:400}):{type:`text`,text:t.text};if(t.type===`file`){if(typeof t.mediaType!=`string`||t.mediaType.length===0)return Response.json({error:`File parts require a non-empty 'mediaType' string.`,ok:!1},{status:400});if(typeof t.data!=`string`)return Response.json({error:`File parts require a 'data' string (base64, data URL, or URL).`,ok:!1},{status:400});if(hasInternalRefScheme(t.data))return Response.json({error:`File part 'data' must not use a framework-internal ref scheme.`,ok:!1},{status:400});let e={type:`file`,mediaType:t.mediaType,data:t.data};return typeof t.filename==`string`&&t.filename.length>0&&(e.filename=t.filename),e}return Response.json({error:`Unsupported message part type "${String(t.type)}". Use 'text' or 'file'.`,ok:!1},{status:400})}function checkUploadPolicy(e,t){if(!e.message)return null;let n=collectUploadPolicyViolations(e.message,t);if(n.length===0)return null;let[r]=n;if(!r)return null;let i=r.kind===`too-large`?413:415;return Response.json({error:formatUploadPolicyViolation(r),ok:!1,violations:n.map(e=>e.kind===`too-large`?{byteLength:e.byteLength,filename:e.filename,kind:e.kind,limit:e.limit,mediaType:e.mediaType}:{allowedMediaTypes:e.allowedMediaTypes,filename:e.filename,kind:e.kind,mediaType:e.mediaType})},{status:i})}function parseInputResponses(e){if(e===void 0)return;if(!Array.isArray(e)||e.length===0)return Response.json({error:`Expected 'inputResponses' to be a non-empty array.`,ok:!1},{status:400});let t=e.filter(isInputResponse);return t.length===e.length?t:Response.json({error:`Expected every 'inputResponses' entry to match the HITL response schema.`,ok:!1},{status:400})}function mergeContext(e,t){return e===void 0?t:t===void 0?e:[...e,...t]}function parseClientContextField(e){if(e!==void 0){if(typeof e==`string`)return e.length>0?[toClientContextMessage(e)]:void 0;if(Array.isArray(e))return e.length===0?void 0:e.every(e=>typeof e==`string`&&e.length>0)?e.map(e=>toClientContextMessage(e)):Response.json({error:`Expected 'clientContext' array entries to be non-empty strings.`,ok:!1},{status:400});if(typeof e!=`object`||!e)return Response.json({error:`Expected 'clientContext' to be a string, string array, or JSON object.`,ok:!1},{status:400});try{let t=parseJsonObject(e);return[toClientContextMessage(JSON.stringify(t))]}catch{return Response.json({error:`Expected 'clientContext' to be a JSON-serializable object.`,ok:!1},{status:400})}}}function toClientContextMessage(e){return`Client context:
2
2
  ${e}`}function parseStartIndex(e){let t=new URL(e.url).searchParams.get(`startIndex`);if(t===null)return;let n=Number.parseInt(t,10);return!Number.isSafeInteger(n)||n<0?Response.json({error:`Expected startIndex to be a non-negative integer.`,ok:!1},{status:400}):n}function serializeAsNdjson(e){let t=new TextEncoder;return e.pipeThrough(new TransformStream({transform(e,n){n.enqueue(t.encode(`${JSON.stringify(e)}\n`))}}))}export{defaultEveAuth,eveChannel};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/defineChannel.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 s=e.botName??process.env.GITHUB_APP_SLUG,u={botName:s},d={...createDefaultEvents({api:e.api,credentials:e.credentials,progress:e.progress}),...e.events};return defineChannel({kindHint:`github`,state:initialGitHubState(),context(t,n){return rebuildGitHubContext(t,n,e)},routes:[POST(e.route??GITHUB_CHANNEL_DEFAULT_ROUTE,async(t,{send:n,waitUntil:r})=>{let a=await verifyInbound(t,e.credentials);if(a===null)return new Response(`unauthorized`,{status:401});let o;try{o=parseGitHubWebhookEvent({body:a,contentType:t.headers.get(`content-type`)??void 0,headers:t.headers})}catch(e){return log.warn(`inbound GitHub body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return o===null?jsonOk({ignored:!0,ok:!0}):o.kind===`ping`?jsonOk({ok:!0}):o.kind===`issue_comment`&&o.action===`created`?(r(dispatchIssueComment({botName:s,config:e,event:o,handler:e.onComment??((e,t)=>defaultOnComment(e,t,u)),send:n})),jsonOk({ok:!0})):o.kind===`pull_request_review_comment`&&o.action===`created`?(r(dispatchPullRequestReviewComment({botName:s,config:e,event:o,handler:e.onComment??((e,t)=>defaultOnComment(e,t,u)),send:n})),jsonOk({ok:!0})):o.kind===`issues`&&e.onIssue!==void 0?(r(dispatchIssue({config:e,event:o,handler:e.onIssue,send:n})),jsonOk({ok:!0})):o.kind===`pull_request`&&e.onPullRequest!==void 0?(r(dispatchPullRequest({config:e,event:o,handler:e.onPullRequest,send:n})),jsonOk({ok:!0})):o.kind===`check_suite`&&e.onCheckSuite!==void 0?(r(dispatchCheckSuite({config:e,event:o,handler:e.onCheckSuite,send:n})),jsonOk({ok:!0})):o.kind===`check_run`&&e.onCheckRun!==void 0?(r(dispatchCheckRun({config:e,event:o,handler:e.onCheckRun,send:n})),jsonOk({ok:!0})):o.kind===`workflow_run`&&e.onWorkflowRun!==void 0?(r(dispatchWorkflowRun({config:e,event:o,handler:e.onWorkflowRun,send:n})),jsonOk({ok:!0})):jsonOk({ignored:!0,ok:!0})})],async receive(t,{send:n}){let i=t.target,s=readNonEmptyString(i.owner),c=readNonEmptyString(i.repo);if(s===void 0||c===void 0)throw Error(`githubChannel().receive requires target.owner and target.repo.`);if([i.issueNumber!==void 0,i.pullRequestNumber!==void 0].filter(Boolean).length!==1)throw Error(`githubChannel().receive requires exactly one of issueNumber or pullRequestNumber.`);let l=stateFromReceiveTarget({target:i,owner:s,repo:c,repositoryId:i.repositoryId??(await getGitHubRepository({api:e.api,credentials:e.credentials,installationId:i.installationId,owner:s,repo:c})).id});if(i.initialMessage!==void 0){let{thread:t}=buildGitHubBinding({config:e,state:l});await t.post(i.initialMessage)}return n(t.message,{auth:t.auth,continuationToken:continuationTokenFromState(l),state:l})},events:d})}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 readNonEmptyString(e){return typeof e==`string`&&e.length>0?e:void 0}function jsonOk(e){return new Response(JSON.stringify(e),{headers:{"content-type":`application/json; charset=utf-8`},status:200})}export{githubChannel};
1
+ import{createLogger}from"#internal/logging.js";import{POST,defineChannel}from"#public/definitions/defineChannel.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 s=e.botName??process.env.GITHUB_APP_SLUG,u={botName:s},d={...createDefaultEvents({api:e.api,credentials:e.credentials,progress:e.progress}),...e.events};return defineChannel({kindHint:`github`,state:initialGitHubState(),context(t,n){return rebuildGitHubContext(t,n,e)},routes:[POST(e.route??GITHUB_CHANNEL_DEFAULT_ROUTE,async(t,{send:n,waitUntil:r})=>{let a=await verifyInbound(t,e.credentials);if(a===null)return new Response(`unauthorized`,{status:401});let o=missingGitHubWebhookHeaders(t.headers),c;try{c=parseGitHubWebhookEvent({body:a,contentType:t.headers.get(`content-type`)??void 0,headers:t.headers})}catch(e){return log.warn(`inbound GitHub body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return c===null?(o.length>0&&log.warn(`GitHub webhook ignored because standard headers were missing`,{missingHeaders:o}),jsonOk({ignored:!0,ok:!0})):(o.length>0&&log.warn(`GitHub webhook missing standard headers; inferred metadata from payload`,{deliveryId:c.delivery.id,event:c.delivery.event,missingHeaders:o,repository:c.repository.fullName}),c.kind===`ping`?jsonOk({ok:!0}):c.kind===`issue_comment`&&c.action===`created`?(r(dispatchIssueComment({botName:s,config:e,event:c,handler:e.onComment??((e,t)=>defaultOnComment(e,t,u)),send:n})),jsonOk({ok:!0})):c.kind===`pull_request_review_comment`&&c.action===`created`?(r(dispatchPullRequestReviewComment({botName:s,config:e,event:c,handler:e.onComment??((e,t)=>defaultOnComment(e,t,u)),send:n})),jsonOk({ok:!0})):c.kind===`issues`&&e.onIssue!==void 0?(r(dispatchIssue({config:e,event:c,handler:e.onIssue,send:n})),jsonOk({ok:!0})):c.kind===`pull_request`&&e.onPullRequest!==void 0?(r(dispatchPullRequest({config:e,event:c,handler:e.onPullRequest,send:n})),jsonOk({ok:!0})):c.kind===`check_suite`&&e.onCheckSuite!==void 0?(r(dispatchCheckSuite({config:e,event:c,handler:e.onCheckSuite,send:n})),jsonOk({ok:!0})):c.kind===`check_run`&&e.onCheckRun!==void 0?(r(dispatchCheckRun({config:e,event:c,handler:e.onCheckRun,send:n})),jsonOk({ok:!0})):c.kind===`workflow_run`&&e.onWorkflowRun!==void 0?(r(dispatchWorkflowRun({config:e,event:c,handler:e.onWorkflowRun,send:n})),jsonOk({ok:!0})):jsonOk({ignored:!0,ok:!0}))})],async receive(t,{send:n}){let i=t.target,s=readNonEmptyString(i.owner),c=readNonEmptyString(i.repo);if(s===void 0||c===void 0)throw Error(`githubChannel().receive requires target.owner and target.repo.`);if([i.issueNumber!==void 0,i.pullRequestNumber!==void 0].filter(Boolean).length!==1)throw Error(`githubChannel().receive requires exactly one of issueNumber or pullRequestNumber.`);let l=stateFromReceiveTarget({target:i,owner:s,repo:c,repositoryId:i.repositoryId??(await getGitHubRepository({api:e.api,credentials:e.credentials,installationId:i.installationId,owner:s,repo:c})).id});if(i.initialMessage!==void 0){let{thread:t}=buildGitHubBinding({config:e,state:l});await t.post(i.initialMessage)}return n(t.message,{auth:t.auth,continuationToken:continuationTokenFromState(l),state:l})},events:d})}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 readNonEmptyString(e){return typeof e==`string`&&e.length>0?e:void 0}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};
@@ -0,0 +1,189 @@
1
+ import type { JsonObject } from "#shared/json.js";
2
+ /** GitHub conversation kinds represented by the channel state. */
3
+ export type GitHubConversationKind = "issue" | "pull_request" | "review_thread";
4
+ /** Stable repository identity normalized from webhook payloads. */
5
+ export interface GitHubRepositoryRef {
6
+ readonly fullName: string;
7
+ readonly id: number;
8
+ readonly name: string;
9
+ readonly owner: string;
10
+ readonly private: boolean;
11
+ }
12
+ /** GitHub actor metadata normalized from webhook payloads. */
13
+ export interface GitHubUser {
14
+ readonly htmlUrl: string | undefined;
15
+ readonly id: number;
16
+ readonly login: string;
17
+ readonly type: string;
18
+ readonly url: string | undefined;
19
+ }
20
+ /** GitHub webhook delivery metadata. */
21
+ export interface GitHubDelivery {
22
+ readonly event: string;
23
+ readonly hookId: string | undefined;
24
+ readonly id: string;
25
+ }
26
+ /** Channel-local conversation reference. */
27
+ export interface GitHubConversationRef {
28
+ readonly issueNumber: number | null;
29
+ readonly kind: GitHubConversationKind;
30
+ readonly pullRequestNumber: number | null;
31
+ }
32
+ /**
33
+ * Normalized GitHub comment handed to the `onComment` hook. Covers issue and PR
34
+ * timeline comments and inline review comments alike; `ctx.conversation.kind`
35
+ * distinguishes them.
36
+ */
37
+ export interface GitHubComment {
38
+ readonly author: GitHubUser | undefined;
39
+ readonly body: string;
40
+ readonly htmlUrl: string | undefined;
41
+ readonly id: number;
42
+ readonly raw: JsonObject;
43
+ readonly url: string | undefined;
44
+ }
45
+ /** Normalized issue/PR timeline comment. */
46
+ export interface GitHubIssueComment {
47
+ readonly author: GitHubUser | undefined;
48
+ readonly body: string;
49
+ readonly htmlUrl: string | undefined;
50
+ readonly id: number;
51
+ readonly issueNumber: number;
52
+ readonly pullRequestNumber: number | null;
53
+ readonly raw: JsonObject;
54
+ readonly url: string | undefined;
55
+ }
56
+ /** Normalized inline pull-request review comment. */
57
+ export interface GitHubPullRequestReviewComment {
58
+ readonly author: GitHubUser | undefined;
59
+ readonly body: string;
60
+ readonly htmlUrl: string | undefined;
61
+ readonly id: number;
62
+ readonly inReplyToId: number | null;
63
+ readonly pullRequestNumber: number;
64
+ readonly raw: JsonObject;
65
+ readonly reviewThreadRootCommentId: number;
66
+ readonly url: string | undefined;
67
+ }
68
+ /**
69
+ * Common `issues` webhook actions, kept open to any action GitHub sends so
70
+ * authors get autocomplete without losing forward compatibility.
71
+ */
72
+ export type GitHubIssueAction = "assigned" | "closed" | "edited" | "labeled" | "opened" | "reopened" | "unassigned" | "unlabeled" | (string & {});
73
+ /** Common `pull_request` webhook actions, kept open to any action GitHub sends. */
74
+ export type GitHubPullRequestAction = "closed" | "edited" | "labeled" | "opened" | "ready_for_review" | "reopened" | "synchronize" | "unlabeled" | (string & {});
75
+ /** Normalized issue event payload. */
76
+ export interface GitHubIssueEvent {
77
+ readonly action: GitHubIssueAction;
78
+ readonly issueNumber: number;
79
+ readonly raw: JsonObject;
80
+ }
81
+ /** Normalized pull-request event payload. */
82
+ export interface GitHubPullRequestEvent {
83
+ readonly action: GitHubPullRequestAction;
84
+ readonly headSha: string | null;
85
+ readonly pullRequestNumber: number;
86
+ readonly raw: JsonObject;
87
+ }
88
+ /** GitHub App identity attached to CI webhook payloads. */
89
+ export interface GitHubAppRef {
90
+ readonly slug: string | null;
91
+ }
92
+ /** Common fields normalized from GitHub CI webhook payloads. */
93
+ export interface GitHubCiEvent {
94
+ readonly action: string;
95
+ readonly app: GitHubAppRef;
96
+ readonly conclusion: string | null;
97
+ readonly headSha: string | null;
98
+ readonly pullRequests: readonly number[];
99
+ readonly raw: JsonObject;
100
+ readonly status: string | null;
101
+ }
102
+ /** Normalized `check_suite` webhook payload. */
103
+ export interface GitHubCheckSuiteEvent extends GitHubCiEvent {
104
+ readonly checkSuiteId: number;
105
+ }
106
+ /** Normalized `check_run` webhook payload. */
107
+ export interface GitHubCheckRunEvent extends GitHubCiEvent {
108
+ readonly checkRunId: number;
109
+ }
110
+ /** Normalized `workflow_run` webhook payload. */
111
+ export interface GitHubWorkflowRunEvent extends GitHubCiEvent {
112
+ readonly workflowRunId: number;
113
+ }
114
+ /** Normalized payload accepted by one of the GitHub CI event hooks. */
115
+ export type GitHubCiPayload = GitHubCheckRunEvent | GitHubCheckSuiteEvent | GitHubWorkflowRunEvent;
116
+ export interface GitHubInboundEventBase {
117
+ readonly delivery: GitHubDelivery;
118
+ readonly installationId: number | undefined;
119
+ readonly raw: JsonObject;
120
+ readonly repository: GitHubRepositoryRef;
121
+ readonly sender: GitHubUser;
122
+ }
123
+ export interface GitHubPingEvent extends GitHubInboundEventBase {
124
+ readonly kind: "ping";
125
+ }
126
+ export interface GitHubIssueCommentEvent extends GitHubInboundEventBase {
127
+ readonly action: string;
128
+ readonly baseRef: string | null;
129
+ readonly baseSha: string | null;
130
+ readonly comment: GitHubIssueComment;
131
+ readonly conversation: GitHubConversationRef;
132
+ readonly defaultBranch: string | null;
133
+ readonly headRef: string | null;
134
+ readonly headSha: string | null;
135
+ readonly kind: "issue_comment";
136
+ }
137
+ export interface GitHubPullRequestReviewCommentEvent extends GitHubInboundEventBase {
138
+ readonly action: string;
139
+ readonly baseRef: string | null;
140
+ readonly baseSha: string | null;
141
+ readonly comment: GitHubPullRequestReviewComment;
142
+ readonly conversation: GitHubConversationRef;
143
+ readonly defaultBranch: string | null;
144
+ readonly headRef: string | null;
145
+ readonly headSha: string | null;
146
+ readonly kind: "pull_request_review_comment";
147
+ }
148
+ export interface GitHubIssueWebhookEvent extends GitHubInboundEventBase {
149
+ readonly action: string;
150
+ readonly conversation: GitHubConversationRef;
151
+ readonly issue: GitHubIssueEvent;
152
+ readonly kind: "issues";
153
+ }
154
+ export interface GitHubPullRequestWebhookEvent extends GitHubInboundEventBase {
155
+ readonly action: string;
156
+ readonly baseRef: string | null;
157
+ readonly baseSha: string | null;
158
+ readonly conversation: GitHubConversationRef;
159
+ readonly defaultBranch: string | null;
160
+ readonly headRef: string | null;
161
+ readonly headSha: string | null;
162
+ readonly kind: "pull_request";
163
+ readonly pullRequest: GitHubPullRequestEvent;
164
+ }
165
+ export interface GitHubCheckSuiteWebhookEvent extends GitHubInboundEventBase {
166
+ readonly checkSuite: GitHubCheckSuiteEvent;
167
+ readonly conversation: GitHubConversationRef;
168
+ readonly kind: "check_suite";
169
+ }
170
+ export interface GitHubCheckRunWebhookEvent extends GitHubInboundEventBase {
171
+ readonly checkRun: GitHubCheckRunEvent;
172
+ readonly conversation: GitHubConversationRef;
173
+ readonly kind: "check_run";
174
+ }
175
+ export interface GitHubWorkflowRunWebhookEvent extends GitHubInboundEventBase {
176
+ readonly conversation: GitHubConversationRef;
177
+ readonly kind: "workflow_run";
178
+ readonly workflowRun: GitHubWorkflowRunEvent;
179
+ }
180
+ /** Parsed CI webhook envelopes consumed by the GitHub channel. */
181
+ export type GitHubCiWebhookEvent = GitHubCheckRunWebhookEvent | GitHubCheckSuiteWebhookEvent | GitHubWorkflowRunWebhookEvent;
182
+ /** Parsed GitHub webhook event shape consumed by the channel. */
183
+ export type GitHubInboundEvent = GitHubCheckRunWebhookEvent | GitHubCheckSuiteWebhookEvent | GitHubIssueCommentEvent | GitHubIssueWebhookEvent | GitHubPingEvent | GitHubPullRequestReviewCommentEvent | GitHubPullRequestWebhookEvent | GitHubWorkflowRunWebhookEvent;
184
+ /** Parsed mention trigger for a bot-directed GitHub comment. */
185
+ export interface GitHubCommentTrigger {
186
+ readonly kind: "mention";
187
+ readonly message: string;
188
+ readonly token: string;
189
+ }
@@ -0,0 +1 @@
1
+ export{};