@ai-development-environment/server 0.0.100 → 0.0.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/standalone/.next/BUILD_ID +1 -1
- package/standalone/.next/build-manifest.json +3 -3
- package/standalone/.next/prerender-manifest.json +3 -3
- package/standalone/.next/server/app/[locale]/(dashboard)/builds/[buildId]/output/route.js.nft.json +1 -1
- package/standalone/.next/server/app/[locale]/(dashboard)/commands/runs/[runId]/output/route.js.nft.json +1 -1
- package/standalone/.next/server/app/_global-error.html +1 -1
- package/standalone/.next/server/app/_global-error.rsc +1 -1
- package/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/standalone/.next/server/app/_not-found.html +1 -1
- package/standalone/.next/server/app/_not-found.rsc +1 -1
- package/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/standalone/.next/server/app/api/agent/build-artifact-transfers/[transferId]/complete/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/agent/build-artifact-transfers/[transferId]/download/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/agent/build-artifact-transfers/[transferId]/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/agent/build-artifact-transfers/[transferId]/upload/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/agent/run-attachments/[attachmentId]/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/build-artifact-uploads/[uploadId]/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/codebases/by-path/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/codebases/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/graphql/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/ios/apns-devices/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/ios/devices/export.tsv/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/ios/enrollment/start/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/ios/notification-devices/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/mcp/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/public/builds/[buildId]/artifacts/[artifactId]/manifest.plist/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/public/builds/[buildId]/artifacts/[artifactId]/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/public/github/webhook/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/public/gitlab/webhook/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/public/ios/enrollment-profile/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/public/ios/profile-response/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/public/jira/webhook/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/public/sse/[token]/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/sse/history/export/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/telemetry/analytics-events/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/telemetry/console-logs/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/telemetry/export/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/tools/call/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/tools/catalog/route.js.nft.json +1 -1
- package/standalone/.next/server/app/api/worktrees/[worktreeId]/diff-image/route.js.nft.json +1 -1
- package/standalone/.next/server/chunks/[root-of-the-server]__03aos_4._.js +1 -1
- package/standalone/.next/server/chunks/_0e8lp3p._.js +1 -1
- package/standalone/.next/server/chunks/_0fwwxlu._.js +1 -1
- package/standalone/.next/server/chunks/_0h78qjg._.js +1 -1
- package/standalone/.next/server/chunks/_0ndnc91._.js +1 -1
- package/standalone/.next/server/chunks/_0wpfe7q._.js +1 -1
- package/standalone/.next/server/chunks/_1-vdyhc._.js +1 -1
- package/standalone/.next/server/chunks/_1gt6607._.js +1 -1
- package/standalone/.next/server/chunks/_1jwsn5v._.js +1 -1
- package/standalone/.next/server/chunks/_1qjb83a._.js +1 -1
- package/standalone/.next/server/chunks/_1zwfwcs._.js +1 -1
- package/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/standalone/.next/server/pages/404.html +1 -1
- package/standalone/.next/server/pages/500.html +1 -1
- package/standalone/.next/server/server-reference-manifest.js +1 -1
- package/standalone/.next/server/server-reference-manifest.json +1 -1
- /package/standalone/.next/static/{iNH0xq2KlqMDpWuRmdLMn → y9Hi8CBWpu_MxfgH-bM8Z}/_buildManifest.js +0 -0
- /package/standalone/.next/static/{iNH0xq2KlqMDpWuRmdLMn → y9Hi8CBWpu_MxfgH-bM8Z}/_clientMiddlewareManifest.js +0 -0
- /package/standalone/.next/static/{iNH0xq2KlqMDpWuRmdLMn → y9Hi8CBWpu_MxfgH-bM8Z}/_ssgManifest.js +0 -0
|
@@ -1533,7 +1533,7 @@ pyQPbp8orlXe+tA8JA==
|
|
|
1533
1533
|
}
|
|
1534
1534
|
}`,{checkSuiteId:A},n,{requestSource:r})).node;if(!a)throw new u("CHECK_SUITE_NOT_FOUND","The GitHub check suite was not found");if(a.repository.id!==e)throw new u("CHECK_SUITE_REPOSITORY_MISMATCH","The check suite does not belong to the selected repository");if(a.app?.slug!=="github-actions")throw new u("NOT_GITHUB_ACTIONS","Only GitHub Actions workflow jobs can be retried");if("COMPLETED"!==a.status)throw new u("WORKFLOW_NOT_COMPLETED","The GitHub Actions workflow must be completed before a job can be retried");if(!a.workflowRun?.databaseId)throw new u("WORKFLOW_RUN_UNAVAILABLE","GitHub did not return a workflow run for this check suite");let o=await this.requireAppCredentials(),s=await this.appRequest(o,`query VerifyGitHubAppRepository($owner: String!, $name: String!) {
|
|
1535
1535
|
repository(owner: $owner, name: $name) { id }
|
|
1536
|
-
}`,{owner:a.repository.owner.login,name:a.repository.name},{requestSource:r});if(s.data.repository?.id!==e)throw new u("REPOSITORY_NOT_INSTALLED","The repository is not available to the GitHub App installation",s.githubRequestId);let l=await U(o,{owner:a.repository.owner.login,repository:a.repository.name,workflowRunId:String(a.workflowRun.databaseId),jobId:t,requestSource:r});return await this.cache.clear(),await this.audit(i,{operation:"GITHUB_ACTIONS_JOB_RERUN",repositoryId:e,checkSuiteId:A,jobId:t,githubRequestId:l.githubRequestId,outcome:"SUCCESS"}),await this.pipelineStatus.optimisticJobByCheckSuite(e,A,t),!0}catch(r){throw await this.audit(i,{operation:"GITHUB_ACTIONS_JOB_RERUN",repositoryId:e,checkSuiteId:A,jobId:t,githubRequestId:r instanceof u?r.githubRequestId:null,outcome:"FAILURE",errorCode:r instanceof u?r.code:"GITHUB_APP_REQUEST_FAILED"}),r}}},"normalizeGitHubRepositoryName",0,eQ],864637)},563629,e=>{"use strict";var A=e.i(666680),t=e.i(135475),r=e.i(751976);e.i(592299);var i=e.i(972425),n=e.i(747461),a=e.i(629097),o=e.i(852045),s=e.i(874185),l=e.i(601143),d=e.i(183291),u=e.i(714147);let c="server:github-actions-notifications",h=new Set(["failure","timed_out","startup_failure","action_required"]);function g(e){return"string"==typeof e&&e.trim()?e.trim():null}function p(e){return"number"==typeof e&&Number.isInteger(e)&&e>0?e:null}function f(e){return Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];let A=p(e.number);return A?[{number:A,url:g(e.html_url)??g(e.url)}]:[]}):[]}function I(e,A,t){let r=p(t?.id),i=p(t?.workflow_id),n=g(t?.updated_at),a=n?new Date(n):null;return r&&i&&a&&Number.isFinite(a.getTime())?{id:String(r),workflowId:String(i),runAttempt:p(t?.run_attempt)??1,name:g(t?.name)??"GitHub Actions",displayTitle:g(t?.display_title)??g(t?.name)??"Workflow run",status:g(t?.status)?.toLowerCase()??"unknown",conclusion:g(t?.conclusion)?.toLowerCase()??null,headBranch:g(t?.head_branch),headSha:g(t?.head_sha),pullRequests:f(t?.pull_requests),url:g(t?.html_url)??"",updatedAt:a,repositoryGithubId:g(A?.node_id),repositoryNameWithOwner:g(A?.full_name)??`${e.owner}/${e.repository}`,repositoryUrl:g(A?.html_url)??`https://github.com/${e.owner}/${e.repository}`,checkSuiteId:g(t?.check_suite_node_id)}:null}function C(e,A){let t=(0,u.normalizePipelineState)(e,A);return"SUCCESS"===t||"NEUTRAL"===t||"SKIPPED"===t?"IN_PROGRESS":t}function m(e,A){if(!e||!A)return null;try{let t=(0,r.compileRe2)(A,{flags:"i",label:"Jira branch regex"}).exec(e),i=(t?.[1]??t?.[0])?.trim();return i?i.toUpperCase():null}catch{return null}}e.s(["GitHubActionsNotificationsService",0,class{credentials;notifications;polling;workflowEvents;cache;pipelineStatus;timer;running;rerunRequested;constructor(e,A,t,r=!0,i,n=new a.GitHubCache,o=new d.GitHubPipelineStatusService){this.credentials=e,this.notifications=A,this.polling=t,this.workflowEvents=i,this.cache=n,this.pipelineStatus=o,this.timer=null,this.running=!1,this.rerunRequested=!1,this.polling.register({id:c,kind:"GITHUB_ACTIONS_NOTIFICATIONS",runtime:"SERVER",enabled:!1,cadenceSeconds:60,details:{mode:"DISABLED"}}),r&&queueMicrotask(()=>void this.tick())}async appConnection(){let e=await this.credentials.getJson(i.CREDENTIALS.githubAppSettings);return e?(0,n.githubAppConnectionSettings)(e):null}async recordWorkflowRunEvent(e,A){if(!this.workflowEvents||"completed"!==A.status)return;let r=await (0,t.getPrismaClient)(),[i,n]=await Promise.all([A.headBranch?r.worktree.findFirst({where:{branch:A.headBranch,missingAt:null,codebase:{repositoryId:e.id}},orderBy:{updatedAt:"desc"},select:{id:!0,folder:!0,branch:!0,baseBranchOverride:!0,headSha:!0,codebase:{select:{id:!0,folder:!0,agentId:!0,defaultBranch:!0,agent:{select:{id:!0,name:!0,hostname:!0}}}}}}):null,r.codebaseSettings.findUnique({where:{id:"default"}})]),a=m(A.headBranch,e.jiraBranchRegex??n?.defaultJiraBranchRegex??""),o=A.pullRequests[0]??null,s={repo:{id:e.id,name:e.name,owner:e.owner,url:`https://github.com/${e.owner}/${e.repository}`,canonicalOrigin:e.canonicalOrigin,displayOrigin:e.displayOrigin,defaultBranch:i?.codebase.defaultBranch??null},pipeline:{runId:A.id,workflowId:A.workflowId,name:A.name,displayTitle:A.displayTitle,status:A.status,conclusion:A.conclusion,headBranch:A.headBranch,headSha:A.headSha,pullRequests:A.pullRequests,url:A.url},...i?{worktree:{id:i.id,path:i.folder,branch:i.branch,baseBranch:i.baseBranchOverride??i.codebase.defaultBranch,headSha:i.headSha},codebase:{id:i.codebase.id,folder:i.codebase.folder,agentId:i.codebase.agentId},agent:i.codebase.agent}:{},...o?{pr:o}:{},...a?{ticket:{key:a}}:{}},l={cursorValue:`${A.id}:${A.runAttempt}:${A.conclusion??"none"}`};await this.workflowEvents.record({kind:"GITHUB_ACTIONS_RESULT",subjectKey:e.id,dedupeKey:`github-actions-trigger:${e.id}:${A.id}:${A.runAttempt}`,payload:{...s,...l,sessionData:s}});let d="success"===A.conclusion?"GITHUB_WORKFLOW_SUCCEEDED":A.conclusion&&h.has(A.conclusion)?"GITHUB_CHECK_FAILED":null;d&&await this.workflowEvents.record({kind:d,subjectKey:e.id,dedupeKey:`github-workflow-trigger:${d}:${e.id}:${A.id}:${A.runAttempt}`,payload:{...s,...l,sessionData:s}})}async observePipelineRun(e,A,t,r=!0){if(!A.repositoryGithubId||!A.headSha)return!1;let i="completed"===A.status,n=!!A.checkSuiteId;return await this.pipelineStatus.observeSnapshot({repositoryGithubId:A.repositoryGithubId,repositoryNameWithOwner:A.repositoryNameWithOwner,repositoryUrl:A.repositoryUrl,headSha:A.headSha,pipelines:[{id:A.id,name:A.name,status:(0,u.normalizePipelineState)(A.status,A.conclusion),url:A.url,checkSuiteId:A.checkSuiteId,workflowRunId:A.id,workflowId:A.workflowId,runAttempt:A.runAttempt,canRetry:i&&n&&r,retryUnavailableReason:i?n?r?null:"GITHUB_APP_NOT_CONFIGURED":"WORKFLOW_RUN_UNAVAILABLE":"NOT_COMPLETED",source:t,githubUpdatedAt:A.updatedAt}]}),!0}async observeEnhancedWebhook(e,A,t,r){let i={workflow_run:new Set(["requested","in_progress","completed"]),workflow_job:new Set(["queued","in_progress","completed"]),check_run:new Set(["created","rerequested","completed"]),check_suite:new Set(["requested","rerequested","in_progress","completed"]),status:new Set([null])};if(!i[A]?.has(t))return!1;let n=r.repository,a=g(n?.node_id),o="status"===A?g(r.sha):g((r[A]??{}).head_sha);if(!a||!o)return!1;let s=g(n?.full_name)??`${e.owner}/${e.repository}`,l=g(n?.html_url)??`https://github.com/${e.owner}/${e.repository}`;if("workflow_run"===A){let A=I(e,n,r.workflow_run);return!!A&&this.observePipelineRun(e,A,"WEBHOOK")}if("status"===A){let e,A=g(r.context);return!!A&&(await this.pipelineStatus.observeSnapshot({repositoryGithubId:a,repositoryNameWithOwner:s,repositoryUrl:l,headSha:o,pipelines:[{id:A,name:A,status:(0,u.normalizePipelineState)(g(r.state)),url:g(r.target_url),statusContext:A,source:"WEBHOOK",githubUpdatedAt:(e=g(r.updated_at)??g(r.created_at))?new Date(e):null}]}),!0)}if("check_suite"===A){let e=r.check_suite,A=g(e?.node_id);if(!e||!A)return!1;let t=e.app,i=g(e.updated_at)??g(e.completed_at)??g(e.started_at);return await this.pipelineStatus.observeSnapshot({repositoryGithubId:a,repositoryNameWithOwner:s,repositoryUrl:l,headSha:o,pipelines:[{id:A,name:g(t?.name)??"GitHub checks",status:(0,u.normalizePipelineState)(g(e.status),g(e.conclusion)),url:g(e.url),checkSuiteId:A,source:"WEBHOOK",githubUpdatedAt:i?new Date(i):null}]}),!0}if("check_run"===A){let e=r.check_run,A=e?.check_suite,t=g(A?.node_id),i=g(e?.node_id);if(!e||!t||!i)return!1;let n=g(e.completed_at)??g(e.started_at)??g(e.updated_at);return await this.pipelineStatus.observeSnapshot({repositoryGithubId:a,repositoryNameWithOwner:s,repositoryUrl:l,headSha:o,pipelines:[{id:i,name:g(e.name)??"GitHub check",status:C(g(e.status),g(e.conclusion)),url:g(e.details_url)??g(e.html_url),checkSuiteId:t,source:"WEBHOOK",githubUpdatedAt:n?new Date(n):null}]}),!0}let d=r.workflow_job,c=p(d?.run_id)?.toString()??null;if(!d||!c)return!1;let h=g(d.completed_at)??g(d.started_at)??g(d.created_at),f=h?new Date(h):null,m=Array.isArray(d.steps)?d.steps.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];let A=p(e.number);return A?[{number:A,name:g(e.name)??`Step ${A}`,status:(0,u.normalizePipelineState)(g(e.status),g(e.conclusion))}]:[]}):[],w={id:p(d.id)?.toString()??g(d.node_id)??"unknown",name:g(d.name)??"Workflow job",status:(0,u.normalizePipelineState)(g(d.status),g(d.conclusion)),url:g(d.html_url),canRetry:g(d.status)?.toLowerCase()==="completed",retryUnavailableReason:g(d.status)?.toLowerCase()==="completed"?null:"NOT_COMPLETED",steps:m,runAttempt:p(d.run_attempt)};return await this.pipelineStatus.observeSnapshot({repositoryGithubId:a,repositoryNameWithOwner:s,repositoryUrl:l,headSha:o,pipelines:[{id:c,name:g(d.workflow_name)??"GitHub Actions",status:C(g(d.status),g(d.conclusion)),url:g(d.html_url),workflowRunId:c,runAttempt:p(d.run_attempt),source:"WEBHOOK",githubUpdatedAt:f}]}),await this.pipelineStatus.observeJobs(a,c,[w],"WEBHOOK",f),!0}async recordWebhookTrigger(e,A,r,i,n){if(!this.workflowEvents)return!1;let a=n.repository??{},o=n.pull_request??{},s=n.review??{},l=n.comment??{},d=n.check_run??n.check_suite??{},u=null;if("pull_request"===A&&new Set(["opened","reopened","ready_for_review"]).has(r??"")?u="GITHUB_PR_STATE":"pull_request"===A&&"synchronize"===r?u="GITHUB_PR_SYNCHRONIZED":"pull_request"===A&&"closed"===r?u="GITHUB_PR_CLOSED":"pull_request"===A&&"labeled"===r?u="GITHUB_PR_LABEL":"pull_request_review"===A&&"submitted"===r&&g(s.state)?.toLowerCase()==="changes_requested"?u="GITHUB_REVIEW_CHANGES_REQUESTED":"pull_request_review"===A&&"submitted"===r&&g(s.state)?.toLowerCase()==="approved"?u="GITHUB_REVIEW_APPROVED":"pull_request_review_comment"===A&&"created"===r?u="GITHUB_REVIEW_COMMENT":("check_run"===A||"check_suite"===A)&&h.has(g(d.conclusion)?.toLowerCase()??"")?u="GITHUB_CHECK_FAILED":"push"===A&&g(n.ref)===`refs/heads/${g(a.default_branch)}`?u="GITHUB_PUSH_DEFAULT":"issue_comment"===A&&"created"===r&&(u="GITHUB_ISSUE_COMMAND"),!u)return!1;let c=l.user??{},f=Array.isArray(o.labels)?o.labels.flatMap(e=>{let A=e&&"object"==typeof e?g(e.name):null;return A?[A]:[]}):[],I=o.head,C=o.base,w=d.check_suite??n.check_suite??{},E=g(I?.ref),y=g(n.ref)?.replace(/^refs\/heads\//,"")??null,B=g(d.head_branch)??g(w.head_branch),Q=E??y??B,D=await (0,t.getPrismaClient)(),b=await D.codebaseSettings.findUnique({where:{id:"default"}}),S=m(Q,e.jiraBranchRegex??b?.defaultJiraBranchRegex??""),k=Q?await D.worktree.findFirst({where:{branch:Q,primary:!1,missingAt:null,codebase:{repositoryId:e.id}},orderBy:{updatedAt:"desc"},select:{id:!0,folder:!0,branch:!0,baseBranchOverride:!0,headSha:!0,pushStatus:!0,hasStagedChanges:!0,hasUnstagedChanges:!0,codebase:{select:{id:!0,folder:!0,agentId:!0,branch:!0,headSha:!0,defaultBranch:!0,agent:{select:{id:!0,name:!0,hostname:!0}}}}}}):null,v={repo:{id:e.id,name:e.name,owner:e.owner,url:g(a.html_url),canonicalOrigin:e.canonicalOrigin,displayOrigin:g(a.full_name)??e.displayOrigin,defaultBranch:g(a.default_branch)},pr:{number:p(o.number)??p(n.issue?.number),url:g(o.html_url),state:g(o.state)?.toUpperCase()??null,merged:!0===o.merged,labels:f,title:g(o.title),isDraft:!0===o.draft,headBranch:E,headSha:g(I?.sha),baseBranch:g(C?.ref),reviewDecision:g(s.state)?.toUpperCase()??null},pipeline:{checkSuiteId:p(d.id)?.toString()??null,status:g(d.status),conclusion:g(d.conclusion),headBranch:B,headSha:g(d.head_sha)??g(w.head_sha)},comment:{id:p(l.id)?.toString()??null,body:g(l.body)??"",author:{login:g(c.login)}},push:{ref:g(n.ref),before:g(n.before),after:g(n.after)},...k?{worktree:{id:k.id,path:k.folder,branch:k.branch,baseBranch:k.baseBranchOverride??k.codebase.defaultBranch,headSha:k.headSha,pushStatus:k.pushStatus,dirty:k.hasStagedChanges||k.hasUnstagedChanges},codebase:{id:k.codebase.id,folder:k.codebase.folder,agentId:k.codebase.agentId,branch:k.codebase.branch,headSha:k.codebase.headSha},agent:k.codebase.agent}:{},...S?{ticket:{key:S}}:{}};return await this.workflowEvents.record({kind:u,subjectKey:e.id,dedupeKey:`github-webhook-trigger:${i}:${u}`,payload:{...v,sessionData:v,cursorValue:`${i}:${u}`,webhook:{event:A,action:r,deliveryId:i}}}),!0}schedule(e){this.timer&&clearTimeout(this.timer);let A=1e3*Math.max(30,e);this.timer=setTimeout(()=>void this.tick(),A),this.timer.unref(),this.polling.schedule(c,new Date(Date.now()+A))}configurationChanged(){if(this.running){this.rerunRequested=!0;return}this.timer&&clearTimeout(this.timer),this.timer=null,queueMicrotask(()=>void this.tick())}async tick(){if(this.running)return;this.running=!0;let e=60;try{let A=await (0,t.getPrismaClient)(),[r,n,a,o,s]=await Promise.all([A.gitHubSettings.upsert({where:{id:"default"},create:{id:"default"},update:{}}),A.gitHubAppSettings.findUnique({where:{id:"default"}}),this.appConnection(),this.credentials.isConfigured(i.CREDENTIALS.githubPersonalAccessToken),this.credentials.isConfigured(i.CREDENTIALS.githubAppWebhookSecret)]);if(e=r.actionsNotificationPollIntervalSeconds,a?.webhookUrl&&n?.webhookConfiguredAt&&s)return void this.polling.configure(c,{enabled:!1,cadenceSeconds:e,details:{mode:"WEBHOOK"}});if(!o)return void this.polling.configure(c,{enabled:!1,cadenceSeconds:e,details:{mode:"DISABLED",reason:"GITHUB_TOKEN_REQUIRED"}});this.polling.configure(c,{enabled:!0,cadenceSeconds:e,details:{mode:"POLLING"}}),await this.polling.run(c,()=>this.pollRepositories(),e=>e)}catch{}finally{this.running=!1,this.rerunRequested?(this.rerunRequested=!1,queueMicrotask(()=>void this.tick())):this.schedule(e)}}async repositories(){return(await (await (0,t.getPrismaClient)()).codebaseRepository.findMany({orderBy:{name:"asc"},select:{id:!0,name:!0,canonicalOrigin:!0,displayOrigin:!0,jiraBranchRegex:!0}})).flatMap(e=>{let A=/^github\.com\/([^/]+)\/([^/]+)$/i.exec(e.canonicalOrigin.trim());return A?.[1]&&A[2]?[{id:e.id,name:e.name,owner:A[1],repository:A[2],canonicalOrigin:e.canonicalOrigin,displayOrigin:e.displayOrigin,jiraBranchRegex:e.jiraBranchRegex}]:[]})}async fetchRuns(e,A,t){let r=[];for(let i=1;;i+=1){let n,a=`${o.GITHUB_API_BASE_URL}/repos/${encodeURIComponent(e.owner)}/${encodeURIComponent(e.repository)}/actions/runs?per_page=100&page=${i}`,d=Date.now(),u=e=>this.cache.recordRestCall({authentication:"PAT",method:"GET",endpoint:a,operation:l.GITHUB_REST_OPERATIONS.actions.listWorkflowRunsForRepo,requestSource:"ACTIONS_NOTIFICATIONS",durationMs:Date.now()-d,...e}).catch(()=>void 0);try{n=await fetch(a,{headers:{accept:"application/vnd.github+json",authorization:`Bearer ${A}`,"user-agent":"ai-development-environment","x-github-api-version":"2022-11-28"},cache:"no-store"})}catch(A){let e=A instanceof Error?A.message:String(A);throw await u({error:e}),A}let c=await (0,s.observeGitHubRateLimit)("PAT",n),h=await n.json().catch(()=>null);if(!n.ok||!Array.isArray(h?.workflow_runs)){let A=h?.message||`GitHub returned HTTP ${n.status} while polling ${e.owner}/${e.repository}`;throw await u({statusCode:n.status,error:A,rateLimit:c}),Error(A)}await u({statusCode:n.status,rateLimit:c});let I=h.workflow_runs.flatMap(A=>{let t=p(A.id),r=p(A.workflow_id),i=g(A.updated_at),n=i?new Date(i):null,a=A.repository;return t&&r&&n&&Number.isFinite(n.getTime())?[{id:String(t),workflowId:String(r),runAttempt:p(A.run_attempt)??1,name:g(A.name)??"GitHub Actions",displayTitle:g(A.display_title)??g(A.name)??"Workflow run",status:g(A.status)?.toLowerCase()??"unknown",conclusion:g(A.conclusion)?.toLowerCase()??null,headBranch:g(A.head_branch),headSha:g(A.head_sha),pullRequests:f(A.pull_requests),url:g(A.html_url)??"",updatedAt:n,repositoryGithubId:g(a?.node_id),repositoryNameWithOwner:g(a?.full_name)??`${e.owner}/${e.repository}`,repositoryUrl:g(a?.html_url)??`https://github.com/${e.owner}/${e.repository}`,checkSuiteId:g(A.check_suite_node_id)}]:[]});if(r.push(...I),!t||h.workflow_runs.length<100||I.some(e=>e.updatedAt<=t))return r}}async worktreeContext(e,A,t){return t?e.worktree.findFirst({where:{branch:t,missingAt:null,codebase:{repositoryId:A}},orderBy:{updatedAt:"desc"},select:{id:!0,highlightColor:!0}}):null}async observeRun(e,t,r,i,n){var a;let o=new Date,s="success"===(a=r.conclusion)?"GITHUB_ACTIONS_SUCCEEDED":a&&h.has(a)?"GITHUB_ACTIONS_FAILED":null,l=await e.gitHubWorkflowRunObservation.findUnique({where:{codebaseRepositoryId_workflowRunId_runAttempt:{codebaseRepositoryId:t.id,workflowRunId:r.id,runAttempt:r.runAttempt}}});if(await e.gitHubWorkflowRunObservation.upsert({where:{codebaseRepositoryId_workflowRunId_runAttempt:{codebaseRepositoryId:t.id,workflowRunId:r.id,runAttempt:r.runAttempt}},create:{id:(0,A.randomUUID)(),codebaseRepositoryId:t.id,workflowRunId:r.id,runAttempt:r.runAttempt,workflowId:r.workflowId,status:r.status,conclusion:r.conclusion,githubUpdatedAt:r.updatedAt,source:i,lastObservedAt:o},update:{workflowId:r.workflowId,status:r.status,conclusion:r.conclusion,githubUpdatedAt:r.updatedAt,source:i,lastObservedAt:o}}),!(l?"completed"!==l.status||l.conclusion!==r.conclusion:n)||!s||"completed"!==r.status||l?.notifiedAt)return null;let d=await this.worktreeContext(e,t.id,r.headBranch),u=new URLSearchParams({repository:t.id});r.headBranch&&u.set("branch",r.headBranch),u.set("pipeline",r.workflowId);let c=await this.notifications.recordInTransaction(e,{dedupeKey:`github-actions:${t.id}:${r.id}:${r.runAttempt}`,typeKey:s,title:"GITHUB_ACTIONS_SUCCEEDED"===s?"GitHub Actions succeeded":"GitHub Actions failed",body:[t.name,r.name,r.headBranch].filter(e=>!!e).join(" · "),href:`/actions?${u.toString()}`,resourceKind:"GITHUB_WORKFLOW_RUN",resourceId:`${t.id}:${r.id}:${r.runAttempt}`,worktreeId:d?.id??null,highlightColor:d?.highlightColor??null});return await e.gitHubWorkflowRunObservation.update({where:{codebaseRepositoryId_workflowRunId_runAttempt:{codebaseRepositoryId:t.id,workflowRunId:r.id,runAttempt:r.runAttempt}},data:{notifiedAt:o}}),c}async pollRepository(e,A,r){let i=await (0,t.getPrismaClient)(),n=new Date,a=await i.gitHubActionsPollingState.findUnique({where:{codebaseRepositoryId:e.id}});await i.gitHubActionsPollingState.upsert({where:{codebaseRepositoryId:e.id},create:{codebaseRepositoryId:e.id,initializedAt:n,lastPollStartedAt:n},update:{lastPollStartedAt:n}});try{let t=await this.fetchRuns(e,A,a?a.lastPollSucceededAt??a.initializedAt:null),n=[];return await i.$transaction(async A=>{for(let r of t){let t=await this.observeRun(A,e,r,"POLL",!!(a&&r.updatedAt>(a.lastPollSucceededAt??a.initializedAt)));t&&n.push(t)}let r=new Date;await A.gitHubActionsPollingState.update({where:{codebaseRepositoryId:e.id},data:{lastPollCompletedAt:r,lastPollSucceededAt:r,lastError:null}})}),n.forEach(e=>this.notifications.created(e)),await Promise.allSettled(t.flatMap(A=>[this.observePipelineRun(e,A,"REST",r),this.recordWorkflowRunEvent(e,A)])),n.length}catch(A){throw await i.gitHubActionsPollingState.update({where:{codebaseRepositoryId:e.id},data:{lastPollCompletedAt:new Date,lastError:A instanceof Error?A.message:String(A)}}),A}}async pollRepositories(){let e=await this.credentials.getText(i.CREDENTIALS.githubPersonalAccessToken);if(!e)throw Error("GitHub personal access token is unavailable");let[A,r,n]=await Promise.all([this.repositories(),(await (0,t.getPrismaClient)()).gitHubAppSettings.findUnique({where:{id:"default"},select:{id:!0}}),this.credentials.isConfigured(i.CREDENTIALS.githubAppPrivateKey)]),a=!!(r&&n),o=await Promise.allSettled(A.map(A=>this.pollRepository(A,e,a))),s=o.filter(e=>"rejected"===e.status),l=o.reduce((e,A)=>e+("fulfilled"===A.status?A.value:0),0);if(await this.prune(),s.length===A.length&&A.length>0)throw s[0].reason;return{mode:"POLLING",repositories:A.length,failures:s.length,notificationsCreated:l}}async prune(){let e=new Date(Date.now()-2592e6),A=await (0,t.getPrismaClient)();await Promise.all([A.gitHubWorkflowRunObservation.deleteMany({where:{lastObservedAt:{lt:e}}}),A.gitHubWebhookDelivery.deleteMany({where:{receivedAt:{lt:e}}})])}async handleWebhook(e){var r,n;let a,o,s=await this.credentials.getText(i.CREDENTIALS.githubAppWebhookSecret);if(!s)throw Error("GitHub webhook is not configured");if(!e.signature?.startsWith("sha256="))throw Error("GitHub webhook signature is missing");if(r=`sha256=${(0,A.createHmac)("sha256",s).update(e.body).digest("hex")}`,n=e.signature,a=Buffer.from(r),o=Buffer.from(n),!(a.length===o.length&&(0,A.timingSafeEqual)(a,o)))throw Error("GitHub webhook signature is invalid");if(!e.deliveryId?.trim())throw Error("GitHub delivery ID is missing");let l=await (0,t.getPrismaClient)(),d=e.deliveryId.trim();try{await l.gitHubWebhookDelivery.create({data:{deliveryId:d,event:e.event??"unknown",outcome:"RECEIVED"}})}catch(A){if("object"==typeof A&&null!==A&&"code"in A&&"P2002"===A.code){if(0===(await l.gitHubWebhookDelivery.updateMany({where:{deliveryId:d,outcome:{notIn:["PROCESSED","IGNORED"]}},data:{event:e.event??"unknown",action:null,repositoryName:null,workflowRunId:null,outcome:"RECEIVED",error:null,receivedAt:new Date,processedAt:null}})).count)return{outcome:"DUPLICATE",notificationCreated:!1}}else throw A}let u=async(e,A=null)=>{await l.gitHubWebhookDelivery.update({where:{deliveryId:d},data:{outcome:e,error:A,processedAt:new Date}})};try{let A;try{A=JSON.parse(Buffer.from(e.body).toString("utf8"))}catch{throw Error("GitHub webhook payload is invalid JSON")}let t=g(A.action),r=A.repository,i=A.workflow_run;if(await l.gitHubWebhookDelivery.update({where:{deliveryId:d},data:{action:t,repositoryName:g(r?.full_name),workflowRunId:p(i?.id)?.toString()??null}}),"workflow_run"!==e.event||"completed"!==t){let[i,n]=await Promise.all([l.gitHubAppSettings.findUnique({where:{id:"default"}}),this.appConnection()]),a=A.installation;if(!i||!n||String(p(a?.id)??"")!==n.installationId)return await u("IGNORED","Installation does not match configured App"),{outcome:"IGNORED",notificationCreated:!1};let o=g(r?.full_name),s=o?(await this.repositories()).find(e=>`${e.owner}/${e.repository}`.toLowerCase()===o.toLowerCase()):null;if(!s)return await u("IGNORED","Repository is not registered"),{outcome:"IGNORED",notificationCreated:!1};let c=e.event??"unknown",[h,f]=await Promise.all([!!i.enhancedPipelineWebhooksEnabled&&this.observeEnhancedWebhook(s,c,t,A),this.recordWebhookTrigger(s,c,t,d,A)]),I=h||f;return await u(I?"PROCESSED":"IGNORED"),{outcome:I?"PROCESSED":"IGNORED",notificationCreated:!1}}let[n,a]=await Promise.all([l.gitHubAppSettings.findUnique({where:{id:"default"}}),this.appConnection()]),o=A.installation;if(!n||!a||String(p(o?.id)??"")!==a.installationId)return await u("IGNORED","Installation does not match configured App"),{outcome:"IGNORED",notificationCreated:!1};let s=g(r?.full_name),h=p(i?.id),f=p(i?.workflow_id),C=g(i?.updated_at);if(!s||!h||!f||!C)throw Error("GitHub workflow_run payload is incomplete");let m=(await this.repositories()).find(e=>`${e.owner}/${e.repository}`.toLowerCase()===s.toLowerCase());if(!m)return await u("IGNORED","Repository is not registered"),{outcome:"IGNORED",notificationCreated:!1};let w=I(m,r,i);if(!w)throw Error("GitHub workflow_run payload is incomplete");let E=null;return await l.$transaction(async e=>{E=await this.observeRun(e,m,w,"WEBHOOK",!0)}),this.notifications.created(E),await this.observePipelineRun(m,w,"WEBHOOK"),await this.recordWorkflowRunEvent(m,w),await u("PROCESSED"),this.polling.configure(c,{enabled:!1,details:{mode:"WEBHOOK",lastDeliveryId:d,lastDeliveryAt:new Date().toISOString()}}),this.prune().catch(()=>void 0),{outcome:"PROCESSED",notificationCreated:!!E}}catch(A){let e=A instanceof Error?A.message:String(A);throw await u("ERROR",e),A}}}])},253992,e=>{"use strict";e.i(864637),e.i(563629),e.i(514616),e.i(183291),e.s([])},429047,e=>{"use strict";let A=new Set(["QUEUED","PREPARING","RUNNING"]);e.s(["buildOutOfDate",0,function(e){let t;if(A.has(e.status)||!e.worktree||(e.worktree._count?.builds??0)>0||e.finishedAt&&(!e.worktree.lastCheckedAt||e.worktree.lastCheckedAt<e.finishedAt))return!1;try{t=JSON.parse(e.snapshotJson)}catch{return!1}if(!t||"object"!=typeof t||Array.isArray(t))return!1;let r=t.worktree;if(!r||"object"!=typeof r||Array.isArray(r))return!1;if("string"==typeof r.codeStateHash&&e.worktree.codeStateHash)return r.codeStateHash!==e.worktree.codeStateHash;if("string"==typeof r.headSha&&e.worktree.headSha!==r.headSha)return!0;if("boolean"==typeof r.hasStagedChanges){if(r.hasStagedChanges!==e.worktree.hasStagedChanges)return!0}else if(e.worktree.hasStagedChanges)return!0;return"boolean"==typeof r.hasUnstagedChanges?r.hasUnstagedChanges!==e.worktree.hasUnstagedChanges:e.worktree.hasUnstagedChanges}])},808331,e=>{"use strict";var A=e.i(666680),t=e.i(246479),r=e.i(898912),i=e.i(969068);let n=new Set([429,500,503]);async function a(e){await new Promise(A=>setTimeout(A,e))}e.s(["ApnsClient",0,class{sessionFactory;sessions;jwtCache;constructor(e=t.connect){this.sessionFactory=e,this.sessions=new Map,this.jwtCache=new Map}close(){for(let e of this.sessions.values())e.close();this.sessions.clear()}session(e,A){let t="TOKEN"===A.kind?`token:${A.teamId}:${A.keyId}`:`certificate:${A.fingerprint}`,r=`${e}:${t}`,i=this.sessions.get(r);if(i&&!i.closed&&!i.destroyed)return i;let n="CERTIFICATE"===A.kind?{pfx:Buffer.from(A.p12Base64,"base64"),passphrase:A.passphrase}:{},a=this.sessionFactory("SANDBOX"===e?"https://api.sandbox.push.apple.com":"https://api.push.apple.com",n);return a.on("error",()=>{this.sessions.get(r)===a&&this.sessions.delete(r)}),a.on("close",()=>{this.sessions.get(r)===a&&this.sessions.delete(r)}),this.sessions.set(r,a),a}async authorization(e){let t;if("CERTIFICATE"===e.kind)return null;let n=`${e.teamId}:${e.keyId}:${(0,A.createHash)("sha256").update(e.privateKey).digest("hex")}`,a=this.jwtCache.get(n);if(a&&Date.now()-a.createdAt<3e6)return`bearer ${a.token}`;try{t=await (0,r.importPKCS8)(e.privateKey,"ES256")}catch{throw Error("The APNs .p8 key must be an ES256 PKCS#8 private key")}let o=await new i.SignJWT({}).setProtectedHeader({alg:"ES256",kid:e.keyId}).setIssuer(e.teamId).setIssuedAt().sign(t);return this.jwtCache.set(n,{token:o,createdAt:Date.now()}),`bearer ${o}`}async requestOnce(e){let A=await this.authorization(e.authentication),r=this.session(e.environment,e.authentication);return new Promise((i,n)=>{let a=r.request({[t.constants.HTTP2_HEADER_METHOD]:e.method??"POST",[t.constants.HTTP2_HEADER_PATH]:e.path,[t.constants.HTTP2_HEADER_SCHEME]:"https","content-type":"application/json",...A?{authorization:A}:{},...e.headers}),o={},s="";a.setEncoding("utf8"),a.on("response",e=>{o=e}),a.on("data",e=>{(s+=e).length>65536&&a.close(t.constants.NGHTTP2_CANCEL)}),a.on("error",n),a.on("end",()=>{let e=o[t.constants.HTTP2_HEADER_STATUS];i({status:Number(Array.isArray(e)?e[0]:e)||0,body:s,headers:o})}),a.setTimeout(2e4,()=>{a.close(t.constants.NGHTTP2_CANCEL),n(Error("APNs request timed out"))}),a.end(JSON.stringify(e.payload))})}async send(e){if(!e.deviceToken&&!e.broadcastTopic)throw Error("An APNs device token or broadcast topic is required");let t=e.deviceToken?`/3/device/${e.deviceToken.toLowerCase()}`:`/4/broadcasts/apps/${encodeURIComponent(e.broadcastTopic)}`,r=Date.now(),i=0;for(;;){let o;try{o=await this.requestOnce({...e,path:t})}catch(e){if(i>=3)throw e;await a(Math.min(4e3,250*2**i)),i+=1;continue}let s={};try{s=o.body?JSON.parse(o.body):{}}catch{s={}}if(n.has(o.status)&&i<3){await a(function(e,A){let t=Array.isArray(e)?e[0]:e;if(t){let e=Number(t);if(Number.isFinite(e))return Math.min(3e4,1e3*e);let A=Date.parse(t);if(Number.isFinite(A))return Math.max(0,Math.min(3e4,A-Date.now()))}return Math.min(4e3,250*2**A)}(o.headers["retry-after"],i)),i+=1;continue}let l=o.headers["apns-id"];return{status:o.status,reason:s.reason??null,timestamp:"number"==typeof s.timestamp?new Date(s.timestamp):null,apnsId:(Array.isArray(l)?l[0]:l)??e.headers["apns-id"]??(0,A.randomUUID)(),attempts:i+1,durationMs:Date.now()-r}}}async createBroadcastChannel(e){let A=await this.requestOnce({environment:e.environment,authentication:e.authentication,path:`/4/broadcasts/apps/${encodeURIComponent(e.bundleId)}`,payload:{"channel-storage-policy":+("NO_STORAGE"!==e.storagePolicy)},headers:{"apns-topic":`${e.bundleId}.push-type.liveactivity`,"apns-push-type":"liveactivity"}}),t=A.headers["apns-channel-id"],r=Array.isArray(t)?t[0]:t;if(![200,201].includes(A.status)||!r)throw Error(`APNs could not create the broadcast channel (HTTP ${A.status})`);return r}async deleteBroadcastChannel(e){let A=await this.requestOnce({environment:e.environment,authentication:e.authentication,method:"DELETE",path:`/4/broadcasts/apps/${encodeURIComponent(e.bundleId)}`,payload:{},headers:{"apns-topic":`${e.bundleId}.push-type.liveactivity`,"apns-push-type":"liveactivity","apns-channel-id":e.channelId}});if(![200,204].includes(A.status))throw Error(`APNs could not delete the broadcast channel (HTTP ${A.status})`)}}])},683832,e=>{"use strict";let A=new Set(["alert","background","complication","controls","fileprovider","liveactivity","location","mdm","pushtotalk","voip","widgets"]),t=/^[A-Za-z0-9][A-Za-z0-9.-]{0,254}$/;function r(e,A){if(!e||"object"!=typeof e||Array.isArray(e))throw Error(`${A} must be an object`);return e}function i(e,A,t){if("string"!=typeof e||!e.trim())throw Error(`${A} is required`);let r=e.trim();if(r.length>t||r.includes("\0"))throw Error(`${A} is invalid`);return r}function n(e,A,t){return null==e||""===e?null:i(e,A,t)}function a(e,A){let t;if("HEX"===A){let A=e.replace(/[\s<>]/g,"");if(!/^[A-Fa-f0-9]{64}$/.test(A))throw Error("token must contain exactly 32 bytes of hexadecimal data");t=Buffer.from(A,"hex")}else{let A=e.trim();if(!/^[A-Za-z0-9+/_-]+={0,2}$/.test(A))throw Error("token is not valid Base64");try{t=Buffer.from(A.replaceAll("-","+").replaceAll("_","/"),"base64")}catch{throw Error("token is not valid Base64")}if(t.toString("base64").replace(/=+$/,"")!==A.replaceAll("-","+").replaceAll("_","/").replace(/=+$/,""))throw Error("token is not valid Base64")}if(32!==t.length)throw Error("token must decode to exactly 32 bytes");return t.toString("hex").toUpperCase()}e.s(["normalizeDeviceToken",0,a,"parseApnsRegistrationInput",0,function(e){let o=r(e,"registration"),s=new Set(["clientRegistrationId","token","tokenEncoding","topic","environment","supportedPushTypes","displayName","deviceModel","osVersion","appVersion","appBuild","locale","pushMagic"]),l=Object.keys(o).find(e=>!s.has(e));if(l)throw Error(`Unexpected registration field: ${l}`);let d=i(o.tokenEncoding,"tokenEncoding",10);if("HEX"!==d&&"BASE64"!==d)throw Error("tokenEncoding must be HEX or BASE64");let u=i(o.environment,"environment",20);if("SANDBOX"!==u&&"PRODUCTION"!==u)throw Error("environment must be SANDBOX or PRODUCTION");let c=i(o.topic,"topic",255);if(!t.test(c))throw Error("topic is invalid");if(!Array.isArray(o.supportedPushTypes)||!o.supportedPushTypes.length)throw Error("supportedPushTypes must contain at least one push type");let h=[...new Set(o.supportedPushTypes.map(e=>{if("string"!=typeof e||!A.has(e))throw Error(`Unsupported APNs push type: ${String(e)}`);return e}))],g=n(o.pushMagic,"pushMagic",500);if(h.includes("mdm")&&!g)throw Error("pushMagic is required when MDM is supported");return{clientRegistrationId:i(o.clientRegistrationId,"clientRegistrationId",200),token:a(i(o.token,"token",1024),d),tokenEncoding:d,topic:c,environment:u,supportedPushTypes:h,displayName:i(o.displayName,"displayName",120),deviceModel:n(o.deviceModel,"deviceModel",120),osVersion:n(o.osVersion,"osVersion",50),appVersion:n(o.appVersion,"appVersion",50),appBuild:n(o.appBuild,"appBuild",50),locale:n(o.locale,"locale",35),pushMagic:g}},"validatePushEditor",0,function(e){let a,o=r(e,"push editor"),s=i(o.pushType,"pushType",30);if(!A.has(s))throw Error("pushType is unsupported");let l=r(o.headers??{},"headers"),d=r(o.aps??{},"aps"),u=r(o.custom??{},"custom"),c=n(o.credentialId,"credentialId",100),h=Number(l.priority??("background"===s?5:10));if(![1,5,10].includes(h))throw Error("APNs priority must be 1, 5, or 10");if("background"===s&&5!==h)throw Error("Background notifications require priority 5");if(["voip","mdm","pushtotalk"].includes(s)&&10!==h)throw Error(`${s} notifications require priority 10`);if(1===h&&"location"!==s)throw Error("Priority 1 is supported only for location notifications");let g=i(l.topic,"topic",255);if(!t.test(g))throw Error("topic is invalid");let p={complication:".complication",fileprovider:".pushkit.fileprovider",liveactivity:".push-type.liveactivity",location:".location-query",pushtotalk:".voip-ptt",voip:".voip",widgets:".push-type.widgets",controls:".push-type.controls"}[s];if(p&&!g.endsWith(p))throw Error(`${s} notifications require a topic ending in ${p}`);if("mdm"===s){if(!c)throw Error("MDM requires a certificate credential");if(Object.keys(d).length)throw Error("MDM payloads cannot contain aps");if(Object.keys(u).length)throw Error("MDM payloads cannot contain custom root fields");a={mdm:"__PUSH_MAGIC__"}}else{let e={...d},A=e["relevance-score"];if(void 0!==A&&("number"!=typeof A||A<0||A>1))throw Error("aps.relevance-score must be between 0 and 1");let t=e.badge;if(void 0!==t&&("number"!=typeof t||!Number.isInteger(t)||t<0))throw Error("aps.badge must be a non-negative integer");let i=e["interruption-level"];if(void 0!==i&&!["passive","active","time-sensitive","critical"].includes(String(i)))throw Error("aps.interruption-level is invalid");let n=e.sound;if(n&&"object"==typeof n&&!Array.isArray(n)){let e=n.volume;if("number"!=typeof e||!Number.isFinite(e)||e<0||e>1)throw Error("Critical sound volume must be between 0 and 1")}if("background"===s){for(let A of["alert","badge","sound"])if(void 0!==e[A])throw Error(`Background notifications cannot contain aps.${A}`);e["content-available"]=1}if("alert"===s&&!Object.keys(e).length)throw Error("Alert notifications require at least one aps field");if("liveactivity"===s){let A=r(o.liveActivity??{},"liveActivity");if(!Number.isInteger(A.timestamp))throw Error("Live Activity timestamp must be an integer Unix timestamp");if(!["start","update","end"].includes(String(A.event)))throw Error("Live Activity event must be start, update, or end");Object.assign(e,A)}a={...u,aps:e}}let f=Buffer.byteLength(JSON.stringify(a)),I="voip"===s?5120:4096;if(f>I)throw Error(`Payload is ${f} bytes; ${s} allows ${I}`);let C={"apns-push-type":s,"apns-topic":g,"apns-priority":String(h)};for(let[e,A]of[["apns-id",l.id],["apns-expiration",l.expiration],["apns-collapse-id",l.collapseId],["apns-channel-id",l.broadcastChannelId]])null!=A&&""!==A&&(C[e]=i(A,e,"apns-collapse-id"===e?64:200));if(C["apns-id"]&&!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(C["apns-id"]))throw Error("apns-id must be a UUID");if(C["apns-expiration"]&&(!/^\d+$/.test(C["apns-expiration"])||0>Number(C["apns-expiration"])))throw Error("apns-expiration must be a non-negative Unix timestamp");return{editor:{pushType:s,headers:l,aps:d,custom:u,liveActivity:"liveactivity"===s?r(o.liveActivity??{},"liveActivity"):null,credentialId:c},payload:a,headers:C,byteLength:f}}])},286078,e=>{"use strict";var A=e.i(666680),t=e.i(685560),r=e.i(898912),i=e.i(135475);e.i(592299);var n=e.i(747461),a=e.i(972425),o=e.i(863568),s=e.i(848201),l=e.i(808331),d=e.i(683832);let u="default",c=["DEVICES","ALL","DIRECT","BROADCAST"],h="server:apns-recovery";function g(e){return(0,A.createHash)("sha256").update(e).digest("hex").toUpperCase()}function p(e,r){let i;try{i=(0,t.createSecureContext)({pfx:e,passphrase:r})}catch{throw Error("The .p12 file or passphrase is invalid")}let n=i.context.getCertificate();if(!n?.length)throw Error("The .p12 file does not contain a leaf certificate");let a=new A.X509Certificate(n),o=new Date(a.validTo);if(Number.isNaN(o.getTime()))throw Error("The .p12 certificate expiration date is invalid");return{expiresAt:o,fingerprint:a.fingerprint256.replaceAll(":","").toUpperCase()}}function f(e){return JSON.parse(e)}function I(e){try{let A=JSON.parse(e);return Array.isArray(A)?A.filter(e=>"string"==typeof e):[]}catch{return[]}}function C(e,A,t=200){let r=e.trim();if(!r||r.length>t||r.includes("\0"))throw Error(`${A} is required or invalid`);return r}let m=Promise.resolve();async function w(e){let A,t=m;m=new Promise(e=>{A=e}),await t;try{return await e()}finally{A()}}e.s(["PushNotificationsService",0,class{client;credentials;polling;async storedTokenSettings(){return(0,n.readConnectionSettings)(this.credentials,a.CREDENTIALS.apnsTokenSettings,n.apnsTokenConnectionSettings)}async storedCertificateCatalog(){return(0,n.readConnectionSettings)(this.credentials,a.CREDENTIALS.apnsCertificateCatalog,n.apnsCertificateCatalog)}recoveryStarted;activeBatchIds;constructor(e=new l.ApnsClient,A=new o.CredentialService,t){this.client=e,this.credentials=A,this.polling=t,this.recoveryStarted=!1,this.activeBatchIds=new Set,this.polling?.register({id:h,kind:"APNS_RECOVERY",runtime:"SERVER",enabled:!0,cadenceSeconds:30,details:{}}),queueMicrotask(()=>void this.pollRecovery()),setInterval(()=>void this.pollRecovery(),3e4).unref()}async pollRecovery(){this.polling?.schedule(h,new Date(Date.now()+3e4));try{this.polling?await this.polling.run(h,()=>this.recover(),e=>e):await this.recover()}catch{}}changed(){s.agentEventBus.publish(s.PUSH_NOTIFICATIONS_CHANGED_TOPIC,{changed:!0})}subscribe(){return s.agentEventBus.iterate(s.PUSH_NOTIFICATIONS_CHANGED_TOPIC)}async register(e,A){let t=(0,d.parseApnsRegistrationInput)(e);return this.registerValidated(t,A)}async registerValidated(e,t){let r=await (0,i.getPrismaClient)(),n=g(e.token),a=new Date,o={clientRegistrationId:e.clientRegistrationId,topic:e.topic,environment:e.environment},s=await r.$transaction(async r=>{let i=await r.apnsRegistration.findUnique({where:{clientRegistrationId_topic_environment:o}}),s=await r.apnsRegistration.findUnique({where:{tokenHash_topic_environment:{tokenHash:n,topic:e.topic,environment:e.environment}}});s&&s.id!==i?.id&&await r.apnsRegistration.update({where:{id:s.id},data:{token:"",tokenHash:`REASSIGNED:${s.id}:${s.tokenHash}`,status:"INACTIVE",invalidatedAt:a,lastFailureReason:"TOKEN_REASSIGNED",lastFailureAt:a}});let l={token:e.token,tokenHash:n,pushTypesJson:JSON.stringify(e.supportedPushTypes),displayName:e.displayName,deviceModel:e.deviceModel,osVersion:e.osVersion,appVersion:e.appVersion,appBuild:e.appBuild,locale:e.locale,pushMagic:e.pushMagic,lastIpAddress:t,status:"ACTIVE",invalidatedAt:null,lastFailureReason:null,lastFailureAt:null,lastRegisteredAt:a};return{registration:i?await r.apnsRegistration.update({where:{id:i.id},data:l}):await r.apnsRegistration.create({data:{id:(0,A.randomUUID)(),...o,...l}}),created:!i}});return this.changed(),s}async registrations(){let e=await (0,i.getPrismaClient)();return(await e.apnsRegistration.findMany({orderBy:[{status:"asc"},{lastRegisteredAt:"desc"}]})).map(e=>({...e,tokenMasked:e.token?`${e.token.slice(0,8)}…${e.token.slice(-8)}`:"—",supportedPushTypes:I(e.pushTypesJson)}))}async renameRegistration(e,A){let t=await (0,i.getPrismaClient)(),r=await t.apnsRegistration.update({where:{id:e},data:{displayName:C(A,"Display name",120)}});return this.changed(),r}async setRegistrationActive(e,A){let t=await (0,i.getPrismaClient)(),r=await t.apnsRegistration.update({where:{id:e},data:{status:A?"ACTIVE":"INACTIVE",invalidatedAt:A?null:new Date}});return this.changed(),r}async deleteRegistration(e){let A=await (0,i.getPrismaClient)();return await A.apnsRegistration.delete({where:{id:e}}),this.changed(),!0}async rawSettings(){return(await (0,i.getPrismaClient)()).pushNotificationSettings.upsert({where:{id:u},create:{id:u},update:{}})}async settings(){let e=await (0,i.getPrismaClient)(),[A,t,r,n]=await Promise.all([this.rawSettings(),this.storedTokenSettings(),this.storedCertificateCatalog(),this.credentials.isConfigured(a.CREDENTIALS.apnsTokenPrivateKey)]),o=r?.value??[],s=new Map((await e.apnsCertificateCredential.findMany({where:{id:{in:o.map(({id:e})=>e)}}})).map(e=>[e.id,e]));return{tokenConfigured:!!(t&&n),tokenTeamId:t?.value.teamId??null,tokenKeyId:t?.value.keyId??null,tokenPrivateKeyFingerprint:A.tokenPrivateKeyFingerprint,tokenConfiguredAt:A.tokenConfiguredAt,tokenLastUsedAt:A.tokenLastUsedAt,tokenLastError:A.tokenLastError,certificates:o.map(e=>{let A=s.get(e.id);return A?{...e,fingerprint:A.fingerprint,expiresAt:A.expiresAt,lastTestedAt:A.lastTestedAt,lastError:A.lastError,createdAt:A.createdAt,updatedAt:A.updatedAt}:null}).filter(e=>null!==e).sort((e,A)=>e.name.localeCompare(A.name)),updatedAt:new Date(Math.max(A.updatedAt.getTime(),t?.updatedAt.getTime()??0,r?.updatedAt.getTime()??0))}}async saveTokenSettings(e){await this.rawSettings();let A=C(e.teamId,"Team ID",20),t=C(e.keyId,"Key ID",20),n=await this.storedTokenSettings(),o=e.privateKey?.trim()||await this.credentials.getText(a.CREDENTIALS.apnsTokenPrivateKey);if(!o?.includes("-----BEGIN PRIVATE KEY-----"))throw Error("An APNs PKCS#8 .p8 private key is required");try{await (0,r.importPKCS8)(o,"ES256")}catch{throw Error("The APNs .p8 key must be an ES256 PKCS#8 private key")}let s={teamId:A,keyId:t},l=async e=>{await e.pushNotificationSettings.update({where:{id:u},data:{tokenPrivateKeyFingerprint:g(o),tokenConfiguredAt:new Date,tokenLastError:null}})},d=[...n&&JSON.stringify(n.value)===JSON.stringify(s)?[]:[{descriptor:a.CREDENTIALS.apnsTokenSettings,value:(0,a.encodeJsonCredential)(s)}],...e.privateKey?.trim()?[{descriptor:a.CREDENTIALS.apnsTokenPrivateKey,value:Buffer.from(o,"utf8")}]:[]];return d.length?await this.credentials.setMany(d,l):await (await (0,i.getPrismaClient)()).$transaction(l),this.changed(),this.settings()}async clearTokenSettings(){return await this.credentials.deleteMany([a.CREDENTIALS.apnsTokenSettings,a.CREDENTIALS.apnsTokenPrivateKey],async e=>{await e.pushNotificationSettings.upsert({where:{id:u},create:{id:u},update:{tokenPrivateKeyFingerprint:null,tokenConfiguredAt:null,tokenLastUsedAt:null,tokenLastError:null}})}),this.changed(),this.settings()}async addCertificateCredential(e){let t=Buffer.from(e.p12Base64,"base64");if(!t.length||t.length>0x1400000)throw Error("The .p12 file is empty or larger than 20 MiB");if(!["SANDBOX","PRODUCTION"].includes(e.environment))throw Error("Certificate environment is invalid");let r=p(t,e.passphrase),i=(0,A.randomUUID)(),n={id:i,name:C(e.name,"Credential name",100),topic:C(e.topic,"Topic",255),environment:e.environment};return await w(async()=>{let A=await this.storedCertificateCatalog();if(A?.value.some(({name:e})=>e===n.name))throw Error("Credential name already exists");let t=[...A?.value??[],n];await this.credentials.setMany([{descriptor:a.CREDENTIALS.apnsCertificateCatalog,value:(0,a.encodeJsonCredential)(t)},{descriptor:(0,a.apnsCertificateCredential)(i),value:(0,a.encodeJsonCredential)({p12Base64:e.p12Base64,passphrase:e.passphrase})}],async e=>{await e.apnsCertificateCredential.create({data:{id:i,fingerprint:r.fingerprint,expiresAt:r.expiresAt,lastTestedAt:new Date}})})}),this.changed(),this.settings()}async deleteCertificateCredential(e){return await w(async()=>{let A=await this.storedCertificateCatalog();if(!A?.value.some(A=>A.id===e))throw Error("APNs certificate credential not found");await this.credentials.setAndDeleteMany([{descriptor:a.CREDENTIALS.apnsCertificateCatalog,value:(0,a.encodeJsonCredential)(A.value.filter(A=>A.id!==e))}],[(0,a.apnsCertificateCredential)(e)],async A=>{await A.apnsCertificateCredential.delete({where:{id:e}})})}),this.changed(),!0}async retestCertificateCredential(e){let A=await (0,i.getPrismaClient)();if(!await A.apnsCertificateCredential.findUnique({where:{id:e}}))throw Error("APNs certificate credential not found");let t=await this.credentials.getJson((0,a.apnsCertificateCredential)(e));if(!t)throw Error("APNs certificate credential is not configured");try{let r=p(Buffer.from(t.p12Base64,"base64"),t.passphrase);await A.apnsCertificateCredential.update({where:{id:e},data:{fingerprint:r.fingerprint,expiresAt:r.expiresAt,lastTestedAt:new Date,lastError:null}})}catch(t){throw await A.apnsCertificateCredential.update({where:{id:e},data:{lastTestedAt:new Date,lastError:t instanceof Error?t.message:String(t)}}),this.changed(),t}return this.changed(),this.settings()}async channels(){return(await (0,i.getPrismaClient)()).apnsBroadcastChannel.findMany({orderBy:{createdAt:"desc"}})}async tokenAuthentication(e="APNs token authentication is not configured"){let A=await this.storedTokenSettings();if(!A)throw Error(e);let t=await this.credentials.getText(a.CREDENTIALS.apnsTokenPrivateKey);if(!t)throw Error(e);return{kind:"TOKEN",teamId:A.value.teamId,keyId:A.value.keyId,privateKey:t}}async createChannel(e){if(!["SANDBOX","PRODUCTION"].includes(e.environment))throw Error("Channel environment is invalid");if(!["NO_STORAGE","MOST_RECENT"].includes(e.storagePolicy))throw Error("Channel storage policy is invalid");let t=C(e.bundleId,"Bundle ID",255),r=e.channelId?null:await this.tokenAuthentication("APNs token authentication is required for broadcast channels"),n=e.channelId?.trim()||await this.client.createBroadcastChannel({environment:e.environment,authentication:r,bundleId:t,storagePolicy:e.storagePolicy}),a=await (0,i.getPrismaClient)(),o=await a.apnsBroadcastChannel.create({data:{id:(0,A.randomUUID)(),channelId:n,bundleId:t,environment:e.environment,storagePolicy:e.storagePolicy}});return this.changed(),o}async deleteChannel(e){let A=await (0,i.getPrismaClient)(),t=await A.apnsBroadcastChannel.findUnique({where:{id:e}});if(!t)throw Error("Broadcast channel not found");let r=await this.tokenAuthentication("APNs token authentication is required for broadcast channels");return await this.client.deleteBroadcastChannel({environment:t.environment,authentication:r,bundleId:t.bundleId,channelId:t.channelId}),await A.apnsBroadcastChannel.delete({where:{id:e}}),this.changed(),!0}async presets(){return(await (0,i.getPrismaClient)()).pushNotificationPreset.findMany({orderBy:{updatedAt:"desc"}})}async preset(e){return(await (0,i.getPrismaClient)()).pushNotificationPreset.findUnique({where:{id:e}})}async savePreset(e,t,r){let n=(0,d.validatePushEditor)(t),a=await (0,i.getPrismaClient)(),o=r?await a.pushNotificationPreset.update({where:{id:r},data:{name:C(e,"Preset name",100),editorJson:JSON.stringify(n.editor)}}):await a.pushNotificationPreset.create({data:{id:(0,A.randomUUID)(),name:C(e,"Preset name",100),editorJson:JSON.stringify(n.editor)}});return this.changed(),o}async deletePreset(e){let A=await (0,i.getPrismaClient)();return await A.pushNotificationPreset.delete({where:{id:e}}),this.changed(),!0}async history(e=100){return(await (0,i.getPrismaClient)()).pushNotificationBatch.findMany({include:{deliveries:{orderBy:{createdAt:"asc"}}},orderBy:{createdAt:"desc"},take:Math.max(1,Math.min(e,200))})}async historyItem(e){return(await (0,i.getPrismaClient)()).pushNotificationBatch.findUnique({where:{id:e},include:{deliveries:{orderBy:{createdAt:"asc"}}}})}async saveDraft(e){let t=(0,d.validatePushEditor)(e),r=await (0,i.getPrismaClient)(),n=await r.pushNotificationBatch.create({data:{id:(0,A.randomUUID)(),requestId:(0,A.randomUUID)(),status:"DRAFT",editorJson:JSON.stringify(t.editor),payloadJson:JSON.stringify(t.payload),headersJson:JSON.stringify(t.headers),targetMode:"DRAFT"},include:{deliveries:!0}});return this.changed(),n}async deleteHistory(e){let A=await (0,i.getPrismaClient)();if(1!==(await A.pushNotificationBatch.deleteMany({where:{id:e,status:{notIn:["QUEUED","SENDING"]}}})).count){if(!await A.pushNotificationBatch.findUnique({where:{id:e},select:{status:!0}}))throw Error("Push history item not found");throw Error("Queued or sending push notifications cannot be deleted")}return this.changed(),!0}async clearHistory(){let e=await (0,i.getPrismaClient)(),A=await e.pushNotificationBatch.deleteMany({where:{status:{notIn:["QUEUED","SENDING"]}}});return this.changed(),A.count}async send(e){var t;if(t=e.targetMode,!c.includes(t))throw Error(`Unsupported push target mode: ${e.targetMode}`);let r=e.targetMode,n=(0,d.validatePushEditor)(e.editor),a=await (0,i.getPrismaClient)(),o=await a.pushNotificationBatch.findUnique({where:{requestId:e.requestId},include:{deliveries:!0}});if(o)return o;let s=[],l=null,u=null;if("BROADCAST"===r){if("liveactivity"!==n.editor.pushType)throw Error("Broadcast delivery is available only for Live Activities");if(!e.channelId)throw Error("Select a broadcast channel");if(!(l=await a.apnsBroadcastChannel.findUnique({where:{id:e.channelId}})))throw Error("Broadcast channel not found")}else if("DIRECT"===r){if("liveactivity"!==n.editor.pushType)throw Error("Direct-token delivery is available only for Live Activities");if(!e.directToken)throw Error("Enter a Live Activity push token");let A=e.directTokenEncoding??"HEX";if("HEX"!==A&&"BASE64"!==A)throw Error("Direct token encoding must be HEX or BASE64");let t=e.directEnvironment??"SANDBOX";if("SANDBOX"!==t&&"PRODUCTION"!==t)throw Error("Direct token environment is invalid");let r=(0,d.normalizeDeviceToken)(e.directToken,A);u={token:r,tokenHash:g(r),environment:t}}else{let A=[...new Set(e.registrationIds??[])];if(!(s=(await a.apnsRegistration.findMany({where:{status:"ACTIVE",topic:n.headers["apns-topic"],..."DEVICES"===r?{id:{in:A}}:{}}})).filter(e=>I(e.pushTypesJson).includes(n.editor.pushType)).map(e=>({id:e.id,tokenHash:e.tokenHash,topic:e.topic,environment:e.environment}))).length)throw Error("No eligible APNs devices selected")}let h=await a.pushNotificationBatch.create({data:{id:(0,A.randomUUID)(),requestId:e.requestId,status:"QUEUED",editorJson:JSON.stringify(n.editor),payloadJson:JSON.stringify(n.payload),headersJson:JSON.stringify(n.headers),targetMode:r,channelId:l?.id??null,recipientCount:l||u?1:s.length,deliveries:{create:l?[{id:(0,A.randomUUID)(),topic:l.bundleId,environment:l.environment}]:u?[{id:(0,A.randomUUID)(),tokenHash:u.tokenHash,topic:n.headers["apns-topic"],environment:u.environment,recipientSecret:{create:{id:(0,A.randomUUID)(),token:u.token}}}]:s.map(e=>({id:(0,A.randomUUID)(),registrationId:e.id,tokenHash:e.tokenHash,topic:e.topic,environment:e.environment}))}},include:{deliveries:!0}});return this.changed(),this.processBatch(h.id).catch(()=>void 0),h}async resend(e,A){let t=await (0,i.getPrismaClient)(),r=await t.pushNotificationBatch.findUnique({where:{id:e},include:{deliveries:!0}});if(!r)throw Error("Push history item not found");if("DRAFT"===r.targetMode)throw Error("Choose recipients before sending a draft");if("DIRECT"===r.targetMode)throw Error("Direct Live Activity tokens are not retained; load the item and enter the token again");return this.send({requestId:A,editor:f(r.editorJson),targetMode:r.targetMode,registrationIds:r.deliveries.map(e=>e.registrationId).filter(e=>!!e),channelId:r.channelId})}async authentication(e,A,t){let r=await (0,i.getPrismaClient)();if(e.credentialId){let[i,n]=await Promise.all([r.apnsCertificateCredential.findUnique({where:{id:e.credentialId}}),this.storedCertificateCatalog()]),o=n?.value.find(({id:A})=>A===e.credentialId);if(!i||!o)throw Error("APNs certificate credential not found");if(o.environment!==A||o.topic!==t)throw Error("APNs certificate does not match the target topic/environment");let s=await this.credentials.getJson((0,a.apnsCertificateCredential)(i.id));if(!s)throw Error("APNs certificate credential is not configured");return{kind:"CERTIFICATE",p12Base64:s.p12Base64,passphrase:s.passphrase,fingerprint:i.fingerprint}}if("mdm"===e.pushType)throw Error("MDM requires certificate authentication");return this.tokenAuthentication()}async failDelivery(e,A){let t=await (0,i.getPrismaClient)();await t.pushNotificationDelivery.update({where:{id:e},data:{status:"FAILED",reason:A,finishedAt:new Date}}),this.changed()}async executeDelivery(e,A,t,r,n){let a=await (0,i.getPrismaClient)();await a.pushNotificationDelivery.update({where:{id:e.id},data:{status:"SENDING",startedAt:new Date}}),this.changed();try{let i=e.registrationId?await a.apnsRegistration.findUnique({where:{id:e.registrationId}}):null,o=e.registrationId?null:await a.apnsPushRecipientSecret.findUnique({where:{deliveryId:e.id}});if(e.registrationId&&(!i||"ACTIVE"!==i.status))return void await this.failDelivery(e.id,"Registration is no longer active");if(!i&&!o&&!n)return void await this.failDelivery(e.id,"Direct recipient token expired");let s=await this.authentication(A,e.environment,e.topic),l="mdm"===A.pushType?{mdm:i?.pushMagic}:t;if("mdm"===A.pushType&&!i?.pushMagic)return void await this.failDelivery(e.id,"Registration has no MDM push magic");let d=await this.client.send({environment:e.environment,authentication:s,deviceToken:i?.token||o?.token,broadcastTopic:n?.bundleId,payload:l,headers:{...r,...n?{"apns-channel-id":n.channelId}:{}}});await this.recordResponse(e.id,i,d,"TOKEN"===s.kind),"CERTIFICATE"===s.kind&&A.credentialId&&await a.apnsCertificateCredential.updateMany({where:{id:A.credentialId},data:{lastTestedAt:new Date,lastError:200===d.status?null:`HTTP ${d.status}${d.reason?`: ${d.reason}`:""}`}})}catch(t){if(!A.credentialId&&"mdm"!==A.pushType){let e=await (0,i.getPrismaClient)();await e.pushNotificationSettings.updateMany({where:{id:u},data:{tokenLastError:t instanceof Error?t.message:String(t)}})}if(A.credentialId){let e=await (0,i.getPrismaClient)();await e.apnsCertificateCredential.updateMany({where:{id:A.credentialId},data:{lastTestedAt:new Date,lastError:t instanceof Error?t.message:String(t)}})}await this.failDelivery(e.id,t instanceof Error?t.message:String(t))}finally{await a.apnsPushRecipientSecret.deleteMany({where:{deliveryId:e.id}})}}async recordResponse(e,A,t,r){let n=await (0,i.getPrismaClient)(),a=200===t.status;if(await n.pushNotificationDelivery.update({where:{id:e},data:{status:a?"SUCCEEDED":"FAILED",responseCode:t.status,reason:t.reason,responseTimestamp:t.timestamp,apnsId:t.apnsId,attempts:t.attempts,durationMs:t.durationMs,finishedAt:new Date}}),this.changed(),r&&await n.pushNotificationSettings.updateMany({where:{id:u},data:a?{tokenLastUsedAt:new Date,tokenLastError:null}:{tokenLastError:`HTTP ${t.status}${t.reason?`: ${t.reason}`:""}`}}),!A)return;if(a)return void await n.apnsRegistration.update({where:{id:A.id},data:{lastSentAt:new Date,lastFailureReason:null}});let o=410===t.status&&"Unregistered"===t.reason,s=400===t.status&&["BadDeviceToken","DeviceTokenNotForTopic"].includes(t.reason??""),l=!t.timestamp||t.timestamp>=A.lastRegisteredAt;o&&l||s?await n.apnsRegistration.updateMany({where:{id:A.id,lastRegisteredAt:A.lastRegisteredAt},data:{status:"INVALID",invalidatedAt:new Date,lastFailureReason:t.reason,lastFailureAt:new Date}}):await n.apnsRegistration.update({where:{id:A.id},data:{lastFailureReason:t.reason,lastFailureAt:new Date}})}async processBatch(e){let A=await (0,i.getPrismaClient)();if(1===(await A.pushNotificationBatch.updateMany({where:{id:e,status:"QUEUED"},data:{status:"SENDING",startedAt:new Date,error:null}})).count){this.activeBatchIds.add(e);try{let t=await A.pushNotificationBatch.findUnique({where:{id:e},include:{deliveries:{where:{status:"QUEUED"}}}});if(!t)return;let r=f(t.editorJson),i=f(t.payloadJson),n=f(t.headersJson),a=t.channelId?await A.apnsBroadcastChannel.findUnique({where:{id:t.channelId}}):null,o=0,s=Array.from({length:Math.min(16,t.deliveries.length)},async()=>{for(;o<t.deliveries.length;){let e=t.deliveries[o++];if(!e)return;await this.executeDelivery(e,r,i,n,a)}});await Promise.all(s);let l=await A.pushNotificationDelivery.findMany({where:{batchId:e},select:{status:!0}}),d=l.filter(e=>"SUCCEEDED"===e.status).length,u=l.length-d;await A.pushNotificationBatch.update({where:{id:e},data:{status:u?d?"PARTIAL":"FAILED":"SUCCEEDED",successCount:d,failureCount:u,finishedAt:new Date}}),this.changed()}finally{this.activeBatchIds.delete(e)}}}async recover(){if(this.recoveryStarted)return{queuedBatches:0,staleBatches:0,recoveredBatches:0,alreadyRunning:!0};this.recoveryStarted=!0;let e=0,A=0,t=0;try{let r=await (0,i.getPrismaClient)();for(;;){let i=new Date(Date.now()-12e4),n=await r.pushNotificationBatch.findMany({where:{OR:[{status:"QUEUED"},{status:"SENDING",startedAt:{lt:i}}]},orderBy:{createdAt:"asc"},take:100});if(!n.length)break;e+=n.filter(e=>"QUEUED"===e.status).length,A+=n.filter(e=>"SENDING"===e.status).length;let a=[];for(let e of n)if(!this.activeBatchIds.has(e.id)){if("SENDING"===e.status){await r.pushNotificationDelivery.updateMany({where:{batchId:e.id,status:"SENDING"},data:{status:"QUEUED",startedAt:null}});let A=await r.pushNotificationBatch.updateMany({where:{id:e.id,status:"SENDING",startedAt:{lt:i}},data:{status:"QUEUED",startedAt:null}});if(1!==A.count)continue}a.push(e.id)}if(!a.length)break;await Promise.all(a.map(e=>this.processBatch(e))),t+=a.length}return{queuedBatches:e,staleBatches:A,recoveredBatches:t}}finally{this.recoveryStarted=!1}}}])},929748,e=>{"use strict";e.i(808331),e.i(286078),e.s([])},384439,e=>{"use strict";let A=new Set(["MANUAL_CHOICE","RESOURCE_MANUAL_CHOICE"]),t=new Set(["RESOURCE_MANUAL","RESOURCE_MANUAL_CHOICE"]);function r(e){return A.has(e)}let i=/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;e.s(["WORKFLOW_CHOICE_KEY_PATTERN",0,i,"WORKFLOW_QUICK_ACTION_KINDS",0,["STANDARD","MERGE_CONFLICT","GITHUB_ACTIONS","GITLAB_PIPELINES","NONE"],"WORKFLOW_RESOURCE_KINDS",0,["BUILD","CODEBASE","JIRA_TICKET","AGENT_RUN","GITHUB_PIPELINE","GITHUB_JOB","GITLAB_MERGE_REQUEST","GITLAB_PIPELINE","GITLAB_JOB","PULL_REQUEST","WORKTREE","COMMAND_RUN","SKILL","SKILL_SYNC","IOS_DEVICE","SIGNING_PROFILE","PUSH_NOTIFICATION_BATCH","BUILD_DATA_COLLECTION"],"WORKFLOW_STEP_KINDS",0,["JIRA_LOAD_TICKET","JIRA_TRANSITION","JIRA_COMMENT","JIRA_ASSIGN","JIRA_UPDATE_FIELDS","JIRA_RESOLVE_BRANCH","GITHUB_LOAD_PR","GITHUB_MERGE_PR","GITHUB_COLLECT_REVIEW_THREADS","GITHUB_REPLY_REVIEW_THREAD","GITHUB_SET_REVIEW_THREAD_RESOLVED","GITHUB_CREATE_PR","GITHUB_SET_PR_LABELS","GITHUB_RETRY_PIPELINE","GITHUB_RETRY_JOB","GITHUB_CANCEL_WORKFLOW_RUN","GITHUB_SAVE_AUTO_RETRY","GITHUB_WAIT_CHECKS","WORKTREE_CREATE","WORKTREE_CHANGE_BRANCH","WORKTREE_COMMIT","WORKTREE_REFRESH_PULL_REQUEST","WORKTREE_OPERATION","WORKTREE_PREPARATION","WORKTREE_SET_AUTO_SYNC","WORKTREE_SET_AUTO_MERGE","WORKTREE_DELETE","WORKTREE_MOVE","WORKTREE_INSPECT","WORKTREE_INSPECT_GIT","WORKTREE_GIT_OPERATION","WORKTREE_WAIT_PUSH_READY","WORKTREE_SNAPSHOT","CODEBASE_FETCH_REFRESH","CODEBASE_INSPECT_GIT","CODEBASE_GIT_OPERATION","BUILD_START","BUILD_READ_TEST_RESULTS","BUILD_READ_COVERAGE","BUILD_IMPORT_COVERAGE","BUILD_EXPORT","BUILD_DEPLOY","BUILD_CANCEL","DISK_SPACE_LOAD","DISK_SPACE_REFRESH","DISK_SPACE_UPDATE_THRESHOLDS","DISK_SPACE_SET_MONITORING","DISK_SPACE_SET_PRESSURE_MODE","SKILL_APPLY","RUN_CREATE_PLAN","RUN_CREATE_SESSION","RUN_PLAY_PLAN","RUN_FOLLOW_UP","RUN_STEER","RUN_ANSWER","RUN_PAUSE","RUN_CONTINUE","RUN_CANCEL","RUN_REVISE_ANSWER","RUN_READ_RESULT","RUN_CAPTURE_CHECKPOINT","RUN_ARCHIVE_DELETE","NOTIFICATION_SEND","IOS_PUSH_SEND","HUMAN_CONFIRM","HUMAN_CHOICE","CONTROL_IF","CONTROL_JOIN","CONTROL_DELAY","CONTROL_WAIT_UNTIL","CONTROL_FOR_EACH","CONTROL_TRY","CONTROL_SET_VARIABLE","CONTROL_SUBWORKFLOW","SAVED_COMMAND","CUSTOM_COMMAND","COMMAND_RERUN","COMMAND_TERMINATE","COMMAND_READ_OUTPUT","WORKTREE_INSPECT_DIFF","WORKTREE_UPDATE_METADATA","WORKTREE_MOVE_CONTROL","BUILD_REBUILD","BUILD_GENERATE_REPORT","BUILD_DELETE","SKILL_PREPARE_SYNC","SKILL_RESOLVE_SYNC","SKILL_SKIP_SYNC","BUILD_DATA_REFRESH","BUILD_DATA_DELETE","BUILD_DATA_SET_LOCK","TAILSCALE_SERVE_INSPECT","TAILSCALE_SERVE_UPSERT_TEMPLATE","TAILSCALE_SERVE_SET_AGENT_ENABLED","TAILSCALE_SERVE_DELETE_TEMPLATE","SIGNING_REFRESH","SIGNING_SYNC_PROFILE","SIGNING_DELETE_EXPIRED","IOS_DEVICE_REGISTER","IOS_DEVICE_REJECT","AGENT_RECONCILE","AGENT_UPDATE_CADENCE","CCUSAGE_COLLECT","MODEL_COST_REFRESH","GITHUB_UPDATE_PR","GITHUB_SUBMIT_REVIEW","GITHUB_REQUEST_REVIEWERS","GITHUB_DISPATCH_WORKFLOW","GITLAB_LOAD_MR","GITLAB_CREATE_MR","GITLAB_UPDATE_MR","GITLAB_SUBMIT_REVIEW","GITLAB_REPLY_DISCUSSION","GITLAB_SET_DISCUSSION_RESOLVED","GITLAB_MERGE_MR","GITLAB_SET_MR_LABELS","GITLAB_REQUEST_REVIEWERS","GITLAB_CREATE_PIPELINE","GITLAB_RETRY_PIPELINE","GITLAB_RETRY_JOB","GITLAB_CANCEL_PIPELINE","GITLAB_SAVE_AUTO_RETRY","GITLAB_WAIT_PIPELINE","JIRA_CREATE_TICKET","JIRA_ADD_WORKLOG","JIRA_LINK_TICKETS","TERMINAL_RUN","MCP_CALL","SSE_ENDPOINT_ACTION","SSE_MOCK_ACTION","SSE_STORAGE_ACTION","SSE_BREAKPOINT_RESOLVE","SSE_HISTORY_CLEAR","SSE_SCRIPT_TEST"],"WORKFLOW_TRIGGER_KINDS",0,["MANUAL","MANUAL_CHOICE","RESOURCE_MANUAL","RESOURCE_MANUAL_CHOICE","SCHEDULE","WORKFLOW_FINISHED","GITHUB_PR_STATE","GITHUB_REVIEW_CHANGES_REQUESTED","GITHUB_REVIEW_COMMENT","GITHUB_PR_CLOSED","GITHUB_CHECK_FAILED","GITHUB_PUSH_DEFAULT","GITHUB_WORKFLOW_SUCCEEDED","GITHUB_ISSUE_COMMAND","GITHUB_ACTIONS_RESULT","GITHUB_PR_LABEL","BUILD_RESULT","BUILD_TEST_THRESHOLD","BUILD_COVERAGE_THRESHOLD","BUILD_HOOK_FAILED","AGENT_CONNECTION","AGENT_JOB_FAILED","AGENT_DISK_REPORT","AGENT_DISK_THRESHOLD","AGENT_DISK_STATE_CHANGED","AGENT_DISK_CLEANUP_RESULT","CCUSAGE_THRESHOLD","WORKTREE_CREATED","WORKTREE_BEHIND","WORKTREE_CONFLICT","WORKTREE_MISSING","WORKTREE_DIVERGED","WORKTREE_DIRTY_DURATION","WORKTREE_NEW_COMMIT","CODEBASE_REMOTE_BRANCH","JIRA_STATUS","JIRA_LABEL","JIRA_ASSIGNED_SELF","JIRA_SOURCE_NEW_TICKET","JIRA_MENTION","JIRA_SPRINT_STARTED","JIRA_ISSUE_CREATED","JIRA_ISSUE_DELETED","JIRA_ISSUE_COMMAND","JIRA_ATTACHMENT_ADDED","JIRA_ISSUE_LINKED","RUN_STARTED","RUN_COMPLETED","RUN_QUESTION_NEEDED","RUN_QUESTION_ANSWERED","RUN_PAUSED","RUN_CONTINUED","RUN_FAILED","RUN_CANCELLED","RUN_PLAN_PLAYED","RUN_FOLLOW_UP","RUN_IMPORTED","RUN_USAGE_THRESHOLD","RUN_EVENT_MATCH","COMMAND_RUN_RESULT","COMMAND_OUTPUT_MATCH","SKILL_SYNC_RESULT","SKILL_SYNC_CONFLICT","GITHUB_PIPELINE_STATUS_CHANGED","GITHUB_PR_SYNCHRONIZED","GITHUB_REVIEW_APPROVED","GITLAB_MR_STATE","GITLAB_REVIEW_CHANGES_REQUESTED","GITLAB_REVIEW_COMMENT","GITLAB_MR_CLOSED","GITLAB_PIPELINE_FAILED","GITLAB_PUSH_DEFAULT","GITLAB_PIPELINE_SUCCEEDED","GITLAB_NOTE_COMMAND","GITLAB_PIPELINE_RESULT","GITLAB_MR_LABEL","GITLAB_PIPELINE_STATUS_CHANGED","GITLAB_MR_SYNCHRONIZED","GITLAB_REVIEW_APPROVED","GITLAB_JOB_STATUS_CHANGED","JIRA_TICKET_UPDATED","JIRA_COMMENT_ADDED","JIRA_WORKLOG_ADDED","JIRA_SPRINT_ENDED","CODEBASE_SYNC_STATE_CHANGED","CODEBASE_OPERATION_FAILED","WORKTREE_SYNC_STATE_CHANGED","WORKTREE_AUTOMATION_RESULT","WORKTREE_CLEAN","PUSH_NOTIFICATION_RESULT","IOS_DEVICE_ENROLLED","IOS_DEVICE_REGISTRATION_RESULT","SIGNING_OPERATION_RESULT","SIGNING_ASSET_EXPIRING","BUILD_DATA_THRESHOLD","BUILD_DATA_CLEANUP_RESULT","POLLING_OPERATION_STATE","MODEL_COST_CATALOG_CHANGED","CREDENTIAL_STORE_DEGRADED","AGENT_RESOURCE_THRESHOLD","AGENT_VERSION_CHANGED","TOOL_CALL_RESULT","SSE_REQUEST_OPENED","SSE_EVENT_EMITTED","SSE_BREAKPOINT_WAITING","SSE_BREAKPOINT_RESOLVED","SSE_STREAM_COMPLETED","SSE_STREAM_FAILED"],"isChoiceTriggerKind",0,r,"isResourceTriggerKind",0,function(e){return t.has(e)},"isWorkflowChoiceKey",0,function(e){return"string"==typeof e&&i.test(e)},"workflowStaticSourceHandles",0,function(e){return r(e)?[]:"CONTROL_IF"===e?["true","false"]:"CONTROL_FOR_EACH"===e?["body","empty"]:"CONTROL_TRY"===e?["success","catch"]:"SAVED_COMMAND"===e||"CUSTOM_COMMAND"===e?["success","failure","match"]:["success","failure"]}])},963408,e=>{"use strict";let A=/^([A-Za-z0-9_-]+)(?:\[(\d+)\])?$/,t=/^[A-Za-z0-9_-]+(?:\[\d+\])?(?:\.[A-Za-z0-9_-]+(?:\[\d+\])?)*$/,r=/\{\{\s*([A-Za-z0-9_-]+(?:\[\d+\])?(?:\.[A-Za-z0-9_-]+(?:\[\d+\])?)*)\s*\}\}/g,i=/\{\{([^{}]*)\}\}/g;function n(e){return e.split(".").flatMap(t=>{let r=A.exec(t);if(!r)throw Error(`Invalid session path: ${e}`);return void 0===r[2]?[r[1]]:[r[1],Number(r[2])]})}function a(e,A){let t=e;for(let e of n(A)){if(null==t)return;if("number"==typeof e){if(!Array.isArray(t))return;t=t[e]}else{if("object"!=typeof t||Array.isArray(t))return;t=t[e]}}return t}e.s(["getSessionValue",0,a,"hasSessionValue",0,function(e,A){return void 0!==a(e,A)},"invalidWorkflowValueBindings",0,function e(A,r=[]){if(Array.isArray(A))for(let t of A)e(t,r);else if(A&&"object"==typeof A)for(let i of("SESSION"!==A.source||"string"==typeof A.path&&t.test(A.path)||r.push("Session bindings require a valid dotted path"),Object.values(A)))e(i,r);else if("string"==typeof A&&/\{\{|\}\}/.test(A)){let e=A.replace(i,"");for(let n of(/\{\{|\}\}/.test(e)&&r.push("Text interpolation contains unmatched braces"),A.matchAll(i)))t.test(n[1].trim())||r.push("Text interpolation requires a valid dotted path")}return r},"mergeSessionData",0,function(e,A){let t=(e,A)=>{if(e&&A&&"object"==typeof e&&"object"==typeof A&&!Array.isArray(e)&&!Array.isArray(A)){let r={...e};for(let[e,i]of Object.entries(A))r[e]=t(r[e],i);return r}return structuredClone(A)};return t(e,A)},"resolveWorkflowValue",0,function e(A,t){var i,n;return A&&"object"==typeof A&&!Array.isArray(A)&&"SESSION"===A.source&&"string"==typeof A.path?a(t,A.path):A&&"object"==typeof A&&!Array.isArray(A)&&"LITERAL"===A.source?A.value:Array.isArray(A)?A.map(A=>e(A,t)):A&&"object"==typeof A?Object.fromEntries(Object.entries(A).map(([A,r])=>[A,e(r,t)])):"string"==typeof A?(i=A,n=t,i.replace(r,(e,A)=>{let t=a(n,A);return null==t?"":"string"==typeof t?t:JSON.stringify(t)})):A},"setSessionValue",0,function(e,A,t){let r=structuredClone(e),i=n(A),a=r;return i.forEach((e,r)=>{if(r===i.length-1){if("number"==typeof e){if(!Array.isArray(a))throw Error(`Expected an array at ${A}`);a[e]=t}else{if(Array.isArray(a))throw Error(`Expected an object at ${A}`);a[e]=t}return}let n="number"==typeof i[r+1];if("number"==typeof e){if(!Array.isArray(a))throw Error(`Expected an array at ${A}`);let t=a[e];t&&"object"==typeof t||(a[e]=n?[]:{}),a=a[e]}else{if(Array.isArray(a))throw Error(`Expected an object at ${A}`);let t=a[e];t&&"object"==typeof t||(a[e]=n?[]:{}),a=a[e]}}),r},"workflowSessionData",0,function(e){let A=JSON.parse(e);if(!A||"object"!=typeof A||Array.isArray(A))throw Error("Workflow session data must be a JSON object");return A},"workflowValueSessionPaths",0,function e(A,i=new Set){if(Array.isArray(A))for(let t of A)e(t,i);else if(A&&"object"==typeof A)for(let r of("SESSION"===A.source&&"string"==typeof A.path&&t.test(A.path)&&i.add(A.path),Object.values(A)))e(r,i);else if("string"==typeof A)for(let e of A.matchAll(r))i.add(e[1]);return i}])},388385,222335,69988,e=>{"use strict";var A=e.i(853205),t=e.i(662114),r=e.i(591135),i=e.i(380592),n=e.i(384439),a=e.i(963408);function o(e){return{kind:"static",options:e.map(e=>({value:e,label:e.charAt(0)+e.slice(1).toLowerCase().replace(/_/g," ")}))}}function s(e){return{kind:"static",options:e}}let l={agent:"agent.id",codebase:"codebase.id",worktree:"worktree.id",githubRepository:"repo.id",githubPullRequest:"pr.number",jiraTicket:"ticket.key",agentRun:"run.id",githubWorkflowRun:"pipeline.runId"};function d(e,A){return{kind:"resource",resource:e,scopeFrom:A,sessionPath:l[e]}}let u=["literal","session","interpolation"],c=["literal","interpolation"],h=(e,A,t={})=>({key:e,label:A,control:"text",valueModes:u,...t}),g=(e,A,t={})=>h(e,A,{multiline:!0,...t}),p=(e,A,t={})=>({key:e,label:A,control:"number",valueModes:["literal","session"],...t}),f=(e,A,t={})=>({key:e,label:A,control:"boolean",...t}),I=(e,A,t,r={})=>({key:e,label:A,control:"enum",options:t,...r}),C=(e,A,t,r={})=>{let{scopeFrom:i,...n}=r;return{key:e,label:A,control:"resource",options:d(t,i),valueModes:u,...n}},m=(e,A,t,r={})=>{let{scopeFrom:i,...n}=r;return{key:e,label:A,control:"resourceMulti",options:d(t,i),valueModes:c,...n}},w=(e,A,t={})=>({key:e,label:A,control:"stringList",valueModes:c,...t}),E=e=>({key:"mcpPresetIds",label:"MCP tool presets",control:"mcpPresetMulti",presetKind:e,default:[]}),y=(e,A,t={})=>({key:e,label:A,control:"record",valueModes:c,...t}),B=(e,A,t={})=>({key:e,label:A,control:"json",valueModes:c,...t}),Q=(e,A,t={})=>({key:e,label:A,control:"triggerChoices",...t}),D=s([{value:"EQ",label:"Equals"},{value:"NE",label:"Not equal"},{value:"GT",label:"Greater than"},{value:"GTE",label:"Greater or equal"},{value:"LT",label:"Less than"},{value:"LTE",label:"Less or equal"},{value:"CONTAINS",label:"Contains"},{value:"MATCHES",label:"Matches RE2"},{value:"EXISTS",label:"Exists"}]),b=o(i.WORKTREE_OPERATIONS.filter(e=>"OPEN_EDITOR"!==e)),S=()=>[h("owner","Repository owner",{placeholder:"octocat",help:"Defaults to the repository from session data."}),h("name","Repository name",{placeholder:"hello-world"})],k=e=>[C("worktreeId","Worktree","worktree"),C("jiraIssueKey","Jira issue key","jiraTicket",{placeholder:"APP-123"}),{key:"model",label:"Model",control:"model",required:!0,valueModes:["literal","session"],modelKeys:{provider:"provider",model:"model",effort:"effort",scopeFrom:"worktreeId"}},f("webSearchEnabled","Enable web search"),E(e),p("worktreeConcurrencyLimit","Worktree concurrency limit",{default:"PLAN"===e?0:"SESSION"===e?1:void 0,minimum:0,maximum:32,integer:!0,help:"PLAN"===e?"Maximum plans admitted on this worktree. Use 0 for unlimited.":"SESSION"===e?"Maximum sessions admitted on this worktree. Use 0 for unlimited.":"Maximum same-kind runs admitted on this worktree. Use 0 for unlimited; leave empty for the source kind's default."}),g("prompt","Prompt",{required:!0}),w("attachmentIds","Attachment IDs")],v={JIRA_LOAD_TICKET:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),f("force","Bypass cache")]},JIRA_TRANSITION:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),h("transitionId","Transition ID",{required:!0})]},JIRA_COMMENT:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),g("content","Comment",{required:!0}),I("format","Format",s([{value:"MARKDOWN",label:"Markdown"},{value:"JIRA_WIKI",label:"Jira wiki"}]))]},JIRA_ASSIGN:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),C("accountId","Assignee","jiraUser",{scopeFrom:"issueKey",help:"Leave empty to unassign the ticket."})]},JIRA_UPDATE_FIELDS:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),B("fields","Fields",{placeholder:'{ "labels": ["ready"] }'})]},JIRA_RESOLVE_BRANCH:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),C("codebaseId","Codebase","codebase")]},GITHUB_LOAD_PR:{fields:[...S(),p("number","Pull request number")]},GITHUB_MERGE_PR:{fields:[...S(),p("number","Pull request number"),I("method","Merge method",s([{value:"SQUASH",label:"Squash"},{value:"MERGE",label:"Merge"},{value:"REBASE",label:"Rebase"}])),h("commitHeadline","Commit headline"),g("commitBody","Commit body"),h("authorEmail","Author email")]},GITHUB_COLLECT_REVIEW_THREADS:{fields:[...S(),p("number","Pull request number")]},GITHUB_REPLY_REVIEW_THREAD:{fields:[h("threadId","Review thread ID",{required:!0}),g("body","Reply",{required:!0})]},GITHUB_SET_REVIEW_THREAD_RESOLVED:{fields:[h("threadId","Review thread ID",{required:!0}),f("resolved","Mark resolved")]},GITHUB_CREATE_PR:{fields:[...S(),h("baseRefName","Base branch"),h("headRefName","Head branch"),h("title","Title"),g("body","Body"),f("draft","Open as draft")]},GITHUB_SET_PR_LABELS:{fields:[...S(),p("number","Pull request number"),w("labels","Labels")]},GITHUB_RETRY_PIPELINE:{fields:[C("repositoryId","Repository","githubRepository"),h("checkSuiteId","Check suite ID")]},GITHUB_RETRY_JOB:{fields:[C("repositoryId","Repository","githubRepository"),h("checkSuiteId","Check suite ID",{required:!0}),h("jobId","Workflow job ID",{required:!0})]},GITHUB_CANCEL_WORKFLOW_RUN:{fields:[h("codebaseRepositoryId","Codebase repository ID"),C("workflowRunId","Workflow run","githubWorkflowRun",{scopeFrom:"codebaseRepositoryId"}),f("force","Force cancel")]},GITHUB_SAVE_AUTO_RETRY:{fields:[B("input","Auto-retry rule",{required:!0})]},GITHUB_WAIT_CHECKS:{fields:[h("repositoryId","Repository ID"),h("workflowRunId","Workflow run ID")]},GITLAB_LOAD_MR:{fields:[h("projectId","Project ID"),p("iid","Merge request IID")]},GITLAB_CREATE_MR:{fields:[h("projectId","Project ID"),h("sourceBranch","Source branch"),h("targetBranch","Target branch"),h("title","Title"),g("description","Description"),f("removeSourceBranch","Remove source branch"),f("squash","Squash commits"),w("reviewerIds","Reviewer IDs"),w("labels","Labels")]},GITLAB_UPDATE_MR:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),h("title","Title"),g("description","Description"),I("stateEvent","State",o(["CLOSE","REOPEN"])),w("reviewerIds","Reviewer IDs"),w("labels","Labels")]},GITLAB_SUBMIT_REVIEW:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),I("outcome","Review outcome",o(["APPROVE","COMMENT","REQUEST_CHANGES"])),g("body","Review body")]},GITLAB_REPLY_DISCUSSION:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),h("discussionId","Discussion ID",{required:!0}),g("body","Reply",{required:!0})]},GITLAB_SET_DISCUSSION_RESOLVED:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),h("discussionId","Discussion ID",{required:!0}),f("resolved","Mark resolved")]},GITLAB_MERGE_MR:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),f("squash","Squash commits"),f("removeSourceBranch","Remove source branch"),f("autoMerge","Enable auto-merge"),h("sha","Expected source SHA")]},GITLAB_SET_MR_LABELS:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),w("labels","Labels")]},GITLAB_REQUEST_REVIEWERS:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),w("reviewerIds","Reviewer IDs")]},GITLAB_CREATE_PIPELINE:{fields:[h("projectId","Project ID"),h("ref","Git ref"),B("variables","Pipeline variables")]},GITLAB_RETRY_PIPELINE:{fields:[h("projectId","Project ID"),h("pipelineId","Pipeline ID")]},GITLAB_RETRY_JOB:{fields:[h("projectId","Project ID"),h("jobId","Job ID")]},GITLAB_CANCEL_PIPELINE:{fields:[h("projectId","Project ID"),h("pipelineId","Pipeline ID")]},GITLAB_SAVE_AUTO_RETRY:{fields:[B("input","Auto-retry rule",{required:!0})]},GITLAB_WAIT_PIPELINE:{fields:[h("projectId","Project ID"),h("pipelineId","Pipeline ID")]},WORKTREE_CREATE:{fields:[C("codebaseId","Codebase","codebase"),I("mode","Branch mode",o(["NEW","EXISTING","TICKET"])),h("branchName","Branch name"),h("ticketKey","Ticket key",{placeholder:"APP-123"}),h("baseBranch","Base branch")]},WORKTREE_CHANGE_BRANCH:{fields:[C("worktreeId","Worktree","worktree"),I("mode","Branch mode",o(["NEW","EXISTING","TICKET"])),h("branchName","Branch name"),h("ticketKey","Ticket key",{placeholder:"APP-123"}),h("baseBranch","Base branch"),f("stashOnFailure","Stash on failure")]},WORKTREE_COMMIT:{fields:[C("worktreeId","Worktree","worktree"),g("message","Commit message",{required:!0}),f("signed","Signed commit"),f("stageAll","Stage all",{default:!0}),B("paths","Selected paths")]},WORKTREE_REFRESH_PULL_REQUEST:{fields:[C("worktreeId","Worktree","worktree")]},WORKTREE_OPERATION:{fields:[C("worktreeId","Worktree","worktree"),I("operation","Operation",b),f("forcePreparations","Force preparation conflicts",{help:"Destructively resets preparation-managed paths before Sync or Rebase, then reapplies the current rules."})]},WORKTREE_PREPARATION:{fields:[C("worktreeId","Worktree","worktree"),I("action","Action",o(i.WORKTREE_PREPARATION_ACTIONS))]},WORKTREE_SET_AUTO_SYNC:{fields:[C("worktreeId","Worktree","worktree"),I("action","Action",o(["ENABLE","RETRY","FORCE","CANCEL"])),h("conflictWorkflowId","Conflict workflow ID"),h("conflictWorkflowChoice","Conflict workflow choice")]},WORKTREE_SET_AUTO_MERGE:{fields:[C("worktreeId","Worktree","worktree"),I("action","Action",o(["ENABLE","RETRY","CANCEL"])),h("repositoryNameWithOwner","Repository",{placeholder:"owner/repository"}),p("pullRequestNumber","Pull request number"),I("method","Merge method",o(["MERGE","REBASE","SQUASH"])),h("commitHeadline","Commit headline"),g("commitBody","Commit body"),h("authorEmail","Author email"),f("deleteWorktree","Delete worktree after merge"),f("moveTicketToDone","Move Jira ticket to done")]},WORKTREE_DELETE:{fields:[C("worktreeId","Worktree","worktree"),f("deleteRemoteBranch","Delete remote branch")]},WORKTREE_MOVE:{fields:[C("worktreeId","Source worktree","worktree"),C("targetCodebaseId","Target codebase","codebase",{required:!0}),C("targetWorktreeId","Target worktree","worktree"),f("deleteSource","Delete source")]},WORKTREE_INSPECT:{fields:[C("worktreeId","Worktree","worktree")]},WORKTREE_INSPECT_GIT:{fields:[C("worktreeId","Worktree","worktree")]},WORKTREE_GIT_OPERATION:{fields:[C("worktreeId","Worktree","worktree"),I("operation","Operation",o(i.WORKTREE_GIT_OPERATIONS)),h("branch","Branch"),h("stashOid","Stash OID"),f("stashChanges","Stash changes first")]},WORKTREE_WAIT_PUSH_READY:{fields:[C("worktreeId","Worktree","worktree")]},WORKTREE_SNAPSHOT:{fields:[h("kind","Checkpoint kind",{placeholder:"STEP"})]},CODEBASE_FETCH_REFRESH:{fields:[C("codebaseId","Codebase","codebase"),I("operation","Operation",o(["FETCH","REFRESH"]))]},CODEBASE_INSPECT_GIT:{fields:[C("codebaseId","Codebase","codebase")]},CODEBASE_GIT_OPERATION:{fields:[C("codebaseId","Codebase","codebase"),I("operation","Operation",o(r.CODEBASE_GIT_OPERATIONS)),h("branch","Branch"),h("stashOid","Stash OID"),f("stashChanges","Stash changes first")]},BUILD_START:{fields:[C("worktreeId","Worktree","worktree"),h("configurationId","Build configuration ID",{required:!0}),I("action","Action",o(t.BUILD_ACTIONS)),B("destination","Destination"),m("scriptIds","Build scripts","buildScript"),B("advancedSettings","Advanced settings"),f("exportWhenComplete","Export when complete"),B("exportSettings","Export settings"),f("worktreeCoverage","Collect worktree coverage")]},BUILD_READ_TEST_RESULTS:{fields:[h("buildId","Build ID")]},BUILD_READ_COVERAGE:{fields:[h("buildId","Build ID")]},BUILD_IMPORT_COVERAGE:{fields:[C("worktreeId","Worktree","worktree"),h("buildName","Build name",{default:"{{workflow.name}}",help:"Name shown on the build and coverage pages. Defaults to the workflow name."}),h("reportPath","Coverage file",{required:!0,default:"coverage/lcov.info",help:"Path inside the worktree, written by whichever test command ran first."}),I("format","Coverage format",o(["AUTO","LCOV","ISTANBUL"]))]},BUILD_EXPORT:{fields:[h("buildId","Build ID"),B("settings","Export settings",{required:!0})]},BUILD_DEPLOY:{fields:[h("buildId","Build ID"),B("destinations","Destinations")]},BUILD_CANCEL:{fields:[h("buildId","Build ID")]},DISK_SPACE_LOAD:{fields:[C("agentId","Agent","agent")]},DISK_SPACE_REFRESH:{fields:[C("agentId","Agent","agent")]},DISK_SPACE_UPDATE_THRESHOLDS:{fields:[p("normalThresholdGiB","Normal threshold (GiB)",{required:!0}),p("pressureThresholdGiB","Pressure threshold (GiB)",{required:!0})]},DISK_SPACE_SET_MONITORING:{fields:[C("agentId","Agent","agent"),f("enabled","Monitoring enabled",{required:!0,default:!0})]},DISK_SPACE_SET_PRESSURE_MODE:{fields:[C("agentId","Agent","agent"),f("enabled","Manual pressure mode",{required:!0,default:!0})]},SKILL_APPLY:{fields:[C("groupId","Skill group","skillGroup",{help:"Leave empty to sync all skills."})]},NOTIFICATION_SEND:{fields:[h("title","Title",{required:!0}),g("body","Body",{required:!0}),h("href","Link")]},IOS_PUSH_SEND:{fields:[I("targetMode","Target mode",o(["ALL","DEVICES","BROADCAST","DIRECT"])),m("registrationIds","Registrations","apnsRegistration"),C("channelId","Broadcast channel","apnsChannel"),B("editor","Notification editor"),h("directToken","Direct device token"),I("directTokenEncoding","Token encoding",o(["HEX","BASE64"])),I("directEnvironment","Environment",o(["SANDBOX","PRODUCTION"]))]},COMMAND_RERUN:{fields:[h("commandRunId","Command run ID",{required:!0})]},COMMAND_TERMINATE:{fields:[h("commandRunId","Command run ID",{required:!0})]},COMMAND_READ_OUTPUT:{fields:[h("commandRunId","Command run ID",{required:!0}),p("first","Maximum chunks")]},WORKTREE_INSPECT_DIFF:{fields:[h("worktreeId","Worktree ID"),h("scope","Diff scope",{required:!0}),h("path","Path"),h("previousPath","Previous path"),h("commitSha","Commit SHA")]},WORKTREE_UPDATE_METADATA:{fields:[h("worktreeId","Worktree ID"),h("baseBranch","Base branch"),h("highlightColor","Highlight color")]},WORKTREE_MOVE_CONTROL:{fields:[h("moveId","Move ID",{required:!0}),I("operation","Operation",o(["RETRY_WITH_STASH","CANCEL"]))]},BUILD_REBUILD:{fields:[h("buildId","Build ID")]},BUILD_GENERATE_REPORT:{fields:[h("buildId","Build ID"),I("reportKind","Report kind",o(["TEST_RESULTS","CODE_COVERAGE"]))]},BUILD_DELETE:{fields:[w("buildIds","Build IDs")]},SKILL_PREPARE_SYNC:{fields:[I("syncKind","Sync kind",o(["ALL","GROUP"])),h("groupId","Skill group ID")]},SKILL_RESOLVE_SYNC:{fields:[h("runId","Sync run ID",{required:!0}),h("itemId","Conflict item ID",{required:!0}),I("resolution","Resolution",o(["LOCAL","REMOTE","SKIP"]))]},SKILL_SKIP_SYNC:{fields:[h("runId","Sync run ID",{required:!0})]},BUILD_DATA_REFRESH:{fields:[]},BUILD_DATA_DELETE:{fields:[h("collectionId","Collection ID",{required:!0}),w("entryIds","Entry IDs"),f("overrideProtection","Override protection")]},BUILD_DATA_SET_LOCK:{fields:[h("collectionId","Collection ID",{required:!0}),h("entryId","Entry ID",{required:!0}),f("locked","Locked")]},TAILSCALE_SERVE_INSPECT:{fields:[m("agentIds","Agents","agent")]},TAILSCALE_SERVE_UPSERT_TEMPLATE:{fields:[h("templateId","Template ID"),p("expectedRevision","Expected revision",{minimum:1,integer:!0}),h("name","Template name",{required:!0}),I("protocol","Listener protocol",o(["HTTP","HTTPS","TCP","TLS_TERMINATED_TCP"]),{required:!0,default:"HTTPS"}),p("listenPort","Incoming port",{required:!0,default:443,minimum:1,maximum:65535,integer:!0}),h("mountPath","Mount path",{default:"/"}),I("destinationProtocol","Destination protocol",o(["HTTP","HTTPS","HTTPS_INSECURE","TCP"]),{required:!0,default:"HTTP"}),p("destinationPort","Destination port",{required:!0,default:3e3,minimum:1,maximum:65535,integer:!0}),h("destinationPath","Destination path",{default:""}),f("funnel","Public Funnel"),w("appCapabilities","App capabilities"),I("proxyProtocol","PROXY protocol",o(["NONE","V1","V2"]),{required:!0,default:"NONE"}),m("agentIds","Enabled agents","agent",{required:!0})]},TAILSCALE_SERVE_SET_AGENT_ENABLED:{fields:[h("templateId","Template ID",{required:!0}),C("agentId","Agent","agent",{required:!0}),f("enabled","Enabled"),p("expectedRevision","Expected revision",{required:!0})]},TAILSCALE_SERVE_DELETE_TEMPLATE:{fields:[h("templateId","Template ID",{required:!0}),p("expectedRevision","Expected revision",{required:!0})]},SIGNING_REFRESH:{fields:[w("agentIds","Agent IDs")]},SIGNING_SYNC_PROFILE:{fields:[h("uuid","Profile UUID",{required:!0}),h("sourceAgentId","Source agent ID",{required:!0}),w("targetAgentIds","Target agent IDs")]},SIGNING_DELETE_EXPIRED:{fields:[w("agentIds","Agent IDs")]},IOS_DEVICE_REGISTER:{fields:[h("deviceId","Device ID",{required:!0})]},IOS_DEVICE_REJECT:{fields:[h("deviceId","Device ID",{required:!0})]},AGENT_RECONCILE:{fields:[w("agentIds","Agent IDs")]},AGENT_UPDATE_CADENCE:{fields:[h("agentId","Agent ID",{required:!0}),B("settings","Cadence settings")]},CCUSAGE_COLLECT:{fields:[]},MODEL_COST_REFRESH:{fields:[]},GITHUB_UPDATE_PR:{fields:[h("owner","Owner",{required:!0}),h("name","Repository",{required:!0}),p("number","Pull request number",{required:!0}),h("title","Title"),g("body","Body"),f("draft","Draft")]},GITHUB_SUBMIT_REVIEW:{fields:[h("owner","Owner",{required:!0}),h("name","Repository",{required:!0}),p("number","Pull request number",{required:!0}),I("event","Review event",o(["APPROVE","REQUEST_CHANGES","COMMENT"])),g("body","Body")]},GITHUB_REQUEST_REVIEWERS:{fields:[h("owner","Owner",{required:!0}),h("name","Repository",{required:!0}),p("number","Pull request number",{required:!0}),w("reviewers","Reviewers"),w("teamReviewers","Team reviewers")]},GITHUB_DISPATCH_WORKFLOW:{fields:[h("repositoryId","Repository ID",{required:!0}),h("workflowId","Workflow ID",{required:!0}),h("ref","Git ref",{required:!0}),y("inputs","Workflow inputs")]},JIRA_CREATE_TICKET:{fields:[h("projectKey","Project key",{required:!0}),h("issueTypeId","Issue type ID",{required:!0}),h("summary","Summary",{required:!0}),g("description","Description"),B("fields","Additional fields")]},JIRA_ADD_WORKLOG:{fields:[h("issueKey","Issue key"),p("timeSpentSeconds","Time spent (seconds)",{required:!0}),h("startedAt","Started at"),g("comment","Comment")]},JIRA_LINK_TICKETS:{fields:[h("inwardIssueKey","Inward issue key",{required:!0}),h("outwardIssueKey","Outward issue key",{required:!0}),h("linkType","Link type",{required:!0})]},MCP_CALL:{fields:[C("groupId","MCP server","mcpServer",{required:!0}),h("name","Tool name",{required:!0}),B("arguments","Arguments")]},SSE_ENDPOINT_ACTION:{fields:[I("operation","Operation",o(["CREATE","UPDATE","SET_MODE","ROTATE_TOKEN","DELETE"]),{required:!0}),h("endpointId","Endpoint ID"),B("input","Endpoint input")]},SSE_MOCK_ACTION:{fields:[I("operation","Operation",o(["SAVE_TEMPLATE","DELETE_TEMPLATE","SAVE_COMPOSITION","ACTIVATE_COMPOSITION","DELETE_COMPOSITION"]),{required:!0}),h("endpointId","Endpoint ID"),h("resourceId","Template or composition ID"),B("input","Mock input")]},SSE_STORAGE_ACTION:{fields:[I("operation","Operation",o(["SET","COMPARE_AND_SET","INCREMENT","DELETE"]),{required:!0}),h("key","Storage key",{required:!0}),B("value","JSON value"),p("expectedVersion","Expected version"),p("delta","Increment amount")]},SSE_BREAKPOINT_RESOLVE:{fields:[h("breakpointId","Breakpoint ID",{required:!0}),p("version","Version",{required:!0,integer:!0}),I("resolution","Resolution",o(["FORWARD","SAVED_MOCK","AD_HOC"]),{required:!0}),h("mockCompositionId","Mock composition ID"),B("adHocComposition","Ad hoc composition")]},SSE_HISTORY_CLEAR:{fields:[h("endpointId","Endpoint ID"),w("ids","Request IDs")]},SSE_SCRIPT_TEST:{fields:[g("source","JavaScript",{required:!0}),B("context","Script context"),p("timeoutMs","Timeout (ms)",{integer:!0}),p("memoryLimitMb","Memory limit (MiB)",{integer:!0}),p("fetchTimeoutMs","Fetch timeout (ms)",{integer:!0})]},RUN_CREATE_PLAN:{fields:k("PLAN")},RUN_CREATE_SESSION:{fields:k("SESSION")},RUN_PLAY_PLAN:{fields:[h("runId","Plan run ID"),E("SESSION"),p("worktreeConcurrencyLimit","Worktree concurrency limit",{default:1,minimum:0,maximum:32,integer:!0,help:"Maximum sessions admitted on this worktree. Use 0 for unlimited."})]},RUN_FOLLOW_UP:{fields:[h("runId","Source run ID"),...k(null),I("followUpMode","Follow-up mode",o(["RESUME","FRESH","RESEND"])),h("contextMode","Context mode")]},RUN_STEER:{fields:[h("runId","Run ID"),g("prompt","Steering prompt",{required:!0}),w("attachmentIds","Attachment IDs")]},RUN_ANSWER:{fields:[h("batchId","Question batch ID",{required:!0}),B("answers","Answers")]},RUN_PAUSE:{fields:[h("runId","Run ID")]},RUN_CONTINUE:{fields:[h("runId","Run ID")]},RUN_CANCEL:{fields:[h("runId","Run ID")]},RUN_REVISE_ANSWER:{fields:[h("batchId","Question batch ID",{required:!0}),B("answers","Answers"),f("stash","Stash before revision"),f("rollback","Roll back to the question")]},RUN_READ_RESULT:{fields:[h("runId","Run ID")]},RUN_CAPTURE_CHECKPOINT:{fields:[h("runId","Run ID")]},RUN_ARCHIVE_DELETE:{fields:[h("runId","Run ID"),f("delete","Delete permanently"),f("archived","Archive")]},HUMAN_CONFIRM:{fields:[g("prompt","Prompt")]},HUMAN_CHOICE:{fields:[g("prompt","Prompt"),f("multiSelect","Allow multiple selections"),f("allowCustom","Allow a custom answer"),((e,A,t={})=>({key:e,label:A,control:"choiceOptions",valueModes:c,...t}))("options","Buttons")]},CONTROL_IF:{fields:[((e,A,t={})=>({key:e,label:A,control:"condition",valueModes:c,...t}))("condition","Condition",{required:!0})]},CONTROL_JOIN:{fields:[I("mode","Join mode",s([{value:"ALL",label:"All — wait for every branch"},{value:"ANY",label:"Any — continue on the first branch"}]),{help:"All (default) waits until every incoming branch has finished before continuing. Any continues as soon as the first incoming branch arrives, and the remaining branches keep running on their own. Either way, branches that were skipped do not block the join, and the join itself is skipped when no branch reaches it."})]},CONTROL_DELAY:{fields:[p("seconds","Delay (seconds)",{required:!0})]},CONTROL_WAIT_UNTIL:{fields:[B("condition","Condition",{required:!0})]},CONTROL_FOR_EACH:{fields:[h("listPath","List session path",{placeholder:"pr.unresolvedThreads"}),B("items","Inline items"),I("errorMode","Error handling",s([{value:"FAIL_FAST",label:"Fail fast"},{value:"COLLECT_ERRORS",label:"Collect errors"}]))]},CONTROL_TRY:{fields:[]},CONTROL_SET_VARIABLE:{fields:[h("path","Output path",{required:!0,placeholder:"flags.ready"}),B("value","Value"),g("script","Script")]},CONTROL_SUBWORKFLOW:{fields:[h("versionId","Sub-workflow version ID",{required:!0}),B("inputMapping","Input mapping")]},SAVED_COMMAND:{fields:[C("commandId","Saved command ID","savedCommand",{required:!0}),I("completionMode","Completion",o(["WAIT_FOR_EXIT","FIRE_AND_FORGET"])),I("targetMode","Target",o(["CONTEXT","FIXED_AGENT","FIXED_WORKTREE"])),h("agentId","Fixed agent ID",{visibleWhen:{key:"targetMode",equals:"FIXED_AGENT"}}),h("worktreeId","Fixed worktree ID",{visibleWhen:{key:"targetMode",equals:"FIXED_WORKTREE"}}),h("outputPattern","Output match pattern (RE2)",{placeholder:"ready on port ([0-9]+)",help:"Optional case-sensitive regex. Requires Wait for exit and emits through the match connector while the command runs.",valueModes:["literal"]}),I("outputMatchMode","Output match behavior",o(["ONCE","EACH_MATCH"]),{default:"ONCE"})]},CUSTOM_COMMAND:{fields:[g("script","Script",{required:!0}),I("completionMode","Completion",o(["WAIT_FOR_EXIT","FIRE_AND_FORGET"])),I("targetMode","Target",o(["CONTEXT","FIXED_AGENT","FIXED_WORKTREE"])),h("agentId","Fixed agent ID",{visibleWhen:{key:"targetMode",equals:"FIXED_AGENT"}}),h("worktreeId","Fixed worktree ID",{visibleWhen:{key:"targetMode",equals:"FIXED_WORKTREE"}}),h("outputPattern","Output match pattern (RE2)",{placeholder:"ready on port ([0-9]+)",help:"Optional case-sensitive regex. Requires Wait for exit and emits through the match connector while the command runs.",valueModes:["literal"]}),I("outputMatchMode","Output match behavior",o(["ONCE","EACH_MATCH"]),{default:"ONCE"})]},TERMINAL_RUN:{fields:[g("script","Script",{required:!0}),I("interpreter","Interpreter",o(["SHELL","NODE"])),y("environment","Environment variables"),B("credentials","Credential environment",{help:"JSON array of { name, credential: { id, kind, ownerId } } entries."})]}},R=()=>p("timeoutSeconds","Timeout (seconds)",{help:"How long to keep waiting before the step fails. Leave empty to wait for as long as the work takes."});function T(e,A){for(let t of e){let e=v[t];if(!e)continue;let r=new Set(e.fields.map(({key:e})=>e));e.fields=[...e.fields,...A().filter(({key:e})=>!r.has(e))]}}function G(e=[]){return{fields:[...e,y("filters","Filters",{help:"Match when each session path equals the given value.",recordValueType:"json"})]}}T(["WORKTREE_CREATE","WORKTREE_CHANGE_BRANCH","WORKTREE_OPERATION","WORKTREE_PREPARATION","WORKTREE_SET_AUTO_SYNC","WORKTREE_DELETE","WORKTREE_GIT_OPERATION","WORKTREE_MOVE","WORKTREE_WAIT_PUSH_READY","WORKTREE_SNAPSHOT","CODEBASE_FETCH_REFRESH","CODEBASE_GIT_OPERATION","BUILD_START","BUILD_IMPORT_COVERAGE","BUILD_EXPORT","BUILD_DEPLOY","DISK_SPACE_REFRESH","TERMINAL_RUN","RUN_CREATE_PLAN","RUN_CREATE_SESSION","RUN_PLAY_PLAN","RUN_FOLLOW_UP","RUN_REVISE_ANSWER","SAVED_COMMAND","CUSTOM_COMMAND","COMMAND_RERUN","BUILD_REBUILD","BUILD_DATA_REFRESH","TAILSCALE_SERVE_INSPECT","TAILSCALE_SERVE_UPSERT_TEMPLATE","TAILSCALE_SERVE_SET_AGENT_ENABLED","TAILSCALE_SERVE_DELETE_TEMPLATE","SIGNING_REFRESH","SIGNING_SYNC_PROFILE","SIGNING_DELETE_EXPIRED","SKILL_APPLY","GITHUB_WAIT_CHECKS","GITLAB_WAIT_PIPELINE","CONTROL_SUBWORKFLOW","CONTROL_WAIT_UNTIL"],()=>[p("cadenceSeconds","Poll cadence (seconds)",{help:"How often to check whether the work has finished. Leave empty for this step's default."}),R()]),T(["HUMAN_CONFIRM","HUMAN_CHOICE"],()=>[R()]);let M=["BUILD_TEST_THRESHOLD","BUILD_COVERAGE_THRESHOLD","AGENT_DISK_THRESHOLD","CCUSAGE_THRESHOLD","RUN_USAGE_THRESHOLD","BUILD_DATA_THRESHOLD","AGENT_RESOURCE_THRESHOLD","SIGNING_ASSET_EXPIRING"],N=Object.fromEntries(["MANUAL","MANUAL_CHOICE","RESOURCE_MANUAL","RESOURCE_MANUAL_CHOICE","SCHEDULE","WORKFLOW_FINISHED","GITHUB_PR_STATE","GITHUB_REVIEW_CHANGES_REQUESTED","GITHUB_REVIEW_COMMENT","GITHUB_PR_CLOSED","GITHUB_CHECK_FAILED","GITHUB_PUSH_DEFAULT","GITHUB_WORKFLOW_SUCCEEDED","GITHUB_ISSUE_COMMAND","GITHUB_ACTIONS_RESULT","GITHUB_PR_LABEL","GITLAB_MR_STATE","GITLAB_REVIEW_CHANGES_REQUESTED","GITLAB_REVIEW_COMMENT","GITLAB_MR_CLOSED","GITLAB_PIPELINE_FAILED","GITLAB_PUSH_DEFAULT","GITLAB_PIPELINE_SUCCEEDED","GITLAB_NOTE_COMMAND","GITLAB_PIPELINE_RESULT","GITLAB_MR_LABEL","BUILD_RESULT","BUILD_TEST_THRESHOLD","BUILD_COVERAGE_THRESHOLD","BUILD_HOOK_FAILED","AGENT_CONNECTION","AGENT_JOB_FAILED","AGENT_DISK_REPORT","AGENT_DISK_THRESHOLD","AGENT_DISK_STATE_CHANGED","AGENT_DISK_CLEANUP_RESULT","CCUSAGE_THRESHOLD","WORKTREE_CREATED","WORKTREE_BEHIND","WORKTREE_CONFLICT","WORKTREE_MISSING","WORKTREE_DIVERGED","WORKTREE_DIRTY_DURATION","WORKTREE_NEW_COMMIT","CODEBASE_REMOTE_BRANCH","JIRA_STATUS","JIRA_LABEL","JIRA_ASSIGNED_SELF","JIRA_SOURCE_NEW_TICKET","JIRA_MENTION","JIRA_SPRINT_STARTED","JIRA_ISSUE_CREATED","JIRA_ISSUE_DELETED","JIRA_ISSUE_COMMAND","JIRA_ATTACHMENT_ADDED","JIRA_ISSUE_LINKED","RUN_STARTED","RUN_COMPLETED","RUN_QUESTION_NEEDED","RUN_QUESTION_ANSWERED","RUN_PAUSED","RUN_CONTINUED","RUN_FAILED","RUN_CANCELLED","RUN_PLAN_PLAYED","RUN_FOLLOW_UP","RUN_IMPORTED","RUN_USAGE_THRESHOLD","RUN_EVENT_MATCH","COMMAND_RUN_RESULT","COMMAND_OUTPUT_MATCH","SKILL_SYNC_RESULT","SKILL_SYNC_CONFLICT","GITHUB_PIPELINE_STATUS_CHANGED","GITHUB_PR_SYNCHRONIZED","GITHUB_REVIEW_APPROVED","GITLAB_PIPELINE_STATUS_CHANGED","GITLAB_MR_SYNCHRONIZED","GITLAB_REVIEW_APPROVED","GITLAB_JOB_STATUS_CHANGED","JIRA_TICKET_UPDATED","JIRA_COMMENT_ADDED","JIRA_WORKLOG_ADDED","JIRA_SPRINT_ENDED","CODEBASE_SYNC_STATE_CHANGED","CODEBASE_OPERATION_FAILED","WORKTREE_SYNC_STATE_CHANGED","WORKTREE_AUTOMATION_RESULT","WORKTREE_CLEAN","PUSH_NOTIFICATION_RESULT","IOS_DEVICE_ENROLLED","IOS_DEVICE_REGISTRATION_RESULT","SIGNING_OPERATION_RESULT","SIGNING_ASSET_EXPIRING","BUILD_DATA_THRESHOLD","BUILD_DATA_CLEANUP_RESULT","POLLING_OPERATION_STATE","MODEL_COST_CATALOG_CHANGED","CREDENTIAL_STORE_DEGRADED","AGENT_RESOURCE_THRESHOLD","AGENT_VERSION_CHANGED","TOOL_CALL_RESULT","SSE_REQUEST_OPENED","SSE_EVENT_EMITTED","SSE_BREAKPOINT_WAITING","SSE_BREAKPOINT_RESOLVED","SSE_STREAM_COMPLETED","SSE_STREAM_FAILED"].map(e=>{if("RESOURCE_MANUAL"===e||"RESOURCE_MANUAL_CHOICE"===e)return[e,G([I("resourceKind","Resource kind",o(n.WORKFLOW_RESOURCE_KINDS),{required:!0}),..."RESOURCE_MANUAL_CHOICE"===e?[Q("choices","Choices",{required:!0})]:[]])];if("MANUAL_CHOICE"===e)return[e,G([Q("choices","Choices",{required:!0})])];if("SCHEDULE"===e)return[e,G([p("cadenceSeconds","Cadence (seconds)",{required:!0})])];if("GITHUB_ISSUE_COMMAND"===e||"GITLAB_NOTE_COMMAND"===e){let A="GITLAB_NOTE_COMMAND"===e;return[e,G([w(A?"allowedUsernames":"allowedLogins",A?"Allowed usernames":"Allowed logins",{placeholder:"octocat",required:!0}),h("commandPattern","Command pattern (RE2)",{placeholder:"^/deploy\\b$",required:!0,valueModes:["literal","interpolation"]})])]}return"JIRA_ISSUE_COMMAND"===e?[e,G([w("allowedAccountIds","Allowed account IDs",{placeholder:"5b10a2844c20165700ede21g",required:!0}),h("commandPattern","Command pattern (RE2)",{placeholder:"^/deploy\\b$",required:!0,valueModes:["literal","interpolation"]})])]:"COMMAND_OUTPUT_MATCH"===e?[e,G([h("outputPattern","Output pattern (RE2)",{placeholder:"error|failed",required:!0,valueModes:["literal","interpolation"]})])]:M.includes(e)?[e,G([h("thresholdPath","Threshold path",{placeholder:"build.testSummary.failed"}),I("thresholdOperator","Operator",D),B("thresholdValue","Threshold value")])]:[e,G()]}));function O(e,A){return"step"===A?v[e]:N[e]}function H(e,A,t){let r=function(e,A){let t=O(e,A);if(!t)return null;let r=new Set,i=new Set;for(let e of t.fields){for(let A of"model"===e.control&&e.modelKeys?[e.modelKeys.provider,e.modelKeys.model,e.modelKeys.effort]:[e.key])r.add(A);e.required&&i.add(e.key)}return{described:r,required:i}}(e,A);if(!r||!t||"object"!=typeof t||Array.isArray(t))return(0,a.workflowValueSessionPaths)(t);let i=new Set;for(let[e,A]of Object.entries(t))(!r.described.has(e)||r.required.has(e))&&(0,a.workflowValueSessionPaths)(A,i);return i}e.s(["getConfigDescriptor",0,O,"requiredConfigSessionPaths",0,H],222335);let U=["EQ","NE","GT","GTE","LT","LTE","CONTAINS","MATCHES","EXISTS"],_={type:"object",title:"Session binding",description:"Reads the value from run session data at `path` instead of hard-coding it.",properties:{source:{const:"SESSION"},path:{type:"string",description:"Dotted session path, e.g. `ticket.key` or `pr.number`."}},required:["source","path"],additionalProperties:!1},x={type:"object",title:"Literal wrapper",description:"An explicit constant. Equivalent to writing the value directly; the editor uses it to record that a field was pinned rather than bound.",properties:{source:{const:"LITERAL"},value:{}},required:["source"],additionalProperties:!1};function L(e,A,t){let r=t.valueModes??[],i=[r.includes("session")?"May also be a session binding.":null,r.includes("interpolation")?"Strings here — including strings nested inside the value — may carry `{{path}}` interpolation tokens, e.g. `{{worktree.baseBranch}}`.":null].filter(Boolean),n=i.length?{...A,description:[A.description,...i].filter(Boolean).join(" ")}:A;return r.includes("session")?{anyOf:[e,_,x],...n}:{...e,...n}}function P(e){let A=e.options?function(e){if("static"===e.kind){let A=e.options.filter(({label:e})=>e);return A.length?A.map(({value:e,label:A})=>`\`${e}\` — ${A}`).join("; "):null}let A=e.scopeFrom?` Scoped by the sibling \`${e.scopeFrom}\` value.`:"",t=e.sessionPath?` Usually bound to \`${e.sessionPath}\`.`:"";return`Identifier of a ${e.resource} known to the control plane.${t}${A}`}(e.options):null,t={description:[e.label,e.help,A].filter(Boolean).join(" — ")};return e.placeholder&&(t.examples=[e.placeholder]),void 0!==e.default&&(t.default=e.default),L(function(e){switch(e.control){case"number":return{type:e.integer?"integer":"number",...void 0===e.minimum?{}:{minimum:e.minimum},...void 0===e.maximum?{}:{maximum:e.maximum}};case"boolean":return{type:"boolean"};case"enum":{let A=e.options;if(A?.kind==="static")return{type:"string",enum:A.options.map(({value:e})=>e)};return{type:"string"}}case"resource":case"model":case"text":default:return{type:"string"};case"resourceMulti":case"stringList":case"mcpPresetMulti":return{type:"array",items:{type:"string"}};case"record":return{type:"object",additionalProperties:"json"===e.recordValueType?{}:{type:"string"}};case"condition":return{$ref:"#/$defs/condition"};case"choiceOptions":return{type:"array",description:"Buttons offered to the person answering.",items:{type:"object",properties:{label:{type:"string"},description:{type:"string"}},required:["label"],additionalProperties:!1}};case"triggerChoices":return{type:"array",minItems:1,description:"Options this trigger offers. Each `key` names an outgoing handle on the trigger, so edges stay attached when a label is renamed.",items:{type:"object",properties:{key:{type:"string",pattern:n.WORKFLOW_CHOICE_KEY_PATTERN.source},label:{type:"string"},description:{type:"string"}},required:["key","label"],additionalProperties:!1}};case"json":return{}}}(e),t,e)}function K(e,A){let t=O(e,A);if(!t)return{type:"object",additionalProperties:!0};let r={},i=[],n=!1;for(let e of t.fields){for(let[A,t]of("condition"===e.control&&(n=!0),"model"===e.control?function(e){let A=e.modelKeys;if(!A)return[[e.key,P(e)]];let t=(A,t)=>[A,L({type:"string"},{description:t},e)];return[t(A.provider,"AI provider that serves the model."),t(A.model,"Model identifier, as listed by the provider catalog."),t(A.effort,"Reasoning effort, when the model supports it.")]}(e):[[e.key,P(e)]]))r[A]=t;e.required&&i.push(e.key)}let a={type:"object",properties:r,additionalProperties:!0};return i.length&&(a.required=i),n&&(a.$defs={condition:{type:"object",description:"A condition tree. `ALL`/`ANY` combine nested conditions, `NOT` negates one, and the comparison operators test `left` against `right`.",anyOf:[{properties:{op:{enum:["ALL","ANY"]},conditions:{type:"array",items:{$ref:"#/$defs/condition"}}},required:["op","conditions"]},{properties:{op:{const:"NOT"},condition:{$ref:"#/$defs/condition"}},required:["op","condition"]},{properties:{op:{enum:[...U]},left:{description:"Value to test — usually a session binding. `EXISTS` needs only this side."},right:{description:"Value to compare against."}},required:["op","left"]}]}}),a}function q(e){let A=e?.outputPattern;return"string"==typeof A&&A.length?A:null}function J(e){if(!e.length)throw Error("Output pattern cannot be empty");if(e.length>1024)throw Error("Output pattern must not exceed 1024 characters")}e.s(["COMMAND_OUTPUT_MATCH_BUFFER_BYTES",0,0x1000000,"commandOutputMatchMode",0,function(e){return e?.outputMatchMode==="EACH_MATCH"?"EACH_MATCH":"ONCE"},"commandOutputPattern",0,q,"validateCommandOutputPattern",0,J],69988);let F="aide.workflow";function j(e){let A=e?.choices;if(!Array.isArray(A))return[];let t=[],r=new Set;for(let e of A)!(!e||"object"!=typeof e||Array.isArray(e))&&(!(0,n.isWorkflowChoiceKey)(e.key)||r.has(e.key)||(r.add(e.key),t.push({key:e.key,label:"string"==typeof e.label&&e.label.trim()?e.label:e.key,description:"string"==typeof e.description?e.description:""})));return t}let z={BUILD:["build.*","worktree.*","codebase.*","agent.*","repo.*","ticket.*"],CODEBASE:["codebase.*","agent.*","repo.*"],JIRA_TICKET:["ticket.*","comment.*"],AGENT_RUN:["run.*","worktree.*","codebase.*","agent.*","repo.*","ticket.*"],GITHUB_PIPELINE:["pipeline.*","repo.*","pr.*","worktree.*","codebase.*","agent.*","ticket.*"],GITHUB_JOB:["job.*","pipeline.*","repo.*","pr.*","worktree.*","codebase.*","agent.*","ticket.*"],GITLAB_MERGE_REQUEST:["pr.*","repo.*","worktree.*","ticket.*"],GITLAB_PIPELINE:["pipeline.*","repo.*","pr.*","worktree.*","ticket.*"],GITLAB_JOB:["job.*","pipeline.*","repo.*","pr.*","worktree.*","ticket.*"],PULL_REQUEST:["pr.number","repo.displayOrigin"],WORKTREE:["worktree.*","codebase.*","agent.*","repo.*","ticket.*","pr.*"],COMMAND_RUN:["command.*","agent.*","worktree.*","codebase.*","repo.*"],SKILL:["skill.*","repo.*","codebase.*"],SKILL_SYNC:["skillSync.*","skill.*","repo.*","codebase.*","worktree.*"],IOS_DEVICE:["device.*"],SIGNING_PROFILE:["signingProfile.*","device.*","agent.*"],PUSH_NOTIFICATION_BATCH:["pushBatch.*"],BUILD_DATA_COLLECTION:["buildData.*","agent.*","worktree.*","codebase.*"]};function Y(e){let A=e?.resourceKind;return"string"==typeof A&&n.WORKFLOW_RESOURCE_KINDS.includes(A)?A:null}function V(e,A){if(!(0,n.isResourceTriggerKind)(e))return[];let t=Y(A);return t?z[t]:[]}let Z=(e,A,t,r,i,a,o)=>({kind:e,category:A,label:t,description:o.description,details:o.details,execution:r,configSchema:K(e,"step"),capabilityFlags:[r,...o.mutatesExternal?["MUTATES_EXTERNAL"]:[],...o.mutatesWorktree?["MUTATES_WORKTREE"]:[]],requiredPaths:i,providedPaths:a,sourceHandles:(0,n.workflowStaticSourceHandles)(e),mutatesExternal:o.mutatesExternal??!1,mutatesWorktree:o.mutatesWorktree??!1}),W=["worktree.*","codebase.*","agent.*","repo.*","ticket.*","pr.*"],$=["codebase.*","agent.*","repo.*"],X=(e,A,t,r=[],i=["steps.<stepId>.*"],n={})=>Z(e,A,t,"SERVER",r,i,{description:`${t} using the control plane's typed service API.`,details:`${t} is a first-class action with validated configuration, audit-friendly output, resource links where available, and normal workflow failure routing.`,...n}),ee=[X("COMMAND_RERUN","Commands","Rerun command",["command.id"],["command.*"]),X("COMMAND_TERMINATE","Commands","Terminate command",["command.id"],["command.*"]),X("COMMAND_READ_OUTPUT","Commands","Read command output",["command.id"],["command.*"]),X("WORKTREE_INSPECT_DIFF","Worktrees","Inspect worktree diff",["worktree.id"],["worktree.diff.*"]),X("WORKTREE_UPDATE_METADATA","Worktrees","Update worktree metadata",["worktree.id"],W),X("WORKTREE_MOVE_CONTROL","Worktrees","Control worktree move",[],W,{mutatesWorktree:!0}),X("BUILD_REBUILD","Builds","Rebuild build",["build.id"],["build.*"]),X("BUILD_GENERATE_REPORT","Builds","Generate build report",["build.id"],["build.*"]),X("BUILD_DELETE","Builds","Delete builds",[],["build.*"]),X("SKILL_PREPARE_SYNC","Skills","Prepare skill sync",[],["skillSync.*"]),X("SKILL_RESOLVE_SYNC","Skills","Resolve skill sync conflict",["skillSync.id"],["skillSync.*"]),X("SKILL_SKIP_SYNC","Skills","Skip skill sync",["skillSync.id"],["skillSync.*"]),X("BUILD_DATA_REFRESH","Build Data","Refresh build data",[],["buildData.*"]),X("BUILD_DATA_DELETE","Build Data","Delete build data",["buildData.id"],["buildData.*"]),X("BUILD_DATA_SET_LOCK","Build Data","Set build-data lock",["buildData.id"],["buildData.*"]),X("TAILSCALE_SERVE_INSPECT","Tailscale","Inspect Tailscale Serve",[],["tailscale.*"],{mutatesExternal:!0}),X("TAILSCALE_SERVE_UPSERT_TEMPLATE","Tailscale","Upsert Tailscale Serve template",[],["tailscale.*"],{mutatesExternal:!0}),X("TAILSCALE_SERVE_SET_AGENT_ENABLED","Tailscale","Set Tailscale Serve agent enabled",["tailscale.templateId"],["tailscale.*"],{mutatesExternal:!0}),X("TAILSCALE_SERVE_DELETE_TEMPLATE","Tailscale","Delete Tailscale Serve template",["tailscale.templateId"],["tailscale.*"],{mutatesExternal:!0}),X("SIGNING_REFRESH","Signing","Refresh signing assets",[],["signing.*"]),X("SIGNING_SYNC_PROFILE","Signing","Sync signing profile",["signingProfile.id"],["signing.*"]),X("SIGNING_DELETE_EXPIRED","Signing","Delete expired profiles",[],["signing.*"]),X("IOS_DEVICE_REGISTER","Devices","Register iOS device",["device.id"],["device.*"],{mutatesExternal:!0}),X("IOS_DEVICE_REJECT","Devices","Reject iOS device",["device.id"],["device.*"],{mutatesExternal:!0}),X("AGENT_RECONCILE","Agents","Reconcile agents",[],["agent.*"]),X("AGENT_UPDATE_CADENCE","Agents","Update agent cadence",["agent.id"],["agent.*"]),X("CCUSAGE_COLLECT","Operations","Collect usage",[],["usage.*"]),X("MODEL_COST_REFRESH","Operations","Refresh model costs",[],["modelCosts.*"],{mutatesExternal:!0}),X("GITHUB_UPDATE_PR","GitHub","Update pull request",["pr.number","repo.*"],["pr.*"],{mutatesExternal:!0}),X("GITHUB_SUBMIT_REVIEW","GitHub","Submit pull request review",["pr.number","repo.*"],["pr.*"],{mutatesExternal:!0}),X("GITHUB_REQUEST_REVIEWERS","GitHub","Request pull request reviewers",["pr.number","repo.*"],["pr.*"],{mutatesExternal:!0}),X("GITHUB_DISPATCH_WORKFLOW","GitHub","Dispatch GitHub workflow",["repo.*"],["pipeline.*"],{mutatesExternal:!0}),...[["GITLAB_LOAD_MR","Load merge request",!1],["GITLAB_CREATE_MR","Create merge request",!0],["GITLAB_UPDATE_MR","Update merge request",!0],["GITLAB_SUBMIT_REVIEW","Submit merge request review",!0],["GITLAB_REPLY_DISCUSSION","Reply to discussion",!0],["GITLAB_SET_DISCUSSION_RESOLVED","Resolve discussion",!0],["GITLAB_MERGE_MR","Merge merge request",!0],["GITLAB_SET_MR_LABELS","Set merge request labels",!0],["GITLAB_REQUEST_REVIEWERS","Request merge request reviewers",!0],["GITLAB_CREATE_PIPELINE","Create pipeline",!0],["GITLAB_RETRY_PIPELINE","Retry pipeline",!0],["GITLAB_RETRY_JOB","Retry job",!0],["GITLAB_CANCEL_PIPELINE","Cancel pipeline",!0]].map(([e,A,t])=>X(e,"GitLab",String(A),[],String(e).includes("PIPELINE")||String(e).includes("JOB")?["pipeline.*","job.*"]:["pr.*"],{mutatesExternal:!!t})),X("GITLAB_SAVE_AUTO_RETRY","GitLab Pipelines","Install auto-retry rule",["pipeline.id"],[],{mutatesExternal:!0}),X("GITLAB_WAIT_PIPELINE","GitLab Pipelines","Wait for pipeline",["pipeline.id"],["pipeline.*"]),X("JIRA_CREATE_TICKET","Jira","Create Jira ticket",[],["ticket.*"],{mutatesExternal:!0}),X("JIRA_ADD_WORKLOG","Jira","Add Jira worklog",["ticket.key"],["ticket.*"],{mutatesExternal:!0}),X("JIRA_LINK_TICKETS","Jira","Link Jira tickets",["ticket.key"],["ticket.*"],{mutatesExternal:!0})],eA=[Z("JIRA_LOAD_TICKET","Jira","Load Jira ticket","SERVER",[],["ticket.*"],{description:"Reads a Jira issue and puts its fields — key, title, type, status, assignee, labels — into session data as `ticket.*`.",details:'Needs a configured Jira credential. Leave the identifier unset to take it from session data. Results are served from cache unless "Bypass cache" is set, so a step that reads a ticket right after changing it should force a refresh. Fails when the issue does not exist or the credential cannot see it. Read-only: it changes nothing in Jira.'}),Z("JIRA_TRANSITION","Jira","Transition Jira ticket","SERVER",["ticket.key"],["ticket.*"],{description:"Moves a ticket to another status by applying one of its workflow transitions.",details:"Takes a transition id, not a status name — the ids are board-specific, so read them from the ticket's available transitions rather than hard-coding a guess. Fails when the transition is not currently available on that issue, which is what happens if an earlier step already moved it. Refreshes `ticket.*` from the response.",mutatesExternal:!0}),Z("JIRA_COMMENT","Jira","Add Jira comment","SERVER",["ticket.key"],["ticket.*"],{description:"Posts a comment on a Jira issue, written in Markdown or Jira wiki markup.",details:"The comment body is converted from Markdown by default; choose Jira wiki format to pass markup through untouched. Comments are never deduplicated, so a step that runs twice comments twice — guard it with a condition if the workflow can retry. Refreshes `ticket.*` from the response.",mutatesExternal:!0}),Z("JIRA_ASSIGN","Jira","Assign Jira ticket","SERVER",["ticket.key"],["ticket.*"],{description:"Sets the assignee of a Jira issue, or clears it when no account is given.",details:"Takes a Jira account id rather than a display name or email. Leaving the assignee empty unassigns the ticket. Fails when the account cannot be assigned on that project. Refreshes `ticket.*` from the response.",mutatesExternal:!0}),Z("JIRA_UPDATE_FIELDS","Jira","Update Jira fields","SERVER",["ticket.key"],["ticket.*"],{description:"Patches arbitrary fields on a Jira issue — labels, summary, custom fields — from a JSON object.",details:"The escape hatch for anything the dedicated Jira steps do not cover. Keys are passed to the Jira update API as given, so an unknown or screen-hidden field fails the step. Prefer the specific steps for status and assignee. Refreshes `ticket.*` from the response.",mutatesExternal:!0}),Z("JIRA_RESOLVE_BRANCH","Jira","Resolve ticket branch","SERVER",["ticket.key","ticket.title","ticket.type"],["worktree.branch","ticket.key","ticket.title","ticket.type"],{description:"Works out the branch name a ticket would get under the codebase's naming convention, without creating anything.",details:"A preview step: it writes `worktree.branch` plus the ticket key, title, and type into session data and touches neither Git nor Jira. Use it before Create worktree when you want the branch name available to earlier steps — for a worktree keyed off a ticket, Create worktree in TICKET mode derives the same name on its own."}),Z("GITHUB_LOAD_PR","GitHub","Load pull request","SERVER",[],["pr.*"],{description:"Reads a pull request and puts its state, branches, labels, checks, and review threads into session data as `pr.*`.",details:"Needs a configured GitHub credential. Owner and repository default to the repository already in session data, and the number to `pr.number`. Fails when the pull request does not exist or the credential cannot see it. Read-only."}),Z("GITHUB_MERGE_PR","GitHub","Merge pull request","SERVER",["pr.number"],["pr.state"],{description:"Merges an open pull request using squash, merge, or rebase, optionally overriding the commit message.",details:"Checks mergeability first and fails with GitHub's own blocking reason — conflicts, failing required checks, missing approvals, an already-closed pull request — rather than forcing the merge. Commit headline and body default to what GitHub would use. Squash is the default method. Irreversible, and repository policy may delete the head branch as a side effect, which strands any worktree still on it. Writes `pr.state`.",mutatesExternal:!0}),Z("GITHUB_COLLECT_REVIEW_THREADS","GitHub","Collect review comments","SERVER",["pr.number"],["pr.unresolvedThreads"],{description:"Gathers the unresolved review threads on a pull request into `pr.unresolvedThreads`.",details:"Resolved threads are filtered out. The result is a list, so it pairs with For each to work through the comments one at a time — the reply and resolve steps take a single thread id from the iteration. Read-only."}),Z("GITHUB_REPLY_REVIEW_THREAD","GitHub","Reply to review thread","SERVER",["pr.unresolvedThreads"],[],{description:"Posts a reply into an existing pull request review thread.",details:"Takes the thread id from Collect review comments, usually inside a For each. Replies are not deduplicated, so a retried step comments twice. Replying does not resolve the thread — follow with Resolve review thread when that is the intent.",mutatesExternal:!0}),Z("GITHUB_SET_REVIEW_THREAD_RESOLVED","GitHub","Resolve review thread","SERVER",["pr.unresolvedThreads"],[],{description:"Marks a pull request review thread resolved, or reopens it.",details:"Takes the thread id from Collect review comments. Resolving is the default; clear the flag to unresolve. Reviewers see this as the bot resolving their comment, so it is usually paired with a reply that explains what changed.",mutatesExternal:!0}),Z("GITHUB_CREATE_PR","GitHub","Open pull request","SERVER",["worktree.branch","worktree.baseBranch"],["pr.*"],{description:"Opens a pull request from the worktree's branch, optionally as a draft.",details:"Head branch defaults to `worktree.branch`, base to `worktree.baseBranch`, and the title to `ticket.title`. The head branch must already be pushed — put Wait for push-ready or a push operation in front of this step. Fails when a pull request is already open for the same branch pair. Writes the new pull request to `pr.*`.",mutatesExternal:!0}),Z("GITHUB_SET_PR_LABELS","GitHub","Set pull request labels","SERVER",["pr.number"],["pr.labels"],{description:"Replaces the labels on a pull request with the given list.",details:"This sets rather than adds — labels not in the list are removed, so include the ones you want to keep. Labels must already exist in the repository. Writes `pr.labels`.",mutatesExternal:!0}),Z("GITHUB_RETRY_PIPELINE","GitHub Actions","Retry failed pipeline","SERVER",["pipeline.runId"],["pipeline.status"],{description:"Re-runs the failed jobs of a check suite, leaving the jobs that passed alone.",details:"Targets a check suite rather than a single job — use Retry workflow job for that. Re-running consumes Actions minutes and re-executes whatever those jobs do, including deployments. Pair it with a Time delay and a retry limit so a permanently broken pipeline is not retried forever. Writes `pipeline.status`.",mutatesExternal:!0}),Z("GITHUB_RETRY_JOB","GitHub Actions","Retry workflow job","SERVER",["pipeline.failedJobs"],[],{description:"Re-runs one job of a GitHub Actions workflow run.",details:"Needs the repository, check suite, and job ids together — typically read out of `pipeline.failedJobs` inside a For each. Use Retry failed pipeline to re-run every failed job at once instead.",mutatesExternal:!0}),Z("GITHUB_CANCEL_WORKFLOW_RUN","GitHub Actions","Cancel workflow run","SERVER",["pipeline.runId"],["pipeline.status"],{description:"Cancels an in-progress GitHub Actions workflow run.",details:"Falls back to `repo.id` and `pipeline.runId` from session data. Force-cancel skips the graceful shutdown that lets `always()` cleanup jobs finish, so leave it off unless a run is stuck. Cancelling a run that has already finished is an error. Writes `pipeline.status`.",mutatesExternal:!0}),Z("GITHUB_SAVE_AUTO_RETRY","GitHub Actions","Install auto-retry rule","SERVER",["pipeline.runId"],[],{description:"Saves a standing rule that automatically retries matching GitHub Actions failures.",details:"Persists configuration rather than acting once — the rule keeps applying after this run ends, and stays until something removes it. Takes the rule as a JSON object. Treat it as a settings change, not a step you re-run casually.",mutatesExternal:!0}),Z("GITHUB_WAIT_CHECKS","GitHub Actions","Wait for checks","WAIT",["pipeline.runId"],["pipeline.status","pipeline.conclusion","pipeline.jobs"],{description:"Parks the run until a GitHub Actions workflow run finishes, then continues on its conclusion.",details:"Polls until the run reaches a terminal status. Anything other than success fails the step, so route the failure handle to the recovery path — or set the step's failure policy to continue and branch on `pipeline.conclusion` yourself. Also refreshes `pipeline.jobs`. Without a timeout the wait is open-ended; a hung pipeline holds the workflow run indefinitely. Falls back to `repo.id` and `pipeline.runId`."}),Z("WORKTREE_CREATE","Worktrees","Create worktree","SERVER",["codebase.id"],W,{description:"Creates a Git worktree on the agent for a new, existing, or ticket-derived branch.",details:"Dispatches a job to the agent that owns the codebase and waits for it, so the agent must be online. Branch mode NEW cuts a branch from the base, EXISTING checks one out, and TICKET derives the name from `ticket.key`. Base branch falls back to `worktree.baseBranch` then `repo.defaultBranch`. Refreshes the created worktree, codebase, owning agent, repository, and any linked ticket. Creates real directories on disk.",mutatesWorktree:!0}),Z("WORKTREE_CHANGE_BRANCH","Worktrees","Change worktree branch","SERVER",["worktree.id"],W,{description:"Switches an existing worktree to a different branch, creating it if needed.",details:'Same branch modes as Create worktree. Uncommitted changes block the switch unless "Stash on failure" is set, which stashes them and retries — the stash is left for a human to deal with. Refreshes the worktree and all of its related resource context.',mutatesWorktree:!0}),Z("WORKTREE_COMMIT","Worktrees","Commit worktree changes","SERVER",["worktree.id"],W,{description:"Stages selected worktree changes and creates a Git commit on the agent.",details:"Stage all defaults on. Disable it and provide an exact list of changed paths for a partial commit; paths omitted from that list are left uncommitted. Signed commits follow effective Git configuration when the signed option is omitted. Dispatches an agent job, waits for completion, and refreshes worktree context.",mutatesWorktree:!0}),Z("WORKTREE_REFRESH_PULL_REQUEST","Worktrees","Refresh pull request","SERVER",["worktree.id"],["pr.*"],{description:"Forces exact-branch pull request discovery and refreshes the worktree's persisted pull request context.",details:"Uses the configured worktree, falling back to `worktree.id`. The step succeeds with `found: false` and clears `pr` when the branch has no open pull request.",mutatesWorktree:!0,mutatesExternal:!1}),Z("WORKTREE_OPERATION","Worktrees","Run worktree operation","SERVER",["worktree.id"],W,{description:"Runs one of the built-in worktree maintenance operations, such as syncing with the base branch or pushing.",details:"Dispatches an agent job and waits for it. Opening an editor is rejected here — it needs a human at the machine. Sync and push touch the remote and can conflict; check `worktree.pushStatus` afterwards or follow with Inspect worktree Git state.",mutatesWorktree:!0}),Z("WORKTREE_PREPARATION","Worktrees","Run worktree preparations","SERVER",["worktree.id"],[],{description:"Inspects, applies, or undoes the repository preparation rules for one worktree.",details:"Dispatches a preparation job to the owning agent and waits for its per-file result. Apply and Undo can overwrite managed paths, while Inspect only refreshes persisted status. Unsupported, offline, and unavailable worktrees fail with the service's explicit skip reason.",mutatesWorktree:!0}),Z("WORKTREE_SET_AUTO_SYNC","Worktrees","Set worktree Auto Sync","SERVER",["worktree.id"],["worktree.autoSync"],{description:"Enables, updates, retries, or cancels persistent Auto Sync for a worktree.",details:"An enabled rule rebases on the target branch whenever it changes and force-pushes with lease. A merge-conflict quick-action workflow can be selected as the automatic recovery path; unresolved conflicts pause the rule. Force is accepted only when preparations paused Auto Sync, destructively resets managed paths, and resumes the rule after a successful sync.",mutatesWorktree:!0,mutatesExternal:!0}),Z("WORKTREE_SET_AUTO_MERGE","Worktrees","Set worktree Auto Merge","SERVER",["worktree.id"],["worktree.autoMerge"],{description:"Enables, updates, retries, or cancels GitHub-native Auto Merge for a worktree.",details:"GitHub remains the authority for required checks and reviews. Optional post-merge actions can move the linked Jira ticket to its configured done status and safely delete a clean linked worktree.",mutatesWorktree:!0,mutatesExternal:!0}),Z("WORKTREE_DELETE","Worktrees","Delete worktree","SERVER",["worktree.id"],$,{description:"Removes a worktree from the agent, optionally deleting its remote branch too.",details:"Destroys the directory and any uncommitted work in it — there is no undo. Deleting the remote branch as well affects everyone, and closes any pull request from that branch. Do not put this before steps that still read `worktree.*`.",mutatesWorktree:!0}),Z("WORKTREE_MOVE","Worktrees","Move worktree","SERVER",["worktree.id"],W,{description:"Moves a worktree's branch and changes into another codebase, optionally deleting the source.",details:"Waits for the move job to finish. Used when a branch was started against the wrong checkout. Deleting the source destroys the original directory; leaving it keeps both, which means two worktrees on one branch. Refreshes `worktree.*` to point at wherever the work now lives.",mutatesWorktree:!0}),Z("WORKTREE_INSPECT","Worktrees","Inspect worktree","SERVER",["worktree.id"],["worktree.commits","worktree.changes","worktree.branchChanges","worktree.commitsTruncated","worktree.changesTruncated","worktree.branchChangesTruncated"],{description:"Reads the worktree's commits and changed files into `worktree.commits` and `worktree.changes`.",details:"Read-only. Use it to give a later condition or AI prompt something concrete to work from — for example to skip opening a pull request when nothing changed. For push/dirty state use Inspect worktree Git state instead, which is cheaper."}),Z("WORKTREE_INSPECT_GIT","Worktrees","Inspect worktree Git state","SERVER",["worktree.id"],["worktree.*"],{description:"Reads the worktree's Git status — dirty flag, ahead/behind counts, push status, conflicts — into `worktree.*`.",details:"Read-only and the cheap way to branch on repository state: gate a commit on `worktree.dirty`, or a sync on the worktree being behind. Use Inspect worktree when you need the actual commits and diffs."}),Z("WORKTREE_GIT_OPERATION","Worktrees","Run worktree Git operation","SERVER",["worktree.id"],W,{description:"Runs a specific Git operation in the worktree — pull, push, rebase, stash, and the rest.",details:'Dispatches an agent job and waits for it. Operations that rewrite history or touch the remote can fail on conflicts; "Stash changes first" clears the way for operations that need a clean tree. Prefer Run worktree operation for the higher-level sync and push flows, which handle more of the edge cases.',mutatesWorktree:!0}),Z("WORKTREE_WAIT_PUSH_READY","Worktrees","Wait for push-ready","WAIT",["worktree.id"],W,{description:"Parks the run until the worktree's branch is pushed and tracking a remote.",details:"The step to put between an AI session that commits and Open pull request, which needs the branch to exist on the remote. Resolves as soon as the branch is push-ready; without a timeout it waits indefinitely, so set one if a human may never push. Writes `worktree.pushStatus`."}),Z("WORKTREE_SNAPSHOT","Worktrees","Snapshot Git state","AGENT",["worktree.path"],["steps.<stepId>.snapshotId"],{description:"Captures a restorable checkpoint of the worktree's Git state before a risky step.",details:"Runs on the agent, so it needs `worktree.path` and an online agent. The snapshot id it writes is what run replay restores from, which makes this the step to place before anything that rewrites the tree. Snapshots cost disk on the agent."}),Z("CODEBASE_FETCH_REFRESH","Codebases","Fetch or refresh codebase","SERVER",["codebase.id"],$,{description:"Fetches remote refs for a codebase, or fully refreshes its cached metadata.",details:"Fetch updates remote-tracking branches; refresh re-reads the whole checkout and is slower. Runs as an agent job and waits. Fails when the agent skips the operation — usually because the codebase is missing or already busy. Put a fetch in front of steps that check whether a remote branch exists.",mutatesWorktree:!0}),Z("CODEBASE_INSPECT_GIT","Codebases","Inspect codebase Git state","SERVER",["codebase.id"],["codebase.*"],{description:"Reads the codebase checkout's Git status into `codebase.*`.",details:"Read-only. This is the primary checkout, not a worktree — use Inspect worktree Git state for per-branch work. Useful for refusing to start work when the base checkout is dirty or on an unexpected branch."}),Z("CODEBASE_GIT_OPERATION","Codebases","Run codebase Git operation","SERVER",["codebase.id"],$,{description:"Runs a Git operation against the codebase's primary checkout.",details:'Same operations as the worktree version, aimed at the main checkout that every worktree branches from — so a bad rebase or reset here affects all of them. "Stash changes first" clears local modifications out of the way. Runs as an agent job and waits.',mutatesWorktree:!0}),Z("BUILD_START","Builds","Start build or test","SERVER",["codebase.id","worktree.id"],["build.*"],{description:"Queues an iOS build, test, or archive run on the agent and waits for it to finish.",details:"Needs a build configuration id and an online agent; the destination and build scripts are optional. The step parks until the build reaches a terminal status, so a long test suite holds the workflow run. Failing builds fail the step — route the failure handle if you want to read the results anyway. Writes `build.*`, which the read-results and coverage steps then consume.",mutatesExternal:!0}),Z("BUILD_READ_TEST_RESULTS","Builds","Read test results","SERVER",["build.id"],["build.testSummary","build.tests"],{description:"Reads a finished build's test report into `build.testSummary` and `build.tests`.",details:"Fails outright when the report is not ready, so it belongs after Start build or test rather than in parallel with it. The summary carries the passed/failed counts a condition can branch on; the per-test list is the detail an AI prompt can be pointed at. Read-only."}),Z("BUILD_READ_COVERAGE","Builds","Read code coverage","SERVER",["build.id"],["build.coverageSummary","build.coverageFiles","build.changedCoverageFiles"],{description:"Reads a finished build's coverage report into `build.coverageSummary` and the per-file breakdowns.",details:'Fails when the coverage report is not ready — the build must have been run with coverage collection on. Also writes the changed-files breakdown, which is what a "coverage on this branch\'s changes" gate should read rather than the whole-project number. Read-only.'}),Z("BUILD_IMPORT_COVERAGE","Builds","Import coverage report","SERVER",["worktree.id"],["build.id","build.coverageSummary"],{description:"Reads a coverage file a test command wrote in the worktree and records it as a coverage report.",details:"Pair it with a Terminal command step that runs the test suite first: this step only reads what that run left behind, at the path given in `Coverage file`. The build name defaults to the workflow name and can be overridden. LCOV and Istanbul (`coverage-final.json`) are both understood, and AUTO tells them apart by the file itself. Runs as an agent job and waits. The report is attached to a new build record of its own, so it shows up on that build's coverage page and in the coverage picker on Changes; changed-line coverage is measured against the worktree's base branch, and is left out when that branch cannot be resolved. Writes the totals to `build.coverageSummary` and the new id to `build.id` — follow with Read code coverage for the per-file breakdown. Fails when the file is missing, unreadable, or describes no files."}),Z("BUILD_EXPORT","Builds","Export archive","SERVER",["build.id"],["build.exportId",...W],{description:"Exports a finished archive build into a distributable package on the agent.",details:"Needs export settings and an archive-action build. Runs as an agent job and waits. Writes files to the agent's disk and may talk to Apple's servers for signing, so it can fail on expired certificates or provisioning profiles.",mutatesExternal:!0}),Z("BUILD_DEPLOY","Builds","Deploy build","SERVER",["build.id"],W,{description:"Installs and launches an existing build on its destinations without rebuilding.",details:"Reuses the artifacts from a previous build, so it is much faster than building again. Destinations default to the ones the build already targeted. Waits for the deployment job. This puts the app on real or simulated devices — treat it as an external effect.",mutatesExternal:!0}),Z("BUILD_CANCEL","Builds","Cancel build","SERVER",["build.id"],["build.id","build.status"],{description:"Cancels a queued or running build.",details:"Aimed at a different build from the one this run started — Start build or test already waits for its own. Cancelling an already-finished build is a no-op rather than an error. Writes `build.status`.",mutatesExternal:!0}),Z("DISK_SPACE_LOAD","Disk space","Load disk-space monitor","SERVER",[],["agent.*","disk.*"],{description:"Loads the current Derived Data disk-space monitor snapshot for an agent.",details:"Targets the configured agent, then falls back to `agent.id` or `codebase.agentId`. The least-free monitored Derived Data volume supplies `disk.freeBytes`, `disk.freeGiB`, and the percentage fields; root and base-repository volumes remain in `disk.volumes` for context only. Read-only and does not request a new report."}),Z("DISK_SPACE_REFRESH","Disk space","Refresh disk-space monitor","WAIT",[],["agent.*","disk.*"],{description:"Requests an immediate disk report from an agent and waits for fresh telemetry.",details:"Targets the configured agent, then falls back to `agent.id` or `codebase.agentId`. Monitoring must be enabled. The step waits until `lastReportedAt` advances, then refreshes `agent.*` and `disk.*`; by default it polls every two seconds and times out after 180 seconds."}),Z("DISK_SPACE_UPDATE_THRESHOLDS","Disk space","Update disk thresholds","SERVER",[],["disk.normalThresholdGiB","disk.pressureThresholdGiB","disk.pollIntervalSeconds","disk.staleAfterSeconds"],{description:"Updates the global normal and pressure free-space thresholds.",details:"Changes the thresholds used for every monitored agent, automatic cleanup, and admission control. The pressure threshold must be positive and lower than the normal threshold. Writes the resulting global settings into `disk.*`."}),Z("DISK_SPACE_SET_MONITORING","Disk space","Set agent disk monitoring","SERVER",[],["agent.*","disk.*"],{description:"Enables or disables Derived Data disk-space monitoring for an agent.",details:"Targets the configured agent, then falls back to `agent.id` or `codebase.agentId`. Disabling monitoring also clears manual and automatic pressure mode and releases cleanup leases that have not started a job. Refreshes `agent.*` and `disk.*`."}),Z("DISK_SPACE_SET_PRESSURE_MODE","Disk space","Set disk pressure mode","SERVER",[],["agent.*","disk.*"],{description:"Enables or clears manual disk pressure mode for an agent.",details:"Targets the configured agent, then falls back to `agent.id` or `codebase.agentId`. Manual pressure mode uses the lower pressure threshold; automatic pressure mode remains controlled by cleanup availability. Refreshes `agent.*` and `disk.*`."}),Z("SKILL_APPLY","Skills","Apply skill group","SERVER",["worktree.id","repo.id"],["steps.<stepId>.status"],{description:"Syncs a skill group's files into the target checkout, or every skill when no group is chosen.",details:"Starts a skill sync run and waits for it. Writes skill files into the repository, which shows up as uncommitted changes — commit or discard them before a step that needs a clean tree. Leave the group empty to sync everything.",mutatesWorktree:!0}),Z("RUN_CREATE_PLAN","AI runs","Create plan and wait","SERVER",["worktree.id"],["run.<stepId>.*"],{description:"Starts an AI planning run against the worktree and waits for the plan to be produced.",details:"Requires a worktree, a provider/model, and a prompt. Plans use a separate FIFO worktree queue and allow unlimited concurrent plans by default; set the worktree concurrency limit to 1–32 to cap them, or 0 for unlimited. Planning inspects the code but does not change it — use Run AI session and wait to actually make edits, or follow with Run completed plan. If the run asks a question it parks until someone answers, so pair long workflows with a question-needed trigger. Writes the run under `run.<stepId>.*`, which later steps reference by this step's id."}),Z("RUN_CREATE_SESSION","AI runs","Run AI session and wait","SERVER",["worktree.id"],["run.<stepId>.*"],{description:"Starts an AI coding session against the worktree and waits for it to finish.",details:"The workhorse step: the agent edits files in the worktree, so the tree is dirty afterwards and the changes still need committing and pushing. Sessions use a separate FIFO worktree queue with one active session by default; set the worktree concurrency limit to 2–32 for parallel sessions or 0 for unlimited. Requires a worktree, a provider/model, and a prompt; attachments and web search are optional. Parks on questions until answered. Writes `run.<stepId>.*`.",mutatesWorktree:!0}),Z("RUN_PLAY_PLAN","AI runs","Run completed plan","SERVER",[],["run.<stepId>.*"],{description:"Executes a plan that has already been produced, turning it into real code changes.",details:"Takes the plan's run id — usually `run.<planStepId>.id` from an earlier Create plan step. The plan must have completed. The resulting Session joins the worktree's FIFO Session queue, which allows one active Session by default; use 0 for unlimited or 2–32 for a larger limit. This is the half of the plan/execute split that touches the worktree. Writes a new run under `run.<stepId>.*`.",mutatesWorktree:!0}),Z("RUN_FOLLOW_UP","AI runs","Follow up run","SERVER",[],["run.<stepId>.*"],{description:"Starts a new AI run that continues from an existing one, resuming its context or starting fresh.",details:'RESUME keeps the previous conversation, FRESH starts over in the same worktree, and RESEND replays the original prompt. The new run joins the source kind\'s separate FIFO worktree queue and defaults to unlimited concurrency for Plans or one active run for Sessions; use 0 for unlimited or 1–32 for a finite limit. Needs the source run id plus a new prompt. The natural step for "fix the review comments" loops after a first session. Writes `run.<stepId>.*`.'}),Z("RUN_STEER","AI runs","Steer active run","SERVER",[],["run.<stepId>.*"],{description:"Sends extra instructions into a run that is already in progress.",details:"Only affects a run that is still going — it does not restart a finished one, which is what Follow up run is for. Because the steps in this workflow that start runs also wait for them, steering usually targets a run started elsewhere, reached through a run trigger."}),Z("RUN_ANSWER","AI runs","Answer run question","SERVER",[],["run.<stepId>.*"],{description:"Answers a question an AI run is blocked on so it can carry on.",details:"Needs the question batch id, typically from `run.questions` seeded by a run-needs-an-answer trigger, and answers keyed by question id. This answers questions asked by an AI run — the Request confirmation and Ask user to choose steps ask questions of a human about the workflow itself."}),Z("RUN_PAUSE","AI runs","Pause run","SERVER",[],["run.<stepId>.*"],{description:"Pauses an in-progress AI run.",details:"The run stops at its next checkpoint and stays paused until something continues it. Falls back to `run.id`. Pausing an already-finished run fails."}),Z("RUN_CONTINUE","AI runs","Continue run","SERVER",[],["run.<stepId>.*"],{description:"Resumes a paused AI run.",details:"The counterpart to Pause run. Fails when the run is not paused. Falls back to `run.id`."}),Z("RUN_CANCEL","AI runs","Cancel run","SERVER",[],["run.<stepId>.*"],{description:"Cancels an AI run, stopping its work.",details:"Whatever the run already wrote to the worktree stays — cancelling stops further work, it does not roll anything back. Falls back to `run.id`."}),Z("RUN_REVISE_ANSWER","AI runs","Revise answer and rewind","SERVER",[],["run.<stepId>.*"],{description:"Rewinds a run to an earlier question, replaces the answer, and replays from there.",details:"Two-phase: the step prepares the revision, parks, and applies it once the run is ready. Rolling back restores the worktree to the checkpoint at that question, discarding work done since — stash first if that work matters. The heavy way to correct a wrong answer; Follow up run is usually enough.",mutatesWorktree:!0}),Z("RUN_READ_RESULT","AI runs","Read run result","SERVER",[],["run.<stepId>.*"],{description:"Loads a finished run's events, questions, token usage, and linked items into session data.",details:"Read-only. Gives later steps the run's actual output to work from — a summary to put in a Jira comment, usage figures to threshold on, or the linked pull request. Falls back to `run.id`."}),Z("RUN_CAPTURE_CHECKPOINT","AI runs","Capture run checkpoint","SERVER",[],["steps.<stepId>.snapshotId"],{description:"Records the run's most recent checkpoint so a later replay can restore from it.",details:"Reads an existing checkpoint rather than creating one, and fails when the run has none. Use Snapshot Git state to capture a fresh checkpoint of the worktree instead. Writes the checkpoint id to `steps.<stepId>.snapshotId`."}),Z("RUN_ARCHIVE_DELETE","AI runs","Archive or delete run","SERVER",[],[],{description:"Archives a run out of the active list, or permanently deletes it.",details:"Archiving is reversible; deleting removes the run and its history for good. Delete wins when both flags are set. Housekeeping for workflows that generate many short-lived runs.",mutatesExternal:!0}),Z("NOTIFICATION_SEND","Human loop","Send notification","SERVER",[],[],{description:"Posts a notification into the app's notification list with a title, body, and link.",details:"Deduplicated per run, step, and generation, so a retried attempt does not notify twice. The link defaults to this workflow run. Fire-and-forget: it tells a human something happened but does not wait — use Request confirmation when the workflow needs an answer.",mutatesExternal:!0}),Z("IOS_PUSH_SEND","Human loop","Push to iOS device","SERVER",[],[],{description:"Sends an Apple push notification to registered devices, a broadcast channel, or one raw device token.",details:"Needs APNs credentials. Target mode picks between all registrations, a chosen few, a broadcast channel, or a direct token — the direct mode also needs the token's encoding and whether it is a sandbox or production token. Leaves the device once delivered; nothing about the run waits on it.",mutatesExternal:!0}),Z("HUMAN_CONFIRM","Human loop","Request confirmation","WAIT",[],["steps.<stepId>.answer"],{description:"Parks the run and asks a human to confirm before continuing.",details:"The approval gate to put in front of anything irreversible. Without a timeout the run waits indefinitely; with one it fails when nobody answers in time, which the failure handle can route to a safe default. The answer lands in `steps.<stepId>.answer`."}),Z("HUMAN_CHOICE","Human loop","Ask user to choose","WAIT",[],["steps.<stepId>.answer"],{description:"Parks the run and asks a human to pick from a set of options, optionally allowing several or a free-text answer.",details:"Like Request confirmation but with named buttons — branch on `steps.<stepId>.answer` with an If step afterwards. Multi-select returns a list. Allowing a custom answer means the value may be anything the person typed, so handle the unexpected case."}),Z("CONTROL_IF","Control flow","If / else","CONTROL",[],[],{description:"Evaluates a condition and sends the run down its `true` or `false` branch.",details:"Exactly one branch is taken; steps on the other are skipped, and a skipped branch does not block a downstream join. Conditions compare session values with the usual operators and combine with ALL/ANY/NOT. Both branches may be left unconnected, which simply ends that path."}),Z("CONTROL_JOIN","Control flow","Join branches","CONTROL",[],[],{description:"Brings parallel branches back together, waiting for all of them or continuing on the first.",details:"Required wherever more than one branch reaches the same step — the validator rejects a plain step with several incoming edges. ALL waits for every branch, ANY continues on the first and lets the others keep running. Skipped branches never block it, and the join is skipped when no branch reaches it. A join that closes a For each also reports the iteration failures."}),Z("CONTROL_DELAY","Control flow","Time delay","WAIT",[],[],{description:"Pauses the run for a fixed number of seconds.",details:"Accepts up to a year. The run is parked rather than held open, so a long delay costs nothing while it waits. Use it to space out polling or to give an external system time to settle; use Wait until when you are waiting for a condition rather than a duration."}),Z("CONTROL_WAIT_UNTIL","Control flow","Wait until","WAIT",[],[],{description:"Parks the run until a condition over session data becomes true, re-checking on a cadence.",details:"Evaluates immediately and continues at once if the condition already holds. Session data only changes when a step writes it, so the condition must be able to become true through some other branch — otherwise the wait never resolves. Default cadence is 15 seconds; set a timeout to bound it."}),Z("CONTROL_FOR_EACH","Control flow","For each","CONTROL",[],["steps.<stepId>.items"],{description:"Runs its `body` branch once per item in a list, or takes the `empty` branch when there is nothing to iterate.",details:"Reads the list from a session path or from inline items, and caps at 1,000. Iterations run in parallel and each sees its own item. Fail-fast stops the whole run on the first failing iteration; collect-errors lets them all finish and reports failures at the closing join. Writes the items to `steps.<stepId>.items`."}),Z("CONTROL_TRY","Control flow","Try / catch","CONTROL",[],[],{description:"Marks the start of a protected region whose failures route out of the `catch` handle.",details:"Takes no config — the recovery path is drawn in the graph. Steps on the `success` branch run normally; when one of them fails, the run continues from `catch` instead of failing outright. Use a step's own failure handle for a single fallible step; reach for this when a whole sequence shares one recovery path."}),Z("CONTROL_SET_VARIABLE","Control flow","Set or compute variable","CONTROL",[],[],{description:"Writes a value into session data at a chosen path, either a constant or the result of a small script.",details:"The script runs in a sandboxed JavaScript interpreter with the session data available and no network or filesystem access; its return value is what gets written. Without a script the literal value is used. The path may be any dotted path — write under a namespace of your own to avoid colliding with what steps produce. Because the path comes from config, the catalog cannot advertise it: list it in this step's own `providedPaths` too, or a later step that binds it fails to publish with REQUIREMENT_UNSATISFIED."}),Z("CONTROL_SUBWORKFLOW","Control flow","Call sub-workflow","SERVER",[],[],{description:"Runs another published workflow as a child and waits for it to finish.",details:"Must pin a specific published version — the validator rejects an unpinned reference, so a sub-workflow cannot change under a caller. The input mapping seeds the child's session data. The child appears as a nested run; its failure fails this step."}),Z("SAVED_COMMAND","Extensibility","Run saved command","AGENT",[],["steps.<stepId>.*"],{description:"Starts a saved command on an eligible agent home or worktree target.",details:"Uses the saved command snapshot, target rules, output log, and restart policy. Wait for exit fails the workflow when the command ultimately fails or is cancelled; fire and forget succeeds after durable dispatch and remains independent if the workflow is later cancelled. An optional RE2 output pattern emits the match connector before exit and records captures in session data; matching requires wait for exit. Always-restart commands can only use fire and forget.",mutatesWorktree:!0}),Z("CUSTOM_COMMAND","Extensibility","Run custom command","AGENT",[],["steps.<stepId>.*"],{description:"Runs a one-off shell command on an agent home or worktree and records it in Commands run history.",details:"The script is retained only in the immutable command-run snapshot, not as a reusable saved command. Context targeting prefers the current worktree, then the current agent. Wait for exit fails the workflow when the command fails or is cancelled; fire and forget succeeds after durable dispatch. An optional RE2 output pattern emits the match connector before exit and records captures in session data; matching requires wait for exit.",mutatesWorktree:!0}),...ee,Z("TERMINAL_RUN","Extensibility","Run terminal script","AGENT",["worktree.path"],["steps.<stepId>.*"],{description:"Runs a shell or Node script on the agent inside the worktree, capturing its output.",details:"Needs `worktree.path` and an online agent. A non-zero exit fails the step. Named credentials can be injected as environment variables so secrets never sit in the definition — the validator rejects secret-looking literals in config. Arbitrary code on the agent's machine: it can change anything the agent user can reach. Writes stdout, stderr, and the exit code under `steps.<stepId>.*`; to publish anything else the script produces into a named path, declare it in this step's own `providedPaths`.",mutatesWorktree:!0}),Z("MCP_CALL","Extensibility","Call MCP tool","SERVER",[],["steps.<stepId>.output"],{description:"Calls a tool on a configured MCP server — built-in or external — with a JSON argument object.",details:"The general escape hatch to anything reachable over MCP. Needs the server (tool group) and the exact tool name; arguments must match that tool's own schema. What it does depends entirely on the tool, so treat it as externally mutating. The result lands in `steps.<stepId>.output`.",mutatesExternal:!0}),...[["SSE_ENDPOINT_ACTION","Manage SSE endpoint"],["SSE_MOCK_ACTION","Manage SSE mock"],["SSE_STORAGE_ACTION","Manage SSE storage"],["SSE_BREAKPOINT_RESOLVE","Resolve SSE breakpoint"],["SSE_HISTORY_CLEAR","Clear SSE history"],["SSE_SCRIPT_TEST","Test SSE script"]].map(([e,A])=>X(e,"SSE",A,[],["sse.*","steps.<stepId>.output"],{mutatesExternal:!1}))],et=new Map(eA.map(e=>[e.kind,e])),er=["run.*","worktree.*","codebase.*","agent.*","repo.*","ticket.*"],ei=["build.*","worktree.*","codebase.*","agent.*","repo.*","ticket.*"],en=["worktree.*","codebase.*","agent.*","repo.*","ticket.*","pr.*"],ea=["ticket.*","comment.*","changelog.*"],eo=["repo.*","pr.*","ticket.*","worktree.*","codebase.*","agent.*"],es=[...eo,"comment.*"],el=["repo.*","pr.*","ticket.*","worktree.*","codebase.*","agent.*"],ed="Filters narrow it further: each session path must equal the given value, or be one of a list of values.",eu="Set a threshold path, operator, and value to fire only on the crossing: it fires when the comparison first becomes true and stays quiet until it goes false again, so a metric hovering over the line does not fire repeatedly.",ec=(e,A,t,r,i)=>({kind:e,category:A,label:t,description:i.description,details:i.details,configSchema:K(e,"trigger"),capabilityFlags:["DURABLE","DEDUPLICATED"],seedPaths:r,sourceHandles:(0,n.workflowStaticSourceHandles)(e)}),eh=(e,A,t,r)=>ec(e,A,t,r,{description:`${t} emits a normalized, filterable workflow event.`,details:`${t} uses the canonical domain event and deduplicates deliveries by subject and revision. ${ed}`}),eg=[eh("COMMAND_RUN_RESULT","Commands","Command run result",["command.*","agent.*","worktree.*"]),eh("COMMAND_OUTPUT_MATCH","Commands","Command output match",["command.*","output.*"]),eh("SKILL_SYNC_RESULT","Skills","Skill sync result",["skillSync.*","skill.*","repo.*"]),eh("SKILL_SYNC_CONFLICT","Skills","Skill sync conflict",["skillSync.*","skill.*","repo.*"]),eh("GITHUB_PIPELINE_STATUS_CHANGED","GitHub","Pipeline status changed",["pipeline.*","repo.*","pr.*","worktree.*","codebase.*","agent.*","ticket.*"]),eh("GITHUB_PR_SYNCHRONIZED","GitHub","Pull request synchronized",eo),eh("GITHUB_REVIEW_APPROVED","GitHub","Pull request review approved",eo),...[["GITLAB_MR_STATE","Merge request opened or ready",el],["GITLAB_REVIEW_CHANGES_REQUESTED","Changes requested",el],["GITLAB_REVIEW_COMMENT","Review comment created",[...el,"comment.*"]],["GITLAB_MR_CLOSED","Merge request merged or closed",el],["GITLAB_PIPELINE_FAILED","Pipeline failed",["pipeline.*","repo.*","pr.*"]],["GITLAB_PUSH_DEFAULT","Push to default branch",["repo.*","push.*"]],["GITLAB_PIPELINE_SUCCEEDED","Pipeline succeeded",["pipeline.*","repo.*","pr.*"]],["GITLAB_NOTE_COMMAND","Note command",[...el,"comment.*"]],["GITLAB_PIPELINE_RESULT","Pipeline result",["pipeline.*","repo.*","pr.*"]],["GITLAB_MR_LABEL","Merge request label set",el],["GITLAB_PIPELINE_STATUS_CHANGED","Pipeline status changed",["pipeline.*","repo.*","pr.*"]],["GITLAB_MR_SYNCHRONIZED","Merge request synchronized",el],["GITLAB_REVIEW_APPROVED","Merge request approved",el],["GITLAB_JOB_STATUS_CHANGED","Job status changed",["job.*","pipeline.*","repo.*"]]].map(([e,A,t])=>eh(String(e),"GitLab",String(A),t)),eh("JIRA_TICKET_UPDATED","Jira","Jira ticket updated",ea),eh("JIRA_COMMENT_ADDED","Jira","Jira comment added",ea),eh("JIRA_WORKLOG_ADDED","Jira","Jira worklog added",ea),eh("JIRA_SPRINT_ENDED","Jira","Jira sprint ended",ea),eh("CODEBASE_SYNC_STATE_CHANGED","Codebases","Codebase sync state changed",["codebase.*","agent.*","repo.*"]),eh("CODEBASE_OPERATION_FAILED","Codebases","Codebase operation failed",["codebase.*","agent.*","repo.*","operation.*"]),eh("WORKTREE_SYNC_STATE_CHANGED","Worktrees","Worktree sync state changed",en),eh("WORKTREE_AUTOMATION_RESULT","Worktrees","Worktree automation result",[...en,"automation.*"]),eh("WORKTREE_CLEAN","Worktrees","Worktree became clean",en),eh("PUSH_NOTIFICATION_RESULT","Notifications","Push notification result",["pushBatch.*"]),eh("IOS_DEVICE_ENROLLED","Devices","iOS device enrolled",["device.*"]),eh("IOS_DEVICE_REGISTRATION_RESULT","Devices","iOS device registration result",["device.*"]),eh("SIGNING_OPERATION_RESULT","Signing","Signing operation result",["signing.*","signingProfile.*","agent.*"]),eh("SIGNING_ASSET_EXPIRING","Signing","Signing asset expiring",["signing.*","signingProfile.*","agent.*"]),eh("BUILD_DATA_THRESHOLD","Build Data","Build-data threshold",["buildData.*","agent.*","worktree.*"]),eh("BUILD_DATA_CLEANUP_RESULT","Build Data","Build-data cleanup result",["buildData.*","cleanup.*","agent.*"]),eh("POLLING_OPERATION_STATE","Operations","Polling operation state",["polling.*"]),eh("MODEL_COST_CATALOG_CHANGED","Operations","Model-cost catalog changed",["modelCosts.*"]),eh("CREDENTIAL_STORE_DEGRADED","Operations","Credential store degraded",["credentials.*"]),eh("AGENT_RESOURCE_THRESHOLD","Agents","Agent resource threshold",["agent.*"]),eh("AGENT_VERSION_CHANGED","Agents","Agent version changed",["agent.*"]),eh("TOOL_CALL_RESULT","Tools","Tool call result",["toolCall.*"]),eh("SSE_REQUEST_OPENED","SSE","SSE request opened",["sse.*","endpoint.*","request.*"]),eh("SSE_EVENT_EMITTED","SSE","SSE event emitted",["sse.*","endpoint.*","request.*","event.*"]),eh("SSE_BREAKPOINT_WAITING","SSE","SSE breakpoint waiting",["sse.*","endpoint.*","request.*","breakpoint.*"]),eh("SSE_BREAKPOINT_RESOLVED","SSE","SSE breakpoint resolved",["sse.*","endpoint.*","request.*","breakpoint.*"]),eh("SSE_STREAM_COMPLETED","SSE","SSE stream completed",["sse.*","endpoint.*","request.*"]),eh("SSE_STREAM_FAILED","SSE","SSE stream failed",["sse.*","endpoint.*","request.*"])],ep=[ec("MANUAL","Manual","Manual run",[],{description:"Fires when someone presses Run on the workflow. The default entry point.",details:"Seeds nothing beyond `workflow.*`, so steps hanging off it can only bind to values that later steps produce. A caller may still pass session data explicitly when starting the run. A workflow that has only a choice trigger refuses a plain run."}),ec("MANUAL_CHOICE","Manual","Manual run with a choice",[],{description:"Fires when someone picks an option from the menu under the run button, and routes the run out of that option's own handle.",details:"Declare at least one option, each with a unique key — the key names the outgoing handle, so renaming a label leaves edges attached. One workflow can fan out into several entry paths without a step in front of them. Every edge must leave a handle that still exists, or publishing fails."}),ec("RESOURCE_MANUAL","Manual","Run from a resource",[],{description:"Fires when someone starts the workflow from a specific resource page — a worktree, pull request, build, codebase, ticket, or run.",details:"Must target exactly one resource kind; add a second trigger to accept another. The page seeds that resource's namespace into session data, so a worktree-launched run gets its worktree, codebase, owning agent, repository, and any linked ticket. Those seeds are an optimistic contract — an optional link that is absent resolves to nothing at run time. A worktree does not seed `pr.*`; use a pull-request trigger or Load pull request to bring one into session data. This is also what makes the workflow show up on that resource's page."}),ec("RESOURCE_MANUAL_CHOICE","Manual","Run from a resource with a choice",[],{description:"Fires from a resource page after the person picks an option, routing out of that option's handle.",details:"The resource and choice triggers combined: pick a resource kind and declare keyed options. Same rules as both — one resource kind per trigger, unique option keys, and every edge on a live handle."}),ec("SCHEDULE","Schedule","On a schedule",[],{description:"Fires repeatedly on a fixed cadence measured in seconds.",details:'A cadence, not a cron expression — there is no way to say "weekdays at 9am". The clock runs while the workflow is enabled, and pausing the workflow stops it. Seeds nothing, so scheduled workflows normally start by loading whatever they operate on. Mind the overlap policy: a cadence shorter than the run takes will queue or coalesce.'}),ec("WORKFLOW_FINISHED","Workflows","Another workflow finished",["workflow.*"],{description:"Fires when a different workflow run reaches a terminal state.",details:`Chains workflows without making one a sub-workflow of the other, so the two stay independently runnable. Filter on \`workflow.id\` to watch a specific one and on the finishing status to react only to failures. ${ed}`}),ec("GITHUB_PR_STATE","GitHub","Pull request opened or ready",eo,{description:"Fires when a pull request is opened, or when a draft is marked ready for review.",details:`Needs GitHub polling configured for the repository. Seeds \`pr.*\` and \`repo.*\`, so steps can act on the pull request straight away. ${ed} Filter on \`pr.isDraft\` or the base branch to avoid firing on every pull request in the repository.`}),ec("GITHUB_REVIEW_CHANGES_REQUESTED","GitHub","Changes requested",eo,{description:"Fires when a reviewer submits a review requesting changes.",details:`The entry point for an automated "address the review" loop: pair it with Collect review comments and an AI session. Approvals and plain comments do not fire it. ${ed}`}),ec("GITHUB_REVIEW_COMMENT","GitHub","Review comment created",es,{description:"Fires when a new review comment is posted on a pull request.",details:`Fires per comment rather than per review, so a reviewer leaving five comments fires it five times — take care with steps that start AI runs. Use Changes requested when you want one event per review. ${ed}`}),ec("GITHUB_PR_CLOSED","GitHub","Pull request merged or closed",eo,{description:"Fires when a pull request is merged or closed without merging.",details:`Both outcomes fire it; branch on \`pr.state\` to tell them apart. The natural place to hang cleanup — deleting the worktree, moving the ticket on. ${ed}`}),ec("GITHUB_CHECK_FAILED","GitHub","Check suite or run failed",["repo.*","pipeline.*","worktree.*","codebase.*","agent.*","pr.*","ticket.*"],{description:"Fires when a check suite or check run reports a failure.",details:`Seeds \`pipeline.*\`, including the ids the retry and cancel steps need. Flaky suites fire this often, so gate an automatic retry on a count or a delay rather than retrying unconditionally. ${ed}`}),ec("GITHUB_PUSH_DEFAULT","GitHub","Push to default branch",["repo.*","push.*","ticket.*"],{description:"Fires when a commit lands on the repository's default branch.",details:`Seeds \`repo.*\` and \`push.*\`, plus a ticket key when the pushed branch contains one. There is no pull request or worktree in scope, so a workflow hanging off it usually starts by creating one. Fires on merges too, since a merge is a push. ${ed}`}),ec("GITHUB_WORKFLOW_SUCCEEDED","GitHub","Workflow run succeeded",["repo.*","pipeline.*","worktree.*","codebase.*","agent.*","pr.*","ticket.*"],{description:"Fires when a GitHub Actions workflow run completes successfully.",details:`The success counterpart to the failure triggers — useful for gating a deploy or a merge on a green pipeline. Filter on the workflow name so every unrelated Actions run does not start this workflow. ${ed}`}),ec("GITHUB_ISSUE_COMMAND","GitHub","Issue comment command",["repo.*","pr.*","ticket.*","comment.*"],{description:"Fires when a comment from an allow-listed GitHub user matches a command pattern, such as `/deploy`.",details:`The only trigger that lets outside text start a workflow, so it is deliberately strict: an explicit list of GitHub logins is required, and the pattern must be anchored with \`^\` and \`$\` — publishing fails otherwise. Both checks must pass. Keep the allow-list tight, since anyone on it can start whatever the workflow does. ${ed}`}),ec("GITHUB_ACTIONS_RESULT","GitHub Actions","Workflow result",["repo.*","pipeline.*","worktree.*","codebase.*","agent.*","pr.*","ticket.*"],{description:"Fires when a tracked GitHub Actions run finishes, whatever its conclusion.",details:`The richest of the Actions triggers: it correlates the run back to its worktree, owning agent, pull request, and ticket when those links exist. Branch on the conclusion rather than adding separate success and failure triggers. ${ed}`}),ec("GITHUB_PR_LABEL","GitHub","Pull request label set",eo,{description:"Fires when a label is applied to a pull request.",details:`Turns a label into a manual switch — label a pull request \`automerge\` and let a workflow take it from there. Filter on the label name, or every label change in the repository starts the workflow. ${ed}`}),ec("BUILD_RESULT","Builds","Build result",ei,{description:"Fires when a build finishes, succeeded or failed.",details:`Seeds \`build.*\` along with the worktree it ran in, so the read-results and coverage steps can follow directly. Branch on \`build.status\` to separate the outcomes. ${ed}`}),ec("BUILD_TEST_THRESHOLD","Builds","Test failure threshold",ei,{description:"Fires when a build's failing-test count crosses a threshold you set.",details:`Point the threshold path at \`build.testSummary.failed\` and pick an operator and value. ${eu} ${ed}`}),ec("BUILD_COVERAGE_THRESHOLD","Builds","Coverage threshold",ei,{description:"Fires when a build's code coverage crosses a threshold you set.",details:`Point the threshold path at the coverage summary — usually the changed-files percentage rather than the whole-project number — and compare with a less-than operator. ${eu} ${ed}`}),ec("BUILD_HOOK_FAILED","Builds","Build hook failed",ei,{description:"Fires when one of a build's pre- or post-build scripts fails.",details:`Distinguishes a broken build script from a genuine compile or test failure, which is what Build result reports. Seeds \`build.*\`. ${ed}`}),ec("AGENT_CONNECTION","Agents","Agent connection changed",["agent.*","codebase.agentId"],{description:"Fires when an agent comes online or goes offline.",details:`Seeds the agent id, name, connection state, and capacity metrics. A workflow hanging off it is usually about notifying a human rather than doing repository work — an offline agent cannot run agent steps anyway. Filter on the connection status to react to one direction only. ${ed}`}),ec("AGENT_JOB_FAILED","Agents","Agent job failed",["steps.trigger.*","agent.*","codebase.*","worktree.*","repo.*","ticket.*"],{description:"Fires when a job dispatched to an agent fails — a build, a Git operation, a terminal script.",details:`The failing job is seeded under \`steps.trigger.*\`, including its kind and error. When it targeted a worktree, the owning agent, codebase, repository, and ticket are included too. Catches infrastructure failures that a workflow's own failure handles never see, because the job belonged to a different run. ${ed}`}),ec("AGENT_DISK_REPORT","Agents","Agent disk report",["agent.*","codebase.agentId","disk.*"],{description:"Fires whenever the Derived Data monitor accepts a new agent disk report.",details:`Seeds the complete monitor snapshot under \`disk.*\`, while \`agent.diskFreeBytes\` remains the legacy root-disk inventory value. This can fire at the agent poll cadence; use filters when every report is not needed. ${ed}`}),ec("AGENT_DISK_THRESHOLD","Agents","Agent disk threshold",["agent.*","codebase.agentId","disk.*"],{description:"Fires when monitored Derived Data free space crosses a threshold you set.",details:`Use \`disk.freeGiB\`, \`disk.freeBytes\`, or \`disk.freePercent\` to evaluate the least-free monitored Derived Data volume. \`agent.diskFreeBytes\` remains available for older root-disk workflows. ${eu} ${ed}`}),ec("AGENT_DISK_STATE_CHANGED","Agents","Agent disk state changed",["agent.*","codebase.agentId","disk.*"],{description:"Fires when an agent's disk monitor changes status, pressure mode, health, or monitored volume.",details:`Filter on \`disk.status\`, \`disk.pressureMode\`, \`disk.enabled\`, or errors and warnings to react to a specific transition. Cleanup start appears as \`DELETING\`; recovery can be selected with \`IDLE\`. Repeated reports in the same state stay quiet. ${ed}`}),ec("AGENT_DISK_CLEANUP_RESULT","Agents","Automatic disk cleanup result",["agent.*","codebase.agentId","disk.*","cleanup.*"],{description:"Fires whenever a monitor-managed automatic Derived Data cleanup finishes.",details:`Seeds the terminal agent job under \`cleanup.*\`, including status, error, targets, and deleted entries. Every cleanup job is independent, so two successive successes both fire. Manual Build Data deletions remain outside this trigger. ${ed}`}),ec("CCUSAGE_THRESHOLD","Agents","Usage threshold",["run.usage.*","agent.*"],{description:"Fires when aggregate AI usage crosses a threshold you set.",details:`Watches usage across runs rather than one run's spend — Run usage threshold does that. The cost guardrail: notify, or pause workflows that start AI runs. ${eu} ${ed}`}),ec("WORKTREE_CREATED","Worktrees","Worktree created",en,{description:"Fires after a new worktree is successfully created.",details:`Fires once after the created worktree is projected into the control plane. Seeds the worktree, repository, codebase, and owning agent, plus a linked pull request and Jira ticket when the branch resolves to them. ${ed}`}),ec("WORKTREE_BEHIND","Worktrees","Worktree behind base",en,{description:"Fires when a worktree's branch falls behind the branch it was cut from.",details:`Pairs with a sync operation to keep long-lived branches current. Fires again as the base moves on, so a workflow that reacts should either sync or be filtered narrowly. ${ed}`}),ec("WORKTREE_CONFLICT","Worktrees","Worktree has conflicts",en,{description:"Fires when a worktree is left with Git conflicts after a merge or rebase.",details:`Only fires when the worktree is genuinely marked conflicted. Conflicts need resolving before most other worktree steps will work, so this usually leads to a notification or an AI session pointed at the conflict. ${ed}`}),ec("WORKTREE_MISSING","Worktrees","Worktree missing",en,{description:"Fires when a worktree the control plane knows about is no longer on disk.",details:`Only fires once the worktree is actually recorded as missing — usually someone deleted the directory by hand, or the agent's disk was cleaned. Steps that need the worktree will fail, so react by recreating it or clearing the record. ${ed}`}),ec("WORKTREE_DIVERGED","Worktrees","Worktree diverged",en,{description:"Fires when a worktree's branch and its remote have both moved on independently.",details:`Only fires when the push status is genuinely diverged. Resolving it means a rebase, a merge, or a force push — all destructive enough that this usually routes to a human rather than to an automatic fix. ${ed}`}),ec("WORKTREE_DIRTY_DURATION","Worktrees","Worktree dirty too long",en,{description:"Fires when a worktree has had uncommitted changes for longer than expected.",details:`Catches work that stalled — an AI session that edited files and was never followed up, or a human who wandered off. Usually a nudge rather than an automatic commit. ${ed}`}),ec("WORKTREE_NEW_COMMIT","Worktrees","New worktree commit",en,{description:"Fires when a new commit lands in a worktree.",details:`Fires per commit, so a rebase or a batch of commits fires it repeatedly — keep the reaction cheap, or filter to one branch. Useful for kicking off a build or lint pass as work lands. ${ed}`}),ec("CODEBASE_REMOTE_BRANCH","Codebases","Matching remote branch",["codebase.*","agent.*","repo.*"],{description:"Fires when a remote branch matching the codebase's conventions appears.",details:`Lets a branch pushed from elsewhere pull work into this system — creating a worktree for it, or opening a pull request. Needs a fetch to have run for the branch to be visible. ${ed}`}),ec("JIRA_STATUS","Jira","Ticket status changed",ea,{description:"Fires when a Jira ticket moves to another status.",details:`Needs Jira polling configured. Seeds \`ticket.*\`. Filter on \`ticket.status\` to react to one column only — without a filter, every transition on every polled ticket starts the workflow. ${ed}`}),ec("JIRA_LABEL","Jira","Jira label set",ea,{description:"Fires when a label is applied to a Jira ticket.",details:`The Jira counterpart to the pull request label trigger: a label becomes a manual switch for automation. Filter on the label name. ${ed}`}),ec("JIRA_ASSIGNED_SELF","Jira","Ticket assigned to me",ea,{description:"Fires when a ticket is assigned to the account behind the configured Jira credential.",details:`"Me" is whoever the Jira credential authenticates as, not whoever is looking at the screen. The usual start of a "pick up my next ticket" workflow — create a worktree, start a plan. ${ed}`}),ec("JIRA_SOURCE_NEW_TICKET","Jira","New ticket in source",ea,{description:"Fires when a ticket appears in a configured Jira source — a saved JQL query or board.",details:`Fires on tickets newly matching the source, which includes existing tickets edited into range, not only freshly created ones. The source itself does the filtering, so keep its JQL tight. Seeds \`ticket.*\`. ${ed}`}),ec("JIRA_MENTION","Jira","Jira comment mention",ea,{description:"Fires when the configured Jira account is mentioned in a ticket comment.",details:`Lets someone pull automation into a conversation by mentioning the bot. The comment is seeded under \`comment.*\`, so an AI step can read what was actually asked — treat that text as untrusted input rather than instructions. ${ed}`}),ec("JIRA_SPRINT_STARTED","Jira","Sprint started",ea,{description:"Fires when a Jira sprint is started.",details:`Fires per ticket in the sprint, so a sprint of thirty tickets starts thirty runs — mind the workflow's concurrency settings. Good for sprint-opening bookkeeping. ${ed}`}),ec("JIRA_ISSUE_CREATED","Jira","Ticket created",ea,{description:"Fires when a Jira ticket is created.",details:`Needs the Jira webhook configured in Settings — the polled Jira triggers only observe tickets something already fetched, so they cannot see a brand-new one. Scope the webhook's JQL filter to the projects you care about, since every created ticket otherwise starts a run. ${ed}`}),ec("JIRA_ISSUE_DELETED","Jira","Ticket deleted",ea,{description:"Fires when a Jira ticket is deleted.",details:`Needs the Jira webhook. The ticket is gone by the time this runs, so only the payload's \`ticket.*\` snapshot is available — a step that loads the ticket will fail. Use it for cleanup: close the worktree, cancel the run, archive the branch. ${ed}`}),ec("JIRA_ISSUE_COMMAND","Jira","Ticket comment command",ea,{description:"Fires when a comment from an allow-listed Jira account matches a command pattern, such as `/deploy`.",details:`The Jira counterpart to the GitHub issue comment command, and just as strict: an explicit list of Jira account IDs is required, and the pattern must be anchored with \`^\` and \`$\` — publishing fails otherwise. Jira identifies people by opaque account ID, not display name, so copy the ID from the user's Jira profile URL. Treat the comment body as untrusted input rather than instructions. Needs the Jira webhook. ${ed}`}),ec("JIRA_ATTACHMENT_ADDED","Jira","Attachment added",[...ea,"attachment.*"],{description:"Fires when a file is attached to a Jira ticket.",details:`Needs the Jira webhook. Seeds \`attachment.*\` with the filename, MIME type, and author. Filter on \`attachment.mimeType\` to react to one kind of upload — a crash log, a design export. ${ed}`}),ec("JIRA_ISSUE_LINKED","Jira","Ticket linked",[...ea,"link.*"],{description:"Fires when a Jira issue link is created.",details:`Needs the Jira webhook. Seeds \`link.*\` with the link type and both issue IDs. Filter on \`link.type\` to react to one relationship — "blocks", "duplicates" — rather than every link. ${ed}`}),ec("RUN_STARTED","Plans and sessions","Run started",er,{description:"Fires when an AI plan or session run begins.",details:`Every run trigger seeds the same shape — \`run.*\` plus the worktree, codebase, repository, and ticket it is attached to. Filter on \`run.kind\` to separate plans from sessions. ${ed}`}),ec("RUN_COMPLETED","Plans and sessions","Run completed",er,{description:"Fires when an AI run finishes successfully.",details:`The place to hang everything that happens after the agent is done — committing, pushing, opening a pull request, moving the ticket. Filter on \`run.kind\` to react only to plans or only to sessions. ${ed}`}),ec("RUN_QUESTION_NEEDED","Plans and sessions","Run needs an answer",er,{description:"Fires when an AI run pauses to ask a question, with the pending questions in session data.",details:`The questions arrive under \`run.questions\`, so the Answer run question step can respond without a human — the basis for unattended runs. Answer carefully: an automatic answer to a question the agent should have asked a person is how unwanted changes get made. ${ed}`}),ec("RUN_QUESTION_ANSWERED","Plans and sessions","Run question answered",er,{description:"Fires when a pending question on an AI run is answered.",details:`Fires however the answer arrived — from a person or from another workflow. Use it to record decisions, or to resume work that was gated on the answer. ${ed}`}),ec("RUN_PAUSED","Plans and sessions","Run paused",er,{description:"Fires when an AI run is paused.",details:`Covers pauses from any source, including a run that paused itself. A run needing an answer reports separately through Run needs an answer. ${ed}`}),ec("RUN_CONTINUED","Plans and sessions","Run continued",er,{description:"Fires when a paused AI run resumes.",details:`The counterpart to Run paused. Fires on each resume, so a run that stops and starts repeatedly fires it repeatedly. ${ed}`}),ec("RUN_FAILED","Plans and sessions","Run failed",er,{description:"Fires when an AI run ends in failure.",details:`The error is in the seeded run data, so a follow-up run can be pointed at what went wrong. Beware of loops — a workflow that reacts by starting another run that fails the same way will keep going. ${ed}`}),ec("RUN_CANCELLED","Plans and sessions","Run cancelled",er,{description:"Fires when an AI run is cancelled.",details:`Cancellation leaves whatever the run already wrote in the worktree, so cleanup usually means inspecting or reverting rather than assuming nothing happened. ${ed}`}),ec("RUN_PLAN_PLAYED","Plans and sessions","Plan played",er,{description:"Fires when a run is created by executing a previously completed plan.",details:`Distinguishes plan execution from an ordinary session, which Run started cannot. Lets a workflow treat planned work differently from ad-hoc work. ${ed}`}),ec("RUN_FOLLOW_UP","Plans and sessions","Run follow-up created",er,{description:"Fires when a run is created as a follow-up to another run.",details:`Does not fire for plan execution, which reports through Plan played. The parent run is in the seeded data, so a workflow can count how deep a follow-up chain has gone and stop it. ${ed}`}),ec("RUN_IMPORTED","Plans and sessions","Provider run imported",er,{description:"Fires when a run started outside this system is imported from a provider.",details:`Lets work begun in another tool pick up the same automation — labelling, ticket updates, pull requests. The run did not originate here, so its worktree and ticket links may be incomplete. ${ed}`}),ec("RUN_USAGE_THRESHOLD","Plans and sessions","Run usage threshold",er,{description:"Fires when a single run's token or cost usage crosses a threshold you set.",details:`Scoped to one run, unlike the aggregate Usage threshold. Point the threshold path at the usage figure you care about — a runaway session can then be cancelled automatically. ${eu} ${ed}`}),ec("RUN_EVENT_MATCH","Plans and sessions","Run event or tool matched",er,{description:"Fires on individual events inside an AI run, including each tool call it makes.",details:`The finest-grained run trigger, and by far the most talkative — a single run produces hundreds of events, and every one is a candidate. Always filter, on the event type or the tool name. Useful for reacting to a specific tool being used; a poor choice for anything expensive. ${ed}`}),...eg],ef=new Map(ep.map(e=>[e.kind,e])),eI=A.z.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9_-]*$/),eC=A.z.string().min(1).max(256).regex(/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_*\[\]-]+)*$/),em=A.z.record(A.z.string(),A.z.unknown()).default({}),ew=A.z.object({id:eI,kind:A.z.enum(n.WORKFLOW_TRIGGER_KINDS),name:A.z.string().min(1).max(200).optional(),position:A.z.object({x:A.z.number().finite(),y:A.z.number().finite()}),config:em}),eE=A.z.object({id:eI,kind:A.z.enum(n.WORKFLOW_STEP_KINDS),name:A.z.string().min(1).max(200).optional(),position:A.z.object({x:A.z.number().finite(),y:A.z.number().finite()}),config:em,requiredPaths:A.z.array(eC).max(100).default([]),providedPaths:A.z.array(eC).max(100).default([]),retry:A.z.object({maxAttempts:A.z.number().int().min(1).max(20).default(1),strategy:A.z.enum(["FIXED","EXPONENTIAL"]).default("EXPONENTIAL"),delaySeconds:A.z.number().int().min(1).max(86400).default(5)}).default({maxAttempts:1,strategy:"EXPONENTIAL",delaySeconds:5}),failurePolicy:A.z.enum(["FAIL","CONTINUE"]).default("FAIL")}),ey=A.z.object({id:eI,source:eI,target:eI,sourceHandle:A.z.string().min(1).max(100).default("success"),targetHandle:A.z.string().min(1).max(100).default("input")}),eB=A.z.object({format:A.z.literal(F),schemaVersion:A.z.literal(1),name:A.z.string().min(1).max(200),description:A.z.string().max(2e3).default(""),triggers:A.z.array(ew).max(100).default([]),nodes:A.z.array(eE).max(1e3).default([]),edges:A.z.array(ey).max(5e3).default([]),editor:A.z.object({viewport:A.z.object({x:A.z.number(),y:A.z.number(),zoom:A.z.number().positive()}).optional(),handleLayout:A.z.enum(["SIDES","TOP_BOTTOM"]).default("SIDES"),displayLayout:A.z.enum(["REGULAR","BASIC"]).default("REGULAR")}).default({handleLayout:"SIDES",displayLayout:"REGULAR"})});function eQ(e,A){return A.map(A=>A.replaceAll("<stepId>",e.id))}function eD(e,A){return e===A||"*"===e||e.endsWith(".*")&&A.startsWith(e.slice(0,-1))}function eb(e){return e.length?new Set([...e[0]].filter(A=>e.every(e=>e.has(A)))):new Set}function eS(e,A){return[...e].some(e=>eD(e,A))}let ek={stepPaths(e){let A=et.get(e);return{requiredPaths:A?.requiredPaths??[],providedPaths:A?.providedPaths??[]}},triggerSeedPaths:e=>ef.get(e)?.seedPaths??[]};function ev(e,A=ek){let t=new Set(e.nodes.map(({id:e})=>e)),r=new Map(e.nodes.map(e=>[e.id,e])),i=new Map,n=new Map;for(let A of e.edges)i.set(A.source,[...i.get(A.source)??[],A.target]),n.set(A.target,[...n.get(A.target)??[],A.source]);let a=new Map(e.nodes.map(e=>[e.id,0]));for(let A of e.edges)t.has(A.source)&&t.has(A.target)&&a.set(A.target,(a.get(A.target)??0)+1);let o=[...a].filter(([,e])=>0===e).map(([e])=>e),s=[];for(;o.length;){let e=o.shift();for(let A of(s.push(e),i.get(e)??[])){if(!t.has(A))continue;let e=(a.get(A)??0)-1;a.set(A,e),0===e&&o.push(A)}}let l=e=>{let A=new Set,t=[...i.get(e)??[]];for(;t.length;){let e=t.shift();A.has(e)||(A.add(e),t.push(...i.get(e)??[]))}return A},d=new Map;for(let A of[...e.triggers,...e.nodes])d.set(A.id,l(A.id));let u=new Map;for(let t of e.nodes){let e=A.stepPaths(t.kind);u.set(t.id,[...eQ(t,e.providedPaths),...t.providedPaths,`steps.${t.id}.*`])}let c=new Map,h=[];for(let t of e.triggers){let e=new Set(["workflow.*"]);for(let r of A.triggerSeedPaths(t.kind))e.add(r);for(let A of V(t.kind,t.config))e.add(A);let i=new Map;for(let a of s){if(!d.get(t.id)?.has(a))continue;let o=r.get(a),s=(n.get(a)??[]).filter(e=>e===t.id||i.has(e));if(!s.length)continue;let l=eb(s.map(A=>A===t.id?e:i.get(A))),g=c.get(a);c.set(a,g?eb([g,l]):new Set(l));let p=new Set(u.get(a)??[]),f=[...H(o.kind,"step",o.config)].filter(e=>!eS(p,e));for(let e of new Set([...eQ(o,A.stepPaths(o.kind).requiredPaths),...o.requiredPaths,...f]))eS(l,e)||h.push({nodeId:o.id,triggerId:t.id,triggerName:t.name??t.kind,path:e});let I=new Set(l);for(let e of u.get(a)??[])I.add(e);i.set(a,I)}}return{availableBefore:new Map([...c].map(([e,A])=>[e,[...A]])),provides:u,requirementViolations:h}}function eR(e,A=""){return Array.isArray(e)?e.some(e=>eR(e,A)):e&&"object"==typeof e?Object.entries(e).some(([e,A])=>eR(A,e)):"string"==typeof e&&/(token|secret|password|passwd|private.?key|api.?key|authorization)/i.test(A)&&!/(credential.?id|credential.?ids)$/i.test(A)}function eT(e){return Array.isArray(e)?e.some(eT):!!e&&"object"==typeof e&&("UNRESOLVED"===e.referenceStatus||Object.values(e).some(eT))}e.s(["WORKFLOW_SCHEMA_VERSION",0,1,"WORKFLOW_STEP_BY_KIND",0,et,"WORKFLOW_STEP_CATALOG",0,eA,"WORKFLOW_TRIGGER_CATALOG",0,ep,"computeWorkflowPathAvailability",0,ev,"emptyWorkflowDefinition",0,function(e="Untitled workflow"){return eB.parse({format:F,schemaVersion:1,name:e,description:"",triggers:[{id:"manual",kind:"MANUAL",position:{x:0,y:100},config:{}}],nodes:[],edges:[],editor:{}})},"hasWorkflowErrors",0,function(e){return e.some(({severity:e})=>"ERROR"===e)},"parseWorkflowDefinition",0,function(e){return eB.parse(e)},"resourceManualSeedPaths",0,V,"sanitizeWorkflowExportDefinition",0,function(e){let A=(e,t="")=>Array.isArray(e)?e.map(e=>A(e,t)):e&&"object"==typeof e?Object.fromEntries(Object.entries(e).map(([e,t])=>[e,A(t,e)])):"string"==typeof e&&/(token|secret|password|passwd|private.?key|api.?key|authorization)/i.test(t)&&!/(credential.?id|credential.?ids)$/i.test(t)||"string"==typeof e&&/^(?:\/|[A-Za-z]:[\\/]|\\\\)/.test(e)&&/^(?:cwd|folder|path|directory)$/i.test(t)?null:e;return eB.parse(A(e))},"validateWorkflowDefinition",0,function(e){let A=eB.safeParse(e);if(!A.success)return{definition:null,diagnostics:A.error.issues.map(e=>({severity:"ERROR",code:"SCHEMA_INVALID",message:e.message,path:e.path.join(".")}))};let t=A.data,r=[],i=new Set;for(let e of[...t.triggers,...t.nodes])i.has(e.id)&&r.push({severity:"ERROR",code:"DUPLICATE_NODE_ID",message:`Duplicate graph id ${e.id}`,nodeId:e.id}),i.add(e.id);let o=new Set;for(let e of t.edges)o.has(e.id)&&r.push({severity:"ERROR",code:"DUPLICATE_EDGE_ID",message:`Duplicate edge id ${e.id}`}),o.add(e.id),i.has(e.source)&&i.has(e.target)||r.push({severity:"ERROR",code:"EDGE_ENDPOINT_MISSING",message:`Edge ${e.id} references a missing endpoint`}),t.triggers.some(({id:A})=>A===e.target)&&r.push({severity:"ERROR",code:"TRIGGER_HAS_INPUT",message:"Triggers cannot have incoming edges",triggerId:e.target});t.triggers.length||r.push({severity:"ERROR",code:"TRIGGER_REQUIRED",message:"At least one trigger is required"}),t.nodes.length||r.push({severity:"ERROR",code:"STEP_REQUIRED",message:"At least one step is required"});let s=new Set(t.nodes.map(({id:e})=>e)),l=new Map,d=new Map;for(let e of t.edges)l.set(e.source,[...l.get(e.source)??[],e.target]),d.set(e.target,[...d.get(e.target)??[],e.source]);for(let e of t.nodes)(d.get(e.id)??[]).filter(e=>s.has(e)).length>1&&"CONTROL_JOIN"!==e.kind&&r.push({severity:"ERROR",code:"EXPLICIT_JOIN_REQUIRED",message:"Nodes with multiple incoming branches must be explicit join nodes",nodeId:e.id});let u=new Map(t.nodes.map(e=>[e.id,0]));for(let e of t.edges)s.has(e.source)&&s.has(e.target)&&u.set(e.target,(u.get(e.target)??0)+1);let c=[...u].filter(([,e])=>0===e).map(([e])=>e),h=[];for(;c.length;){let e=c.shift();for(let A of(h.push(e),l.get(e)??[])){if(!s.has(A))continue;let e=(u.get(A)??0)-1;u.set(A,e),0===e&&c.push(A)}}h.length!==t.nodes.length&&r.push({severity:"ERROR",code:"DAG_CYCLE",message:"Workflow graphs cannot contain free-form cycles"});let g=new Map,p=e=>{let A=new Set,t=[...l.get(e)??[]];for(;t.length;){let e=t.shift();A.has(e)||(A.add(e),t.push(...l.get(e)??[]))}return A};for(let e of[...t.triggers,...t.nodes])g.set(e.id,p(e.id));for(let e of t.nodes){for(let A of(t.triggers.some(A=>g.get(A.id)?.has(e.id))||r.push({severity:"ERROR",code:"UNREACHABLE_STEP",message:"Step is not reachable from a trigger",nodeId:e.id}),eR(e.config)&&r.push({severity:"ERROR",code:"SECRET_LITERAL",message:"Store secrets as credential references, not workflow literals",nodeId:e.id}),eT(e.config)&&r.push({severity:"ERROR",code:"UNRESOLVED_REFERENCE",message:"Resolve imported references before publishing",nodeId:e.id}),new Set((0,a.invalidWorkflowValueBindings)(e.config))))r.push({severity:"ERROR",code:"SESSION_BINDING_INVALID",message:A,nodeId:e.id});if("CONTROL_SUBWORKFLOW"===e.kind&&"string"!=typeof e.config.versionId&&r.push({severity:"ERROR",code:"SUBWORKFLOW_VERSION_REQUIRED",message:"Sub-workflows must pin a published version",nodeId:e.id}),"SAVED_COMMAND"===e.kind||"CUSTOM_COMMAND"===e.kind){let A=q(e.config);if(t.edges.some(A=>A.source===e.id&&"match"===A.sourceHandle)&&!A&&r.push({severity:"ERROR",code:"COMMAND_MATCH_PATTERN_REQUIRED",message:"The match connector requires an output pattern",nodeId:e.id}),A){void 0!==e.config.outputMatchMode&&"ONCE"!==e.config.outputMatchMode&&"EACH_MATCH"!==e.config.outputMatchMode&&r.push({severity:"ERROR",code:"COMMAND_MATCH_MODE_INVALID",message:"Output match behavior must be Once or Each match",nodeId:e.id}),"FIRE_AND_FORGET"===e.config.completionMode&&r.push({severity:"ERROR",code:"COMMAND_MATCH_REQUIRES_WAIT",message:"Output matching requires Wait for exit completion",nodeId:e.id});try{J(A)}catch(A){r.push({severity:"ERROR",code:"COMMAND_MATCH_PATTERN_INVALID",message:A instanceof Error?A.message:String(A),nodeId:e.id})}let i=A=>t.edges.filter(t=>t.source===e.id&&t.sourceHandle===A).map(({target:e})=>e),n=e=>{let A=new Set,r=[...e];for(;r.length;){let e=r.shift();A.has(e)||(A.add(e),r.push(...t.edges.filter(A=>A.source===e).map(({target:e})=>e)))}return A},a=n(i("match")),o=n([...i("success"),...i("failure")]);[...a].some(e=>o.has(e))&&r.push({severity:"ERROR",code:"COMMAND_MATCH_BRANCH_RECONVERGES",message:"A command match branch cannot reconverge with its success or failure branch",nodeId:e.id})}}}for(let e of t.triggers){for(let A of((l.get(e.id)??[]).length||r.push({severity:"ERROR",code:"TRIGGER_DISCONNECTED",message:"Trigger is not connected to a step",triggerId:e.id}),eR(e.config)&&r.push({severity:"ERROR",code:"SECRET_LITERAL",message:"Store secrets as credential references, not trigger literals",triggerId:e.id}),eT(e.config)&&r.push({severity:"ERROR",code:"UNRESOLVED_REFERENCE",message:"Resolve imported references before publishing",triggerId:e.id}),new Set((0,a.invalidWorkflowValueBindings)(e.config))))r.push({severity:"ERROR",code:"SESSION_BINDING_INVALID",message:A,triggerId:e.id});if((0,n.isResourceTriggerKind)(e.kind)&&!Y(e.config)&&r.push({severity:"ERROR",code:"RESOURCE_KIND_REQUIRED",message:"Resource triggers must target a single resource kind; add one trigger per kind",triggerId:e.id}),(0,n.isChoiceTriggerKind)(e.kind)){let A=j(e.config),i=Array.isArray(e.config.choices)?e.config.choices.length:0;A.length&&A.length===i||r.push({severity:"ERROR",code:"TRIGGER_CHOICES_REQUIRED",message:"Choice triggers need at least one option, each with a unique key",triggerId:e.id});let n=new Set(A.map(({key:e})=>e));for(let A of t.edges)A.source===e.id&&(n.has(A.sourceHandle)||r.push({severity:"ERROR",code:"TRIGGER_CHOICE_HANDLE_UNKNOWN",message:`Connection ${A.id} leaves an option that no longer exists`,triggerId:e.id}))}if("GITHUB_ISSUE_COMMAND"===e.kind||"JIRA_ISSUE_COMMAND"===e.kind||"GITLAB_NOTE_COMMAND"===e.kind){let A="JIRA_ISSUE_COMMAND"===e.kind,t="GITLAB_NOTE_COMMAND"===e.kind,i=A?e.config.allowedAccountIds:t?e.config.allowedUsernames:e.config.allowedLogins,n=e.config.commandPattern;(!Array.isArray(i)||!i.length||i.some(e=>"string"!=typeof e||!e.trim()))&&r.push({severity:"ERROR",code:"ISSUE_COMMAND_ALLOWLIST_REQUIRED",message:A?"Issue command triggers require an explicit Jira account ID allow-list":t?"Note command triggers require an explicit GitLab username allow-list":"Issue command triggers require an explicit GitHub login allow-list",triggerId:e.id}),"string"==typeof n&&n.startsWith("^")&&n.endsWith("$")||r.push({severity:"ERROR",code:"ISSUE_COMMAND_PATTERN_ANCHORED",message:"Issue command patterns must be anchored with ^ and $",triggerId:e.id})}}for(let e of ev(t).requirementViolations)r.push({severity:"ERROR",code:"REQUIREMENT_UNSATISFIED",message:`${e.path} is not guaranteed on the path from ${e.triggerName}`,nodeId:e.nodeId,triggerId:e.triggerId,path:e.path});for(let e=0;e<t.nodes.length;e+=1){let A=t.nodes[e],i=[...eQ(A,et.get(A.kind).providedPaths),...A.providedPaths].filter(e=>!e.startsWith(`steps.${A.id}.`));for(let n=e+1;n<t.nodes.length;n+=1){let e=t.nodes[n];if(g.get(A.id)?.has(e.id)||g.get(e.id)?.has(A.id))continue;let a=[...eQ(e,et.get(e.kind).providedPaths),...e.providedPaths].filter(A=>!A.startsWith(`steps.${e.id}.`));i.some(e=>a.some(A=>eD(e,A)||eD(A,e)))&&r.push({severity:"ERROR",code:"PARALLEL_WRITE_CONFLICT",message:`Parallel steps ${A.name??A.id} and ${e.name??e.id} can write the same session-data path`,nodeId:e.id})}}return{definition:t,diagnostics:r}},"workflowResourceKind",0,Y,"workflowTriggerChoices",0,j],388385)},269671,e=>{"use strict";var A,t=e.i(522527),r=e.i(855646),i=e.i(329736),n=e.i(736426),a=new Map,o=new Map,s=!0,l=!1;function d(e){return e.replace(/[\s,]+/g," ").trim()}function u(e){for(var A=[],t=1;t<arguments.length;t++)A[t-1]=arguments[t];"string"==typeof e&&(e=[e]);var r=e[0];return A.forEach(function(A,t){A&&"Document"===A.kind?r+=A.loc.source.body:r+=A,r+=e[t+1]}),function(e){var A=d(e);if(!a.has(A)){var t,r,u,c,h,g=(0,n.parse)(e,{experimentalFragmentVariables:l,allowLegacyFragmentVariables:l,experimentalFragmentArguments:l});if(!g||"Document"!==g.kind)throw Error("Not a valid GraphQL document.");a.set(A,((c=new Set((t=new Set,r=[],g.definitions.forEach(function(e){if("FragmentDefinition"===e.kind){var A,i=e.name.value,n=d((A=e.loc).source.body.substring(A.start,A.end)),a=o.get(i);a&&!a.has(n)?s&&console.warn("Warning: fragment with name "+i+" already exists.\ngraphql-tag enforces all fragment names across your application to be unique; read more about\nthis in the docs: http://dev.apollodata.com/core/fragments.html#unique-names"):a||o.set(i,a=new Set),a.add(n),t.has(n)||(t.add(n),r.push(e))}else r.push(e)}),u=(0,i.__assign)((0,i.__assign)({},g),{definitions:r})).definitions)).forEach(function(e){e.loc&&delete e.loc,Object.keys(e).forEach(function(A){var t=e[A];t&&"object"==typeof t&&c.add(t)})}),(h=u.loc)&&(delete h.startToken,delete h.endToken),u))}return a.get(A)}(r)}var c=u;(A=u||(u={})).gql=c,A.resetCaches=function(){a.clear(),o.clear()},A.disableFragmentWarnings=function(){s=!1},A.enableExperimentalFragmentVariables=function(){l=!0},A.disableExperimentalFragmentVariables=function(){l=!1},u.default=u;let h=[`"Values supported for action center resource."
|
|
1536
|
+
}`,{owner:a.repository.owner.login,name:a.repository.name},{requestSource:r});if(s.data.repository?.id!==e)throw new u("REPOSITORY_NOT_INSTALLED","The repository is not available to the GitHub App installation",s.githubRequestId);let l=await U(o,{owner:a.repository.owner.login,repository:a.repository.name,workflowRunId:String(a.workflowRun.databaseId),jobId:t,requestSource:r});return await this.cache.clear(),await this.audit(i,{operation:"GITHUB_ACTIONS_JOB_RERUN",repositoryId:e,checkSuiteId:A,jobId:t,githubRequestId:l.githubRequestId,outcome:"SUCCESS"}),await this.pipelineStatus.optimisticJobByCheckSuite(e,A,t),!0}catch(r){throw await this.audit(i,{operation:"GITHUB_ACTIONS_JOB_RERUN",repositoryId:e,checkSuiteId:A,jobId:t,githubRequestId:r instanceof u?r.githubRequestId:null,outcome:"FAILURE",errorCode:r instanceof u?r.code:"GITHUB_APP_REQUEST_FAILED"}),r}}},"normalizeGitHubRepositoryName",0,eQ],864637)},563629,e=>{"use strict";var A=e.i(666680),t=e.i(135475),r=e.i(751976);e.i(592299);var i=e.i(972425),n=e.i(747461),a=e.i(629097),o=e.i(852045),s=e.i(874185),l=e.i(601143),d=e.i(183291),u=e.i(714147);let c="server:github-actions-notifications",h=new Set(["failure","timed_out","startup_failure","action_required"]);function g(e){return"string"==typeof e&&e.trim()?e.trim():null}function p(e){return"number"==typeof e&&Number.isInteger(e)&&e>0?e:null}function f(e){return Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];let A=p(e.number);return A?[{number:A,url:g(e.html_url)??g(e.url)}]:[]}):[]}function I(e,A,t){let r=p(t?.id),i=p(t?.workflow_id),n=g(t?.updated_at),a=n?new Date(n):null;return r&&i&&a&&Number.isFinite(a.getTime())?{id:String(r),workflowId:String(i),runAttempt:p(t?.run_attempt)??1,name:g(t?.name)??"GitHub Actions",displayTitle:g(t?.display_title)??g(t?.name)??"Workflow run",status:g(t?.status)?.toLowerCase()??"unknown",conclusion:g(t?.conclusion)?.toLowerCase()??null,headBranch:g(t?.head_branch),headSha:g(t?.head_sha),pullRequests:f(t?.pull_requests),url:g(t?.html_url)??"",updatedAt:a,repositoryGithubId:g(A?.node_id),repositoryNameWithOwner:g(A?.full_name)??`${e.owner}/${e.repository}`,repositoryUrl:g(A?.html_url)??`https://github.com/${e.owner}/${e.repository}`,checkSuiteId:g(t?.check_suite_node_id)}:null}function C(e,A){let t=(0,u.normalizePipelineState)(e,A);return"SUCCESS"===t||"NEUTRAL"===t||"SKIPPED"===t?"IN_PROGRESS":t}function m(e,A){if(!e||!A)return null;try{let t=(0,r.compileRe2)(A,{flags:"i",label:"Jira branch regex"}).exec(e),i=(t?.[1]??t?.[0])?.trim();return i?i.toUpperCase():null}catch{return null}}e.s(["GitHubActionsNotificationsService",0,class{credentials;notifications;polling;workflowEvents;cache;pipelineStatus;timer;running;rerunRequested;constructor(e,A,t,r=!0,i,n=new a.GitHubCache,o=new d.GitHubPipelineStatusService){this.credentials=e,this.notifications=A,this.polling=t,this.workflowEvents=i,this.cache=n,this.pipelineStatus=o,this.timer=null,this.running=!1,this.rerunRequested=!1,this.polling.register({id:c,kind:"GITHUB_ACTIONS_NOTIFICATIONS",runtime:"SERVER",enabled:!1,cadenceSeconds:60,details:{mode:"DISABLED"}}),r&&queueMicrotask(()=>void this.tick())}async appConnection(){let e=await this.credentials.getJson(i.CREDENTIALS.githubAppSettings);return e?(0,n.githubAppConnectionSettings)(e):null}async recordWorkflowRunEvent(e,A){if(!this.workflowEvents||"completed"!==A.status)return;let r=await (0,t.getPrismaClient)(),[i,n]=await Promise.all([A.headBranch?r.worktree.findFirst({where:{branch:A.headBranch,missingAt:null,codebase:{repositoryId:e.id}},orderBy:{updatedAt:"desc"},select:{id:!0,folder:!0,branch:!0,baseBranchOverride:!0,headSha:!0,codebase:{select:{id:!0,folder:!0,agentId:!0,defaultBranch:!0,agent:{select:{id:!0,name:!0,hostname:!0}}}}}}):null,r.codebaseSettings.findUnique({where:{id:"default"}})]),a=m(A.headBranch,e.jiraBranchRegex??n?.defaultJiraBranchRegex??""),o=A.pullRequests[0]??null,s={repo:{id:e.id,name:e.name,owner:e.owner,url:`https://github.com/${e.owner}/${e.repository}`,canonicalOrigin:e.canonicalOrigin,displayOrigin:e.displayOrigin,defaultBranch:i?.codebase.defaultBranch??null},pipeline:{runId:A.id,workflowId:A.workflowId,name:A.name,displayTitle:A.displayTitle,status:A.status,conclusion:A.conclusion,headBranch:A.headBranch,headSha:A.headSha,pullRequests:A.pullRequests,url:A.url},...i?{worktree:{id:i.id,path:i.folder,branch:i.branch,baseBranch:i.baseBranchOverride??i.codebase.defaultBranch,headSha:i.headSha},codebase:{id:i.codebase.id,folder:i.codebase.folder,agentId:i.codebase.agentId},agent:i.codebase.agent}:{},...o?{pr:o}:{},...a?{ticket:{key:a}}:{}},l={cursorValue:`${A.id}:${A.runAttempt}:${A.conclusion??"none"}`};await this.workflowEvents.record({kind:"GITHUB_ACTIONS_RESULT",subjectKey:e.id,dedupeKey:`github-actions-trigger:${e.id}:${A.id}:${A.runAttempt}`,payload:{...s,...l,sessionData:s}});let d="success"===A.conclusion?"GITHUB_WORKFLOW_SUCCEEDED":A.conclusion&&h.has(A.conclusion)?"GITHUB_CHECK_FAILED":null;d&&await this.workflowEvents.record({kind:d,subjectKey:e.id,dedupeKey:`github-workflow-trigger:${d}:${e.id}:${A.id}:${A.runAttempt}`,payload:{...s,...l,sessionData:s}})}async observePipelineRun(e,A,t,r=!0){if(!A.repositoryGithubId||!A.headSha)return!1;let i="completed"===A.status,n=!!A.checkSuiteId;return await this.pipelineStatus.observeSnapshot({repositoryGithubId:A.repositoryGithubId,repositoryNameWithOwner:A.repositoryNameWithOwner,repositoryUrl:A.repositoryUrl,headSha:A.headSha,pipelines:[{id:A.id,name:A.name,status:(0,u.normalizePipelineState)(A.status,A.conclusion),url:A.url,checkSuiteId:A.checkSuiteId,workflowRunId:A.id,workflowId:A.workflowId,runAttempt:A.runAttempt,canRetry:i&&n&&r,retryUnavailableReason:i?n?r?null:"GITHUB_APP_NOT_CONFIGURED":"WORKFLOW_RUN_UNAVAILABLE":"NOT_COMPLETED",source:t,githubUpdatedAt:A.updatedAt}]}),!0}async observeEnhancedWebhook(e,A,t,r){let i={workflow_run:new Set(["requested","in_progress","completed"]),workflow_job:new Set(["queued","in_progress","completed"]),check_run:new Set(["created","rerequested","completed"]),check_suite:new Set(["requested","rerequested","in_progress","completed"]),status:new Set([null])};if(!i[A]?.has(t))return!1;let n=r.repository,a=g(n?.node_id),o="status"===A?g(r.sha):g((r[A]??{}).head_sha);if(!a||!o)return!1;let s=g(n?.full_name)??`${e.owner}/${e.repository}`,l=g(n?.html_url)??`https://github.com/${e.owner}/${e.repository}`;if("workflow_run"===A){let A=I(e,n,r.workflow_run);return!!A&&this.observePipelineRun(e,A,"WEBHOOK")}if("status"===A){let e,A=g(r.context);return!!A&&(await this.pipelineStatus.observeSnapshot({repositoryGithubId:a,repositoryNameWithOwner:s,repositoryUrl:l,headSha:o,pipelines:[{id:A,name:A,status:(0,u.normalizePipelineState)(g(r.state)),url:g(r.target_url),statusContext:A,source:"WEBHOOK",githubUpdatedAt:(e=g(r.updated_at)??g(r.created_at))?new Date(e):null}]}),!0)}if("check_suite"===A){let e=r.check_suite,A=g(e?.node_id);if(!e||!A)return!1;let t=e.app,i=g(e.updated_at)??g(e.completed_at)??g(e.started_at);return await this.pipelineStatus.observeSnapshot({repositoryGithubId:a,repositoryNameWithOwner:s,repositoryUrl:l,headSha:o,pipelines:[{id:A,name:g(t?.name)??"GitHub checks",status:(0,u.normalizePipelineState)(g(e.status),g(e.conclusion)),url:g(e.url),checkSuiteId:A,source:"WEBHOOK",githubUpdatedAt:i?new Date(i):null}]}),!0}if("check_run"===A){let e=r.check_run,A=e?.check_suite,t=g(A?.node_id),i=g(e?.node_id);if(!e||!t||!i)return!1;let n=g(e.completed_at)??g(e.started_at)??g(e.updated_at);return await this.pipelineStatus.observeSnapshot({repositoryGithubId:a,repositoryNameWithOwner:s,repositoryUrl:l,headSha:o,pipelines:[{id:i,name:g(e.name)??"GitHub check",status:C(g(e.status),g(e.conclusion)),url:g(e.details_url)??g(e.html_url),checkSuiteId:t,source:"WEBHOOK",githubUpdatedAt:n?new Date(n):null}]}),!0}let d=r.workflow_job,c=p(d?.run_id)?.toString()??null;if(!d||!c)return!1;let h=g(d.completed_at)??g(d.started_at)??g(d.created_at),f=h?new Date(h):null,m=Array.isArray(d.steps)?d.steps.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];let A=p(e.number);return A?[{number:A,name:g(e.name)??`Step ${A}`,status:(0,u.normalizePipelineState)(g(e.status),g(e.conclusion))}]:[]}):[],w={id:p(d.id)?.toString()??g(d.node_id)??"unknown",name:g(d.name)??"Workflow job",status:(0,u.normalizePipelineState)(g(d.status),g(d.conclusion)),url:g(d.html_url),canRetry:g(d.status)?.toLowerCase()==="completed",retryUnavailableReason:g(d.status)?.toLowerCase()==="completed"?null:"NOT_COMPLETED",steps:m,runAttempt:p(d.run_attempt)};return await this.pipelineStatus.observeSnapshot({repositoryGithubId:a,repositoryNameWithOwner:s,repositoryUrl:l,headSha:o,pipelines:[{id:c,name:g(d.workflow_name)??"GitHub Actions",status:C(g(d.status),g(d.conclusion)),url:g(d.html_url),workflowRunId:c,runAttempt:p(d.run_attempt),source:"WEBHOOK",githubUpdatedAt:f}]}),await this.pipelineStatus.observeJobs(a,c,[w],"WEBHOOK",f),!0}async recordWebhookTrigger(e,A,r,i,n){if(!this.workflowEvents)return!1;let a=n.repository??{},o=n.pull_request??{},s=n.review??{},l=n.comment??{},d=n.check_run??n.check_suite??{},u=null;if("pull_request"===A&&new Set(["opened","reopened","ready_for_review"]).has(r??"")?u="GITHUB_PR_STATE":"pull_request"===A&&"synchronize"===r?u="GITHUB_PR_SYNCHRONIZED":"pull_request"===A&&"closed"===r?u="GITHUB_PR_CLOSED":"pull_request"===A&&"labeled"===r?u="GITHUB_PR_LABEL":"pull_request_review"===A&&"submitted"===r&&g(s.state)?.toLowerCase()==="changes_requested"?u="GITHUB_REVIEW_CHANGES_REQUESTED":"pull_request_review"===A&&"submitted"===r&&g(s.state)?.toLowerCase()==="approved"?u="GITHUB_REVIEW_APPROVED":"pull_request_review_comment"===A&&"created"===r?u="GITHUB_REVIEW_COMMENT":("check_run"===A||"check_suite"===A)&&h.has(g(d.conclusion)?.toLowerCase()??"")?u="GITHUB_CHECK_FAILED":"push"===A&&g(n.ref)===`refs/heads/${g(a.default_branch)}`?u="GITHUB_PUSH_DEFAULT":"issue_comment"===A&&"created"===r&&(u="GITHUB_ISSUE_COMMAND"),!u)return!1;let c=l.user??{},f=Array.isArray(o.labels)?o.labels.flatMap(e=>{let A=e&&"object"==typeof e?g(e.name):null;return A?[A]:[]}):[],I=o.head,C=o.base,w=d.check_suite??n.check_suite??{},E=g(I?.ref),y=g(n.ref)?.replace(/^refs\/heads\//,"")??null,B=g(d.head_branch)??g(w.head_branch),Q=E??y??B,D=await (0,t.getPrismaClient)(),b=await D.codebaseSettings.findUnique({where:{id:"default"}}),S=m(Q,e.jiraBranchRegex??b?.defaultJiraBranchRegex??""),k=Q?await D.worktree.findFirst({where:{branch:Q,primary:!1,missingAt:null,codebase:{repositoryId:e.id}},orderBy:{updatedAt:"desc"},select:{id:!0,folder:!0,branch:!0,baseBranchOverride:!0,headSha:!0,pushStatus:!0,hasStagedChanges:!0,hasUnstagedChanges:!0,codebase:{select:{id:!0,folder:!0,agentId:!0,branch:!0,headSha:!0,defaultBranch:!0,agent:{select:{id:!0,name:!0,hostname:!0}}}}}}):null,v={repo:{id:e.id,name:e.name,owner:e.owner,url:g(a.html_url),canonicalOrigin:e.canonicalOrigin,displayOrigin:g(a.full_name)??e.displayOrigin,defaultBranch:g(a.default_branch)},pr:{number:p(o.number)??p(n.issue?.number),url:g(o.html_url),state:g(o.state)?.toUpperCase()??null,merged:!0===o.merged,labels:f,title:g(o.title),isDraft:!0===o.draft,headBranch:E,headSha:g(I?.sha),baseBranch:g(C?.ref),reviewDecision:g(s.state)?.toUpperCase()??null},pipeline:{checkSuiteId:p(d.id)?.toString()??null,status:g(d.status),conclusion:g(d.conclusion),headBranch:B,headSha:g(d.head_sha)??g(w.head_sha)},comment:{id:p(l.id)?.toString()??null,body:g(l.body)??"",author:{login:g(c.login)}},push:{ref:g(n.ref),before:g(n.before),after:g(n.after)},...k?{worktree:{id:k.id,path:k.folder,branch:k.branch,baseBranch:k.baseBranchOverride??k.codebase.defaultBranch,headSha:k.headSha,pushStatus:k.pushStatus,dirty:k.hasStagedChanges||k.hasUnstagedChanges},codebase:{id:k.codebase.id,folder:k.codebase.folder,agentId:k.codebase.agentId,branch:k.codebase.branch,headSha:k.codebase.headSha},agent:k.codebase.agent}:{},...S?{ticket:{key:S}}:{}};return await this.workflowEvents.record({kind:u,subjectKey:e.id,dedupeKey:`github-webhook-trigger:${i}:${u}`,payload:{...v,sessionData:v,cursorValue:`${i}:${u}`,webhook:{event:A,action:r,deliveryId:i}}}),!0}schedule(e){this.timer&&clearTimeout(this.timer);let A=1e3*Math.max(30,e);this.timer=setTimeout(()=>void this.tick(),A),this.timer.unref(),this.polling.schedule(c,new Date(Date.now()+A))}configurationChanged(){if(this.running){this.rerunRequested=!0;return}this.timer&&clearTimeout(this.timer),this.timer=null,queueMicrotask(()=>void this.tick())}async tick(){if(this.running)return;this.running=!0;let e=60;try{let A=await (0,t.getPrismaClient)(),[r,n,a,o,s]=await Promise.all([A.gitHubSettings.upsert({where:{id:"default"},create:{id:"default"},update:{}}),A.gitHubAppSettings.findUnique({where:{id:"default"}}),this.appConnection(),this.credentials.isConfigured(i.CREDENTIALS.githubPersonalAccessToken),this.credentials.isConfigured(i.CREDENTIALS.githubAppWebhookSecret)]);if(e=r.actionsNotificationPollIntervalSeconds,a?.webhookUrl&&n?.webhookConfiguredAt&&s)return void this.polling.configure(c,{enabled:!1,cadenceSeconds:e,details:{mode:"WEBHOOK"}});if(!o)return void this.polling.configure(c,{enabled:!1,cadenceSeconds:e,details:{mode:"DISABLED",reason:"GITHUB_TOKEN_REQUIRED"}});this.polling.configure(c,{enabled:!0,cadenceSeconds:e,details:{mode:"POLLING"}}),await this.polling.run(c,()=>this.pollRepositories(),e=>e)}catch{}finally{this.running=!1,this.rerunRequested?(this.rerunRequested=!1,queueMicrotask(()=>void this.tick())):this.schedule(e)}}async repositories(){return(await (await (0,t.getPrismaClient)()).codebaseRepository.findMany({orderBy:{name:"asc"},select:{id:!0,name:!0,canonicalOrigin:!0,displayOrigin:!0,jiraBranchRegex:!0}})).flatMap(e=>{let A=/^github\.com\/([^/]+)\/([^/]+)$/i.exec(e.canonicalOrigin.trim());return A?.[1]&&A[2]?[{id:e.id,name:e.name,owner:A[1],repository:A[2],canonicalOrigin:e.canonicalOrigin,displayOrigin:e.displayOrigin,jiraBranchRegex:e.jiraBranchRegex}]:[]})}async fetchRuns(e,A,t){let r=[];for(let i=1;;i+=1){let n,a=`${o.GITHUB_API_BASE_URL}/repos/${encodeURIComponent(e.owner)}/${encodeURIComponent(e.repository)}/actions/runs?per_page=100&page=${i}`,d=Date.now(),u=e=>this.cache.recordRestCall({authentication:"PAT",method:"GET",endpoint:a,operation:l.GITHUB_REST_OPERATIONS.actions.listWorkflowRunsForRepo,requestSource:"ACTIONS_NOTIFICATIONS",durationMs:Date.now()-d,...e}).catch(()=>void 0);try{n=await fetch(a,{headers:{accept:"application/vnd.github+json",authorization:`Bearer ${A}`,"user-agent":"ai-development-environment","x-github-api-version":"2022-11-28"},cache:"no-store"})}catch(A){let e=A instanceof Error?A.message:String(A);throw await u({error:e}),A}let c=await (0,s.observeGitHubRateLimit)("PAT",n),h=await n.json().catch(()=>null);if(!n.ok||!Array.isArray(h?.workflow_runs)){let A=h?.message||`GitHub returned HTTP ${n.status} while polling ${e.owner}/${e.repository}`;throw await u({statusCode:n.status,error:A,rateLimit:c}),Error(A)}await u({statusCode:n.status,rateLimit:c});let I=h.workflow_runs.flatMap(A=>{let t=p(A.id),r=p(A.workflow_id),i=g(A.updated_at),n=i?new Date(i):null,a=A.repository;return t&&r&&n&&Number.isFinite(n.getTime())?[{id:String(t),workflowId:String(r),runAttempt:p(A.run_attempt)??1,name:g(A.name)??"GitHub Actions",displayTitle:g(A.display_title)??g(A.name)??"Workflow run",status:g(A.status)?.toLowerCase()??"unknown",conclusion:g(A.conclusion)?.toLowerCase()??null,headBranch:g(A.head_branch),headSha:g(A.head_sha),pullRequests:f(A.pull_requests),url:g(A.html_url)??"",updatedAt:n,repositoryGithubId:g(a?.node_id),repositoryNameWithOwner:g(a?.full_name)??`${e.owner}/${e.repository}`,repositoryUrl:g(a?.html_url)??`https://github.com/${e.owner}/${e.repository}`,checkSuiteId:g(A.check_suite_node_id)}]:[]});if(r.push(...I),!t||h.workflow_runs.length<100||I.some(e=>e.updatedAt<=t))return r}}async worktreeContext(e,A,t){return t?e.worktree.findFirst({where:{branch:t,missingAt:null,codebase:{repositoryId:A}},orderBy:{updatedAt:"desc"},select:{id:!0,highlightColor:!0}}):null}async observeRun(e,t,r,i,n){var a;let o=new Date,s="success"===(a=r.conclusion)?"GITHUB_ACTIONS_SUCCEEDED":a&&h.has(a)?"GITHUB_ACTIONS_FAILED":null,l=await e.gitHubWorkflowRunObservation.findUnique({where:{codebaseRepositoryId_workflowRunId_runAttempt:{codebaseRepositoryId:t.id,workflowRunId:r.id,runAttempt:r.runAttempt}}});if(await e.gitHubWorkflowRunObservation.upsert({where:{codebaseRepositoryId_workflowRunId_runAttempt:{codebaseRepositoryId:t.id,workflowRunId:r.id,runAttempt:r.runAttempt}},create:{id:(0,A.randomUUID)(),codebaseRepositoryId:t.id,workflowRunId:r.id,runAttempt:r.runAttempt,workflowId:r.workflowId,status:r.status,conclusion:r.conclusion,githubUpdatedAt:r.updatedAt,source:i,lastObservedAt:o},update:{workflowId:r.workflowId,status:r.status,conclusion:r.conclusion,githubUpdatedAt:r.updatedAt,source:i,lastObservedAt:o}}),!(l?"completed"!==l.status||l.conclusion!==r.conclusion:n)||!s||"completed"!==r.status||l?.notifiedAt)return null;let d=await this.worktreeContext(e,t.id,r.headBranch),u=new URLSearchParams({repository:t.id});r.headBranch&&u.set("branch",r.headBranch),u.set("pipeline",r.workflowId);let c=await this.notifications.recordInTransaction(e,{dedupeKey:`github-actions:${t.id}:${r.id}:${r.runAttempt}`,typeKey:s,title:"GITHUB_ACTIONS_SUCCEEDED"===s?"GitHub Actions succeeded":"GitHub Actions failed",body:[t.name,r.name,r.headBranch].filter(e=>!!e).join(" · "),href:`/actions?${u.toString()}`,resourceKind:"GITHUB_WORKFLOW_RUN",resourceId:`${t.id}:${r.id}:${r.runAttempt}`,worktreeId:d?.id??null,highlightColor:d?.highlightColor??null});return await e.gitHubWorkflowRunObservation.update({where:{codebaseRepositoryId_workflowRunId_runAttempt:{codebaseRepositoryId:t.id,workflowRunId:r.id,runAttempt:r.runAttempt}},data:{notifiedAt:o}}),c}async pollRepository(e,A,r){let i=await (0,t.getPrismaClient)(),n=new Date,a=await i.gitHubActionsPollingState.findUnique({where:{codebaseRepositoryId:e.id}});await i.gitHubActionsPollingState.upsert({where:{codebaseRepositoryId:e.id},create:{codebaseRepositoryId:e.id,initializedAt:n,lastPollStartedAt:n},update:{lastPollStartedAt:n}});try{let t=await this.fetchRuns(e,A,a?a.lastPollSucceededAt??a.initializedAt:null),n=[];return await i.$transaction(async A=>{for(let r of t){let t=await this.observeRun(A,e,r,"POLL",!!(a&&r.updatedAt>(a.lastPollSucceededAt??a.initializedAt)));t&&n.push(t)}let r=new Date;await A.gitHubActionsPollingState.update({where:{codebaseRepositoryId:e.id},data:{lastPollCompletedAt:r,lastPollSucceededAt:r,lastError:null}})}),n.forEach(e=>this.notifications.created(e)),await Promise.allSettled(t.flatMap(A=>[this.observePipelineRun(e,A,"REST",r),this.recordWorkflowRunEvent(e,A)])),n.length}catch(A){throw await i.gitHubActionsPollingState.update({where:{codebaseRepositoryId:e.id},data:{lastPollCompletedAt:new Date,lastError:A instanceof Error?A.message:String(A)}}),A}}async pollRepositories(){let e=await this.credentials.getText(i.CREDENTIALS.githubPersonalAccessToken);if(!e)throw Error("GitHub personal access token is unavailable");let[A,r,n]=await Promise.all([this.repositories(),(await (0,t.getPrismaClient)()).gitHubAppSettings.findUnique({where:{id:"default"},select:{id:!0}}),this.credentials.isConfigured(i.CREDENTIALS.githubAppPrivateKey)]),a=!!(r&&n),o=await Promise.allSettled(A.map(A=>this.pollRepository(A,e,a))),s=o.filter(e=>"rejected"===e.status),l=o.reduce((e,A)=>e+("fulfilled"===A.status?A.value:0),0);if(await this.prune(),s.length===A.length&&A.length>0)throw s[0].reason;return{mode:"POLLING",repositories:A.length,failures:s.length,notificationsCreated:l}}async prune(){let e=new Date(Date.now()-2592e6),A=await (0,t.getPrismaClient)();await Promise.all([A.gitHubWorkflowRunObservation.deleteMany({where:{lastObservedAt:{lt:e}}}),A.gitHubWebhookDelivery.deleteMany({where:{receivedAt:{lt:e}}})])}async handleWebhook(e){var r,n;let a,o,s=await this.credentials.getText(i.CREDENTIALS.githubAppWebhookSecret);if(!s)throw Error("GitHub webhook is not configured");if(!e.signature?.startsWith("sha256="))throw Error("GitHub webhook signature is missing");if(r=`sha256=${(0,A.createHmac)("sha256",s).update(e.body).digest("hex")}`,n=e.signature,a=Buffer.from(r),o=Buffer.from(n),!(a.length===o.length&&(0,A.timingSafeEqual)(a,o)))throw Error("GitHub webhook signature is invalid");if(!e.deliveryId?.trim())throw Error("GitHub delivery ID is missing");let l=await (0,t.getPrismaClient)(),d=e.deliveryId.trim();try{await l.gitHubWebhookDelivery.create({data:{deliveryId:d,event:e.event??"unknown",outcome:"RECEIVED"}})}catch(A){if("object"==typeof A&&null!==A&&"code"in A&&"P2002"===A.code){if(0===(await l.gitHubWebhookDelivery.updateMany({where:{deliveryId:d,outcome:{notIn:["PROCESSED","IGNORED"]}},data:{event:e.event??"unknown",action:null,repositoryName:null,workflowRunId:null,outcome:"RECEIVED",error:null,receivedAt:new Date,processedAt:null}})).count)return{outcome:"DUPLICATE",notificationCreated:!1}}else throw A}let u=async(e,A=null)=>{await l.gitHubWebhookDelivery.update({where:{deliveryId:d},data:{outcome:e,error:A,processedAt:new Date}})};try{let A;try{A=JSON.parse(Buffer.from(e.body).toString("utf8"))}catch{throw Error("GitHub webhook payload is invalid JSON")}let t=g(A.action),r=A.repository,i=A.workflow_run;if(await l.gitHubWebhookDelivery.update({where:{deliveryId:d},data:{action:t,repositoryName:g(r?.full_name),workflowRunId:p(i?.id)?.toString()??null}}),"workflow_run"!==e.event||"completed"!==t){let[i,n]=await Promise.all([l.gitHubAppSettings.findUnique({where:{id:"default"}}),this.appConnection()]),a=A.installation;if(!i||!n||String(p(a?.id)??"")!==n.installationId)return await u("IGNORED","Installation does not match configured App"),{outcome:"IGNORED",notificationCreated:!1};let o=g(r?.full_name),s=o?(await this.repositories()).find(e=>`${e.owner}/${e.repository}`.toLowerCase()===o.toLowerCase()):null;if(!s)return await u("IGNORED","Repository is not registered"),{outcome:"IGNORED",notificationCreated:!1};let c=e.event??"unknown",[h,f]=await Promise.all([!!i.enhancedPipelineWebhooksEnabled&&this.observeEnhancedWebhook(s,c,t,A),this.recordWebhookTrigger(s,c,t,d,A)]),I=h||f;return await u(I?"PROCESSED":"IGNORED"),{outcome:I?"PROCESSED":"IGNORED",notificationCreated:!1}}let[n,a]=await Promise.all([l.gitHubAppSettings.findUnique({where:{id:"default"}}),this.appConnection()]),o=A.installation;if(!n||!a||String(p(o?.id)??"")!==a.installationId)return await u("IGNORED","Installation does not match configured App"),{outcome:"IGNORED",notificationCreated:!1};let s=g(r?.full_name),h=p(i?.id),f=p(i?.workflow_id),C=g(i?.updated_at);if(!s||!h||!f||!C)throw Error("GitHub workflow_run payload is incomplete");let m=(await this.repositories()).find(e=>`${e.owner}/${e.repository}`.toLowerCase()===s.toLowerCase());if(!m)return await u("IGNORED","Repository is not registered"),{outcome:"IGNORED",notificationCreated:!1};let w=I(m,r,i);if(!w)throw Error("GitHub workflow_run payload is incomplete");let E=null;return await l.$transaction(async e=>{E=await this.observeRun(e,m,w,"WEBHOOK",!0)}),this.notifications.created(E),await this.observePipelineRun(m,w,"WEBHOOK"),await this.recordWorkflowRunEvent(m,w),await u("PROCESSED"),this.polling.configure(c,{enabled:!1,details:{mode:"WEBHOOK",lastDeliveryId:d,lastDeliveryAt:new Date().toISOString()}}),this.prune().catch(()=>void 0),{outcome:"PROCESSED",notificationCreated:!!E}}catch(A){let e=A instanceof Error?A.message:String(A);throw await u("ERROR",e),A}}}])},253992,e=>{"use strict";e.i(864637),e.i(563629),e.i(514616),e.i(183291),e.s([])},429047,e=>{"use strict";let A=new Set(["QUEUED","PREPARING","RUNNING"]);e.s(["buildOutOfDate",0,function(e){let t;if(A.has(e.status)||!e.worktree||(e.worktree._count?.builds??0)>0||e.finishedAt&&(!e.worktree.lastCheckedAt||e.worktree.lastCheckedAt<e.finishedAt))return!1;try{t=JSON.parse(e.snapshotJson)}catch{return!1}if(!t||"object"!=typeof t||Array.isArray(t))return!1;let r=t.worktree;if(!r||"object"!=typeof r||Array.isArray(r))return!1;if("string"==typeof r.codeStateHash&&e.worktree.codeStateHash)return r.codeStateHash!==e.worktree.codeStateHash;if("string"==typeof r.headSha&&e.worktree.headSha!==r.headSha)return!0;if("boolean"==typeof r.hasStagedChanges){if(r.hasStagedChanges!==e.worktree.hasStagedChanges)return!0}else if(e.worktree.hasStagedChanges)return!0;return"boolean"==typeof r.hasUnstagedChanges?r.hasUnstagedChanges!==e.worktree.hasUnstagedChanges:e.worktree.hasUnstagedChanges}])},808331,e=>{"use strict";var A=e.i(666680),t=e.i(246479),r=e.i(898912),i=e.i(969068);let n=new Set([429,500,503]);async function a(e){await new Promise(A=>setTimeout(A,e))}e.s(["ApnsClient",0,class{sessionFactory;sessions;jwtCache;constructor(e=t.connect){this.sessionFactory=e,this.sessions=new Map,this.jwtCache=new Map}close(){for(let e of this.sessions.values())e.close();this.sessions.clear()}session(e,A){let t="TOKEN"===A.kind?`token:${A.teamId}:${A.keyId}`:`certificate:${A.fingerprint}`,r=`${e}:${t}`,i=this.sessions.get(r);if(i&&!i.closed&&!i.destroyed)return i;let n="CERTIFICATE"===A.kind?{pfx:Buffer.from(A.p12Base64,"base64"),passphrase:A.passphrase}:{},a=this.sessionFactory("SANDBOX"===e?"https://api.sandbox.push.apple.com":"https://api.push.apple.com",n);return a.on("error",()=>{this.sessions.get(r)===a&&this.sessions.delete(r)}),a.on("close",()=>{this.sessions.get(r)===a&&this.sessions.delete(r)}),this.sessions.set(r,a),a}async authorization(e){let t;if("CERTIFICATE"===e.kind)return null;let n=`${e.teamId}:${e.keyId}:${(0,A.createHash)("sha256").update(e.privateKey).digest("hex")}`,a=this.jwtCache.get(n);if(a&&Date.now()-a.createdAt<3e6)return`bearer ${a.token}`;try{t=await (0,r.importPKCS8)(e.privateKey,"ES256")}catch{throw Error("The APNs .p8 key must be an ES256 PKCS#8 private key")}let o=await new i.SignJWT({}).setProtectedHeader({alg:"ES256",kid:e.keyId}).setIssuer(e.teamId).setIssuedAt().sign(t);return this.jwtCache.set(n,{token:o,createdAt:Date.now()}),`bearer ${o}`}async requestOnce(e){let A=await this.authorization(e.authentication),r=this.session(e.environment,e.authentication);return new Promise((i,n)=>{let a=r.request({[t.constants.HTTP2_HEADER_METHOD]:e.method??"POST",[t.constants.HTTP2_HEADER_PATH]:e.path,[t.constants.HTTP2_HEADER_SCHEME]:"https","content-type":"application/json",...A?{authorization:A}:{},...e.headers}),o={},s="";a.setEncoding("utf8"),a.on("response",e=>{o=e}),a.on("data",e=>{(s+=e).length>65536&&a.close(t.constants.NGHTTP2_CANCEL)}),a.on("error",n),a.on("end",()=>{let e=o[t.constants.HTTP2_HEADER_STATUS];i({status:Number(Array.isArray(e)?e[0]:e)||0,body:s,headers:o})}),a.setTimeout(2e4,()=>{a.close(t.constants.NGHTTP2_CANCEL),n(Error("APNs request timed out"))}),a.end(JSON.stringify(e.payload))})}async send(e){if(!e.deviceToken&&!e.broadcastTopic)throw Error("An APNs device token or broadcast topic is required");let t=e.deviceToken?`/3/device/${e.deviceToken.toLowerCase()}`:`/4/broadcasts/apps/${encodeURIComponent(e.broadcastTopic)}`,r=Date.now(),i=0;for(;;){let o;try{o=await this.requestOnce({...e,path:t})}catch(e){if(i>=3)throw e;await a(Math.min(4e3,250*2**i)),i+=1;continue}let s={};try{s=o.body?JSON.parse(o.body):{}}catch{s={}}if(n.has(o.status)&&i<3){await a(function(e,A){let t=Array.isArray(e)?e[0]:e;if(t){let e=Number(t);if(Number.isFinite(e))return Math.min(3e4,1e3*e);let A=Date.parse(t);if(Number.isFinite(A))return Math.max(0,Math.min(3e4,A-Date.now()))}return Math.min(4e3,250*2**A)}(o.headers["retry-after"],i)),i+=1;continue}let l=o.headers["apns-id"];return{status:o.status,reason:s.reason??null,timestamp:"number"==typeof s.timestamp?new Date(s.timestamp):null,apnsId:(Array.isArray(l)?l[0]:l)??e.headers["apns-id"]??(0,A.randomUUID)(),attempts:i+1,durationMs:Date.now()-r}}}async createBroadcastChannel(e){let A=await this.requestOnce({environment:e.environment,authentication:e.authentication,path:`/4/broadcasts/apps/${encodeURIComponent(e.bundleId)}`,payload:{"channel-storage-policy":+("NO_STORAGE"!==e.storagePolicy)},headers:{"apns-topic":`${e.bundleId}.push-type.liveactivity`,"apns-push-type":"liveactivity"}}),t=A.headers["apns-channel-id"],r=Array.isArray(t)?t[0]:t;if(![200,201].includes(A.status)||!r)throw Error(`APNs could not create the broadcast channel (HTTP ${A.status})`);return r}async deleteBroadcastChannel(e){let A=await this.requestOnce({environment:e.environment,authentication:e.authentication,method:"DELETE",path:`/4/broadcasts/apps/${encodeURIComponent(e.bundleId)}`,payload:{},headers:{"apns-topic":`${e.bundleId}.push-type.liveactivity`,"apns-push-type":"liveactivity","apns-channel-id":e.channelId}});if(![200,204].includes(A.status))throw Error(`APNs could not delete the broadcast channel (HTTP ${A.status})`)}}])},683832,e=>{"use strict";let A=new Set(["alert","background","complication","controls","fileprovider","liveactivity","location","mdm","pushtotalk","voip","widgets"]),t=/^[A-Za-z0-9][A-Za-z0-9.-]{0,254}$/;function r(e,A){if(!e||"object"!=typeof e||Array.isArray(e))throw Error(`${A} must be an object`);return e}function i(e,A,t){if("string"!=typeof e||!e.trim())throw Error(`${A} is required`);let r=e.trim();if(r.length>t||r.includes("\0"))throw Error(`${A} is invalid`);return r}function n(e,A,t){return null==e||""===e?null:i(e,A,t)}function a(e,A){let t;if("HEX"===A){let A=e.replace(/[\s<>]/g,"");if(!/^[A-Fa-f0-9]{64}$/.test(A))throw Error("token must contain exactly 32 bytes of hexadecimal data");t=Buffer.from(A,"hex")}else{let A=e.trim();if(!/^[A-Za-z0-9+/_-]+={0,2}$/.test(A))throw Error("token is not valid Base64");try{t=Buffer.from(A.replaceAll("-","+").replaceAll("_","/"),"base64")}catch{throw Error("token is not valid Base64")}if(t.toString("base64").replace(/=+$/,"")!==A.replaceAll("-","+").replaceAll("_","/").replace(/=+$/,""))throw Error("token is not valid Base64")}if(32!==t.length)throw Error("token must decode to exactly 32 bytes");return t.toString("hex").toUpperCase()}e.s(["normalizeDeviceToken",0,a,"parseApnsRegistrationInput",0,function(e){let o=r(e,"registration"),s=new Set(["clientRegistrationId","token","tokenEncoding","topic","environment","supportedPushTypes","displayName","deviceModel","osVersion","appVersion","appBuild","locale","pushMagic"]),l=Object.keys(o).find(e=>!s.has(e));if(l)throw Error(`Unexpected registration field: ${l}`);let d=i(o.tokenEncoding,"tokenEncoding",10);if("HEX"!==d&&"BASE64"!==d)throw Error("tokenEncoding must be HEX or BASE64");let u=i(o.environment,"environment",20);if("SANDBOX"!==u&&"PRODUCTION"!==u)throw Error("environment must be SANDBOX or PRODUCTION");let c=i(o.topic,"topic",255);if(!t.test(c))throw Error("topic is invalid");if(!Array.isArray(o.supportedPushTypes)||!o.supportedPushTypes.length)throw Error("supportedPushTypes must contain at least one push type");let h=[...new Set(o.supportedPushTypes.map(e=>{if("string"!=typeof e||!A.has(e))throw Error(`Unsupported APNs push type: ${String(e)}`);return e}))],g=n(o.pushMagic,"pushMagic",500);if(h.includes("mdm")&&!g)throw Error("pushMagic is required when MDM is supported");return{clientRegistrationId:i(o.clientRegistrationId,"clientRegistrationId",200),token:a(i(o.token,"token",1024),d),tokenEncoding:d,topic:c,environment:u,supportedPushTypes:h,displayName:i(o.displayName,"displayName",120),deviceModel:n(o.deviceModel,"deviceModel",120),osVersion:n(o.osVersion,"osVersion",50),appVersion:n(o.appVersion,"appVersion",50),appBuild:n(o.appBuild,"appBuild",50),locale:n(o.locale,"locale",35),pushMagic:g}},"validatePushEditor",0,function(e){let a,o=r(e,"push editor"),s=i(o.pushType,"pushType",30);if(!A.has(s))throw Error("pushType is unsupported");let l=r(o.headers??{},"headers"),d=r(o.aps??{},"aps"),u=r(o.custom??{},"custom"),c=n(o.credentialId,"credentialId",100),h=Number(l.priority??("background"===s?5:10));if(![1,5,10].includes(h))throw Error("APNs priority must be 1, 5, or 10");if("background"===s&&5!==h)throw Error("Background notifications require priority 5");if(["voip","mdm","pushtotalk"].includes(s)&&10!==h)throw Error(`${s} notifications require priority 10`);if(1===h&&"location"!==s)throw Error("Priority 1 is supported only for location notifications");let g=i(l.topic,"topic",255);if(!t.test(g))throw Error("topic is invalid");let p={complication:".complication",fileprovider:".pushkit.fileprovider",liveactivity:".push-type.liveactivity",location:".location-query",pushtotalk:".voip-ptt",voip:".voip",widgets:".push-type.widgets",controls:".push-type.controls"}[s];if(p&&!g.endsWith(p))throw Error(`${s} notifications require a topic ending in ${p}`);if("mdm"===s){if(!c)throw Error("MDM requires a certificate credential");if(Object.keys(d).length)throw Error("MDM payloads cannot contain aps");if(Object.keys(u).length)throw Error("MDM payloads cannot contain custom root fields");a={mdm:"__PUSH_MAGIC__"}}else{let e={...d},A=e["relevance-score"];if(void 0!==A&&("number"!=typeof A||A<0||A>1))throw Error("aps.relevance-score must be between 0 and 1");let t=e.badge;if(void 0!==t&&("number"!=typeof t||!Number.isInteger(t)||t<0))throw Error("aps.badge must be a non-negative integer");let i=e["interruption-level"];if(void 0!==i&&!["passive","active","time-sensitive","critical"].includes(String(i)))throw Error("aps.interruption-level is invalid");let n=e.sound;if(n&&"object"==typeof n&&!Array.isArray(n)){let e=n.volume;if("number"!=typeof e||!Number.isFinite(e)||e<0||e>1)throw Error("Critical sound volume must be between 0 and 1")}if("background"===s){for(let A of["alert","badge","sound"])if(void 0!==e[A])throw Error(`Background notifications cannot contain aps.${A}`);e["content-available"]=1}if("alert"===s&&!Object.keys(e).length)throw Error("Alert notifications require at least one aps field");if("liveactivity"===s){let A=r(o.liveActivity??{},"liveActivity");if(!Number.isInteger(A.timestamp))throw Error("Live Activity timestamp must be an integer Unix timestamp");if(!["start","update","end"].includes(String(A.event)))throw Error("Live Activity event must be start, update, or end");Object.assign(e,A)}a={...u,aps:e}}let f=Buffer.byteLength(JSON.stringify(a)),I="voip"===s?5120:4096;if(f>I)throw Error(`Payload is ${f} bytes; ${s} allows ${I}`);let C={"apns-push-type":s,"apns-topic":g,"apns-priority":String(h)};for(let[e,A]of[["apns-id",l.id],["apns-expiration",l.expiration],["apns-collapse-id",l.collapseId],["apns-channel-id",l.broadcastChannelId]])null!=A&&""!==A&&(C[e]=i(A,e,"apns-collapse-id"===e?64:200));if(C["apns-id"]&&!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(C["apns-id"]))throw Error("apns-id must be a UUID");if(C["apns-expiration"]&&(!/^\d+$/.test(C["apns-expiration"])||0>Number(C["apns-expiration"])))throw Error("apns-expiration must be a non-negative Unix timestamp");return{editor:{pushType:s,headers:l,aps:d,custom:u,liveActivity:"liveactivity"===s?r(o.liveActivity??{},"liveActivity"):null,credentialId:c},payload:a,headers:C,byteLength:f}}])},286078,e=>{"use strict";var A=e.i(666680),t=e.i(685560),r=e.i(898912),i=e.i(135475);e.i(592299);var n=e.i(747461),a=e.i(972425),o=e.i(863568),s=e.i(848201),l=e.i(808331),d=e.i(683832);let u="default",c=["DEVICES","ALL","DIRECT","BROADCAST"],h="server:apns-recovery";function g(e){return(0,A.createHash)("sha256").update(e).digest("hex").toUpperCase()}function p(e,r){let i;try{i=(0,t.createSecureContext)({pfx:e,passphrase:r})}catch{throw Error("The .p12 file or passphrase is invalid")}let n=i.context.getCertificate();if(!n?.length)throw Error("The .p12 file does not contain a leaf certificate");let a=new A.X509Certificate(n),o=new Date(a.validTo);if(Number.isNaN(o.getTime()))throw Error("The .p12 certificate expiration date is invalid");return{expiresAt:o,fingerprint:a.fingerprint256.replaceAll(":","").toUpperCase()}}function f(e){return JSON.parse(e)}function I(e){try{let A=JSON.parse(e);return Array.isArray(A)?A.filter(e=>"string"==typeof e):[]}catch{return[]}}function C(e,A,t=200){let r=e.trim();if(!r||r.length>t||r.includes("\0"))throw Error(`${A} is required or invalid`);return r}let m=Promise.resolve();async function w(e){let A,t=m;m=new Promise(e=>{A=e}),await t;try{return await e()}finally{A()}}e.s(["PushNotificationsService",0,class{client;credentials;polling;async storedTokenSettings(){return(0,n.readConnectionSettings)(this.credentials,a.CREDENTIALS.apnsTokenSettings,n.apnsTokenConnectionSettings)}async storedCertificateCatalog(){return(0,n.readConnectionSettings)(this.credentials,a.CREDENTIALS.apnsCertificateCatalog,n.apnsCertificateCatalog)}recoveryStarted;activeBatchIds;constructor(e=new l.ApnsClient,A=new o.CredentialService,t){this.client=e,this.credentials=A,this.polling=t,this.recoveryStarted=!1,this.activeBatchIds=new Set,this.polling?.register({id:h,kind:"APNS_RECOVERY",runtime:"SERVER",enabled:!0,cadenceSeconds:30,details:{}}),queueMicrotask(()=>void this.pollRecovery()),setInterval(()=>void this.pollRecovery(),3e4).unref()}async pollRecovery(){this.polling?.schedule(h,new Date(Date.now()+3e4));try{this.polling?await this.polling.run(h,()=>this.recover(),e=>e):await this.recover()}catch{}}changed(){s.agentEventBus.publish(s.PUSH_NOTIFICATIONS_CHANGED_TOPIC,{changed:!0})}subscribe(){return s.agentEventBus.iterate(s.PUSH_NOTIFICATIONS_CHANGED_TOPIC)}async register(e,A){let t=(0,d.parseApnsRegistrationInput)(e);return this.registerValidated(t,A)}async registerValidated(e,t){let r=await (0,i.getPrismaClient)(),n=g(e.token),a=new Date,o={clientRegistrationId:e.clientRegistrationId,topic:e.topic,environment:e.environment},s=await r.$transaction(async r=>{let i=await r.apnsRegistration.findUnique({where:{clientRegistrationId_topic_environment:o}}),s=await r.apnsRegistration.findUnique({where:{tokenHash_topic_environment:{tokenHash:n,topic:e.topic,environment:e.environment}}});s&&s.id!==i?.id&&await r.apnsRegistration.update({where:{id:s.id},data:{token:"",tokenHash:`REASSIGNED:${s.id}:${s.tokenHash}`,status:"INACTIVE",invalidatedAt:a,lastFailureReason:"TOKEN_REASSIGNED",lastFailureAt:a}});let l={token:e.token,tokenHash:n,pushTypesJson:JSON.stringify(e.supportedPushTypes),displayName:e.displayName,deviceModel:e.deviceModel,osVersion:e.osVersion,appVersion:e.appVersion,appBuild:e.appBuild,locale:e.locale,pushMagic:e.pushMagic,lastIpAddress:t,status:"ACTIVE",invalidatedAt:null,lastFailureReason:null,lastFailureAt:null,lastRegisteredAt:a};return{registration:i?await r.apnsRegistration.update({where:{id:i.id},data:l}):await r.apnsRegistration.create({data:{id:(0,A.randomUUID)(),...o,...l}}),created:!i}});return this.changed(),s}async registrations(){let e=await (0,i.getPrismaClient)();return(await e.apnsRegistration.findMany({orderBy:[{status:"asc"},{lastRegisteredAt:"desc"}]})).map(e=>({...e,tokenMasked:e.token?`${e.token.slice(0,8)}…${e.token.slice(-8)}`:"—",supportedPushTypes:I(e.pushTypesJson)}))}async renameRegistration(e,A){let t=await (0,i.getPrismaClient)(),r=await t.apnsRegistration.update({where:{id:e},data:{displayName:C(A,"Display name",120)}});return this.changed(),r}async setRegistrationActive(e,A){let t=await (0,i.getPrismaClient)(),r=await t.apnsRegistration.update({where:{id:e},data:{status:A?"ACTIVE":"INACTIVE",invalidatedAt:A?null:new Date}});return this.changed(),r}async deleteRegistration(e){let A=await (0,i.getPrismaClient)();return await A.apnsRegistration.delete({where:{id:e}}),this.changed(),!0}async rawSettings(){return(await (0,i.getPrismaClient)()).pushNotificationSettings.upsert({where:{id:u},create:{id:u},update:{}})}async settings(){let e=await (0,i.getPrismaClient)(),[A,t,r,n]=await Promise.all([this.rawSettings(),this.storedTokenSettings(),this.storedCertificateCatalog(),this.credentials.isConfigured(a.CREDENTIALS.apnsTokenPrivateKey)]),o=r?.value??[],s=new Map((await e.apnsCertificateCredential.findMany({where:{id:{in:o.map(({id:e})=>e)}}})).map(e=>[e.id,e]));return{tokenConfigured:!!(t&&n),tokenTeamId:t?.value.teamId??null,tokenKeyId:t?.value.keyId??null,tokenPrivateKeyFingerprint:A.tokenPrivateKeyFingerprint,tokenConfiguredAt:A.tokenConfiguredAt,tokenLastUsedAt:A.tokenLastUsedAt,tokenLastError:A.tokenLastError,certificates:o.map(e=>{let A=s.get(e.id);return A?{...e,fingerprint:A.fingerprint,expiresAt:A.expiresAt,lastTestedAt:A.lastTestedAt,lastError:A.lastError,createdAt:A.createdAt,updatedAt:A.updatedAt}:null}).filter(e=>null!==e).sort((e,A)=>e.name.localeCompare(A.name)),updatedAt:new Date(Math.max(A.updatedAt.getTime(),t?.updatedAt.getTime()??0,r?.updatedAt.getTime()??0))}}async saveTokenSettings(e){await this.rawSettings();let A=C(e.teamId,"Team ID",20),t=C(e.keyId,"Key ID",20),n=await this.storedTokenSettings(),o=e.privateKey?.trim()||await this.credentials.getText(a.CREDENTIALS.apnsTokenPrivateKey);if(!o?.includes("-----BEGIN PRIVATE KEY-----"))throw Error("An APNs PKCS#8 .p8 private key is required");try{await (0,r.importPKCS8)(o,"ES256")}catch{throw Error("The APNs .p8 key must be an ES256 PKCS#8 private key")}let s={teamId:A,keyId:t},l=async e=>{await e.pushNotificationSettings.update({where:{id:u},data:{tokenPrivateKeyFingerprint:g(o),tokenConfiguredAt:new Date,tokenLastError:null}})},d=[...n&&JSON.stringify(n.value)===JSON.stringify(s)?[]:[{descriptor:a.CREDENTIALS.apnsTokenSettings,value:(0,a.encodeJsonCredential)(s)}],...e.privateKey?.trim()?[{descriptor:a.CREDENTIALS.apnsTokenPrivateKey,value:Buffer.from(o,"utf8")}]:[]];return d.length?await this.credentials.setMany(d,l):await (await (0,i.getPrismaClient)()).$transaction(l),this.changed(),this.settings()}async clearTokenSettings(){return await this.credentials.deleteMany([a.CREDENTIALS.apnsTokenSettings,a.CREDENTIALS.apnsTokenPrivateKey],async e=>{await e.pushNotificationSettings.upsert({where:{id:u},create:{id:u},update:{tokenPrivateKeyFingerprint:null,tokenConfiguredAt:null,tokenLastUsedAt:null,tokenLastError:null}})}),this.changed(),this.settings()}async addCertificateCredential(e){let t=Buffer.from(e.p12Base64,"base64");if(!t.length||t.length>0x1400000)throw Error("The .p12 file is empty or larger than 20 MiB");if(!["SANDBOX","PRODUCTION"].includes(e.environment))throw Error("Certificate environment is invalid");let r=p(t,e.passphrase),i=(0,A.randomUUID)(),n={id:i,name:C(e.name,"Credential name",100),topic:C(e.topic,"Topic",255),environment:e.environment};return await w(async()=>{let A=await this.storedCertificateCatalog();if(A?.value.some(({name:e})=>e===n.name))throw Error("Credential name already exists");let t=[...A?.value??[],n];await this.credentials.setMany([{descriptor:a.CREDENTIALS.apnsCertificateCatalog,value:(0,a.encodeJsonCredential)(t)},{descriptor:(0,a.apnsCertificateCredential)(i),value:(0,a.encodeJsonCredential)({p12Base64:e.p12Base64,passphrase:e.passphrase})}],async e=>{await e.apnsCertificateCredential.create({data:{id:i,fingerprint:r.fingerprint,expiresAt:r.expiresAt,lastTestedAt:new Date}})})}),this.changed(),this.settings()}async deleteCertificateCredential(e){return await w(async()=>{let A=await this.storedCertificateCatalog();if(!A?.value.some(A=>A.id===e))throw Error("APNs certificate credential not found");await this.credentials.setAndDeleteMany([{descriptor:a.CREDENTIALS.apnsCertificateCatalog,value:(0,a.encodeJsonCredential)(A.value.filter(A=>A.id!==e))}],[(0,a.apnsCertificateCredential)(e)],async A=>{await A.apnsCertificateCredential.delete({where:{id:e}})})}),this.changed(),!0}async retestCertificateCredential(e){let A=await (0,i.getPrismaClient)();if(!await A.apnsCertificateCredential.findUnique({where:{id:e}}))throw Error("APNs certificate credential not found");let t=await this.credentials.getJson((0,a.apnsCertificateCredential)(e));if(!t)throw Error("APNs certificate credential is not configured");try{let r=p(Buffer.from(t.p12Base64,"base64"),t.passphrase);await A.apnsCertificateCredential.update({where:{id:e},data:{fingerprint:r.fingerprint,expiresAt:r.expiresAt,lastTestedAt:new Date,lastError:null}})}catch(t){throw await A.apnsCertificateCredential.update({where:{id:e},data:{lastTestedAt:new Date,lastError:t instanceof Error?t.message:String(t)}}),this.changed(),t}return this.changed(),this.settings()}async channels(){return(await (0,i.getPrismaClient)()).apnsBroadcastChannel.findMany({orderBy:{createdAt:"desc"}})}async tokenAuthentication(e="APNs token authentication is not configured"){let A=await this.storedTokenSettings();if(!A)throw Error(e);let t=await this.credentials.getText(a.CREDENTIALS.apnsTokenPrivateKey);if(!t)throw Error(e);return{kind:"TOKEN",teamId:A.value.teamId,keyId:A.value.keyId,privateKey:t}}async createChannel(e){if(!["SANDBOX","PRODUCTION"].includes(e.environment))throw Error("Channel environment is invalid");if(!["NO_STORAGE","MOST_RECENT"].includes(e.storagePolicy))throw Error("Channel storage policy is invalid");let t=C(e.bundleId,"Bundle ID",255),r=e.channelId?null:await this.tokenAuthentication("APNs token authentication is required for broadcast channels"),n=e.channelId?.trim()||await this.client.createBroadcastChannel({environment:e.environment,authentication:r,bundleId:t,storagePolicy:e.storagePolicy}),a=await (0,i.getPrismaClient)(),o=await a.apnsBroadcastChannel.create({data:{id:(0,A.randomUUID)(),channelId:n,bundleId:t,environment:e.environment,storagePolicy:e.storagePolicy}});return this.changed(),o}async deleteChannel(e){let A=await (0,i.getPrismaClient)(),t=await A.apnsBroadcastChannel.findUnique({where:{id:e}});if(!t)throw Error("Broadcast channel not found");let r=await this.tokenAuthentication("APNs token authentication is required for broadcast channels");return await this.client.deleteBroadcastChannel({environment:t.environment,authentication:r,bundleId:t.bundleId,channelId:t.channelId}),await A.apnsBroadcastChannel.delete({where:{id:e}}),this.changed(),!0}async presets(){return(await (0,i.getPrismaClient)()).pushNotificationPreset.findMany({orderBy:{updatedAt:"desc"}})}async preset(e){return(await (0,i.getPrismaClient)()).pushNotificationPreset.findUnique({where:{id:e}})}async savePreset(e,t,r){let n=(0,d.validatePushEditor)(t),a=await (0,i.getPrismaClient)(),o=r?await a.pushNotificationPreset.update({where:{id:r},data:{name:C(e,"Preset name",100),editorJson:JSON.stringify(n.editor)}}):await a.pushNotificationPreset.create({data:{id:(0,A.randomUUID)(),name:C(e,"Preset name",100),editorJson:JSON.stringify(n.editor)}});return this.changed(),o}async deletePreset(e){let A=await (0,i.getPrismaClient)();return await A.pushNotificationPreset.delete({where:{id:e}}),this.changed(),!0}async history(e=100){return(await (0,i.getPrismaClient)()).pushNotificationBatch.findMany({include:{deliveries:{orderBy:{createdAt:"asc"}}},orderBy:{createdAt:"desc"},take:Math.max(1,Math.min(e,200))})}async historyItem(e){return(await (0,i.getPrismaClient)()).pushNotificationBatch.findUnique({where:{id:e},include:{deliveries:{orderBy:{createdAt:"asc"}}}})}async saveDraft(e){let t=(0,d.validatePushEditor)(e),r=await (0,i.getPrismaClient)(),n=await r.pushNotificationBatch.create({data:{id:(0,A.randomUUID)(),requestId:(0,A.randomUUID)(),status:"DRAFT",editorJson:JSON.stringify(t.editor),payloadJson:JSON.stringify(t.payload),headersJson:JSON.stringify(t.headers),targetMode:"DRAFT"},include:{deliveries:!0}});return this.changed(),n}async deleteHistory(e){let A=await (0,i.getPrismaClient)();if(1!==(await A.pushNotificationBatch.deleteMany({where:{id:e,status:{notIn:["QUEUED","SENDING"]}}})).count){if(!await A.pushNotificationBatch.findUnique({where:{id:e},select:{status:!0}}))throw Error("Push history item not found");throw Error("Queued or sending push notifications cannot be deleted")}return this.changed(),!0}async clearHistory(){let e=await (0,i.getPrismaClient)(),A=await e.pushNotificationBatch.deleteMany({where:{status:{notIn:["QUEUED","SENDING"]}}});return this.changed(),A.count}async send(e){var t;if(t=e.targetMode,!c.includes(t))throw Error(`Unsupported push target mode: ${e.targetMode}`);let r=e.targetMode,n=(0,d.validatePushEditor)(e.editor),a=await (0,i.getPrismaClient)(),o=await a.pushNotificationBatch.findUnique({where:{requestId:e.requestId},include:{deliveries:!0}});if(o)return o;let s=[],l=null,u=null;if("BROADCAST"===r){if("liveactivity"!==n.editor.pushType)throw Error("Broadcast delivery is available only for Live Activities");if(!e.channelId)throw Error("Select a broadcast channel");if(!(l=await a.apnsBroadcastChannel.findUnique({where:{id:e.channelId}})))throw Error("Broadcast channel not found")}else if("DIRECT"===r){if("liveactivity"!==n.editor.pushType)throw Error("Direct-token delivery is available only for Live Activities");if(!e.directToken)throw Error("Enter a Live Activity push token");let A=e.directTokenEncoding??"HEX";if("HEX"!==A&&"BASE64"!==A)throw Error("Direct token encoding must be HEX or BASE64");let t=e.directEnvironment??"SANDBOX";if("SANDBOX"!==t&&"PRODUCTION"!==t)throw Error("Direct token environment is invalid");let r=(0,d.normalizeDeviceToken)(e.directToken,A);u={token:r,tokenHash:g(r),environment:t}}else{let A=[...new Set(e.registrationIds??[])];if(!(s=(await a.apnsRegistration.findMany({where:{status:"ACTIVE",topic:n.headers["apns-topic"],..."DEVICES"===r?{id:{in:A}}:{}}})).filter(e=>I(e.pushTypesJson).includes(n.editor.pushType)).map(e=>({id:e.id,tokenHash:e.tokenHash,topic:e.topic,environment:e.environment}))).length)throw Error("No eligible APNs devices selected")}let h=await a.pushNotificationBatch.create({data:{id:(0,A.randomUUID)(),requestId:e.requestId,status:"QUEUED",editorJson:JSON.stringify(n.editor),payloadJson:JSON.stringify(n.payload),headersJson:JSON.stringify(n.headers),targetMode:r,channelId:l?.id??null,recipientCount:l||u?1:s.length,deliveries:{create:l?[{id:(0,A.randomUUID)(),topic:l.bundleId,environment:l.environment}]:u?[{id:(0,A.randomUUID)(),tokenHash:u.tokenHash,topic:n.headers["apns-topic"],environment:u.environment,recipientSecret:{create:{id:(0,A.randomUUID)(),token:u.token}}}]:s.map(e=>({id:(0,A.randomUUID)(),registrationId:e.id,tokenHash:e.tokenHash,topic:e.topic,environment:e.environment}))}},include:{deliveries:!0}});return this.changed(),this.processBatch(h.id).catch(()=>void 0),h}async resend(e,A){let t=await (0,i.getPrismaClient)(),r=await t.pushNotificationBatch.findUnique({where:{id:e},include:{deliveries:!0}});if(!r)throw Error("Push history item not found");if("DRAFT"===r.targetMode)throw Error("Choose recipients before sending a draft");if("DIRECT"===r.targetMode)throw Error("Direct Live Activity tokens are not retained; load the item and enter the token again");return this.send({requestId:A,editor:f(r.editorJson),targetMode:r.targetMode,registrationIds:r.deliveries.map(e=>e.registrationId).filter(e=>!!e),channelId:r.channelId})}async authentication(e,A,t){let r=await (0,i.getPrismaClient)();if(e.credentialId){let[i,n]=await Promise.all([r.apnsCertificateCredential.findUnique({where:{id:e.credentialId}}),this.storedCertificateCatalog()]),o=n?.value.find(({id:A})=>A===e.credentialId);if(!i||!o)throw Error("APNs certificate credential not found");if(o.environment!==A||o.topic!==t)throw Error("APNs certificate does not match the target topic/environment");let s=await this.credentials.getJson((0,a.apnsCertificateCredential)(i.id));if(!s)throw Error("APNs certificate credential is not configured");return{kind:"CERTIFICATE",p12Base64:s.p12Base64,passphrase:s.passphrase,fingerprint:i.fingerprint}}if("mdm"===e.pushType)throw Error("MDM requires certificate authentication");return this.tokenAuthentication()}async failDelivery(e,A){let t=await (0,i.getPrismaClient)();await t.pushNotificationDelivery.update({where:{id:e},data:{status:"FAILED",reason:A,finishedAt:new Date}}),this.changed()}async executeDelivery(e,A,t,r,n){let a=await (0,i.getPrismaClient)();await a.pushNotificationDelivery.update({where:{id:e.id},data:{status:"SENDING",startedAt:new Date}}),this.changed();try{let i=e.registrationId?await a.apnsRegistration.findUnique({where:{id:e.registrationId}}):null,o=e.registrationId?null:await a.apnsPushRecipientSecret.findUnique({where:{deliveryId:e.id}});if(e.registrationId&&(!i||"ACTIVE"!==i.status))return void await this.failDelivery(e.id,"Registration is no longer active");if(!i&&!o&&!n)return void await this.failDelivery(e.id,"Direct recipient token expired");let s=await this.authentication(A,e.environment,e.topic),l="mdm"===A.pushType?{mdm:i?.pushMagic}:t;if("mdm"===A.pushType&&!i?.pushMagic)return void await this.failDelivery(e.id,"Registration has no MDM push magic");let d=await this.client.send({environment:e.environment,authentication:s,deviceToken:i?.token||o?.token,broadcastTopic:n?.bundleId,payload:l,headers:{...r,...n?{"apns-channel-id":n.channelId}:{}}});await this.recordResponse(e.id,i,d,"TOKEN"===s.kind),"CERTIFICATE"===s.kind&&A.credentialId&&await a.apnsCertificateCredential.updateMany({where:{id:A.credentialId},data:{lastTestedAt:new Date,lastError:200===d.status?null:`HTTP ${d.status}${d.reason?`: ${d.reason}`:""}`}})}catch(t){if(!A.credentialId&&"mdm"!==A.pushType){let e=await (0,i.getPrismaClient)();await e.pushNotificationSettings.updateMany({where:{id:u},data:{tokenLastError:t instanceof Error?t.message:String(t)}})}if(A.credentialId){let e=await (0,i.getPrismaClient)();await e.apnsCertificateCredential.updateMany({where:{id:A.credentialId},data:{lastTestedAt:new Date,lastError:t instanceof Error?t.message:String(t)}})}await this.failDelivery(e.id,t instanceof Error?t.message:String(t))}finally{await a.apnsPushRecipientSecret.deleteMany({where:{deliveryId:e.id}})}}async recordResponse(e,A,t,r){let n=await (0,i.getPrismaClient)(),a=200===t.status;if(await n.pushNotificationDelivery.update({where:{id:e},data:{status:a?"SUCCEEDED":"FAILED",responseCode:t.status,reason:t.reason,responseTimestamp:t.timestamp,apnsId:t.apnsId,attempts:t.attempts,durationMs:t.durationMs,finishedAt:new Date}}),this.changed(),r&&await n.pushNotificationSettings.updateMany({where:{id:u},data:a?{tokenLastUsedAt:new Date,tokenLastError:null}:{tokenLastError:`HTTP ${t.status}${t.reason?`: ${t.reason}`:""}`}}),!A)return;if(a)return void await n.apnsRegistration.update({where:{id:A.id},data:{lastSentAt:new Date,lastFailureReason:null}});let o=410===t.status&&"Unregistered"===t.reason,s=400===t.status&&["BadDeviceToken","DeviceTokenNotForTopic"].includes(t.reason??""),l=!t.timestamp||t.timestamp>=A.lastRegisteredAt;o&&l||s?await n.apnsRegistration.updateMany({where:{id:A.id,lastRegisteredAt:A.lastRegisteredAt},data:{status:"INVALID",invalidatedAt:new Date,lastFailureReason:t.reason,lastFailureAt:new Date}}):await n.apnsRegistration.update({where:{id:A.id},data:{lastFailureReason:t.reason,lastFailureAt:new Date}})}async processBatch(e){let A=await (0,i.getPrismaClient)();if(1===(await A.pushNotificationBatch.updateMany({where:{id:e,status:"QUEUED"},data:{status:"SENDING",startedAt:new Date,error:null}})).count){this.activeBatchIds.add(e);try{let t=await A.pushNotificationBatch.findUnique({where:{id:e},include:{deliveries:{where:{status:"QUEUED"}}}});if(!t)return;let r=f(t.editorJson),i=f(t.payloadJson),n=f(t.headersJson),a=t.channelId?await A.apnsBroadcastChannel.findUnique({where:{id:t.channelId}}):null,o=0,s=Array.from({length:Math.min(16,t.deliveries.length)},async()=>{for(;o<t.deliveries.length;){let e=t.deliveries[o++];if(!e)return;await this.executeDelivery(e,r,i,n,a)}});await Promise.all(s);let l=await A.pushNotificationDelivery.findMany({where:{batchId:e},select:{status:!0}}),d=l.filter(e=>"SUCCEEDED"===e.status).length,u=l.length-d;await A.pushNotificationBatch.update({where:{id:e},data:{status:u?d?"PARTIAL":"FAILED":"SUCCEEDED",successCount:d,failureCount:u,finishedAt:new Date}}),this.changed()}finally{this.activeBatchIds.delete(e)}}}async recover(){if(this.recoveryStarted)return{queuedBatches:0,staleBatches:0,recoveredBatches:0,alreadyRunning:!0};this.recoveryStarted=!0;let e=0,A=0,t=0;try{let r=await (0,i.getPrismaClient)();for(;;){let i=new Date(Date.now()-12e4),n=await r.pushNotificationBatch.findMany({where:{OR:[{status:"QUEUED"},{status:"SENDING",startedAt:{lt:i}}]},orderBy:{createdAt:"asc"},take:100});if(!n.length)break;e+=n.filter(e=>"QUEUED"===e.status).length,A+=n.filter(e=>"SENDING"===e.status).length;let a=[];for(let e of n)if(!this.activeBatchIds.has(e.id)){if("SENDING"===e.status){await r.pushNotificationDelivery.updateMany({where:{batchId:e.id,status:"SENDING"},data:{status:"QUEUED",startedAt:null}});let A=await r.pushNotificationBatch.updateMany({where:{id:e.id,status:"SENDING",startedAt:{lt:i}},data:{status:"QUEUED",startedAt:null}});if(1!==A.count)continue}a.push(e.id)}if(!a.length)break;await Promise.all(a.map(e=>this.processBatch(e))),t+=a.length}return{queuedBatches:e,staleBatches:A,recoveredBatches:t}}finally{this.recoveryStarted=!1}}}])},929748,e=>{"use strict";e.i(808331),e.i(286078),e.s([])},384439,e=>{"use strict";let A=new Set(["MANUAL_CHOICE","RESOURCE_MANUAL_CHOICE"]),t=new Set(["RESOURCE_MANUAL","RESOURCE_MANUAL_CHOICE"]);function r(e){return A.has(e)}let i=/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;e.s(["WORKFLOW_CHOICE_KEY_PATTERN",0,i,"WORKFLOW_QUICK_ACTION_KINDS",0,["STANDARD","MERGE_CONFLICT","GITHUB_ACTIONS","GITLAB_PIPELINES","NONE"],"WORKFLOW_RESOURCE_KINDS",0,["BUILD","CODEBASE","JIRA_TICKET","AGENT_RUN","GITHUB_PIPELINE","GITHUB_JOB","GITLAB_MERGE_REQUEST","GITLAB_PIPELINE","GITLAB_JOB","PULL_REQUEST","WORKTREE","COMMAND_RUN","SKILL","SKILL_SYNC","IOS_DEVICE","SIGNING_PROFILE","PUSH_NOTIFICATION_BATCH","BUILD_DATA_COLLECTION"],"WORKFLOW_STEP_KINDS",0,["JIRA_LOAD_TICKET","JIRA_TRANSITION","JIRA_COMMENT","JIRA_ASSIGN","JIRA_UPDATE_FIELDS","JIRA_RESOLVE_BRANCH","GITHUB_LOAD_PR","GITHUB_MERGE_PR","GITHUB_COLLECT_REVIEW_THREADS","GITHUB_REPLY_REVIEW_THREAD","GITHUB_SET_REVIEW_THREAD_RESOLVED","GITHUB_CREATE_PR","GITHUB_SET_PR_LABELS","GITHUB_RETRY_PIPELINE","GITHUB_RETRY_JOB","GITHUB_CANCEL_WORKFLOW_RUN","GITHUB_SAVE_AUTO_RETRY","GITHUB_WAIT_CHECKS","WORKTREE_CREATE","WORKTREE_CHANGE_BRANCH","WORKTREE_COMMIT","WORKTREE_REFRESH_PULL_REQUEST","WORKTREE_OPERATION","WORKTREE_PREPARATION","WORKTREE_SET_AUTO_SYNC","WORKTREE_SET_AUTO_MERGE","WORKTREE_DELETE","WORKTREE_MOVE","WORKTREE_INSPECT","WORKTREE_INSPECT_GIT","WORKTREE_GIT_OPERATION","WORKTREE_WAIT_PUSH_READY","WORKTREE_SNAPSHOT","CODEBASE_FETCH_REFRESH","CODEBASE_INSPECT_GIT","CODEBASE_GIT_OPERATION","BUILD_START","BUILD_READ_TEST_RESULTS","BUILD_READ_COVERAGE","BUILD_IMPORT_COVERAGE","BUILD_EXPORT","BUILD_DEPLOY","BUILD_CANCEL","DISK_SPACE_LOAD","DISK_SPACE_REFRESH","DISK_SPACE_UPDATE_THRESHOLDS","DISK_SPACE_SET_MONITORING","DISK_SPACE_SET_PRESSURE_MODE","SKILL_APPLY","RUN_CREATE_PLAN","RUN_CREATE_SESSION","RUN_PLAY_PLAN","RUN_FOLLOW_UP","RUN_STEER","RUN_ANSWER","RUN_PAUSE","RUN_CONTINUE","RUN_CANCEL","RUN_REVISE_ANSWER","RUN_READ_RESULT","RUN_CAPTURE_CHECKPOINT","RUN_ARCHIVE_DELETE","NOTIFICATION_SEND","IOS_PUSH_SEND","HUMAN_CONFIRM","HUMAN_CHOICE","CONTROL_IF","CONTROL_JOIN","CONTROL_DELAY","CONTROL_WAIT_UNTIL","CONTROL_FOR_EACH","CONTROL_TRY","CONTROL_SET_VARIABLE","CONTROL_SUBWORKFLOW","SAVED_COMMAND","CUSTOM_COMMAND","COMMAND_RERUN","COMMAND_TERMINATE","COMMAND_READ_OUTPUT","WORKTREE_INSPECT_DIFF","WORKTREE_UPDATE_METADATA","WORKTREE_MOVE_CONTROL","BUILD_REBUILD","BUILD_GENERATE_REPORT","BUILD_DELETE","SKILL_PREPARE_SYNC","SKILL_RESOLVE_SYNC","SKILL_SKIP_SYNC","BUILD_DATA_REFRESH","BUILD_DATA_DELETE","BUILD_DATA_SET_LOCK","TAILSCALE_SERVE_INSPECT","TAILSCALE_SERVE_UPSERT_TEMPLATE","TAILSCALE_SERVE_SET_AGENT_ENABLED","TAILSCALE_SERVE_DELETE_TEMPLATE","SIGNING_REFRESH","SIGNING_SYNC_PROFILE","SIGNING_DELETE_EXPIRED","IOS_DEVICE_REGISTER","IOS_DEVICE_REJECT","AGENT_RECONCILE","AGENT_UPDATE_CADENCE","CCUSAGE_COLLECT","MODEL_COST_REFRESH","GITHUB_UPDATE_PR","GITHUB_SUBMIT_REVIEW","GITHUB_REQUEST_REVIEWERS","GITHUB_DISPATCH_WORKFLOW","GITLAB_LOAD_MR","GITLAB_CREATE_MR","GITLAB_UPDATE_MR","GITLAB_SUBMIT_REVIEW","GITLAB_REPLY_DISCUSSION","GITLAB_SET_DISCUSSION_RESOLVED","GITLAB_MERGE_MR","GITLAB_SET_MR_LABELS","GITLAB_REQUEST_REVIEWERS","GITLAB_CREATE_PIPELINE","GITLAB_RETRY_PIPELINE","GITLAB_RETRY_JOB","GITLAB_CANCEL_PIPELINE","GITLAB_SAVE_AUTO_RETRY","GITLAB_WAIT_PIPELINE","JIRA_CREATE_TICKET","JIRA_ADD_WORKLOG","JIRA_LINK_TICKETS","TERMINAL_RUN","MCP_CALL","SSE_ENDPOINT_ACTION","SSE_MOCK_ACTION","SSE_STORAGE_ACTION","SSE_BREAKPOINT_RESOLVE","SSE_HISTORY_CLEAR","SSE_SCRIPT_TEST"],"WORKFLOW_TRIGGER_KINDS",0,["MANUAL","MANUAL_CHOICE","RESOURCE_MANUAL","RESOURCE_MANUAL_CHOICE","SCHEDULE","WORKFLOW_FINISHED","GITHUB_PR_STATE","GITHUB_REVIEW_CHANGES_REQUESTED","GITHUB_REVIEW_COMMENT","GITHUB_PR_CLOSED","GITHUB_CHECK_FAILED","GITHUB_PUSH_DEFAULT","GITHUB_WORKFLOW_SUCCEEDED","GITHUB_ISSUE_COMMAND","GITHUB_ACTIONS_RESULT","GITHUB_PR_LABEL","BUILD_RESULT","BUILD_TEST_THRESHOLD","BUILD_COVERAGE_THRESHOLD","BUILD_HOOK_FAILED","AGENT_CONNECTION","AGENT_JOB_FAILED","AGENT_DISK_REPORT","AGENT_DISK_THRESHOLD","AGENT_DISK_STATE_CHANGED","AGENT_DISK_CLEANUP_RESULT","CCUSAGE_THRESHOLD","WORKTREE_CREATED","WORKTREE_BEHIND","WORKTREE_CONFLICT","WORKTREE_MISSING","WORKTREE_DIVERGED","WORKTREE_DIRTY_DURATION","WORKTREE_NEW_COMMIT","CODEBASE_REMOTE_BRANCH","JIRA_STATUS","JIRA_LABEL","JIRA_ASSIGNED_SELF","JIRA_SOURCE_NEW_TICKET","JIRA_MENTION","JIRA_SPRINT_STARTED","JIRA_ISSUE_CREATED","JIRA_ISSUE_DELETED","JIRA_ISSUE_COMMAND","JIRA_ATTACHMENT_ADDED","JIRA_ISSUE_LINKED","RUN_STARTED","RUN_COMPLETED","RUN_QUESTION_NEEDED","RUN_QUESTION_ANSWERED","RUN_PAUSED","RUN_CONTINUED","RUN_FAILED","RUN_CANCELLED","RUN_PLAN_PLAYED","RUN_FOLLOW_UP","RUN_IMPORTED","RUN_USAGE_THRESHOLD","RUN_EVENT_MATCH","COMMAND_RUN_RESULT","COMMAND_OUTPUT_MATCH","SKILL_SYNC_RESULT","SKILL_SYNC_CONFLICT","GITHUB_PIPELINE_STATUS_CHANGED","GITHUB_PR_SYNCHRONIZED","GITHUB_REVIEW_APPROVED","GITLAB_MR_STATE","GITLAB_REVIEW_CHANGES_REQUESTED","GITLAB_REVIEW_COMMENT","GITLAB_MR_CLOSED","GITLAB_PIPELINE_FAILED","GITLAB_PUSH_DEFAULT","GITLAB_PIPELINE_SUCCEEDED","GITLAB_NOTE_COMMAND","GITLAB_PIPELINE_RESULT","GITLAB_MR_LABEL","GITLAB_PIPELINE_STATUS_CHANGED","GITLAB_MR_SYNCHRONIZED","GITLAB_REVIEW_APPROVED","GITLAB_JOB_STATUS_CHANGED","JIRA_TICKET_UPDATED","JIRA_COMMENT_ADDED","JIRA_WORKLOG_ADDED","JIRA_SPRINT_ENDED","CODEBASE_SYNC_STATE_CHANGED","CODEBASE_OPERATION_FAILED","WORKTREE_SYNC_STATE_CHANGED","WORKTREE_AUTOMATION_RESULT","WORKTREE_CLEAN","PUSH_NOTIFICATION_RESULT","IOS_DEVICE_ENROLLED","IOS_DEVICE_REGISTRATION_RESULT","SIGNING_OPERATION_RESULT","SIGNING_ASSET_EXPIRING","BUILD_DATA_THRESHOLD","BUILD_DATA_CLEANUP_RESULT","POLLING_OPERATION_STATE","MODEL_COST_CATALOG_CHANGED","CREDENTIAL_STORE_DEGRADED","AGENT_RESOURCE_THRESHOLD","AGENT_VERSION_CHANGED","TOOL_CALL_RESULT","SSE_REQUEST_OPENED","SSE_EVENT_EMITTED","SSE_BREAKPOINT_WAITING","SSE_BREAKPOINT_RESOLVED","SSE_STREAM_COMPLETED","SSE_STREAM_FAILED"],"isChoiceTriggerKind",0,r,"isResourceTriggerKind",0,function(e){return t.has(e)},"isWorkflowChoiceKey",0,function(e){return"string"==typeof e&&i.test(e)},"workflowStaticSourceHandles",0,function(e){return r(e)?[]:"CONTROL_IF"===e?["true","false"]:"CONTROL_FOR_EACH"===e?["body","empty"]:"CONTROL_TRY"===e?["success","catch"]:"SAVED_COMMAND"===e||"CUSTOM_COMMAND"===e?["success","failure","match"]:["success","failure"]}])},963408,e=>{"use strict";let A=/^([A-Za-z0-9_-]+)(?:\[(\d+)\])?$/,t=/^[A-Za-z0-9_-]+(?:\[\d+\])?(?:\.[A-Za-z0-9_-]+(?:\[\d+\])?)*$/,r=/\{\{\s*([A-Za-z0-9_-]+(?:\[\d+\])?(?:\.[A-Za-z0-9_-]+(?:\[\d+\])?)*)\s*\}\}/g,i=/\{\{([^{}]*)\}\}/g;function n(e){return e.split(".").flatMap(t=>{let r=A.exec(t);if(!r)throw Error(`Invalid session path: ${e}`);return void 0===r[2]?[r[1]]:[r[1],Number(r[2])]})}function a(e,A){let t=e;for(let e of n(A)){if(null==t)return;if("number"==typeof e){if(!Array.isArray(t))return;t=t[e]}else{if("object"!=typeof t||Array.isArray(t))return;t=t[e]}}return t}e.s(["getSessionValue",0,a,"hasSessionValue",0,function(e,A){return void 0!==a(e,A)},"invalidWorkflowValueBindings",0,function e(A,r=[]){if(Array.isArray(A))for(let t of A)e(t,r);else if(A&&"object"==typeof A)for(let i of("SESSION"!==A.source||"string"==typeof A.path&&t.test(A.path)||r.push("Session bindings require a valid dotted path"),Object.values(A)))e(i,r);else if("string"==typeof A&&/\{\{|\}\}/.test(A)){let e=A.replace(i,"");for(let n of(/\{\{|\}\}/.test(e)&&r.push("Text interpolation contains unmatched braces"),A.matchAll(i)))t.test(n[1].trim())||r.push("Text interpolation requires a valid dotted path")}return r},"mergeSessionData",0,function(e,A){let t=(e,A)=>{if(e&&A&&"object"==typeof e&&"object"==typeof A&&!Array.isArray(e)&&!Array.isArray(A)){let r={...e};for(let[e,i]of Object.entries(A))r[e]=t(r[e],i);return r}return structuredClone(A)};return t(e,A)},"resolveWorkflowValue",0,function e(A,t){var i,n;return A&&"object"==typeof A&&!Array.isArray(A)&&"SESSION"===A.source&&"string"==typeof A.path?a(t,A.path):A&&"object"==typeof A&&!Array.isArray(A)&&"LITERAL"===A.source?A.value:Array.isArray(A)?A.map(A=>e(A,t)):A&&"object"==typeof A?Object.fromEntries(Object.entries(A).map(([A,r])=>[A,e(r,t)])):"string"==typeof A?(i=A,n=t,i.replace(r,(e,A)=>{let t=a(n,A);return null==t?"":"string"==typeof t?t:JSON.stringify(t)})):A},"setSessionValue",0,function(e,A,t){let r=structuredClone(e),i=n(A),a=r;return i.forEach((e,r)=>{if(r===i.length-1){if("number"==typeof e){if(!Array.isArray(a))throw Error(`Expected an array at ${A}`);a[e]=t}else{if(Array.isArray(a))throw Error(`Expected an object at ${A}`);a[e]=t}return}let n="number"==typeof i[r+1];if("number"==typeof e){if(!Array.isArray(a))throw Error(`Expected an array at ${A}`);let t=a[e];t&&"object"==typeof t||(a[e]=n?[]:{}),a=a[e]}else{if(Array.isArray(a))throw Error(`Expected an object at ${A}`);let t=a[e];t&&"object"==typeof t||(a[e]=n?[]:{}),a=a[e]}}),r},"workflowSessionData",0,function(e){let A=JSON.parse(e);if(!A||"object"!=typeof A||Array.isArray(A))throw Error("Workflow session data must be a JSON object");return A},"workflowValueSessionPaths",0,function e(A,i=new Set){if(Array.isArray(A))for(let t of A)e(t,i);else if(A&&"object"==typeof A)for(let r of("SESSION"===A.source&&"string"==typeof A.path&&t.test(A.path)&&i.add(A.path),Object.values(A)))e(r,i);else if("string"==typeof A)for(let e of A.matchAll(r))i.add(e[1]);return i}])},388385,222335,69988,e=>{"use strict";var A=e.i(853205),t=e.i(662114),r=e.i(591135),i=e.i(380592),n=e.i(384439),a=e.i(963408);function o(e){return{kind:"static",options:e.map(e=>({value:e,label:e.charAt(0)+e.slice(1).toLowerCase().replace(/_/g," ")}))}}function s(e){return{kind:"static",options:e}}let l={agent:"agent.id",codebase:"codebase.id",worktree:"worktree.id",githubRepository:"repo.id",githubPullRequest:"pr.number",jiraTicket:"ticket.key",agentRun:"run.id",githubWorkflowRun:"pipeline.runId"};function d(e,A){return{kind:"resource",resource:e,scopeFrom:A,sessionPath:l[e]}}let u=["literal","session","interpolation"],c=["literal","interpolation"],h=(e,A,t={})=>({key:e,label:A,control:"text",valueModes:u,...t}),g=(e,A,t={})=>h(e,A,{multiline:!0,...t}),p=(e,A,t={})=>({key:e,label:A,control:"number",valueModes:["literal","session"],...t}),f=(e,A,t={})=>({key:e,label:A,control:"boolean",...t}),I=(e,A,t,r={})=>({key:e,label:A,control:"enum",options:t,...r}),C=(e,A,t,r={})=>{let{scopeFrom:i,...n}=r;return{key:e,label:A,control:"resource",options:d(t,i),valueModes:u,...n}},m=(e,A,t,r={})=>{let{scopeFrom:i,...n}=r;return{key:e,label:A,control:"resourceMulti",options:d(t,i),valueModes:c,...n}},w=(e,A,t={})=>({key:e,label:A,control:"stringList",valueModes:c,...t}),E=e=>({key:"mcpPresetIds",label:"MCP tool presets",control:"mcpPresetMulti",presetKind:e,default:[]}),y=(e,A,t={})=>({key:e,label:A,control:"record",valueModes:c,...t}),B=(e,A,t={})=>({key:e,label:A,control:"json",valueModes:c,...t}),Q=(e,A,t={})=>({key:e,label:A,control:"triggerChoices",...t}),D=s([{value:"EQ",label:"Equals"},{value:"NE",label:"Not equal"},{value:"GT",label:"Greater than"},{value:"GTE",label:"Greater or equal"},{value:"LT",label:"Less than"},{value:"LTE",label:"Less or equal"},{value:"CONTAINS",label:"Contains"},{value:"MATCHES",label:"Matches RE2"},{value:"EXISTS",label:"Exists"}]),b=o(i.WORKTREE_OPERATIONS.filter(e=>"OPEN_EDITOR"!==e)),S=()=>[h("owner","Repository owner",{placeholder:"octocat",help:"Defaults to the repository from session data."}),h("name","Repository name",{placeholder:"hello-world"})],k=e=>[C("worktreeId","Worktree","worktree"),C("jiraIssueKey","Jira issue key","jiraTicket",{placeholder:"APP-123"}),{key:"model",label:"Model",control:"model",required:!0,valueModes:["literal","session"],modelKeys:{provider:"provider",model:"model",effort:"effort",scopeFrom:"worktreeId"}},f("webSearchEnabled","Enable web search"),E(e),p("worktreeConcurrencyLimit","Worktree concurrency limit",{default:"PLAN"===e?0:"SESSION"===e?1:void 0,minimum:0,maximum:32,integer:!0,help:"PLAN"===e?"Maximum plans admitted on this worktree. Use 0 for unlimited.":"SESSION"===e?"Maximum sessions admitted on this worktree. Use 0 for unlimited.":"Maximum same-kind runs admitted on this worktree. Use 0 for unlimited; leave empty for the source kind's default."}),g("prompt","Prompt",{required:!0}),w("attachmentIds","Attachment IDs")],v={JIRA_LOAD_TICKET:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),f("force","Bypass cache")]},JIRA_TRANSITION:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),h("transitionId","Transition ID",{required:!0})]},JIRA_COMMENT:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),g("content","Comment",{required:!0}),I("format","Format",s([{value:"MARKDOWN",label:"Markdown"},{value:"JIRA_WIKI",label:"Jira wiki"}]))]},JIRA_ASSIGN:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),C("accountId","Assignee","jiraUser",{scopeFrom:"issueKey",help:"Leave empty to unassign the ticket."})]},JIRA_UPDATE_FIELDS:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),B("fields","Fields",{placeholder:'{ "labels": ["ready"] }'})]},JIRA_RESOLVE_BRANCH:{fields:[C("issueKey","Issue key","jiraTicket",{placeholder:"APP-123"}),C("codebaseId","Codebase","codebase")]},GITHUB_LOAD_PR:{fields:[...S(),p("number","Pull request number")]},GITHUB_MERGE_PR:{fields:[...S(),p("number","Pull request number"),I("method","Merge method",s([{value:"SQUASH",label:"Squash"},{value:"MERGE",label:"Merge"},{value:"REBASE",label:"Rebase"}])),h("commitHeadline","Commit headline"),g("commitBody","Commit body"),h("authorEmail","Author email")]},GITHUB_COLLECT_REVIEW_THREADS:{fields:[...S(),p("number","Pull request number")]},GITHUB_REPLY_REVIEW_THREAD:{fields:[h("threadId","Review thread ID",{required:!0}),g("body","Reply",{required:!0})]},GITHUB_SET_REVIEW_THREAD_RESOLVED:{fields:[h("threadId","Review thread ID",{required:!0}),f("resolved","Mark resolved")]},GITHUB_CREATE_PR:{fields:[...S(),h("baseRefName","Base branch"),h("headRefName","Head branch"),h("title","Title"),g("body","Body"),f("draft","Open as draft")]},GITHUB_SET_PR_LABELS:{fields:[...S(),p("number","Pull request number"),w("labels","Labels")]},GITHUB_RETRY_PIPELINE:{fields:[C("repositoryId","Repository","githubRepository"),h("checkSuiteId","Check suite ID")]},GITHUB_RETRY_JOB:{fields:[C("repositoryId","Repository","githubRepository"),h("checkSuiteId","Check suite ID",{required:!0}),h("jobId","Workflow job ID",{required:!0})]},GITHUB_CANCEL_WORKFLOW_RUN:{fields:[h("codebaseRepositoryId","Codebase repository ID"),C("workflowRunId","Workflow run","githubWorkflowRun",{scopeFrom:"codebaseRepositoryId"}),f("force","Force cancel")]},GITHUB_SAVE_AUTO_RETRY:{fields:[B("input","Auto-retry rule",{required:!0})]},GITHUB_WAIT_CHECKS:{fields:[h("repositoryId","Repository ID"),h("workflowRunId","Workflow run ID")]},GITLAB_LOAD_MR:{fields:[h("projectId","Project ID"),p("iid","Merge request IID")]},GITLAB_CREATE_MR:{fields:[h("projectId","Project ID"),h("sourceBranch","Source branch"),h("targetBranch","Target branch"),h("title","Title"),g("description","Description"),f("removeSourceBranch","Remove source branch"),f("squash","Squash commits"),w("reviewerIds","Reviewer IDs"),w("labels","Labels")]},GITLAB_UPDATE_MR:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),h("title","Title"),g("description","Description"),I("stateEvent","State",o(["CLOSE","REOPEN"])),w("reviewerIds","Reviewer IDs"),w("labels","Labels")]},GITLAB_SUBMIT_REVIEW:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),I("outcome","Review outcome",o(["APPROVE","COMMENT","REQUEST_CHANGES"])),g("body","Review body")]},GITLAB_REPLY_DISCUSSION:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),h("discussionId","Discussion ID",{required:!0}),g("body","Reply",{required:!0})]},GITLAB_SET_DISCUSSION_RESOLVED:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),h("discussionId","Discussion ID",{required:!0}),f("resolved","Mark resolved")]},GITLAB_MERGE_MR:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),f("squash","Squash commits"),f("removeSourceBranch","Remove source branch"),f("autoMerge","Enable auto-merge"),h("sha","Expected source SHA")]},GITLAB_SET_MR_LABELS:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),w("labels","Labels")]},GITLAB_REQUEST_REVIEWERS:{fields:[h("projectId","Project ID"),p("iid","Merge request IID"),w("reviewerIds","Reviewer IDs")]},GITLAB_CREATE_PIPELINE:{fields:[h("projectId","Project ID"),h("ref","Git ref"),B("variables","Pipeline variables")]},GITLAB_RETRY_PIPELINE:{fields:[h("projectId","Project ID"),h("pipelineId","Pipeline ID")]},GITLAB_RETRY_JOB:{fields:[h("projectId","Project ID"),h("jobId","Job ID")]},GITLAB_CANCEL_PIPELINE:{fields:[h("projectId","Project ID"),h("pipelineId","Pipeline ID")]},GITLAB_SAVE_AUTO_RETRY:{fields:[B("input","Auto-retry rule",{required:!0})]},GITLAB_WAIT_PIPELINE:{fields:[h("projectId","Project ID"),h("pipelineId","Pipeline ID")]},WORKTREE_CREATE:{fields:[C("codebaseId","Codebase","codebase"),I("mode","Branch mode",o(["NEW","EXISTING","TICKET"])),h("branchName","Branch name"),h("ticketKey","Ticket key",{placeholder:"APP-123"}),h("baseBranch","Base branch")]},WORKTREE_CHANGE_BRANCH:{fields:[C("worktreeId","Worktree","worktree"),I("mode","Branch mode",o(["NEW","EXISTING","TICKET"])),h("branchName","Branch name"),h("ticketKey","Ticket key",{placeholder:"APP-123"}),h("baseBranch","Base branch"),f("stashOnFailure","Stash on failure")]},WORKTREE_COMMIT:{fields:[C("worktreeId","Worktree","worktree"),g("message","Commit message",{required:!0}),f("signed","Signed commit"),f("stageAll","Stage all",{default:!0}),B("paths","Selected paths")]},WORKTREE_REFRESH_PULL_REQUEST:{fields:[C("worktreeId","Worktree","worktree")]},WORKTREE_OPERATION:{fields:[C("worktreeId","Worktree","worktree"),I("operation","Operation",b),f("forcePreparations","Force preparation conflicts",{help:"Destructively resets preparation-managed paths before Sync or Rebase, then reapplies the current rules."})]},WORKTREE_PREPARATION:{fields:[C("worktreeId","Worktree","worktree"),I("action","Action",o(i.WORKTREE_PREPARATION_ACTIONS))]},WORKTREE_SET_AUTO_SYNC:{fields:[C("worktreeId","Worktree","worktree"),I("action","Action",o(["ENABLE","RETRY","FORCE","CANCEL"])),h("conflictWorkflowId","Conflict workflow ID"),h("conflictWorkflowChoice","Conflict workflow choice")]},WORKTREE_SET_AUTO_MERGE:{fields:[C("worktreeId","Worktree","worktree"),I("action","Action",o(["ENABLE","RETRY","CANCEL"])),h("repositoryNameWithOwner","Repository",{placeholder:"owner/repository"}),p("pullRequestNumber","Pull request number"),I("method","Merge method",o(["MERGE","REBASE","SQUASH"])),h("commitHeadline","Commit headline"),g("commitBody","Commit body"),h("authorEmail","Author email"),f("deleteWorktree","Delete worktree after merge"),f("moveTicketToDone","Move Jira ticket to done")]},WORKTREE_DELETE:{fields:[C("worktreeId","Worktree","worktree"),f("deleteRemoteBranch","Delete remote branch")]},WORKTREE_MOVE:{fields:[C("worktreeId","Source worktree","worktree"),C("targetCodebaseId","Target codebase","codebase",{required:!0}),C("targetWorktreeId","Target worktree","worktree"),f("deleteSource","Delete source")]},WORKTREE_INSPECT:{fields:[C("worktreeId","Worktree","worktree")]},WORKTREE_INSPECT_GIT:{fields:[C("worktreeId","Worktree","worktree")]},WORKTREE_GIT_OPERATION:{fields:[C("worktreeId","Worktree","worktree"),I("operation","Operation",o(i.WORKTREE_GIT_OPERATIONS)),h("branch","Branch"),h("stashOid","Stash OID"),f("stashChanges","Stash changes first")]},WORKTREE_WAIT_PUSH_READY:{fields:[C("worktreeId","Worktree","worktree")]},WORKTREE_SNAPSHOT:{fields:[h("kind","Checkpoint kind",{placeholder:"STEP"})]},CODEBASE_FETCH_REFRESH:{fields:[C("codebaseId","Codebase","codebase"),I("operation","Operation",o(["FETCH","REFRESH"]))]},CODEBASE_INSPECT_GIT:{fields:[C("codebaseId","Codebase","codebase")]},CODEBASE_GIT_OPERATION:{fields:[C("codebaseId","Codebase","codebase"),I("operation","Operation",o(r.CODEBASE_GIT_OPERATIONS)),h("branch","Branch"),h("stashOid","Stash OID"),f("stashChanges","Stash changes first")]},BUILD_START:{fields:[C("worktreeId","Worktree","worktree"),h("configurationId","Build configuration ID",{required:!0}),I("action","Action",o(t.BUILD_ACTIONS)),B("destination","Destination"),m("scriptIds","Build scripts","buildScript"),B("advancedSettings","Advanced settings"),f("exportWhenComplete","Export when complete"),B("exportSettings","Export settings"),f("worktreeCoverage","Collect worktree coverage")]},BUILD_READ_TEST_RESULTS:{fields:[h("buildId","Build ID")]},BUILD_READ_COVERAGE:{fields:[h("buildId","Build ID")]},BUILD_IMPORT_COVERAGE:{fields:[C("worktreeId","Worktree","worktree"),h("buildName","Build name",{default:"{{workflow.name}}",help:"Name shown on the build and coverage pages. Defaults to the workflow name."}),h("reportPath","Coverage file",{required:!0,default:"coverage/lcov.info",help:"Path inside the worktree, written by whichever test command ran first."}),I("format","Coverage format",o(["AUTO","LCOV","ISTANBUL"]))]},BUILD_EXPORT:{fields:[h("buildId","Build ID"),B("settings","Export settings",{required:!0})]},BUILD_DEPLOY:{fields:[h("buildId","Build ID"),B("destinations","Destinations")]},BUILD_CANCEL:{fields:[h("buildId","Build ID")]},DISK_SPACE_LOAD:{fields:[C("agentId","Agent","agent")]},DISK_SPACE_REFRESH:{fields:[C("agentId","Agent","agent")]},DISK_SPACE_UPDATE_THRESHOLDS:{fields:[p("normalThresholdGiB","Normal threshold (GiB)",{required:!0}),p("pressureThresholdGiB","Pressure threshold (GiB)",{required:!0})]},DISK_SPACE_SET_MONITORING:{fields:[C("agentId","Agent","agent"),f("enabled","Monitoring enabled",{required:!0,default:!0})]},DISK_SPACE_SET_PRESSURE_MODE:{fields:[C("agentId","Agent","agent"),f("enabled","Manual pressure mode",{required:!0,default:!0})]},SKILL_APPLY:{fields:[C("groupId","Skill group","skillGroup",{help:"Leave empty to sync all skills."})]},NOTIFICATION_SEND:{fields:[h("title","Title",{required:!0}),g("body","Body",{required:!0}),h("href","Link")]},IOS_PUSH_SEND:{fields:[I("targetMode","Target mode",o(["ALL","DEVICES","BROADCAST","DIRECT"])),m("registrationIds","Registrations","apnsRegistration"),C("channelId","Broadcast channel","apnsChannel"),B("editor","Notification editor"),h("directToken","Direct device token"),I("directTokenEncoding","Token encoding",o(["HEX","BASE64"])),I("directEnvironment","Environment",o(["SANDBOX","PRODUCTION"]))]},COMMAND_RERUN:{fields:[h("commandRunId","Command run ID",{required:!0})]},COMMAND_TERMINATE:{fields:[h("commandRunId","Command run ID",{required:!0})]},COMMAND_READ_OUTPUT:{fields:[h("commandRunId","Command run ID",{required:!0}),p("first","Maximum chunks")]},WORKTREE_INSPECT_DIFF:{fields:[h("worktreeId","Worktree ID"),h("scope","Diff scope",{required:!0}),h("path","Path"),h("previousPath","Previous path"),h("commitSha","Commit SHA")]},WORKTREE_UPDATE_METADATA:{fields:[h("worktreeId","Worktree ID"),h("baseBranch","Base branch"),h("highlightColor","Highlight color")]},WORKTREE_MOVE_CONTROL:{fields:[h("moveId","Move ID",{required:!0}),I("operation","Operation",o(["RETRY_WITH_STASH","CANCEL"]))]},BUILD_REBUILD:{fields:[h("buildId","Build ID")]},BUILD_GENERATE_REPORT:{fields:[h("buildId","Build ID"),I("reportKind","Report kind",o(["TEST_RESULTS","CODE_COVERAGE"]))]},BUILD_DELETE:{fields:[w("buildIds","Build IDs")]},SKILL_PREPARE_SYNC:{fields:[I("syncKind","Sync kind",o(["ALL","GROUP"])),h("groupId","Skill group ID")]},SKILL_RESOLVE_SYNC:{fields:[h("runId","Sync run ID",{required:!0}),h("itemId","Conflict item ID",{required:!0}),I("resolution","Resolution",o(["LOCAL","REMOTE","SKIP"]))]},SKILL_SKIP_SYNC:{fields:[h("runId","Sync run ID",{required:!0})]},BUILD_DATA_REFRESH:{fields:[]},BUILD_DATA_DELETE:{fields:[h("collectionId","Collection ID",{required:!0}),w("entryIds","Entry IDs"),f("overrideProtection","Override protection")]},BUILD_DATA_SET_LOCK:{fields:[h("collectionId","Collection ID",{required:!0}),h("entryId","Entry ID",{required:!0}),f("locked","Locked")]},TAILSCALE_SERVE_INSPECT:{fields:[m("agentIds","Agents","agent")]},TAILSCALE_SERVE_UPSERT_TEMPLATE:{fields:[h("templateId","Template ID"),p("expectedRevision","Expected revision",{minimum:1,integer:!0}),h("name","Template name",{required:!0}),I("protocol","Listener protocol",o(["HTTP","HTTPS","TCP","TLS_TERMINATED_TCP"]),{required:!0,default:"HTTPS"}),p("listenPort","Incoming port",{required:!0,default:443,minimum:1,maximum:65535,integer:!0}),h("mountPath","Mount path",{default:"/"}),I("destinationProtocol","Destination protocol",o(["HTTP","HTTPS","HTTPS_INSECURE","TCP"]),{required:!0,default:"HTTP"}),p("destinationPort","Destination port",{required:!0,default:3e3,minimum:1,maximum:65535,integer:!0}),h("destinationPath","Destination path",{default:""}),f("funnel","Public Funnel"),w("appCapabilities","App capabilities"),I("proxyProtocol","PROXY protocol",o(["NONE","V1","V2"]),{required:!0,default:"NONE"}),m("agentIds","Enabled agents","agent",{required:!0})]},TAILSCALE_SERVE_SET_AGENT_ENABLED:{fields:[h("templateId","Template ID",{required:!0}),C("agentId","Agent","agent",{required:!0}),f("enabled","Enabled"),p("expectedRevision","Expected revision",{required:!0})]},TAILSCALE_SERVE_DELETE_TEMPLATE:{fields:[h("templateId","Template ID",{required:!0}),p("expectedRevision","Expected revision",{required:!0})]},SIGNING_REFRESH:{fields:[w("agentIds","Agent IDs")]},SIGNING_SYNC_PROFILE:{fields:[h("uuid","Profile UUID",{required:!0}),h("sourceAgentId","Source agent ID",{required:!0}),w("targetAgentIds","Target agent IDs")]},SIGNING_DELETE_EXPIRED:{fields:[w("agentIds","Agent IDs")]},IOS_DEVICE_REGISTER:{fields:[h("deviceId","Device ID",{required:!0})]},IOS_DEVICE_REJECT:{fields:[h("deviceId","Device ID",{required:!0})]},AGENT_RECONCILE:{fields:[w("agentIds","Agent IDs")]},AGENT_UPDATE_CADENCE:{fields:[h("agentId","Agent ID",{required:!0}),B("settings","Cadence settings")]},CCUSAGE_COLLECT:{fields:[]},MODEL_COST_REFRESH:{fields:[]},GITHUB_UPDATE_PR:{fields:[h("owner","Owner",{required:!0}),h("name","Repository",{required:!0}),p("number","Pull request number",{required:!0}),h("title","Title"),g("body","Body"),f("draft","Draft")]},GITHUB_SUBMIT_REVIEW:{fields:[h("owner","Owner",{required:!0}),h("name","Repository",{required:!0}),p("number","Pull request number",{required:!0}),I("event","Review event",o(["APPROVE","REQUEST_CHANGES","COMMENT"])),g("body","Body")]},GITHUB_REQUEST_REVIEWERS:{fields:[h("owner","Owner",{required:!0}),h("name","Repository",{required:!0}),p("number","Pull request number",{required:!0}),w("reviewers","Reviewers"),w("teamReviewers","Team reviewers")]},GITHUB_DISPATCH_WORKFLOW:{fields:[h("repositoryId","Repository ID",{required:!0}),h("workflowId","Workflow ID",{required:!0}),h("ref","Git ref",{required:!0}),y("inputs","Workflow inputs")]},JIRA_CREATE_TICKET:{fields:[h("projectKey","Project key",{required:!0}),h("issueTypeId","Issue type ID",{required:!0}),h("summary","Summary",{required:!0}),g("description","Description"),B("fields","Additional fields")]},JIRA_ADD_WORKLOG:{fields:[h("issueKey","Issue key"),p("timeSpentSeconds","Time spent (seconds)",{required:!0}),h("startedAt","Started at"),g("comment","Comment")]},JIRA_LINK_TICKETS:{fields:[h("inwardIssueKey","Inward issue key",{required:!0}),h("outwardIssueKey","Outward issue key",{required:!0}),h("linkType","Link type",{required:!0})]},MCP_CALL:{fields:[C("groupId","MCP server","mcpServer",{required:!0}),h("name","Tool name",{required:!0}),B("arguments","Arguments")]},SSE_ENDPOINT_ACTION:{fields:[I("operation","Operation",o(["CREATE","UPDATE","SET_MODE","ROTATE_TOKEN","DELETE"]),{required:!0}),h("endpointId","Endpoint ID"),B("input","Endpoint input")]},SSE_MOCK_ACTION:{fields:[I("operation","Operation",o(["SAVE_TEMPLATE","DELETE_TEMPLATE","SAVE_COMPOSITION","ACTIVATE_COMPOSITION","DELETE_COMPOSITION"]),{required:!0}),h("endpointId","Endpoint ID"),h("resourceId","Template or composition ID"),B("input","Mock input")]},SSE_STORAGE_ACTION:{fields:[I("operation","Operation",o(["SET","COMPARE_AND_SET","INCREMENT","DELETE"]),{required:!0}),h("key","Storage key",{required:!0}),B("value","JSON value"),p("expectedVersion","Expected version"),p("delta","Increment amount")]},SSE_BREAKPOINT_RESOLVE:{fields:[h("breakpointId","Breakpoint ID",{required:!0}),p("version","Version",{required:!0,integer:!0}),I("resolution","Resolution",o(["FORWARD","SAVED_MOCK","AD_HOC"]),{required:!0}),h("mockCompositionId","Mock composition ID"),B("adHocComposition","Ad hoc composition")]},SSE_HISTORY_CLEAR:{fields:[h("endpointId","Endpoint ID"),w("ids","Request IDs")]},SSE_SCRIPT_TEST:{fields:[g("source","JavaScript",{required:!0}),B("context","Script context"),p("timeoutMs","Timeout (ms)",{integer:!0}),p("memoryLimitMb","Memory limit (MiB)",{integer:!0}),p("fetchTimeoutMs","Fetch timeout (ms)",{integer:!0})]},RUN_CREATE_PLAN:{fields:k("PLAN")},RUN_CREATE_SESSION:{fields:k("SESSION")},RUN_PLAY_PLAN:{fields:[h("runId","Plan run ID"),E("SESSION"),p("worktreeConcurrencyLimit","Worktree concurrency limit",{default:1,minimum:0,maximum:32,integer:!0,help:"Maximum sessions admitted on this worktree. Use 0 for unlimited."})]},RUN_FOLLOW_UP:{fields:[h("runId","Source run ID"),...k(null),I("followUpMode","Follow-up mode",o(["RESUME","FRESH","RESEND"])),h("contextMode","Context mode")]},RUN_STEER:{fields:[h("runId","Run ID"),g("prompt","Steering prompt",{required:!0}),w("attachmentIds","Attachment IDs")]},RUN_ANSWER:{fields:[h("batchId","Question batch ID",{required:!0}),B("answers","Answers")]},RUN_PAUSE:{fields:[h("runId","Run ID")]},RUN_CONTINUE:{fields:[h("runId","Run ID")]},RUN_CANCEL:{fields:[h("runId","Run ID")]},RUN_REVISE_ANSWER:{fields:[h("batchId","Question batch ID",{required:!0}),B("answers","Answers"),f("stash","Stash before revision"),f("rollback","Roll back to the question")]},RUN_READ_RESULT:{fields:[h("runId","Run ID")]},RUN_CAPTURE_CHECKPOINT:{fields:[h("runId","Run ID")]},RUN_ARCHIVE_DELETE:{fields:[h("runId","Run ID"),f("delete","Delete permanently"),f("archived","Archive")]},HUMAN_CONFIRM:{fields:[g("prompt","Prompt")]},HUMAN_CHOICE:{fields:[g("prompt","Prompt"),f("multiSelect","Allow multiple selections"),f("allowCustom","Allow a custom answer"),((e,A,t={})=>({key:e,label:A,control:"choiceOptions",valueModes:c,...t}))("options","Buttons")]},CONTROL_IF:{fields:[((e,A,t={})=>({key:e,label:A,control:"condition",valueModes:c,...t}))("condition","Condition",{required:!0})]},CONTROL_JOIN:{fields:[I("mode","Join mode",s([{value:"ALL",label:"All — wait for every branch"},{value:"ANY",label:"Any — continue on the first branch"}]),{help:"All (default) waits until every incoming branch has finished before continuing. Any continues as soon as the first incoming branch arrives, and the remaining branches keep running on their own. Either way, branches that were skipped do not block the join, and the join itself is skipped when no branch reaches it."})]},CONTROL_DELAY:{fields:[p("seconds","Delay (seconds)",{required:!0})]},CONTROL_WAIT_UNTIL:{fields:[B("condition","Condition",{required:!0})]},CONTROL_FOR_EACH:{fields:[h("listPath","List session path",{placeholder:"pr.unresolvedThreads"}),B("items","Inline items"),I("errorMode","Error handling",s([{value:"FAIL_FAST",label:"Fail fast"},{value:"COLLECT_ERRORS",label:"Collect errors"}]))]},CONTROL_TRY:{fields:[]},CONTROL_SET_VARIABLE:{fields:[h("path","Output path",{required:!0,placeholder:"flags.ready"}),B("value","Value"),g("script","Script")]},CONTROL_SUBWORKFLOW:{fields:[h("versionId","Sub-workflow version ID",{required:!0}),B("inputMapping","Input mapping")]},SAVED_COMMAND:{fields:[C("commandId","Saved command ID","savedCommand",{required:!0}),I("completionMode","Completion",o(["WAIT_FOR_EXIT","FIRE_AND_FORGET"])),I("targetMode","Target",o(["CONTEXT","FIXED_AGENT","FIXED_WORKTREE"])),h("agentId","Fixed agent ID",{visibleWhen:{key:"targetMode",equals:"FIXED_AGENT"}}),h("worktreeId","Fixed worktree ID",{visibleWhen:{key:"targetMode",equals:"FIXED_WORKTREE"}}),h("outputPattern","Output match pattern (RE2)",{placeholder:"ready on port ([0-9]+)",help:"Optional case-sensitive regex. Requires Wait for exit and emits through the match connector while the command runs.",valueModes:["literal"]}),I("outputMatchMode","Output match behavior",o(["ONCE","EACH_MATCH"]),{default:"ONCE"})]},CUSTOM_COMMAND:{fields:[g("script","Script",{required:!0}),I("completionMode","Completion",o(["WAIT_FOR_EXIT","FIRE_AND_FORGET"])),I("targetMode","Target",o(["CONTEXT","FIXED_AGENT","FIXED_WORKTREE"])),h("agentId","Fixed agent ID",{visibleWhen:{key:"targetMode",equals:"FIXED_AGENT"}}),h("worktreeId","Fixed worktree ID",{visibleWhen:{key:"targetMode",equals:"FIXED_WORKTREE"}}),h("outputPattern","Output match pattern (RE2)",{placeholder:"ready on port ([0-9]+)",help:"Optional case-sensitive regex. Requires Wait for exit and emits through the match connector while the command runs.",valueModes:["literal"]}),I("outputMatchMode","Output match behavior",o(["ONCE","EACH_MATCH"]),{default:"ONCE"})]},TERMINAL_RUN:{fields:[g("script","Script",{required:!0}),I("interpreter","Interpreter",o(["SHELL","NODE"])),y("environment","Environment variables"),B("credentials","Credential environment",{help:"JSON array of { name, credential: { id, kind, ownerId } } entries."})]}},R=()=>p("timeoutSeconds","Timeout (seconds)",{help:"How long to keep waiting before the step fails. Leave empty to wait for as long as the work takes."});function T(e,A){for(let t of e){let e=v[t];if(!e)continue;let r=new Set(e.fields.map(({key:e})=>e));e.fields=[...e.fields,...A().filter(({key:e})=>!r.has(e))]}}function G(e=[]){return{fields:[...e,y("filters","Filters",{help:"Match when each session path equals the given value.",recordValueType:"json"})]}}T(["WORKTREE_CREATE","WORKTREE_CHANGE_BRANCH","WORKTREE_OPERATION","WORKTREE_PREPARATION","WORKTREE_SET_AUTO_SYNC","WORKTREE_DELETE","WORKTREE_GIT_OPERATION","WORKTREE_MOVE","WORKTREE_WAIT_PUSH_READY","WORKTREE_SNAPSHOT","CODEBASE_FETCH_REFRESH","CODEBASE_GIT_OPERATION","BUILD_START","BUILD_IMPORT_COVERAGE","BUILD_EXPORT","BUILD_DEPLOY","DISK_SPACE_REFRESH","TERMINAL_RUN","RUN_CREATE_PLAN","RUN_CREATE_SESSION","RUN_PLAY_PLAN","RUN_FOLLOW_UP","RUN_REVISE_ANSWER","SAVED_COMMAND","CUSTOM_COMMAND","COMMAND_RERUN","BUILD_REBUILD","BUILD_DATA_REFRESH","TAILSCALE_SERVE_INSPECT","TAILSCALE_SERVE_UPSERT_TEMPLATE","TAILSCALE_SERVE_SET_AGENT_ENABLED","TAILSCALE_SERVE_DELETE_TEMPLATE","SIGNING_REFRESH","SIGNING_SYNC_PROFILE","SIGNING_DELETE_EXPIRED","SKILL_APPLY","GITHUB_WAIT_CHECKS","GITLAB_WAIT_PIPELINE","CONTROL_SUBWORKFLOW","CONTROL_WAIT_UNTIL"],()=>[p("cadenceSeconds","Poll cadence (seconds)",{help:"How often to check whether the work has finished. Leave empty for this step's default."}),R()]),T(["HUMAN_CONFIRM","HUMAN_CHOICE"],()=>[R()]);let M=["BUILD_TEST_THRESHOLD","BUILD_COVERAGE_THRESHOLD","AGENT_DISK_THRESHOLD","CCUSAGE_THRESHOLD","RUN_USAGE_THRESHOLD","BUILD_DATA_THRESHOLD","AGENT_RESOURCE_THRESHOLD","SIGNING_ASSET_EXPIRING"],N=Object.fromEntries(["MANUAL","MANUAL_CHOICE","RESOURCE_MANUAL","RESOURCE_MANUAL_CHOICE","SCHEDULE","WORKFLOW_FINISHED","GITHUB_PR_STATE","GITHUB_REVIEW_CHANGES_REQUESTED","GITHUB_REVIEW_COMMENT","GITHUB_PR_CLOSED","GITHUB_CHECK_FAILED","GITHUB_PUSH_DEFAULT","GITHUB_WORKFLOW_SUCCEEDED","GITHUB_ISSUE_COMMAND","GITHUB_ACTIONS_RESULT","GITHUB_PR_LABEL","GITLAB_MR_STATE","GITLAB_REVIEW_CHANGES_REQUESTED","GITLAB_REVIEW_COMMENT","GITLAB_MR_CLOSED","GITLAB_PIPELINE_FAILED","GITLAB_PUSH_DEFAULT","GITLAB_PIPELINE_SUCCEEDED","GITLAB_NOTE_COMMAND","GITLAB_PIPELINE_RESULT","GITLAB_MR_LABEL","BUILD_RESULT","BUILD_TEST_THRESHOLD","BUILD_COVERAGE_THRESHOLD","BUILD_HOOK_FAILED","AGENT_CONNECTION","AGENT_JOB_FAILED","AGENT_DISK_REPORT","AGENT_DISK_THRESHOLD","AGENT_DISK_STATE_CHANGED","AGENT_DISK_CLEANUP_RESULT","CCUSAGE_THRESHOLD","WORKTREE_CREATED","WORKTREE_BEHIND","WORKTREE_CONFLICT","WORKTREE_MISSING","WORKTREE_DIVERGED","WORKTREE_DIRTY_DURATION","WORKTREE_NEW_COMMIT","CODEBASE_REMOTE_BRANCH","JIRA_STATUS","JIRA_LABEL","JIRA_ASSIGNED_SELF","JIRA_SOURCE_NEW_TICKET","JIRA_MENTION","JIRA_SPRINT_STARTED","JIRA_ISSUE_CREATED","JIRA_ISSUE_DELETED","JIRA_ISSUE_COMMAND","JIRA_ATTACHMENT_ADDED","JIRA_ISSUE_LINKED","RUN_STARTED","RUN_COMPLETED","RUN_QUESTION_NEEDED","RUN_QUESTION_ANSWERED","RUN_PAUSED","RUN_CONTINUED","RUN_FAILED","RUN_CANCELLED","RUN_PLAN_PLAYED","RUN_FOLLOW_UP","RUN_IMPORTED","RUN_USAGE_THRESHOLD","RUN_EVENT_MATCH","COMMAND_RUN_RESULT","COMMAND_OUTPUT_MATCH","SKILL_SYNC_RESULT","SKILL_SYNC_CONFLICT","GITHUB_PIPELINE_STATUS_CHANGED","GITHUB_PR_SYNCHRONIZED","GITHUB_REVIEW_APPROVED","GITLAB_PIPELINE_STATUS_CHANGED","GITLAB_MR_SYNCHRONIZED","GITLAB_REVIEW_APPROVED","GITLAB_JOB_STATUS_CHANGED","JIRA_TICKET_UPDATED","JIRA_COMMENT_ADDED","JIRA_WORKLOG_ADDED","JIRA_SPRINT_ENDED","CODEBASE_SYNC_STATE_CHANGED","CODEBASE_OPERATION_FAILED","WORKTREE_SYNC_STATE_CHANGED","WORKTREE_AUTOMATION_RESULT","WORKTREE_CLEAN","PUSH_NOTIFICATION_RESULT","IOS_DEVICE_ENROLLED","IOS_DEVICE_REGISTRATION_RESULT","SIGNING_OPERATION_RESULT","SIGNING_ASSET_EXPIRING","BUILD_DATA_THRESHOLD","BUILD_DATA_CLEANUP_RESULT","POLLING_OPERATION_STATE","MODEL_COST_CATALOG_CHANGED","CREDENTIAL_STORE_DEGRADED","AGENT_RESOURCE_THRESHOLD","AGENT_VERSION_CHANGED","TOOL_CALL_RESULT","SSE_REQUEST_OPENED","SSE_EVENT_EMITTED","SSE_BREAKPOINT_WAITING","SSE_BREAKPOINT_RESOLVED","SSE_STREAM_COMPLETED","SSE_STREAM_FAILED"].map(e=>{if("RESOURCE_MANUAL"===e||"RESOURCE_MANUAL_CHOICE"===e)return[e,G([I("resourceKind","Resource kind",o(n.WORKFLOW_RESOURCE_KINDS),{required:!0}),..."RESOURCE_MANUAL_CHOICE"===e?[Q("choices","Choices",{required:!0})]:[]])];if("MANUAL_CHOICE"===e)return[e,G([Q("choices","Choices",{required:!0})])];if("SCHEDULE"===e)return[e,G([p("cadenceSeconds","Cadence (seconds)",{required:!0})])];if("GITHUB_ISSUE_COMMAND"===e||"GITLAB_NOTE_COMMAND"===e){let A="GITLAB_NOTE_COMMAND"===e;return[e,G([w(A?"allowedUsernames":"allowedLogins",A?"Allowed usernames":"Allowed logins",{placeholder:"octocat",required:!0}),h("commandPattern","Command pattern (RE2)",{placeholder:"^/deploy\\b$",required:!0,valueModes:["literal","interpolation"]})])]}return"JIRA_ISSUE_COMMAND"===e?[e,G([w("allowedAccountIds","Allowed account IDs",{placeholder:"5b10a2844c20165700ede21g",required:!0}),h("commandPattern","Command pattern (RE2)",{placeholder:"^/deploy\\b$",required:!0,valueModes:["literal","interpolation"]})])]:"COMMAND_OUTPUT_MATCH"===e?[e,G([h("outputPattern","Output pattern (RE2)",{placeholder:"error|failed",required:!0,valueModes:["literal","interpolation"]})])]:M.includes(e)?[e,G([h("thresholdPath","Threshold path",{placeholder:"build.testSummary.failed"}),I("thresholdOperator","Operator",D),B("thresholdValue","Threshold value")])]:[e,G()]}));function O(e,A){return"step"===A?v[e]:N[e]}function H(e,A,t){let r=function(e,A){let t=O(e,A);if(!t)return null;let r=new Set,i=new Set;for(let e of t.fields){for(let A of"model"===e.control&&e.modelKeys?[e.modelKeys.provider,e.modelKeys.model,e.modelKeys.effort]:[e.key])r.add(A);e.required&&i.add(e.key)}return{described:r,required:i}}(e,A);if(!r||!t||"object"!=typeof t||Array.isArray(t))return(0,a.workflowValueSessionPaths)(t);let i=new Set;for(let[e,A]of Object.entries(t))(!r.described.has(e)||r.required.has(e))&&(0,a.workflowValueSessionPaths)(A,i);return i}e.s(["getConfigDescriptor",0,O,"requiredConfigSessionPaths",0,H],222335);let U=["EQ","NE","GT","GTE","LT","LTE","CONTAINS","MATCHES","EXISTS"],_={type:"object",title:"Session binding",description:"Reads the value from run session data at `path` instead of hard-coding it.",properties:{source:{const:"SESSION"},path:{type:"string",description:"Dotted session path, e.g. `ticket.key` or `pr.number`."}},required:["source","path"],additionalProperties:!1},x={type:"object",title:"Literal wrapper",description:"An explicit constant. Equivalent to writing the value directly; the editor uses it to record that a field was pinned rather than bound.",properties:{source:{const:"LITERAL"},value:{}},required:["source"],additionalProperties:!1};function L(e,A,t){let r=t.valueModes??[],i=[r.includes("session")?"May also be a session binding.":null,r.includes("interpolation")?"Strings here — including strings nested inside the value — may carry `{{path}}` interpolation tokens, e.g. `{{worktree.baseBranch}}`.":null].filter(Boolean),n=i.length?{...A,description:[A.description,...i].filter(Boolean).join(" ")}:A;return r.includes("session")?{anyOf:[e,_,x],...n}:{...e,...n}}function P(e){let A=e.options?function(e){if("static"===e.kind){let A=e.options.filter(({label:e})=>e);return A.length?A.map(({value:e,label:A})=>`\`${e}\` — ${A}`).join("; "):null}let A=e.scopeFrom?` Scoped by the sibling \`${e.scopeFrom}\` value.`:"",t=e.sessionPath?` Usually bound to \`${e.sessionPath}\`.`:"";return`Identifier of a ${e.resource} known to the control plane.${t}${A}`}(e.options):null,t={description:[e.label,e.help,A].filter(Boolean).join(" — ")};return e.placeholder&&(t.examples=[e.placeholder]),void 0!==e.default&&(t.default=e.default),L(function(e){switch(e.control){case"number":return{type:e.integer?"integer":"number",...void 0===e.minimum?{}:{minimum:e.minimum},...void 0===e.maximum?{}:{maximum:e.maximum}};case"boolean":return{type:"boolean"};case"enum":{let A=e.options;if(A?.kind==="static")return{type:"string",enum:A.options.map(({value:e})=>e)};return{type:"string"}}case"resource":case"model":case"text":default:return{type:"string"};case"resourceMulti":case"stringList":case"mcpPresetMulti":return{type:"array",items:{type:"string"}};case"record":return{type:"object",additionalProperties:"json"===e.recordValueType?{}:{type:"string"}};case"condition":return{$ref:"#/$defs/condition"};case"choiceOptions":return{type:"array",description:"Buttons offered to the person answering.",items:{type:"object",properties:{label:{type:"string"},description:{type:"string"}},required:["label"],additionalProperties:!1}};case"triggerChoices":return{type:"array",minItems:1,description:"Options this trigger offers. Each `key` names an outgoing handle on the trigger, so edges stay attached when a label is renamed.",items:{type:"object",properties:{key:{type:"string",pattern:n.WORKFLOW_CHOICE_KEY_PATTERN.source},label:{type:"string"},description:{type:"string"}},required:["key","label"],additionalProperties:!1}};case"json":return{}}}(e),t,e)}function K(e,A){let t=O(e,A);if(!t)return{type:"object",additionalProperties:!0};let r={},i=[],n=!1;for(let e of t.fields){for(let[A,t]of("condition"===e.control&&(n=!0),"model"===e.control?function(e){let A=e.modelKeys;if(!A)return[[e.key,P(e)]];let t=(A,t)=>[A,L({type:"string"},{description:t},e)];return[t(A.provider,"AI provider that serves the model."),t(A.model,"Model identifier, as listed by the provider catalog."),t(A.effort,"Reasoning effort, when the model supports it.")]}(e):[[e.key,P(e)]]))r[A]=t;e.required&&i.push(e.key)}let a={type:"object",properties:r,additionalProperties:!0};return i.length&&(a.required=i),n&&(a.$defs={condition:{type:"object",description:"A condition tree. `ALL`/`ANY` combine nested conditions, `NOT` negates one, and the comparison operators test `left` against `right`.",anyOf:[{properties:{op:{enum:["ALL","ANY"]},conditions:{type:"array",items:{$ref:"#/$defs/condition"}}},required:["op","conditions"]},{properties:{op:{const:"NOT"},condition:{$ref:"#/$defs/condition"}},required:["op","condition"]},{properties:{op:{enum:[...U]},left:{description:"Value to test — usually a session binding. `EXISTS` needs only this side."},right:{description:"Value to compare against."}},required:["op","left"]}]}}),a}function q(e){let A=e?.outputPattern;return"string"==typeof A&&A.length?A:null}function J(e){if(!e.length)throw Error("Output pattern cannot be empty");if(e.length>1024)throw Error("Output pattern must not exceed 1024 characters")}e.s(["COMMAND_OUTPUT_MATCH_BUFFER_BYTES",0,0x1000000,"commandOutputMatchMode",0,function(e){return e?.outputMatchMode==="EACH_MATCH"?"EACH_MATCH":"ONCE"},"commandOutputPattern",0,q,"validateCommandOutputPattern",0,J],69988);let F="aide.workflow";function j(e){let A=e?.choices;if(!Array.isArray(A))return[];let t=[],r=new Set;for(let e of A)!(!e||"object"!=typeof e||Array.isArray(e))&&(!(0,n.isWorkflowChoiceKey)(e.key)||r.has(e.key)||(r.add(e.key),t.push({key:e.key,label:"string"==typeof e.label&&e.label.trim()?e.label:e.key,description:"string"==typeof e.description?e.description:""})));return t}let z={BUILD:["build.*","worktree.*","codebase.*","agent.*","repo.*","ticket.*"],CODEBASE:["codebase.*","agent.*","repo.*"],JIRA_TICKET:["ticket.*","comment.*"],AGENT_RUN:["run.*","worktree.*","codebase.*","agent.*","repo.*","ticket.*"],GITHUB_PIPELINE:["pipeline.*","repo.*","pr.*","worktree.*","codebase.*","agent.*","ticket.*"],GITHUB_JOB:["job.*","pipeline.*","repo.*","pr.*","worktree.*","codebase.*","agent.*","ticket.*"],GITLAB_MERGE_REQUEST:["pr.*","repo.*","worktree.*","ticket.*"],GITLAB_PIPELINE:["pipeline.*","repo.*","pr.*","worktree.*","ticket.*"],GITLAB_JOB:["job.*","pipeline.*","repo.*","pr.*","worktree.*","ticket.*"],PULL_REQUEST:["pr.number","repo.displayOrigin"],WORKTREE:["worktree.*","codebase.*","agent.*","repo.*","ticket.*","pr.*"],COMMAND_RUN:["command.*","agent.*","worktree.*","codebase.*","repo.*"],SKILL:["skill.*","repo.*","codebase.*"],SKILL_SYNC:["skillSync.*","skill.*","repo.*","codebase.*","worktree.*"],IOS_DEVICE:["device.*"],SIGNING_PROFILE:["signingProfile.*","device.*","agent.*"],PUSH_NOTIFICATION_BATCH:["pushBatch.*"],BUILD_DATA_COLLECTION:["buildData.*","agent.*","worktree.*","codebase.*"]};function Y(e){let A=e?.resourceKind;return"string"==typeof A&&n.WORKFLOW_RESOURCE_KINDS.includes(A)?A:null}function V(e,A){if(!(0,n.isResourceTriggerKind)(e))return[];let t=Y(A);return t?z[t]:[]}let Z=(e,A,t,r,i,a,o)=>({kind:e,category:A,label:t,description:o.description,details:o.details,execution:r,configSchema:K(e,"step"),capabilityFlags:[r,...o.mutatesExternal?["MUTATES_EXTERNAL"]:[],...o.mutatesWorktree?["MUTATES_WORKTREE"]:[]],requiredPaths:i,providedPaths:a,sourceHandles:(0,n.workflowStaticSourceHandles)(e),mutatesExternal:o.mutatesExternal??!1,mutatesWorktree:o.mutatesWorktree??!1}),W=["worktree.*","codebase.*","agent.*","repo.*","ticket.*","pr.*"],$=["codebase.*","agent.*","repo.*"],X=(e,A,t,r=[],i=["steps.<stepId>.*"],n={})=>Z(e,A,t,"SERVER",r,i,{description:`${t} using the control plane's typed service API.`,details:`${t} is a first-class action with validated configuration, audit-friendly output, resource links where available, and normal workflow failure routing.`,...n}),ee=[X("COMMAND_RERUN","Commands","Rerun command",["command.id"],["command.*"]),X("COMMAND_TERMINATE","Commands","Terminate command",["command.id"],["command.*"]),X("COMMAND_READ_OUTPUT","Commands","Read command output",["command.id"],["command.*"]),X("WORKTREE_INSPECT_DIFF","Worktrees","Inspect worktree diff",["worktree.id"],["worktree.diff.*"]),X("WORKTREE_UPDATE_METADATA","Worktrees","Update worktree metadata",["worktree.id"],W),X("WORKTREE_MOVE_CONTROL","Worktrees","Control worktree move",[],W,{mutatesWorktree:!0}),X("BUILD_REBUILD","Builds","Rebuild build",["build.id"],["build.*"]),X("BUILD_GENERATE_REPORT","Builds","Generate build report",["build.id"],["build.*"]),X("BUILD_DELETE","Builds","Delete builds",[],["build.*"]),X("SKILL_PREPARE_SYNC","Skills","Prepare skill sync",[],["skillSync.*"]),X("SKILL_RESOLVE_SYNC","Skills","Resolve skill sync conflict",["skillSync.id"],["skillSync.*"]),X("SKILL_SKIP_SYNC","Skills","Skip skill sync",["skillSync.id"],["skillSync.*"]),X("BUILD_DATA_REFRESH","Build Data","Refresh build data",[],["buildData.*"]),X("BUILD_DATA_DELETE","Build Data","Delete build data",["buildData.id"],["buildData.*"]),X("BUILD_DATA_SET_LOCK","Build Data","Set build-data lock",["buildData.id"],["buildData.*"]),X("TAILSCALE_SERVE_INSPECT","Tailscale","Inspect Tailscale Serve",[],["tailscale.*"],{mutatesExternal:!0}),X("TAILSCALE_SERVE_UPSERT_TEMPLATE","Tailscale","Upsert Tailscale Serve template",[],["tailscale.*"],{mutatesExternal:!0}),X("TAILSCALE_SERVE_SET_AGENT_ENABLED","Tailscale","Set Tailscale Serve agent enabled",["tailscale.templateId"],["tailscale.*"],{mutatesExternal:!0}),X("TAILSCALE_SERVE_DELETE_TEMPLATE","Tailscale","Delete Tailscale Serve template",["tailscale.templateId"],["tailscale.*"],{mutatesExternal:!0}),X("SIGNING_REFRESH","Signing","Refresh signing assets",[],["signing.*"]),X("SIGNING_SYNC_PROFILE","Signing","Sync signing profile",["signingProfile.id"],["signing.*"]),X("SIGNING_DELETE_EXPIRED","Signing","Delete expired profiles",[],["signing.*"]),X("IOS_DEVICE_REGISTER","Devices","Register iOS device",["device.id"],["device.*"],{mutatesExternal:!0}),X("IOS_DEVICE_REJECT","Devices","Reject iOS device",["device.id"],["device.*"],{mutatesExternal:!0}),X("AGENT_RECONCILE","Agents","Reconcile agents",[],["agent.*"]),X("AGENT_UPDATE_CADENCE","Agents","Update agent cadence",["agent.id"],["agent.*"]),X("CCUSAGE_COLLECT","Operations","Collect usage",[],["usage.*"]),X("MODEL_COST_REFRESH","Operations","Refresh model costs",[],["modelCosts.*"],{mutatesExternal:!0}),X("GITHUB_UPDATE_PR","GitHub","Update pull request",["pr.number","repo.*"],["pr.*"],{mutatesExternal:!0}),X("GITHUB_SUBMIT_REVIEW","GitHub","Submit pull request review",["pr.number","repo.*"],["pr.*"],{mutatesExternal:!0}),X("GITHUB_REQUEST_REVIEWERS","GitHub","Request pull request reviewers",["pr.number","repo.*"],["pr.*"],{mutatesExternal:!0}),X("GITHUB_DISPATCH_WORKFLOW","GitHub","Dispatch GitHub workflow",["repo.*"],["pipeline.*"],{mutatesExternal:!0}),...[["GITLAB_LOAD_MR","Load merge request",!1],["GITLAB_CREATE_MR","Create merge request",!0],["GITLAB_UPDATE_MR","Update merge request",!0],["GITLAB_SUBMIT_REVIEW","Submit merge request review",!0],["GITLAB_REPLY_DISCUSSION","Reply to discussion",!0],["GITLAB_SET_DISCUSSION_RESOLVED","Resolve discussion",!0],["GITLAB_MERGE_MR","Merge merge request",!0],["GITLAB_SET_MR_LABELS","Set merge request labels",!0],["GITLAB_REQUEST_REVIEWERS","Request merge request reviewers",!0],["GITLAB_CREATE_PIPELINE","Create pipeline",!0],["GITLAB_RETRY_PIPELINE","Retry pipeline",!0],["GITLAB_RETRY_JOB","Retry job",!0],["GITLAB_CANCEL_PIPELINE","Cancel pipeline",!0]].map(([e,A,t])=>X(e,"GitLab",String(A),[],String(e).includes("PIPELINE")||String(e).includes("JOB")?["pipeline.*","job.*"]:["pr.*"],{mutatesExternal:!!t})),X("GITLAB_SAVE_AUTO_RETRY","GitLab Pipelines","Install auto-retry rule",["pipeline.id"],[],{mutatesExternal:!0}),X("GITLAB_WAIT_PIPELINE","GitLab Pipelines","Wait for pipeline",["pipeline.id"],["pipeline.*"]),X("JIRA_CREATE_TICKET","Jira","Create Jira ticket",[],["ticket.*"],{mutatesExternal:!0}),X("JIRA_ADD_WORKLOG","Jira","Add Jira worklog",["ticket.key"],["ticket.*"],{mutatesExternal:!0}),X("JIRA_LINK_TICKETS","Jira","Link Jira tickets",["ticket.key"],["ticket.*"],{mutatesExternal:!0})],eA=[Z("JIRA_LOAD_TICKET","Jira","Load Jira ticket","SERVER",[],["ticket.*"],{description:"Reads a Jira issue and puts its fields — key, title, type, status, assignee, labels — into session data as `ticket.*`.",details:'Needs a configured Jira credential. Leave the identifier unset to take it from session data. Results are served from cache unless "Bypass cache" is set, so a step that reads a ticket right after changing it should force a refresh. Fails when the issue does not exist or the credential cannot see it. Read-only: it changes nothing in Jira.'}),Z("JIRA_TRANSITION","Jira","Transition Jira ticket","SERVER",["ticket.key"],["ticket.*"],{description:"Moves a ticket to another status by applying one of its workflow transitions.",details:"Takes a transition id, not a status name — the ids are board-specific, so read them from the ticket's available transitions rather than hard-coding a guess. Fails when the transition is not currently available on that issue, which is what happens if an earlier step already moved it. Refreshes `ticket.*` from the response.",mutatesExternal:!0}),Z("JIRA_COMMENT","Jira","Add Jira comment","SERVER",["ticket.key"],["ticket.*"],{description:"Posts a comment on a Jira issue, written in Markdown or Jira wiki markup.",details:"The comment body is converted from Markdown by default; choose Jira wiki format to pass markup through untouched. Comments are never deduplicated, so a step that runs twice comments twice — guard it with a condition if the workflow can retry. Refreshes `ticket.*` from the response.",mutatesExternal:!0}),Z("JIRA_ASSIGN","Jira","Assign Jira ticket","SERVER",["ticket.key"],["ticket.*"],{description:"Sets the assignee of a Jira issue, or clears it when no account is given.",details:"Takes a Jira account id rather than a display name or email. Leaving the assignee empty unassigns the ticket. Fails when the account cannot be assigned on that project. Refreshes `ticket.*` from the response.",mutatesExternal:!0}),Z("JIRA_UPDATE_FIELDS","Jira","Update Jira fields","SERVER",["ticket.key"],["ticket.*"],{description:"Patches arbitrary fields on a Jira issue — labels, summary, custom fields — from a JSON object.",details:"The escape hatch for anything the dedicated Jira steps do not cover. Keys are passed to the Jira update API as given, so an unknown or screen-hidden field fails the step. Prefer the specific steps for status and assignee. Refreshes `ticket.*` from the response.",mutatesExternal:!0}),Z("JIRA_RESOLVE_BRANCH","Jira","Resolve ticket branch","SERVER",["ticket.key","ticket.title","ticket.type"],["worktree.branch","ticket.key","ticket.title","ticket.type"],{description:"Works out the branch name a ticket would get under the codebase's naming convention, without creating anything.",details:"A preview step: it writes `worktree.branch` plus the ticket key, title, and type into session data and touches neither Git nor Jira. Use it before Create worktree when you want the branch name available to earlier steps — for a worktree keyed off a ticket, Create worktree in TICKET mode derives the same name on its own."}),Z("GITHUB_LOAD_PR","GitHub","Load pull request","SERVER",[],["pr.*"],{description:"Reads a pull request and puts its state, branches, labels, checks, and review threads into session data as `pr.*`.",details:"Needs a configured GitHub credential. Owner and repository default to the repository already in session data, and the number to `pr.number`. Fails when the pull request does not exist or the credential cannot see it. Read-only."}),Z("GITHUB_MERGE_PR","GitHub","Merge pull request","SERVER",["pr.number"],["pr.state"],{description:"Merges an open pull request using squash, merge, or rebase, optionally overriding the commit message.",details:"Checks mergeability first and fails with GitHub's own blocking reason — conflicts, failing required checks, missing approvals, an already-closed pull request — rather than forcing the merge. Commit headline and body default to what GitHub would use. Squash is the default method. Irreversible, and repository policy may delete the head branch as a side effect, which strands any worktree still on it. Writes `pr.state`.",mutatesExternal:!0}),Z("GITHUB_COLLECT_REVIEW_THREADS","GitHub","Collect review comments","SERVER",["pr.number"],["pr.unresolvedThreads"],{description:"Gathers the unresolved review threads on a pull request into `pr.unresolvedThreads`.",details:"Resolved threads are filtered out. The result is a list, so it pairs with For each to work through the comments one at a time — the reply and resolve steps take a single thread id from the iteration. Read-only."}),Z("GITHUB_REPLY_REVIEW_THREAD","GitHub","Reply to review thread","SERVER",["pr.unresolvedThreads"],[],{description:"Posts a reply into an existing pull request review thread.",details:"Takes the thread id from Collect review comments, usually inside a For each. Replies are not deduplicated, so a retried step comments twice. Replying does not resolve the thread — follow with Resolve review thread when that is the intent.",mutatesExternal:!0}),Z("GITHUB_SET_REVIEW_THREAD_RESOLVED","GitHub","Resolve review thread","SERVER",["pr.unresolvedThreads"],[],{description:"Marks a pull request review thread resolved, or reopens it.",details:"Takes the thread id from Collect review comments. Resolving is the default; clear the flag to unresolve. Reviewers see this as the bot resolving their comment, so it is usually paired with a reply that explains what changed.",mutatesExternal:!0}),Z("GITHUB_CREATE_PR","GitHub","Open pull request","SERVER",["worktree.branch","worktree.baseBranch"],["pr.*"],{description:"Opens a pull request from the worktree's branch, optionally as a draft.",details:"Head branch defaults to `worktree.branch`, base to `worktree.baseBranch`, and the title to `ticket.title`. The head branch must already be pushed — put Wait for push-ready or a push operation in front of this step. Fails when a pull request is already open for the same branch pair. Writes the new pull request to `pr.*`.",mutatesExternal:!0}),Z("GITHUB_SET_PR_LABELS","GitHub","Set pull request labels","SERVER",["pr.number"],["pr.labels"],{description:"Replaces the labels on a pull request with the given list.",details:"This sets rather than adds — labels not in the list are removed, so include the ones you want to keep. Labels must already exist in the repository. Writes `pr.labels`.",mutatesExternal:!0}),Z("GITHUB_RETRY_PIPELINE","GitHub Actions","Retry failed pipeline","SERVER",["pipeline.runId"],["pipeline.status"],{description:"Re-runs the failed jobs of a check suite, leaving the jobs that passed alone.",details:"Targets a check suite rather than a single job — use Retry workflow job for that. Re-running consumes Actions minutes and re-executes whatever those jobs do, including deployments. Pair it with a Time delay and a retry limit so a permanently broken pipeline is not retried forever. Writes `pipeline.status`.",mutatesExternal:!0}),Z("GITHUB_RETRY_JOB","GitHub Actions","Retry workflow job","SERVER",["pipeline.failedJobs"],[],{description:"Re-runs one job of a GitHub Actions workflow run.",details:"Needs the repository, check suite, and job ids together — typically read out of `pipeline.failedJobs` inside a For each. Use Retry failed pipeline to re-run every failed job at once instead.",mutatesExternal:!0}),Z("GITHUB_CANCEL_WORKFLOW_RUN","GitHub Actions","Cancel workflow run","SERVER",["pipeline.runId"],["pipeline.status"],{description:"Cancels an in-progress GitHub Actions workflow run.",details:"Falls back to `repo.id` and `pipeline.runId` from session data. Force-cancel skips the graceful shutdown that lets `always()` cleanup jobs finish, so leave it off unless a run is stuck. Cancelling a run that has already finished is an error. Writes `pipeline.status`.",mutatesExternal:!0}),Z("GITHUB_SAVE_AUTO_RETRY","GitHub Actions","Install auto-retry rule","SERVER",["pipeline.runId"],[],{description:"Saves a standing rule that automatically retries matching GitHub Actions failures.",details:"Persists configuration rather than acting once — the rule keeps applying after this run ends, and stays until something removes it. Takes the rule as a JSON object. Treat it as a settings change, not a step you re-run casually.",mutatesExternal:!0}),Z("GITHUB_WAIT_CHECKS","GitHub Actions","Wait for checks","WAIT",["pipeline.runId"],["pipeline.status","pipeline.conclusion","pipeline.jobs"],{description:"Parks the run until a GitHub Actions workflow run finishes, then continues on its conclusion.",details:"Polls until the run reaches a terminal status. Anything other than success fails the step, so route the failure handle to the recovery path — or set the step's failure policy to continue and branch on `pipeline.conclusion` yourself. Also refreshes `pipeline.jobs`. Without a timeout the wait is open-ended; a hung pipeline holds the workflow run indefinitely. Falls back to `repo.id` and `pipeline.runId`."}),Z("WORKTREE_CREATE","Worktrees","Create worktree","SERVER",["codebase.id"],W,{description:"Creates a Git worktree on the agent for a new, existing, or ticket-derived branch.",details:"Dispatches a job to the agent that owns the codebase and waits for it, so the agent must be online. Branch mode NEW cuts a branch from the base, EXISTING checks one out, and TICKET derives the name from `ticket.key`. Base branch falls back to `worktree.baseBranch` then `repo.defaultBranch`. Refreshes the created worktree, codebase, owning agent, repository, and any linked ticket. Creates real directories on disk.",mutatesWorktree:!0}),Z("WORKTREE_CHANGE_BRANCH","Worktrees","Change worktree branch","SERVER",["worktree.id"],W,{description:"Switches an existing worktree to a different branch, creating it if needed.",details:'Same branch modes as Create worktree. Uncommitted changes block the switch unless "Stash on failure" is set, which stashes them and retries — the stash is left for a human to deal with. Refreshes the worktree and all of its related resource context.',mutatesWorktree:!0}),Z("WORKTREE_COMMIT","Worktrees","Commit worktree changes","SERVER",["worktree.id"],W,{description:"Stages selected worktree changes and creates a Git commit on the agent.",details:"Stage all defaults on. Disable it and provide an exact list of changed paths for a partial commit; paths omitted from that list are left uncommitted. Signed commits follow effective Git configuration when the signed option is omitted. Dispatches an agent job, waits for completion, and refreshes worktree context.",mutatesWorktree:!0}),Z("WORKTREE_REFRESH_PULL_REQUEST","Worktrees","Refresh pull request","SERVER",["worktree.id"],["pr.*"],{description:"Forces exact-branch pull request discovery and refreshes the worktree's persisted pull request context.",details:"Uses the configured worktree, falling back to `worktree.id`. The step succeeds with `found: false` and clears `pr` when the branch has no open pull request.",mutatesWorktree:!0,mutatesExternal:!1}),Z("WORKTREE_OPERATION","Worktrees","Run worktree operation","SERVER",["worktree.id"],W,{description:"Runs one of the built-in worktree maintenance operations, such as syncing with the base branch or pushing.",details:"Dispatches an agent job and waits for it. Opening an editor is rejected here — it needs a human at the machine. Sync and push touch the remote and can conflict; check `worktree.pushStatus` afterwards or follow with Inspect worktree Git state.",mutatesWorktree:!0}),Z("WORKTREE_PREPARATION","Worktrees","Run worktree preparations","SERVER",["worktree.id"],[],{description:"Inspects, applies, or undoes the repository preparation rules for one worktree.",details:"Dispatches a preparation job to the owning agent and waits for its per-file result. Apply and Undo can overwrite managed paths, while Inspect only refreshes persisted status. Unsupported, offline, and unavailable worktrees fail with the service's explicit skip reason.",mutatesWorktree:!0}),Z("WORKTREE_SET_AUTO_SYNC","Worktrees","Set worktree Auto Sync","SERVER",["worktree.id"],["worktree.autoSync"],{description:"Enables, updates, retries, or cancels persistent Auto Sync for a worktree.",details:"An enabled rule rebases on the target branch whenever it changes and force-pushes with lease. A merge-conflict quick-action workflow can be selected as the automatic recovery path; unresolved conflicts pause the rule. Force is accepted only when preparations paused Auto Sync, destructively resets managed paths, and resumes the rule after a successful sync.",mutatesWorktree:!0,mutatesExternal:!0}),Z("WORKTREE_SET_AUTO_MERGE","Worktrees","Set worktree Auto Merge","SERVER",["worktree.id"],["worktree.autoMerge"],{description:"Enables, updates, retries, or cancels GitHub-native Auto Merge for a worktree.",details:"GitHub remains the authority for required checks and reviews. Optional post-merge actions can move the linked Jira ticket to its configured done status and safely delete a clean linked worktree.",mutatesWorktree:!0,mutatesExternal:!0}),Z("WORKTREE_DELETE","Worktrees","Delete worktree","SERVER",["worktree.id"],$,{description:"Removes a worktree from the agent, optionally deleting its remote branch too.",details:"Destroys the directory and any uncommitted work in it — there is no undo. Deleting the remote branch as well affects everyone, and closes any pull request from that branch. Do not put this before steps that still read `worktree.*`.",mutatesWorktree:!0}),Z("WORKTREE_MOVE","Worktrees","Move worktree","SERVER",["worktree.id"],W,{description:"Moves a worktree's branch and changes into another codebase, optionally deleting the source.",details:"Waits for the move job to finish. Used when a branch was started against the wrong checkout. Deleting the source destroys the original directory; leaving it keeps both, which means two worktrees on one branch. Refreshes `worktree.*` to point at wherever the work now lives.",mutatesWorktree:!0}),Z("WORKTREE_INSPECT","Worktrees","Inspect worktree","SERVER",["worktree.id"],["worktree.commits","worktree.changes","worktree.branchChanges","worktree.commitsTruncated","worktree.changesTruncated","worktree.branchChangesTruncated"],{description:"Reads the worktree's commits and changed files into `worktree.commits` and `worktree.changes`.",details:"Read-only. Use it to give a later condition or AI prompt something concrete to work from — for example to skip opening a pull request when nothing changed. For push/dirty state use Inspect worktree Git state instead, which is cheaper."}),Z("WORKTREE_INSPECT_GIT","Worktrees","Inspect worktree Git state","SERVER",["worktree.id"],["worktree.*"],{description:"Reads the worktree's Git status — dirty flag, ahead/behind counts, push status, conflicts — into `worktree.*`.",details:"Read-only and the cheap way to branch on repository state: gate a commit on `worktree.dirty`, or a sync on the worktree being behind. Use Inspect worktree when you need the actual commits and diffs."}),Z("WORKTREE_GIT_OPERATION","Worktrees","Run worktree Git operation","SERVER",["worktree.id"],W,{description:"Runs a specific Git operation in the worktree — pull, push, rebase, stash, and the rest.",details:'Dispatches an agent job and waits for it. Operations that rewrite history or touch the remote can fail on conflicts; "Stash changes first" clears the way for operations that need a clean tree. Prefer Run worktree operation for the higher-level sync and push flows, which handle more of the edge cases.',mutatesWorktree:!0}),Z("WORKTREE_WAIT_PUSH_READY","Worktrees","Wait for push-ready","WAIT",["worktree.id"],W,{description:"Parks the run until the worktree's branch is pushed and tracking a remote.",details:"The step to put between an AI session that commits and Open pull request, which needs the branch to exist on the remote. Resolves as soon as the branch is push-ready; without a timeout it waits indefinitely, so set one if a human may never push. Writes `worktree.pushStatus`."}),Z("WORKTREE_SNAPSHOT","Worktrees","Snapshot Git state","AGENT",["worktree.path"],["steps.<stepId>.snapshotId"],{description:"Captures a restorable checkpoint of the worktree's Git state before a risky step.",details:"Runs on the agent, so it needs `worktree.path` and an online agent. The snapshot id it writes is what run replay restores from, which makes this the step to place before anything that rewrites the tree. Snapshots cost disk on the agent."}),Z("CODEBASE_FETCH_REFRESH","Codebases","Fetch or refresh codebase","SERVER",["codebase.id"],$,{description:"Fetches remote refs for a codebase, or fully refreshes its cached metadata.",details:"Fetch updates remote-tracking branches; refresh re-reads the whole checkout and is slower. Runs as an agent job and waits. Fails when the agent skips the operation — usually because the codebase is missing or already busy. Put a fetch in front of steps that check whether a remote branch exists.",mutatesWorktree:!0}),Z("CODEBASE_INSPECT_GIT","Codebases","Inspect codebase Git state","SERVER",["codebase.id"],["codebase.*"],{description:"Reads the codebase checkout's Git status into `codebase.*`.",details:"Read-only. This is the primary checkout, not a worktree — use Inspect worktree Git state for per-branch work. Useful for refusing to start work when the base checkout is dirty or on an unexpected branch."}),Z("CODEBASE_GIT_OPERATION","Codebases","Run codebase Git operation","SERVER",["codebase.id"],$,{description:"Runs a Git operation against the codebase's primary checkout.",details:'Same operations as the worktree version, aimed at the main checkout that every worktree branches from — so a bad rebase or reset here affects all of them. "Stash changes first" clears local modifications out of the way. Runs as an agent job and waits.',mutatesWorktree:!0}),Z("BUILD_START","Builds","Start build or test","SERVER",["codebase.id","worktree.id"],["build.*"],{description:"Queues an iOS build, test, or archive run on the agent and waits for it to finish.",details:"Needs a build configuration id and an online agent; the destination and build scripts are optional. The step parks until the build reaches a terminal status, so a long test suite holds the workflow run. Failing builds fail the step — route the failure handle if you want to read the results anyway. Writes `build.*`, which the read-results and coverage steps then consume.",mutatesExternal:!0}),Z("BUILD_READ_TEST_RESULTS","Builds","Read test results","SERVER",["build.id"],["build.testSummary","build.tests"],{description:"Reads a finished build's test report into `build.testSummary` and `build.tests`.",details:"Fails outright when the report is not ready, so it belongs after Start build or test rather than in parallel with it. The summary carries the passed/failed counts a condition can branch on; the per-test list is the detail an AI prompt can be pointed at. Read-only."}),Z("BUILD_READ_COVERAGE","Builds","Read code coverage","SERVER",["build.id"],["build.coverageSummary","build.coverageFiles","build.changedCoverageFiles"],{description:"Reads a finished build's coverage report into `build.coverageSummary` and the per-file breakdowns.",details:'Fails when the coverage report is not ready — the build must have been run with coverage collection on. Also writes the changed-files breakdown, which is what a "coverage on this branch\'s changes" gate should read rather than the whole-project number. Read-only.'}),Z("BUILD_IMPORT_COVERAGE","Builds","Import coverage report","SERVER",["worktree.id"],["build.id","build.coverageSummary"],{description:"Reads a coverage file a test command wrote in the worktree and records it as a coverage report.",details:"Pair it with a Terminal command step that runs the test suite first: this step only reads what that run left behind, at the path given in `Coverage file`. The build name defaults to the workflow name and can be overridden. LCOV and Istanbul (`coverage-final.json`) are both understood, and AUTO tells them apart by the file itself. Runs as an agent job and waits. The report is attached to a new build record of its own, so it shows up on that build's coverage page and in the coverage picker on Changes; changed-line coverage is measured against the worktree's base branch, and is left out when that branch cannot be resolved. Writes the totals to `build.coverageSummary` and the new id to `build.id` — follow with Read code coverage for the per-file breakdown. Fails when the file is missing, unreadable, or describes no files."}),Z("BUILD_EXPORT","Builds","Export archive","SERVER",["build.id"],["build.exportId",...W],{description:"Exports a finished archive build into a distributable package on the agent.",details:"Needs export settings and an archive-action build. Runs as an agent job and waits. Writes files to the agent's disk and may talk to Apple's servers for signing, so it can fail on expired certificates or provisioning profiles.",mutatesExternal:!0}),Z("BUILD_DEPLOY","Builds","Deploy build","SERVER",["build.id"],W,{description:"Installs and launches an existing build on its destinations without rebuilding.",details:"Reuses the artifacts from a previous build, so it is much faster than building again. Destinations default to the ones the build already targeted. Waits for the deployment job. This puts the app on real or simulated devices — treat it as an external effect.",mutatesExternal:!0}),Z("BUILD_CANCEL","Builds","Cancel build","SERVER",["build.id"],["build.id","build.status"],{description:"Cancels a queued or running build.",details:"Aimed at a different build from the one this run started — Start build or test already waits for its own. Cancelling an already-finished build is a no-op rather than an error. Writes `build.status`.",mutatesExternal:!0}),Z("DISK_SPACE_LOAD","Disk space","Load disk-space monitor","SERVER",[],["agent.*","disk.*"],{description:"Loads the current Derived Data disk-space monitor snapshot for an agent.",details:"Targets the configured agent, then falls back to `agent.id` or `codebase.agentId`. The least-free monitored Derived Data volume supplies `disk.freeBytes`, `disk.freeGiB`, and the percentage fields; root and base-repository volumes remain in `disk.volumes` for context only. Read-only and does not request a new report."}),Z("DISK_SPACE_REFRESH","Disk space","Refresh disk-space monitor","WAIT",[],["agent.*","disk.*"],{description:"Requests an immediate disk report from an agent and waits for fresh telemetry.",details:"Targets the configured agent, then falls back to `agent.id` or `codebase.agentId`. Monitoring must be enabled. The step waits until `lastReportedAt` advances, then refreshes `agent.*` and `disk.*`; by default it polls every two seconds and times out after 180 seconds."}),Z("DISK_SPACE_UPDATE_THRESHOLDS","Disk space","Update disk thresholds","SERVER",[],["disk.normalThresholdGiB","disk.pressureThresholdGiB","disk.pollIntervalSeconds","disk.staleAfterSeconds"],{description:"Updates the global normal and pressure free-space thresholds.",details:"Changes the thresholds used for every monitored agent, automatic cleanup, and admission control. The pressure threshold must be positive and lower than the normal threshold. Writes the resulting global settings into `disk.*`."}),Z("DISK_SPACE_SET_MONITORING","Disk space","Set agent disk monitoring","SERVER",[],["agent.*","disk.*"],{description:"Enables or disables Derived Data disk-space monitoring for an agent.",details:"Targets the configured agent, then falls back to `agent.id` or `codebase.agentId`. Disabling monitoring also clears manual and automatic pressure mode and releases cleanup leases that have not started a job. Refreshes `agent.*` and `disk.*`."}),Z("DISK_SPACE_SET_PRESSURE_MODE","Disk space","Set disk pressure mode","SERVER",[],["agent.*","disk.*"],{description:"Enables or clears manual disk pressure mode for an agent.",details:"Targets the configured agent, then falls back to `agent.id` or `codebase.agentId`. Manual pressure mode uses the lower pressure threshold; automatic pressure mode remains controlled by cleanup availability. Refreshes `agent.*` and `disk.*`."}),Z("SKILL_APPLY","Skills","Apply skill group","SERVER",["worktree.id","repo.id"],["steps.<stepId>.status"],{description:"Syncs a skill group's files into the target checkout, or every skill when no group is chosen.",details:"Starts a skill sync run and waits for it. Writes skill files into the repository, which shows up as uncommitted changes — commit or discard them before a step that needs a clean tree. Leave the group empty to sync everything.",mutatesWorktree:!0}),Z("RUN_CREATE_PLAN","AI runs","Create plan and wait","SERVER",["worktree.id"],["run.<stepId>.*"],{description:"Starts an AI planning run against the worktree and waits for the plan to be produced.",details:"Requires a worktree, a provider/model, and a prompt. Plans use a separate FIFO worktree queue and allow unlimited concurrent plans by default; set the worktree concurrency limit to 1–32 to cap them, or 0 for unlimited. Planning inspects the code but does not change it — use Run AI session and wait to actually make edits, or follow with Run completed plan. If the run asks a question it parks until someone answers, so pair long workflows with a question-needed trigger. Writes the run under `run.<stepId>.*`, which later steps reference by this step's id."}),Z("RUN_CREATE_SESSION","AI runs","Run AI session and wait","SERVER",["worktree.id"],["run.<stepId>.*"],{description:"Starts an AI coding session against the worktree and waits for it to finish.",details:"The workhorse step: the agent edits files in the worktree, so the tree is dirty afterwards and the changes still need committing and pushing. Sessions use a separate FIFO worktree queue with one active session by default; set the worktree concurrency limit to 2–32 for parallel sessions or 0 for unlimited. Requires a worktree, a provider/model, and a prompt; attachments and web search are optional. Parks on questions until answered. Writes `run.<stepId>.*`.",mutatesWorktree:!0}),Z("RUN_PLAY_PLAN","AI runs","Run completed plan","SERVER",[],["run.<stepId>.*"],{description:"Executes a plan that has already been produced, turning it into real code changes.",details:"Takes the plan's run id — usually `run.<planStepId>.id` from an earlier Create plan step. The plan must have completed. The resulting Session joins the worktree's FIFO Session queue, which allows one active Session by default; use 0 for unlimited or 2–32 for a larger limit. This is the half of the plan/execute split that touches the worktree. Writes a new run under `run.<stepId>.*`.",mutatesWorktree:!0}),Z("RUN_FOLLOW_UP","AI runs","Follow up run","SERVER",[],["run.<stepId>.*"],{description:"Starts a new AI run that continues from an existing one, resuming its context or starting fresh.",details:'RESUME keeps the previous conversation, FRESH starts over in the same worktree, and RESEND replays the original prompt. The new run joins the source kind\'s separate FIFO worktree queue and defaults to unlimited concurrency for Plans or one active run for Sessions; use 0 for unlimited or 1–32 for a finite limit. Needs the source run id plus a new prompt. The natural step for "fix the review comments" loops after a first session. Writes `run.<stepId>.*`.'}),Z("RUN_STEER","AI runs","Steer active run","SERVER",[],["run.<stepId>.*"],{description:"Sends extra instructions into a run that is already in progress.",details:"Only affects a run that is still going — it does not restart a finished one, which is what Follow up run is for. Because the steps in this workflow that start runs also wait for them, steering usually targets a run started elsewhere, reached through a run trigger."}),Z("RUN_ANSWER","AI runs","Answer run question","SERVER",[],["run.<stepId>.*"],{description:"Answers a question an AI run is blocked on so it can carry on.",details:"Needs the question batch id, typically from `run.questions` seeded by a run-needs-an-answer trigger, and answers keyed by question id. This answers questions asked by an AI run — the Request confirmation and Ask user to choose steps ask questions of a human about the workflow itself."}),Z("RUN_PAUSE","AI runs","Pause run","SERVER",[],["run.<stepId>.*"],{description:"Pauses an in-progress AI run.",details:"The run stops at its next checkpoint and stays paused until something continues it. Falls back to `run.id`. Pausing an already-finished run fails."}),Z("RUN_CONTINUE","AI runs","Continue run","SERVER",[],["run.<stepId>.*"],{description:"Resumes a paused AI run.",details:"The counterpart to Pause run. Fails when the run is not paused. Falls back to `run.id`."}),Z("RUN_CANCEL","AI runs","Cancel run","SERVER",[],["run.<stepId>.*"],{description:"Cancels an AI run, stopping its work.",details:"Whatever the run already wrote to the worktree stays — cancelling stops further work, it does not roll anything back. Falls back to `run.id`."}),Z("RUN_REVISE_ANSWER","AI runs","Revise answer and rewind","SERVER",[],["run.<stepId>.*"],{description:"Rewinds a run to an earlier question, replaces the answer, and replays from there.",details:"Two-phase: the step prepares the revision, parks, and applies it once the run is ready. Rolling back restores the worktree to the checkpoint at that question, discarding work done since — stash first if that work matters. The heavy way to correct a wrong answer; Follow up run is usually enough.",mutatesWorktree:!0}),Z("RUN_READ_RESULT","AI runs","Read run result","SERVER",[],["run.<stepId>.*"],{description:"Loads a finished run's events, questions, token usage, and linked items into session data.",details:"Read-only. Gives later steps the run's actual output to work from — a summary to put in a Jira comment, usage figures to threshold on, or the linked pull request. Falls back to `run.id`."}),Z("RUN_CAPTURE_CHECKPOINT","AI runs","Capture run checkpoint","SERVER",[],["steps.<stepId>.snapshotId"],{description:"Records the run's most recent checkpoint so a later replay can restore from it.",details:"Reads an existing checkpoint rather than creating one, and fails when the run has none. Use Snapshot Git state to capture a fresh checkpoint of the worktree instead. Writes the checkpoint id to `steps.<stepId>.snapshotId`."}),Z("RUN_ARCHIVE_DELETE","AI runs","Archive or delete run","SERVER",[],[],{description:"Archives a run out of the active list, or permanently deletes it.",details:"Archiving is reversible; deleting removes the run and its history for good. Delete wins when both flags are set. Housekeeping for workflows that generate many short-lived runs.",mutatesExternal:!0}),Z("NOTIFICATION_SEND","Human loop","Send notification","SERVER",[],[],{description:"Posts a notification into the app's notification list with a title, body, and link.",details:"Deduplicated per run, step, and generation, so a retried attempt does not notify twice. The link defaults to this workflow run. Fire-and-forget: it tells a human something happened but does not wait — use Request confirmation when the workflow needs an answer.",mutatesExternal:!0}),Z("IOS_PUSH_SEND","Human loop","Push to iOS device","SERVER",[],[],{description:"Sends an Apple push notification to registered devices, a broadcast channel, or one raw device token.",details:"Needs APNs credentials. Target mode picks between all registrations, a chosen few, a broadcast channel, or a direct token — the direct mode also needs the token's encoding and whether it is a sandbox or production token. Leaves the device once delivered; nothing about the run waits on it.",mutatesExternal:!0}),Z("HUMAN_CONFIRM","Human loop","Request confirmation","WAIT",[],["steps.<stepId>.answer"],{description:"Parks the run and asks a human to confirm before continuing.",details:"The approval gate to put in front of anything irreversible. Without a timeout the run waits indefinitely; with one it fails when nobody answers in time, which the failure handle can route to a safe default. The answer lands in `steps.<stepId>.answer`."}),Z("HUMAN_CHOICE","Human loop","Ask user to choose","WAIT",[],["steps.<stepId>.answer"],{description:"Parks the run and asks a human to pick from a set of options, optionally allowing several or a free-text answer.",details:"Like Request confirmation but with named buttons — branch on `steps.<stepId>.answer` with an If step afterwards. Multi-select returns a list. Allowing a custom answer means the value may be anything the person typed, so handle the unexpected case."}),Z("CONTROL_IF","Control flow","If / else","CONTROL",[],[],{description:"Evaluates a condition and sends the run down its `true` or `false` branch.",details:"Exactly one branch is taken; steps on the other are skipped, and a skipped branch does not block a downstream join. Conditions compare session values with the usual operators and combine with ALL/ANY/NOT. Both branches may be left unconnected, which simply ends that path."}),Z("CONTROL_JOIN","Control flow","Join branches","CONTROL",[],[],{description:"Brings parallel branches back together, waiting for all of them or continuing on the first.",details:"Required wherever more than one branch reaches the same step — the validator rejects a plain step with several incoming edges. ALL waits for every branch, ANY continues on the first and lets the others keep running. Skipped branches never block it, and the join is skipped when no branch reaches it. A join that closes a For each also reports the iteration failures."}),Z("CONTROL_DELAY","Control flow","Time delay","WAIT",[],[],{description:"Pauses the run for a fixed number of seconds.",details:"Accepts up to a year. The run is parked rather than held open, so a long delay costs nothing while it waits. Use it to space out polling or to give an external system time to settle; use Wait until when you are waiting for a condition rather than a duration."}),Z("CONTROL_WAIT_UNTIL","Control flow","Wait until","WAIT",[],[],{description:"Parks the run until a condition over session data becomes true, re-checking on a cadence.",details:"Evaluates immediately and continues at once if the condition already holds. Session data only changes when a step writes it, so the condition must be able to become true through some other branch — otherwise the wait never resolves. Default cadence is 15 seconds; set a timeout to bound it."}),Z("CONTROL_FOR_EACH","Control flow","For each","CONTROL",[],["steps.<stepId>.items"],{description:"Runs its `body` branch once per item in a list, or takes the `empty` branch when there is nothing to iterate.",details:"Reads the list from a session path or from inline items, and caps at 1,000. Iterations run in parallel and each sees its own item. Fail-fast stops the whole run on the first failing iteration; collect-errors lets them all finish and reports failures at the closing join. Writes the items to `steps.<stepId>.items`."}),Z("CONTROL_TRY","Control flow","Try / catch","CONTROL",[],[],{description:"Marks the start of a protected region whose failures route out of the `catch` handle.",details:"Takes no config — the recovery path is drawn in the graph. Steps on the `success` branch run normally; when one of them fails, the run continues from `catch` instead of failing outright. Use a step's own failure handle for a single fallible step; reach for this when a whole sequence shares one recovery path."}),Z("CONTROL_SET_VARIABLE","Control flow","Set or compute variable","CONTROL",[],[],{description:"Writes a value into session data at a chosen path, either a constant or the result of a small script.",details:"The script runs in a sandboxed JavaScript interpreter with the session data available and no network or filesystem access; its return value is what gets written. Without a script the literal value is used. The path may be any dotted path — write under a namespace of your own to avoid colliding with what steps produce. Because the path comes from config, the catalog cannot advertise it: list it in this step's own `providedPaths` too, or a later step that binds it fails to publish with REQUIREMENT_UNSATISFIED."}),Z("CONTROL_SUBWORKFLOW","Control flow","Call sub-workflow","SERVER",[],[],{description:"Runs another published workflow as a child and waits for it to finish.",details:"Must pin a specific published version — the validator rejects an unpinned reference, so a sub-workflow cannot change under a caller. The input mapping seeds the child's session data. The child appears as a nested run; its failure fails this step."}),Z("SAVED_COMMAND","Extensibility","Run saved command","AGENT",[],["steps.<stepId>.*"],{description:"Starts a saved command on an eligible agent home or worktree target.",details:"Uses the saved command snapshot, target rules, output log, and restart policy. Wait for exit fails the workflow when the command ultimately fails or is cancelled; fire and forget succeeds after durable dispatch and remains independent if the workflow is later cancelled. An optional RE2 output pattern emits the match connector before exit and records captures in session data; matching requires wait for exit. Always-restart commands can only use fire and forget.",mutatesWorktree:!0}),Z("CUSTOM_COMMAND","Extensibility","Run custom command","AGENT",[],["steps.<stepId>.*"],{description:"Runs a one-off shell command on an agent home or worktree and records it in Commands run history.",details:"The script is retained only in the immutable command-run snapshot, not as a reusable saved command. Context targeting prefers the current worktree, then the current agent. Wait for exit fails the workflow when the command fails or is cancelled; fire and forget succeeds after durable dispatch. An optional RE2 output pattern emits the match connector before exit and records captures in session data; matching requires wait for exit.",mutatesWorktree:!0}),...ee,Z("TERMINAL_RUN","Extensibility","Run terminal script","AGENT",["worktree.path"],["steps.<stepId>.*"],{description:"Runs a shell or Node script on the agent inside the worktree, capturing its output.",details:"Needs `worktree.path` and an online agent. A non-zero exit fails the step. Named credentials can be injected as environment variables so secrets never sit in the definition — the validator rejects secret-looking literals in config. Arbitrary code on the agent's machine: it can change anything the agent user can reach. Writes stdout, stderr, and the exit code under `steps.<stepId>.*`; to publish anything else the script produces into a named path, declare it in this step's own `providedPaths`.",mutatesWorktree:!0}),Z("MCP_CALL","Extensibility","Call MCP tool","SERVER",[],["steps.<stepId>.output"],{description:"Calls a tool on a configured MCP server — built-in or external — with a JSON argument object.",details:"The general escape hatch to anything reachable over MCP. Needs the server (tool group) and the exact tool name; arguments must match that tool's own schema. What it does depends entirely on the tool, so treat it as externally mutating. The result lands in `steps.<stepId>.output`.",mutatesExternal:!0}),...[["SSE_ENDPOINT_ACTION","Manage SSE endpoint"],["SSE_MOCK_ACTION","Manage SSE mock"],["SSE_STORAGE_ACTION","Manage SSE storage"],["SSE_BREAKPOINT_RESOLVE","Resolve SSE breakpoint"],["SSE_HISTORY_CLEAR","Clear SSE history"],["SSE_SCRIPT_TEST","Test SSE script"]].map(([e,A])=>X(e,"SSE",A,[],["sse.*","steps.<stepId>.output"],{mutatesExternal:!1}))],et=new Map(eA.map(e=>[e.kind,e])),er=["run.*","worktree.*","codebase.*","agent.*","repo.*","ticket.*"],ei=["build.*","worktree.*","codebase.*","agent.*","repo.*","ticket.*"],en=["worktree.*","codebase.*","agent.*","repo.*","ticket.*","pr.*"],ea=["ticket.*","comment.*","changelog.*"],eo=["repo.*","pr.*","ticket.*","worktree.*","codebase.*","agent.*"],es=[...eo,"comment.*"],el=["repo.*","pr.*","ticket.*","worktree.*","codebase.*","agent.*"],ed="Filters narrow it further: each session path must equal the given value, or be one of a list of values.",eu="Set a threshold path, operator, and value to fire only on the crossing: it fires when the comparison first becomes true and stays quiet until it goes false again, so a metric hovering over the line does not fire repeatedly.",ec=(e,A,t,r,i)=>({kind:e,category:A,label:t,description:i.description,details:i.details,configSchema:K(e,"trigger"),capabilityFlags:["DURABLE","DEDUPLICATED"],seedPaths:r,sourceHandles:(0,n.workflowStaticSourceHandles)(e)}),eh=(e,A,t,r)=>ec(e,A,t,r,{description:`${t} emits a normalized, filterable workflow event.`,details:`${t} uses the canonical domain event and deduplicates deliveries by subject and revision. ${ed}`}),eg=[eh("COMMAND_RUN_RESULT","Commands","Command run result",["command.*","agent.*","worktree.*"]),eh("COMMAND_OUTPUT_MATCH","Commands","Command output match",["command.*","output.*"]),eh("SKILL_SYNC_RESULT","Skills","Skill sync result",["skillSync.*","skill.*","repo.*"]),eh("SKILL_SYNC_CONFLICT","Skills","Skill sync conflict",["skillSync.*","skill.*","repo.*"]),eh("GITHUB_PIPELINE_STATUS_CHANGED","GitHub","Pipeline status changed",["pipeline.*","repo.*","pr.*","worktree.*","codebase.*","agent.*","ticket.*"]),eh("GITHUB_PR_SYNCHRONIZED","GitHub","Pull request synchronized",eo),eh("GITHUB_REVIEW_APPROVED","GitHub","Pull request review approved",eo),...[["GITLAB_MR_STATE","Merge request opened or ready",el],["GITLAB_REVIEW_CHANGES_REQUESTED","Changes requested",el],["GITLAB_REVIEW_COMMENT","Review comment created",[...el,"comment.*"]],["GITLAB_MR_CLOSED","Merge request merged or closed",el],["GITLAB_PIPELINE_FAILED","Pipeline failed",["pipeline.*","repo.*","pr.*"]],["GITLAB_PUSH_DEFAULT","Push to default branch",["repo.*","push.*"]],["GITLAB_PIPELINE_SUCCEEDED","Pipeline succeeded",["pipeline.*","repo.*","pr.*"]],["GITLAB_NOTE_COMMAND","Note command",[...el,"comment.*"]],["GITLAB_PIPELINE_RESULT","Pipeline result",["pipeline.*","repo.*","pr.*"]],["GITLAB_MR_LABEL","Merge request label set",el],["GITLAB_PIPELINE_STATUS_CHANGED","Pipeline status changed",["pipeline.*","repo.*","pr.*"]],["GITLAB_MR_SYNCHRONIZED","Merge request synchronized",el],["GITLAB_REVIEW_APPROVED","Merge request approved",el],["GITLAB_JOB_STATUS_CHANGED","Job status changed",["job.*","pipeline.*","repo.*"]]].map(([e,A,t])=>eh(String(e),"GitLab",String(A),t)),eh("JIRA_TICKET_UPDATED","Jira","Jira ticket updated",ea),eh("JIRA_COMMENT_ADDED","Jira","Jira comment added",ea),eh("JIRA_WORKLOG_ADDED","Jira","Jira worklog added",ea),eh("JIRA_SPRINT_ENDED","Jira","Jira sprint ended",ea),eh("CODEBASE_SYNC_STATE_CHANGED","Codebases","Codebase sync state changed",["codebase.*","agent.*","repo.*"]),eh("CODEBASE_OPERATION_FAILED","Codebases","Codebase operation failed",["codebase.*","agent.*","repo.*","operation.*"]),eh("WORKTREE_SYNC_STATE_CHANGED","Worktrees","Worktree sync state changed",en),eh("WORKTREE_AUTOMATION_RESULT","Worktrees","Worktree automation result",[...en,"automation.*"]),eh("WORKTREE_CLEAN","Worktrees","Worktree became clean",en),eh("PUSH_NOTIFICATION_RESULT","Notifications","Push notification result",["pushBatch.*"]),eh("IOS_DEVICE_ENROLLED","Devices","iOS device enrolled",["device.*"]),eh("IOS_DEVICE_REGISTRATION_RESULT","Devices","iOS device registration result",["device.*"]),eh("SIGNING_OPERATION_RESULT","Signing","Signing operation result",["signing.*","signingProfile.*","agent.*"]),eh("SIGNING_ASSET_EXPIRING","Signing","Signing asset expiring",["signing.*","signingProfile.*","agent.*"]),eh("BUILD_DATA_THRESHOLD","Build Data","Build-data threshold",["buildData.*","agent.*","worktree.*"]),eh("BUILD_DATA_CLEANUP_RESULT","Build Data","Build-data cleanup result",["buildData.*","cleanup.*","agent.*"]),eh("POLLING_OPERATION_STATE","Operations","Polling operation state",["polling.*"]),eh("MODEL_COST_CATALOG_CHANGED","Operations","Model-cost catalog changed",["modelCosts.*"]),eh("CREDENTIAL_STORE_DEGRADED","Operations","Credential store degraded",["credentials.*"]),eh("AGENT_RESOURCE_THRESHOLD","Agents","Agent resource threshold",["agent.*"]),eh("AGENT_VERSION_CHANGED","Agents","Agent version changed",["agent.*"]),eh("TOOL_CALL_RESULT","Tools","Tool call result",["toolCall.*"]),eh("SSE_REQUEST_OPENED","SSE","SSE request opened",["sse.*","endpoint.*","request.*"]),eh("SSE_EVENT_EMITTED","SSE","SSE event emitted",["sse.*","endpoint.*","request.*","event.*"]),eh("SSE_BREAKPOINT_WAITING","SSE","SSE breakpoint waiting",["sse.*","endpoint.*","request.*","breakpoint.*"]),eh("SSE_BREAKPOINT_RESOLVED","SSE","SSE breakpoint resolved",["sse.*","endpoint.*","request.*","breakpoint.*"]),eh("SSE_STREAM_COMPLETED","SSE","SSE stream completed",["sse.*","endpoint.*","request.*"]),eh("SSE_STREAM_FAILED","SSE","SSE stream failed",["sse.*","endpoint.*","request.*"])],ep=[ec("MANUAL","Manual","Manual run",[],{description:"Fires when someone presses Run on the workflow. The default entry point.",details:"Seeds nothing beyond `workflow.*`, so steps hanging off it can only bind to values that later steps produce. A caller may still pass session data explicitly when starting the run. A workflow that has only a choice trigger refuses a plain run."}),ec("MANUAL_CHOICE","Manual","Manual run with a choice",[],{description:"Fires when someone picks an option from the menu under the run button, and routes the run out of that option's own handle.",details:"Declare at least one option, each with a unique key — the key names the outgoing handle, so renaming a label leaves edges attached. One workflow can fan out into several entry paths without a step in front of them. Every edge must leave a handle that still exists, or publishing fails."}),ec("RESOURCE_MANUAL","Manual","Run from a resource",[],{description:"Fires when someone starts the workflow from a specific resource page — a worktree, pull request, build, codebase, ticket, or run.",details:"Must target exactly one resource kind; add a second trigger to accept another. The page seeds that resource's namespace into session data, so a worktree-launched run gets its worktree, codebase, owning agent, repository, and any linked ticket. Those seeds are an optimistic contract — an optional link that is absent resolves to nothing at run time. A worktree does not seed `pr.*`; use a pull-request trigger or Load pull request to bring one into session data. This is also what makes the workflow show up on that resource's page."}),ec("RESOURCE_MANUAL_CHOICE","Manual","Run from a resource with a choice",[],{description:"Fires from a resource page after the person picks an option, routing out of that option's handle.",details:"The resource and choice triggers combined: pick a resource kind and declare keyed options. Same rules as both — one resource kind per trigger, unique option keys, and every edge on a live handle."}),ec("SCHEDULE","Schedule","On a schedule",[],{description:"Fires repeatedly on a fixed cadence measured in seconds.",details:'A cadence, not a cron expression — there is no way to say "weekdays at 9am". The clock runs while the workflow is enabled, and pausing the workflow stops it. Seeds nothing, so scheduled workflows normally start by loading whatever they operate on. Mind the overlap policy: a cadence shorter than the run takes will queue or coalesce.'}),ec("WORKFLOW_FINISHED","Workflows","Another workflow finished",["workflow.*"],{description:"Fires when a different workflow run reaches a terminal state.",details:`Chains workflows without making one a sub-workflow of the other, so the two stay independently runnable. Filter on \`workflow.id\` to watch a specific one and on the finishing status to react only to failures. ${ed}`}),ec("GITHUB_PR_STATE","GitHub","Pull request opened or ready",eo,{description:"Fires when a pull request is opened, or when a draft is marked ready for review.",details:`Needs GitHub polling configured for the repository. Seeds \`pr.*\` and \`repo.*\`, so steps can act on the pull request straight away. ${ed} Filter on \`pr.isDraft\` or the base branch to avoid firing on every pull request in the repository.`}),ec("GITHUB_REVIEW_CHANGES_REQUESTED","GitHub","Changes requested",eo,{description:"Fires when a reviewer submits a review requesting changes.",details:`The entry point for an automated "address the review" loop: pair it with Collect review comments and an AI session. Approvals and plain comments do not fire it. ${ed}`}),ec("GITHUB_REVIEW_COMMENT","GitHub","Review comment created",es,{description:"Fires when a new review comment is posted on a pull request.",details:`Fires per comment rather than per review, so a reviewer leaving five comments fires it five times — take care with steps that start AI runs. Use Changes requested when you want one event per review. ${ed}`}),ec("GITHUB_PR_CLOSED","GitHub","Pull request merged or closed",eo,{description:"Fires when a pull request is merged or closed without merging.",details:`Both outcomes fire it; branch on \`pr.state\` to tell them apart. The natural place to hang cleanup — deleting the worktree, moving the ticket on. ${ed}`}),ec("GITHUB_CHECK_FAILED","GitHub","Check suite or run failed",["repo.*","pipeline.*","worktree.*","codebase.*","agent.*","pr.*","ticket.*"],{description:"Fires when a check suite or check run reports a failure.",details:`Seeds \`pipeline.*\`, including the ids the retry and cancel steps need. Flaky suites fire this often, so gate an automatic retry on a count or a delay rather than retrying unconditionally. ${ed}`}),ec("GITHUB_PUSH_DEFAULT","GitHub","Push to default branch",["repo.*","push.*","ticket.*"],{description:"Fires when a commit lands on the repository's default branch.",details:`Seeds \`repo.*\` and \`push.*\`, plus a ticket key when the pushed branch contains one. There is no pull request or worktree in scope, so a workflow hanging off it usually starts by creating one. Fires on merges too, since a merge is a push. ${ed}`}),ec("GITHUB_WORKFLOW_SUCCEEDED","GitHub","Workflow run succeeded",["repo.*","pipeline.*","worktree.*","codebase.*","agent.*","pr.*","ticket.*"],{description:"Fires when a GitHub Actions workflow run completes successfully.",details:`The success counterpart to the failure triggers — useful for gating a deploy or a merge on a green pipeline. Filter on the workflow name so every unrelated Actions run does not start this workflow. ${ed}`}),ec("GITHUB_ISSUE_COMMAND","GitHub","Issue comment command",["repo.*","pr.*","ticket.*","comment.*"],{description:"Fires when a comment from an allow-listed GitHub user matches a command pattern, such as `/deploy`.",details:`The only trigger that lets outside text start a workflow, so it is deliberately strict: an explicit list of GitHub logins is required, and the pattern must be anchored with \`^\` and \`$\` — publishing fails otherwise. Both checks must pass. Keep the allow-list tight, since anyone on it can start whatever the workflow does. ${ed}`}),ec("GITHUB_ACTIONS_RESULT","GitHub Actions","Workflow result",["repo.*","pipeline.*","worktree.*","codebase.*","agent.*","pr.*","ticket.*"],{description:"Fires when a tracked GitHub Actions run finishes, whatever its conclusion.",details:`The richest of the Actions triggers: it correlates the run back to its worktree, owning agent, pull request, and ticket when those links exist. Branch on the conclusion rather than adding separate success and failure triggers. ${ed}`}),ec("GITHUB_PR_LABEL","GitHub","Pull request label set",eo,{description:"Fires when a label is applied to a pull request.",details:`Turns a label into a manual switch — label a pull request \`automerge\` and let a workflow take it from there. Filter on the label name, or every label change in the repository starts the workflow. ${ed}`}),ec("BUILD_RESULT","Builds","Build result",ei,{description:"Fires when a build finishes, succeeded or failed.",details:`Seeds \`build.*\` along with the worktree it ran in, so the read-results and coverage steps can follow directly. Branch on \`build.status\` to separate the outcomes. ${ed}`}),ec("BUILD_TEST_THRESHOLD","Builds","Test failure threshold",ei,{description:"Fires when a build's failing-test count crosses a threshold you set.",details:`Point the threshold path at \`build.testSummary.failed\` and pick an operator and value. ${eu} ${ed}`}),ec("BUILD_COVERAGE_THRESHOLD","Builds","Coverage threshold",ei,{description:"Fires when a build's code coverage crosses a threshold you set.",details:`Point the threshold path at the coverage summary — usually the changed-files percentage rather than the whole-project number — and compare with a less-than operator. ${eu} ${ed}`}),ec("BUILD_HOOK_FAILED","Builds","Build hook failed",ei,{description:"Fires when one of a build's pre- or post-build scripts fails.",details:`Distinguishes a broken build script from a genuine compile or test failure, which is what Build result reports. Seeds \`build.*\`. ${ed}`}),ec("AGENT_CONNECTION","Agents","Agent connection changed",["agent.*","codebase.agentId"],{description:"Fires when an agent comes online or goes offline.",details:`Seeds the agent id, name, connection state, and capacity metrics. A workflow hanging off it is usually about notifying a human rather than doing repository work — an offline agent cannot run agent steps anyway. Filter on the connection status to react to one direction only. ${ed}`}),ec("AGENT_JOB_FAILED","Agents","Agent job failed",["steps.trigger.*","agent.*","codebase.*","worktree.*","repo.*","ticket.*"],{description:"Fires when a job dispatched to an agent fails — a build, a Git operation, a terminal script.",details:`The failing job is seeded under \`steps.trigger.*\`, including its kind and error. When it targeted a worktree, the owning agent, codebase, repository, and ticket are included too. Catches infrastructure failures that a workflow's own failure handles never see, because the job belonged to a different run. ${ed}`}),ec("AGENT_DISK_REPORT","Agents","Agent disk report",["agent.*","codebase.agentId","disk.*"],{description:"Fires whenever the Derived Data monitor accepts a new agent disk report.",details:`Seeds the complete monitor snapshot under \`disk.*\`, while \`agent.diskFreeBytes\` remains the legacy root-disk inventory value. This can fire at the agent poll cadence; use filters when every report is not needed. ${ed}`}),ec("AGENT_DISK_THRESHOLD","Agents","Agent disk threshold",["agent.*","codebase.agentId","disk.*"],{description:"Fires when monitored Derived Data free space crosses a threshold you set.",details:`Use \`disk.freeGiB\`, \`disk.freeBytes\`, or \`disk.freePercent\` to evaluate the least-free monitored Derived Data volume. \`agent.diskFreeBytes\` remains available for older root-disk workflows. ${eu} ${ed}`}),ec("AGENT_DISK_STATE_CHANGED","Agents","Agent disk state changed",["agent.*","codebase.agentId","disk.*"],{description:"Fires when an agent's disk monitor changes status, pressure mode, health, or monitored volume.",details:`Filter on \`disk.status\`, \`disk.pressureMode\`, \`disk.enabled\`, or errors and warnings to react to a specific transition. Cleanup start appears as \`DELETING\`; recovery can be selected with \`IDLE\`. Repeated reports in the same state stay quiet. ${ed}`}),ec("AGENT_DISK_CLEANUP_RESULT","Agents","Automatic disk cleanup result",["agent.*","codebase.agentId","disk.*","cleanup.*"],{description:"Fires whenever a monitor-managed automatic Derived Data cleanup finishes.",details:`Seeds the terminal agent job under \`cleanup.*\`, including status, error, targets, and deleted entries. Every cleanup job is independent, so two successive successes both fire. Manual Build Data deletions remain outside this trigger. ${ed}`}),ec("CCUSAGE_THRESHOLD","Agents","Usage threshold",["run.usage.*","agent.*"],{description:"Fires when aggregate AI usage crosses a threshold you set.",details:`Watches usage across runs rather than one run's spend — Run usage threshold does that. The cost guardrail: notify, or pause workflows that start AI runs. ${eu} ${ed}`}),ec("WORKTREE_CREATED","Worktrees","Worktree created",en,{description:"Fires after a new worktree is successfully created.",details:`Fires once after the created worktree is projected into the control plane. Seeds the worktree, repository, codebase, and owning agent, plus a linked pull request and Jira ticket when the branch resolves to them. ${ed}`}),ec("WORKTREE_BEHIND","Worktrees","Worktree behind base",en,{description:"Fires when a worktree's branch falls behind the branch it was cut from.",details:`Pairs with a sync operation to keep long-lived branches current. Fires again as the base moves on, so a workflow that reacts should either sync or be filtered narrowly. ${ed}`}),ec("WORKTREE_CONFLICT","Worktrees","Worktree has conflicts",en,{description:"Fires when a worktree is left with Git conflicts after a merge or rebase.",details:`Only fires when the worktree is genuinely marked conflicted. Conflicts need resolving before most other worktree steps will work, so this usually leads to a notification or an AI session pointed at the conflict. ${ed}`}),ec("WORKTREE_MISSING","Worktrees","Worktree missing",en,{description:"Fires when a worktree the control plane knows about is no longer on disk.",details:`Only fires once the worktree is actually recorded as missing — usually someone deleted the directory by hand, or the agent's disk was cleaned. Steps that need the worktree will fail, so react by recreating it or clearing the record. ${ed}`}),ec("WORKTREE_DIVERGED","Worktrees","Worktree diverged",en,{description:"Fires when a worktree's branch and its remote have both moved on independently.",details:`Only fires when the push status is genuinely diverged. Resolving it means a rebase, a merge, or a force push — all destructive enough that this usually routes to a human rather than to an automatic fix. ${ed}`}),ec("WORKTREE_DIRTY_DURATION","Worktrees","Worktree dirty too long",en,{description:"Fires when a worktree has had uncommitted changes for longer than expected.",details:`Catches work that stalled — an AI session that edited files and was never followed up, or a human who wandered off. Usually a nudge rather than an automatic commit. ${ed}`}),ec("WORKTREE_NEW_COMMIT","Worktrees","New worktree commit",en,{description:"Fires when a new commit lands in a worktree.",details:`Fires per commit, so a rebase or a batch of commits fires it repeatedly — keep the reaction cheap, or filter to one branch. Useful for kicking off a build or lint pass as work lands. ${ed}`}),ec("CODEBASE_REMOTE_BRANCH","Codebases","Matching remote branch",["codebase.*","agent.*","repo.*"],{description:"Fires when a remote branch matching the codebase's conventions appears.",details:`Lets a branch pushed from elsewhere pull work into this system — creating a worktree for it, or opening a pull request. Needs a fetch to have run for the branch to be visible. ${ed}`}),ec("JIRA_STATUS","Jira","Ticket status changed",ea,{description:"Fires when a Jira ticket moves to another status.",details:`Needs Jira polling configured. Seeds \`ticket.*\`. Filter on \`ticket.status\` to react to one column only — without a filter, every transition on every polled ticket starts the workflow. ${ed}`}),ec("JIRA_LABEL","Jira","Jira label set",ea,{description:"Fires when a label is applied to a Jira ticket.",details:`The Jira counterpart to the pull request label trigger: a label becomes a manual switch for automation. Filter on the label name. ${ed}`}),ec("JIRA_ASSIGNED_SELF","Jira","Ticket assigned to me",ea,{description:"Fires when a ticket is assigned to the account behind the configured Jira credential.",details:`"Me" is whoever the Jira credential authenticates as, not whoever is looking at the screen. The usual start of a "pick up my next ticket" workflow — create a worktree, start a plan. ${ed}`}),ec("JIRA_SOURCE_NEW_TICKET","Jira","New ticket in source",ea,{description:"Fires when a ticket appears in a configured Jira source — a saved JQL query or board.",details:`Fires on tickets newly matching the source, which includes existing tickets edited into range, not only freshly created ones. The source itself does the filtering, so keep its JQL tight. Seeds \`ticket.*\`. ${ed}`}),ec("JIRA_MENTION","Jira","Jira comment mention",ea,{description:"Fires when the configured Jira account is mentioned in a ticket comment.",details:`Lets someone pull automation into a conversation by mentioning the bot. The comment is seeded under \`comment.*\`, so an AI step can read what was actually asked — treat that text as untrusted input rather than instructions. ${ed}`}),ec("JIRA_SPRINT_STARTED","Jira","Sprint started",ea,{description:"Fires when a Jira sprint is started.",details:`Fires per ticket in the sprint, so a sprint of thirty tickets starts thirty runs — mind the workflow's concurrency settings. Good for sprint-opening bookkeeping. ${ed}`}),ec("JIRA_ISSUE_CREATED","Jira","Ticket created",ea,{description:"Fires when a Jira ticket is created.",details:`Needs the Jira webhook configured in Settings — the polled Jira triggers only observe tickets something already fetched, so they cannot see a brand-new one. Scope the webhook's JQL filter to the projects you care about, since every created ticket otherwise starts a run. ${ed}`}),ec("JIRA_ISSUE_DELETED","Jira","Ticket deleted",ea,{description:"Fires when a Jira ticket is deleted.",details:`Needs the Jira webhook. The ticket is gone by the time this runs, so only the payload's \`ticket.*\` snapshot is available — a step that loads the ticket will fail. Use it for cleanup: close the worktree, cancel the run, archive the branch. ${ed}`}),ec("JIRA_ISSUE_COMMAND","Jira","Ticket comment command",ea,{description:"Fires when a comment from an allow-listed Jira account matches a command pattern, such as `/deploy`.",details:`The Jira counterpart to the GitHub issue comment command, and just as strict: an explicit list of Jira account IDs is required, and the pattern must be anchored with \`^\` and \`$\` — publishing fails otherwise. Jira identifies people by opaque account ID, not display name, so copy the ID from the user's Jira profile URL. Treat the comment body as untrusted input rather than instructions. Needs the Jira webhook. ${ed}`}),ec("JIRA_ATTACHMENT_ADDED","Jira","Attachment added",[...ea,"attachment.*"],{description:"Fires when a file is attached to a Jira ticket.",details:`Needs the Jira webhook. Seeds \`attachment.*\` with the filename, MIME type, and author. Filter on \`attachment.mimeType\` to react to one kind of upload — a crash log, a design export. ${ed}`}),ec("JIRA_ISSUE_LINKED","Jira","Ticket linked",[...ea,"link.*"],{description:"Fires when a Jira issue link is created.",details:`Needs the Jira webhook. Seeds \`link.*\` with the link type and both issue IDs. Filter on \`link.type\` to react to one relationship — "blocks", "duplicates" — rather than every link. ${ed}`}),ec("RUN_STARTED","Plans and sessions","Run started",er,{description:"Fires when an AI plan or session run begins.",details:`Every run trigger seeds the same shape — \`run.*\` plus the worktree, codebase, repository, and ticket it is attached to. Filter on \`run.kind\` to separate plans from sessions. ${ed}`}),ec("RUN_COMPLETED","Plans and sessions","Run completed",er,{description:"Fires when an AI run finishes successfully.",details:`The place to hang everything that happens after the agent is done — committing, pushing, opening a pull request, moving the ticket. Filter on \`run.kind\` to react only to plans or only to sessions. ${ed}`}),ec("RUN_QUESTION_NEEDED","Plans and sessions","Run needs an answer",er,{description:"Fires when an AI run pauses to ask a question, with the pending questions in session data.",details:`The questions arrive under \`run.questions\`, so the Answer run question step can respond without a human — the basis for unattended runs. Answer carefully: an automatic answer to a question the agent should have asked a person is how unwanted changes get made. ${ed}`}),ec("RUN_QUESTION_ANSWERED","Plans and sessions","Run question answered",er,{description:"Fires when a pending question on an AI run is answered.",details:`Fires however the answer arrived — from a person or from another workflow. Use it to record decisions, or to resume work that was gated on the answer. ${ed}`}),ec("RUN_PAUSED","Plans and sessions","Run paused",er,{description:"Fires when an AI run is paused.",details:`Covers pauses from any source, including a run that paused itself. A run needing an answer reports separately through Run needs an answer. ${ed}`}),ec("RUN_CONTINUED","Plans and sessions","Run continued",er,{description:"Fires when a paused AI run resumes.",details:`The counterpart to Run paused. Fires on each resume, so a run that stops and starts repeatedly fires it repeatedly. ${ed}`}),ec("RUN_FAILED","Plans and sessions","Run failed",er,{description:"Fires when an AI run ends in failure.",details:`The error is in the seeded run data, so a follow-up run can be pointed at what went wrong. Beware of loops — a workflow that reacts by starting another run that fails the same way will keep going. ${ed}`}),ec("RUN_CANCELLED","Plans and sessions","Run cancelled",er,{description:"Fires when an AI run is cancelled.",details:`Cancellation leaves whatever the run already wrote in the worktree, so cleanup usually means inspecting or reverting rather than assuming nothing happened. ${ed}`}),ec("RUN_PLAN_PLAYED","Plans and sessions","Plan played",er,{description:"Fires when a run is created by executing a previously completed plan.",details:`Distinguishes plan execution from an ordinary session, which Run started cannot. Lets a workflow treat planned work differently from ad-hoc work. ${ed}`}),ec("RUN_FOLLOW_UP","Plans and sessions","Run follow-up created",er,{description:"Fires when a run is created as a follow-up to another run.",details:`Does not fire for plan execution, which reports through Plan played. The parent run is in the seeded data, so a workflow can count how deep a follow-up chain has gone and stop it. ${ed}`}),ec("RUN_IMPORTED","Plans and sessions","Provider run imported",er,{description:"Fires when a run started outside this system is imported from a provider.",details:`Lets work begun in another tool pick up the same automation — labelling, ticket updates, pull requests. The run did not originate here, so its worktree and ticket links may be incomplete. ${ed}`}),ec("RUN_USAGE_THRESHOLD","Plans and sessions","Run usage threshold",er,{description:"Fires when a single run's token or cost usage crosses a threshold you set.",details:`Scoped to one run, unlike the aggregate Usage threshold. Point the threshold path at the usage figure you care about — a runaway session can then be cancelled automatically. ${eu} ${ed}`}),ec("RUN_EVENT_MATCH","Plans and sessions","Run event or tool matched",er,{description:"Fires on individual events inside an AI run, including each tool call it makes.",details:`The finest-grained run trigger, and by far the most talkative — a single run produces hundreds of events, and every one is a candidate. Always filter, on the event type or the tool name. Useful for reacting to a specific tool being used; a poor choice for anything expensive. ${ed}`}),...eg],ef=new Map(ep.map(e=>[e.kind,e])),eI=A.z.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9_-]*$/),eC=A.z.string().min(1).max(256).regex(/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_*\[\]-]+)*$/),em=A.z.record(A.z.string(),A.z.unknown()).default({}),ew=A.z.object({id:eI,kind:A.z.enum(n.WORKFLOW_TRIGGER_KINDS),name:A.z.string().min(1).max(200).optional(),position:A.z.object({x:A.z.number().finite(),y:A.z.number().finite()}),config:em}),eE=A.z.object({id:eI,kind:A.z.enum(n.WORKFLOW_STEP_KINDS),name:A.z.string().min(1).max(200).optional(),position:A.z.object({x:A.z.number().finite(),y:A.z.number().finite()}),config:em,requiredPaths:A.z.array(eC).max(100).default([]),providedPaths:A.z.array(eC).max(100).default([]),retry:A.z.object({maxAttempts:A.z.number().int().min(1).max(20).default(1),strategy:A.z.enum(["FIXED","EXPONENTIAL"]).default("EXPONENTIAL"),delaySeconds:A.z.number().int().min(1).max(86400).default(5)}).default({maxAttempts:1,strategy:"EXPONENTIAL",delaySeconds:5}),failurePolicy:A.z.enum(["FAIL","CONTINUE"]).default("FAIL")}),ey=A.z.object({id:eI,source:eI,target:eI,sourceHandle:A.z.string().min(1).max(100).default("success"),targetHandle:A.z.string().min(1).max(100).default("input")}),eB=A.z.object({format:A.z.literal(F),schemaVersion:A.z.literal(1),name:A.z.string().min(1).max(200),description:A.z.string().max(2e3).default(""),triggers:A.z.array(ew).max(100).default([]),nodes:A.z.array(eE).max(1e3).default([]),edges:A.z.array(ey).max(5e3).default([]),editor:A.z.object({viewport:A.z.object({x:A.z.number(),y:A.z.number(),zoom:A.z.number().positive()}).optional(),handleLayout:A.z.enum(["SIDES","TOP_BOTTOM"]).default("SIDES"),displayLayout:A.z.enum(["REGULAR","BASIC"]).default("REGULAR")}).default({handleLayout:"SIDES",displayLayout:"REGULAR"})});function eQ(e){return{...e,nodes:e.nodes.map(e=>{if(("RUN_CREATE_PLAN"===e.kind||"RUN_CREATE_SESSION"===e.kind)&&Object.hasOwn(e.config,"jiraSummary")){let A={...e.config};return delete A.jiraSummary,{...e,config:A}}return e})}}function eD(e,A){return A.map(A=>A.replaceAll("<stepId>",e.id))}function eb(e,A){return e===A||"*"===e||e.endsWith(".*")&&A.startsWith(e.slice(0,-1))}function eS(e){return e.length?new Set([...e[0]].filter(A=>e.every(e=>e.has(A)))):new Set}function ek(e,A){return[...e].some(e=>eb(e,A))}let ev={stepPaths(e){let A=et.get(e);return{requiredPaths:A?.requiredPaths??[],providedPaths:A?.providedPaths??[]}},triggerSeedPaths:e=>ef.get(e)?.seedPaths??[]};function eR(e,A=ev){let t=new Set(e.nodes.map(({id:e})=>e)),r=new Map(e.nodes.map(e=>[e.id,e])),i=new Map,n=new Map;for(let A of e.edges)i.set(A.source,[...i.get(A.source)??[],A.target]),n.set(A.target,[...n.get(A.target)??[],A.source]);let a=new Map(e.nodes.map(e=>[e.id,0]));for(let A of e.edges)t.has(A.source)&&t.has(A.target)&&a.set(A.target,(a.get(A.target)??0)+1);let o=[...a].filter(([,e])=>0===e).map(([e])=>e),s=[];for(;o.length;){let e=o.shift();for(let A of(s.push(e),i.get(e)??[])){if(!t.has(A))continue;let e=(a.get(A)??0)-1;a.set(A,e),0===e&&o.push(A)}}let l=e=>{let A=new Set,t=[...i.get(e)??[]];for(;t.length;){let e=t.shift();A.has(e)||(A.add(e),t.push(...i.get(e)??[]))}return A},d=new Map;for(let A of[...e.triggers,...e.nodes])d.set(A.id,l(A.id));let u=new Map;for(let t of e.nodes){let e=A.stepPaths(t.kind);u.set(t.id,[...eD(t,e.providedPaths),...t.providedPaths,`steps.${t.id}.*`])}let c=new Map,h=[];for(let t of e.triggers){let e=new Set(["workflow.*"]);for(let r of A.triggerSeedPaths(t.kind))e.add(r);for(let A of V(t.kind,t.config))e.add(A);let i=new Map;for(let a of s){if(!d.get(t.id)?.has(a))continue;let o=r.get(a),s=(n.get(a)??[]).filter(e=>e===t.id||i.has(e));if(!s.length)continue;let l=eS(s.map(A=>A===t.id?e:i.get(A))),g=c.get(a);c.set(a,g?eS([g,l]):new Set(l));let p=new Set(u.get(a)??[]),f=[...H(o.kind,"step",o.config)].filter(e=>!ek(p,e));for(let e of new Set([...eD(o,A.stepPaths(o.kind).requiredPaths),...o.requiredPaths,...f]))ek(l,e)||h.push({nodeId:o.id,triggerId:t.id,triggerName:t.name??t.kind,path:e});let I=new Set(l);for(let e of u.get(a)??[])I.add(e);i.set(a,I)}}return{availableBefore:new Map([...c].map(([e,A])=>[e,[...A]])),provides:u,requirementViolations:h}}function eT(e,A=""){return Array.isArray(e)?e.some(e=>eT(e,A)):e&&"object"==typeof e?Object.entries(e).some(([e,A])=>eT(A,e)):"string"==typeof e&&/(token|secret|password|passwd|private.?key|api.?key|authorization)/i.test(A)&&!/(credential.?id|credential.?ids)$/i.test(A)}function eG(e){return Array.isArray(e)?e.some(eG):!!e&&"object"==typeof e&&("UNRESOLVED"===e.referenceStatus||Object.values(e).some(eG))}e.s(["WORKFLOW_SCHEMA_VERSION",0,1,"WORKFLOW_STEP_BY_KIND",0,et,"WORKFLOW_STEP_CATALOG",0,eA,"WORKFLOW_TRIGGER_CATALOG",0,ep,"computeWorkflowPathAvailability",0,eR,"emptyWorkflowDefinition",0,function(e="Untitled workflow"){return eB.parse({format:F,schemaVersion:1,name:e,description:"",triggers:[{id:"manual",kind:"MANUAL",position:{x:0,y:100},config:{}}],nodes:[],edges:[],editor:{}})},"hasWorkflowErrors",0,function(e){return e.some(({severity:e})=>"ERROR"===e)},"parseWorkflowDefinition",0,function(e){return eQ(eB.parse(e))},"resourceManualSeedPaths",0,V,"sanitizeWorkflowExportDefinition",0,function(e){let A=(e,t="")=>Array.isArray(e)?e.map(e=>A(e,t)):e&&"object"==typeof e?Object.fromEntries(Object.entries(e).map(([e,t])=>[e,A(t,e)])):"string"==typeof e&&/(token|secret|password|passwd|private.?key|api.?key|authorization)/i.test(t)&&!/(credential.?id|credential.?ids)$/i.test(t)||"string"==typeof e&&/^(?:\/|[A-Za-z]:[\\/]|\\\\)/.test(e)&&/^(?:cwd|folder|path|directory)$/i.test(t)?null:e;return eB.parse(A(e))},"validateWorkflowDefinition",0,function(e){let A=eB.safeParse(e);if(!A.success)return{definition:null,diagnostics:A.error.issues.map(e=>({severity:"ERROR",code:"SCHEMA_INVALID",message:e.message,path:e.path.join(".")}))};let t=eQ(A.data),r=[],i=new Set;for(let e of[...t.triggers,...t.nodes])i.has(e.id)&&r.push({severity:"ERROR",code:"DUPLICATE_NODE_ID",message:`Duplicate graph id ${e.id}`,nodeId:e.id}),i.add(e.id);let o=new Set;for(let e of t.edges)o.has(e.id)&&r.push({severity:"ERROR",code:"DUPLICATE_EDGE_ID",message:`Duplicate edge id ${e.id}`}),o.add(e.id),i.has(e.source)&&i.has(e.target)||r.push({severity:"ERROR",code:"EDGE_ENDPOINT_MISSING",message:`Edge ${e.id} references a missing endpoint`}),t.triggers.some(({id:A})=>A===e.target)&&r.push({severity:"ERROR",code:"TRIGGER_HAS_INPUT",message:"Triggers cannot have incoming edges",triggerId:e.target});t.triggers.length||r.push({severity:"ERROR",code:"TRIGGER_REQUIRED",message:"At least one trigger is required"}),t.nodes.length||r.push({severity:"ERROR",code:"STEP_REQUIRED",message:"At least one step is required"});let s=new Set(t.nodes.map(({id:e})=>e)),l=new Map,d=new Map;for(let e of t.edges)l.set(e.source,[...l.get(e.source)??[],e.target]),d.set(e.target,[...d.get(e.target)??[],e.source]);for(let e of t.nodes)(d.get(e.id)??[]).filter(e=>s.has(e)).length>1&&"CONTROL_JOIN"!==e.kind&&r.push({severity:"ERROR",code:"EXPLICIT_JOIN_REQUIRED",message:"Nodes with multiple incoming branches must be explicit join nodes",nodeId:e.id});let u=new Map(t.nodes.map(e=>[e.id,0]));for(let e of t.edges)s.has(e.source)&&s.has(e.target)&&u.set(e.target,(u.get(e.target)??0)+1);let c=[...u].filter(([,e])=>0===e).map(([e])=>e),h=[];for(;c.length;){let e=c.shift();for(let A of(h.push(e),l.get(e)??[])){if(!s.has(A))continue;let e=(u.get(A)??0)-1;u.set(A,e),0===e&&c.push(A)}}h.length!==t.nodes.length&&r.push({severity:"ERROR",code:"DAG_CYCLE",message:"Workflow graphs cannot contain free-form cycles"});let g=new Map,p=e=>{let A=new Set,t=[...l.get(e)??[]];for(;t.length;){let e=t.shift();A.has(e)||(A.add(e),t.push(...l.get(e)??[]))}return A};for(let e of[...t.triggers,...t.nodes])g.set(e.id,p(e.id));for(let e of t.nodes){for(let A of(t.triggers.some(A=>g.get(A.id)?.has(e.id))||r.push({severity:"ERROR",code:"UNREACHABLE_STEP",message:"Step is not reachable from a trigger",nodeId:e.id}),eT(e.config)&&r.push({severity:"ERROR",code:"SECRET_LITERAL",message:"Store secrets as credential references, not workflow literals",nodeId:e.id}),eG(e.config)&&r.push({severity:"ERROR",code:"UNRESOLVED_REFERENCE",message:"Resolve imported references before publishing",nodeId:e.id}),new Set((0,a.invalidWorkflowValueBindings)(e.config))))r.push({severity:"ERROR",code:"SESSION_BINDING_INVALID",message:A,nodeId:e.id});if("CONTROL_SUBWORKFLOW"===e.kind&&"string"!=typeof e.config.versionId&&r.push({severity:"ERROR",code:"SUBWORKFLOW_VERSION_REQUIRED",message:"Sub-workflows must pin a published version",nodeId:e.id}),"SAVED_COMMAND"===e.kind||"CUSTOM_COMMAND"===e.kind){let A=q(e.config);if(t.edges.some(A=>A.source===e.id&&"match"===A.sourceHandle)&&!A&&r.push({severity:"ERROR",code:"COMMAND_MATCH_PATTERN_REQUIRED",message:"The match connector requires an output pattern",nodeId:e.id}),A){void 0!==e.config.outputMatchMode&&"ONCE"!==e.config.outputMatchMode&&"EACH_MATCH"!==e.config.outputMatchMode&&r.push({severity:"ERROR",code:"COMMAND_MATCH_MODE_INVALID",message:"Output match behavior must be Once or Each match",nodeId:e.id}),"FIRE_AND_FORGET"===e.config.completionMode&&r.push({severity:"ERROR",code:"COMMAND_MATCH_REQUIRES_WAIT",message:"Output matching requires Wait for exit completion",nodeId:e.id});try{J(A)}catch(A){r.push({severity:"ERROR",code:"COMMAND_MATCH_PATTERN_INVALID",message:A instanceof Error?A.message:String(A),nodeId:e.id})}let i=A=>t.edges.filter(t=>t.source===e.id&&t.sourceHandle===A).map(({target:e})=>e),n=e=>{let A=new Set,r=[...e];for(;r.length;){let e=r.shift();A.has(e)||(A.add(e),r.push(...t.edges.filter(A=>A.source===e).map(({target:e})=>e)))}return A},a=n(i("match")),o=n([...i("success"),...i("failure")]);[...a].some(e=>o.has(e))&&r.push({severity:"ERROR",code:"COMMAND_MATCH_BRANCH_RECONVERGES",message:"A command match branch cannot reconverge with its success or failure branch",nodeId:e.id})}}}for(let e of t.triggers){for(let A of((l.get(e.id)??[]).length||r.push({severity:"ERROR",code:"TRIGGER_DISCONNECTED",message:"Trigger is not connected to a step",triggerId:e.id}),eT(e.config)&&r.push({severity:"ERROR",code:"SECRET_LITERAL",message:"Store secrets as credential references, not trigger literals",triggerId:e.id}),eG(e.config)&&r.push({severity:"ERROR",code:"UNRESOLVED_REFERENCE",message:"Resolve imported references before publishing",triggerId:e.id}),new Set((0,a.invalidWorkflowValueBindings)(e.config))))r.push({severity:"ERROR",code:"SESSION_BINDING_INVALID",message:A,triggerId:e.id});if((0,n.isResourceTriggerKind)(e.kind)&&!Y(e.config)&&r.push({severity:"ERROR",code:"RESOURCE_KIND_REQUIRED",message:"Resource triggers must target a single resource kind; add one trigger per kind",triggerId:e.id}),(0,n.isChoiceTriggerKind)(e.kind)){let A=j(e.config),i=Array.isArray(e.config.choices)?e.config.choices.length:0;A.length&&A.length===i||r.push({severity:"ERROR",code:"TRIGGER_CHOICES_REQUIRED",message:"Choice triggers need at least one option, each with a unique key",triggerId:e.id});let n=new Set(A.map(({key:e})=>e));for(let A of t.edges)A.source===e.id&&(n.has(A.sourceHandle)||r.push({severity:"ERROR",code:"TRIGGER_CHOICE_HANDLE_UNKNOWN",message:`Connection ${A.id} leaves an option that no longer exists`,triggerId:e.id}))}if("GITHUB_ISSUE_COMMAND"===e.kind||"JIRA_ISSUE_COMMAND"===e.kind||"GITLAB_NOTE_COMMAND"===e.kind){let A="JIRA_ISSUE_COMMAND"===e.kind,t="GITLAB_NOTE_COMMAND"===e.kind,i=A?e.config.allowedAccountIds:t?e.config.allowedUsernames:e.config.allowedLogins,n=e.config.commandPattern;(!Array.isArray(i)||!i.length||i.some(e=>"string"!=typeof e||!e.trim()))&&r.push({severity:"ERROR",code:"ISSUE_COMMAND_ALLOWLIST_REQUIRED",message:A?"Issue command triggers require an explicit Jira account ID allow-list":t?"Note command triggers require an explicit GitLab username allow-list":"Issue command triggers require an explicit GitHub login allow-list",triggerId:e.id}),"string"==typeof n&&n.startsWith("^")&&n.endsWith("$")||r.push({severity:"ERROR",code:"ISSUE_COMMAND_PATTERN_ANCHORED",message:"Issue command patterns must be anchored with ^ and $",triggerId:e.id})}}for(let e of eR(t).requirementViolations)r.push({severity:"ERROR",code:"REQUIREMENT_UNSATISFIED",message:`${e.path} is not guaranteed on the path from ${e.triggerName}`,nodeId:e.nodeId,triggerId:e.triggerId,path:e.path});for(let e=0;e<t.nodes.length;e+=1){let A=t.nodes[e],i=[...eD(A,et.get(A.kind).providedPaths),...A.providedPaths].filter(e=>!e.startsWith(`steps.${A.id}.`));for(let n=e+1;n<t.nodes.length;n+=1){let e=t.nodes[n];if(g.get(A.id)?.has(e.id)||g.get(e.id)?.has(A.id))continue;let a=[...eD(e,et.get(e.kind).providedPaths),...e.providedPaths].filter(A=>!A.startsWith(`steps.${e.id}.`));i.some(e=>a.some(A=>eb(e,A)||eb(A,e)))&&r.push({severity:"ERROR",code:"PARALLEL_WRITE_CONFLICT",message:`Parallel steps ${A.name??A.id} and ${e.name??e.id} can write the same session-data path`,nodeId:e.id})}}return{definition:t,diagnostics:r}},"workflowResourceKind",0,Y,"workflowTriggerChoices",0,j],388385)},269671,e=>{"use strict";var A,t=e.i(522527),r=e.i(855646),i=e.i(329736),n=e.i(736426),a=new Map,o=new Map,s=!0,l=!1;function d(e){return e.replace(/[\s,]+/g," ").trim()}function u(e){for(var A=[],t=1;t<arguments.length;t++)A[t-1]=arguments[t];"string"==typeof e&&(e=[e]);var r=e[0];return A.forEach(function(A,t){A&&"Document"===A.kind?r+=A.loc.source.body:r+=A,r+=e[t+1]}),function(e){var A=d(e);if(!a.has(A)){var t,r,u,c,h,g=(0,n.parse)(e,{experimentalFragmentVariables:l,allowLegacyFragmentVariables:l,experimentalFragmentArguments:l});if(!g||"Document"!==g.kind)throw Error("Not a valid GraphQL document.");a.set(A,((c=new Set((t=new Set,r=[],g.definitions.forEach(function(e){if("FragmentDefinition"===e.kind){var A,i=e.name.value,n=d((A=e.loc).source.body.substring(A.start,A.end)),a=o.get(i);a&&!a.has(n)?s&&console.warn("Warning: fragment with name "+i+" already exists.\ngraphql-tag enforces all fragment names across your application to be unique; read more about\nthis in the docs: http://dev.apollodata.com/core/fragments.html#unique-names"):a||o.set(i,a=new Set),a.add(n),t.has(n)||(t.add(n),r.push(e))}else r.push(e)}),u=(0,i.__assign)((0,i.__assign)({},g),{definitions:r})).definitions)).forEach(function(e){e.loc&&delete e.loc,Object.keys(e).forEach(function(A){var t=e[A];t&&"object"==typeof t&&c.add(t)})}),(h=u.loc)&&(delete h.startToken,delete h.endToken),u))}return a.get(A)}(r)}var c=u;(A=u||(u={})).gql=c,A.resetCaches=function(){a.clear(),o.clear()},A.disableFragmentWarnings=function(){s=!1},A.enableExperimentalFragmentVariables=function(){l=!0},A.disableExperimentalFragmentVariables=function(){l=!1},u.default=u;let h=[`"Values supported for action center resource."
|
|
1537
1537
|
enum ActionCenterResourceKind {
|
|
1538
1538
|
"Represents the plan option."
|
|
1539
1539
|
PLAN
|