eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 4.89 kB
JavaScript
import{createLogger}from"#internal/logging.js";import{readNonEmptyString}from"#shared/guards.js";import{POST,defineChannel}from"#public/definitions/channel.js";import{createGitHubBotNameResolver}from"#public/channels/github/auth.js";import{getGitHubRepository}from"#public/channels/github/api.js";import{parseGitHubWebhookEvent}from"#public/channels/github/inbound.js";import{buildGitHubBinding}from"#public/channels/github/binding.js";import{continuationTokenFromState,conversationFromState,initialGitHubState,stateFromReceiveTarget}from"#public/channels/github/state.js";import{GITHUB_CHANNEL_DEFAULT_ROUTE}from"#public/channels/github/constants.js";import{createDefaultEvents,defaultOnComment}from"#public/channels/github/defaults.js";import{dispatchCheckRun,dispatchCheckSuite,dispatchIssue,dispatchIssueComment,dispatchPullRequest,dispatchPullRequestReviewComment,dispatchWorkflowRun}from"#public/channels/github/dispatch.js";import{verifyGitHubRequest}from"#public/channels/github/verify.js";const log=createLogger(`github.channel`);function githubChannel(e={}){let t=createGitHubBotNameResolver({botName:e.botName,credentials:e.credentials}),n={botName:t},r={...createDefaultEvents({api:e.api,botName:t,credentials:e.credentials,progress:e.progress}),...e.events};return defineChannel({kindHint:`github`,turnPolicy:e.turnPolicy,state:initialGitHubState(),context(t,n){return rebuildGitHubContext(t,n,e)},routes:[POST(e.route??GITHUB_CHANNEL_DEFAULT_ROUTE,async(r,{from:i,waitUntil:a})=>{let o=await verifyInbound(r,e.credentials);if(o===null)return new Response(`unauthorized`,{status:401});let s=missingGitHubWebhookHeaders(r.headers),c;try{c=parseGitHubWebhookEvent({body:o,contentType:r.headers.get(`content-type`)??void 0,headers:r.headers})}catch(e){return log.warn(`inbound GitHub body is not valid JSON`,{error:e}),jsonOk({ignored:!0,ok:!0})}return c===null?(s.length>0&&log.warn(`GitHub webhook ignored because standard headers were missing`,{missingHeaders:s}),jsonOk({ignored:!0,ok:!0})):(s.length>0&&log.warn(`GitHub webhook missing standard headers; inferred metadata from payload`,{deliveryId:c.delivery.id,event:c.delivery.event,missingHeaders:s,repository:c.repository.fullName}),c.kind===`ping`?jsonOk({ok:!0}):c.kind===`issue_comment`&&c.action===`created`?(a(dispatchIssueComment({botName:t,config:e,event:c,handler:e.onComment??((e,t)=>defaultOnComment(e,t,n)),from:i})),jsonOk({ok:!0})):c.kind===`pull_request_review_comment`&&c.action===`created`?(a(dispatchPullRequestReviewComment({botName:t,config:e,event:c,handler:e.onComment??((e,t)=>defaultOnComment(e,t,n)),from:i})),jsonOk({ok:!0})):c.kind===`issues`&&e.onIssue!==void 0?(a(dispatchIssue({botName:t,config:e,event:c,handler:e.onIssue,from:i})),jsonOk({ok:!0})):c.kind===`pull_request`&&e.onPullRequest!==void 0?(a(dispatchPullRequest({botName:t,config:e,event:c,handler:e.onPullRequest,from:i})),jsonOk({ok:!0})):c.kind===`check_suite`&&e.onCheckSuite!==void 0?(a(dispatchCheckSuite({botName:t,config:e,event:c,handler:e.onCheckSuite,from:i})),jsonOk({ok:!0})):c.kind===`check_run`&&e.onCheckRun!==void 0?(a(dispatchCheckRun({botName:t,config:e,event:c,handler:e.onCheckRun,from:i})),jsonOk({ok:!0})):c.kind===`workflow_run`&&e.onWorkflowRun!==void 0?(a(dispatchWorkflowRun({botName:t,config:e,event:c,handler:e.onWorkflowRun,from:i})),jsonOk({ok:!0})):jsonOk({ignored:!0,ok:!0}))})],async receive(t,{from:n}){let r=t.target,i=readNonEmptyString(r.owner),a=readNonEmptyString(r.repo);if(i===void 0||a===void 0)throw Error(`githubChannel().receive requires target.owner and target.repo.`);if([r.issueNumber!==void 0,r.pullRequestNumber!==void 0].filter(Boolean).length!==1)throw Error(`githubChannel().receive requires exactly one of issueNumber or pullRequestNumber.`);let o=r.repositoryId??(await getGitHubRepository({api:e.api,credentials:e.credentials,installationId:r.installationId,owner:i,repo:a})).id,s=stateFromReceiveTarget({target:r,owner:i,repo:a,repositoryId:o});if(r.initialMessage!==void 0){let{thread:t}=buildGitHubBinding({config:e,state:s});await t.post(r.initialMessage)}return n(continuationTokenFromState(s)).send(t.message,{auth:t.auth,state:s})},events:r})}function rebuildGitHubContext(e,t,n){let r=buildGitHubBinding({config:n,state:e});return{conversation:conversationFromState(e),github:r.github,repository:r.github.repository,state:e,thread:r.thread}}async function verifyInbound(e,t){try{return await verifyGitHubRequest(e,{webhookSecret:t?.webhookSecret,webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`github inbound verification failed`,{error:e}),null}}function missingGitHubWebhookHeaders(e){return[`x-github-event`,`x-github-delivery`].filter(t=>{let n=e.get(t);return n===null||n.trim().length===0})}function jsonOk(e){return new Response(JSON.stringify(e),{headers:{"content-type":`application/json; charset=utf-8`},status:200})}export{githubChannel};