@superclawd-ai/pipelines 0.1.2 → 0.1.3

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.
@@ -1,29 +1,29 @@
1
1
  import { createRequire as __cr } from 'module'; const require = __cr(import.meta.url);
2
- var wi=Object.defineProperty;var Rn=(e,t)=>()=>(e&&(t=e(e=0)),t);var bi=(e,t)=>{for(var n in t)wi(e,n,{get:t[n],enumerable:!0})};var he,j,Re,Te,y,h,I,x,S,l,M,te,E,H,B,L,q,P,C,G,J,V=Rn(()=>{"use strict";he={loggedIn:!0,account:{email:"owner@example.com",org:"superclawd"}},j=[{id:"ws_front",name:"Frontend",tier:"paid"},{id:"ws_core",name:"Core Platform",tier:"paid"},{id:"ws_sandbox",name:"Sandbox",tier:"free"}],Re=[{id:"team_core",name:"Core"},{id:"team_review",name:"Reviewers"}],Te=[{id:"agent_orch",name:"Orchestrator"},{id:"agent_reviewer",name:"Code Reviewer"},{id:"agent_fixer",name:"Bug Fixer"}],y=[{id:"conn_acme",provider:"linear",providerAccountName:"Acme",workspaceId:"ws_front",workspaceName:"Frontend",workingDir:"/Users/andy/code/acme",linkStatus:"linked",authStatus:"connected",lastSyncedAt:new Date(Date.now()-2*6e4).toISOString(),ticketCount:5},{id:"conn_web",provider:"linear",providerAccountName:"Acme Web",workspaceId:"ws_front",workspaceName:"Frontend",workingDir:"/Users/andy/code/acme-web",linkStatus:"linked",authStatus:"connected",lastSyncedAt:new Date(Date.now()-5*6e4).toISOString(),ticketCount:3},{id:"conn_beta",provider:"linear",providerAccountName:"Beta Board",workspaceId:null,workspaceName:null,workingDir:null,linkStatus:"unlinked",linkLostReason:"access_lost",authStatus:"connected",lastSyncedAt:new Date(Date.now()-3*36e5).toISOString(),ticketCount:3},{id:"conn_personal",provider:"linear",providerAccountName:"Personal",workspaceId:"ws_core",workspaceName:"Core Platform",workingDir:"/Users/andy/code/core",linkStatus:"linked",authStatus:"expired",lastSyncedAt:new Date(Date.now()-26*36e5).toISOString(),ticketCount:2},{id:"conn_jira_demo",provider:"jira",providerAccountName:"demo.atlassian.net",workspaceId:"ws_core",workspaceName:"Core Platform",workingDir:"/Users/andy/code/core",linkStatus:"linked",authStatus:"connected",lastSyncedAt:new Date(Date.now()-4*6e4).toISOString(),ticketCount:1,cloudId:"cloud-demo"},{id:"conn_local_front",provider:"local",providerAccountName:"Local",workspaceId:"ws_front",workspaceName:"Frontend",workingDir:null,linkStatus:"linked",authStatus:"connected",lastSyncedAt:null,ticketCount:2},{id:"conn_local_core",provider:"local",providerAccountName:"Local",workspaceId:"ws_core",workspaceName:"Core Platform",workingDir:null,linkStatus:"linked",authStatus:"connected",lastSyncedAt:null,ticketCount:0},{id:"conn_local_sandbox",provider:"local",providerAccountName:"Local",workspaceId:"ws_sandbox",workspaceName:"Sandbox",workingDir:null,linkStatus:"linked",authStatus:"connected",lastSyncedAt:null,ticketCount:0}],h=[{id:"jira_9001",connectionId:"conn_jira_demo",provider:"jira",externalIdentifier:"PLAT-1",project:"Platform",title:"Migrate auth service to the new token format",status:"in_progress",statusRaw:"In Progress",assignee:{name:"Andy"},reporter:{name:"Dana K."},dueDate:"2026-07-20",priority:2,labels:[{name:"backend"}],url:"https://demo.atlassian.net/browse/PLAT-1",workspaceId:"ws_core",description:"Swap the legacy HS256 tokens for the rotated RS256 pair."},{id:"t_123",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-123",project:"Auth",title:"Fix login redirect loop",status:"todo",statusRaw:"Todo",assignee:{name:"Andy"},reporter:{name:"Priya"},dueDate:"2026-07-15",priority:1,labels:[{name:"bug",color:"#e5484d"}],url:"https://linear.app/acme/issue/ENG-123",workspaceId:"ws_front",description:"After SSO, users bounce between /login and /dashboard."},{id:"t_140",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-140",project:"Auth",title:"Add SSO to the settings page",status:"in_progress",statusRaw:"In Progress",assignee:{name:"Andy"},priority:2,labels:[{name:"feature"}],url:"https://linear.app/acme/issue/ENG-140",workspaceId:"ws_front",description:"Wire the SAML flow into Settings \u2192 Security."},{id:"t_131",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-131",project:"Platform Config",title:"Migrate config loader to zod",status:"blocked",statusRaw:"Blocked",assignee:{name:"Andy"},priority:2,labels:[{name:"chore"}],url:"https://linear.app/acme/issue/ENG-131",workspaceId:"ws_front",description:"Replace ad-hoc env parsing with a zod schema."},{id:"t_118",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-118",project:"Design System",title:"Refactor the toast provider",status:"in_review",statusRaw:"In Review",assignee:{name:"Andy"},priority:3,labels:[{name:"refactor"}],url:"https://linear.app/acme/issue/ENG-118",workspaceId:"ws_front",description:"Consolidate the two toast systems into one."},{id:"t_090",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-90",project:"Billing",title:"Dark-mode polish on the billing page",status:"done",statusRaw:"Done",priority:4,labels:[{name:"ui"}],url:"https://linear.app/acme/issue/ENG-90",workspaceId:"ws_front"},{id:"t_112",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-112",project:"Dashboard",title:"Empty states for the dashboard widgets",status:"done",statusRaw:"Done",assignee:{name:"Andy"},priority:3,labels:[{name:"ui"}],url:"https://linear.app/acme/issue/ENG-112",workspaceId:"ws_front",description:"Show friendly empty states when a widget has no data yet."},{id:"t_201",connectionId:"conn_personal",provider:"linear",externalIdentifier:"CORE-201",project:"Directives",title:"Cache invalidation for the directives endpoint",status:"todo",statusRaw:"Todo",priority:2,labels:[{name:"perf"}],url:"https://linear.app/personal/issue/CORE-201",workspaceId:"ws_core"},{id:"t_web1",connectionId:"conn_web",provider:"linear",externalIdentifier:"WEB-11",project:"Marketing Site",title:"Rework the pricing page hero",status:"todo",statusRaw:"Todo",priority:3,labels:[{name:"ui"}],url:"https://linear.app/acme/issue/WEB-11",workspaceId:"ws_front",description:"New hero with the updated value prop and a single primary CTA."},{id:"t_web2",connectionId:"conn_web",provider:"linear",externalIdentifier:"WEB-14",project:"Marketing Site",title:"Add OpenGraph images to blog posts",status:"in_progress",statusRaw:"In Progress",priority:2,labels:[{name:"feature"}],url:"https://linear.app/acme/issue/WEB-14",workspaceId:"ws_front",description:"Generate per-post OG images at build time."},{id:"t_web3",connectionId:"conn_web",provider:"linear",externalIdentifier:"WEB-9",project:"Marketing Site",title:"Fix layout shift on the careers page",status:"in_review",statusRaw:"In Review",priority:1,labels:[{name:"bug"}],url:"https://linear.app/acme/issue/WEB-9",workspaceId:"ws_front",description:"Reserve space for the hero image to stop CLS."},{id:"t_local1",connectionId:"conn_local_front",provider:"local",externalIdentifier:"LOCAL-1",project:"Local",title:"Spike: evaluate the new charts library",status:"todo",statusRaw:"Backlog",priority:3,labels:[],url:"",workspaceId:"ws_front",description:"Timebox a day to compare two charting libraries for the dashboard."},{id:"t_local2",connectionId:"conn_local_front",provider:"local",externalIdentifier:"LOCAL-2",project:"Local",title:"Write the onboarding checklist doc",status:"todo",statusRaw:"Backlog",priority:4,labels:[],url:"",workspaceId:"ws_front"}],I={run_web2:{id:"run_web2",ticketId:"t_web2",ticketKey:"WEB-14",title:"Add OpenGraph images to blog posts",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"agent",agentName:"Orchestrator",autonomy:"autonomous",status:"running",sessionId:"e1f2a3b4-5c6d-4e7f-8a90-1b2c3d4e5f60",branchName:"superclawd/WEB-14-9a8b",plan:[{text:"Add the OG image template",done:!0},{text:"Hook into the build",done:!1}],events:[{id:"e1",ts:"14:02",kind:"tool_use",text:"Read scripts/og.ts"}],createdAt:new Date(Date.now()-8*6e4).toISOString(),updatedAt:new Date().toISOString()},run_web3:{id:"run_web3",ticketId:"t_web3",ticketKey:"WEB-9",title:"Fix layout shift on the careers page",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"team",teamName:"Core",autonomy:"autonomous",status:"stopped",stopReason:"completed",sessionId:"f6e5d4c3-2b1a-4098-8f7e-6d5c4b3a2190",branchName:"superclawd/WEB-9-3c4d",prUrl:"https://github.com/acme/web/pull/77",plan:[{text:"Reserve hero space",done:!0},{text:"Verify CLS budget",done:!0}],events:[{id:"e1",ts:"13:10",kind:"verification",text:"CLS 0.02 \u2713"}],createdAt:new Date(Date.now()-70*6e4).toISOString(),updatedAt:new Date(Date.now()-25*6e4).toISOString()},run_140:{id:"run_140",ticketId:"t_140",ticketKey:"ENG-140",title:"Add SSO to the settings page",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"team",teamName:"Core",autonomy:"autonomous",status:"running",sessionId:"3f2a7c9e-1b4d-4a6f-9c2e-8d5b0a1f6e42",branchName:"superclawd/ENG-140-a1b2",plan:[{text:"Read the auth module",done:!0},{text:"Add the SAML client",done:!0},{text:"Wire into Settings \u2192 Security",done:!1},{text:"Add a regression test",done:!1}],events:[{id:"e1",ts:"12:01",kind:"tool_use",text:"Read src/auth.ts"},{id:"e2",ts:"12:02",kind:"commit",text:"wip: SAML client scaffold"},{id:"e3",ts:"12:03",kind:"guardrail",text:"warn: wrote to .env.example (logged)"},{id:"e4",ts:"12:04",kind:"tool_use",text:"Edit src/settings/security.tsx"}],createdAt:new Date(Date.now()-10*6e4).toISOString(),updatedAt:new Date().toISOString()},run_131:{id:"run_131",ticketId:"t_131",ticketKey:"ENG-131",title:"Migrate config loader to zod",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"anyone",autonomy:"supervised",status:"blocked",sessionId:"a91c04b8-7e2f-4d13-b6a0-2c9f5e731d80",branchName:"superclawd/ENG-131-c3d4",plan:[{text:"Inventory env vars",done:!0},{text:"Draft the zod schema",done:!0},{text:"Swap the loader",done:!1},{text:"Update callers",done:!1}],events:[{id:"e1",ts:"11:40",kind:"tool_use",text:"Grep process.env usages"},{id:"e2",ts:"11:44",kind:"commit",text:"wip: zod schema draft"},{id:"e3",ts:"11:46",kind:"mcp_tool",text:"request_human_input(...)"}],blocker:{id:"b_131",origin:"agent",kind:"agent_question",status:"open",question:"Should the metrics call use the REST or GraphQL client? The repo has both."},createdAt:new Date(Date.now()-30*6e4).toISOString(),updatedAt:new Date(Date.now()-4*6e4).toISOString()},run_118:{id:"run_118",ticketId:"t_118",ticketKey:"ENG-118",title:"Refactor the toast provider",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"agent",agentName:"Orchestrator",autonomy:"autonomous",status:"stopped",stopReason:"completed",sessionId:"c7d81f30-5a62-4e09-8b17-46f2a9c3e5d1",branchName:"superclawd/ENG-118-e5f6",prUrl:"https://github.com/acme/app/pull/42",plan:[{text:"Map both toast systems",done:!0},{text:"Unify into one provider",done:!0},{text:"Migrate call sites",done:!0},{text:"Verify build + tests",done:!0}],events:[{id:"e1",ts:"10:20",kind:"commit",text:"refactor: unify toast provider"},{id:"e2",ts:"10:35",kind:"verification",text:"build \u2713 \xB7 tests \u2713 \xB7 lint \u2713"},{id:"e3",ts:"10:36",kind:"mcp_tool",text:"mark_complete(...) \u2192 draft PR #42"}],createdAt:new Date(Date.now()-60*6e4).toISOString(),updatedAt:new Date(Date.now()-20*6e4).toISOString()},run_112:{id:"run_112",ticketId:"t_112",ticketKey:"ENG-112",title:"Empty states for the dashboard widgets",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"team",teamName:"Core",autonomy:"autonomous",status:"stopped",stopReason:"completed",sessionId:"d4e5f6a1-9c02-4b38-a7e1-5f0c2b83d419",branchName:"superclawd/ENG-112-b7c8",prUrl:"https://github.com/acme/app/pull/38",plan:[{text:"Design the empty-state component",done:!0},{text:"Wire it into each widget",done:!0},{text:"Verify build + tests",done:!0}],events:[{id:"e1",ts:"09:10",kind:"commit",text:"feat: dashboard empty states"},{id:"e2",ts:"09:22",kind:"verification",text:"build \u2713 \xB7 tests \u2713"},{id:"e3",ts:"09:23",kind:"state_change",text:"approved by human \u2192 Done"}],createdAt:new Date(Date.now()-90*6e4).toISOString(),updatedAt:new Date(Date.now()-40*6e4).toISOString()},run_090:{id:"run_090",ticketId:"t_090",ticketKey:"ENG-90",title:"Dark-mode polish on the billing page",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"team",teamName:"Core",autonomy:"supervised",status:"not_started",plan:[],events:[],createdAt:new Date(Date.now()-5*6e4).toISOString(),updatedAt:new Date(Date.now()-5*6e4).toISOString()}},x={t_140:"run_140",t_131:"run_131",t_118:"run_118",t_090:"run_090",t_112:"run_112",t_web2:"run_web2",t_web3:"run_web3"},S={jira_9001:"in_progress",t_123:"backlog",t_090:"backlog",t_140:"in_progress",t_131:"needs_input",t_118:"in_review",t_112:"done",t_201:"backlog",t_web1:"backlog",t_web2:"in_progress",t_web3:"in_review",t_local1:"backlog",t_local2:"backlog"},l={defaultAutonomy:"supervised",maxConcurrentRuns:3,branchPrefix:"feature",defaultModel:"opus",defaultEffort:"high"},M={conv_1:{id:"conv_1",title:"Debounce the workspace search",workspaceId:"ws_front",workspaceName:"Frontend",tier:"Medium",effort:"medium",sessionId:"b8e3d1a4-6f27-4c95-90ab-1e7d32c8f0a5",messages:[{id:"m1",role:"user",text:"How should I debounce the workspace search input?",ts:"09:02"},{id:"m2",role:"assistant",text:`Running under Frontend (Medium \xB7 Sonnet) \u2014 your team, guardrails and memory are in context.
2
+ var ea=Object.defineProperty;var Qn=(e,t)=>()=>(e&&(t=e(e=0)),t);var ta=(e,t)=>{for(var n in t)ea(e,n,{get:t[n],enumerable:!0})};var Ie,$,Ce,Pe,b,h,x,T,S,l,F,ce,O,ne,z,W,K,B,X,j,D,H,re,Y=Qn(()=>{"use strict";Ie={loggedIn:!0,account:{email:"owner@example.com",org:"superclawd"}},$=[{id:"ws_front",name:"Frontend",tier:"paid"},{id:"ws_core",name:"Core Platform",tier:"paid"},{id:"ws_sandbox",name:"Sandbox",tier:"free"}],Ce=[{id:"team_core",name:"Core"},{id:"team_review",name:"Reviewers"}],Pe=[{id:"agent_orch",name:"Orchestrator"},{id:"agent_reviewer",name:"Code Reviewer"},{id:"agent_fixer",name:"Bug Fixer"}],b=[{id:"conn_acme",provider:"linear",providerAccountName:"Acme",workspaceId:"ws_front",workspaceName:"Frontend",workingDir:"/Users/andy/code/acme",linkStatus:"linked",authStatus:"connected",lastSyncedAt:new Date(Date.now()-2*6e4).toISOString(),ticketCount:5},{id:"conn_web",provider:"linear",providerAccountName:"Acme Web",workspaceId:"ws_front",workspaceName:"Frontend",workingDir:"/Users/andy/code/acme-web",linkStatus:"linked",authStatus:"connected",lastSyncedAt:new Date(Date.now()-5*6e4).toISOString(),ticketCount:3},{id:"conn_beta",provider:"linear",providerAccountName:"Beta Board",workspaceId:null,workspaceName:null,workingDir:null,linkStatus:"unlinked",linkLostReason:"access_lost",authStatus:"connected",lastSyncedAt:new Date(Date.now()-3*36e5).toISOString(),ticketCount:3},{id:"conn_personal",provider:"linear",providerAccountName:"Personal",workspaceId:"ws_core",workspaceName:"Core Platform",workingDir:"/Users/andy/code/core",linkStatus:"linked",authStatus:"expired",lastSyncedAt:new Date(Date.now()-26*36e5).toISOString(),ticketCount:2},{id:"conn_jira_demo",provider:"jira",providerAccountName:"demo.atlassian.net",workspaceId:"ws_core",workspaceName:"Core Platform",workingDir:"/Users/andy/code/core",linkStatus:"linked",authStatus:"connected",lastSyncedAt:new Date(Date.now()-4*6e4).toISOString(),ticketCount:1,cloudId:"cloud-demo"},{id:"conn_local_front",provider:"local",providerAccountName:"Local",workspaceId:"ws_front",workspaceName:"Frontend",workingDir:null,linkStatus:"linked",authStatus:"connected",lastSyncedAt:null,ticketCount:2},{id:"conn_local_core",provider:"local",providerAccountName:"Local",workspaceId:"ws_core",workspaceName:"Core Platform",workingDir:null,linkStatus:"linked",authStatus:"connected",lastSyncedAt:null,ticketCount:0},{id:"conn_local_sandbox",provider:"local",providerAccountName:"Local",workspaceId:"ws_sandbox",workspaceName:"Sandbox",workingDir:null,linkStatus:"linked",authStatus:"connected",lastSyncedAt:null,ticketCount:0}],h=[{id:"jira_9001",connectionId:"conn_jira_demo",provider:"jira",externalIdentifier:"PLAT-1",project:"Platform",title:"Migrate auth service to the new token format",status:"in_progress",statusRaw:"In Progress",assignee:{name:"Andy"},reporter:{name:"Dana K."},dueDate:"2026-07-20",priority:2,labels:[{name:"backend"}],url:"https://demo.atlassian.net/browse/PLAT-1",workspaceId:"ws_core",description:"Swap the legacy HS256 tokens for the rotated RS256 pair."},{id:"t_123",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-123",project:"Auth",title:"Fix login redirect loop",status:"todo",statusRaw:"Todo",assignee:{name:"Andy"},reporter:{name:"Priya"},dueDate:"2026-07-15",priority:1,labels:[{name:"bug",color:"#e5484d"}],url:"https://linear.app/acme/issue/ENG-123",workspaceId:"ws_front",description:"After SSO, users bounce between /login and /dashboard."},{id:"t_140",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-140",project:"Auth",title:"Add SSO to the settings page",status:"in_progress",statusRaw:"In Progress",assignee:{name:"Andy"},priority:2,labels:[{name:"feature"}],url:"https://linear.app/acme/issue/ENG-140",workspaceId:"ws_front",description:"Wire the SAML flow into Settings \u2192 Security."},{id:"t_131",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-131",project:"Platform Config",title:"Migrate config loader to zod",status:"blocked",statusRaw:"Blocked",assignee:{name:"Andy"},priority:2,labels:[{name:"chore"}],url:"https://linear.app/acme/issue/ENG-131",workspaceId:"ws_front",description:"Replace ad-hoc env parsing with a zod schema."},{id:"t_118",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-118",project:"Design System",title:"Refactor the toast provider",status:"in_review",statusRaw:"In Review",assignee:{name:"Andy"},priority:3,labels:[{name:"refactor"}],url:"https://linear.app/acme/issue/ENG-118",workspaceId:"ws_front",description:"Consolidate the two toast systems into one."},{id:"t_090",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-90",project:"Billing",title:"Dark-mode polish on the billing page",status:"done",statusRaw:"Done",priority:4,labels:[{name:"ui"}],url:"https://linear.app/acme/issue/ENG-90",workspaceId:"ws_front"},{id:"t_112",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-112",project:"Dashboard",title:"Empty states for the dashboard widgets",status:"done",statusRaw:"Done",assignee:{name:"Andy"},priority:3,labels:[{name:"ui"}],url:"https://linear.app/acme/issue/ENG-112",workspaceId:"ws_front",description:"Show friendly empty states when a widget has no data yet."},{id:"t_201",connectionId:"conn_personal",provider:"linear",externalIdentifier:"CORE-201",project:"Directives",title:"Cache invalidation for the directives endpoint",status:"todo",statusRaw:"Todo",priority:2,labels:[{name:"perf"}],url:"https://linear.app/personal/issue/CORE-201",workspaceId:"ws_core"},{id:"t_web1",connectionId:"conn_web",provider:"linear",externalIdentifier:"WEB-11",project:"Marketing Site",title:"Rework the pricing page hero",status:"todo",statusRaw:"Todo",priority:3,labels:[{name:"ui"}],url:"https://linear.app/acme/issue/WEB-11",workspaceId:"ws_front",description:"New hero with the updated value prop and a single primary CTA."},{id:"t_web2",connectionId:"conn_web",provider:"linear",externalIdentifier:"WEB-14",project:"Marketing Site",title:"Add OpenGraph images to blog posts",status:"in_progress",statusRaw:"In Progress",priority:2,labels:[{name:"feature"}],url:"https://linear.app/acme/issue/WEB-14",workspaceId:"ws_front",description:"Generate per-post OG images at build time."},{id:"t_web3",connectionId:"conn_web",provider:"linear",externalIdentifier:"WEB-9",project:"Marketing Site",title:"Fix layout shift on the careers page",status:"in_review",statusRaw:"In Review",priority:1,labels:[{name:"bug"}],url:"https://linear.app/acme/issue/WEB-9",workspaceId:"ws_front",description:"Reserve space for the hero image to stop CLS."},{id:"t_local1",connectionId:"conn_local_front",provider:"local",externalIdentifier:"LOCAL-1",project:"Local",title:"Spike: evaluate the new charts library",status:"todo",statusRaw:"Backlog",priority:3,labels:[],url:"",workspaceId:"ws_front",description:"Timebox a day to compare two charting libraries for the dashboard."},{id:"t_local2",connectionId:"conn_local_front",provider:"local",externalIdentifier:"LOCAL-2",project:"Local",title:"Write the onboarding checklist doc",status:"todo",statusRaw:"Backlog",priority:4,labels:[],url:"",workspaceId:"ws_front"}],x={run_web2:{id:"run_web2",ticketId:"t_web2",ticketKey:"WEB-14",title:"Add OpenGraph images to blog posts",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"agent",agentName:"Orchestrator",autonomy:"autonomous",status:"running",sessionId:"e1f2a3b4-5c6d-4e7f-8a90-1b2c3d4e5f60",branchName:"superclawd/WEB-14-9a8b",plan:[{text:"Add the OG image template",done:!0},{text:"Hook into the build",done:!1}],events:[{id:"e1",ts:"14:02",kind:"tool_use",text:"Read scripts/og.ts"}],createdAt:new Date(Date.now()-8*6e4).toISOString(),updatedAt:new Date().toISOString()},run_web3:{id:"run_web3",ticketId:"t_web3",ticketKey:"WEB-9",title:"Fix layout shift on the careers page",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"team",teamName:"Core",autonomy:"autonomous",status:"stopped",stopReason:"completed",sessionId:"f6e5d4c3-2b1a-4098-8f7e-6d5c4b3a2190",branchName:"superclawd/WEB-9-3c4d",prUrl:"https://github.com/acme/web/pull/77",plan:[{text:"Reserve hero space",done:!0},{text:"Verify CLS budget",done:!0}],events:[{id:"e1",ts:"13:10",kind:"verification",text:"CLS 0.02 \u2713"}],createdAt:new Date(Date.now()-70*6e4).toISOString(),updatedAt:new Date(Date.now()-25*6e4).toISOString()},run_140:{id:"run_140",ticketId:"t_140",ticketKey:"ENG-140",title:"Add SSO to the settings page",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"team",teamName:"Core",autonomy:"autonomous",status:"running",sessionId:"3f2a7c9e-1b4d-4a6f-9c2e-8d5b0a1f6e42",branchName:"superclawd/ENG-140-a1b2",plan:[{text:"Read the auth module",done:!0},{text:"Add the SAML client",done:!0},{text:"Wire into Settings \u2192 Security",done:!1},{text:"Add a regression test",done:!1}],events:[{id:"e1",ts:"12:01",kind:"tool_use",text:"Read src/auth.ts"},{id:"e2",ts:"12:02",kind:"commit",text:"wip: SAML client scaffold"},{id:"e3",ts:"12:03",kind:"guardrail",text:"warn: wrote to .env.example (logged)"},{id:"e4",ts:"12:04",kind:"tool_use",text:"Edit src/settings/security.tsx"}],createdAt:new Date(Date.now()-10*6e4).toISOString(),updatedAt:new Date().toISOString()},run_131:{id:"run_131",ticketId:"t_131",ticketKey:"ENG-131",title:"Migrate config loader to zod",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"anyone",autonomy:"supervised",status:"blocked",sessionId:"a91c04b8-7e2f-4d13-b6a0-2c9f5e731d80",branchName:"superclawd/ENG-131-c3d4",plan:[{text:"Inventory env vars",done:!0},{text:"Draft the zod schema",done:!0},{text:"Swap the loader",done:!1},{text:"Update callers",done:!1}],events:[{id:"e1",ts:"11:40",kind:"tool_use",text:"Grep process.env usages"},{id:"e2",ts:"11:44",kind:"commit",text:"wip: zod schema draft"},{id:"e3",ts:"11:46",kind:"mcp_tool",text:"request_human_input(...)"}],blocker:{id:"b_131",origin:"agent",kind:"agent_question",status:"open",question:"Should the metrics call use the REST or GraphQL client? The repo has both."},createdAt:new Date(Date.now()-30*6e4).toISOString(),updatedAt:new Date(Date.now()-4*6e4).toISOString()},run_118:{id:"run_118",ticketId:"t_118",ticketKey:"ENG-118",title:"Refactor the toast provider",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"agent",agentName:"Orchestrator",autonomy:"autonomous",status:"stopped",stopReason:"completed",sessionId:"c7d81f30-5a62-4e09-8b17-46f2a9c3e5d1",branchName:"superclawd/ENG-118-e5f6",prUrl:"https://github.com/acme/app/pull/42",plan:[{text:"Map both toast systems",done:!0},{text:"Unify into one provider",done:!0},{text:"Migrate call sites",done:!0},{text:"Verify build + tests",done:!0}],events:[{id:"e1",ts:"10:20",kind:"commit",text:"refactor: unify toast provider"},{id:"e2",ts:"10:35",kind:"verification",text:"build \u2713 \xB7 tests \u2713 \xB7 lint \u2713"},{id:"e3",ts:"10:36",kind:"mcp_tool",text:"mark_complete(...) \u2192 draft PR #42"}],createdAt:new Date(Date.now()-60*6e4).toISOString(),updatedAt:new Date(Date.now()-20*6e4).toISOString()},run_112:{id:"run_112",ticketId:"t_112",ticketKey:"ENG-112",title:"Empty states for the dashboard widgets",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"team",teamName:"Core",autonomy:"autonomous",status:"stopped",stopReason:"completed",sessionId:"d4e5f6a1-9c02-4b38-a7e1-5f0c2b83d419",branchName:"superclawd/ENG-112-b7c8",prUrl:"https://github.com/acme/app/pull/38",plan:[{text:"Design the empty-state component",done:!0},{text:"Wire it into each widget",done:!0},{text:"Verify build + tests",done:!0}],events:[{id:"e1",ts:"09:10",kind:"commit",text:"feat: dashboard empty states"},{id:"e2",ts:"09:22",kind:"verification",text:"build \u2713 \xB7 tests \u2713"},{id:"e3",ts:"09:23",kind:"state_change",text:"approved by human \u2192 Done"}],createdAt:new Date(Date.now()-90*6e4).toISOString(),updatedAt:new Date(Date.now()-40*6e4).toISOString()},run_090:{id:"run_090",ticketId:"t_090",ticketKey:"ENG-90",title:"Dark-mode polish on the billing page",provider:"linear",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"team",teamName:"Core",autonomy:"supervised",status:"not_started",plan:[],events:[],createdAt:new Date(Date.now()-5*6e4).toISOString(),updatedAt:new Date(Date.now()-5*6e4).toISOString()}},T={t_140:"run_140",t_131:"run_131",t_118:"run_118",t_090:"run_090",t_112:"run_112",t_web2:"run_web2",t_web3:"run_web3"},S={jira_9001:"in_progress",t_123:"backlog",t_090:"backlog",t_140:"in_progress",t_131:"needs_input",t_118:"in_review",t_112:"done",t_201:"backlog",t_web1:"backlog",t_web2:"in_progress",t_web3:"in_review",t_local1:"backlog",t_local2:"backlog"},l={defaultAutonomy:"supervised",maxConcurrentRuns:3,branchPrefix:"feature",defaultModel:"opus",defaultEffort:"high"},F={conv_1:{id:"conv_1",title:"Debounce the workspace search",workspaceId:"ws_front",workspaceName:"Frontend",tier:"Medium",effort:"medium",sessionId:"b8e3d1a4-6f27-4c95-90ab-1e7d32c8f0a5",messages:[{id:"m1",role:"user",text:"How should I debounce the workspace search input?",ts:"09:02"},{id:"m2",role:"assistant",text:`Running under Frontend (Medium \xB7 Sonnet) \u2014 your team, guardrails and memory are in context.
3
3
 
4
4
  Debounce the input ~300ms with a trailing call, cancel in-flight requests on a new keystroke, and skip the fetch for empty queries. Want me to sketch the hook?`,ts:"09:02"}],starred:!0,createdAt:new Date(Date.now()-3*36e5).toISOString(),updatedAt:new Date(Date.now()-3*36e5).toISOString()},conv_2:{id:"conv_2",title:"Explain the credit reservation flow",workspaceId:"ws_core",workspaceName:"Core Platform",tier:"High",effort:"high",sessionId:"3f9c7e21-8a4b-4d16-b0e2-59c8a1f4d7b3",messages:[{id:"m1",role:"user",text:"Walk me through how credits get reserved and finalized on a metered fetch.",ts:"11:20"},{id:"m2",role:"assistant",text:`Running under Core Platform (High \xB7 Opus) \u2014 your team, guardrails and memory are in context.
5
5
 
6
6
  Reserve holds an estimated amount up front, the fetch runs, then finalize settles the real cost and refunds the difference. Want the FOR-UPDATE details?`,ts:"11:20"}],starred:!1,createdAt:new Date(Date.now()-26*36e5).toISOString(),updatedAt:new Date(Date.now()-26*36e5).toISOString()},conv_3:{id:"conv_3",title:"Draft release notes for v2",workspaceId:"ws_front",workspaceName:"Frontend",tier:"Instant",effort:"low",sessionId:"a17d54c9-2be6-4f80-9c3a-6d0f8b2e1a44",messages:[{id:"m1",role:"user",text:"Draft short release notes for the v2 dashboard changes.",ts:"08:05"},{id:"m2",role:"assistant",text:`Running under Frontend (Instant \xB7 Haiku) \u2014 your team, guardrails and memory are in context.
7
7
 
8
- Here\u2019s a first pass grouped by Added / Changed / Fixed. Want me to tighten the copy?`,ts:"08:05"}],starred:!1,createdAt:new Date(Date.now()-2*24*36e5).toISOString(),updatedAt:new Date(Date.now()-2*24*36e5).toISOString()}},te=["conv_3","conv_2","conv_1"],E={sched_1:{id:"sched_1",name:"Triage new bugs",prompt:"Triage new Linear bugs: reproduce, label severity, and open a follow-up for anything urgent.",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"team",teamId:"team_core",teamName:"Core",cadence:"Every 2 hours",enabled:!0,starred:!0,createdAt:new Date(Date.now()-8*24*36e5).toISOString(),lastRunAt:new Date(Date.now()-40*6e4).toISOString(),nextRunAt:new Date(Date.now()+80*6e4).toISOString()},sched_2:{id:"sched_2",name:"Nightly flaky-test sweep",prompt:"Run the test suite, detect flakes, and file an issue per flaky test with the failing output.",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"anyone",cadence:"Every 1 day",enabled:!1,starred:!1,createdAt:new Date(Date.now()-20*24*36e5).toISOString(),lastRunAt:new Date(Date.now()-14*36e5).toISOString(),nextRunAt:null},sched_3:{id:"sched_3",name:"Reconcile credit ledger",prompt:"Reconcile the credit ledger against Stripe: flag drift over $1 and open a dispute task for anything unexplained.",workspaceId:"ws_core",workspaceName:"Core Platform",assignmentKind:"agent",agentId:"agent_orch",agentName:"Orchestrator",cadence:"Every 6 hours",enabled:!0,starred:!0,createdAt:new Date(Date.now()-5*24*36e5).toISOString(),lastRunAt:new Date(Date.now()-2*36e5).toISOString(),nextRunAt:new Date(Date.now()+4*36e5).toISOString()}},H=["sched_1","sched_2","sched_3"],B={sched_1:Array.from({length:14},(e,t)=>({id:`srun_1_${14-t}`,scheduleId:"sched_1",status:t===0?"success":t%6===0?"failed":"success",sessionId:`a1b2c3${String(14-t).padStart(2,"0")}-6f27-4c95-90ab-1e7d32c8f0a5`,startedAt:new Date(Date.now()-(40+t*120)*6e4).toISOString(),finishedAt:new Date(Date.now()-(40+t*120)*6e4+95e3).toISOString(),output:t%6===0?"Failed: could not reach the Linear API (429). Will retry next tick.":`Triaged ${2+t%4} new issues \xB7 labeled severity \xB7 opened ${t%3===0?1:0} follow-up. (mocked output)`})),sched_2:Array.from({length:3},(e,t)=>({id:`srun_2_${3-t}`,scheduleId:"sched_2",status:"success",sessionId:`d4e5f6${String(3-t).padStart(2,"0")}-9c02-4b38-a7e1-5f0c2b83d419`,startedAt:new Date(Date.now()-(14+t*24)*36e5).toISOString(),finishedAt:new Date(Date.now()-(14+t*24)*36e5+22e4).toISOString(),output:`Ran the suite \xB7 ${t===0?"no":"1"} flaky test found${t===0?"":" \xB7 filed 1 issue"}. (mocked output)`})),sched_3:Array.from({length:7},(e,t)=>({id:`srun_3_${7-t}`,scheduleId:"sched_3",status:"success",sessionId:`c7d8e9${String(7-t).padStart(2,"0")}-4b38-4c95-90ab-1e7d32c8f0a5`,startedAt:new Date(Date.now()-(2+t*6)*36e5).toISOString(),finishedAt:new Date(Date.now()-(2+t*6)*36e5+18e4).toISOString(),output:`Reconciled ${180+t*12} charges \xB7 ${t%3===0?"no drift":"flagged 1 mismatch \xB7 opened dispute task"}. (mocked output)`}))},L={runSeq:500,convSeq:3,schedSeq:3,schedRunSeq:100,localSeq:2},q=[],P=[],C=[],G=[],J=[{id:"jira_9002",connectionId:"conn_jira_demo",provider:"jira",externalIdentifier:"PLAT-2",project:"Platform",title:"Add rate-limit headers to the public API",status:"todo",statusRaw:"To Do",assignee:{name:"Priya"},priority:3,labels:[{name:"api"}],url:"https://demo.atlassian.net/browse/PLAT-2",workspaceId:"ws_core",description:"Surface X-RateLimit-* so clients can back off."},{id:"s_150",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-150",project:"Frontend App",title:"Debounce the workspace search input",status:"todo",statusRaw:"Todo",assignee:{name:"Priya"},priority:3,labels:[{name:"ui"}],url:"https://linear.app/acme/issue/ENG-150",workspaceId:"ws_front",description:"The search fires a request per keystroke; debounce ~300ms."},{id:"s_151",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-151",project:"CI",title:"Flaky test: auth.session.spec times out on CI",status:"todo",statusRaw:"Todo",assignee:{name:"Sam"},priority:1,labels:[{name:"bug"},{name:"ci"}],url:"https://linear.app/acme/issue/ENG-151",workspaceId:"ws_front",description:"Intermittent 30s timeout; suspect a missing await."},{id:"s_152",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-152",project:"Public API",title:"Add rate-limit headers to the public API",status:"backlog",statusRaw:"Backlog",priority:2,labels:[{name:"api"}],url:"https://linear.app/acme/issue/ENG-152",workspaceId:"ws_front",description:"Expose X-RateLimit-* on responses."},{id:"s_160",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-160",project:"Auth",title:"Login page: remember-me checkbox does nothing",status:"todo",statusRaw:"Todo",assignee:{name:"Andy"},priority:2,labels:[{name:"bug"}],url:"https://linear.app/acme/issue/ENG-160",workspaceId:"ws_front",description:"Session still expires on browser close."},{id:"s_210",connectionId:"conn_personal",provider:"linear",externalIdentifier:"CORE-210",project:"Directives",title:"Batch the memory-read endpoint",status:"backlog",statusRaw:"Backlog",priority:2,labels:[{name:"perf"}],url:"https://linear.app/personal/issue/CORE-210",workspaceId:"ws_core",description:"Coalesce N per-memory fetches into one batch call."},{id:"s_211",connectionId:"conn_personal",provider:"linear",externalIdentifier:"CORE-211",project:"Docs",title:"Document the directives cache TTL",status:"todo",statusRaw:"Todo",priority:4,labels:[{name:"docs"}],url:"https://linear.app/personal/issue/CORE-211",workspaceId:"ws_core"}]});var Tn={};bi(Tn,{seedFromFixtures:()=>Si});async function Si(){let e=A();await $e.bulkCreate(y.map(n=>({...n,userId:e}))),await ke.bulkCreate(h.map((n,r)=>({...n,userId:e,column:S[n.id]??"backlog",position:r}))),await _e.bulkCreate(Object.values(I).map(n=>({...n,userId:e}))),await Me.bulkCreate(H.map(n=>({...E[n],userId:e})));let t=Object.keys(B).flatMap(n=>{let r=B[n];return r.map((s,o)=>({...s,userId:e,seq:r.length-o}))});await Ae.bulkCreate(t),await Ne.bulkCreate(te.map(n=>({...M[n],userId:e}))),await Ee.bulkCreate(q.map(n=>({...n,userId:e}))),await Le.bulkCreate(P.map(n=>({...n,userId:e}))),await Pe.bulkCreate(C.map((n,r)=>({...n,userId:e,position:n.position??r}))),await Ce.bulkCreate(G.map((n,r)=>({...n,userId:e,position:n.position??r}))),await He.create({userId:e,defaultAutonomy:l.defaultAutonomy,maxConcurrentRuns:l.maxConcurrentRuns??3,branchPrefix:l.branchPrefix??"feature",connectedWorkspaces:l.connectedWorkspaces??null,workspaceDirs:l.workspaceDirs??null,defaultModel:l.defaultModel??null,defaultEffort:l.defaultEffort??null})}var _n=Rn(()=>{"use strict";V();Je()});import Ii from"node:os";import Ar from"node:path";import xi from"node:fs";import{Sequelize as vi,DataTypes as a}from"sequelize";import{Umzug as Ri}from"umzug";function A(){return Nr}function qt(e){Nr=e}async function _r(e){try{return await e.count()}catch{return 0}}async function Cr(){if(xi.mkdirSync(Ar.dirname(Bt),{recursive:!0}),await k.authenticate(),await Ti.up(),await _r(ke)===0&&await _r(Ne)===0&&A()===xt){let{seedFromFixtures:t}=await Promise.resolve().then(()=>(_n(),Tn));await t()}}var Bt,xt,Nr,k,$e,ke,_e,Me,Ae,Ne,He,ze,Ee,Le,Ce,Pe,Er,Ti,Je=Rn(()=>{"use strict";Bt=process.env.PIPELINES_DB_PATH??Ar.join(Ii.homedir(),".superclawd","pipelines.db"),xt=process.env.PIPELINES_DEV_USER_ID??"dev-user",Nr=xt;k=new vi({dialect:"sqlite",storage:Bt,logging:!1}),$e=k.define("Connection",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,provider:a.STRING,providerAccountName:a.STRING,displayName:a.STRING,workspaceId:a.STRING,workspaceName:a.STRING,workingDir:a.STRING,linkStatus:a.STRING,linkLostReason:a.STRING,authStatus:a.STRING,lastSyncedAt:a.STRING,ticketCount:a.INTEGER,syncFilters:a.JSON,cloudId:a.STRING,providerAccountId:a.STRING},{tableName:"connections",underscored:!0,timestamps:!1}),ke=k.define("Ticket",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,connectionId:a.STRING,provider:a.STRING,externalIdentifier:a.STRING,title:a.STRING,description:a.TEXT,status:a.STRING,statusRaw:a.STRING,assignee:a.JSON,reporter:a.JSON,dueDate:a.STRING,priority:a.INTEGER,labels:a.JSON,project:a.STRING,parent:a.JSON,model:a.STRING,effort:a.STRING,blockedReason:a.TEXT,comments:a.JSON,additionalContext:a.TEXT,plan:a.TEXT,conclusion:a.TEXT,additionalContextUpdatedAt:a.STRING,planUpdatedAt:a.STRING,conclusionUpdatedAt:a.STRING,createdAt:a.STRING,updatedAt:a.STRING,prLinks:a.JSON,attempt:a.INTEGER,dependsOn:a.JSON,prMonitor:a.BOOLEAN,prMonitorCount:a.INTEGER,prMonitorLastAt:a.STRING,prMonitorNote:a.TEXT,url:a.STRING,workspaceId:a.STRING,workingDir:a.STRING,column:a.STRING,position:a.INTEGER},{tableName:"tickets",underscored:!0,timestamps:!1}),_e=k.define("Run",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,ticketId:a.STRING,ticketKey:a.STRING,title:a.STRING,provider:a.STRING,workspaceId:a.STRING,workspaceName:a.STRING,assignmentKind:a.STRING,teamName:a.STRING,agentName:a.STRING,autonomy:a.STRING,status:a.STRING,stopReason:a.STRING,sessionId:a.STRING,branchName:a.STRING,prUrl:a.STRING,worktrees:a.JSON,blocker:a.JSON,plan:a.JSON,events:a.JSON,resultText:a.TEXT,pid:a.INTEGER,pgid:a.INTEGER,createdAt:a.STRING,updatedAt:a.STRING},{tableName:"runs",underscored:!0,timestamps:!1}),Me=k.define("Schedule",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,name:a.STRING,prompt:a.TEXT,workspaceId:a.STRING,workspaceName:a.STRING,assignmentKind:a.STRING,teamId:a.STRING,teamName:a.STRING,agentId:a.STRING,agentName:a.STRING,cadence:a.STRING,workingDir:a.STRING,model:a.STRING,effort:a.STRING,enabled:a.BOOLEAN,starred:a.BOOLEAN,createdAt:a.STRING,lastRunAt:a.STRING,nextRunAt:a.STRING},{tableName:"schedules",underscored:!0,timestamps:!1}),Ae=k.define("ScheduleRun",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,scheduleId:a.STRING,status:a.STRING,sessionId:a.STRING,startedAt:a.STRING,finishedAt:a.STRING,output:a.TEXT,model:a.STRING,effort:a.STRING,seq:a.INTEGER},{tableName:"schedule_runs",underscored:!0,timestamps:!1}),Ne=k.define("Conversation",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,title:a.STRING,workspaceId:a.STRING,workspaceName:a.STRING,tier:a.STRING,effort:a.STRING,sessionId:a.STRING,workingDir:a.STRING,messages:a.JSON,starred:a.BOOLEAN,createdAt:a.STRING,updatedAt:a.STRING},{tableName:"conversations",underscored:!0,timestamps:!1}),He=k.define("Setting",{userId:{type:a.STRING,primaryKey:!0},defaultAutonomy:a.STRING,maxConcurrentRuns:a.INTEGER,branchPrefix:a.STRING,connectedWorkspaces:a.JSON,workspaceDirs:a.JSON,defaultModel:a.STRING,defaultEffort:a.STRING,prMonitorDefault:a.BOOLEAN,prMonitorIntervalMinutes:a.INTEGER,prMonitorMaxEngagements:a.INTEGER,prMonitorReplyToComments:a.BOOLEAN,sandboxWorktreeEdits:a.BOOLEAN,publicApiEnabled:a.BOOLEAN,apiKeyHash:a.STRING,apiKeyLast4:a.STRING,apiKeyCreatedAt:a.STRING,webhookEnabled:a.BOOLEAN,webhookUrl:a.STRING,webhookHeaders:a.JSON,webhookEvents:a.JSON,webhookSecret:a.TEXT},{tableName:"settings",underscored:!0,timestamps:!1}),ze=k.define("OAuthToken",{connectionId:{type:a.STRING,primaryKey:!0},userId:a.STRING,provider:a.STRING,accessToken:a.TEXT,refreshToken:a.TEXT,scope:a.STRING,expiresAt:a.STRING},{tableName:"oauth_tokens",underscored:!0,timestamps:!1}),Ee=k.define("RunResult",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,ticketId:a.STRING,runId:a.STRING,sessionId:a.STRING,prompt:a.TEXT,response:a.TEXT,status:a.STRING,model:a.STRING,effort:a.STRING,createdAt:a.STRING},{tableName:"run_results",underscored:!0,timestamps:!1}),Le=k.define("Note",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,ticketId:a.STRING,scheduleId:a.STRING,author:a.STRING,body:a.TEXT,createdAt:a.STRING,updatedAt:a.STRING},{tableName:"notes",underscored:!0,timestamps:!1}),Ce=k.define("MessagePreset",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,title:a.STRING,prompt:a.TEXT,enabled:a.BOOLEAN,position:a.INTEGER,createdAt:a.STRING,updatedAt:a.STRING},{tableName:"message_presets",underscored:!0,timestamps:!1}),Pe=k.define("OpenQuestion",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,ticketId:a.STRING,question:a.TEXT,answer:a.TEXT,resolved:a.BOOLEAN,position:a.INTEGER,createdAt:a.STRING,updatedAt:a.STRING},{tableName:"open_questions",underscored:!0,timestamps:!1}),Er={Connection:$e,Ticket:ke,Run:_e,Schedule:Me,ScheduleRun:Ae,Conversation:Ne,Setting:He,OAuthToken:ze,RunResult:Ee,Note:Le,MessagePreset:Ce,OpenQuestion:Pe},Ti=new Ri({context:k.getQueryInterface(),storage:{async logMigration({name:e}){await k.query("INSERT INTO pipelines_migrations (name) VALUES (:name)",{replacements:{name:e}})},async unlogMigration({name:e}){await k.query("DELETE FROM pipelines_migrations WHERE name = :name",{replacements:{name:e}})},async executed(){await k.query("CREATE TABLE IF NOT EXISTS pipelines_migrations (name TEXT PRIMARY KEY)");let[e]=await k.query("SELECT name FROM pipelines_migrations ORDER BY name");return e.map(t=>t.name)}},logger:void 0,migrations:[{name:"0001-init",async up(){await k.sync()}},{name:"0002-oauth-tokens",async up(){await ze.sync()}},{name:"0003-settings-branch-prefix",async up(){let e=k.getQueryInterface();(await e.describeTable("settings")).branch_prefix||await e.addColumn("settings","branch_prefix",{type:a.STRING,allowNull:!0})}},{name:"0004-settings-connected-workspaces",async up(){let e=k.getQueryInterface();(await e.describeTable("settings")).connected_workspaces||await e.addColumn("settings","connected_workspaces",{type:a.JSON,allowNull:!0})}},{name:"0005-runs-result-text",async up(){let e=k.getQueryInterface();(await e.describeTable("runs")).result_text||await e.addColumn("runs","result_text",{type:a.TEXT,allowNull:!0})}},{name:"0006-run-results",async up(){let e=k.getQueryInterface();(await e.showAllTables()).map(String).includes("run_results")||await e.createTable("run_results",{id:{type:a.STRING,primaryKey:!0},user_id:a.STRING,ticket_id:a.STRING,run_id:a.STRING,session_id:a.STRING,prompt:a.TEXT,response:a.TEXT,status:a.STRING,created_at:a.STRING})}},{name:"0007-comments",async up(){let e=k.getQueryInterface();(await e.showAllTables()).map(String).includes("comments")||await e.createTable("comments",{id:{type:a.STRING,primaryKey:!0},user_id:a.STRING,ticket_id:a.STRING,author:a.STRING,body:a.TEXT,created_at:a.STRING})}},{name:"0008-comments-updated-at",async up(){let e=k.getQueryInterface();(await e.describeTable("comments")).updated_at||await e.addColumn("comments","updated_at",{type:a.STRING,allowNull:!0})}},{name:"0009-conversations-working-dir",async up(){let e=k.getQueryInterface();(await e.describeTable("conversations")).working_dir||await e.addColumn("conversations","working_dir",{type:a.STRING,allowNull:!0})}},{name:"0010-settings-workspace-dirs",async up(){let e=k.getQueryInterface();(await e.describeTable("settings")).workspace_dirs||await e.addColumn("settings","workspace_dirs",{type:a.JSON,allowNull:!0})}},{name:"0011-tickets-working-dir",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).working_dir||await e.addColumn("tickets","working_dir",{type:a.STRING,allowNull:!0})}},{name:"0012-schedules-working-dir",async up(){let e=k.getQueryInterface();(await e.describeTable("schedules")).working_dir||await e.addColumn("schedules","working_dir",{type:a.STRING,allowNull:!0})}},{name:"0013-rename-comments-to-notes",async up(){let e=k.getQueryInterface(),t=(await e.showAllTables()).map(String);t.includes("comments")&&!t.includes("notes")&&await e.renameTable("comments","notes")}},{name:"0014-notes-schedule-id",async up(){let e=k.getQueryInterface();(await e.describeTable("notes")).schedule_id||await e.addColumn("notes","schedule_id",{type:a.STRING,allowNull:!0})}},{name:"0015-connections-sync-filters",async up(){let e=k.getQueryInterface();(await e.describeTable("connections")).sync_filters||await e.addColumn("connections","sync_filters",{type:a.JSON,allowNull:!0})}},{name:"0016-tickets-parent",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).parent||await e.addColumn("tickets","parent",{type:a.JSON,allowNull:!0})}},{name:"0017-conversations-effort",async up(){let e=k.getQueryInterface();(await e.describeTable("conversations")).effort||await e.addColumn("conversations","effort",{type:a.STRING,allowNull:!0})}},{name:"0018-model-effort",async up(){let e=k.getQueryInterface(),t={type:a.STRING,allowNull:!0},n=async(r,s)=>{(await e.describeTable(r))[s]||await e.addColumn(r,s,t)};await n("settings","default_model"),await n("settings","default_effort");for(let r of["tickets","schedules","run_results","schedule_runs"])await n(r,"model"),await n(r,"effort")}},{name:"0019-tickets-blocked-reason",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).blocked_reason||await e.addColumn("tickets","blocked_reason",{type:a.TEXT,allowNull:!0})}},{name:"0020-message-presets",async up(){let e=k.getQueryInterface();(await e.showAllTables()).map(String).includes("message_presets")||await e.createTable("message_presets",{id:{type:a.STRING,primaryKey:!0},user_id:a.STRING,title:a.STRING,prompt:a.TEXT,enabled:a.BOOLEAN,position:a.INTEGER,created_at:a.STRING,updated_at:a.STRING})}},{name:"0021-ticket-context-fields",async up(){let e=k.getQueryInterface(),t=await e.describeTable("tickets"),n={type:a.TEXT,allowNull:!0};t.additional_context||await e.addColumn("tickets","additional_context",n),!t.tech_plan&&!t.plan&&await e.addColumn("tickets","tech_plan",n),t.conclusion||await e.addColumn("tickets","conclusion",n)}},{name:"0022-open-questions",async up(){let e=k.getQueryInterface();(await e.showAllTables()).map(String).includes("open_questions")||await e.createTable("open_questions",{id:{type:a.STRING,primaryKey:!0},user_id:a.STRING,ticket_id:a.STRING,question:a.TEXT,answer:a.TEXT,resolved:a.BOOLEAN,position:a.INTEGER,created_at:a.STRING,updated_at:a.STRING})}},{name:"0023-rename-tech-plan-to-plan",async up(){let e=k.getQueryInterface(),t=await e.describeTable("tickets");t.tech_plan&&!t.plan&&await e.renameColumn("tickets","tech_plan","plan")}},{name:"0024-ticket-context-timestamps",async up(){let e=k.getQueryInterface(),t=await e.describeTable("tickets"),n={type:a.STRING,allowNull:!0};t.additional_context_updated_at||await e.addColumn("tickets","additional_context_updated_at",n),t.plan_updated_at||await e.addColumn("tickets","plan_updated_at",n),t.conclusion_updated_at||await e.addColumn("tickets","conclusion_updated_at",n)}},{name:"0025-ticket-created-updated",async up(){let e=k.getQueryInterface(),t=await e.describeTable("tickets"),n={type:a.STRING,allowNull:!0};t.created_at||await e.addColumn("tickets","created_at",n),t.updated_at||await e.addColumn("tickets","updated_at",n)}},{name:"0026-ticket-pr-links",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).pr_links||await e.addColumn("tickets","pr_links",{type:a.JSON,allowNull:!0})}},{name:"0027-run-worktrees",async up(){let e=k.getQueryInterface();(await e.describeTable("runs")).worktrees||await e.addColumn("runs","worktrees",{type:a.JSON,allowNull:!0})}},{name:"0028-ticket-attempt",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).attempt||await e.addColumn("tickets","attempt",{type:a.INTEGER,allowNull:!0})}},{name:"0029-pr-monitor",async up(){let e=k.getQueryInterface(),t={type:a.INTEGER,allowNull:!0},n={type:a.BOOLEAN,allowNull:!0},r={type:a.STRING,allowNull:!0},s={type:a.TEXT,allowNull:!0},o=await e.describeTable("settings");o.pr_monitor_default||await e.addColumn("settings","pr_monitor_default",n),o.pr_monitor_interval_minutes||await e.addColumn("settings","pr_monitor_interval_minutes",t),o.pr_monitor_max_engagements||await e.addColumn("settings","pr_monitor_max_engagements",t),o.pr_monitor_reply_to_comments||await e.addColumn("settings","pr_monitor_reply_to_comments",n);let i=await e.describeTable("tickets");i.pr_monitor||await e.addColumn("tickets","pr_monitor",n),i.pr_monitor_count||await e.addColumn("tickets","pr_monitor_count",t),i.pr_monitor_last_at||await e.addColumn("tickets","pr_monitor_last_at",r),i.pr_monitor_note||await e.addColumn("tickets","pr_monitor_note",s)}},{name:"0030-ticket-depends-on",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).depends_on||await e.addColumn("tickets","depends_on",{type:a.JSON,allowNull:!0})}},{name:"0031-settings-sandbox",async up(){let e=k.getQueryInterface();(await e.describeTable("settings")).sandbox_worktree_edits||await e.addColumn("settings","sandbox_worktree_edits",{type:a.BOOLEAN,allowNull:!0})}},{name:"0032-connection-cloud-id",async up(){let e=k.getQueryInterface();(await e.describeTable("connections")).cloud_id||await e.addColumn("connections","cloud_id",{type:a.STRING,allowNull:!0})}},{name:"0033-ticket-reporter-due-date",async up(){let e=k.getQueryInterface(),t=await e.describeTable("tickets");t.reporter||await e.addColumn("tickets","reporter",{type:a.JSON,allowNull:!0}),t.due_date||await e.addColumn("tickets","due_date",{type:a.STRING,allowNull:!0})}},{name:"0034-connection-provider-account-id",async up(){let e=k.getQueryInterface();(await e.describeTable("connections")).provider_account_id||await e.addColumn("connections","provider_account_id",{type:a.STRING,allowNull:!0})}},{name:"0035-settings-public-api",async up(){let e=k.getQueryInterface(),t=await e.describeTable("settings"),n=async(r,s)=>{t[r]||await e.addColumn("settings",r,{type:s,allowNull:!0})};await n("public_api_enabled",a.BOOLEAN),await n("api_key_hash",a.STRING),await n("api_key_last4",a.STRING),await n("api_key_created_at",a.STRING),await n("webhook_enabled",a.BOOLEAN),await n("webhook_url",a.STRING),await n("webhook_headers",a.JSON),await n("webhook_events",a.JSON),await n("webhook_secret",a.TEXT)}},{name:"0036-ticket-comments",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).comments||await e.addColumn("tickets","comments",{type:a.JSON,allowNull:!0})}}]})});V();Je();import In from"express";import Jc from"cors";import{randomUUID as Ke}from"node:crypto";import Q from"node:path";import ve from"node:fs";import Sn from"node:os";import{fileURLToPath as zc}from"node:url";V();import Oe from"node:crypto";import An from"node:fs";import _i from"node:os";import Cn from"node:path";var En="enc:v1:",Ai=process.env.SUPERCLAWD_HOME||Cn.join(_i.homedir(),".superclawd"),Nn=process.env.PIPELINES_KEY_FILE||Cn.join(Ai,"pipelines.key"),vt=null;function Pr(){if(vt)return vt;An.mkdirSync(Cn.dirname(Nn),{recursive:!0});try{let t=An.readFileSync(Nn);if(t.length===32)return vt=t,vt}catch{}let e=Oe.randomBytes(32);return An.writeFileSync(Nn,e,{mode:384}),vt=e,e}function Xe(e){let t=Oe.randomBytes(12),n=Oe.createCipheriv("aes-256-gcm",Pr(),t),r=Buffer.concat([n.update(e,"utf8"),n.final()]),s=n.getAuthTag();return`${En}${t.toString("base64")}:${s.toString("base64")}:${r.toString("base64")}`}function Ye(e){if(!e.startsWith(En))return e;let[t,n,r]=e.slice(En.length).split(":"),s=Oe.createDecipheriv("aes-256-gcm",Pr(),Buffer.from(t,"base64"));return s.setAuthTag(Buffer.from(n,"base64")),Buffer.concat([s.update(Buffer.from(r,"base64")),s.final()]).toString("utf8")}function Ve(e){return Oe.createHash("sha256").update(e,"utf8").digest("hex")}function Ze(e="",t=32){return e+Oe.randomBytes(t).toString("base64url")}function Rt(e,t){let n=Buffer.from(e),r=Buffer.from(t);return n.length!==r.length?!1:Oe.timingSafeEqual(n,r)}function Or(e,t){return Oe.createHmac("sha256",e).update(t,"utf8").digest("hex")}Je();function Ni(e){let t={};for(let[n,r]of Object.entries(e))r!=null&&(t[n]=r);return t}var z=e=>e.get({plain:!0}),ne=(e,t)=>{let n={...e};for(let r of t)delete n[r];return Ni(n)};function Dr(e){let t={};for(let[n,r]of Object.entries(e))t[n]=r===void 0?null:r;return t}function Tt(e,t){let n=0;for(let r of e){let s=new RegExp(`^${t}_?(\\d+)$`).exec(r);s&&(n=Math.max(n,Number(s[1])))}return n}async function jr(){let e={where:{userId:A()}},t=await $e.findAll(e);y.length=0,y.push(...t.map(p=>ne(z(p),["userId"])));let n=await ke.findAll({...e,order:[["position","ASC"]]});h.length=0;for(let p of Object.keys(S))delete S[p];for(let p of n){let w=z(p);S[w.id]=w.column??"backlog",h.push(ne(w,["userId","column","position"]))}let r=await _e.findAll(e);for(let p of Object.keys(I))delete I[p];for(let p of Object.keys(x))delete x[p];for(let p of r){let w=ne(z(p),["userId","pid","pgid"]);I[w.id]=w,x[w.ticketId]=w.id}let s=await Me.findAll({...e,order:[["createdAt","ASC"]]});for(let p of Object.keys(E))delete E[p];H.length=0;for(let p of s){let w=ne(z(p),["userId"]);E[w.id]=w,H.push(w.id)}let o=await Ae.findAll({...e,order:[["seq","DESC"]]});for(let p of Object.keys(B))delete B[p];for(let p of H)B[p]=[];for(let p of o){let w=z(p),Y=ne(w,["userId","seq"]);(B[w.scheduleId]??=[]).push(Y)}let i=await Ne.findAll({...e,order:[["updatedAt","DESC"]]});for(let p of Object.keys(M))delete M[p];te.length=0;for(let p of i){let w=ne(z(p),["userId"]);w.messages||(w.messages=[]),M[w.id]=w,te.push(w.id)}let c=await Ee.findAll({...e,order:[["createdAt","DESC"]]});q.length=0;for(let p of c)q.push(ne(z(p),["userId"]));let d=await Le.findAll({...e,order:[["createdAt","ASC"]]});P.length=0;for(let p of d)P.push(ne(z(p),["userId"]));let u=await Ce.findAll({...e,order:[["position","ASC"]]});G.length=0;for(let p of u)G.push(ne(z(p),["userId"]));let m=await Pe.findAll({...e,order:[["position","ASC"]]});C.length=0;for(let p of m)C.push(ne(z(p),["userId"]));let g=await He.findByPk(A());if(g){let p=z(g);l.defaultAutonomy=p.defaultAutonomy??l.defaultAutonomy,typeof p.maxConcurrentRuns=="number"&&(l.maxConcurrentRuns=p.maxConcurrentRuns),typeof p.branchPrefix=="string"&&(l.branchPrefix=p.branchPrefix),Array.isArray(p.connectedWorkspaces)&&(l.connectedWorkspaces=p.connectedWorkspaces),p.workspaceDirs&&typeof p.workspaceDirs=="object"&&(l.workspaceDirs=p.workspaceDirs),typeof p.defaultModel=="string"&&(l.defaultModel=p.defaultModel),typeof p.defaultEffort=="string"&&(l.defaultEffort=p.defaultEffort),typeof p.prMonitorDefault=="boolean"&&(l.prMonitorDefault=p.prMonitorDefault),typeof p.prMonitorIntervalMinutes=="number"&&(l.prMonitorIntervalMinutes=p.prMonitorIntervalMinutes),typeof p.prMonitorMaxEngagements=="number"&&(l.prMonitorMaxEngagements=p.prMonitorMaxEngagements),typeof p.prMonitorReplyToComments=="boolean"&&(l.prMonitorReplyToComments=p.prMonitorReplyToComments),typeof p.sandboxWorktreeEdits=="boolean"&&(l.sandboxWorktreeEdits=p.sandboxWorktreeEdits),typeof p.publicApiEnabled=="boolean"&&(l.publicApiEnabled=p.publicApiEnabled),typeof p.apiKeyHash=="string"&&(l.apiKeyHash=p.apiKeyHash),typeof p.apiKeyLast4=="string"&&(l.apiKeyLast4=p.apiKeyLast4),typeof p.apiKeyCreatedAt=="string"&&(l.apiKeyCreatedAt=p.apiKeyCreatedAt),typeof p.webhookEnabled=="boolean"&&(l.webhookEnabled=p.webhookEnabled),typeof p.webhookUrl=="string"&&(l.webhookUrl=p.webhookUrl),Array.isArray(p.webhookHeaders)&&(l.webhookHeaders=p.webhookHeaders.map(w=>({key:w.key,value:Ye(String(w.value??""))}))),Array.isArray(p.webhookEvents)&&(l.webhookEvents=p.webhookEvents),typeof p.webhookSecret=="string"&&(l.webhookSecret=Ye(p.webhookSecret))}L.convSeq=Tt(Object.keys(M),"conv"),L.schedSeq=Tt(Object.keys(E),"sched"),L.localSeq=Math.max(L.localSeq,Tt(h.map(p=>p.id),"t_local")),L.schedRunSeq=Tt(o.map(p=>z(p).id),"srun"),L.runSeq=Tt(Object.keys(I),"run")}async function R(e){await $e.upsert({...e,userId:A()})}async function $r(e){await $e.destroy({where:{id:e}})}async function Ft(){for(let e of j){let t=`conn_local_${e.id}`;if(y.some(r=>r.provider==="local"&&r.workspaceId===e.id))continue;let n={id:t,provider:"local",providerAccountName:"Local",workspaceId:e.id,workspaceName:e.name,workingDir:null,linkStatus:"linked",authStatus:"connected",lastSyncedAt:null,ticketCount:0};y.push(n),await R(n)}}async function T(e){let t=h.find(n=>n.id===e);t&&await ke.upsert(Dr({...t,userId:A(),column:S[e]??"backlog",position:h.indexOf(t)}))}async function Mr(){await Promise.all(h.map((e,t)=>ke.update({position:t,column:S[e.id]??"backlog"},{where:{id:e.id}})))}async function Wt(e){await ke.destroy({where:{id:e}}),await _e.destroy({where:{ticketId:e}})}async function $(e){let t=I[e];t&&await _e.upsert({...t,userId:A()})}async function Lr(e){await _e.destroy({where:{id:e}})}async function _t(e){let t=E[e];t&&await Me.upsert({...t,userId:A()})}async function Gr(e){await Me.destroy({where:{id:e}}),await Ae.destroy({where:{scheduleId:e}})}async function Kt(e,t){await Ae.upsert({...e,userId:A(),seq:t})}async function Ge(e){let t=M[e];t&&await Ne.upsert({...t,userId:A()})}async function Ur(e){await Ne.destroy({where:{id:e}})}async function Qt(e){await Ee.upsert({...e,userId:A()})}async function Br(e){await Ee.destroy({where:{ticketId:e,userId:A()}})}async function qr(e,t,n){let{count:r,rows:s}=await Ee.findAndCountAll({where:{ticketId:e,userId:A()},order:[["createdAt","DESC"]],limit:t,offset:n});return{entries:s.map(o=>ne(z(o),["userId"])),total:r}}async function Fr(e,t,n){let{count:r,rows:s}=await Ae.findAndCountAll({where:{scheduleId:e,userId:A()},order:[["seq","DESC"]],limit:t,offset:n});return{runs:s.map(o=>ne(z(o),["userId","seq"])),total:r}}async function et(e){await Le.upsert({...e,userId:A()})}async function Ht(e){await Le.destroy({where:{id:e}})}async function Jt(e){let t=G.find(n=>n.id===e);t&&await Ce.upsert({...t,userId:A()})}async function Wr(e){await Ce.destroy({where:{id:e}})}async function Kr(){await Promise.all(G.map((e,t)=>Ce.update({position:t},{where:{id:e.id}})))}async function Pn(e){let t=C.find(n=>n.id===e);t&&await Pe.upsert(Dr({...t,userId:A()}))}async function zt(e){await Pe.destroy({where:{id:e}})}async function Qr(){await Promise.all(C.map((e,t)=>Pe.update({position:t},{where:{id:e.id}})))}async function X(){await He.upsert({userId:A(),defaultAutonomy:l.defaultAutonomy,maxConcurrentRuns:l.maxConcurrentRuns??3,branchPrefix:l.branchPrefix??"feature",connectedWorkspaces:l.connectedWorkspaces??null,workspaceDirs:l.workspaceDirs??null,defaultModel:l.defaultModel??null,defaultEffort:l.defaultEffort??null,prMonitorDefault:l.prMonitorDefault??null,prMonitorIntervalMinutes:l.prMonitorIntervalMinutes??null,prMonitorMaxEngagements:l.prMonitorMaxEngagements??null,prMonitorReplyToComments:l.prMonitorReplyToComments??null,sandboxWorktreeEdits:l.sandboxWorktreeEdits??null,publicApiEnabled:l.publicApiEnabled??null,apiKeyHash:l.apiKeyHash??null,apiKeyLast4:l.apiKeyLast4??null,apiKeyCreatedAt:l.apiKeyCreatedAt??null,webhookEnabled:l.webhookEnabled??null,webhookUrl:l.webhookUrl??null,webhookHeaders:l.webhookHeaders?l.webhookHeaders.map(e=>({key:e.key,value:Xe(e.value)})):null,webhookEvents:l.webhookEvents??null,webhookSecret:l.webhookSecret?Xe(l.webhookSecret):null})}async function Hr(){let e={where:{userId:A()}};await Promise.all(Object.values(Er).map(t=>t.destroy(e)))}async function Jr(){await Hr();let{seedFromFixtures:e}=await Promise.resolve().then(()=>(_n(),Tn));await e()}async function zr(){let e=new Set(j.map(o=>o.id)),t=[],n=new Set;for(let o of y)o.provider!=="local"||!o.workspaceId||!e.has(o.workspaceId)||n.has(o.workspaceId)||(n.add(o.workspaceId),t.push(o));let r=o=>{o.length=0},s=o=>{for(let i of Object.keys(o))delete o[i]};r(y),y.push(...t),r(h),r(J),r(q),r(P),r(C),r(H),r(te),s(I),s(x),s(S),s(E),s(B),s(M),await Hr();for(let o of t)await R(o);await Ft(),await X();for(let o of G)await Jt(o.id)}import Xt from"node:fs";import Ei from"node:os";import On from"node:path";function Ci(){let e=process.env.CLAUDE_CONFIG_DIR||On.join(Ei.homedir(),".claude");return On.join(e,"projects")}function Xr(e){let t=Ci(),n;try{n=Xt.readdirSync(t)}catch{return null}let r=`${e}.jsonl`;for(let s of n){let o=On.join(t,s,r);if(Xt.existsSync(o))return o}return null}function Pi(e){return Array.isArray(e)?e.filter(t=>!!t&&typeof t=="object"&&t.type==="text"&&typeof t.text=="string").map(t=>t.text).join("").trim():typeof e=="string"?e.trim():""}function Yt(e){return Dn(e).response}function Dn(e){let t=Xr(e);if(!t)return{prompt:null,response:null};let n;try{n=Xt.readFileSync(t,"utf8")}catch{return{prompt:null,response:null}}let r=null,s=null;for(let o of n.split(`
9
- `)){let i=o.trim();if(!i)continue;let c;try{c=JSON.parse(i)}catch{continue}let d=c,u=Pi(d.message?.content);u&&(d.type==="user"&&r===null&&(r=u),d.type==="assistant"&&(s=u))}return{prompt:r,response:s}}function Oi(e,t){let n=typeof e=="string"?e:"tool",r=n.includes("__")?n.slice(n.lastIndexOf("__")+2):n,s=t??{},o=(i,c=80)=>{let u=(typeof i=="string"?i:i==null?"":JSON.stringify(i)).replace(/\s+/g," ").trim();return u.length>c?`${u.slice(0,c)}\u2026`:u};switch(r){case"Bash":return`$ ${o(s.command,120)}`;case"Read":return`Read ${o(s.file_path)}`;case"Edit":case"Write":case"NotebookEdit":return`${r} ${o(s.file_path)}`;case"Grep":return`Grep ${o(s.pattern)}`;case"Glob":return`Glob ${o(s.pattern)}`;case"Task":return`Task \u2192 ${o(s.subagent_type,40)}: ${o(s.description,80)}`;case"WebFetch":return`WebFetch ${o(s.url)}`;default:{let i=s.file_path??s.pattern??s.command??s.repo??s.query;return i!==void 0?`${r} ${o(i)}`:Object.keys(s).length?`${r}(${o(s,80)})`:r}}}function jn(e){let t=Xr(e);if(!t)return[];let n;try{n=Xt.readFileSync(t,"utf8")}catch{return[]}let r=[];for(let s of n.split(`
10
- `)){let o=s.trim();if(!o)continue;let i;try{i=JSON.parse(o)}catch{continue}let c=i,d=c.type,u=c.message?.content;if(typeof u=="string"){let m=u.trim();if(!m)continue;d==="user"?r.push({type:"prompt",text:m}):d==="assistant"&&r.push({type:"text",text:m});continue}if(Array.isArray(u))for(let m of u){if(!m||typeof m!="object")continue;let g=m;if(g.type==="text"&&typeof g.text=="string"&&g.text.trim()){let p=g.text.trim();d==="user"?r.push({type:"prompt",text:p}):d==="assistant"&&r.push({type:"text",text:p})}else g.type==="tool_use"&&r.push({type:"tool",text:Oi(g.name,g.input)})}}return r}Je();V();import Di from"node:fs";import ji from"node:os";import Zr from"node:path";import{randomUUID as es}from"node:crypto";var $i=process.env.SUPERCLAWD_HOME||Zr.join(ji.homedir(),".superclawd"),Mi=Zr.join($i,"config.json"),ts=process.env.SUPERCLAWD_MCP_API_URL||"https://mcp-api.superclawd.com",ns=process.env.PIPELINES_BACKEND==="mock"||process.env.SUPERCLAWD_BACKEND==="mock",en=3,$n="__logged_out__";function _(){return ns}var nt={loggedIn:!1,userId:$n,email:null};function ae(){return Mn()}function Mn(){let e=process.env.SUPERCLAWD_MCP_KEY,t=process.env.SUPERCLAWD_MCP_SECRET;if(e&&t)return{keyId:e,secret:t};try{let n=JSON.parse(Di.readFileSync(Mi,"utf8")),r=n?.credentials??n;if(typeof r?.keyId=="string"&&typeof r?.secret=="string")return{keyId:r.keyId,secret:r.secret}}catch{}return null}var Zt=[];function At(){return Zt}var Yr=new Map,Li=5*6e4;async function Nt(e){let t=Yr.get(e);if(t&&Date.now()-t.at<Li)return{agents:t.agents,teams:t.teams};let n=Mn();if(!n)return null;try{let r=await fetch(`${ts}/api/prompt/agents-teams`,{headers:{"content-type":"application/json","x-mcp-key-id":n.keyId,"x-mcp-secret":n.secret,"x-workspace-slug":e,"x-request-id":es()}});if(!r.ok)return null;let s=await r.json().catch(()=>null),o=s?.agents??[],i=s?.teams??[];return Yr.set(e,{agents:o,teams:i,at:Date.now()}),{agents:o,teams:i}}catch{return null}}function Gi(e){return e.map(t=>({id:t.slug,name:t.name,tier:t.tier==="paid"?"paid":"free"}))}function Vr(e){return e===401?"Your credentials are invalid or expired. Run `superclawd login`.":e===403?"This account isn't permitted to use Pipelines.":e===0||e>=500?"The SuperClawd backend is unreachable. Try again in a moment.":`Authentication failed (HTTP ${e}).`}function Vt(e){return qt($n),he.loggedIn=!1,delete he.account,j.length=0,Zt=[],nt={loggedIn:!1,userId:$n,email:null,error:e},nt}async function rs(){if(ns)return qt(xt),he.loggedIn=!0,Zt=[...j],nt={loggedIn:!0,userId:xt,email:he.account?.email??null},nt;let e=Mn();if(!e)return Vt("Not authenticated. Run `superclawd login` to get started.");let t=d=>new Promise(u=>setTimeout(u,d)),n=8,r=2e3,s=0,o=null,i=!1;for(let d=1;d<=n;d++){try{let u=await fetch(`${ts}/api/prompt/workspaces`,{headers:{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret,"x-request-id":es()}});if(s=u.status,o=await u.json().catch(()=>null),u.ok){i=!0;break}if(s<500)return Vt(Vr(s))}catch{s=0}d===1&&console.log("[pipelines] waiting for the SuperClawd backend to come up\u2026"),d<n&&await t(r)}if(!i)return Vt(Vr(s));let c=o?.userId;return c?(qt(c),he.loggedIn=!0,he.account={email:o?.email??"",org:"SuperClawd"},Zt=Gi(o?.workspaces??[]),j.length=0,nt={loggedIn:!0,userId:c,email:o?.email??null},nt):Vt("The backend didn't return an account id. Update the CLI/backend.")}V();import{execFile as Ui}from"node:child_process";import{existsSync as nn}from"node:fs";import{rm as Bi}from"node:fs/promises";import{homedir as qi}from"node:os";import{dirname as Fi,join as tn,resolve as ss}from"node:path";var Ln=tn(qi(),".superclawd","pipelines-worktrees");function Z(e,t){return new Promise(n=>{Ui("git",t,{cwd:e,maxBuffer:10*1024*1024},(r,s,o)=>{n({code:r&&typeof r.code=="number"?r.code:r?1:0,stdout:String(s??"").trim(),stderr:String(o??"").trim()})})})}async function os(e){if(!e||!nn(e))return!1;let t=await Z(e,["rev-parse","--is-inside-work-tree"]);return t.code===0&&t.stdout==="true"}async function De(e){if(!e||!nn(e))return[];if(await os(e))return[{name:".",path:ss(e)}];let{readdir:t}=await import("node:fs/promises"),n=await t(e,{withFileTypes:!0}).catch(()=>[]),r=[];for(let s of n){if(!s.isDirectory()||s.name.startsWith("."))continue;let o=tn(e,s.name);await os(o)&&r.push({name:s.name,path:ss(o)})}return r}async function is(e,t){let n=await De(e);if(!n.length)return null;let r=(t??"").trim();return!r||r==="."?n.length===1?n[0]:null:n.find(s=>s.name===r)??null}async function as(e){let t=await Z(e,["symbolic-ref","--short","refs/remotes/origin/HEAD"]);if(t.code===0&&t.stdout)return t.stdout.replace(/^origin\//,"");let n=await Z(e,["rev-parse","--abbrev-ref","HEAD"]);return n.code===0&&n.stdout&&n.stdout!=="HEAD"?n.stdout:"main"}async function Gn(e,t){await Z(e,["fetch","origin",t]);let n=`origin/${t}`;return(await Z(e,["rev-parse","--verify","--quiet",`refs/remotes/${n}`])).code===0?n:t}async function cs(e){if(nn(e.worktreePath)){let s=await Z(e.worktreePath,["rev-parse","--is-inside-work-tree"]);if(s.code===0&&s.stdout==="true")return{ok:!0,worktreePath:e.worktreePath}}let n=(await Z(e.repoPath,["rev-parse","--verify","--quiet",`refs/heads/${e.branch}`])).code===0?["worktree","add",e.worktreePath,e.branch]:["worktree","add","-b",e.branch,e.worktreePath,e.startPoint??e.base],r=await Z(e.repoPath,n);return r.code!==0?{ok:!1,error:r.stderr||r.stdout||"git worktree add failed"}:{ok:!0,worktreePath:e.worktreePath}}async function ds(e,t,n){let r=await Gn(e,n),s=await Z(e,["rev-list","--left-right","--count",`${r}...${t}`]);if(s.code!==0)return{behind:0,ahead:0};let[o,i]=s.stdout.split(/\s+/).map(c=>Number(c)||0);return{behind:o??0,ahead:i??0}}async function us(e,t){await Z(e,["branch","-D",t])}async function rn(e){let t=tn(Ln,e);if(!nn(t))return;let{readdir:n}=await import("node:fs/promises"),r=await n(t,{withFileTypes:!0}).catch(()=>[]);for(let s of r){if(!s.isDirectory())continue;let o=tn(t,s.name),i=await Z(o,["rev-parse","--path-format=absolute","--git-common-dir"]);if(i.code===0&&i.stdout){let c=Fi(i.stdout);await Z(c,["worktree","remove","--force",o])}}await Bi(t,{recursive:!0,force:!0}).catch(()=>{})}function Wi(e){let t=e.trim().replace(/\.git$/,""),n=/^git@([^:]+):(.+)$/.exec(t);return n?`https://${n[1]}/${n[2]}`:(n=/^ssh:\/\/git@([^/]+)\/(.+)$/.exec(t),n?`https://${n[1]}/${n[2]}`:/^https?:\/\//.test(t)?t:null)}async function ls(e,t,n){let r=await Z(e,["remote","get-url","origin"]);if(r.code!==0||!r.stdout)return null;let s=Wi(r.stdout);return s?`${s}/compare/${t}...${n}?expand=1`:null}import{spawn as Yi,spawnSync as Vi}from"node:child_process";import Bn from"node:fs";import qn from"node:os";import rt from"node:path";import{fileURLToPath as Zi}from"node:url";import{execFileSync as Ki}from"node:child_process";import{realpathSync as Qi}from"node:fs";function Hi(){if(process.platform!=="darwin")return!1;try{return Ki("which",["sandbox-exec"],{stdio:"ignore"}),!0}catch{return!1}}function Ji(e){try{return Qi(e)}catch{return e}}function zi(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Xi(e){let t=["(version 1)","(allow default)"];for(let n of e)t.push(`(deny file-write* (subpath "${zi(Ji(n))}"))`);return t.push('(allow file-write* (regex #"/\\.git/"))'),t.push('(allow file-write* (regex #"/\\.claude/"))'),t.join(`
11
- `)}function ps(e){let{cmd:t,args:n,repoPaths:r,enabled:s}=e;return!s||!r.length||!Hi()?{cmd:t,args:n,sandboxed:!1}:{cmd:"sandbox-exec",args:["-p",Xi(r),t,...n],sandboxed:!0}}function Et(e){if(!e||!e.trim())return process.cwd();let t=e.trim();return t==="~"?t=qn.homedir():(t.startsWith("~/")||t.startsWith("~\\"))&&(t=rt.join(qn.homedir(),t.slice(2))),rt.resolve(t)}function ea(){return`http://127.0.0.1:${Number(process.env.PIPELINES_PORT||process.env.PIPELINES_MOCK_PORT||63210)}`}function ta(){let e=process.env.SUPERCLAWD_BIN;if(e)return{cmd:e,baseArgs:[]};let t=rt.dirname(Zi(import.meta.url));for(let n=0;n<8;n++){let r=rt.join(t,"apps","cli","dist","index.js");if(Bn.existsSync(r))return{cmd:process.execPath,baseArgs:[r]};let s=rt.dirname(t);if(s===t)break;t=s}return{cmd:"superclawd",baseArgs:[]}}function Fn(e){let{cmd:t,baseArgs:n}=ta(),r=[...n,"-p",e.prompt,"--pipelines"];e.pipelinesTools&&r.push(`--pipelines-tools=${e.pipelinesToolsMode??"board"}`),e.workspace&&r.push("--workspace",e.workspace),e.model&&r.push("--model",e.model),e.effort&&r.push("--effort",e.effort),e.noCapture&&r.push("--no-capture"),e.resume?r.push("--resume",e.resume):e.sessionId&&r.push("--session-id",e.sessionId);let s={};e.pipelinesTools&&(s.SUPERCLAWD_PIPELINES_URL=ea(),e.ticketId&&(s.SUPERCLAWD_PIPELINES_TICKET=e.ticketId));let o=Et(e.workingDir);if(!Bn.existsSync(o))return{pid:0,pgid:0,done:Promise.resolve({code:1,stdout:"",stderr:`working directory does not exist: ${o}${e.workingDir&&e.workingDir!==o?` (from "${e.workingDir}")`:""}`})};let i=ps({cmd:t,args:r,repoPaths:e.sandboxRepos??[],enabled:!!e.sandbox});if(process.env.PIPELINES_DEBUG){let p=`[pipelines] spawn (cwd=${o}${i.sandboxed?", sandboxed":""}): ${i.cmd} ${i.args.join(" ")}`;console.log(p);try{Bn.appendFileSync(rt.join(qn.homedir(),".superclawd","pipelines-debug.log"),`${new Date().toISOString()} ${p}
12
- `)}catch{}}let c=Yi(i.cmd,i.args,{cwd:o,detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,...s}}),d="",u="";c.stdout?.on("data",p=>d+=String(p)),c.stderr?.on("data",p=>u+=String(p));let m=new Promise(p=>{c.on("error",w=>p({code:127,stdout:d,stderr:`${u}
13
- ${String(w)}`})),c.on("close",w=>p({code:w??137,stdout:d,stderr:u}))}),g=c.pid??0;return{pid:g,pgid:g,done:m}}function fs(e,t="SIGTERM"){if(e){if(process.platform==="win32"){try{Vi("taskkill",["/pid",String(e),"/T","/F"],{stdio:"ignore"})}catch{}return}try{process.kill(-e,t)}catch{try{process.kill(e,t)}catch{}}}}function Ue(e){return Fn(e).done}var na=["haiku","sonnet","opus","fable"],ra=["low","medium","high","xhigh","max"],ce="opus",de="high",ye=(e,t=ce)=>{let n=String(e??"").trim();return na.includes(n)?n:t},we=(e,t=de)=>{let n=String(e??"").trim();return ra.includes(n)?n:t};function sa(){let e=new Date;return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}function je(e,t,n){let r={id:`e${e.events.length+1}`,ts:sa(),kind:t,text:n};return e.events.push(r),r}V();import{randomUUID as gs}from"node:crypto";var oa=1e4,ms=3,ia=1e3,aa=new Set(["host","content-length","content-type","user-agent","x-superclawd-event","x-superclawd-signature","transfer-encoding","connection"]),ca=e=>new Promise(t=>setTimeout(t,e));function hs(e,t){let n={"content-type":"application/json","user-agent":"SuperClawd-Pipelines-Webhook/1","x-superclawd-event":e};l.webhookSecret&&(n["x-superclawd-signature"]=`sha256=${Or(l.webhookSecret,t)}`);for(let r of l.webhookHeaders??[])r.key&&!aa.has(r.key.toLowerCase())&&(n[r.key]=r.value);return n}async function ks(e,t,n){let r=new AbortController,s=setTimeout(()=>r.abort(),oa);try{return(await fetch(e,{method:"POST",headers:n,body:t,signal:r.signal})).status}catch{return 0}finally{clearTimeout(s)}}function ue(e,t,n={}){let r=l;if(!r.webhookEnabled||!r.webhookUrl||!r.webhookEvents||!r.webhookEvents.includes(e))return;let s=r.webhookUrl,o={id:`evt_${gs()}`,event:e,occurredAt:new Date().toISOString(),workspaceId:n.workspaceId,data:t},i=JSON.stringify(o),c=hs(e,i);(async()=>{for(let d=1;d<=ms;d++){let u=await ks(s,i,c);if(u>=200&&u<300)return;d<ms&&await ca(ia*d)}})().catch(()=>{})}async function ys(){let e=l.webhookUrl;if(!e)return{ok:!1,error:"no webhook URL configured"};let t={id:`evt_${gs()}`,event:"webhook.test",occurredAt:new Date().toISOString(),data:{message:"SuperClawd Pipelines test event"}},n=JSON.stringify(t),r=hs("webhook.test",n),s=await ks(e,n,r);return s>=200&&s<300?{ok:!0,status:s}:{ok:!1,...s?{status:s}:{error:"could not reach the webhook URL"}}}function se(e,t,n={}){return e.status=t,n.stopReason!==void 0&&(e.stopReason=n.stopReason===null?void 0:n.stopReason),n.clearBlocker&&(e.blocker=void 0),n.event&&je(e,n.event.kind,n.event.text),e.updatedAt=new Date().toISOString(),n.webhookEvent&&ue(n.webhookEvent,{runId:e.id,ticketId:e.ticketId,ticketKey:e.ticketKey,title:e.title,status:e.status,stopReason:e.stopReason},{workspaceId:e.workspaceId}),e}import{randomUUID as da}from"node:crypto";var ua=3,la=1,pa=10,st=new Map,ot=[];function fa(){let e=l.maxConcurrentRuns??ua;return Math.max(la,Math.min(pa,e))}function be(e,t=!1,n){st.has(e)||ot.some(r=>r.runId===e)||(ot.push({runId:e,resume:t,prompt:n}),ws())}function ws(){for(;st.size<fa()&&ot.length>0;){let e=ot.shift();ha(e.runId,e.resume,e.prompt)}}function ma(e,t,n){let r=e?`You are working on SuperClawd Pipelines ticket ${e.externalIdentifier} \u2014 "${e.title}" (ticket id: ${e.id}).`:`You are working on SuperClawd Pipelines run "${t.title}".`,o=!!e&&e.provider!=="local"?"- Start by calling read_ticket to read the full ticket (description, vendor comments, context, plan, open questions, conclusion, notes). On this run you can call it with no arguments \u2014 it defaults to this ticket. Read the vendor comments too \u2014 the real acceptance criteria and decisions often live in the discussion, not the description.":"- Start by calling read_ticket to read the full ticket (description, context, plan, open questions, conclusion, notes). On this run you can call it with no arguments \u2014 it defaults to this ticket.",i=[r,"","Use the SuperClawd Pipelines tools for this task:",o,"- Write your plan with set_plan (use the tool; do not create a plan file unless the ticket explicitly asks for one).","- If this task changes code: your working directory may be an umbrella folder containing several git repositories. Call list_repos to see them, research to decide which you need, then \u2014 BEFORE editing any repo \u2014 call start_repo_work({repo}) to get an isolated worktree. Make ALL changes for that repo inside the returned worktreePath and commit there; NEVER edit the repo in the working directory directly (other runs may be working on it at the same time). Claim each repo you touch. When done, push the branch and record the PR with add_pr_link (if you can't open a PR, push the branch and pass the compareUrl to add_pr_link so a human can).","- If you need something that isn't in the ticket, record it with add_open_question rather than guessing \u2014 and if it blocks progress, also call block_ticket with a reason.","- Keep durable findings or decisions on the ticket with add_note.","- When you've fully completed what the ticket asked, write a short wrap-up of what you did (and any results) with set_conclusion."];if(t.autonomy==="autonomous"&&i.push("","This run is AUTONOMOUS \u2014 no one is available to answer questions while it runs. Do NOT guess on any decision that materially changes the outcome. When you hit a genuine unknown, record it with add_open_question AND call block_ticket with a short reason, then stop \u2014 a human will resolve it and the ticket will be re-run. Only make assumptions for trivial, low-risk gaps, and state them clearly."),t.assignmentKind==="agent"&&t.agentName)i.push("",`DELEGATION \u2014 this ticket is assigned to the "${t.agentName}" agent. Use the Task tool to hand the ENTIRE ticket to the subagent for "${t.agentName}" (available in this session), let it complete the work, then report its result. Do NOT do the work yourself. If you cannot find that subagent, proceed yourself and add_note that the assigned agent was unavailable.`);else if(t.assignmentKind==="team"&&t.teamName){let u=t.teamLeadName;i.push("",u?`DELEGATION \u2014 this ticket is assigned to the "${t.teamName}" team. Use the Task tool to hand the ENTIRE ticket to the team's LEAD subagent, "${u}" (available in this session); it will coordinate its members. Do NOT do the work yourself. If you cannot find it, proceed yourself and add_note that the assigned team was unavailable.`:`DELEGATION \u2014 this ticket is assigned to the "${t.teamName}" team. Use the Task tool to hand the ENTIRE ticket to that team's lead-agent subagent, which coordinates its members. Do NOT do the work yourself. If you cannot find it, proceed yourself and add_note that the assigned team was unavailable.`)}i.push("","Then do the work the ticket asks for.");let c=i.join(`
8
+ Here\u2019s a first pass grouped by Added / Changed / Fixed. Want me to tighten the copy?`,ts:"08:05"}],starred:!1,createdAt:new Date(Date.now()-2*24*36e5).toISOString(),updatedAt:new Date(Date.now()-2*24*36e5).toISOString()}},ce=["conv_3","conv_2","conv_1"],O={sched_1:{id:"sched_1",name:"Triage new bugs",prompt:"Triage new Linear bugs: reproduce, label severity, and open a follow-up for anything urgent.",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"team",teamId:"team_core",teamName:"Core",cadence:"Every 2 hours",enabled:!0,starred:!0,createdAt:new Date(Date.now()-8*24*36e5).toISOString(),lastRunAt:new Date(Date.now()-40*6e4).toISOString(),nextRunAt:new Date(Date.now()+80*6e4).toISOString()},sched_2:{id:"sched_2",name:"Nightly flaky-test sweep",prompt:"Run the test suite, detect flakes, and file an issue per flaky test with the failing output.",workspaceId:"ws_front",workspaceName:"Frontend",assignmentKind:"anyone",cadence:"Every 1 day",enabled:!1,starred:!1,createdAt:new Date(Date.now()-20*24*36e5).toISOString(),lastRunAt:new Date(Date.now()-14*36e5).toISOString(),nextRunAt:null},sched_3:{id:"sched_3",name:"Reconcile credit ledger",prompt:"Reconcile the credit ledger against Stripe: flag drift over $1 and open a dispute task for anything unexplained.",workspaceId:"ws_core",workspaceName:"Core Platform",assignmentKind:"agent",agentId:"agent_orch",agentName:"Orchestrator",cadence:"Every 6 hours",enabled:!0,starred:!0,createdAt:new Date(Date.now()-5*24*36e5).toISOString(),lastRunAt:new Date(Date.now()-2*36e5).toISOString(),nextRunAt:new Date(Date.now()+4*36e5).toISOString()}},ne=["sched_1","sched_2","sched_3"],z={sched_1:Array.from({length:14},(e,t)=>({id:`srun_1_${14-t}`,scheduleId:"sched_1",status:t===0?"success":t%6===0?"failed":"success",sessionId:`a1b2c3${String(14-t).padStart(2,"0")}-6f27-4c95-90ab-1e7d32c8f0a5`,startedAt:new Date(Date.now()-(40+t*120)*6e4).toISOString(),finishedAt:new Date(Date.now()-(40+t*120)*6e4+95e3).toISOString(),output:t%6===0?"Failed: could not reach the Linear API (429). Will retry next tick.":`Triaged ${2+t%4} new issues \xB7 labeled severity \xB7 opened ${t%3===0?1:0} follow-up. (mocked output)`})),sched_2:Array.from({length:3},(e,t)=>({id:`srun_2_${3-t}`,scheduleId:"sched_2",status:"success",sessionId:`d4e5f6${String(3-t).padStart(2,"0")}-9c02-4b38-a7e1-5f0c2b83d419`,startedAt:new Date(Date.now()-(14+t*24)*36e5).toISOString(),finishedAt:new Date(Date.now()-(14+t*24)*36e5+22e4).toISOString(),output:`Ran the suite \xB7 ${t===0?"no":"1"} flaky test found${t===0?"":" \xB7 filed 1 issue"}. (mocked output)`})),sched_3:Array.from({length:7},(e,t)=>({id:`srun_3_${7-t}`,scheduleId:"sched_3",status:"success",sessionId:`c7d8e9${String(7-t).padStart(2,"0")}-4b38-4c95-90ab-1e7d32c8f0a5`,startedAt:new Date(Date.now()-(2+t*6)*36e5).toISOString(),finishedAt:new Date(Date.now()-(2+t*6)*36e5+18e4).toISOString(),output:`Reconciled ${180+t*12} charges \xB7 ${t%3===0?"no drift":"flagged 1 mismatch \xB7 opened dispute task"}. (mocked output)`}))},W={},K=[],B={runSeq:500,convSeq:3,schedSeq:3,schedRunSeq:100,batchSeq:0,localSeq:2},X=[],j=[],D=[],H=[],re=[{id:"jira_9002",connectionId:"conn_jira_demo",provider:"jira",externalIdentifier:"PLAT-2",project:"Platform",title:"Add rate-limit headers to the public API",status:"todo",statusRaw:"To Do",assignee:{name:"Priya"},priority:3,labels:[{name:"api"}],url:"https://demo.atlassian.net/browse/PLAT-2",workspaceId:"ws_core",description:"Surface X-RateLimit-* so clients can back off."},{id:"s_150",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-150",project:"Frontend App",title:"Debounce the workspace search input",status:"todo",statusRaw:"Todo",assignee:{name:"Priya"},priority:3,labels:[{name:"ui"}],url:"https://linear.app/acme/issue/ENG-150",workspaceId:"ws_front",description:"The search fires a request per keystroke; debounce ~300ms."},{id:"s_151",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-151",project:"CI",title:"Flaky test: auth.session.spec times out on CI",status:"todo",statusRaw:"Todo",assignee:{name:"Sam"},priority:1,labels:[{name:"bug"},{name:"ci"}],url:"https://linear.app/acme/issue/ENG-151",workspaceId:"ws_front",description:"Intermittent 30s timeout; suspect a missing await."},{id:"s_152",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-152",project:"Public API",title:"Add rate-limit headers to the public API",status:"backlog",statusRaw:"Backlog",priority:2,labels:[{name:"api"}],url:"https://linear.app/acme/issue/ENG-152",workspaceId:"ws_front",description:"Expose X-RateLimit-* on responses."},{id:"s_160",connectionId:"conn_acme",provider:"linear",externalIdentifier:"ENG-160",project:"Auth",title:"Login page: remember-me checkbox does nothing",status:"todo",statusRaw:"Todo",assignee:{name:"Andy"},priority:2,labels:[{name:"bug"}],url:"https://linear.app/acme/issue/ENG-160",workspaceId:"ws_front",description:"Session still expires on browser close."},{id:"s_210",connectionId:"conn_personal",provider:"linear",externalIdentifier:"CORE-210",project:"Directives",title:"Batch the memory-read endpoint",status:"backlog",statusRaw:"Backlog",priority:2,labels:[{name:"perf"}],url:"https://linear.app/personal/issue/CORE-210",workspaceId:"ws_core",description:"Coalesce N per-memory fetches into one batch call."},{id:"s_211",connectionId:"conn_personal",provider:"linear",externalIdentifier:"CORE-211",project:"Docs",title:"Document the directives cache TTL",status:"todo",statusRaw:"Todo",priority:4,labels:[{name:"docs"}],url:"https://linear.app/personal/issue/CORE-211",workspaceId:"ws_core"}]});var Jn={};ta(Jn,{seedFromFixtures:()=>na});async function na(){let e=E();await Je.bulkCreate(b.map(n=>({...n,userId:e}))),await xe.bulkCreate(h.map((n,r)=>({...n,userId:e,column:S[n.id]??"backlog",position:r}))),await Oe.bulkCreate(Object.values(x).map(n=>({...n,userId:e}))),await ze.bulkCreate(ne.map(n=>({...O[n],userId:e})));let t=Object.keys(z).flatMap(n=>{let r=z[n];return r.map((s,o)=>({...s,userId:e,seq:r.length-o}))});await De.bulkCreate(t),await je.bulkCreate(ce.map(n=>({...F[n],userId:e}))),await Me.bulkCreate(X.map(n=>({...n,userId:e}))),await Xe.bulkCreate(j.map(n=>({...n,userId:e}))),await Be.bulkCreate(D.map((n,r)=>({...n,userId:e,position:n.position??r}))),await $e.bulkCreate(H.map((n,r)=>({...n,userId:e,position:n.position??r}))),await ct.create({userId:e,defaultAutonomy:l.defaultAutonomy,maxConcurrentRuns:l.maxConcurrentRuns??3,branchPrefix:l.branchPrefix??"feature",connectedWorkspaces:l.connectedWorkspaces??null,workspaceDirs:l.workspaceDirs??null,defaultModel:l.defaultModel??null,defaultEffort:l.defaultEffort??null})}var zn=Qn(()=>{"use strict";Y();dt()});import ra from"node:os";import es from"node:path";import sa from"node:fs";import{Sequelize as oa,DataTypes as a}from"sequelize";import{Umzug as ia}from"umzug";function E(){return ts}function un(e){ts=e}async function Zr(e){try{return await e.count()}catch{return 0}}async function rs(){if(sa.mkdirSync(es.dirname(dn),{recursive:!0}),await k.authenticate(),await aa.up(),await Zr(xe)===0&&await Zr(je)===0&&E()===qt){let{seedFromFixtures:t}=await Promise.resolve().then(()=>(zn(),Jn));await t()}}var dn,qt,ts,k,Je,xe,Oe,ze,De,Ft,je,ct,ut,Me,Xe,$e,Be,ns,aa,dt=Qn(()=>{"use strict";dn=process.env.PIPELINES_DB_PATH??es.join(ra.homedir(),".superclawd","pipelines.db"),qt=process.env.PIPELINES_DEV_USER_ID??"dev-user",ts=qt;k=new oa({dialect:"sqlite",storage:dn,logging:!1}),Je=k.define("Connection",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,provider:a.STRING,providerAccountName:a.STRING,displayName:a.STRING,workspaceId:a.STRING,workspaceName:a.STRING,workingDir:a.STRING,linkStatus:a.STRING,linkLostReason:a.STRING,authStatus:a.STRING,lastSyncedAt:a.STRING,ticketCount:a.INTEGER,syncFilters:a.JSON,cloudId:a.STRING,providerAccountId:a.STRING},{tableName:"connections",underscored:!0,timestamps:!1}),xe=k.define("Ticket",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,connectionId:a.STRING,provider:a.STRING,externalIdentifier:a.STRING,title:a.STRING,description:a.TEXT,status:a.STRING,statusRaw:a.STRING,assignee:a.JSON,reporter:a.JSON,dueDate:a.STRING,priority:a.INTEGER,labels:a.JSON,project:a.STRING,parent:a.JSON,model:a.STRING,effort:a.STRING,blockedReason:a.TEXT,comments:a.JSON,additionalContext:a.TEXT,plan:a.TEXT,conclusion:a.TEXT,additionalContextUpdatedAt:a.STRING,planUpdatedAt:a.STRING,conclusionUpdatedAt:a.STRING,createdAt:a.STRING,updatedAt:a.STRING,prLinks:a.JSON,attempt:a.INTEGER,dependsOn:a.JSON,prMonitor:a.BOOLEAN,prMonitorCount:a.INTEGER,prMonitorLastAt:a.STRING,prMonitorNote:a.TEXT,url:a.STRING,workspaceId:a.STRING,workingDir:a.STRING,column:a.STRING,position:a.INTEGER},{tableName:"tickets",underscored:!0,timestamps:!1}),Oe=k.define("Run",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,ticketId:a.STRING,ticketKey:a.STRING,title:a.STRING,provider:a.STRING,workspaceId:a.STRING,workspaceName:a.STRING,assignmentKind:a.STRING,teamName:a.STRING,agentName:a.STRING,autonomy:a.STRING,status:a.STRING,stopReason:a.STRING,sessionId:a.STRING,branchName:a.STRING,prUrl:a.STRING,worktrees:a.JSON,blocker:a.JSON,plan:a.JSON,events:a.JSON,resultText:a.TEXT,pid:a.INTEGER,pgid:a.INTEGER,createdAt:a.STRING,updatedAt:a.STRING},{tableName:"runs",underscored:!0,timestamps:!1}),ze=k.define("Schedule",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,name:a.STRING,prompt:a.TEXT,workspaceId:a.STRING,workspaceName:a.STRING,assignmentKind:a.STRING,teamId:a.STRING,teamName:a.STRING,agentId:a.STRING,agentName:a.STRING,cadence:a.STRING,workingDir:a.STRING,model:a.STRING,effort:a.STRING,enabled:a.BOOLEAN,starred:a.BOOLEAN,createdAt:a.STRING,lastRunAt:a.STRING,nextRunAt:a.STRING},{tableName:"schedules",underscored:!0,timestamps:!1}),De=k.define("ScheduleRun",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,scheduleId:a.STRING,status:a.STRING,sessionId:a.STRING,startedAt:a.STRING,finishedAt:a.STRING,output:a.TEXT,model:a.STRING,effort:a.STRING,seq:a.INTEGER},{tableName:"schedule_runs",underscored:!0,timestamps:!1}),Ft=k.define("Batch",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,name:a.STRING,workspaceId:a.STRING,workspaceName:a.STRING,ticketIds:a.JSON,mode:a.STRING,advanceMode:a.STRING,stackDependentWork:a.BOOLEAN,status:a.STRING,budgetCap:a.INTEGER,pausedReason:a.TEXT,runsStarted:a.INTEGER,createdAt:a.STRING,updatedAt:a.STRING},{tableName:"batches",underscored:!0,timestamps:!1}),je=k.define("Conversation",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,title:a.STRING,workspaceId:a.STRING,workspaceName:a.STRING,tier:a.STRING,effort:a.STRING,sessionId:a.STRING,workingDir:a.STRING,messages:a.JSON,starred:a.BOOLEAN,createdAt:a.STRING,updatedAt:a.STRING},{tableName:"conversations",underscored:!0,timestamps:!1}),ct=k.define("Setting",{userId:{type:a.STRING,primaryKey:!0},defaultAutonomy:a.STRING,maxConcurrentRuns:a.INTEGER,branchPrefix:a.STRING,connectedWorkspaces:a.JSON,workspaceDirs:a.JSON,defaultModel:a.STRING,defaultEffort:a.STRING,prMonitorDefault:a.BOOLEAN,prMonitorIntervalMinutes:a.INTEGER,prMonitorMaxEngagements:a.INTEGER,prMonitorReplyToComments:a.BOOLEAN,sandboxWorktreeEdits:a.BOOLEAN,publicApiEnabled:a.BOOLEAN,apiKeyHash:a.STRING,apiKeyLast4:a.STRING,apiKeyCreatedAt:a.STRING,webhookEnabled:a.BOOLEAN,webhookUrl:a.STRING,webhookHeaders:a.JSON,webhookEvents:a.JSON,webhookSecret:a.TEXT},{tableName:"settings",underscored:!0,timestamps:!1}),ut=k.define("OAuthToken",{connectionId:{type:a.STRING,primaryKey:!0},userId:a.STRING,provider:a.STRING,accessToken:a.TEXT,refreshToken:a.TEXT,scope:a.STRING,expiresAt:a.STRING},{tableName:"oauth_tokens",underscored:!0,timestamps:!1}),Me=k.define("RunResult",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,ticketId:a.STRING,runId:a.STRING,sessionId:a.STRING,prompt:a.TEXT,response:a.TEXT,status:a.STRING,model:a.STRING,effort:a.STRING,createdAt:a.STRING},{tableName:"run_results",underscored:!0,timestamps:!1}),Xe=k.define("Note",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,ticketId:a.STRING,scheduleId:a.STRING,author:a.STRING,body:a.TEXT,createdAt:a.STRING,updatedAt:a.STRING},{tableName:"notes",underscored:!0,timestamps:!1}),$e=k.define("MessagePreset",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,title:a.STRING,prompt:a.TEXT,enabled:a.BOOLEAN,position:a.INTEGER,createdAt:a.STRING,updatedAt:a.STRING},{tableName:"message_presets",underscored:!0,timestamps:!1}),Be=k.define("OpenQuestion",{id:{type:a.STRING,primaryKey:!0},userId:a.STRING,ticketId:a.STRING,question:a.TEXT,answer:a.TEXT,resolved:a.BOOLEAN,position:a.INTEGER,createdAt:a.STRING,updatedAt:a.STRING},{tableName:"open_questions",underscored:!0,timestamps:!1}),ns={Connection:Je,Ticket:xe,Run:Oe,Schedule:ze,ScheduleRun:De,Batch:Ft,Conversation:je,Setting:ct,OAuthToken:ut,RunResult:Me,Note:Xe,MessagePreset:$e,OpenQuestion:Be},aa=new ia({context:k.getQueryInterface(),storage:{async logMigration({name:e}){await k.query("INSERT INTO pipelines_migrations (name) VALUES (:name)",{replacements:{name:e}})},async unlogMigration({name:e}){await k.query("DELETE FROM pipelines_migrations WHERE name = :name",{replacements:{name:e}})},async executed(){await k.query("CREATE TABLE IF NOT EXISTS pipelines_migrations (name TEXT PRIMARY KEY)");let[e]=await k.query("SELECT name FROM pipelines_migrations ORDER BY name");return e.map(t=>t.name)}},logger:void 0,migrations:[{name:"0001-init",async up(){await k.sync()}},{name:"0002-oauth-tokens",async up(){await ut.sync()}},{name:"0003-settings-branch-prefix",async up(){let e=k.getQueryInterface();(await e.describeTable("settings")).branch_prefix||await e.addColumn("settings","branch_prefix",{type:a.STRING,allowNull:!0})}},{name:"0004-settings-connected-workspaces",async up(){let e=k.getQueryInterface();(await e.describeTable("settings")).connected_workspaces||await e.addColumn("settings","connected_workspaces",{type:a.JSON,allowNull:!0})}},{name:"0005-runs-result-text",async up(){let e=k.getQueryInterface();(await e.describeTable("runs")).result_text||await e.addColumn("runs","result_text",{type:a.TEXT,allowNull:!0})}},{name:"0006-run-results",async up(){let e=k.getQueryInterface();(await e.showAllTables()).map(String).includes("run_results")||await e.createTable("run_results",{id:{type:a.STRING,primaryKey:!0},user_id:a.STRING,ticket_id:a.STRING,run_id:a.STRING,session_id:a.STRING,prompt:a.TEXT,response:a.TEXT,status:a.STRING,created_at:a.STRING})}},{name:"0007-comments",async up(){let e=k.getQueryInterface();(await e.showAllTables()).map(String).includes("comments")||await e.createTable("comments",{id:{type:a.STRING,primaryKey:!0},user_id:a.STRING,ticket_id:a.STRING,author:a.STRING,body:a.TEXT,created_at:a.STRING})}},{name:"0008-comments-updated-at",async up(){let e=k.getQueryInterface();(await e.describeTable("comments")).updated_at||await e.addColumn("comments","updated_at",{type:a.STRING,allowNull:!0})}},{name:"0009-conversations-working-dir",async up(){let e=k.getQueryInterface();(await e.describeTable("conversations")).working_dir||await e.addColumn("conversations","working_dir",{type:a.STRING,allowNull:!0})}},{name:"0010-settings-workspace-dirs",async up(){let e=k.getQueryInterface();(await e.describeTable("settings")).workspace_dirs||await e.addColumn("settings","workspace_dirs",{type:a.JSON,allowNull:!0})}},{name:"0011-tickets-working-dir",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).working_dir||await e.addColumn("tickets","working_dir",{type:a.STRING,allowNull:!0})}},{name:"0012-schedules-working-dir",async up(){let e=k.getQueryInterface();(await e.describeTable("schedules")).working_dir||await e.addColumn("schedules","working_dir",{type:a.STRING,allowNull:!0})}},{name:"0013-rename-comments-to-notes",async up(){let e=k.getQueryInterface(),t=(await e.showAllTables()).map(String);t.includes("comments")&&!t.includes("notes")&&await e.renameTable("comments","notes")}},{name:"0014-notes-schedule-id",async up(){let e=k.getQueryInterface();(await e.describeTable("notes")).schedule_id||await e.addColumn("notes","schedule_id",{type:a.STRING,allowNull:!0})}},{name:"0015-connections-sync-filters",async up(){let e=k.getQueryInterface();(await e.describeTable("connections")).sync_filters||await e.addColumn("connections","sync_filters",{type:a.JSON,allowNull:!0})}},{name:"0016-tickets-parent",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).parent||await e.addColumn("tickets","parent",{type:a.JSON,allowNull:!0})}},{name:"0017-conversations-effort",async up(){let e=k.getQueryInterface();(await e.describeTable("conversations")).effort||await e.addColumn("conversations","effort",{type:a.STRING,allowNull:!0})}},{name:"0018-model-effort",async up(){let e=k.getQueryInterface(),t={type:a.STRING,allowNull:!0},n=async(r,s)=>{(await e.describeTable(r))[s]||await e.addColumn(r,s,t)};await n("settings","default_model"),await n("settings","default_effort");for(let r of["tickets","schedules","run_results","schedule_runs"])await n(r,"model"),await n(r,"effort")}},{name:"0019-tickets-blocked-reason",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).blocked_reason||await e.addColumn("tickets","blocked_reason",{type:a.TEXT,allowNull:!0})}},{name:"0020-message-presets",async up(){let e=k.getQueryInterface();(await e.showAllTables()).map(String).includes("message_presets")||await e.createTable("message_presets",{id:{type:a.STRING,primaryKey:!0},user_id:a.STRING,title:a.STRING,prompt:a.TEXT,enabled:a.BOOLEAN,position:a.INTEGER,created_at:a.STRING,updated_at:a.STRING})}},{name:"0021-ticket-context-fields",async up(){let e=k.getQueryInterface(),t=await e.describeTable("tickets"),n={type:a.TEXT,allowNull:!0};t.additional_context||await e.addColumn("tickets","additional_context",n),!t.tech_plan&&!t.plan&&await e.addColumn("tickets","tech_plan",n),t.conclusion||await e.addColumn("tickets","conclusion",n)}},{name:"0022-open-questions",async up(){let e=k.getQueryInterface();(await e.showAllTables()).map(String).includes("open_questions")||await e.createTable("open_questions",{id:{type:a.STRING,primaryKey:!0},user_id:a.STRING,ticket_id:a.STRING,question:a.TEXT,answer:a.TEXT,resolved:a.BOOLEAN,position:a.INTEGER,created_at:a.STRING,updated_at:a.STRING})}},{name:"0023-rename-tech-plan-to-plan",async up(){let e=k.getQueryInterface(),t=await e.describeTable("tickets");t.tech_plan&&!t.plan&&await e.renameColumn("tickets","tech_plan","plan")}},{name:"0024-ticket-context-timestamps",async up(){let e=k.getQueryInterface(),t=await e.describeTable("tickets"),n={type:a.STRING,allowNull:!0};t.additional_context_updated_at||await e.addColumn("tickets","additional_context_updated_at",n),t.plan_updated_at||await e.addColumn("tickets","plan_updated_at",n),t.conclusion_updated_at||await e.addColumn("tickets","conclusion_updated_at",n)}},{name:"0025-ticket-created-updated",async up(){let e=k.getQueryInterface(),t=await e.describeTable("tickets"),n={type:a.STRING,allowNull:!0};t.created_at||await e.addColumn("tickets","created_at",n),t.updated_at||await e.addColumn("tickets","updated_at",n)}},{name:"0026-ticket-pr-links",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).pr_links||await e.addColumn("tickets","pr_links",{type:a.JSON,allowNull:!0})}},{name:"0027-run-worktrees",async up(){let e=k.getQueryInterface();(await e.describeTable("runs")).worktrees||await e.addColumn("runs","worktrees",{type:a.JSON,allowNull:!0})}},{name:"0028-ticket-attempt",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).attempt||await e.addColumn("tickets","attempt",{type:a.INTEGER,allowNull:!0})}},{name:"0029-pr-monitor",async up(){let e=k.getQueryInterface(),t={type:a.INTEGER,allowNull:!0},n={type:a.BOOLEAN,allowNull:!0},r={type:a.STRING,allowNull:!0},s={type:a.TEXT,allowNull:!0},o=await e.describeTable("settings");o.pr_monitor_default||await e.addColumn("settings","pr_monitor_default",n),o.pr_monitor_interval_minutes||await e.addColumn("settings","pr_monitor_interval_minutes",t),o.pr_monitor_max_engagements||await e.addColumn("settings","pr_monitor_max_engagements",t),o.pr_monitor_reply_to_comments||await e.addColumn("settings","pr_monitor_reply_to_comments",n);let i=await e.describeTable("tickets");i.pr_monitor||await e.addColumn("tickets","pr_monitor",n),i.pr_monitor_count||await e.addColumn("tickets","pr_monitor_count",t),i.pr_monitor_last_at||await e.addColumn("tickets","pr_monitor_last_at",r),i.pr_monitor_note||await e.addColumn("tickets","pr_monitor_note",s)}},{name:"0030-ticket-depends-on",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).depends_on||await e.addColumn("tickets","depends_on",{type:a.JSON,allowNull:!0})}},{name:"0031-settings-sandbox",async up(){let e=k.getQueryInterface();(await e.describeTable("settings")).sandbox_worktree_edits||await e.addColumn("settings","sandbox_worktree_edits",{type:a.BOOLEAN,allowNull:!0})}},{name:"0032-connection-cloud-id",async up(){let e=k.getQueryInterface();(await e.describeTable("connections")).cloud_id||await e.addColumn("connections","cloud_id",{type:a.STRING,allowNull:!0})}},{name:"0033-ticket-reporter-due-date",async up(){let e=k.getQueryInterface(),t=await e.describeTable("tickets");t.reporter||await e.addColumn("tickets","reporter",{type:a.JSON,allowNull:!0}),t.due_date||await e.addColumn("tickets","due_date",{type:a.STRING,allowNull:!0})}},{name:"0034-connection-provider-account-id",async up(){let e=k.getQueryInterface();(await e.describeTable("connections")).provider_account_id||await e.addColumn("connections","provider_account_id",{type:a.STRING,allowNull:!0})}},{name:"0035-settings-public-api",async up(){let e=k.getQueryInterface(),t=await e.describeTable("settings"),n=async(r,s)=>{t[r]||await e.addColumn("settings",r,{type:s,allowNull:!0})};await n("public_api_enabled",a.BOOLEAN),await n("api_key_hash",a.STRING),await n("api_key_last4",a.STRING),await n("api_key_created_at",a.STRING),await n("webhook_enabled",a.BOOLEAN),await n("webhook_url",a.STRING),await n("webhook_headers",a.JSON),await n("webhook_events",a.JSON),await n("webhook_secret",a.TEXT)}},{name:"0036-ticket-comments",async up(){let e=k.getQueryInterface();(await e.describeTable("tickets")).comments||await e.addColumn("tickets","comments",{type:a.JSON,allowNull:!0})}},{name:"0037-batches",async up(){let e=k.getQueryInterface();(await e.showAllTables()).map(String).includes("batches")||await e.createTable("batches",{id:{type:a.STRING,primaryKey:!0},user_id:a.STRING,name:a.STRING,workspace_id:a.STRING,workspace_name:a.STRING,ticket_ids:a.JSON,mode:a.STRING,advance_mode:a.STRING,stack_dependent_work:a.BOOLEAN,status:a.STRING,budget_cap:a.INTEGER,paused_reason:a.TEXT,runs_started:a.INTEGER,created_at:a.STRING,updated_at:a.STRING})}}]})});Y();dt();import Wn from"express";import Od from"cors";import{randomUUID as ot}from"node:crypto";import ee from"node:path";import Ee from"node:fs";import Fn from"node:os";import{fileURLToPath as Dd}from"node:url";Y();import Le from"node:crypto";import Xn from"node:fs";import ca from"node:os";import Zn from"node:path";var Vn="enc:v1:",da=process.env.SUPERCLAWD_HOME||Zn.join(ca.homedir(),".superclawd"),Yn=process.env.PIPELINES_KEY_FILE||Zn.join(da,"pipelines.key"),Wt=null;function ss(){if(Wt)return Wt;Xn.mkdirSync(Zn.dirname(Yn),{recursive:!0});try{let t=Xn.readFileSync(Yn);if(t.length===32)return Wt=t,Wt}catch{}let e=Le.randomBytes(32);return Xn.writeFileSync(Yn,e,{mode:384}),Wt=e,e}function lt(e){let t=Le.randomBytes(12),n=Le.createCipheriv("aes-256-gcm",ss(),t),r=Buffer.concat([n.update(e,"utf8"),n.final()]),s=n.getAuthTag();return`${Vn}${t.toString("base64")}:${s.toString("base64")}:${r.toString("base64")}`}function pt(e){if(!e.startsWith(Vn))return e;let[t,n,r]=e.slice(Vn.length).split(":"),s=Le.createDecipheriv("aes-256-gcm",ss(),Buffer.from(t,"base64"));return s.setAuthTag(Buffer.from(n,"base64")),Buffer.concat([s.update(Buffer.from(r,"base64")),s.final()]).toString("utf8")}function ft(e){return Le.createHash("sha256").update(e,"utf8").digest("hex")}function mt(e="",t=32){return e+Le.randomBytes(t).toString("base64url")}function Kt(e,t){let n=Buffer.from(e),r=Buffer.from(t);return n.length!==r.length?!1:Le.timingSafeEqual(n,r)}function os(e,t){return Le.createHmac("sha256",e).update(t,"utf8").digest("hex")}dt();function ua(e){let t={};for(let[n,r]of Object.entries(e))r!=null&&(t[n]=r);return t}var V=e=>e.get({plain:!0}),oe=(e,t)=>{let n={...e};for(let r of t)delete n[r];return ua(n)};function is(e){let t={};for(let[n,r]of Object.entries(e))t[n]=r===void 0?null:r;return t}function gt(e,t){let n=0;for(let r of e){let s=new RegExp(`^${t}_?(\\d+)$`).exec(r);s&&(n=Math.max(n,Number(s[1])))}return n}async function as(){let e={where:{userId:E()}},t=await Je.findAll(e);b.length=0,b.push(...t.map(p=>oe(V(p),["userId"])));let n=await xe.findAll({...e,order:[["position","ASC"]]});h.length=0;for(let p of Object.keys(S))delete S[p];for(let p of n){let w=V(p);S[w.id]=w.column??"backlog",h.push(oe(w,["userId","column","position"]))}let r=await Oe.findAll(e);for(let p of Object.keys(x))delete x[p];for(let p of Object.keys(T))delete T[p];for(let p of r){let w=oe(V(p),["userId","pid","pgid"]);x[w.id]=w,T[w.ticketId]=w.id}let s=await ze.findAll({...e,order:[["createdAt","ASC"]]});for(let p of Object.keys(O))delete O[p];ne.length=0;for(let p of s){let w=oe(V(p),["userId"]);O[w.id]=w,ne.push(w.id)}let o=await De.findAll({...e,order:[["seq","DESC"]]});for(let p of Object.keys(z))delete z[p];for(let p of ne)z[p]=[];for(let p of o){let w=V(p),te=oe(w,["userId","seq"]);(z[w.scheduleId]??=[]).push(te)}let i=await Ft.findAll({...e,order:[["createdAt","ASC"]]});for(let p of Object.keys(W))delete W[p];K.length=0;for(let p of i){let w=oe(V(p),["userId"]);W[w.id]=w,K.push(w.id)}let c=await je.findAll({...e,order:[["updatedAt","DESC"]]});for(let p of Object.keys(F))delete F[p];ce.length=0;for(let p of c){let w=oe(V(p),["userId"]);w.messages||(w.messages=[]),F[w.id]=w,ce.push(w.id)}let d=await Me.findAll({...e,order:[["createdAt","DESC"]]});X.length=0;for(let p of d)X.push(oe(V(p),["userId"]));let u=await Xe.findAll({...e,order:[["createdAt","ASC"]]});j.length=0;for(let p of u)j.push(oe(V(p),["userId"]));let m=await $e.findAll({...e,order:[["position","ASC"]]});H.length=0;for(let p of m)H.push(oe(V(p),["userId"]));let g=await Be.findAll({...e,order:[["position","ASC"]]});D.length=0;for(let p of g)D.push(oe(V(p),["userId"]));let I=await ct.findByPk(E());if(I){let p=V(I);l.defaultAutonomy=p.defaultAutonomy??l.defaultAutonomy,typeof p.maxConcurrentRuns=="number"&&(l.maxConcurrentRuns=p.maxConcurrentRuns),typeof p.branchPrefix=="string"&&(l.branchPrefix=p.branchPrefix),Array.isArray(p.connectedWorkspaces)&&(l.connectedWorkspaces=p.connectedWorkspaces),p.workspaceDirs&&typeof p.workspaceDirs=="object"&&(l.workspaceDirs=p.workspaceDirs),typeof p.defaultModel=="string"&&(l.defaultModel=p.defaultModel),typeof p.defaultEffort=="string"&&(l.defaultEffort=p.defaultEffort),typeof p.prMonitorDefault=="boolean"&&(l.prMonitorDefault=p.prMonitorDefault),typeof p.prMonitorIntervalMinutes=="number"&&(l.prMonitorIntervalMinutes=p.prMonitorIntervalMinutes),typeof p.prMonitorMaxEngagements=="number"&&(l.prMonitorMaxEngagements=p.prMonitorMaxEngagements),typeof p.prMonitorReplyToComments=="boolean"&&(l.prMonitorReplyToComments=p.prMonitorReplyToComments),typeof p.sandboxWorktreeEdits=="boolean"&&(l.sandboxWorktreeEdits=p.sandboxWorktreeEdits),typeof p.publicApiEnabled=="boolean"&&(l.publicApiEnabled=p.publicApiEnabled),typeof p.apiKeyHash=="string"&&(l.apiKeyHash=p.apiKeyHash),typeof p.apiKeyLast4=="string"&&(l.apiKeyLast4=p.apiKeyLast4),typeof p.apiKeyCreatedAt=="string"&&(l.apiKeyCreatedAt=p.apiKeyCreatedAt),typeof p.webhookEnabled=="boolean"&&(l.webhookEnabled=p.webhookEnabled),typeof p.webhookUrl=="string"&&(l.webhookUrl=p.webhookUrl),Array.isArray(p.webhookHeaders)&&(l.webhookHeaders=p.webhookHeaders.map(w=>({key:w.key,value:pt(String(w.value??""))}))),Array.isArray(p.webhookEvents)&&(l.webhookEvents=p.webhookEvents),typeof p.webhookSecret=="string"&&(l.webhookSecret=pt(p.webhookSecret))}B.convSeq=gt(Object.keys(F),"conv"),B.schedSeq=gt(Object.keys(O),"sched"),B.batchSeq=gt(Object.keys(W),"batch"),B.localSeq=Math.max(B.localSeq,gt(h.map(p=>p.id),"t_local")),B.schedRunSeq=gt(o.map(p=>V(p).id),"srun"),B.runSeq=gt(Object.keys(x),"run")}async function A(e){await Je.upsert({...e,userId:E()})}async function cs(e){await Je.destroy({where:{id:e}})}async function ln(){for(let e of $){let t=`conn_local_${e.id}`;if(b.some(r=>r.provider==="local"&&r.workspaceId===e.id))continue;let n={id:t,provider:"local",providerAccountName:"Local",workspaceId:e.id,workspaceName:e.name,workingDir:null,linkStatus:"linked",authStatus:"connected",lastSyncedAt:null,ticketCount:0};b.push(n),await A(n)}}async function N(e){let t=h.find(n=>n.id===e);t&&await xe.upsert(is({...t,userId:E(),column:S[e]??"backlog",position:h.indexOf(t)}))}async function ds(){await Promise.all(h.map((e,t)=>xe.update({position:t,column:S[e.id]??"backlog"},{where:{id:e.id}})))}async function pn(e){await xe.destroy({where:{id:e}}),await Oe.destroy({where:{ticketId:e}})}async function L(e){let t=x[e];t&&await Oe.upsert({...t,userId:E()})}async function us(e){await Oe.destroy({where:{id:e}})}async function Ht(e){let t=O[e];t&&await ze.upsert({...t,userId:E()})}async function ls(e){await ze.destroy({where:{id:e}}),await De.destroy({where:{scheduleId:e}})}async function pe(e){let t=W[e];t&&await Ft.upsert({...t,userId:E()})}async function Qt(e){await Ft.destroy({where:{id:e}})}async function fn(e,t){await De.upsert({...e,userId:E(),seq:t})}async function Ye(e){let t=F[e];t&&await je.upsert({...t,userId:E()})}async function ps(e){await je.destroy({where:{id:e}})}async function mn(e){await Me.upsert({...e,userId:E()})}async function fs(e){await Me.destroy({where:{ticketId:e,userId:E()}})}async function ms(e,t,n){let{count:r,rows:s}=await Me.findAndCountAll({where:{ticketId:e,userId:E()},order:[["createdAt","DESC"]],limit:t,offset:n});return{entries:s.map(o=>oe(V(o),["userId"])),total:r}}async function gs(e,t,n){let{count:r,rows:s}=await De.findAndCountAll({where:{scheduleId:e,userId:E()},order:[["seq","DESC"]],limit:t,offset:n});return{runs:s.map(o=>oe(V(o),["userId","seq"])),total:r}}async function ht(e){await Xe.upsert({...e,userId:E()})}async function gn(e){await Xe.destroy({where:{id:e}})}async function hn(e){let t=H.find(n=>n.id===e);t&&await $e.upsert({...t,userId:E()})}async function hs(e){await $e.destroy({where:{id:e}})}async function ks(){await Promise.all(H.map((e,t)=>$e.update({position:t},{where:{id:e.id}})))}async function er(e){let t=D.find(n=>n.id===e);t&&await Be.upsert(is({...t,userId:E()}))}async function kn(e){await Be.destroy({where:{id:e}})}async function ys(){await Promise.all(D.map((e,t)=>Be.update({position:t},{where:{id:e.id}})))}async function se(){await ct.upsert({userId:E(),defaultAutonomy:l.defaultAutonomy,maxConcurrentRuns:l.maxConcurrentRuns??3,branchPrefix:l.branchPrefix??"feature",connectedWorkspaces:l.connectedWorkspaces??null,workspaceDirs:l.workspaceDirs??null,defaultModel:l.defaultModel??null,defaultEffort:l.defaultEffort??null,prMonitorDefault:l.prMonitorDefault??null,prMonitorIntervalMinutes:l.prMonitorIntervalMinutes??null,prMonitorMaxEngagements:l.prMonitorMaxEngagements??null,prMonitorReplyToComments:l.prMonitorReplyToComments??null,sandboxWorktreeEdits:l.sandboxWorktreeEdits??null,publicApiEnabled:l.publicApiEnabled??null,apiKeyHash:l.apiKeyHash??null,apiKeyLast4:l.apiKeyLast4??null,apiKeyCreatedAt:l.apiKeyCreatedAt??null,webhookEnabled:l.webhookEnabled??null,webhookUrl:l.webhookUrl??null,webhookHeaders:l.webhookHeaders?l.webhookHeaders.map(e=>({key:e.key,value:lt(e.value)})):null,webhookEvents:l.webhookEvents??null,webhookSecret:l.webhookSecret?lt(l.webhookSecret):null})}async function ws(){let e={where:{userId:E()}};await Promise.all(Object.values(ns).map(t=>t.destroy(e)))}async function bs(){await ws();let{seedFromFixtures:e}=await Promise.resolve().then(()=>(zn(),Jn));await e()}async function Ss(){let e=new Set($.map(o=>o.id)),t=[],n=new Set;for(let o of b)o.provider!=="local"||!o.workspaceId||!e.has(o.workspaceId)||n.has(o.workspaceId)||(n.add(o.workspaceId),t.push(o));let r=o=>{o.length=0},s=o=>{for(let i of Object.keys(o))delete o[i]};r(b),b.push(...t),r(h),r(re),r(X),r(j),r(D),r(ne),r(K),r(ce),s(x),s(T),s(S),s(O),s(z),s(W),s(F),await ws();for(let o of t)await A(o);await ln(),await se();for(let o of H)await hn(o.id)}import yn from"node:fs";import la from"node:os";import tr from"node:path";function pa(){let e=process.env.CLAUDE_CONFIG_DIR||tr.join(la.homedir(),".claude");return tr.join(e,"projects")}function Is(e){let t=pa(),n;try{n=yn.readdirSync(t)}catch{return null}let r=`${e}.jsonl`;for(let s of n){let o=tr.join(t,s,r);if(yn.existsSync(o))return o}return null}function fa(e){return Array.isArray(e)?e.filter(t=>!!t&&typeof t=="object"&&t.type==="text"&&typeof t.text=="string").map(t=>t.text).join("").trim():typeof e=="string"?e.trim():""}function wn(e){return nr(e).response}function nr(e){let t=Is(e);if(!t)return{prompt:null,response:null};let n;try{n=yn.readFileSync(t,"utf8")}catch{return{prompt:null,response:null}}let r=null,s=null;for(let o of n.split(`
9
+ `)){let i=o.trim();if(!i)continue;let c;try{c=JSON.parse(i)}catch{continue}let d=c,u=fa(d.message?.content);u&&(d.type==="user"&&r===null&&(r=u),d.type==="assistant"&&(s=u))}return{prompt:r,response:s}}function ma(e,t){let n=typeof e=="string"?e:"tool",r=n.includes("__")?n.slice(n.lastIndexOf("__")+2):n,s=t??{},o=(i,c=80)=>{let u=(typeof i=="string"?i:i==null?"":JSON.stringify(i)).replace(/\s+/g," ").trim();return u.length>c?`${u.slice(0,c)}\u2026`:u};switch(r){case"Bash":return`$ ${o(s.command,120)}`;case"Read":return`Read ${o(s.file_path)}`;case"Edit":case"Write":case"NotebookEdit":return`${r} ${o(s.file_path)}`;case"Grep":return`Grep ${o(s.pattern)}`;case"Glob":return`Glob ${o(s.pattern)}`;case"Task":return`Task \u2192 ${o(s.subagent_type,40)}: ${o(s.description,80)}`;case"WebFetch":return`WebFetch ${o(s.url)}`;default:{let i=s.file_path??s.pattern??s.command??s.repo??s.query;return i!==void 0?`${r} ${o(i)}`:Object.keys(s).length?`${r}(${o(s,80)})`:r}}}function rr(e){let t=Is(e);if(!t)return[];let n;try{n=yn.readFileSync(t,"utf8")}catch{return[]}let r=[];for(let s of n.split(`
10
+ `)){let o=s.trim();if(!o)continue;let i;try{i=JSON.parse(o)}catch{continue}let c=i,d=c.type,u=c.message?.content;if(typeof u=="string"){let m=u.trim();if(!m)continue;d==="user"?r.push({type:"prompt",text:m}):d==="assistant"&&r.push({type:"text",text:m});continue}if(Array.isArray(u))for(let m of u){if(!m||typeof m!="object")continue;let g=m;if(g.type==="text"&&typeof g.text=="string"&&g.text.trim()){let I=g.text.trim();d==="user"?r.push({type:"prompt",text:I}):d==="assistant"&&r.push({type:"text",text:I})}else g.type==="tool_use"&&r.push({type:"tool",text:ma(g.name,g.input)})}}return r}dt();Y();import ga from"node:fs";import ha from"node:os";import Rs from"node:path";import{randomUUID as Ts}from"node:crypto";var ka=process.env.SUPERCLAWD_HOME||Rs.join(ha.homedir(),".superclawd"),ya=Rs.join(ka,"config.json"),_s=process.env.SUPERCLAWD_MCP_API_URL||"https://mcp-api.superclawd.com",As=process.env.PIPELINES_BACKEND==="mock"||process.env.SUPERCLAWD_BACKEND==="mock",In=3,sr="__logged_out__";function C(){return As}var kt={loggedIn:!1,userId:sr,email:null};function ge(){return or()}function or(){let e=process.env.SUPERCLAWD_MCP_KEY,t=process.env.SUPERCLAWD_MCP_SECRET;if(e&&t)return{keyId:e,secret:t};try{let n=JSON.parse(ga.readFileSync(ya,"utf8")),r=n?.credentials??n;if(typeof r?.keyId=="string"&&typeof r?.secret=="string")return{keyId:r.keyId,secret:r.secret}}catch{}return null}var Sn=[];function Jt(){return Sn}var xs=new Map,wa=5*6e4;async function zt(e){let t=xs.get(e);if(t&&Date.now()-t.at<wa)return{agents:t.agents,teams:t.teams};let n=or();if(!n)return null;try{let r=await fetch(`${_s}/api/prompt/agents-teams`,{headers:{"content-type":"application/json","x-mcp-key-id":n.keyId,"x-mcp-secret":n.secret,"x-workspace-slug":e,"x-request-id":Ts()}});if(!r.ok)return null;let s=await r.json().catch(()=>null),o=s?.agents??[],i=s?.teams??[];return xs.set(e,{agents:o,teams:i,at:Date.now()}),{agents:o,teams:i}}catch{return null}}function ba(e){return e.map(t=>({id:t.slug,name:t.name,tier:t.tier==="paid"?"paid":"free"}))}function vs(e){return e===401?"Your credentials are invalid or expired. Run `superclawd login`.":e===403?"This account isn't permitted to use Pipelines.":e===0||e>=500?"The SuperClawd backend is unreachable. Try again in a moment.":`Authentication failed (HTTP ${e}).`}function bn(e){return un(sr),Ie.loggedIn=!1,delete Ie.account,$.length=0,Sn=[],kt={loggedIn:!1,userId:sr,email:null,error:e},kt}async function Ns(){if(As)return un(qt),Ie.loggedIn=!0,Sn=[...$],kt={loggedIn:!0,userId:qt,email:Ie.account?.email??null},kt;let e=or();if(!e)return bn("Not authenticated. Run `superclawd login` to get started.");let t=d=>new Promise(u=>setTimeout(u,d)),n=8,r=2e3,s=0,o=null,i=!1;for(let d=1;d<=n;d++){try{let u=await fetch(`${_s}/api/prompt/workspaces`,{headers:{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret,"x-request-id":Ts()}});if(s=u.status,o=await u.json().catch(()=>null),u.ok){i=!0;break}if(s<500)return bn(vs(s))}catch{s=0}d===1&&console.log("[pipelines] waiting for the SuperClawd backend to come up\u2026"),d<n&&await t(r)}if(!i)return bn(vs(s));let c=o?.userId;return c?(un(c),Ie.loggedIn=!0,Ie.account={email:o?.email??"",org:"SuperClawd"},Sn=ba(o?.workspaces??[]),$.length=0,kt={loggedIn:!0,userId:c,email:o?.email??null},kt):bn("The backend didn't return an account id. Update the CLI/backend.")}Y();import{execFile as Sa}from"node:child_process";import{existsSync as vn}from"node:fs";import{rm as Ia}from"node:fs/promises";import{homedir as xa}from"node:os";import{dirname as va,join as xn,resolve as Es}from"node:path";var ir=xn(xa(),".superclawd","pipelines-worktrees");function ie(e,t){return new Promise(n=>{Sa("git",t,{cwd:e,maxBuffer:10*1024*1024},(r,s,o)=>{n({code:r&&typeof r.code=="number"?r.code:r?1:0,stdout:String(s??"").trim(),stderr:String(o??"").trim()})})})}async function Cs(e){if(!e||!vn(e))return!1;let t=await ie(e,["rev-parse","--is-inside-work-tree"]);return t.code===0&&t.stdout==="true"}async function Ue(e){if(!e||!vn(e))return[];if(await Cs(e))return[{name:".",path:Es(e)}];let{readdir:t}=await import("node:fs/promises"),n=await t(e,{withFileTypes:!0}).catch(()=>[]),r=[];for(let s of n){if(!s.isDirectory()||s.name.startsWith("."))continue;let o=xn(e,s.name);await Cs(o)&&r.push({name:s.name,path:Es(o)})}return r}async function Ps(e,t){let n=await Ue(e);if(!n.length)return null;let r=(t??"").trim();return!r||r==="."?n.length===1?n[0]:null:n.find(s=>s.name===r)??null}async function Os(e){let t=await ie(e,["symbolic-ref","--short","refs/remotes/origin/HEAD"]);if(t.code===0&&t.stdout)return t.stdout.replace(/^origin\//,"");let n=await ie(e,["rev-parse","--abbrev-ref","HEAD"]);return n.code===0&&n.stdout&&n.stdout!=="HEAD"?n.stdout:"main"}async function ar(e,t){await ie(e,["fetch","origin",t]);let n=`origin/${t}`;return(await ie(e,["rev-parse","--verify","--quiet",`refs/remotes/${n}`])).code===0?n:t}async function Ds(e){if(vn(e.worktreePath)){let s=await ie(e.worktreePath,["rev-parse","--is-inside-work-tree"]);if(s.code===0&&s.stdout==="true")return{ok:!0,worktreePath:e.worktreePath}}let n=(await ie(e.repoPath,["rev-parse","--verify","--quiet",`refs/heads/${e.branch}`])).code===0?["worktree","add",e.worktreePath,e.branch]:["worktree","add","-b",e.branch,e.worktreePath,e.startPoint??e.base],r=await ie(e.repoPath,n);return r.code!==0?{ok:!1,error:r.stderr||r.stdout||"git worktree add failed"}:{ok:!0,worktreePath:e.worktreePath}}async function js(e,t,n){let r=await ar(e,n),s=await ie(e,["rev-list","--left-right","--count",`${r}...${t}`]);if(s.code!==0)return{behind:0,ahead:0};let[o,i]=s.stdout.split(/\s+/).map(c=>Number(c)||0);return{behind:o??0,ahead:i??0}}async function Ms(e,t){await ie(e,["branch","-D",t])}async function Rn(e){let t=xn(ir,e);if(!vn(t))return;let{readdir:n}=await import("node:fs/promises"),r=await n(t,{withFileTypes:!0}).catch(()=>[]);for(let s of r){if(!s.isDirectory())continue;let o=xn(t,s.name),i=await ie(o,["rev-parse","--path-format=absolute","--git-common-dir"]);if(i.code===0&&i.stdout){let c=va(i.stdout);await ie(c,["worktree","remove","--force",o])}}await Ia(t,{recursive:!0,force:!0}).catch(()=>{})}function Ra(e){let t=e.trim().replace(/\.git$/,""),n=/^git@([^:]+):(.+)$/.exec(t);return n?`https://${n[1]}/${n[2]}`:(n=/^ssh:\/\/git@([^/]+)\/(.+)$/.exec(t),n?`https://${n[1]}/${n[2]}`:/^https?:\/\//.test(t)?t:null)}async function $s(e,t,n){let r=await ie(e,["remote","get-url","origin"]);if(r.code!==0||!r.stdout)return null;let s=Ra(r.stdout);return s?`${s}/compare/${t}...${n}?expand=1`:null}import{spawn as Pa,spawnSync as Oa}from"node:child_process";import dr from"node:fs";import ur from"node:os";import yt from"node:path";import{fileURLToPath as Da}from"node:url";import{execFileSync as Ta}from"node:child_process";import{realpathSync as _a}from"node:fs";function Aa(){if(process.platform!=="darwin")return!1;try{return Ta("which",["sandbox-exec"],{stdio:"ignore"}),!0}catch{return!1}}function Na(e){try{return _a(e)}catch{return e}}function Ea(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Ca(e){let t=["(version 1)","(allow default)"];for(let n of e)t.push(`(deny file-write* (subpath "${Ea(Na(n))}"))`);return t.push('(allow file-write* (regex #"/\\.git/"))'),t.push('(allow file-write* (regex #"/\\.claude/"))'),t.join(`
11
+ `)}function Bs(e){let{cmd:t,args:n,repoPaths:r,enabled:s}=e;return!s||!r.length||!Aa()?{cmd:t,args:n,sandboxed:!1}:{cmd:"sandbox-exec",args:["-p",Ca(r),t,...n],sandboxed:!0}}function Xt(e){if(!e||!e.trim())return process.cwd();let t=e.trim();return t==="~"?t=ur.homedir():(t.startsWith("~/")||t.startsWith("~\\"))&&(t=yt.join(ur.homedir(),t.slice(2))),yt.resolve(t)}function ja(){return`http://127.0.0.1:${Number(process.env.PIPELINES_PORT||process.env.PIPELINES_MOCK_PORT||63210)}`}function Ma(){let e=process.env.SUPERCLAWD_BIN;if(e)return{cmd:e,baseArgs:[]};let t=yt.dirname(Da(import.meta.url));for(let n=0;n<8;n++){let r=yt.join(t,"apps","cli","dist","index.js");if(dr.existsSync(r))return{cmd:process.execPath,baseArgs:[r]};let s=yt.dirname(t);if(s===t)break;t=s}return{cmd:"superclawd",baseArgs:[]}}function lr(e){let{cmd:t,baseArgs:n}=Ma(),r=[...n,"-p",e.prompt,"--pipelines"];e.pipelinesTools&&r.push(`--pipelines-tools=${e.pipelinesToolsMode??"board"}`),e.workspace&&r.push("--workspace",e.workspace),e.model&&r.push("--model",e.model),e.effort&&r.push("--effort",e.effort),e.noCapture&&r.push("--no-capture"),e.resume?r.push("--resume",e.resume):e.sessionId&&r.push("--session-id",e.sessionId);let s={};e.pipelinesTools&&(s.SUPERCLAWD_PIPELINES_URL=ja(),e.ticketId&&(s.SUPERCLAWD_PIPELINES_TICKET=e.ticketId));let o=Xt(e.workingDir);if(!dr.existsSync(o))return{pid:0,pgid:0,done:Promise.resolve({code:1,stdout:"",stderr:`working directory does not exist: ${o}${e.workingDir&&e.workingDir!==o?` (from "${e.workingDir}")`:""}`})};let i=Bs({cmd:t,args:r,repoPaths:e.sandboxRepos??[],enabled:!!e.sandbox});if(process.env.PIPELINES_DEBUG){let I=`[pipelines] spawn (cwd=${o}${i.sandboxed?", sandboxed":""}): ${i.cmd} ${i.args.join(" ")}`;console.log(I);try{dr.appendFileSync(yt.join(ur.homedir(),".superclawd","pipelines-debug.log"),`${new Date().toISOString()} ${I}
12
+ `)}catch{}}let c=Pa(i.cmd,i.args,{cwd:o,detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,...s}}),d="",u="";c.stdout?.on("data",I=>d+=String(I)),c.stderr?.on("data",I=>u+=String(I));let m=new Promise(I=>{c.on("error",p=>I({code:127,stdout:d,stderr:`${u}
13
+ ${String(p)}`})),c.on("close",p=>I({code:p??137,stdout:d,stderr:u}))}),g=c.pid??0;return{pid:g,pgid:g,done:m}}function Ls(e,t="SIGTERM"){if(e){if(process.platform==="win32"){try{Oa("taskkill",["/pid",String(e),"/T","/F"],{stdio:"ignore"})}catch{}return}try{process.kill(-e,t)}catch{try{process.kill(e,t)}catch{}}}}function Ve(e){return lr(e).done}var $a=["haiku","sonnet","opus","fable"],Ba=["low","medium","high","xhigh","max"],he="opus",ke="high",ve=(e,t=he)=>{let n=String(e??"").trim();return $a.includes(n)?n:t},Re=(e,t=ke)=>{let n=String(e??"").trim();return Ba.includes(n)?n:t};function La(){let e=new Date;return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}function qe(e,t,n){let r={id:`e${e.events.length+1}`,ts:La(),kind:t,text:n};return e.events.push(r),r}Y();import{randomUUID as Us}from"node:crypto";var Ga=1e4,Gs=3,Ua=1e3,qa=new Set(["host","content-length","content-type","user-agent","x-superclawd-event","x-superclawd-signature","transfer-encoding","connection"]),Fa=e=>new Promise(t=>setTimeout(t,e));function qs(e,t){let n={"content-type":"application/json","user-agent":"SuperClawd-Pipelines-Webhook/1","x-superclawd-event":e};l.webhookSecret&&(n["x-superclawd-signature"]=`sha256=${os(l.webhookSecret,t)}`);for(let r of l.webhookHeaders??[])r.key&&!qa.has(r.key.toLowerCase())&&(n[r.key]=r.value);return n}async function Fs(e,t,n){let r=new AbortController,s=setTimeout(()=>r.abort(),Ga);try{return(await fetch(e,{method:"POST",headers:n,body:t,signal:r.signal})).status}catch{return 0}finally{clearTimeout(s)}}function ue(e,t,n={}){let r=l;if(!r.webhookEnabled||!r.webhookUrl||!r.webhookEvents||!r.webhookEvents.includes(e))return;let s=r.webhookUrl,o={id:`evt_${Us()}`,event:e,occurredAt:new Date().toISOString(),workspaceId:n.workspaceId,data:t},i=JSON.stringify(o),c=qs(e,i);(async()=>{for(let d=1;d<=Gs;d++){let u=await Fs(s,i,c);if(u>=200&&u<300)return;d<Gs&&await Fa(Ua*d)}})().catch(()=>{})}async function Ws(){let e=l.webhookUrl;if(!e)return{ok:!1,error:"no webhook URL configured"};let t={id:`evt_${Us()}`,event:"webhook.test",occurredAt:new Date().toISOString(),data:{message:"SuperClawd Pipelines test event"}},n=JSON.stringify(t),r=qs("webhook.test",n),s=await Fs(e,n,r);return s>=200&&s<300?{ok:!0,status:s}:{ok:!1,...s?{status:s}:{error:"could not reach the webhook URL"}}}function fe(e,t,n={}){return e.status=t,n.stopReason!==void 0&&(e.stopReason=n.stopReason===null?void 0:n.stopReason),n.clearBlocker&&(e.blocker=void 0),n.event&&qe(e,n.event.kind,n.event.text),e.updatedAt=new Date().toISOString(),n.webhookEvent&&ue(n.webhookEvent,{runId:e.id,ticketId:e.ticketId,ticketKey:e.ticketKey,title:e.title,status:e.status,stopReason:e.stopReason},{workspaceId:e.workspaceId}),e}import{randomUUID as Wa}from"node:crypto";var Ka=3,Ha=1,Qa=10,wt=new Map,bt=[];function Ja(){let e=l.maxConcurrentRuns??Ka;return Math.max(Ha,Math.min(Qa,e))}function Te(e,t=!1,n){wt.has(e)||bt.some(r=>r.runId===e)||(bt.push({runId:e,resume:t,prompt:n}),Ks())}function Ks(){for(;wt.size<Ja()&&bt.length>0;){let e=bt.shift();Ya(e.runId,e.resume,e.prompt)}}function za(e,t,n){let r=e?`You are working on SuperClawd Pipelines ticket ${e.externalIdentifier} \u2014 "${e.title}" (ticket id: ${e.id}).`:`You are working on SuperClawd Pipelines run "${t.title}".`,o=!!e&&e.provider!=="local"?"- Start by calling read_ticket to read the full ticket (description, vendor comments, context, plan, open questions, conclusion, notes). On this run you can call it with no arguments \u2014 it defaults to this ticket. Read the vendor comments too \u2014 the real acceptance criteria and decisions often live in the discussion, not the description.":"- Start by calling read_ticket to read the full ticket (description, context, plan, open questions, conclusion, notes). On this run you can call it with no arguments \u2014 it defaults to this ticket.",i=[r,"","Use the SuperClawd Pipelines tools for this task:",o,"- Write your plan with set_plan (use the tool; do not create a plan file unless the ticket explicitly asks for one).","- If this task changes code: your working directory may be an umbrella folder containing several git repositories. Call list_repos to see them, research to decide which you need, then \u2014 BEFORE editing any repo \u2014 call start_repo_work({repo}) to get an isolated worktree. Make ALL changes for that repo inside the returned worktreePath and commit there; NEVER edit the repo in the working directory directly (other runs may be working on it at the same time). Claim each repo you touch. When done, push the branch and record the PR with add_pr_link (if you can't open a PR, push the branch and pass the compareUrl to add_pr_link so a human can).","- If you need something that isn't in the ticket, record it with add_open_question rather than guessing \u2014 and if it blocks progress, also call block_ticket with a reason.","- Keep durable findings or decisions on the ticket with add_note.","- When you've fully completed what the ticket asked, write a short wrap-up of what you did (and any results) with set_conclusion."];if(t.autonomy==="autonomous"&&i.push("","This run is AUTONOMOUS \u2014 no one is available to answer questions while it runs. Do NOT guess on any decision that materially changes the outcome. When you hit a genuine unknown, record it with add_open_question AND call block_ticket with a short reason, then stop \u2014 a human will resolve it and the ticket will be re-run. Only make assumptions for trivial, low-risk gaps, and state them clearly."),t.assignmentKind==="agent"&&t.agentName)i.push("",`DELEGATION \u2014 this ticket is assigned to the "${t.agentName}" agent. Use the Task tool to hand the ENTIRE ticket to the subagent for "${t.agentName}" (available in this session), let it complete the work, then report its result. Do NOT do the work yourself. If you cannot find that subagent, proceed yourself and add_note that the assigned agent was unavailable.`);else if(t.assignmentKind==="team"&&t.teamName){let u=t.teamLeadName;i.push("",u?`DELEGATION \u2014 this ticket is assigned to the "${t.teamName}" team. Use the Task tool to hand the ENTIRE ticket to the team's LEAD subagent, "${u}" (available in this session); it will coordinate its members. Do NOT do the work yourself. If you cannot find it, proceed yourself and add_note that the assigned team was unavailable.`:`DELEGATION \u2014 this ticket is assigned to the "${t.teamName}" team. Use the Task tool to hand the ENTIRE ticket to that team's lead-agent subagent, which coordinates its members. Do NOT do the work yourself. If you cannot find it, proceed yourself and add_note that the assigned team was unavailable.`)}i.push("","Then do the work the ticket asks for.");let c=i.join(`
14
14
  `),d=(n??"").trim();return d?`${c}
15
15
 
16
16
  Additional instructions from the human:
17
- ${d}`:c}async function ga(e){let t=e.worktrees??[];if(!t.length)return"";let n=[],r=!1;for(let o of t){let{behind:i}=await ds(o.worktreePath,o.branch,o.base);i>0&&(r=!0),n.push(`- repo "${o.repo}": worktree at ${o.worktreePath} (branch ${o.branch}`+(i>0?`, ${i} commit(s) behind ${o.base})`:")"))}let s=r?"One or more branches are behind their base branch. BEFORE making changes, update each stale branch: in its worktree run `git rebase origin/<base>`, resolve any conflicts, and then push with `--force-with-lease` to update the PR. If a rebase conflict is beyond what you can safely resolve, add_note explaining it and stop.":"";return["You are continuing earlier work on this ticket. You already created isolated git worktree(s) for it:",...n,"Make ALL changes inside the worktree path(s) above and commit/push there on the SAME branch \u2014 do NOT create a new worktree or branch, and do NOT edit the repo in the working directory. Update the existing PR rather than opening a new one. Only call start_repo_work if you need a repo not listed above.",...s?[s]:[],"",""].join(`
18
- `)}async function ha(e,t,n){let r=I[e];if(!r)return;let s=h.find(w=>w.id===r.ticketId),o=n??(s?`${s.title}
17
+ ${d}`:c}async function Xa(e){let t=e.worktrees??[];if(!t.length)return"";let n=[],r=!1;for(let o of t){let{behind:i}=await js(o.worktreePath,o.branch,o.base);i>0&&(r=!0),n.push(`- repo "${o.repo}": worktree at ${o.worktreePath} (branch ${o.branch}`+(i>0?`, ${i} commit(s) behind ${o.base})`:")"))}let s=r?"One or more branches are behind their base branch. BEFORE making changes, update each stale branch: in its worktree run `git rebase origin/<base>`, resolve any conflicts, and then push with `--force-with-lease` to update the PR. If a rebase conflict is beyond what you can safely resolve, add_note explaining it and stop.":"";return["You are continuing earlier work on this ticket. You already created isolated git worktree(s) for it:",...n,"Make ALL changes inside the worktree path(s) above and commit/push there on the SAME branch \u2014 do NOT create a new worktree or branch, and do NOT edit the repo in the working directory. Update the existing PR rather than opening a new one. Only call start_repo_work if you need a repo not listed above.",...s?[s]:[],"",""].join(`
18
+ `)}async function Ya(e,t,n){let r=x[e];if(!r)return;let s=h.find(p=>p.id===r.ticketId),o=n??(s?`${s.title}
19
19
 
20
- ${s.description??""}`.trim():r.title),i=t?await ga(r)+o:ma(s,r,n),c=s?.workingDir??l.workspaceDirs?.[r.workspaceId]??"~",d=s?.model||l.defaultModel||ce,u=s?.effort||l.defaultEffort||de,m=l.sandboxWorktreeEdits?(await De(Et(c))).map(w=>w.path):void 0,g=Fn({prompt:i,workspace:r.workspaceId,workingDir:c,model:d,effort:u,sessionId:t?null:r.sessionId,resume:t?r.sessionId??null:null,pipelinesTools:!0,ticketId:r.ticketId,sandbox:l.sandboxWorktreeEdits,sandboxRepos:m});st.set(e,g),je(r,"state_change",t?"re-engaged (resume)":"agent started"),r.updatedAt=new Date().toISOString(),await $(e);let p=await g.done;st.delete(e),await ka(e,p.code,p.stdout,p.stderr,i),ws()}async function ka(e,t,n,r,s){let o=I[e];if(!o||o.status!=="running")return;let i;if(t===0)i=((o.sessionId?Yt(o.sessionId):null)??n).trim();else{let d=(r||n).trim().slice(0,5e4);i=`\u26A0\uFE0F The run failed (exit code ${t}).${d?`
20
+ ${s.description??""}`.trim():r.title),i=t?await Xa(r)+o:za(s,r,n),c=s?.workingDir??l.workspaceDirs?.[r.workspaceId]??"~",d=s?.model||l.defaultModel||he,u=s?.effort||l.defaultEffort||ke,m=l.sandboxWorktreeEdits?(await Ue(Xt(c))).map(p=>p.path):void 0,g=lr({prompt:i,workspace:r.workspaceId,workingDir:c,model:d,effort:u,sessionId:t?null:r.sessionId,resume:t?r.sessionId??null:null,pipelinesTools:!0,ticketId:r.ticketId,sandbox:l.sandboxWorktreeEdits,sandboxRepos:m});wt.set(e,g),qe(r,"state_change",t?"re-engaged (resume)":"agent started"),r.updatedAt=new Date().toISOString(),await L(e);let I=await g.done;wt.delete(e),await Va(e,I.code,I.stdout,I.stderr,i),Ks()}var pr=null;function Hs(e){pr=e}async function Va(e,t,n,r,s){let o=x[e];if(!o||o.status!=="running")return;let i;if(t===0)i=((o.sessionId?wn(o.sessionId):null)??n).trim();else{let d=(r||n).trim().slice(0,5e4);i=`\u26A0\uFE0F The run failed (exit code ${t}).${d?`
21
21
 
22
- ${d}`:""}`}if(i&&(o.resultText=i.slice(0,5e4)),s||i){let d=h.find(m=>m.id===o.ticketId),u={id:`rr_${da()}`,ticketId:o.ticketId,runId:e,sessionId:o.sessionId,prompt:(s??"").slice(0,5e4),response:i.slice(0,5e4),status:t===0?"completed":"error",model:d?.model||l.defaultModel||ce,effort:d?.effort||l.defaultEffort||de,createdAt:new Date().toISOString()};q.unshift(u),await Qt(u)}let c=!!h.find(d=>d.id===o.ticketId)?.blockedReason;if(t===0){let d=n.trim().slice(0,4e3);if(d&&je(o,"state_change",d),je(o,"mcp_tool","agent finished its turn"),se(o,"stopped",{stopReason:"completed",clearBlocker:!0,webhookEvent:"run.completed"}),!c){S[o.ticketId]="in_review";let u=h.find(m=>m.id===o.ticketId);u&&l.prMonitorDefault&&u.prLinks?.length&&!u.prMonitor&&(u.prMonitor=!0,u.prMonitorCount=0,u.prMonitorLastAt=void 0,u.prMonitorNote=void 0)}}else{let d=(r||n).trim().slice(0,500);je(o,"error",`agent exited with code ${t}${d?`: ${d}`:""}`),se(o,"stopped",{stopReason:"error",webhookEvent:"run.failed"})}o.updatedAt=new Date().toISOString(),await $(e),await T(o.ticketId)}async function it(e){let t=st.get(e);t&&(fs(t.pgid),st.delete(e));let n=ot.findIndex(r=>r.runId===e);n!==-1&&ot.splice(n,1)}async function bs(){let e=Object.values(I).filter(t=>t.status==="running");for(let t of e)je(t,"error","interrupted by daemon restart"),se(t,"stopped",{stopReason:"error"}),await $(t.id);e.length&&console.log(`[pipelines] reconciled ${e.length} interrupted run(s)`)}V();function Ct(e,t,n){let r=[];for(let s of e.dependsOn??[]){let o=t(s);if(!o){r.push({id:s,reason:"missing"});continue}n(s)!=="done"&&r.push({id:s,identifier:o.externalIdentifier,title:o.title,reason:"not_done"})}return r}function Ss(e,t,n){let r=new Set,s=[...t];for(;s.length;){let o=s.pop();if(o===e)return!0;if(r.has(o))continue;r.add(o);let i=n(o);i?.dependsOn?.length&&s.push(...i.dependsOn)}return!1}function Is(e,t,n,r){if(!Array.isArray(n))return[];let s=[];for(let o of n){let i=String(o??"").trim();if(!i||i===e||s.includes(i))continue;let c=r(i);c&&c.connectionId===t&&s.push(i)}return s}import{randomUUID as ya}from"node:crypto";var re=class extends Error{constructor(n,r,s,o){super(s);this.status=n;this.code=r;this.extra=o;this.name="RunError"}},wa=e=>S[e]??"backlog";function on(e){let t=I[e];if(!t)throw new re(404,void 0,"run not found");return t}function Se(e){let t=x[e];return t?I[t]:void 0}async function Kn(e){let t=h.find(d=>d.id===e.ticketId);if(!t)throw new re(404,void 0,"ticket not found");let n=y.find(d=>d.id===t.connectionId);if(!n||n.linkStatus!=="linked"||!n.workspaceId)throw new re(409,void 0,"ticket connection is not linked to a workspace");let r=`run_${L.runSeq++}`,s=_()?{teams:Re,agents:Te}:await Nt(n.workspaceId)??{teams:[],agents:[]},o=s.teams.find(d=>d.id===e.teamId),i=s.agents.find(d=>d.id===e.agentId),c={id:r,ticketId:t.id,ticketKey:t.externalIdentifier,title:t.title,provider:t.provider,workspaceId:n.workspaceId,workspaceName:n.workspaceName,assignmentKind:e.assignmentKind,teamId:e.teamId,teamName:o?.name,teamLeadName:o?.leadAgentName??void 0,agentId:e.agentId,agentName:i?.name,autonomy:e.autonomy,status:"not_started",plan:[],events:[],createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return I[r]=c,x[t.id]=r,await $(r),c}async function an(e,t={}){let n=Se(e);return n||Kn({ticketId:e,assignmentKind:"anyone",autonomy:t.autonomy??l.defaultAutonomy})}async function at(e,t={}){let n=on(e);if(n.status==="not_started"){let i=h.find(d=>d.id===n.ticketId),c=i?Ct(i,d=>h.find(u=>u.id===d),wa):[];if(c.length)throw new re(409,"unmet_dependencies","blocked by dependencies",{unmet:c})}let r=(t.details??"").trim(),s=t.attachments??[],o=r+(s.length?`
22
+ ${d}`:""}`}if(i&&(o.resultText=i.slice(0,5e4)),s||i){let d=h.find(m=>m.id===o.ticketId),u={id:`rr_${Wa()}`,ticketId:o.ticketId,runId:e,sessionId:o.sessionId,prompt:(s??"").slice(0,5e4),response:i.slice(0,5e4),status:t===0?"completed":"error",model:d?.model||l.defaultModel||he,effort:d?.effort||l.defaultEffort||ke,createdAt:new Date().toISOString()};X.unshift(u),await mn(u)}let c=!!h.find(d=>d.id===o.ticketId)?.blockedReason;if(t===0){let d=n.trim().slice(0,4e3);if(d&&qe(o,"state_change",d),qe(o,"mcp_tool","agent finished its turn"),fe(o,"stopped",{stopReason:"completed",clearBlocker:!0,webhookEvent:"run.completed"}),!c){S[o.ticketId]="in_review";let u=h.find(m=>m.id===o.ticketId);u&&l.prMonitorDefault&&u.prLinks?.length&&!u.prMonitor&&(u.prMonitor=!0,u.prMonitorCount=0,u.prMonitorLastAt=void 0,u.prMonitorNote=void 0)}}else{let d=(r||n).trim().slice(0,500);qe(o,"error",`agent exited with code ${t}${d?`: ${d}`:""}`),fe(o,"stopped",{stopReason:"error",webhookEvent:"run.failed"})}if(o.updatedAt=new Date().toISOString(),await L(e),await N(o.ticketId),pr){let d=t===0?c?"blocked":"in_review":"error";try{pr(o.ticketId,d)}catch(u){console.error("batch finalize hook failed",u)}}}async function St(e){let t=wt.get(e);t&&(Ls(t.pgid),wt.delete(e));let n=bt.findIndex(r=>r.runId===e);n!==-1&&bt.splice(n,1)}async function Qs(){let e=Object.values(x).filter(t=>t.status==="running");for(let t of e)qe(t,"error","interrupted by daemon restart"),fe(t,"stopped",{stopReason:"error"}),await L(t.id);e.length&&console.log(`[pipelines] reconciled ${e.length} interrupted run(s)`)}Y();function Vt(e,t,n){let r=[];for(let s of e.dependsOn??[]){let o=t(s);if(!o){r.push({id:s,reason:"missing"});continue}n(s)!=="done"&&r.push({id:s,identifier:o.externalIdentifier,title:o.title,reason:"not_done"})}return r}function Js(e,t,n){let r=new Set,s=[...t];for(;s.length;){let o=s.pop();if(o===e)return!0;if(r.has(o))continue;r.add(o);let i=n(o);i?.dependsOn?.length&&s.push(...i.dependsOn)}return!1}function zs(e,t,n,r){if(!Array.isArray(n))return[];let s=[];for(let o of n){let i=String(o??"").trim();if(!i||i===e||s.includes(i))continue;let c=r(i);c&&c.connectionId===t&&s.push(i)}return s}import{randomUUID as Za}from"node:crypto";var le=class extends Error{constructor(n,r,s,o){super(s);this.status=n;this.code=r;this.extra=o;this.name="RunError"}},ec=e=>S[e]??"backlog";function Tn(e){let t=x[e];if(!t)throw new le(404,void 0,"run not found");return t}function J(e){let t=T[e];return t?x[t]:void 0}async function mr(e){let t=h.find(d=>d.id===e.ticketId);if(!t)throw new le(404,void 0,"ticket not found");let n=b.find(d=>d.id===t.connectionId);if(!n||n.linkStatus!=="linked"||!n.workspaceId)throw new le(409,void 0,"ticket connection is not linked to a workspace");let r=`run_${B.runSeq++}`,s=C()?{teams:Ce,agents:Pe}:await zt(n.workspaceId)??{teams:[],agents:[]},o=s.teams.find(d=>d.id===e.teamId),i=s.agents.find(d=>d.id===e.agentId),c={id:r,ticketId:t.id,ticketKey:t.externalIdentifier,title:t.title,provider:t.provider,workspaceId:n.workspaceId,workspaceName:n.workspaceName,assignmentKind:e.assignmentKind,teamId:e.teamId,teamName:o?.name,teamLeadName:o?.leadAgentName??void 0,agentId:e.agentId,agentName:i?.name,autonomy:e.autonomy,status:"not_started",plan:[],events:[],createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return x[r]=c,T[t.id]=r,await L(r),c}async function It(e,t={}){let n=J(e);return n||mr({ticketId:e,assignmentKind:"anyone",autonomy:t.autonomy??l.defaultAutonomy})}async function Fe(e,t={}){let n=Tn(e);if(n.status==="not_started"&&!t.skipDepGate){let i=h.find(d=>d.id===n.ticketId),c=i?Vt(i,d=>h.find(u=>u.id===d),ec):[];if(c.length)throw new le(409,"unmet_dependencies","blocked by dependencies",{unmet:c})}let r=(t.details??"").trim(),s=t.attachments??[],o=r+(s.length?`
23
23
 
24
24
  Attached files (read these):
25
25
  ${s.map(i=>`- ${i}`).join(`
26
- `)}`:"");return n.sessionId||(n.sessionId=ya()),se(n,"running",{stopReason:null,event:{kind:"state_change",text:r?`started with details: ${r.slice(0,80)}`:"started"},webhookEvent:"run.started"}),S[n.ticketId]="in_progress",await $(n.id),await T(n.ticketId),_()||be(n.id,!1,o||void 0),n}async function ct(e){let t=on(e);return se(t,"paused",{event:{kind:"state_change",text:"paused by user"},webhookEvent:"run.paused"}),await it(t.id),await $(t.id),t}async function dt(e){let t=on(e);return se(t,"running",{event:{kind:"state_change",text:"resumed (continue)"},webhookEvent:"run.resumed"}),S[t.ticketId]="in_progress",await $(t.id),await T(t.ticketId),_()||be(t.id,!0),t}async function ut(e){let t=on(e);return se(t,"stopped",{stopReason:"user",clearBlocker:!0,event:{kind:"state_change",text:"stopped by user"},webhookEvent:"run.stopped"}),await it(t.id),await $(t.id),t}V();import{randomUUID as Rs}from"node:crypto";var N=class extends Error{constructor(n,r,s){super(r);this.status=n;this.extra=s;this.name="TicketError"}},ba=["backlog","in_progress","needs_input","in_review","done"],vs=e=>S[e]??"backlog",Hn=e=>y.find(t=>t.id===e.connectionId)?.workspaceId??void 0;function Pt(e){let t=h.find(n=>n.id===e);if(!t)throw new N(404,"ticket not found");return t}function cn(e){return h.find(t=>t.id===e)}function lt(e){return P.filter(t=>t.ticketId===e).slice().reverse()}function pt(e){return C.filter(t=>t.ticketId===e)}async function ft(e,t){let n=Pt(e);if(!ba.includes(t))throw new N(400,"invalid column");if(n.blockedReason&&t!==vs(n.id))throw new N(409,"a blocked ticket can't change lanes \u2014 unblock it first");if(t==="done"){let s=x[n.id],o=s?I[s]:void 0;if(!o||o.status!=="stopped")throw new N(409,"a task can only enter Done once its session is stopped")}let r=vs(n.id);return S[n.id]=t,await T(n.id),t!==r&&ue("ticket.moved",{ticketId:n.id,ticketKey:n.externalIdentifier,from:r,to:t},{workspaceId:Hn(n)}),{ticketId:n.id,column:t}}async function Ie(e,t){let n=Pt(e),r=[],s=null;if(typeof t.workingDir=="string"&&(n.workingDir=t.workingDir.trim()||void 0),t.model!==void 0&&(n.model=ye(t.model,n.model||ce)),t.effort!==void 0&&(n.effort=we(t.effort,n.effort||de)),"blockedReason"in t){let i=String(t.blockedReason??"").trim().slice(0,2e3),c=!!n.blockedReason,d=!!i;if(c&&!d){let u=C.filter(m=>m.ticketId===n.id&&!m.resolved).length;if(u>0)throw new N(409,"resolve open questions before unblocking",{unresolved:u})}n.blockedReason=i||void 0,d&&!c?(S[n.id]="needs_input",s={event:"ticket.blocked"}):!d&&c&&(S[n.id]="backlog",s={event:"ticket.unblocked"})}for(let i of["additionalContext","plan","conclusion"])if(i in t){let d=String(t[i]??"").trim().slice(0,2e4)||void 0;d!==n[i]&&(n[i]=d,n[`${i}UpdatedAt`]=d?new Date().toISOString():void 0,r.push(i))}if(n.provider==="local"){if(typeof t.title=="string"&&t.title.trim()&&t.title.trim()!==n.title&&(n.title=t.title.trim(),r.push("title")),typeof t.description=="string"){let c=t.description.trim()||void 0;c!==n.description&&(n.description=c,r.push("description"))}let i=Number(t.priority);[0,1,2,3,4].includes(i)&&i!==n.priority&&(n.priority=i,r.push("priority")),n.updatedAt=new Date().toISOString()}await T(n.id);let o=Hn(n);return s&&ue(s.event,{ticketId:n.id,ticketKey:n.externalIdentifier,...n.blockedReason?{reason:n.blockedReason}:{}},{workspaceId:o}),r.length&&ue("ticket.updated",{ticketId:n.id,ticketKey:n.externalIdentifier,fields:r},{workspaceId:o}),n}async function mt(e,t={}){let n=Pt(e);if(!n.blockedReason)throw new N(409,"ticket is not blocked");let r=C.filter(d=>d.ticketId===n.id&&!d.resolved).length;if(r>0)throw new N(409,"resolve open questions before unblocking",{unresolved:r});let s=x[n.id],o=s?I[s]:void 0,i=t.resume===!0&&!!o?.sessionId;n.blockedReason=void 0;let c=Hn(n);return ue("ticket.unblocked",{ticketId:n.id,ticketKey:n.externalIdentifier},{workspaceId:c}),i&&o?(se(o,"running",{stopReason:null,clearBlocker:!0,event:{kind:"state_change",text:"unblocked & resumed"},webhookEvent:"run.resumed"}),S[n.id]="in_progress",await $(o.id),await T(n.id),_()||be(o.id,!0,"The block on this ticket has been resolved. Re-read the ticket with read_ticket (its open questions are now answered) and continue the work."),{ticket:n,run:o,resumed:!0}):(S[n.id]="backlog",await T(n.id),{ticket:n,resumed:!1})}async function gt(e,t){let n=y.find(u=>u.id===e);if(!n)throw new N(404,"board not found");if(n.provider!=="local")throw new N(400,"tickets can only be created on the Local board");let r=String(t.title??"").trim();if(!r)throw new N(400,"title is required");let s=Number(t.priority),o=[0,1,2,3,4].includes(s)?s:0,i=++L.localSeq,c=new Date().toISOString(),d={id:`t_local${i}`,connectionId:n.id,provider:"local",externalIdentifier:`LOCAL-${i}`,project:"Local",title:r,status:"todo",statusRaw:"Backlog",priority:o,labels:[],url:"",workspaceId:n.workspaceId,workingDir:String(t.workingDir??"").trim()||(n.workspaceId?l.workspaceDirs?.[n.workspaceId]??"~":"~"),model:ye(t.model??l.defaultModel),effort:we(t.effort??l.defaultEffort),description:String(t.description??"").trim()||void 0,createdAt:c,updatedAt:c};return h.push(d),S[d.id]="backlog",n.ticketCount+=1,await T(d.id),await R(n),d}async function ht(e,t){Pt(e);let n=String(t.body??"").trim();if(!n)throw new N(400,"empty note");let r=t.author==="assistant"?"assistant":"user",s=new Date().toISOString(),o={id:`note_${Rs()}`,ticketId:e,author:r,body:n.slice(0,5e3),createdAt:s,updatedAt:s};return P.push(o),await et(o),o}async function kt(e,t){let n=P.find(s=>s.id===e);if(!n)throw new N(404,"note not found");let r=String(t??"").trim();if(!r)throw new N(400,"empty note");return n.body=r.slice(0,5e3),n.updatedAt=new Date().toISOString(),await et(n),n}async function yt(e){let t=P.findIndex(n=>n.id===e);if(t===-1)throw new N(404,"note not found");P.splice(t,1),await Ht(e)}async function wt(e,t){Pt(e);let n=String(t??"").trim();if(!n)throw new N(400,"empty question");let r=new Date().toISOString(),s=C.filter(i=>i.ticketId===e).length,o={id:`oq_${Rs()}`,ticketId:e,question:n.slice(0,5e3),answer:void 0,resolved:!1,position:s,createdAt:r,updatedAt:r};return C.push(o),await Pn(o.id),o}async function bt(e,t){let n=C.find(r=>r.id===e);if(n===void 0)throw new N(404,"question not found");return typeof t.question=="string"&&t.question.trim()&&(n.question=t.question.trim().slice(0,5e3)),"answer"in t&&(n.answer=String(t.answer??"").trim().slice(0,2e4)||void 0),typeof t.resolved=="boolean"&&(n.resolved=t.resolved),n.updatedAt=new Date().toISOString(),await Pn(n.id),n}async function St(e){let t=C.findIndex(n=>n.id===e);if(t===-1)throw new N(404,"question not found");C.splice(t,1),await zt(e),await Qr()}V();V();import _s from"express";import Ia from"cors";import{createRequire as xa}from"node:module";import{dirname as As,join as zn}from"node:path";import{existsSync as va}from"node:fs";var dn=["ticket.moved","ticket.blocked","ticket.unblocked","ticket.updated","run.started","run.paused","run.resumed","run.completed","run.failed","run.stopped","schedule.run.started","schedule.run.completed","schedule.run.failed"];var K={name:"id",in:"path",required:!0,schema:{type:"string"}},U=[{bearerAuth:[]}],le=(e,t=!0)=>({required:t,content:{"application/json":{schema:e}}}),F=(e,t="Success")=>({description:t,content:{"application/json":{schema:e}}}),v=e=>({$ref:`#/components/schemas/${e}`}),O=e=>({description:e,content:{"application/json":{schema:v("Error")}}});function Sa(){let e={};for(let t of dn)e[t]={post:{summary:`\`${t}\` event`,description:"Delivered to your configured webhook URL. Fixed headers (Content-Type, User-Agent, X-SuperClawd-Event) plus your custom headers; signed with HMAC-SHA256 in X-SuperClawd-Signature (sha256=<hex>) when a signing secret is set.",requestBody:le(v("WebhookEnvelope")),responses:{"2xx":{description:"Acknowledge with any 2xx; non-2xx is retried."}}}};return e}var Ts={openapi:"3.1.0",info:{title:"SuperClawd Pipelines \u2014 Public API",version:"1.0.0",description:"Key-authenticated HTTP API for board, ticket, and run actions, plus outbound webhooks for ticket and run lifecycle events. Authenticate every request with `Authorization: Bearer <key>` (generate a key in Settings \u2192 API)."},servers:[{url:"/",description:"This Pipelines daemon (public API port)"}],security:U,tags:[{name:"Boards"},{name:"Tickets"},{name:"Notes"},{name:"Questions"},{name:"Runs"}],paths:{"/v1/boards":{get:{tags:["Boards"],summary:"List boards (connections)",security:U,responses:{200:F({type:"array",items:v("Board")},"Boards"),401:O("Missing or invalid API key")}}},"/v1/boards/{id}/tickets":{get:{tags:["Boards"],summary:"List a board's tickets",security:U,parameters:[K],responses:{200:F({type:"array",items:v("Ticket")},"Tickets"),401:O("Missing or invalid API key")}},post:{tags:["Boards"],summary:"Create a ticket on a Local board",description:"Local-board only (vendor boards import tickets, they don't author them). New tickets land in Backlog.",security:U,parameters:[K],requestBody:le({type:"object",required:["title"],properties:{title:{type:"string"},description:{type:"string"},priority:{type:"integer",enum:[0,1,2,3,4],description:"0 none \xB7 1 urgent \xB7 2 high \xB7 3 medium \xB7 4 low"},workingDir:{type:"string"},model:{type:"string"},effort:{type:"string"}}}),responses:{201:F(v("Ticket"),"Created ticket"),400:O("Not a local board, or title missing"),404:O("Board not found")}}},"/v1/tickets/{id}":{get:{tags:["Tickets"],summary:"Get a ticket",security:U,parameters:[K],responses:{200:F(v("Ticket"),"Ticket"),404:O("Ticket not found")}},patch:{tags:["Tickets"],summary:"Update ticket fields",description:"plan/conclusion/additionalContext/blockedReason/workingDir/model/effort apply to any ticket; title/description/priority to local-board tickets only. Setting blockedReason blocks (moves to the Blocked lane); clearing it unblocks (refused while open questions are unresolved).",security:U,parameters:[K],requestBody:le(v("TicketUpdate")),responses:{200:F(v("Ticket"),"Updated ticket"),404:O("Ticket not found"),409:O("Unresolved open questions block unblocking")}}},"/v1/tickets/{id}/move":{post:{tags:["Tickets"],summary:"Move a ticket to a lane",description:"A blocked ticket can't change lanes until unblocked; Done is only allowed once the ticket's run is stopped.",security:U,parameters:[K],requestBody:le(v("MoveRequest")),responses:{200:F(v("MoveResult"),"Moved"),400:O("Invalid column"),404:O("Ticket not found"),409:O("Blocked-lane freeze or Done gate")}}},"/v1/tickets/{id}/unblock":{post:{tags:["Tickets"],summary:"Unblock a ticket",description:"Refused while open questions are unresolved. With `resume: true` (and an existing run session) the run re-enters and the card goes to In Progress; otherwise it returns to Backlog.",security:U,parameters:[K],requestBody:le(v("UnblockRequest"),!1),responses:{200:F(v("UnblockResult"),"Unblocked"),409:O("Not blocked, or unresolved open questions")}}},"/v1/tickets/{id}/notes":{get:{tags:["Notes"],summary:"List a ticket's notes (newest first)",security:U,parameters:[K],responses:{200:F({type:"array",items:v("Note")},"Notes")}},post:{tags:["Notes"],summary:"Add a note",security:U,parameters:[K],requestBody:le(v("NoteCreate")),responses:{201:F(v("Note"),"Created"),400:O("Empty note"),404:O("Ticket not found")}}},"/v1/notes/{id}":{patch:{tags:["Notes"],summary:"Edit a note",security:U,parameters:[K],requestBody:le(v("NoteCreate")),responses:{200:F(v("Note"),"Updated"),404:O("Note not found")}},delete:{tags:["Notes"],summary:"Delete a note",security:U,parameters:[K],responses:{200:F(v("Ok"),"Deleted"),404:O("Note not found")}}},"/v1/tickets/{id}/questions":{get:{tags:["Questions"],summary:"List a ticket's open questions",security:U,parameters:[K],responses:{200:F({type:"array",items:v("Question")},"Questions")}},post:{tags:["Questions"],summary:"Add an open question",security:U,parameters:[K],requestBody:le(v("QuestionCreate")),responses:{201:F(v("Question"),"Created"),400:O("Empty question"),404:O("Ticket not found")}}},"/v1/questions/{id}":{patch:{tags:["Questions"],summary:"Edit a question (text / answer / resolved)",security:U,parameters:[K],requestBody:le(v("QuestionUpdate")),responses:{200:F(v("Question"),"Updated"),404:O("Question not found")}},delete:{tags:["Questions"],summary:"Delete a question",security:U,parameters:[K],responses:{200:F(v("Ok"),"Deleted"),404:O("Question not found")}}},"/v1/tickets/{id}/run":{get:{tags:["Runs"],summary:"Get the ticket's run",security:U,parameters:[K],responses:{200:F(v("Run"),"Run"),404:O("No run for this ticket")}}},"/v1/tickets/{id}/run/{action}":{post:{tags:["Runs"],summary:"Control the run (start | pause | resume | stop)",description:"start creates a run if none exists, then enqueues it. pause kills the process but keeps the session resumable; resume re-enters it; stop marks it stopped and kills it.",security:U,parameters:[K,{name:"action",in:"path",required:!0,schema:{type:"string",enum:["start","pause","resume","stop"]}}],requestBody:le(v("RunStartRequest"),!1),responses:{200:F(v("Run"),"Run"),400:O("Unknown action"),404:O("No run for this ticket"),409:O("Unmet dependencies (on first start)")}}}},webhooks:Sa(),components:{securitySchemes:{bearerAuth:{type:"http",scheme:"bearer",description:"The API key generated in Settings \u2192 API."}},schemas:{Error:{type:"object",properties:{error:{type:"string"},code:{type:"string"}},required:["error"]},Ok:{type:"object",properties:{ok:{type:"boolean"}}},Board:{type:"object",properties:{id:{type:"string"},provider:{type:"string"},workspaceId:{type:"string"},workspaceName:{type:"string"},linkStatus:{type:"string"},ticketCount:{type:"integer"}}},Ticket:{type:"object",description:"A board ticket (fields vary by provider).",properties:{id:{type:"string"},connectionId:{type:"string"},provider:{type:"string"},externalIdentifier:{type:"string"},title:{type:"string"},description:{type:"string"},column:{type:"string",enum:["backlog","in_progress","needs_input","in_review","done"]},blockedReason:{type:"string",nullable:!0},plan:{type:"string",nullable:!0},conclusion:{type:"string",nullable:!0},additionalContext:{type:"string",nullable:!0},comments:{type:"array",description:"Vendor comments/discussion synced read-only from the provider (oldest\u2192newest).",items:v("TicketComment")}}},TicketComment:{type:"object",description:"A ticket comment synced read-only from the vendor.",properties:{id:{type:"string"},author:{type:"string",nullable:!0},body:{type:"string"},createdAt:{type:"string",format:"date-time",nullable:!0},updatedAt:{type:"string",format:"date-time",nullable:!0}}},TicketUpdate:{type:"object",properties:{title:{type:"string"},description:{type:"string"},priority:{type:"integer",minimum:0,maximum:4},plan:{type:"string"},conclusion:{type:"string"},additionalContext:{type:"string"},blockedReason:{type:"string",nullable:!0,description:"Non-empty blocks; null/empty unblocks."},workingDir:{type:"string"},model:{type:"string"},effort:{type:"string"}}},MoveRequest:{type:"object",required:["column"],properties:{column:{type:"string",enum:["backlog","in_progress","needs_input","in_review","done"]}}},MoveResult:{type:"object",properties:{ticketId:{type:"string"},column:{type:"string"}}},UnblockRequest:{type:"object",properties:{resume:{type:"boolean",description:"Re-enter the existing run session on unblock."}}},UnblockResult:{type:"object",properties:{ticket:v("Ticket"),run:v("Run"),resumed:{type:"boolean"}}},Note:{type:"object",properties:{id:{type:"string"},ticketId:{type:"string"},author:{type:"string",enum:["user","assistant"]},body:{type:"string"},createdAt:{type:"string",format:"date-time"},updatedAt:{type:"string",format:"date-time"}}},NoteCreate:{type:"object",required:["body"],properties:{body:{type:"string",maxLength:5e3},author:{type:"string",enum:["user","assistant"]}}},Question:{type:"object",properties:{id:{type:"string"},ticketId:{type:"string"},question:{type:"string"},answer:{type:"string",nullable:!0},resolved:{type:"boolean"},position:{type:"integer"}}},QuestionCreate:{type:"object",required:["question"],properties:{question:{type:"string",maxLength:5e3}}},QuestionUpdate:{type:"object",properties:{question:{type:"string"},answer:{type:"string",nullable:!0},resolved:{type:"boolean"}}},RunStartRequest:{type:"object",description:"Only used by the `start` action.",properties:{details:{type:"string",description:"Calibration prompt appended to the run's guiding prompt."},attachments:{type:"array",items:{type:"string"},description:"File paths the agent reads from disk."},autonomy:{type:"string",enum:["supervised","autonomous"],description:"Applied only when the run doesn't exist yet; defaults to the workspace setting."}}},Run:{type:"object",properties:{id:{type:"string"},ticketId:{type:"string"},ticketKey:{type:"string"},title:{type:"string"},status:{type:"string",enum:["not_started","running","paused","blocked","stopped"]},stopReason:{type:"string",enum:["completed","user","error"],nullable:!0},workspaceId:{type:"string"}}},WebhookEnvelope:{type:"object",properties:{id:{type:"string",description:"Unique event id (evt_\u2026)."},event:{type:"string"},occurredAt:{type:"string",format:"date-time"},workspaceId:{type:"string"},data:{type:"object",additionalProperties:!0,description:"Event-specific payload (ticketId/runId, changed fields, \u2026)."}},required:["id","event","occurredAt","data"]}}}};function Ra(){let e="dist/browser/standalone.js",t=As(xa(import.meta.url).resolve("@scalar/api-reference"));for(let n=0;n<6;n++){if(va(zn(t,e)))return zn(t,e);t=As(t)}return zn(t,e)}var Ta=Ra(),_a=`<!doctype html>
26
+ `)}`:"");return n.sessionId||(n.sessionId=Za()),fe(n,"running",{stopReason:null,event:{kind:"state_change",text:r?`started with details: ${r.slice(0,80)}`:"started"},webhookEvent:"run.started"}),S[n.ticketId]="in_progress",await L(n.id),await N(n.ticketId),C()||Te(n.id,!1,o||void 0),n}async function xt(e){let t=Tn(e);return fe(t,"paused",{event:{kind:"state_change",text:"paused by user"},webhookEvent:"run.paused"}),await St(t.id),await L(t.id),t}async function vt(e){let t=Tn(e);return fe(t,"running",{event:{kind:"state_change",text:"resumed (continue)"},webhookEvent:"run.resumed"}),S[t.ticketId]="in_progress",await L(t.id),await N(t.ticketId),C()||Te(t.id,!0),t}async function We(e){let t=Tn(e);return fe(t,"stopped",{stopReason:"user",clearBlocker:!0,event:{kind:"state_change",text:"stopped by user"},webhookEvent:"run.stopped"}),await St(t.id),await L(t.id),t}Y();import{randomUUID as Vs}from"node:crypto";var P=class extends Error{constructor(n,r,s){super(r);this.status=n;this.extra=s;this.name="TicketError"}},tc=["backlog","in_progress","needs_input","in_review","done"],Ys=e=>S[e]??"backlog",hr=e=>b.find(t=>t.id===e.connectionId)?.workspaceId??void 0;function Zt(e){let t=h.find(n=>n.id===e);if(!t)throw new P(404,"ticket not found");return t}function _n(e){return h.find(t=>t.id===e)}function Rt(e){return j.filter(t=>t.ticketId===e).slice().reverse()}function Tt(e){return D.filter(t=>t.ticketId===e)}async function _t(e,t){let n=Zt(e);if(!tc.includes(t))throw new P(400,"invalid column");if(n.blockedReason&&t!==Ys(n.id))throw new P(409,"a blocked ticket can't change lanes \u2014 unblock it first");if(t==="done"){let s=T[n.id],o=s?x[s]:void 0;if(!o||o.status!=="stopped")throw new P(409,"a task can only enter Done once its session is stopped")}let r=Ys(n.id);return S[n.id]=t,await N(n.id),t!==r&&ue("ticket.moved",{ticketId:n.id,ticketKey:n.externalIdentifier,from:r,to:t},{workspaceId:hr(n)}),{ticketId:n.id,column:t}}async function _e(e,t){let n=Zt(e),r=[],s=null;if(typeof t.workingDir=="string"&&(n.workingDir=t.workingDir.trim()||void 0),t.model!==void 0&&(n.model=ve(t.model,n.model||he)),t.effort!==void 0&&(n.effort=Re(t.effort,n.effort||ke)),"blockedReason"in t){let i=String(t.blockedReason??"").trim().slice(0,2e3),c=!!n.blockedReason,d=!!i;if(c&&!d){let u=D.filter(m=>m.ticketId===n.id&&!m.resolved).length;if(u>0)throw new P(409,"resolve open questions before unblocking",{unresolved:u})}n.blockedReason=i||void 0,d&&!c?(S[n.id]="needs_input",s={event:"ticket.blocked"}):!d&&c&&(S[n.id]="backlog",s={event:"ticket.unblocked"})}for(let i of["additionalContext","plan","conclusion"])if(i in t){let d=String(t[i]??"").trim().slice(0,2e4)||void 0;d!==n[i]&&(n[i]=d,n[`${i}UpdatedAt`]=d?new Date().toISOString():void 0,r.push(i))}if(n.provider==="local"){if(typeof t.title=="string"&&t.title.trim()&&t.title.trim()!==n.title&&(n.title=t.title.trim(),r.push("title")),typeof t.description=="string"){let c=t.description.trim()||void 0;c!==n.description&&(n.description=c,r.push("description"))}let i=Number(t.priority);[0,1,2,3,4].includes(i)&&i!==n.priority&&(n.priority=i,r.push("priority")),n.updatedAt=new Date().toISOString()}await N(n.id);let o=hr(n);return s&&ue(s.event,{ticketId:n.id,ticketKey:n.externalIdentifier,...n.blockedReason?{reason:n.blockedReason}:{}},{workspaceId:o}),r.length&&ue("ticket.updated",{ticketId:n.id,ticketKey:n.externalIdentifier,fields:r},{workspaceId:o}),n}async function At(e,t={}){let n=Zt(e);if(!n.blockedReason)throw new P(409,"ticket is not blocked");let r=D.filter(d=>d.ticketId===n.id&&!d.resolved).length;if(r>0)throw new P(409,"resolve open questions before unblocking",{unresolved:r});let s=T[n.id],o=s?x[s]:void 0,i=t.resume===!0&&!!o?.sessionId;n.blockedReason=void 0;let c=hr(n);return ue("ticket.unblocked",{ticketId:n.id,ticketKey:n.externalIdentifier},{workspaceId:c}),i&&o?(fe(o,"running",{stopReason:null,clearBlocker:!0,event:{kind:"state_change",text:"unblocked & resumed"},webhookEvent:"run.resumed"}),S[n.id]="in_progress",await L(o.id),await N(n.id),C()||Te(o.id,!0,"The block on this ticket has been resolved. Re-read the ticket with read_ticket (its open questions are now answered) and continue the work."),{ticket:n,run:o,resumed:!0}):(S[n.id]="backlog",await N(n.id),{ticket:n,resumed:!1})}async function Nt(e,t){let n=b.find(u=>u.id===e);if(!n)throw new P(404,"board not found");if(n.provider!=="local")throw new P(400,"tickets can only be created on the Local board");let r=String(t.title??"").trim();if(!r)throw new P(400,"title is required");let s=Number(t.priority),o=[0,1,2,3,4].includes(s)?s:0,i=++B.localSeq,c=new Date().toISOString(),d={id:`t_local${i}`,connectionId:n.id,provider:"local",externalIdentifier:`LOCAL-${i}`,project:"Local",title:r,status:"todo",statusRaw:"Backlog",priority:o,labels:[],url:"",workspaceId:n.workspaceId,workingDir:String(t.workingDir??"").trim()||(n.workspaceId?l.workspaceDirs?.[n.workspaceId]??"~":"~"),model:ve(t.model??l.defaultModel),effort:Re(t.effort??l.defaultEffort),description:String(t.description??"").trim()||void 0,createdAt:c,updatedAt:c};return h.push(d),S[d.id]="backlog",n.ticketCount+=1,await N(d.id),await A(n),d}async function Et(e,t){Zt(e);let n=String(t.body??"").trim();if(!n)throw new P(400,"empty note");let r=t.author==="assistant"?"assistant":"user",s=new Date().toISOString(),o={id:`note_${Vs()}`,ticketId:e,author:r,body:n.slice(0,5e3),createdAt:s,updatedAt:s};return j.push(o),await ht(o),o}async function Ct(e,t){let n=j.find(s=>s.id===e);if(!n)throw new P(404,"note not found");let r=String(t??"").trim();if(!r)throw new P(400,"empty note");return n.body=r.slice(0,5e3),n.updatedAt=new Date().toISOString(),await ht(n),n}async function Pt(e){let t=j.findIndex(n=>n.id===e);if(t===-1)throw new P(404,"note not found");j.splice(t,1),await gn(e)}async function Ot(e,t){Zt(e);let n=String(t??"").trim();if(!n)throw new P(400,"empty question");let r=new Date().toISOString(),s=D.filter(i=>i.ticketId===e).length,o={id:`oq_${Vs()}`,ticketId:e,question:n.slice(0,5e3),answer:void 0,resolved:!1,position:s,createdAt:r,updatedAt:r};return D.push(o),await er(o.id),o}async function Dt(e,t){let n=D.find(r=>r.id===e);if(n===void 0)throw new P(404,"question not found");return typeof t.question=="string"&&t.question.trim()&&(n.question=t.question.trim().slice(0,5e3)),"answer"in t&&(n.answer=String(t.answer??"").trim().slice(0,2e4)||void 0),typeof t.resolved=="boolean"&&(n.resolved=t.resolved),n.updatedAt=new Date().toISOString(),await er(n.id),n}async function jt(e){let t=D.findIndex(n=>n.id===e);if(t===-1)throw new P(404,"question not found");D.splice(t,1),await kn(e),await ys()}Y();var G=class extends Error{constructor(n,r,s,o){super(s);this.status=n;this.code=r;this.extra=o;this.name="BatchError"}};function Mt(){return K.map(e=>W[e]).filter(Boolean)}function Ze(e){let t=W[e];if(!t)throw new G(404,"not_found","batch not found");return t}async function et(e){let t=(e.name??"").trim();if(!t)throw new G(400,"invalid","batch name is required");let n=[...new Set(e.ticketIds??[])];if(n.length===0)throw new G(400,"invalid","a batch needs at least one ticket");let r=new Set(["queued","running","paused"]);for(let I of K){let p=W[I];if(!p||!r.has(p.status))continue;let w=n.find(te=>p.ticketIds.includes(te));if(w){let te=h.find(Qe=>Qe.id===w);throw new G(409,"in_batch",`ticket ${te?.externalIdentifier??w} is already in the active batch "${p.name}"`)}}let s=new Set(n),o,i,c=!1;for(let I of n){let p=h.find(te=>te.id===I);if(!p)throw new G(404,"not_found",`ticket ${I} not found`);if(!J(I))throw new G(409,"not_assigned",`ticket ${p.externalIdentifier} isn't assigned \u2014 assign it before adding it to a batch`);let w=b.find(te=>te.id===p.connectionId);if(!w||w.linkStatus!=="linked"||!w.workspaceId)throw new G(409,"not_linked",`ticket ${p.externalIdentifier}'s connection isn't linked to a workspace`);if(o&&w.workspaceId!==o)throw new G(409,"mixed_workspaces","all tickets in a batch must belong to the same workspace");o=w.workspaceId,i=w.workspaceName??o,(p.dependsOn??[]).some(te=>s.has(te))&&(c=!0)}let d=c?"ordered":"unordered",u=new Date().toISOString(),m=`batch_${++B.batchSeq}`,g={id:m,name:t,workspaceId:o,workspaceName:i,ticketIds:n,mode:d,advanceMode:e.advanceMode??"on_success",stackDependentWork:e.stackDependentWork??d==="ordered",status:"idle",budgetCap:e.budgetCap??null,pausedReason:null,runsStarted:0,createdAt:u,updatedAt:u};return W[m]=g,K.unshift(m),await pe(m),g}async function Zs(e,t){let n=Ze(e);if(n.status!=="idle"&&n.status!=="done")throw new G(409,"active","stop the batch before editing it");if(t.name!==void 0){let r=t.name.trim();if(!r)throw new G(400,"invalid","batch name is required");n.name=r}if(t.ticketIds!==void 0){let r=await et({name:n.name,ticketIds:t.ticketIds,advanceMode:t.advanceMode??n.advanceMode,stackDependentWork:t.stackDependentWork??n.stackDependentWork,budgetCap:t.budgetCap??n.budgetCap});n.ticketIds=r.ticketIds,n.mode=r.mode,n.advanceMode=r.advanceMode,n.stackDependentWork=r.stackDependentWork,n.budgetCap=r.budgetCap,delete W[r.id],K.splice(K.indexOf(r.id),1),await Qt(r.id)}else t.advanceMode!==void 0&&(n.advanceMode=t.advanceMode),t.stackDependentWork!==void 0&&(n.stackDependentWork=t.stackDependentWork),t.budgetCap!==void 0&&(n.budgetCap=t.budgetCap);return n.updatedAt=new Date().toISOString(),await pe(e),n}async function An(e){if(Ze(e).status==="running")throw new G(409,"running","stop the batch before deleting it");delete W[e];let n=K.indexOf(e);n!==-1&&K.splice(n,1),await Qt(e)}Y();var eo=e=>S[e];function Ae(e,t,n={}){ue(e,{batch:{id:t.id,name:t.name,status:t.status,mode:t.mode,ticketCount:t.ticketIds.length},...n},{workspaceId:t.workspaceId})}function Ke(e,t,n){e.status=t,e.pausedReason=n,e.updatedAt=new Date().toISOString(),pe(e.id)}function wr(e,t){let n=eo(e);return n==="done"?!0:t.ticketIds.includes(e)&&t.advanceMode==="on_success"&&n==="in_review"}function nc(e){return e.ticketIds.filter(t=>{let n=J(t);if(!n||n.status!=="not_started")return!1;let r=h.find(s=>s.id===t);return r?(r.dependsOn??[]).every(s=>wr(s,e)):!1})}function to(e){return e.ticketIds.filter(t=>J(t)?.status==="running")}function rc(e){(async()=>{try{let t=await It(e,{autonomy:"autonomous"});if(t.status!=="not_started")return;t.autonomy="autonomous",await Fe(t.id,{skipDepGate:!0})}catch(t){console.error(`batch: failed to start ticket ${e}`,t)}})()}function no(e,t){for(let n of K){let r=W[n];if(r?.ticketIds.includes(e)&&(!t||t(r)))return r}}function sc(e){return no(e,t=>t.status==="running")}function ro(){return K.map(e=>W[e]).find(e=>e?.status==="running")}function He(){if(ro())return;let t=K.map(n=>W[n]).filter(n=>!!n&&n.status==="queued").sort((n,r)=>n.updatedAt.localeCompare(r.updatedAt))[0];t&&(t.runsStarted=0,Ke(t,"running",null),Ae("batch.started",t),Nn(t))}function so(e,t){let n=no(e,i=>i.stackDependentWork&&i.mode==="ordered");if(!n)return{};let r=h.find(i=>i.id===e);if(!r)return{};let s=[];for(let i of r.dependsOn??[]){if(!n.ticketIds.includes(i))continue;let c=J(i)?.worktrees?.find(d=>d.repo===t);c&&s.push(c.branch)}let o=[...new Set(s)];return o.length>1?{ambiguous:o}:o.length===1?{startPoint:o[0]}:{}}function Nn(e){if(e.status!=="running")return;let t=nc(e),n=to(e);if(t.length===0&&n.length===0){let r=e.ticketIds.filter(s=>J(s)?.status==="not_started");if(r.length>0){let s=u=>h.find(m=>m.id===u)?.externalIdentifier??u,o=r[0],i=(h.find(u=>u.id===o)?.dependsOn??[]).filter(u=>!wr(u,e)).map(s),c=r.length>1?` (+${r.length-1} more)`:"",d=i.length?`${s(o)} can't start \u2014 waiting on ${i.join(", ")} (not satisfied in this batch)${c}. Resolve (approve / add to the batch) and Resume.`:`${s(o)} can't start${c}.`;Ke(e,"paused",d),Ae("batch.paused",e,{reason:d,stuck:r}),He();return}Ke(e,"done",null),Ae("batch.completed",e),He();return}for(let r of t){if(e.budgetCap!=null&&e.runsStarted>=e.budgetCap){Ke(e,"paused",`hit the budget cap of ${e.budgetCap} runs`),Ae("batch.paused",e,{reason:e.pausedReason}),He();return}e.runsStarted++,rc(r)}pe(e.id)}function oc(e,t){let n=sc(e);if(!n)return;let s=h.find(o=>o.id===e)?.externalIdentifier??e;t==="blocked"?(Ke(n,"paused",`${s} blocked \u2014 needs input`),Ae("batch.ticket_blocked",n,{ticket:{id:e,key:s}}),Ae("batch.paused",n,{reason:n.pausedReason}),He()):t==="error"?(Ke(n,"paused",`${s} failed`),Ae("batch.paused",n,{reason:n.pausedReason}),He()):Nn(n)}function $t(e){let t=Ze(e),r=t.ticketIds.filter(s=>h.some(o=>o.id===s)).map(s=>{let o=h.find(m=>m.id===s),i=J(s),c=eo(s)??"backlog",d=(o?.dependsOn??[]).filter(m=>!wr(m,t)),u;return c==="in_review"||c==="done"?u="done":i?.status==="running"?u="running":o?.blockedReason?u="blocked":i?.status==="stopped"&&i.stopReason==="error"?u="failed":d.length?u="waiting":u="queued",{ticketId:s,externalIdentifier:o?.externalIdentifier??s,title:o?.title??s,state:u,column:c,unmetDeps:d}});return{batch:t,tickets:r}}async function Bt(e){let t=Ze(e);if(t.status==="running")throw new G(409,"running","batch is already running");let n=ro();return n&&n.id!==e?(Ke(t,"queued",`waiting for "${n.name}" to finish`),t):(t.status!=="paused"&&(t.runsStarted=0),t.status="running",t.pausedReason=null,t.updatedAt=new Date().toISOString(),await pe(e),Ae("batch.started",t),Nn(t),t)}async function Lt(e){let t=Ze(e);if(t.status!=="running")throw new G(409,"not_running","batch isn't running");return t.status="paused",t.pausedReason="paused by you",t.updatedAt=new Date().toISOString(),await pe(e),Ae("batch.paused",t,{reason:t.pausedReason}),He(),t}async function Gt(e){let t=Ze(e),n=t.status==="running";for(let r of to(t)){let s=J(r);s&&await We(s.id).catch(()=>{})}return t.status="idle",t.pausedReason=null,t.updatedAt=new Date().toISOString(),await pe(e),n&&He(),t}function oo(e){let t=new Set(e);return e.some(r=>(h.find(s=>s.id===r)?.dependsOn??[]).some(s=>t.has(s)))?"ordered":"unordered"}async function io(e){delete W[e];let t=K.indexOf(e);t!==-1&&K.splice(t,1),await Qt(e)}async function En(e){for(let t of[...K]){let n=W[t];if(!(!n||!n.ticketIds.includes(e))){if(n.ticketIds=n.ticketIds.filter(r=>r!==e),n.ticketIds.length===0){await io(t);continue}n.mode=oo(n.ticketIds),n.updatedAt=new Date().toISOString(),await pe(t),n.status==="running"&&Nn(n)}}}function ao(){for(let e of[...K]){let t=W[e];if(!t)continue;let n=t.ticketIds.filter(r=>h.some(s=>s.id===r));if(n.length===0){io(e);continue}n.length!==t.ticketIds.length&&(t.ticketIds=n,t.mode=oo(n),pe(e)),t.status==="running"&&Ke(t,"paused","interrupted by a daemon restart \u2014 resume to continue")}He()}Hs(oc);Y();Y();import uo from"express";import ac from"cors";import{createRequire as cc}from"node:module";import{dirname as lo,join as Sr}from"node:path";import{existsSync as dc}from"node:fs";var Cn=["ticket.moved","ticket.blocked","ticket.unblocked","ticket.updated","run.started","run.paused","run.resumed","run.completed","run.failed","run.stopped","schedule.run.started","schedule.run.completed","schedule.run.failed","batch.started","batch.completed","batch.paused","batch.ticket_blocked"];var Q={name:"id",in:"path",required:!0,schema:{type:"string"}},M=[{bearerAuth:[]}],me=(e,t=!0)=>({required:t,content:{"application/json":{schema:e}}}),U=(e,t="Success")=>({description:t,content:{"application/json":{schema:e}}}),v=e=>({$ref:`#/components/schemas/${e}`}),R=e=>({description:e,content:{"application/json":{schema:v("Error")}}});function ic(){let e={};for(let t of Cn)e[t]={post:{summary:`\`${t}\` event`,description:"Delivered to your configured webhook URL. Fixed headers (Content-Type, User-Agent, X-SuperClawd-Event) plus your custom headers; signed with HMAC-SHA256 in X-SuperClawd-Signature (sha256=<hex>) when a signing secret is set.",requestBody:me(v("WebhookEnvelope")),responses:{"2xx":{description:"Acknowledge with any 2xx; non-2xx is retried."}}}};return e}var co={openapi:"3.1.0",info:{title:"SuperClawd Pipelines \u2014 Public API",version:"1.0.0",description:"Key-authenticated HTTP API for board, ticket, and run actions, plus outbound webhooks for ticket and run lifecycle events. Authenticate every request with `Authorization: Bearer <key>` (generate a key in Settings \u2192 API)."},servers:[{url:"/",description:"This Pipelines daemon (public API port)"}],security:M,tags:[{name:"Boards"},{name:"Tickets"},{name:"Notes"},{name:"Questions"},{name:"Runs"},{name:"Batches"}],paths:{"/v1/boards":{get:{tags:["Boards"],summary:"List boards (connections)",security:M,responses:{200:U({type:"array",items:v("Board")},"Boards"),401:R("Missing or invalid API key")}}},"/v1/boards/{id}/tickets":{get:{tags:["Boards"],summary:"List a board's tickets",security:M,parameters:[Q],responses:{200:U({type:"array",items:v("Ticket")},"Tickets"),401:R("Missing or invalid API key")}},post:{tags:["Boards"],summary:"Create a ticket on a Local board",description:"Local-board only (vendor boards import tickets, they don't author them). New tickets land in Backlog.",security:M,parameters:[Q],requestBody:me({type:"object",required:["title"],properties:{title:{type:"string"},description:{type:"string"},priority:{type:"integer",enum:[0,1,2,3,4],description:"0 none \xB7 1 urgent \xB7 2 high \xB7 3 medium \xB7 4 low"},workingDir:{type:"string"},model:{type:"string"},effort:{type:"string"}}}),responses:{201:U(v("Ticket"),"Created ticket"),400:R("Not a local board, or title missing"),404:R("Board not found")}}},"/v1/tickets/{id}":{get:{tags:["Tickets"],summary:"Get a ticket",security:M,parameters:[Q],responses:{200:U(v("Ticket"),"Ticket"),404:R("Ticket not found")}},patch:{tags:["Tickets"],summary:"Update ticket fields",description:"plan/conclusion/additionalContext/blockedReason/workingDir/model/effort apply to any ticket; title/description/priority to local-board tickets only. Setting blockedReason blocks (moves to the Blocked lane); clearing it unblocks (refused while open questions are unresolved).",security:M,parameters:[Q],requestBody:me(v("TicketUpdate")),responses:{200:U(v("Ticket"),"Updated ticket"),404:R("Ticket not found"),409:R("Unresolved open questions block unblocking")}}},"/v1/tickets/{id}/move":{post:{tags:["Tickets"],summary:"Move a ticket to a lane",description:"A blocked ticket can't change lanes until unblocked; Done is only allowed once the ticket's run is stopped.",security:M,parameters:[Q],requestBody:me(v("MoveRequest")),responses:{200:U(v("MoveResult"),"Moved"),400:R("Invalid column"),404:R("Ticket not found"),409:R("Blocked-lane freeze or Done gate")}}},"/v1/tickets/{id}/unblock":{post:{tags:["Tickets"],summary:"Unblock a ticket",description:"Refused while open questions are unresolved. With `resume: true` (and an existing run session) the run re-enters and the card goes to In Progress; otherwise it returns to Backlog.",security:M,parameters:[Q],requestBody:me(v("UnblockRequest"),!1),responses:{200:U(v("UnblockResult"),"Unblocked"),409:R("Not blocked, or unresolved open questions")}}},"/v1/tickets/{id}/notes":{get:{tags:["Notes"],summary:"List a ticket's notes (newest first)",security:M,parameters:[Q],responses:{200:U({type:"array",items:v("Note")},"Notes")}},post:{tags:["Notes"],summary:"Add a note",security:M,parameters:[Q],requestBody:me(v("NoteCreate")),responses:{201:U(v("Note"),"Created"),400:R("Empty note"),404:R("Ticket not found")}}},"/v1/notes/{id}":{patch:{tags:["Notes"],summary:"Edit a note",security:M,parameters:[Q],requestBody:me(v("NoteCreate")),responses:{200:U(v("Note"),"Updated"),404:R("Note not found")}},delete:{tags:["Notes"],summary:"Delete a note",security:M,parameters:[Q],responses:{200:U(v("Ok"),"Deleted"),404:R("Note not found")}}},"/v1/tickets/{id}/questions":{get:{tags:["Questions"],summary:"List a ticket's open questions",security:M,parameters:[Q],responses:{200:U({type:"array",items:v("Question")},"Questions")}},post:{tags:["Questions"],summary:"Add an open question",security:M,parameters:[Q],requestBody:me(v("QuestionCreate")),responses:{201:U(v("Question"),"Created"),400:R("Empty question"),404:R("Ticket not found")}}},"/v1/questions/{id}":{patch:{tags:["Questions"],summary:"Edit a question (text / answer / resolved)",security:M,parameters:[Q],requestBody:me(v("QuestionUpdate")),responses:{200:U(v("Question"),"Updated"),404:R("Question not found")}},delete:{tags:["Questions"],summary:"Delete a question",security:M,parameters:[Q],responses:{200:U(v("Ok"),"Deleted"),404:R("Question not found")}}},"/v1/tickets/{id}/run":{get:{tags:["Runs"],summary:"Get the ticket's run",security:M,parameters:[Q],responses:{200:U(v("Run"),"Run"),404:R("No run for this ticket")}}},"/v1/tickets/{id}/run/{action}":{post:{tags:["Runs"],summary:"Control the run (start | pause | resume | stop)",description:"start creates a run if none exists, then enqueues it. pause kills the process but keeps the session resumable; resume re-enters it; stop marks it stopped and kills it.",security:M,parameters:[Q,{name:"action",in:"path",required:!0,schema:{type:"string",enum:["start","pause","resume","stop"]}}],requestBody:me(v("RunStartRequest"),!1),responses:{200:U(v("Run"),"Run"),400:R("Unknown action"),404:R("No run for this ticket"),409:R("Unmet dependencies (on first start)")}}},"/v1/batches":{get:{tags:["Batches"],summary:"List batches",security:M,responses:{200:U({type:"array",items:v("Batch")},"Batches"),401:R("Missing or invalid API key")}},post:{tags:["Batches"],summary:"Create a batch",description:"A batch is a set of already-assigned tickets you press play on to run unattended. ordered/unordered is derived from the tickets' dependencies. Every ticket must be assigned and share one linked workspace, and can't already be in another active batch.",security:M,requestBody:me({type:"object",required:["name","ticketIds"],properties:{name:{type:"string"},ticketIds:{type:"array",items:{type:"string"}},advanceMode:{type:"string",enum:["on_success","approval"],description:"on_success: a member reaching In Review unblocks the next. approval: dependents wait for Done."},stackDependentWork:{type:"boolean",description:"Ordered batches only: a dependent member branches off its blocker's branch."},budgetCap:{type:["integer","null"],description:"Pause the batch after this many runs (null = no cap)."}}}),responses:{201:U(v("Batch"),"Created batch"),400:R("Invalid (name/tickets missing)"),409:R("A ticket isn't assigned, mixes workspaces, or is already in an active batch")}}},"/v1/batches/{id}":{get:{tags:["Batches"],summary:"Get a batch with its members' live state",security:M,parameters:[Q],responses:{200:U(v("BatchDetail"),"Batch detail"),404:R("Batch not found")}},delete:{tags:["Batches"],summary:"Delete a batch",description:"Removes the batch grouping only \u2014 the tickets and their runs are untouched. A running batch can't be deleted (stop it first).",security:M,parameters:[Q],responses:{200:U(v("Ok"),"Deleted"),404:R("Batch not found"),409:R("Batch is running")}}},"/v1/batches/{id}/{action}":{post:{tags:["Batches"],summary:"Control the batch (start | pause | stop)",description:"start plays or resumes it (queues behind any already-running batch). pause stops starting new members (in-flight runs finish). stop halts it and kills its running members.",security:M,parameters:[Q,{name:"action",in:"path",required:!0,schema:{type:"string",enum:["start","pause","stop"]}}],responses:{200:U(v("Batch"),"Batch"),400:R("Unknown action"),404:R("Batch not found"),409:R("Illegal transition (e.g. already running)")}}}},webhooks:ic(),components:{securitySchemes:{bearerAuth:{type:"http",scheme:"bearer",description:"The API key generated in Settings \u2192 API."}},schemas:{Error:{type:"object",properties:{error:{type:"string"},code:{type:"string"}},required:["error"]},Ok:{type:"object",properties:{ok:{type:"boolean"}}},Board:{type:"object",properties:{id:{type:"string"},provider:{type:"string"},workspaceId:{type:"string"},workspaceName:{type:"string"},linkStatus:{type:"string"},ticketCount:{type:"integer"}}},Ticket:{type:"object",description:"A board ticket (fields vary by provider).",properties:{id:{type:"string"},connectionId:{type:"string"},provider:{type:"string"},externalIdentifier:{type:"string"},title:{type:"string"},description:{type:"string"},column:{type:"string",enum:["backlog","in_progress","needs_input","in_review","done"]},blockedReason:{type:"string",nullable:!0},plan:{type:"string",nullable:!0},conclusion:{type:"string",nullable:!0},additionalContext:{type:"string",nullable:!0},comments:{type:"array",description:"Vendor comments/discussion synced read-only from the provider (oldest\u2192newest).",items:v("TicketComment")}}},TicketComment:{type:"object",description:"A ticket comment synced read-only from the vendor.",properties:{id:{type:"string"},author:{type:"string",nullable:!0},body:{type:"string"},createdAt:{type:"string",format:"date-time",nullable:!0},updatedAt:{type:"string",format:"date-time",nullable:!0}}},TicketUpdate:{type:"object",properties:{title:{type:"string"},description:{type:"string"},priority:{type:"integer",minimum:0,maximum:4},plan:{type:"string"},conclusion:{type:"string"},additionalContext:{type:"string"},blockedReason:{type:"string",nullable:!0,description:"Non-empty blocks; null/empty unblocks."},workingDir:{type:"string"},model:{type:"string"},effort:{type:"string"}}},MoveRequest:{type:"object",required:["column"],properties:{column:{type:"string",enum:["backlog","in_progress","needs_input","in_review","done"]}}},MoveResult:{type:"object",properties:{ticketId:{type:"string"},column:{type:"string"}}},UnblockRequest:{type:"object",properties:{resume:{type:"boolean",description:"Re-enter the existing run session on unblock."}}},UnblockResult:{type:"object",properties:{ticket:v("Ticket"),run:v("Run"),resumed:{type:"boolean"}}},Note:{type:"object",properties:{id:{type:"string"},ticketId:{type:"string"},author:{type:"string",enum:["user","assistant"]},body:{type:"string"},createdAt:{type:"string",format:"date-time"},updatedAt:{type:"string",format:"date-time"}}},NoteCreate:{type:"object",required:["body"],properties:{body:{type:"string",maxLength:5e3},author:{type:"string",enum:["user","assistant"]}}},Question:{type:"object",properties:{id:{type:"string"},ticketId:{type:"string"},question:{type:"string"},answer:{type:"string",nullable:!0},resolved:{type:"boolean"},position:{type:"integer"}}},QuestionCreate:{type:"object",required:["question"],properties:{question:{type:"string",maxLength:5e3}}},QuestionUpdate:{type:"object",properties:{question:{type:"string"},answer:{type:"string",nullable:!0},resolved:{type:"boolean"}}},RunStartRequest:{type:"object",description:"Only used by the `start` action.",properties:{details:{type:"string",description:"Calibration prompt appended to the run's guiding prompt."},attachments:{type:"array",items:{type:"string"},description:"File paths the agent reads from disk."},autonomy:{type:"string",enum:["supervised","autonomous"],description:"Applied only when the run doesn't exist yet; defaults to the workspace setting."}}},Run:{type:"object",properties:{id:{type:"string"},ticketId:{type:"string"},ticketKey:{type:"string"},title:{type:"string"},status:{type:"string",enum:["not_started","running","paused","blocked","stopped"]},stopReason:{type:"string",enum:["completed","user","error"],nullable:!0},workspaceId:{type:"string"}}},WebhookEnvelope:{type:"object",properties:{id:{type:"string",description:"Unique event id (evt_\u2026)."},event:{type:"string"},occurredAt:{type:"string",format:"date-time"},workspaceId:{type:"string"},data:{type:"object",additionalProperties:!0,description:"Event-specific payload (ticketId/runId, changed fields, \u2026)."}},required:["id","event","occurredAt","data"]},Batch:{type:"object",properties:{id:{type:"string"},name:{type:"string"},workspaceId:{type:"string"},workspaceName:{type:"string"},ticketIds:{type:"array",items:{type:"string"}},mode:{type:"string",enum:["ordered","unordered"]},advanceMode:{type:"string",enum:["on_success","approval"]},stackDependentWork:{type:"boolean"},status:{type:"string",enum:["idle","queued","running","paused","done"]},budgetCap:{type:["integer","null"]},pausedReason:{type:["string","null"]},runsStarted:{type:"integer"},createdAt:{type:"string",format:"date-time"},updatedAt:{type:"string",format:"date-time"}}},BatchDetail:{type:"object",properties:{batch:v("Batch"),tickets:{type:"array",items:{type:"object",properties:{ticketId:{type:"string"},externalIdentifier:{type:"string"},title:{type:"string"},state:{type:"string",enum:["done","running","blocked","failed","waiting","queued"]},column:{type:"string"},unmetDeps:{type:"array",items:{type:"string"}}}}}}}}}};function uc(){let e="dist/browser/standalone.js",t=lo(cc(import.meta.url).resolve("@scalar/api-reference"));for(let n=0;n<6;n++){if(dc(Sr(t,e)))return Sr(t,e);t=lo(t)}return Sr(t,e)}var lc=uc(),pc=`<!doctype html>
27
27
  <html>
28
28
  <head>
29
29
  <meta charset="utf-8" />
@@ -61,27 +61,27 @@ ${s.map(i=>`- ${i}`).join(`
61
61
  })();
62
62
  </script>
63
63
  </body>
64
- </html>`,Ns=e=>S[e]??"backlog";function Aa(e,t,n){let r=l.apiKeyHash;if(!r){t.status(401).json({error:"public API key is not configured"});return}let o=/^Bearer\s+(.+)$/i.exec(e.headers.authorization??"")?.[1]?.trim();if(!o||!Rt(Ve(o),r)){t.status(401).json({error:"invalid or missing API key"});return}n()}function oe(e,t){return t instanceof re?e.status(t.status).json({error:t.message,...t.code?{code:t.code}:{},...t.extra??{}}):t instanceof N?e.status(t.status).json({error:t.message,...t.extra??{}}):(console.error("[public-api]",t),e.status(500).json({error:"internal error"}))}function Na(e){let t=cn(e);return t?{...t,column:Ns(t.id)}:null}function Ea(){let e=_s();return e.use(Ia()),e.use(_s.json()),e.get("/openapi.json",(t,n)=>n.json(Ts)),e.get("/docs/scalar.js",(t,n)=>n.sendFile(Ta)),e.get("/docs",(t,n)=>n.type("html").send(_a)),e.use("/v1",Aa),e.get("/v1/boards",(t,n)=>{n.json(y.map(r=>({id:r.id,provider:r.provider,workspaceId:r.workspaceId,workspaceName:r.workspaceName,linkStatus:r.linkStatus,ticketCount:r.ticketCount})))}),e.get("/v1/boards/:id/tickets",(t,n)=>{let r=h.filter(s=>s.connectionId===t.params.id).map(s=>({...s,column:Ns(s.id)}));n.json(r)}),e.post("/v1/boards/:id/tickets",async(t,n)=>{try{return n.status(201).json(await gt(t.params.id,t.body??{}))}catch(r){return oe(n,r)}}),e.get("/v1/tickets/:id",(t,n)=>{let r=Na(t.params.id);return r?n.json(r):n.status(404).json({error:"ticket not found"})}),e.post("/v1/tickets/:id/move",async(t,n)=>{try{return n.json(await ft(t.params.id,t.body?.column))}catch(r){return oe(n,r)}}),e.patch("/v1/tickets/:id",async(t,n)=>{try{return n.json(await Ie(t.params.id,t.body??{}))}catch(r){return oe(n,r)}}),e.post("/v1/tickets/:id/unblock",async(t,n)=>{try{return n.json(await mt(t.params.id,{resume:t.body?.resume===!0}))}catch(r){return oe(n,r)}}),e.get("/v1/tickets/:id/notes",(t,n)=>{n.json(lt(t.params.id))}),e.post("/v1/tickets/:id/notes",async(t,n)=>{try{let r=await ht(t.params.id,{body:String(t.body?.body??""),author:t.body?.author});return n.status(201).json(r)}catch(r){return oe(n,r)}}),e.patch("/v1/notes/:id",async(t,n)=>{try{return n.json(await kt(t.params.id,String(t.body?.body??"")))}catch(r){return oe(n,r)}}),e.delete("/v1/notes/:id",async(t,n)=>{try{return await yt(t.params.id),n.json({ok:!0})}catch(r){return oe(n,r)}}),e.get("/v1/tickets/:id/questions",(t,n)=>{n.json(pt(t.params.id))}),e.post("/v1/tickets/:id/questions",async(t,n)=>{try{let r=await wt(t.params.id,String(t.body?.question??""));return n.status(201).json(r)}catch(r){return oe(n,r)}}),e.patch("/v1/questions/:id",async(t,n)=>{try{return n.json(await bt(t.params.id,t.body??{}))}catch(r){return oe(n,r)}}),e.delete("/v1/questions/:id",async(t,n)=>{try{return await St(t.params.id),n.json({ok:!0})}catch(r){return oe(n,r)}}),e.get("/v1/tickets/:id/run",(t,n)=>{let r=Se(t.params.id);return r?n.json(r):n.status(404).json({error:"no run for this ticket"})}),e.post("/v1/tickets/:id/run/:action",async(t,n)=>{let r=t.params.action;try{if(r==="start"){let o=t.body?.autonomy,i=await an(t.params.id,o==="supervised"||o==="autonomous"?{autonomy:o}:{});return n.json(await at(i.id,{details:String(t.body?.details??""),attachments:Array.isArray(t.body?.attachments)?t.body.attachments.map(c=>String(c)):[]}))}let s=Se(t.params.id);return s?r==="pause"?n.json(await ct(s.id)):r==="resume"?n.json(await dt(s.id)):r==="stop"?n.json(await ut(s.id)):n.status(400).json({error:"unknown action (use start | pause | resume | stop)"}):n.status(404).json({error:"no run for this ticket"})}catch(s){return oe(n,s)}}),e}var Ot=null;function Es(){return Ot!==null}function un(e){if(Ot)return;Ot=Ea().listen(e,()=>{console.log(`[pipelines] public API ready http://localhost:${e}/v1`)})}async function Cs(){let e=Ot;e&&(Ot=null,await new Promise(t=>e.close(()=>t())),console.log("[pipelines] public API stopped"))}var ln=Number(process.env.PIPELINES_PUBLIC_API_PORT||63211),Ps=4,Ca=/^[a-zA-Z0-9-]+$/,Pa=new Set(["host","content-length","content-type","user-agent","x-superclawd-event","x-superclawd-signature","transfer-encoding","connection"]),xe=class extends Error{constructor(n,r){super(r);this.status=n;this.name="ApiSettingsError"}};function Dt(){let e=l;return{publicApiEnabled:!!e.publicApiEnabled,port:ln,running:Es(),apiKey:e.apiKeyHash?{last4:e.apiKeyLast4??"",createdAt:e.apiKeyCreatedAt??null}:null,webhook:{enabled:!!e.webhookEnabled,url:e.webhookUrl??"",headers:e.webhookHeaders??[],events:e.webhookEvents??[],hasSecret:!!e.webhookSecret}}}async function Os(e){return l.publicApiEnabled=e,await X(),e?un(ln):await Cs(),Dt()}async function Ds(){let e=Ze("sck_",32);return l.apiKeyHash=Ve(e),l.apiKeyLast4=e.slice(-4),l.apiKeyCreatedAt=new Date().toISOString(),await X(),{key:e}}async function js(){return l.apiKeyHash=void 0,l.apiKeyLast4=void 0,l.apiKeyCreatedAt=void 0,await X(),Dt()}async function $s(e){let t=l;if(e.url!==void 0){let n=String(e.url??"").trim();if(n&&!/^https?:\/\//i.test(n))throw new xe(400,"webhook URL must start with http:// or https://");t.webhookUrl=n||void 0}if(e.headers!==void 0){let n=(e.headers??[]).filter(r=>r&&r.key);if(n.length>Ps)throw new xe(400,`at most ${Ps} custom headers`);for(let r of n){if(!Ca.test(r.key)||r.key.length>64)throw new xe(400,`invalid header name: ${r.key}`);if(Pa.has(r.key.toLowerCase()))throw new xe(400,`header not allowed: ${r.key}`);if(String(r.value??"").length>512)throw new xe(400,`header value too long: ${r.key}`)}t.webhookHeaders=n.map(r=>({key:r.key,value:String(r.value??"")}))}if(e.events!==void 0){let n=new Set(dn);t.webhookEvents=(e.events??[]).filter(r=>n.has(r))}return e.enabled!==void 0&&(t.webhookEnabled=!!e.enabled),t.webhookEnabled&&!t.webhookSecret&&(t.webhookSecret=Ze("whsec_",32)),await X(),Dt()}async function Ms(){let e=Ze("whsec_",32);return l.webhookSecret=e,await X(),{secret:e}}async function Ls(){return ys()}V();import Yn from"node:fs";import Da from"node:os";import Us from"node:path";import{McpServer as ja}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as $a}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as b}from"zod";var Bs=process.env.SUPERCLAWD_HOME||Us.join(Da.homedir(),".superclawd"),qs=Us.join(Bs,"pipelines-mcp.json"),pn=null;function Fs(){if(pn)return pn;try{let e=JSON.parse(Yn.readFileSync(qs,"utf8"));if(typeof e?.token=="string"&&e.token)return pn=e.token}catch{}return pn=Ze("scpmcp_")}function Ma(e){Yn.mkdirSync(Bs,{recursive:!0}),Yn.writeFileSync(qs,JSON.stringify({port:e,token:Fs()}),{mode:384})}var Gs=e=>S[e]??"backlog";function Xn(e,t,n){let s=/^Bearer\s+(.+)$/i.exec(e.headers.authorization??"")?.[1]?.trim();if(s){if(Rt(s,Fs()))return n();let o=l.apiKeyHash;if(o&&Rt(Ve(s),o))return n()}t.status(401).json({error:"invalid or missing MCP token"})}var D=e=>({content:[{type:"text",text:JSON.stringify(e,null,2)}]}),Be=e=>({isError:!0,content:[{type:"text",text:e}]});function W(e){return e instanceof re||e instanceof N?Be(e.message):(console.error("[pipelines-mcp]",e),Be("internal error"))}function La(){let e=new ja({name:"superclawd-pipelines",version:"0.1.0"});return e.tool("list_boards","List the connected boards (one per project-management connection in the active workspace).",{},async()=>D(y.map(t=>({id:t.id,provider:t.provider,workspaceId:t.workspaceId,workspaceName:t.workspaceName,linkStatus:t.linkStatus,ticketCount:t.ticketCount})))),e.tool("list_tickets","List the tickets on a board, with each ticket's current board column.",{boardId:b.string().describe("The board (connection) id from list_boards")},async({boardId:t})=>D(h.filter(n=>n.connectionId===t).map(n=>({...n,column:Gs(n.id)})))),e.tool("get_ticket","Get a single ticket (full fields + its current board column).",{ticketId:b.string()},async({ticketId:t})=>{let n=cn(t);return n?D({...n,column:Gs(n.id)}):Be("ticket not found")}),e.tool("create_ticket","Create a ticket on a Local board (vendor boards import tickets, so boardId must be a local board \u2014 see list_boards). New tickets land in Backlog.",{boardId:b.string().describe("A local board id from list_boards"),title:b.string(),description:b.string().optional(),priority:b.number().int().min(0).max(4).optional().describe("0 none \xB7 1 urgent \xB7 2 high \xB7 3 medium \xB7 4 low")},async({boardId:t,title:n,description:r,priority:s})=>{try{return D(await gt(t,{title:n,description:r,priority:s}))}catch(o){return W(o)}}),e.tool("update_ticket","Update a ticket's editable fields. title/description/priority apply to Local-board tickets only; workingDir/model/effort apply to any ticket. (Use set_plan/set_conclusion/block_ticket for those.)",{ticketId:b.string(),title:b.string().optional(),description:b.string().optional(),priority:b.number().int().min(0).max(4).optional(),workingDir:b.string().optional(),model:b.string().optional(),effort:b.string().optional()},async({ticketId:t,...n})=>{let r={};for(let[s,o]of Object.entries(n))o!==void 0&&(r[s]=o);try{return D(await Ie(t,r))}catch(s){return W(s)}}),e.tool("move_ticket","Move a ticket to a board column (backlog | in_progress | needs_input | in_review | done). Blocked tickets can't move until unblocked; Done requires a stopped run.",{ticketId:b.string(),column:b.string()},async({ticketId:t,column:n})=>{try{return D(await ft(t,n))}catch(r){return W(r)}}),e.tool("add_note","Add a freeform note to a ticket.",{ticketId:b.string(),body:b.string()},async({ticketId:t,body:n})=>{try{return D(await ht(t,{body:n}))}catch(r){return W(r)}}),e.tool("list_notes","List a ticket's notes (newest first), each with its id + author.",{ticketId:b.string()},async({ticketId:t})=>D(lt(t))),e.tool("edit_note","Edit a note's body.",{noteId:b.string(),body:b.string()},async({noteId:t,body:n})=>{try{return D(await kt(t,n))}catch(r){return W(r)}}),e.tool("delete_note","Delete a note.",{noteId:b.string()},async({noteId:t})=>{try{return await yt(t),D({ok:!0})}catch(n){return W(n)}}),e.tool("set_plan","Set (replace) a ticket's plan \u2014 the intended approach for the task (markdown).",{ticketId:b.string(),plan:b.string()},async({ticketId:t,plan:n})=>{try{return D(await Ie(t,{plan:n}))}catch(r){return W(r)}}),e.tool("set_conclusion","Set (replace) a ticket's conclusion \u2014 the wrap-up / findings (markdown).",{ticketId:b.string(),conclusion:b.string()},async({ticketId:t,conclusion:n})=>{try{return D(await Ie(t,{conclusion:n}))}catch(r){return W(r)}}),e.tool("block_ticket","Block a ticket with a reason \u2014 moves it to the Blocked lane until it's unblocked.",{ticketId:b.string(),reason:b.string()},async({ticketId:t,reason:n})=>{try{return D(await Ie(t,{blockedReason:n}))}catch(r){return W(r)}}),e.tool("unblock_ticket","Unblock a ticket. Set resume=true to resume its saved run; otherwise it returns to Backlog. Fails if the ticket has unresolved open questions.",{ticketId:b.string(),resume:b.boolean().optional()},async({ticketId:t,resume:n})=>{try{return D(await mt(t,{resume:n===!0}))}catch(r){return W(r)}}),e.tool("add_question","Add an open question to a ticket \u2014 a decision or blocker that needs a human answer.",{ticketId:b.string(),question:b.string()},async({ticketId:t,question:n})=>{try{return D(await wt(t,n))}catch(r){return W(r)}}),e.tool("list_questions","List a ticket's open questions (each with its answer + resolved state).",{ticketId:b.string()},async({ticketId:t})=>D(pt(t))),e.tool("update_question","Update an open question \u2014 set its answer, mark it resolved (or reopen it), and/or edit its text. All open questions must be resolved before a ticket can be unblocked.",{questionId:b.string(),question:b.string().optional(),answer:b.string().optional(),resolved:b.boolean().optional()},async({questionId:t,question:n,answer:r,resolved:s})=>{let o={};n!==void 0&&(o.question=n),r!==void 0&&(o.answer=r),s!==void 0&&(o.resolved=s);try{return D(await bt(t,o))}catch(i){return W(i)}}),e.tool("delete_question","Delete an open question from a ticket.",{questionId:b.string()},async({questionId:t})=>{try{return await St(t),D({ok:!0})}catch(n){return W(n)}}),e.tool("start_run","Start (or resume) a run on a ticket. `autonomy` (supervised | autonomous) applies only when a run doesn't exist yet; `details` is optional calibration text.",{ticketId:b.string(),details:b.string().optional(),autonomy:b.enum(["supervised","autonomous"]).optional()},async({ticketId:t,details:n,autonomy:r})=>{try{let s=await an(t,r?{autonomy:r}:{});return D(await at(s.id,{details:n??"",attachments:[]}))}catch(s){return W(s)}}),e.tool("pause_run","Pause the active run on a ticket \u2014 kills the process but keeps the session resumable.",{ticketId:b.string()},async({ticketId:t})=>{let n=Se(t);if(!n)return Be("no run for this ticket");try{return D(await ct(n.id))}catch(r){return W(r)}}),e.tool("stop_run","Stop the active run on a ticket.",{ticketId:b.string()},async({ticketId:t})=>{let n=Se(t);if(!n)return Be("no run for this ticket");try{return D(await ut(n.id))}catch(r){return W(r)}}),e.tool("resume_run","Resume a stopped or paused run on a ticket (re-enters the same session).",{ticketId:b.string()},async({ticketId:t})=>{let n=Se(t);if(!n)return Be("no run for this ticket");try{return D(await dt(n.id))}catch(r){return W(r)}}),e.tool("get_run_status","Get the current run for a ticket (session status, stop reason, model/effort, latest result).",{ticketId:b.string()},async({ticketId:t})=>{let n=Se(t);return n?D(n):Be("no run for this ticket")}),e}function Ws(e,t){Ma(t),e.post("/mcp",Xn,async(r,s)=>{let o=La(),i=new $a({sessionIdGenerator:void 0});s.on("close",()=>{i.close(),o.close()});try{await o.connect(i),await i.handleRequest(r,s,r.body)}catch(c){console.error("[pipelines-mcp] request error",c),s.headersSent||s.status(500).json({error:"internal error"})}});let n=(r,s)=>s.status(405).json({error:"method not allowed"});e.get("/mcp",Xn,n),e.delete("/mcp",Xn,n),console.log("[pipelines] MCP endpoint ready at /mcp")}V();import{randomUUID as Fa}from"node:crypto";import{homedir as Ga}from"node:os";var fn=["You are running in a RESTRICTED context (a schedule or conversation), not a board task.","You may read, investigate, analyze, run read-only commands, write non-code files (reports, notes) in non-git folders, and file board tickets with create_ticket.","You must NOT modify code or write into any git repository \u2014 there is no worktree here and repo writes are blocked. If a code change is warranted, create a board ticket describing exactly what to change (which repo, files, and why); the work happens on the board."].join(`
65
- `);async function mn(e){if(!e)return[];let t=Et(e);return t===Ga()?[]:(await De(t)).map(n=>n.path)}var Ba={min:6e4,minute:6e4,minutes:6e4,hour:36e5,hours:36e5,hr:36e5,hrs:36e5,day:864e5,days:864e5,week:6048e5,weeks:6048e5};function qa(e){let t=e.trim().toLowerCase();if(t==="hourly")return 36e5;if(t==="daily")return 864e5;if(t==="weekly")return 6048e5;let n=/every\s+(\d+)?\s*([a-z]+)/.exec(t);if(n){let r=n[1]?parseInt(n[1],10):1,s=Ba[n[2]];if(s&&r>0)return Math.max(6e4,r*s)}return 36e5}function jt(e,t){return new Date(e+qa(t)).toISOString()}var Wa=3e4,gn=new Set,Vn=null;async function Zn(e,t=!0){let n=E[e];if(!n||gn.has(e))return null;gn.add(e);let r=++L.schedRunSeq,s={id:`srun_${r}`,scheduleId:e,status:"running",sessionId:Fa(),startedAt:new Date().toISOString(),finishedAt:null,output:"",model:n.model||l.defaultModel||ce,effort:n.effort||l.defaultEffort||de};return(B[e]??=[]).unshift(s),n.lastRunAt=s.startedAt,t&&(n.nextRunAt=jt(Date.now(),n.cadence)),await Kt(s,r),await _t(e),ue("schedule.run.started",{scheduleId:e,scheduleRunId:s.id,scheduleName:n.name,status:s.status},{workspaceId:n.workspaceId}),Ka(n,s,r),s}async function Ka(e,t,n){try{if(_())t.output=`Ran "${e.name}" on its ${e.cadence} cadence. (mock output)`,t.status="success";else{let r=e.workingDir??l.workspaceDirs?.[e.workspaceId]??"~",s=await Ue({prompt:`${fn}
64
+ </html>`,po=e=>S[e]??"backlog";function fc(e,t,n){let r=l.apiKeyHash;if(!r){t.status(401).json({error:"public API key is not configured"});return}let o=/^Bearer\s+(.+)$/i.exec(e.headers.authorization??"")?.[1]?.trim();if(!o||!Kt(ft(o),r)){t.status(401).json({error:"invalid or missing API key"});return}n()}function Z(e,t){return t instanceof le?e.status(t.status).json({error:t.message,...t.code?{code:t.code}:{},...t.extra??{}}):t instanceof P?e.status(t.status).json({error:t.message,...t.extra??{}}):t instanceof G?e.status(t.status).json({error:t.message,...t.code?{code:t.code}:{},...t.extra??{}}):(console.error("[public-api]",t),e.status(500).json({error:"internal error"}))}function mc(e){let t=_n(e);return t?{...t,column:po(t.id)}:null}function gc(){let e=uo();return e.use(ac()),e.use(uo.json()),e.get("/openapi.json",(t,n)=>n.json(co)),e.get("/docs/scalar.js",(t,n)=>n.sendFile(lc)),e.get("/docs",(t,n)=>n.type("html").send(pc)),e.use("/v1",fc),e.get("/v1/boards",(t,n)=>{n.json(b.map(r=>({id:r.id,provider:r.provider,workspaceId:r.workspaceId,workspaceName:r.workspaceName,linkStatus:r.linkStatus,ticketCount:r.ticketCount})))}),e.get("/v1/boards/:id/tickets",(t,n)=>{let r=h.filter(s=>s.connectionId===t.params.id).map(s=>({...s,column:po(s.id)}));n.json(r)}),e.post("/v1/boards/:id/tickets",async(t,n)=>{try{return n.status(201).json(await Nt(t.params.id,t.body??{}))}catch(r){return Z(n,r)}}),e.get("/v1/tickets/:id",(t,n)=>{let r=mc(t.params.id);return r?n.json(r):n.status(404).json({error:"ticket not found"})}),e.post("/v1/tickets/:id/move",async(t,n)=>{try{return n.json(await _t(t.params.id,t.body?.column))}catch(r){return Z(n,r)}}),e.patch("/v1/tickets/:id",async(t,n)=>{try{return n.json(await _e(t.params.id,t.body??{}))}catch(r){return Z(n,r)}}),e.post("/v1/tickets/:id/unblock",async(t,n)=>{try{return n.json(await At(t.params.id,{resume:t.body?.resume===!0}))}catch(r){return Z(n,r)}}),e.get("/v1/tickets/:id/notes",(t,n)=>{n.json(Rt(t.params.id))}),e.post("/v1/tickets/:id/notes",async(t,n)=>{try{let r=await Et(t.params.id,{body:String(t.body?.body??""),author:t.body?.author});return n.status(201).json(r)}catch(r){return Z(n,r)}}),e.patch("/v1/notes/:id",async(t,n)=>{try{return n.json(await Ct(t.params.id,String(t.body?.body??"")))}catch(r){return Z(n,r)}}),e.delete("/v1/notes/:id",async(t,n)=>{try{return await Pt(t.params.id),n.json({ok:!0})}catch(r){return Z(n,r)}}),e.get("/v1/tickets/:id/questions",(t,n)=>{n.json(Tt(t.params.id))}),e.post("/v1/tickets/:id/questions",async(t,n)=>{try{let r=await Ot(t.params.id,String(t.body?.question??""));return n.status(201).json(r)}catch(r){return Z(n,r)}}),e.patch("/v1/questions/:id",async(t,n)=>{try{return n.json(await Dt(t.params.id,t.body??{}))}catch(r){return Z(n,r)}}),e.delete("/v1/questions/:id",async(t,n)=>{try{return await jt(t.params.id),n.json({ok:!0})}catch(r){return Z(n,r)}}),e.get("/v1/tickets/:id/run",(t,n)=>{let r=J(t.params.id);return r?n.json(r):n.status(404).json({error:"no run for this ticket"})}),e.post("/v1/tickets/:id/run/:action",async(t,n)=>{let r=t.params.action;try{if(r==="start"){let o=t.body?.autonomy,i=await It(t.params.id,o==="supervised"||o==="autonomous"?{autonomy:o}:{});return n.json(await Fe(i.id,{details:String(t.body?.details??""),attachments:Array.isArray(t.body?.attachments)?t.body.attachments.map(c=>String(c)):[]}))}let s=J(t.params.id);return s?r==="pause"?n.json(await xt(s.id)):r==="resume"?n.json(await vt(s.id)):r==="stop"?n.json(await We(s.id)):n.status(400).json({error:"unknown action (use start | pause | resume | stop)"}):n.status(404).json({error:"no run for this ticket"})}catch(s){return Z(n,s)}}),e.get("/v1/batches",(t,n)=>{n.json(Mt())}),e.get("/v1/batches/:id",(t,n)=>{try{return n.json($t(t.params.id))}catch(r){return Z(n,r)}}),e.post("/v1/batches",async(t,n)=>{try{let r=await et({name:String(t.body?.name??""),ticketIds:Array.isArray(t.body?.ticketIds)?t.body.ticketIds.map(s=>String(s)):[],advanceMode:t.body?.advanceMode==="approval"?"approval":"on_success",stackDependentWork:t.body?.stackDependentWork!==!1,budgetCap:typeof t.body?.budgetCap=="number"?t.body.budgetCap:null});return n.status(201).json(r)}catch(r){return Z(n,r)}}),e.post("/v1/batches/:id/:action",async(t,n)=>{let{id:r,action:s}=t.params;try{return s==="start"?n.json(await Bt(r)):s==="pause"?n.json(await Lt(r)):s==="stop"?n.json(await Gt(r)):n.status(400).json({error:"unknown action (use start | pause | stop)"})}catch(o){return Z(n,o)}}),e.delete("/v1/batches/:id",async(t,n)=>{try{return await An(t.params.id),n.json({ok:!0})}catch(r){return Z(n,r)}}),e}var en=null;function fo(){return en!==null}function Pn(e){if(en)return;en=gc().listen(e,()=>{console.log(`[pipelines] public API ready http://localhost:${e}/v1`)})}async function mo(){let e=en;e&&(en=null,await new Promise(t=>e.close(()=>t())),console.log("[pipelines] public API stopped"))}var On=Number(process.env.PIPELINES_PUBLIC_API_PORT||63211),go=4,hc=/^[a-zA-Z0-9-]+$/,kc=new Set(["host","content-length","content-type","user-agent","x-superclawd-event","x-superclawd-signature","transfer-encoding","connection"]),Ne=class extends Error{constructor(n,r){super(r);this.status=n;this.name="ApiSettingsError"}};function tn(){let e=l;return{publicApiEnabled:!!e.publicApiEnabled,port:On,running:fo(),apiKey:e.apiKeyHash?{last4:e.apiKeyLast4??"",createdAt:e.apiKeyCreatedAt??null}:null,webhook:{enabled:!!e.webhookEnabled,url:e.webhookUrl??"",headers:e.webhookHeaders??[],events:e.webhookEvents??[],hasSecret:!!e.webhookSecret}}}async function ho(e){return l.publicApiEnabled=e,await se(),e?Pn(On):await mo(),tn()}async function ko(){let e=mt("sck_",32);return l.apiKeyHash=ft(e),l.apiKeyLast4=e.slice(-4),l.apiKeyCreatedAt=new Date().toISOString(),await se(),{key:e}}async function yo(){return l.apiKeyHash=void 0,l.apiKeyLast4=void 0,l.apiKeyCreatedAt=void 0,await se(),tn()}async function wo(e){let t=l;if(e.url!==void 0){let n=String(e.url??"").trim();if(n&&!/^https?:\/\//i.test(n))throw new Ne(400,"webhook URL must start with http:// or https://");t.webhookUrl=n||void 0}if(e.headers!==void 0){let n=(e.headers??[]).filter(r=>r&&r.key);if(n.length>go)throw new Ne(400,`at most ${go} custom headers`);for(let r of n){if(!hc.test(r.key)||r.key.length>64)throw new Ne(400,`invalid header name: ${r.key}`);if(kc.has(r.key.toLowerCase()))throw new Ne(400,`header not allowed: ${r.key}`);if(String(r.value??"").length>512)throw new Ne(400,`header value too long: ${r.key}`)}t.webhookHeaders=n.map(r=>({key:r.key,value:String(r.value??"")}))}if(e.events!==void 0){let n=new Set(Cn);t.webhookEvents=(e.events??[]).filter(r=>n.has(r))}return e.enabled!==void 0&&(t.webhookEnabled=!!e.enabled),t.webhookEnabled&&!t.webhookSecret&&(t.webhookSecret=mt("whsec_",32)),await se(),tn()}async function bo(){let e=mt("whsec_",32);return l.webhookSecret=e,await se(),{secret:e}}async function So(){return Ws()}Y();import xr from"node:fs";import wc from"node:os";import xo from"node:path";import{McpServer as bc}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Sc}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as y}from"zod";var vo=process.env.SUPERCLAWD_HOME||xo.join(wc.homedir(),".superclawd"),Ro=xo.join(vo,"pipelines-mcp.json"),Dn=null;function To(){if(Dn)return Dn;try{let e=JSON.parse(xr.readFileSync(Ro,"utf8"));if(typeof e?.token=="string"&&e.token)return Dn=e.token}catch{}return Dn=mt("scpmcp_")}function Ic(e){xr.mkdirSync(vo,{recursive:!0}),xr.writeFileSync(Ro,JSON.stringify({port:e,token:To()}),{mode:384})}var Io=e=>S[e]??"backlog";function Ir(e,t,n){let s=/^Bearer\s+(.+)$/i.exec(e.headers.authorization??"")?.[1]?.trim();if(s){if(Kt(s,To()))return n();let o=l.apiKeyHash;if(o&&Kt(ft(s),o))return n()}t.status(401).json({error:"invalid or missing MCP token"})}var _=e=>({content:[{type:"text",text:JSON.stringify(e,null,2)}]}),tt=e=>({isError:!0,content:[{type:"text",text:e}]});function q(e){return e instanceof le||e instanceof P||e instanceof G?tt(e.message):(console.error("[pipelines-mcp]",e),tt("internal error"))}function xc(){let e=new bc({name:"superclawd-pipelines",version:"0.1.0"});return e.tool("list_boards","List the connected boards (one per project-management connection in the active workspace).",{},async()=>_(b.map(t=>({id:t.id,provider:t.provider,workspaceId:t.workspaceId,workspaceName:t.workspaceName,linkStatus:t.linkStatus,ticketCount:t.ticketCount})))),e.tool("list_tickets","List the tickets on a board, with each ticket's current board column.",{boardId:y.string().describe("The board (connection) id from list_boards")},async({boardId:t})=>_(h.filter(n=>n.connectionId===t).map(n=>({...n,column:Io(n.id)})))),e.tool("get_ticket","Get a single ticket (full fields + its current board column).",{ticketId:y.string()},async({ticketId:t})=>{let n=_n(t);return n?_({...n,column:Io(n.id)}):tt("ticket not found")}),e.tool("create_ticket","Create a ticket on a Local board (vendor boards import tickets, so boardId must be a local board \u2014 see list_boards). New tickets land in Backlog.",{boardId:y.string().describe("A local board id from list_boards"),title:y.string(),description:y.string().optional(),priority:y.number().int().min(0).max(4).optional().describe("0 none \xB7 1 urgent \xB7 2 high \xB7 3 medium \xB7 4 low")},async({boardId:t,title:n,description:r,priority:s})=>{try{return _(await Nt(t,{title:n,description:r,priority:s}))}catch(o){return q(o)}}),e.tool("update_ticket","Update a ticket's editable fields. title/description/priority apply to Local-board tickets only; workingDir/model/effort apply to any ticket. (Use set_plan/set_conclusion/block_ticket for those.)",{ticketId:y.string(),title:y.string().optional(),description:y.string().optional(),priority:y.number().int().min(0).max(4).optional(),workingDir:y.string().optional(),model:y.string().optional(),effort:y.string().optional()},async({ticketId:t,...n})=>{let r={};for(let[s,o]of Object.entries(n))o!==void 0&&(r[s]=o);try{return _(await _e(t,r))}catch(s){return q(s)}}),e.tool("move_ticket","Move a ticket to a board column (backlog | in_progress | needs_input | in_review | done). Blocked tickets can't move until unblocked; Done requires a stopped run.",{ticketId:y.string(),column:y.string()},async({ticketId:t,column:n})=>{try{return _(await _t(t,n))}catch(r){return q(r)}}),e.tool("add_note","Add a freeform note to a ticket.",{ticketId:y.string(),body:y.string()},async({ticketId:t,body:n})=>{try{return _(await Et(t,{body:n}))}catch(r){return q(r)}}),e.tool("list_notes","List a ticket's notes (newest first), each with its id + author.",{ticketId:y.string()},async({ticketId:t})=>_(Rt(t))),e.tool("edit_note","Edit a note's body.",{noteId:y.string(),body:y.string()},async({noteId:t,body:n})=>{try{return _(await Ct(t,n))}catch(r){return q(r)}}),e.tool("delete_note","Delete a note.",{noteId:y.string()},async({noteId:t})=>{try{return await Pt(t),_({ok:!0})}catch(n){return q(n)}}),e.tool("set_plan","Set (replace) a ticket's plan \u2014 the intended approach for the task (markdown).",{ticketId:y.string(),plan:y.string()},async({ticketId:t,plan:n})=>{try{return _(await _e(t,{plan:n}))}catch(r){return q(r)}}),e.tool("set_conclusion","Set (replace) a ticket's conclusion \u2014 the wrap-up / findings (markdown).",{ticketId:y.string(),conclusion:y.string()},async({ticketId:t,conclusion:n})=>{try{return _(await _e(t,{conclusion:n}))}catch(r){return q(r)}}),e.tool("block_ticket","Block a ticket with a reason \u2014 moves it to the Blocked lane until it's unblocked.",{ticketId:y.string(),reason:y.string()},async({ticketId:t,reason:n})=>{try{return _(await _e(t,{blockedReason:n}))}catch(r){return q(r)}}),e.tool("unblock_ticket","Unblock a ticket. Set resume=true to resume its saved run; otherwise it returns to Backlog. Fails if the ticket has unresolved open questions.",{ticketId:y.string(),resume:y.boolean().optional()},async({ticketId:t,resume:n})=>{try{return _(await At(t,{resume:n===!0}))}catch(r){return q(r)}}),e.tool("add_question","Add an open question to a ticket \u2014 a decision or blocker that needs a human answer.",{ticketId:y.string(),question:y.string()},async({ticketId:t,question:n})=>{try{return _(await Ot(t,n))}catch(r){return q(r)}}),e.tool("list_questions","List a ticket's open questions (each with its answer + resolved state).",{ticketId:y.string()},async({ticketId:t})=>_(Tt(t))),e.tool("update_question","Update an open question \u2014 set its answer, mark it resolved (or reopen it), and/or edit its text. All open questions must be resolved before a ticket can be unblocked.",{questionId:y.string(),question:y.string().optional(),answer:y.string().optional(),resolved:y.boolean().optional()},async({questionId:t,question:n,answer:r,resolved:s})=>{let o={};n!==void 0&&(o.question=n),r!==void 0&&(o.answer=r),s!==void 0&&(o.resolved=s);try{return _(await Dt(t,o))}catch(i){return q(i)}}),e.tool("delete_question","Delete an open question from a ticket.",{questionId:y.string()},async({questionId:t})=>{try{return await jt(t),_({ok:!0})}catch(n){return q(n)}}),e.tool("start_run","Start (or resume) a run on a ticket. `autonomy` (supervised | autonomous) applies only when a run doesn't exist yet; `details` is optional calibration text.",{ticketId:y.string(),details:y.string().optional(),autonomy:y.enum(["supervised","autonomous"]).optional()},async({ticketId:t,details:n,autonomy:r})=>{try{let s=await It(t,r?{autonomy:r}:{});return _(await Fe(s.id,{details:n??"",attachments:[]}))}catch(s){return q(s)}}),e.tool("pause_run","Pause the active run on a ticket \u2014 kills the process but keeps the session resumable.",{ticketId:y.string()},async({ticketId:t})=>{let n=J(t);if(!n)return tt("no run for this ticket");try{return _(await xt(n.id))}catch(r){return q(r)}}),e.tool("stop_run","Stop the active run on a ticket.",{ticketId:y.string()},async({ticketId:t})=>{let n=J(t);if(!n)return tt("no run for this ticket");try{return _(await We(n.id))}catch(r){return q(r)}}),e.tool("resume_run","Resume a stopped or paused run on a ticket (re-enters the same session).",{ticketId:y.string()},async({ticketId:t})=>{let n=J(t);if(!n)return tt("no run for this ticket");try{return _(await vt(n.id))}catch(r){return q(r)}}),e.tool("get_run_status","Get the current run for a ticket (session status, stop reason, model/effort, latest result).",{ticketId:y.string()},async({ticketId:t})=>{let n=J(t);return n?_(n):tt("no run for this ticket")}),e.tool("list_batches","List the batches (sets of assigned tickets that run unattended), with each batch's status.",{},async()=>_(Mt())),e.tool("get_batch","Get a batch and each member ticket's live state (done | running | blocked | failed | waiting | queued) plus unmet dependencies.",{batchId:y.string()},async({batchId:t})=>{try{return _($t(t))}catch(n){return q(n)}}),e.tool("create_batch","Create a batch from a set of already-assigned tickets (each must be assigned and share one workspace). Ordered vs. unordered is derived from the tickets' dependencies. Does NOT start it \u2014 call start_batch.",{name:y.string(),ticketIds:y.array(y.string()).describe("The assigned tickets to batch"),advanceMode:y.enum(["on_success","approval"]).optional().describe("on_success (default): a member reaching In Review unblocks the next. approval: dependents wait for Done."),stackDependentWork:y.boolean().optional().describe("Ordered batches only: a dependent member branches off its blocker's branch (default true)."),budgetCap:y.number().int().min(1).optional().describe("Pause the batch after this many runs.")},async({name:t,ticketIds:n,advanceMode:r,stackDependentWork:s,budgetCap:o})=>{try{return _(await et({name:t,ticketIds:n,advanceMode:r,stackDependentWork:s,budgetCap:o??null}))}catch(i){return q(i)}}),e.tool("start_batch","Play (or resume) a batch \u2014 starts its ready members autonomously. If another batch is already running, this one queues and starts when the slot frees.",{batchId:y.string()},async({batchId:t})=>{try{return _(await Bt(t))}catch(n){return q(n)}}),e.tool("pause_batch","Pause a running batch: stop starting new members (in-flight runs finish on their own).",{batchId:y.string()},async({batchId:t})=>{try{return _(await Lt(t))}catch(n){return q(n)}}),e.tool("stop_batch","Stop a batch and kill any of its still-running members (resets it to idle so it can be played again).",{batchId:y.string()},async({batchId:t})=>{try{return _(await Gt(t))}catch(n){return q(n)}}),e}function _o(e,t){Ic(t),e.post("/mcp",Ir,async(r,s)=>{let o=xc(),i=new Sc({sessionIdGenerator:void 0});s.on("close",()=>{i.close(),o.close()});try{await o.connect(i),await i.handleRequest(r,s,r.body)}catch(c){console.error("[pipelines-mcp] request error",c),s.headersSent||s.status(500).json({error:"internal error"})}});let n=(r,s)=>s.status(405).json({error:"method not allowed"});e.get("/mcp",Ir,n),e.delete("/mcp",Ir,n),console.log("[pipelines] MCP endpoint ready at /mcp")}Y();import{randomUUID as Ac}from"node:crypto";import{homedir as vc}from"node:os";var jn=["You are running in a RESTRICTED context (a schedule or conversation), not a board task.","You may read, investigate, analyze, run read-only commands, write non-code files (reports, notes) in non-git folders, and file board tickets with create_ticket.","You must NOT modify code or write into any git repository \u2014 there is no worktree here and repo writes are blocked. If a code change is warranted, create a board ticket describing exactly what to change (which repo, files, and why); the work happens on the board."].join(`
65
+ `);async function Mn(e){if(!e)return[];let t=Xt(e);return t===vc()?[]:(await Ue(t)).map(n=>n.path)}var Tc={min:6e4,minute:6e4,minutes:6e4,hour:36e5,hours:36e5,hr:36e5,hrs:36e5,day:864e5,days:864e5,week:6048e5,weeks:6048e5};function _c(e){let t=e.trim().toLowerCase();if(t==="hourly")return 36e5;if(t==="daily")return 864e5;if(t==="weekly")return 6048e5;let n=/every\s+(\d+)?\s*([a-z]+)/.exec(t);if(n){let r=n[1]?parseInt(n[1],10):1,s=Tc[n[2]];if(s&&r>0)return Math.max(6e4,r*s)}return 36e5}function nn(e,t){return new Date(e+_c(t)).toISOString()}var Nc=3e4,$n=new Set,vr=null;async function Rr(e,t=!0){let n=O[e];if(!n||$n.has(e))return null;$n.add(e);let r=++B.schedRunSeq,s={id:`srun_${r}`,scheduleId:e,status:"running",sessionId:Ac(),startedAt:new Date().toISOString(),finishedAt:null,output:"",model:n.model||l.defaultModel||he,effort:n.effort||l.defaultEffort||ke};return(z[e]??=[]).unshift(s),n.lastRunAt=s.startedAt,t&&(n.nextRunAt=nn(Date.now(),n.cadence)),await fn(s,r),await Ht(e),ue("schedule.run.started",{scheduleId:e,scheduleRunId:s.id,scheduleName:n.name,status:s.status},{workspaceId:n.workspaceId}),Ec(n,s,r),s}async function Ec(e,t,n){try{if(C())t.output=`Ran "${e.name}" on its ${e.cadence} cadence. (mock output)`,t.status="success";else{let r=e.workingDir??l.workspaceDirs?.[e.workspaceId]??"~",s=await Ve({prompt:`${jn}
66
66
 
67
- ${e.prompt}`,workspace:e.workspaceId,workingDir:r,model:t.model,effort:t.effort,sessionId:t.sessionId,pipelinesTools:!0,pipelinesToolsMode:"restricted",sandbox:!0,sandboxRepos:await mn(r)}),o=s.code===0?Yt(t.sessionId):null;t.output=(o??(s.code===0?s.stdout:s.stderr||s.stdout)).trim().slice(0,8e3),t.status=s.code===0?"success":"failed"}}catch(r){t.status="failed",t.output=String(r)}finally{t.finishedAt=new Date().toISOString(),await Kt(t,n),gn.delete(e.id),ue(t.status==="success"?"schedule.run.completed":"schedule.run.failed",{scheduleId:e.id,scheduleRunId:t.id,scheduleName:e.name,status:t.status},{workspaceId:e.workspaceId})}}async function Qa(){let e=Date.now(),t=l.connectedWorkspaces,n=Object.values(E).filter(r=>r.enabled&&r.nextRunAt&&Date.parse(r.nextRunAt)<=e&&!gn.has(r.id)&&(!t||t.includes(r.workspaceId)));for(let r of n)Zn(r.id,!0)}function Ks(){Vn||(Vn=setInterval(()=>void Qa(),Wa),Vn.unref?.())}async function Qs(){let e=0;for(let t of Object.values(B))for(let n of t)n.status==="running"&&(n.status="failed",n.finishedAt=new Date().toISOString(),n.output=n.output||"interrupted by daemon restart",await Kt(n,Number(n.id.replace(/^srun_/,""))||0),e++);e&&console.log(`[pipelines] reconciled ${e} interrupted schedule run(s)`)}async function hn(e,t,n){let r=new Array(e.length),s=0,o=async()=>{for(;s<e.length;){let c=s++;r[c]=await n(e[c],c)}},i=Math.max(1,Math.min(t,e.length));return await Promise.all(Array.from({length:i},()=>o())),r}function pe(e,t){console.warn(`[pipelines] ${e} discovery hit the ~${t}-ticket page cap; older tickets may be absent from the import pool \u2014 narrow the connection's sync filters to surface them.`)}function Ha(e){return new Promise(t=>setTimeout(t,e))}async function ee(e,t){let n=await fetch(e,t);if(n.status!==429)return n;let r=Number(n.headers.get("retry-after")),s=Number.isFinite(r)?Math.min(r*1e3,1e4):1e3;return await Ha(s),fetch(e,t)}var Hs="https://api.linear.app/graphql";function Ja(e){switch(e){case"triage":return"triage";case"backlog":return"backlog";case"unstarted":return"todo";case"started":return"in_progress";case"completed":return"done";case"canceled":return"canceled";default:return"todo"}}function er(e,t,n){let r=typeof e.priority=="number"?e.priority:void 0;return{id:`lin_${e.id}`,connectionId:t,provider:"linear",externalIdentifier:e.identifier,title:e.title,description:e.description??void 0,status:Ja(e.state?.type),statusRaw:e.state?.name??"",assignee:e.assignee?.name?{name:e.assignee.name,avatarUrl:e.assignee.avatarUrl??void 0}:void 0,reporter:e.creator?.name?{name:e.creator.name,avatarUrl:e.creator.avatarUrl??void 0}:void 0,dueDate:e.dueDate??void 0,priority:r!==void 0&&r>=0&&r<=4?r:void 0,labels:(e.labels?.nodes??[]).map(s=>({name:s.name,color:s.color??void 0})),project:e.project?.name,parent:e.parent?.identifier?{identifier:e.parent.identifier,title:e.parent.title??""}:void 0,url:e.url,workspaceId:n,createdAt:e.createdAt,updatedAt:e.updatedAt}}function Js(e,t,n,r,s){let o=new Map(r.filter(u=>u.connectionId===n).map(u=>[u.externalIdentifier,u])),i=[];for(let u of t){let m=o.get(u.externalIdentifier);m&&(m.title=u.title,m.description=u.description,m.comments=u.comments??m.comments,m.status=u.status,m.statusRaw=u.statusRaw,m.assignee=u.assignee,m.reporter=u.reporter,m.dueDate=u.dueDate,m.priority=u.priority,m.labels=u.labels,m.project=u.project,m.parent=u.parent,m.url=u.url,m.createdAt=u.createdAt,m.updatedAt=u.updatedAt,i.push(m.id))}let c=e.filter(u=>!o.has(u.externalIdentifier)),d=s.filter(u=>u.connectionId!==n);return s.length=0,s.push(...d,...c),{refreshed:i,pool:c}}var zs=`id identifier title description url priority createdAt updatedAt dueDate
67
+ ${e.prompt}`,workspace:e.workspaceId,workingDir:r,model:t.model,effort:t.effort,sessionId:t.sessionId,pipelinesTools:!0,pipelinesToolsMode:"restricted",sandbox:!0,sandboxRepos:await Mn(r)}),o=s.code===0?wn(t.sessionId):null;t.output=(o??(s.code===0?s.stdout:s.stderr||s.stdout)).trim().slice(0,8e3),t.status=s.code===0?"success":"failed"}}catch(r){t.status="failed",t.output=String(r)}finally{t.finishedAt=new Date().toISOString(),await fn(t,n),$n.delete(e.id),ue(t.status==="success"?"schedule.run.completed":"schedule.run.failed",{scheduleId:e.id,scheduleRunId:t.id,scheduleName:e.name,status:t.status},{workspaceId:e.workspaceId})}}async function Cc(){let e=Date.now(),t=l.connectedWorkspaces,n=Object.values(O).filter(r=>r.enabled&&r.nextRunAt&&Date.parse(r.nextRunAt)<=e&&!$n.has(r.id)&&(!t||t.includes(r.workspaceId)));for(let r of n)Rr(r.id,!0)}function Ao(){vr||(vr=setInterval(()=>void Cc(),Nc),vr.unref?.())}async function No(){let e=0;for(let t of Object.values(z))for(let n of t)n.status==="running"&&(n.status="failed",n.finishedAt=new Date().toISOString(),n.output=n.output||"interrupted by daemon restart",await fn(n,Number(n.id.replace(/^srun_/,""))||0),e++);e&&console.log(`[pipelines] reconciled ${e} interrupted schedule run(s)`)}async function Bn(e,t,n){let r=new Array(e.length),s=0,o=async()=>{for(;s<e.length;){let c=s++;r[c]=await n(e[c],c)}},i=Math.max(1,Math.min(t,e.length));return await Promise.all(Array.from({length:i},()=>o())),r}function ye(e,t){console.warn(`[pipelines] ${e} discovery hit the ~${t}-ticket page cap; older tickets may be absent from the import pool \u2014 narrow the connection's sync filters to surface them.`)}function Pc(e){return new Promise(t=>setTimeout(t,e))}async function ae(e,t){let n=await fetch(e,t);if(n.status!==429)return n;let r=Number(n.headers.get("retry-after")),s=Number.isFinite(r)?Math.min(r*1e3,1e4):1e3;return await Pc(s),fetch(e,t)}var Eo="https://api.linear.app/graphql";function Oc(e){switch(e){case"triage":return"triage";case"backlog":return"backlog";case"unstarted":return"todo";case"started":return"in_progress";case"completed":return"done";case"canceled":return"canceled";default:return"todo"}}function Tr(e,t,n){let r=typeof e.priority=="number"?e.priority:void 0;return{id:`lin_${e.id}`,connectionId:t,provider:"linear",externalIdentifier:e.identifier,title:e.title,description:e.description??void 0,status:Oc(e.state?.type),statusRaw:e.state?.name??"",assignee:e.assignee?.name?{name:e.assignee.name,avatarUrl:e.assignee.avatarUrl??void 0}:void 0,reporter:e.creator?.name?{name:e.creator.name,avatarUrl:e.creator.avatarUrl??void 0}:void 0,dueDate:e.dueDate??void 0,priority:r!==void 0&&r>=0&&r<=4?r:void 0,labels:(e.labels?.nodes??[]).map(s=>({name:s.name,color:s.color??void 0})),project:e.project?.name,parent:e.parent?.identifier?{identifier:e.parent.identifier,title:e.parent.title??""}:void 0,url:e.url,workspaceId:n,createdAt:e.createdAt,updatedAt:e.updatedAt}}function Co(e,t,n,r,s){let o=new Map(r.filter(u=>u.connectionId===n).map(u=>[u.externalIdentifier,u])),i=[];for(let u of t){let m=o.get(u.externalIdentifier);m&&(m.title=u.title,m.description=u.description,m.comments=u.comments??m.comments,m.status=u.status,m.statusRaw=u.statusRaw,m.assignee=u.assignee,m.reporter=u.reporter,m.dueDate=u.dueDate,m.priority=u.priority,m.labels=u.labels,m.project=u.project,m.parent=u.parent,m.url=u.url,m.createdAt=u.createdAt,m.updatedAt=u.updatedAt,i.push(m.id))}let c=e.filter(u=>!o.has(u.externalIdentifier)),d=s.filter(u=>u.connectionId!==n);return s.length=0,s.push(...d,...c),{refreshed:i,pool:c}}var Po=`id identifier title description url priority createdAt updatedAt dueDate
68
68
  state { name type } assignee { name avatarUrl } creator { name avatarUrl } project { name }
69
69
  parent { identifier title }
70
- labels { nodes { name color } }`,za=`query Issues($filter: IssueFilter, $after: String) {
70
+ labels { nodes { name color } }`,Dc=`query Issues($filter: IssueFilter, $after: String) {
71
71
  issues(first: 100, filter: $filter, after: $after) {
72
- nodes { ${zs} }
72
+ nodes { ${Po} }
73
73
  pageInfo { hasNextPage endCursor }
74
- } }`,Xa=`query IssuesById($ids: [ID!]) {
75
- issues(first: 250, filter: { id: { in: $ids } }) { nodes { ${zs} } } }`;function Ya(e){let t={state:{type:{neq:"canceled"}}},n=(e?.labels??[]).map(r=>r.trim()).filter(Boolean);if(n.length&&(t.labels={or:n.map(r=>({name:{eqIgnoreCase:r}}))}),e?.assignedToMe)t.assignee={isMe:{eq:!0}};else if(e?.assignee?.trim()){let r=e.assignee.trim();t.assignee={or:[{email:{eqIgnoreCase:r}},{displayName:{eqIgnoreCase:r}}]}}return t}async function Xs(e,t,n){let r=await ee(Hs,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e}`},body:JSON.stringify({query:t,variables:n})});if(!r.ok){let o=new Error(`Linear issues fetch failed (HTTP ${r.status})`);throw o.status=r.status,o}let s=await r.json();return{nodes:s.data?.issues?.nodes??[],pageInfo:s.data?.issues?.pageInfo}}async function Ys(e,t){let n=Ya(t),r=[],s;for(let o=0;o<5;o++){let{nodes:i,pageInfo:c}=await Xs(e,za,{filter:n,after:s});if(r.push(...i),!c?.hasNextPage||!c.endCursor)return r;s=c.endCursor}return pe("Linear",r.length),r}async function Vs(e,t){return t.length?(await Xs(e,Xa,{ids:t})).nodes:[]}var Va=`query IssueComments($id: String!) {
74
+ } }`,jc=`query IssuesById($ids: [ID!]) {
75
+ issues(first: 250, filter: { id: { in: $ids } }) { nodes { ${Po} } } }`;function Mc(e){let t={state:{type:{neq:"canceled"}}},n=(e?.labels??[]).map(r=>r.trim()).filter(Boolean);if(n.length&&(t.labels={or:n.map(r=>({name:{eqIgnoreCase:r}}))}),e?.assignedToMe)t.assignee={isMe:{eq:!0}};else if(e?.assignee?.trim()){let r=e.assignee.trim();t.assignee={or:[{email:{eqIgnoreCase:r}},{displayName:{eqIgnoreCase:r}}]}}return t}async function Oo(e,t,n){let r=await ae(Eo,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e}`},body:JSON.stringify({query:t,variables:n})});if(!r.ok){let o=new Error(`Linear issues fetch failed (HTTP ${r.status})`);throw o.status=r.status,o}let s=await r.json();return{nodes:s.data?.issues?.nodes??[],pageInfo:s.data?.issues?.pageInfo}}async function Do(e,t){let n=Mc(t),r=[],s;for(let o=0;o<5;o++){let{nodes:i,pageInfo:c}=await Oo(e,Dc,{filter:n,after:s});if(r.push(...i),!c?.hasNextPage||!c.endCursor)return r;s=c.endCursor}return ye("Linear",r.length),r}async function jo(e,t){return t.length?(await Oo(e,jc,{ids:t})).nodes:[]}var $c=`query IssueComments($id: String!) {
76
76
  issue(id: $id) {
77
77
  comments(first: 100) { nodes { id body createdAt updatedAt user { name } } }
78
- } }`;async function Zs(e,t){let n=await ee(Hs,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e}`},body:JSON.stringify({query:Va,variables:{id:t}})});if(!n.ok){let s=new Error(`Linear comments fetch failed (HTTP ${n.status})`);throw s.status=n.status,s}return((await n.json()).data?.issue?.comments?.nodes??[]).filter(s=>(s.body??"").trim()).map(s=>({id:s.id,author:s.user?.name??void 0,body:s.body??"",createdAt:s.createdAt,updatedAt:s.updatedAt}))}var eo=e=>`https://api.atlassian.com/ex/jira/${e}/rest/api/3`;function tc(e){switch(e){case"new":return"todo";case"indeterminate":return"in_progress";case"done":return"done";default:return"todo"}}function nc(e){switch((e??"").toLowerCase()){case"highest":case"urgent":case"critical":case"blocker":return 1;case"high":return 2;case"medium":case"normal":return 3;case"low":case"lowest":case"minor":case"trivial":return 4;default:return}}function to(e){if(e==null)return;if(typeof e=="string")return e||void 0;let t=[],n=(r,s=!1)=>{if(!r||typeof r!="object")return;if(r.type==="text"){t.push(r.text??"");return}if(r.type==="hardBreak"){t.push(`
78
+ } }`;async function Mo(e,t){let n=await ae(Eo,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e}`},body:JSON.stringify({query:$c,variables:{id:t}})});if(!n.ok){let s=new Error(`Linear comments fetch failed (HTTP ${n.status})`);throw s.status=n.status,s}return((await n.json()).data?.issue?.comments?.nodes??[]).filter(s=>(s.body??"").trim()).map(s=>({id:s.id,author:s.user?.name??void 0,body:s.body??"",createdAt:s.createdAt,updatedAt:s.updatedAt}))}var $o=e=>`https://api.atlassian.com/ex/jira/${e}/rest/api/3`;function Gc(e){switch(e){case"new":return"todo";case"indeterminate":return"in_progress";case"done":return"done";default:return"todo"}}function Uc(e){switch((e??"").toLowerCase()){case"highest":case"urgent":case"critical":case"blocker":return 1;case"high":return 2;case"medium":case"normal":return 3;case"low":case"lowest":case"minor":case"trivial":return 4;default:return}}function Bo(e){if(e==null)return;if(typeof e=="string")return e||void 0;let t=[],n=(r,s=!1)=>{if(!r||typeof r!="object")return;if(r.type==="text"){t.push(r.text??"");return}if(r.type==="hardBreak"){t.push(`
79
79
  `);return}let o=r.type==="paragraph"||r.type==="heading"||r.type==="codeBlock"||r.type==="listItem"||r.type==="blockquote";r.type==="listItem"&&t.push("- ");for(let i of r.content??[])n(i,r.type==="listItem");o&&t.push(`
80
80
  `)};return n(e),t.join("").replace(/\n{3,}/g,`
81
81
 
82
- `).trim()||void 0}function nr(e,t,n,r){let s=e.fields??{},o=s.assignee?.avatarUrls?.["48x48"]??void 0,i=s.reporter?.avatarUrls?.["48x48"]??void 0;return{id:`jira_${e.id}`,connectionId:t,provider:"jira",externalIdentifier:e.key,title:s.summary??e.key,description:to(s.description),status:tc(s.status?.statusCategory?.key),statusRaw:s.status?.name??"",assignee:s.assignee?.displayName?{name:s.assignee.displayName,avatarUrl:o}:void 0,reporter:s.reporter?.displayName?{name:s.reporter.displayName,avatarUrl:i}:void 0,dueDate:s.duedate??void 0,priority:nc(s.priority?.name??void 0),labels:(s.labels??[]).map(c=>({name:c})),project:s.project?.name,parent:s.parent?.key?{identifier:s.parent.key,title:s.parent.fields?.summary??"",type:s.parent.fields?.issuetype?.name}:void 0,url:r?`https://${r}/browse/${e.key}`:e.key,workspaceId:n,createdAt:s.created,updatedAt:s.updated}}var rc=["summary","description","status","assignee","reporter","duedate","priority","labels","project","parent","created","updated"];function tr(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function sc(e){let t=["statusCategory != Done"],n=(e?.labels??[]).map(r=>r.trim()).filter(Boolean);return n.length&&t.push(`labels in (${n.map(r=>`"${tr(r)}"`).join(", ")})`),e?.assignedToMe?t.push("assignee = currentUser()"):e?.assignee?.trim()&&t.push(`assignee = "${tr(e.assignee.trim())}"`),`${t.join(" AND ")} ORDER BY updated DESC`}async function no(e,t,n,r,s=!1){let o=[],i,c=s?5:1;for(let d=0;d<c;d++){let u=await ee(`${eo(e)}/search/jql`,{method:"POST",headers:{"content-type":"application/json",accept:"application/json",authorization:`Bearer ${t}`},body:JSON.stringify({jql:n,fields:rc,maxResults:r,...i?{nextPageToken:i}:{}})});if(!u.ok){let g=new Error(`Jira search failed (HTTP ${u.status})`);throw g.status=u.status,g}let m=await u.json();if(o.push(...m.issues??[]),!s||m.isLast||!m.nextPageToken)return o;i=m.nextPageToken}return s&&pe("Jira",o.length),o}function ro(e,t,n){return no(e,t,sc(n),100,!0)}function so(e,t,n){if(!n.length)return Promise.resolve([]);let r=n.map(s=>`"${tr(s)}"`).join(", ");return no(e,t,`id in (${r})`,250)}async function oo(e,t,n){let r=await ee(`${eo(e)}/issue/${encodeURIComponent(n)}/comment?maxResults=100&orderBy=created`,{headers:{accept:"application/json",authorization:`Bearer ${t}`}});if(!r.ok){let o=new Error(`Jira comments fetch failed (HTTP ${r.status})`);throw o.status=r.status,o}return((await r.json()).comments??[]).map(o=>({id:o.id,author:o.author?.displayName??void 0,body:to(o.body)??"",createdAt:o.created,updatedAt:o.updated})).filter(o=>o.body.trim())}var io="https://app.asana.com/api/1.0",ao=["name","notes","completed","assignee.name","due_on","tags.name","projects.name","parent.name","parent.gid","created_at","modified_at","permalink_url"].join(",");function ic(e){return e?"done":"todo"}function rr(e,t,n){return{id:`asana_${e.gid}`,connectionId:t,provider:"asana",externalIdentifier:e.gid,title:e.name||e.gid,description:e.notes?.trim()||void 0,status:ic(e.completed),statusRaw:"",assignee:e.assignee?.name?{name:e.assignee.name}:void 0,dueDate:e.due_on??void 0,labels:(e.tags??[]).map(r=>r.name).filter(r=>!!r).map(r=>({name:r})),project:(e.projects??[]).map(r=>r.name).filter(r=>!!r).join(`
83
- `)||void 0,parent:e.parent?.gid?{identifier:e.parent.gid,title:e.parent.name??""}:void 0,url:e.permalink_url||`https://app.asana.com/0/0/${e.gid}`,workspaceId:n,createdAt:e.created_at,updatedAt:e.modified_at}}async function sr(e,t){let n=await ee(`${io}${e}`,{headers:{authorization:`Bearer ${t}`,accept:"application/json"}});if(!n.ok){let s=new Error(`Asana request failed (HTTP ${n.status})`);throw s.status=n.status,s}return(await n.json()).data}async function ac(e,t){let n=await ee(`${io}${e}`,{headers:{authorization:`Bearer ${t}`,accept:"application/json"}});if(!n.ok){let s=new Error(`Asana request failed (HTTP ${n.status})`);throw s.status=n.status,s}let r=await n.json();return{data:r.data??[],nextOffset:r.next_page?.offset}}function cc(e,t){let n=t?.assignee?.trim()||"me";return new URLSearchParams({workspace:e,assignee:n,completed_since:"now",limit:"100",opt_fields:ao}).toString()}async function co(e,t,n){let r=cc(e,n),s=[],o;for(let i=0;i<5;i++){let{data:c,nextOffset:d}=await ac(`/tasks?${r}${o?`&offset=${o}`:""}`,t);if(s.push(...c),!d)return s;o=d}return pe("Asana",s.length),s}async function uo(e,t){return t.length?(await hn(t,5,r=>sr(`/tasks/${r}?opt_fields=${ao}`,e).catch(()=>null))).filter(r=>!!r):[]}async function lo(e,t){return(await sr(`/tasks/${encodeURIComponent(t)}/stories?opt_fields=text,created_at,created_by.name,type`,e)??[]).filter(r=>r.type==="comment"&&(r.text??"").trim()).map(r=>({id:r.gid,author:r.created_by?.name??void 0,body:r.text??"",createdAt:r.created_at}))}async function po(e){try{let t=await sr("/workspaces?opt_fields=name",e);return Array.isArray(t)?t:[]}catch{return[]}}var uc="https://api.clickup.com/api/v2";function lc(e){switch((e??"").toLowerCase()){case"done":case"closed":return"done";case"open":return"todo";default:return"in_progress"}}function pc(e){return(e??"").replace(/\b\w/g,t=>t.toUpperCase())}function fc(e){switch((e??"").toLowerCase()){case"urgent":return 1;case"high":return 2;case"normal":return 3;case"low":return 4;default:return}}function or(e){if(e==null||e==="")return;let t=Number(e);return Number.isFinite(t)?new Date(t).toISOString():void 0}function mc(e){return or(e)?.slice(0,10)}function ir(e,t,n){let r=e.assignees?.[0];return{id:`clickup_${e.id}`,connectionId:t,provider:"clickup",externalIdentifier:e.custom_id?.trim()||e.id,title:e.name||e.id,description:(e.text_content??e.description??"").trim()||void 0,status:lc(e.status?.type),statusRaw:pc(e.status?.status??void 0),assignee:r?.username?{name:r.username,avatarUrl:r.profilePicture??void 0}:void 0,reporter:e.creator?.username?{name:e.creator.username,avatarUrl:e.creator.profilePicture??void 0}:void 0,dueDate:mc(e.due_date),priority:fc(e.priority?.priority),labels:(e.tags??[]).map(s=>s.name).filter(s=>!!s).map(s=>({name:s})),project:e.list?.name,url:e.url||`https://app.clickup.com/t/${e.id}`,workspaceId:n,createdAt:or(e.date_created),updatedAt:or(e.date_updated)}}async function kn(e,t){let n=await ee(`${uc}${e}`,{headers:{authorization:t,accept:"application/json"}});if(!n.ok){let r=new Error(`ClickUp request failed (HTTP ${n.status})`);throw r.status=n.status,r}return await n.json()}function gc(e){let t=new URLSearchParams({archived:"false",include_closed:"false",subtasks:"true",order_by:"updated"});for(let n of(e?.labels??[]).map(r=>r.trim()).filter(Boolean))t.append("tags[]",n);return t.toString()}async function fo(e,t,n){let r=gc(n),s=[];for(let o=0;o<5;o++){let i=await kn(`/team/${e}/task?${r}&page=${o}`,t);if(s.push(...i.tasks??[]),i.last_page||!i.tasks?.length)return s}return pe("ClickUp",s.length),s}async function mo(e,t){return t.length?(await hn(t,5,r=>kn(`/task/${r}`,e).catch(()=>null))).filter(r=>!!r):[]}async function go(e,t){let n=await kn(`/task/${encodeURIComponent(t)}/comment`,e),r=s=>{let o=Number(s);return Number.isFinite(o)&&o>0?new Date(o).toISOString():void 0};return(n.comments??[]).filter(s=>(s.comment_text??"").trim()).map(s=>({id:String(s.id),author:s.user?.username??void 0,body:s.comment_text??"",createdAt:r(s.date)}))}async function ho(e){try{return(await kn("/team",e)).teams??[]}catch{return[]}}var kc="https://api.monday.com/v2";function yc(e){let t=(e??"").toLowerCase();return t?/done|complete|closed|resolved|shipped/.test(t)?"done":/progress|working|review|doing|active/.test(t)?"in_progress":"todo":"todo"}function ar(e,t,n,r){let s=e.column_values??[],o=g=>g.column?.title??"",i=s.find(g=>g.id==="status")??s.find(g=>g.type==="status"&&!/priorit/i.test(o(g))),c=[...new Set(s.filter(g=>g.type==="people"||g.type==="multiple-person").flatMap(g=>(g.text??"").split(",")).map(g=>g.trim()).filter(Boolean))],d=s.find(g=>/due|date/i.test(o(g)))??s.find(g=>g.type==="date"),u=e.board?.id,m=t&&u?`https://${t}.monday.com/boards/${u}/pulses/${e.id}`:"https://monday.com";return{id:`monday_${e.id}`,connectionId:n,provider:"monday",externalIdentifier:e.id,title:e.name||e.id,status:yc(i?.text??void 0),statusRaw:i?.text?.trim()||e.group?.title||"",assignee:c.length?{name:c.join(`
84
- `)}:void 0,dueDate:d?.text?.trim()||void 0,labels:[],project:e.board?.name,url:m,workspaceId:r,createdAt:e.created_at,updatedAt:e.updated_at}}var ko=`
82
+ `).trim()||void 0}function Ar(e,t,n,r){let s=e.fields??{},o=s.assignee?.avatarUrls?.["48x48"]??void 0,i=s.reporter?.avatarUrls?.["48x48"]??void 0;return{id:`jira_${e.id}`,connectionId:t,provider:"jira",externalIdentifier:e.key,title:s.summary??e.key,description:Bo(s.description),status:Gc(s.status?.statusCategory?.key),statusRaw:s.status?.name??"",assignee:s.assignee?.displayName?{name:s.assignee.displayName,avatarUrl:o}:void 0,reporter:s.reporter?.displayName?{name:s.reporter.displayName,avatarUrl:i}:void 0,dueDate:s.duedate??void 0,priority:Uc(s.priority?.name??void 0),labels:(s.labels??[]).map(c=>({name:c})),project:s.project?.name,parent:s.parent?.key?{identifier:s.parent.key,title:s.parent.fields?.summary??"",type:s.parent.fields?.issuetype?.name}:void 0,url:r?`https://${r}/browse/${e.key}`:e.key,workspaceId:n,createdAt:s.created,updatedAt:s.updated}}var qc=["summary","description","status","assignee","reporter","duedate","priority","labels","project","parent","created","updated"];function _r(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Fc(e){let t=["statusCategory != Done"],n=(e?.labels??[]).map(r=>r.trim()).filter(Boolean);return n.length&&t.push(`labels in (${n.map(r=>`"${_r(r)}"`).join(", ")})`),e?.assignedToMe?t.push("assignee = currentUser()"):e?.assignee?.trim()&&t.push(`assignee = "${_r(e.assignee.trim())}"`),`${t.join(" AND ")} ORDER BY updated DESC`}async function Lo(e,t,n,r,s=!1){let o=[],i,c=s?5:1;for(let d=0;d<c;d++){let u=await ae(`${$o(e)}/search/jql`,{method:"POST",headers:{"content-type":"application/json",accept:"application/json",authorization:`Bearer ${t}`},body:JSON.stringify({jql:n,fields:qc,maxResults:r,...i?{nextPageToken:i}:{}})});if(!u.ok){let g=new Error(`Jira search failed (HTTP ${u.status})`);throw g.status=u.status,g}let m=await u.json();if(o.push(...m.issues??[]),!s||m.isLast||!m.nextPageToken)return o;i=m.nextPageToken}return s&&ye("Jira",o.length),o}function Go(e,t,n){return Lo(e,t,Fc(n),100,!0)}function Uo(e,t,n){if(!n.length)return Promise.resolve([]);let r=n.map(s=>`"${_r(s)}"`).join(", ");return Lo(e,t,`id in (${r})`,250)}async function qo(e,t,n){let r=await ae(`${$o(e)}/issue/${encodeURIComponent(n)}/comment?maxResults=100&orderBy=created`,{headers:{accept:"application/json",authorization:`Bearer ${t}`}});if(!r.ok){let o=new Error(`Jira comments fetch failed (HTTP ${r.status})`);throw o.status=r.status,o}return((await r.json()).comments??[]).map(o=>({id:o.id,author:o.author?.displayName??void 0,body:Bo(o.body)??"",createdAt:o.created,updatedAt:o.updated})).filter(o=>o.body.trim())}var Fo="https://app.asana.com/api/1.0",Wo=["name","notes","completed","assignee.name","due_on","tags.name","projects.name","parent.name","parent.gid","created_at","modified_at","permalink_url"].join(",");function Kc(e){return e?"done":"todo"}function Nr(e,t,n){return{id:`asana_${e.gid}`,connectionId:t,provider:"asana",externalIdentifier:e.gid,title:e.name||e.gid,description:e.notes?.trim()||void 0,status:Kc(e.completed),statusRaw:"",assignee:e.assignee?.name?{name:e.assignee.name}:void 0,dueDate:e.due_on??void 0,labels:(e.tags??[]).map(r=>r.name).filter(r=>!!r).map(r=>({name:r})),project:(e.projects??[]).map(r=>r.name).filter(r=>!!r).join(`
83
+ `)||void 0,parent:e.parent?.gid?{identifier:e.parent.gid,title:e.parent.name??""}:void 0,url:e.permalink_url||`https://app.asana.com/0/0/${e.gid}`,workspaceId:n,createdAt:e.created_at,updatedAt:e.modified_at}}async function Er(e,t){let n=await ae(`${Fo}${e}`,{headers:{authorization:`Bearer ${t}`,accept:"application/json"}});if(!n.ok){let s=new Error(`Asana request failed (HTTP ${n.status})`);throw s.status=n.status,s}return(await n.json()).data}async function Hc(e,t){let n=await ae(`${Fo}${e}`,{headers:{authorization:`Bearer ${t}`,accept:"application/json"}});if(!n.ok){let s=new Error(`Asana request failed (HTTP ${n.status})`);throw s.status=n.status,s}let r=await n.json();return{data:r.data??[],nextOffset:r.next_page?.offset}}function Qc(e,t){let n=t?.assignee?.trim()||"me";return new URLSearchParams({workspace:e,assignee:n,completed_since:"now",limit:"100",opt_fields:Wo}).toString()}async function Ko(e,t,n){let r=Qc(e,n),s=[],o;for(let i=0;i<5;i++){let{data:c,nextOffset:d}=await Hc(`/tasks?${r}${o?`&offset=${o}`:""}`,t);if(s.push(...c),!d)return s;o=d}return ye("Asana",s.length),s}async function Ho(e,t){return t.length?(await Bn(t,5,r=>Er(`/tasks/${r}?opt_fields=${Wo}`,e).catch(()=>null))).filter(r=>!!r):[]}async function Qo(e,t){return(await Er(`/tasks/${encodeURIComponent(t)}/stories?opt_fields=text,created_at,created_by.name,type`,e)??[]).filter(r=>r.type==="comment"&&(r.text??"").trim()).map(r=>({id:r.gid,author:r.created_by?.name??void 0,body:r.text??"",createdAt:r.created_at}))}async function Jo(e){try{let t=await Er("/workspaces?opt_fields=name",e);return Array.isArray(t)?t:[]}catch{return[]}}var zc="https://api.clickup.com/api/v2";function Xc(e){switch((e??"").toLowerCase()){case"done":case"closed":return"done";case"open":return"todo";default:return"in_progress"}}function Yc(e){return(e??"").replace(/\b\w/g,t=>t.toUpperCase())}function Vc(e){switch((e??"").toLowerCase()){case"urgent":return 1;case"high":return 2;case"normal":return 3;case"low":return 4;default:return}}function Cr(e){if(e==null||e==="")return;let t=Number(e);return Number.isFinite(t)?new Date(t).toISOString():void 0}function Zc(e){return Cr(e)?.slice(0,10)}function Pr(e,t,n){let r=e.assignees?.[0];return{id:`clickup_${e.id}`,connectionId:t,provider:"clickup",externalIdentifier:e.custom_id?.trim()||e.id,title:e.name||e.id,description:(e.text_content??e.description??"").trim()||void 0,status:Xc(e.status?.type),statusRaw:Yc(e.status?.status??void 0),assignee:r?.username?{name:r.username,avatarUrl:r.profilePicture??void 0}:void 0,reporter:e.creator?.username?{name:e.creator.username,avatarUrl:e.creator.profilePicture??void 0}:void 0,dueDate:Zc(e.due_date),priority:Vc(e.priority?.priority),labels:(e.tags??[]).map(s=>s.name).filter(s=>!!s).map(s=>({name:s})),project:e.list?.name,url:e.url||`https://app.clickup.com/t/${e.id}`,workspaceId:n,createdAt:Cr(e.date_created),updatedAt:Cr(e.date_updated)}}async function Ln(e,t){let n=await ae(`${zc}${e}`,{headers:{authorization:t,accept:"application/json"}});if(!n.ok){let r=new Error(`ClickUp request failed (HTTP ${n.status})`);throw r.status=n.status,r}return await n.json()}function ed(e){let t=new URLSearchParams({archived:"false",include_closed:"false",subtasks:"true",order_by:"updated"});for(let n of(e?.labels??[]).map(r=>r.trim()).filter(Boolean))t.append("tags[]",n);return t.toString()}async function zo(e,t,n){let r=ed(n),s=[];for(let o=0;o<5;o++){let i=await Ln(`/team/${e}/task?${r}&page=${o}`,t);if(s.push(...i.tasks??[]),i.last_page||!i.tasks?.length)return s}return ye("ClickUp",s.length),s}async function Xo(e,t){return t.length?(await Bn(t,5,r=>Ln(`/task/${r}`,e).catch(()=>null))).filter(r=>!!r):[]}async function Yo(e,t){let n=await Ln(`/task/${encodeURIComponent(t)}/comment`,e),r=s=>{let o=Number(s);return Number.isFinite(o)&&o>0?new Date(o).toISOString():void 0};return(n.comments??[]).filter(s=>(s.comment_text??"").trim()).map(s=>({id:String(s.id),author:s.user?.username??void 0,body:s.comment_text??"",createdAt:r(s.date)}))}async function Vo(e){try{return(await Ln("/team",e)).teams??[]}catch{return[]}}var nd="https://api.monday.com/v2";function rd(e){let t=(e??"").toLowerCase();return t?/done|complete|closed|resolved|shipped/.test(t)?"done":/progress|working|review|doing|active/.test(t)?"in_progress":"todo":"todo"}function Or(e,t,n,r){let s=e.column_values??[],o=g=>g.column?.title??"",i=s.find(g=>g.id==="status")??s.find(g=>g.type==="status"&&!/priorit/i.test(o(g))),c=[...new Set(s.filter(g=>g.type==="people"||g.type==="multiple-person").flatMap(g=>(g.text??"").split(",")).map(g=>g.trim()).filter(Boolean))],d=s.find(g=>/due|date/i.test(o(g)))??s.find(g=>g.type==="date"),u=e.board?.id,m=t&&u?`https://${t}.monday.com/boards/${u}/pulses/${e.id}`:"https://monday.com";return{id:`monday_${e.id}`,connectionId:n,provider:"monday",externalIdentifier:e.id,title:e.name||e.id,status:rd(i?.text??void 0),statusRaw:i?.text?.trim()||e.group?.title||"",assignee:c.length?{name:c.join(`
84
+ `)}:void 0,dueDate:d?.text?.trim()||void 0,labels:[],project:e.board?.name,url:m,workspaceId:r,createdAt:e.created_at,updatedAt:e.updated_at}}var Zo=`
85
85
  id
86
86
  name
87
87
  created_at
@@ -89,7 +89,7 @@ ${e.prompt}`,workspace:e.workspaceId,workingDir:r,model:t.model,effort:t.effort,
89
89
  group { title }
90
90
  board { id name }
91
91
  column_values { id type text column { title } }
92
- `;async function yn(e,t){let n=await ee(kc,{method:"POST",headers:{authorization:t,"content-type":"application/json","api-version":"2024-01"},body:JSON.stringify({query:e})});if(!n.ok){let s=new Error(`Monday request failed (HTTP ${n.status})`);throw s.status=n.status,s}let r=await n.json();if(r.errors)throw new Error(`Monday GraphQL error: ${JSON.stringify(r.errors)}`);return r.data}async function yo(e,t){let r=(await yn(`query { boards (limit: 50) { id name items_page (limit: 100) { cursor items { ${ko} } } } }`,e)).boards??[],s=[],o=r.length>=50;for(let i of r){for(let c of i.items_page?.items??[])s.push({...c,board:c.board??{id:i.id,name:i.name}});i.items_page?.cursor&&(o=!0)}return o&&pe("Monday",s.length),s}async function wo(e,t){if(!t.length)return[];let n=t.map(s=>JSON.stringify(s)).join(", ");return(await yn(`query { items (ids: [${n}]) { ${ko} } }`,e)).items??[]}async function bo(e,t){return((await yn(`query { items (ids: [${JSON.stringify(t)}]) { updates (limit: 100) { id text_body body created_at creator { name } } } }`,e)).items?.[0]?.updates??[]).map(r=>({id:r.id,author:r.creator?.name??void 0,body:(r.text_body??r.body??"").trim(),createdAt:r.created_at})).filter(r=>r.body)}async function So(e){try{return(await yn(`
92
+ `;async function Gn(e,t){let n=await ae(nd,{method:"POST",headers:{authorization:t,"content-type":"application/json","api-version":"2024-01"},body:JSON.stringify({query:e})});if(!n.ok){let s=new Error(`Monday request failed (HTTP ${n.status})`);throw s.status=n.status,s}let r=await n.json();if(r.errors)throw new Error(`Monday GraphQL error: ${JSON.stringify(r.errors)}`);return r.data}async function ei(e,t){let r=(await Gn(`query { boards (limit: 50) { id name items_page (limit: 100) { cursor items { ${Zo} } } } }`,e)).boards??[],s=[],o=r.length>=50;for(let i of r){for(let c of i.items_page?.items??[])s.push({...c,board:c.board??{id:i.id,name:i.name}});i.items_page?.cursor&&(o=!0)}return o&&ye("Monday",s.length),s}async function ti(e,t){if(!t.length)return[];let n=t.map(s=>JSON.stringify(s)).join(", ");return(await Gn(`query { items (ids: [${n}]) { ${Zo} } }`,e)).items??[]}async function ni(e,t){return((await Gn(`query { items (ids: [${JSON.stringify(t)}]) { updates (limit: 100) { id text_body body created_at creator { name } } } }`,e)).items?.[0]?.updates??[]).map(r=>({id:r.id,author:r.creator?.name??void 0,body:(r.text_body??r.body??"").trim(),createdAt:r.created_at})).filter(r=>r.body)}async function ri(e){try{return(await Gn(`
93
93
  query {
94
94
  me {
95
95
  account {
@@ -98,54 +98,54 @@ ${e.prompt}`,workspace:e.workspaceId,workingDir:r,model:t.model,effort:t.effort,
98
98
  }
99
99
  }
100
100
  }
101
- `,e)).me?.account??null}catch{return null}}var cr=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function dr(){let e=ae();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function Io(e,t){let n=dr();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${cr}/api/oauth/linear/start`,{method:"POST",headers:n,body:JSON.stringify({connectionId:e,daemonPort:t})}),s=await r.json().catch(()=>null);return r.ok?s?.configured===!1?{configured:!1,error:s?.message??"Linear isn't set up on the server yet."}:s?.url?{url:s.url}:{error:"The server didn't return an authorize URL."}:{error:s?.message??`Couldn't start OAuth (HTTP ${r.status}).`}}catch(r){return{error:`Couldn't reach the SuperClawd backend (${String(r)}).`}}}async function xo(e){let t=dr();if(!t)return null;try{let n=await fetch(`${cr}/api/oauth/linear/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}async function vo(e){let t=dr();if(!t)return null;try{let n=await fetch(`${cr}/api/oauth/linear/refresh`,{method:"POST",headers:t,body:JSON.stringify({refreshToken:e})});if(!n.ok)return null;let r=await n.json();return r?.accessToken?r:null}catch{return null}}var ur=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com",bc="https://api.atlassian.com/oauth/token/accessible-resources";function lr(){let e=ae();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function Ro(e,t){let n=lr();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${ur}/api/oauth/jira/start`,{method:"POST",headers:n,body:JSON.stringify({connectionId:e,daemonPort:t})}),s=await r.json().catch(()=>null);return r.ok?s?.configured===!1?{configured:!1,error:s?.message??"Jira isn't set up on the server yet."}:s?.url?{url:s.url}:{error:"The server didn't return an authorize URL."}:{error:s?.message??`Couldn't start OAuth (HTTP ${r.status}).`}}catch(r){return{error:`Couldn't reach the SuperClawd backend (${String(r)}).`}}}async function To(e){let t=lr();if(!t)return null;try{let n=await fetch(`${ur}/api/oauth/jira/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}async function _o(e){let t=lr();if(!t)return null;try{let n=await fetch(`${ur}/api/oauth/jira/refresh`,{method:"POST",headers:t,body:JSON.stringify({refreshToken:e})});if(!n.ok)return null;let r=await n.json();return r?.accessToken?r:null}catch{return null}}async function Ao(e){try{let t=await fetch(bc,{headers:{authorization:`Bearer ${e}`,accept:"application/json"}});if(!t.ok)return[];let n=await t.json();return Array.isArray(n)?n:[]}catch{return[]}}var pr=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function fr(){let e=ae();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function No(e,t){let n=fr();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${pr}/api/oauth/asana/start`,{method:"POST",headers:n,body:JSON.stringify({connectionId:e,daemonPort:t})}),s=await r.json().catch(()=>null);return r.ok?s?.configured===!1?{configured:!1,error:s?.message??"Asana isn't set up on the server yet."}:s?.url?{url:s.url}:{error:"The server didn't return an authorize URL."}:{error:s?.message??`Couldn't start OAuth (HTTP ${r.status}).`}}catch(r){return{error:`Couldn't reach the SuperClawd backend (${String(r)}).`}}}async function Eo(e){let t=fr();if(!t)return null;try{let n=await fetch(`${pr}/api/oauth/asana/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}async function Co(e){let t=fr();if(!t)return null;try{let n=await fetch(`${pr}/api/oauth/asana/refresh`,{method:"POST",headers:t,body:JSON.stringify({refreshToken:e})});if(!n.ok)return null;let r=await n.json();return r?.accessToken?r:null}catch{return null}}var Po=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function Oo(){let e=ae();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function Do(e,t){let n=Oo();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${Po}/api/oauth/clickup/start`,{method:"POST",headers:n,body:JSON.stringify({connectionId:e,daemonPort:t})}),s=await r.json().catch(()=>null);return r.ok?s?.configured===!1?{configured:!1,error:s?.message??"ClickUp isn't set up on the server yet."}:s?.url?{url:s.url}:{error:"The server didn't return an authorize URL."}:{error:s?.message??`Couldn't start OAuth (HTTP ${r.status}).`}}catch(r){return{error:`Couldn't reach the SuperClawd backend (${String(r)}).`}}}async function jo(e){let t=Oo();if(!t)return null;try{let n=await fetch(`${Po}/api/oauth/clickup/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}function $o(){return Promise.resolve(null)}var Mo=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function Lo(){let e=ae();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function Go(e,t){let n=Lo();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${Mo}/api/oauth/monday/start`,{method:"POST",headers:n,body:JSON.stringify({connectionId:e,daemonPort:t})}),s=await r.json().catch(()=>null);return r.ok?s?.configured===!1?{configured:!1,error:s?.message??"Monday isn't set up on the server yet."}:s?.url?{url:s.url}:{error:"The server didn't return an authorize URL."}:{error:s?.message??`Couldn't start OAuth (HTTP ${r.status}).`}}catch(r){return{error:`Couldn't reach the SuperClawd backend (${String(r)}).`}}}async function Uo(e){let t=Lo();if(!t)return null;try{let n=await fetch(`${Mo}/api/oauth/monday/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}function Bo(){return Promise.resolve(null)}var Sc=100;async function $t(e,t,n){return await Promise.all(e.map(async r=>{try{let o=[...await t(r.id.slice(n.length))].sort((i,c)=>(i.createdAt??"").localeCompare(c.createdAt??""));r.comments=o.slice(-Sc)}catch{}})),e}var Ic={idPrefix:"lin_",async fetchDiscovery(e,t,n){return(await Ys(t,n)).map(r=>er(r,e.id,e.workspaceId))},async fetchByIds(e,t,n){let r=(await Vs(t,n)).map(s=>er(s,e.id,e.workspaceId));return $t(r,s=>Zs(t,s),"lin_")},refresh:vo};function qo(e){if(!e.cloudId)throw Object.assign(new Error("Jira connection has no cloudId (reconnect)"),{terminal:!0});return e.cloudId}var xc={idPrefix:"jira_",async fetchDiscovery(e,t,n){let r=e.providerAccountName??"";return(await ro(qo(e),t,n)).map(s=>nr(s,e.id,e.workspaceId,r))},async fetchByIds(e,t,n){let r=e.providerAccountName??"",s=qo(e),o=(await so(s,t,n)).map(i=>nr(i,e.id,e.workspaceId,r));return $t(o,i=>oo(s,t,i),"jira_")},refresh:_o};function Fo(e,t){if(!e.providerAccountId)throw Object.assign(new Error(`${t} connection has no account scope (reconnect)`),{terminal:!0});return e.providerAccountId}var vc={idPrefix:"asana_",async fetchDiscovery(e,t,n){return(await co(Fo(e,"Asana"),t,n)).map(r=>rr(r,e.id,e.workspaceId))},async fetchByIds(e,t,n){let r=(await uo(t,n)).map(s=>rr(s,e.id,e.workspaceId));return $t(r,s=>lo(t,s),"asana_")},refresh:Co},Rc={idPrefix:"clickup_",async fetchDiscovery(e,t,n){return(await fo(Fo(e,"ClickUp"),t,n)).map(r=>ir(r,e.id,e.workspaceId))},async fetchByIds(e,t,n){let r=(await mo(t,n)).map(s=>ir(s,e.id,e.workspaceId));return $t(r,s=>go(t,s),"clickup_")},refresh:$o},Tc={idPrefix:"monday_",async fetchDiscovery(e,t,n){return(await yo(t,n)).map(r=>ar(r,e.providerAccountId,e.id,e.workspaceId))},async fetchByIds(e,t,n){let r=(await wo(t,n)).map(s=>ar(s,e.providerAccountId,e.id,e.workspaceId));return $t(r,s=>bo(t,s),"monday_")},refresh:Bo},_c={linear:Ic,jira:xc,asana:vc,clickup:Rc,monday:Tc};function Mt(e){return _c[e]??null}Je();async function Fe(e){await ze.upsert({connectionId:e.connectionId,userId:A(),provider:e.provider,accessToken:Xe(e.accessToken),refreshToken:e.refreshToken?Xe(e.refreshToken):null,scope:e.scope??null,expiresAt:e.expiresAt??null})}async function wn(e){let t=await ze.findByPk(e);if(!t)return null;let n=t.get({plain:!0});if(n.userId!==A())return null;let r=n.refreshToken??null;return{connectionId:e,provider:String(n.provider),accessToken:Ye(String(n.accessToken)),refreshToken:r?Ye(r):null,scope:n.scope??null,expiresAt:n.expiresAt??null}}async function Wo(e){await ze.destroy({where:{connectionId:e,userId:A()}})}async function mr(e,t,n){if(!t.refreshToken)return null;let r=await n.refresh(t.provider,t.refreshToken);return r?(await n.saveToken({connectionId:e,provider:t.provider,accessToken:r.accessToken,refreshToken:r.refreshToken??t.refreshToken,scope:r.scope??t.scope,expiresAt:r.expiresAt??t.expiresAt}),r.accessToken):null}async function Ko(e,t){let n=await t.getToken(e);if(!n)return null;let r=t.now?t.now():Date.now();return(n.expiresAt?Date.parse(n.expiresAt)-r<6e4:!1)?mr(e,n,t):n.accessToken}function Cc(e,t){return e.filter(n=>n.provider!=="local"&&n.linkStatus==="linked"&&(n.authStatus==="connected"||n.authStatus==="needs_refresh")&&(!t||n.workspaceId!=null&&t.includes(n.workspaceId)))}async function Pc(e){if(e.isMock())return;let t=Cc(e.listConnections(),e.connectedWorkspaces());for(let n of t)try{await e.syncOne(n)}catch{}}var gr=null;function Qo(e,t=6e5){gr||(gr=setInterval(()=>void Pc(e),t),gr.unref?.())}import{execFile as Dc}from"node:child_process";function bn(e){return new Promise(t=>{Dc("gh",e,{maxBuffer:10*1024*1024},(n,r)=>{t({code:n&&typeof n.code=="number"?n.code:n?1:0,stdout:String(r??"")})})})}var jc=new Set(["FAILURE","CANCELLED","TIMED_OUT","ACTION_REQUIRED","STARTUP_FAILURE","STALE"]),$c=new Set(["FAILURE","ERROR"]),Ho=new Set(["QUEUED","IN_PROGRESS","WAITING","PENDING","REQUESTED"]);function Mc(e){if(!e.length)return{ci:"none",failing:[]};let t=[],n=!1;for(let r of e){let s=r.name||r.context||"check",o=r.conclusion&&jc.has(r.conclusion)||r.state&&$c.has(r.state),i=r.status&&Ho.has(r.status)||r.state&&Ho.has(r.state)||r.__typename==="CheckRun"&&r.status!=="COMPLETED"&&!r.conclusion;o?t.push(s):i&&(n=!0)}return t.length?{ci:"failing",failing:t}:n?{ci:"pending",failing:[]}:{ci:"passing",failing:[]}}async function Lc(e){let t=await bn(["pr","view",e,"--json","state,statusCheckRollup"]);if(t.code!==0)return{state:"unknown",ci:"unknown",failingChecks:[]};let n;try{n=JSON.parse(t.stdout)}catch{return{state:"unknown",ci:"unknown",failingChecks:[]}}let r=n.state==="MERGED"?"merged":n.state==="CLOSED"?"closed":n.state==="OPEN"?"open":"unknown",{ci:s,failing:o}=Mc(n.statusCheckRollup??[]);return{state:r,ci:s,failingChecks:o}}function Jo(e){let t=/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/.exec(e);return t?{owner:t[1],repo:t[2],num:Number(t[3])}:null}function zo(e){let t=Jo(e);return t?`${t.repo}#${t.num}`:e}function Gc(e){if(!e.length)return{state:"unknown",ci:"unknown",failingChecks:[],perPr:[]};let t=e.map(i=>i.status.state),n=e.map(i=>i.status.ci),r=t.some(i=>i==="open")?"open":t.every(i=>i==="merged")?"merged":t.every(i=>i==="merged"||i==="closed")?"closed":"unknown",s=n.some(i=>i==="failing")?"failing":n.some(i=>i==="pending")?"pending":n.some(i=>i==="unknown")?"unknown":n.some(i=>i==="passing")?"passing":"none",o=[];for(let i of e){if(i.status.ci!=="failing")continue;let c=zo(i.url);if(i.status.failingChecks.length)for(let d of i.status.failingChecks)o.push(`${c} ${d}`);else o.push(`${c} checks`)}return{state:r,ci:s,failingChecks:o,perPr:e}}async function Xo(e){let t=await Promise.all(e.map(async n=>({url:n,status:await Lc(n)})));return Gc(t)}async function Uc(e){let t=Jo(e);if(!t)return{count:0,digest:[]};let r=await bn(["api","graphql","-f",`query=query($owner:String!,$repo:String!,$num:Int!){
101
+ `,e)).me?.account??null}catch{return null}}var Dr=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function jr(){let e=ge();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function si(e,t){let n=jr();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${Dr}/api/oauth/linear/start`,{method:"POST",headers:n,body:JSON.stringify({connectionId:e,daemonPort:t})}),s=await r.json().catch(()=>null);return r.ok?s?.configured===!1?{configured:!1,error:s?.message??"Linear isn't set up on the server yet."}:s?.url?{url:s.url}:{error:"The server didn't return an authorize URL."}:{error:s?.message??`Couldn't start OAuth (HTTP ${r.status}).`}}catch(r){return{error:`Couldn't reach the SuperClawd backend (${String(r)}).`}}}async function oi(e){let t=jr();if(!t)return null;try{let n=await fetch(`${Dr}/api/oauth/linear/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}async function ii(e){let t=jr();if(!t)return null;try{let n=await fetch(`${Dr}/api/oauth/linear/refresh`,{method:"POST",headers:t,body:JSON.stringify({refreshToken:e})});if(!n.ok)return null;let r=await n.json();return r?.accessToken?r:null}catch{return null}}var Mr=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com",od="https://api.atlassian.com/oauth/token/accessible-resources";function $r(){let e=ge();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function ai(e,t){let n=$r();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${Mr}/api/oauth/jira/start`,{method:"POST",headers:n,body:JSON.stringify({connectionId:e,daemonPort:t})}),s=await r.json().catch(()=>null);return r.ok?s?.configured===!1?{configured:!1,error:s?.message??"Jira isn't set up on the server yet."}:s?.url?{url:s.url}:{error:"The server didn't return an authorize URL."}:{error:s?.message??`Couldn't start OAuth (HTTP ${r.status}).`}}catch(r){return{error:`Couldn't reach the SuperClawd backend (${String(r)}).`}}}async function ci(e){let t=$r();if(!t)return null;try{let n=await fetch(`${Mr}/api/oauth/jira/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}async function di(e){let t=$r();if(!t)return null;try{let n=await fetch(`${Mr}/api/oauth/jira/refresh`,{method:"POST",headers:t,body:JSON.stringify({refreshToken:e})});if(!n.ok)return null;let r=await n.json();return r?.accessToken?r:null}catch{return null}}async function ui(e){try{let t=await fetch(od,{headers:{authorization:`Bearer ${e}`,accept:"application/json"}});if(!t.ok)return[];let n=await t.json();return Array.isArray(n)?n:[]}catch{return[]}}var Br=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function Lr(){let e=ge();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function li(e,t){let n=Lr();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${Br}/api/oauth/asana/start`,{method:"POST",headers:n,body:JSON.stringify({connectionId:e,daemonPort:t})}),s=await r.json().catch(()=>null);return r.ok?s?.configured===!1?{configured:!1,error:s?.message??"Asana isn't set up on the server yet."}:s?.url?{url:s.url}:{error:"The server didn't return an authorize URL."}:{error:s?.message??`Couldn't start OAuth (HTTP ${r.status}).`}}catch(r){return{error:`Couldn't reach the SuperClawd backend (${String(r)}).`}}}async function pi(e){let t=Lr();if(!t)return null;try{let n=await fetch(`${Br}/api/oauth/asana/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}async function fi(e){let t=Lr();if(!t)return null;try{let n=await fetch(`${Br}/api/oauth/asana/refresh`,{method:"POST",headers:t,body:JSON.stringify({refreshToken:e})});if(!n.ok)return null;let r=await n.json();return r?.accessToken?r:null}catch{return null}}var mi=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function gi(){let e=ge();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function hi(e,t){let n=gi();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${mi}/api/oauth/clickup/start`,{method:"POST",headers:n,body:JSON.stringify({connectionId:e,daemonPort:t})}),s=await r.json().catch(()=>null);return r.ok?s?.configured===!1?{configured:!1,error:s?.message??"ClickUp isn't set up on the server yet."}:s?.url?{url:s.url}:{error:"The server didn't return an authorize URL."}:{error:s?.message??`Couldn't start OAuth (HTTP ${r.status}).`}}catch(r){return{error:`Couldn't reach the SuperClawd backend (${String(r)}).`}}}async function ki(e){let t=gi();if(!t)return null;try{let n=await fetch(`${mi}/api/oauth/clickup/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}function yi(){return Promise.resolve(null)}var wi=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function bi(){let e=ge();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function Si(e,t){let n=bi();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${wi}/api/oauth/monday/start`,{method:"POST",headers:n,body:JSON.stringify({connectionId:e,daemonPort:t})}),s=await r.json().catch(()=>null);return r.ok?s?.configured===!1?{configured:!1,error:s?.message??"Monday isn't set up on the server yet."}:s?.url?{url:s.url}:{error:"The server didn't return an authorize URL."}:{error:s?.message??`Couldn't start OAuth (HTTP ${r.status}).`}}catch(r){return{error:`Couldn't reach the SuperClawd backend (${String(r)}).`}}}async function Ii(e){let t=bi();if(!t)return null;try{let n=await fetch(`${wi}/api/oauth/monday/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}function xi(){return Promise.resolve(null)}var id=100;async function rn(e,t,n){return await Promise.all(e.map(async r=>{try{let o=[...await t(r.id.slice(n.length))].sort((i,c)=>(i.createdAt??"").localeCompare(c.createdAt??""));r.comments=o.slice(-id)}catch{}})),e}var ad={idPrefix:"lin_",async fetchDiscovery(e,t,n){return(await Do(t,n)).map(r=>Tr(r,e.id,e.workspaceId))},async fetchByIds(e,t,n){let r=(await jo(t,n)).map(s=>Tr(s,e.id,e.workspaceId));return rn(r,s=>Mo(t,s),"lin_")},refresh:ii};function vi(e){if(!e.cloudId)throw Object.assign(new Error("Jira connection has no cloudId (reconnect)"),{terminal:!0});return e.cloudId}var cd={idPrefix:"jira_",async fetchDiscovery(e,t,n){let r=e.providerAccountName??"";return(await Go(vi(e),t,n)).map(s=>Ar(s,e.id,e.workspaceId,r))},async fetchByIds(e,t,n){let r=e.providerAccountName??"",s=vi(e),o=(await Uo(s,t,n)).map(i=>Ar(i,e.id,e.workspaceId,r));return rn(o,i=>qo(s,t,i),"jira_")},refresh:di};function Ri(e,t){if(!e.providerAccountId)throw Object.assign(new Error(`${t} connection has no account scope (reconnect)`),{terminal:!0});return e.providerAccountId}var dd={idPrefix:"asana_",async fetchDiscovery(e,t,n){return(await Ko(Ri(e,"Asana"),t,n)).map(r=>Nr(r,e.id,e.workspaceId))},async fetchByIds(e,t,n){let r=(await Ho(t,n)).map(s=>Nr(s,e.id,e.workspaceId));return rn(r,s=>Qo(t,s),"asana_")},refresh:fi},ud={idPrefix:"clickup_",async fetchDiscovery(e,t,n){return(await zo(Ri(e,"ClickUp"),t,n)).map(r=>Pr(r,e.id,e.workspaceId))},async fetchByIds(e,t,n){let r=(await Xo(t,n)).map(s=>Pr(s,e.id,e.workspaceId));return rn(r,s=>Yo(t,s),"clickup_")},refresh:yi},ld={idPrefix:"monday_",async fetchDiscovery(e,t,n){return(await ei(t,n)).map(r=>Or(r,e.providerAccountId,e.id,e.workspaceId))},async fetchByIds(e,t,n){let r=(await ti(t,n)).map(s=>Or(s,e.providerAccountId,e.id,e.workspaceId));return rn(r,s=>ni(t,s),"monday_")},refresh:xi},pd={linear:ad,jira:cd,asana:dd,clickup:ud,monday:ld};function sn(e){return pd[e]??null}dt();async function rt(e){await ut.upsert({connectionId:e.connectionId,userId:E(),provider:e.provider,accessToken:lt(e.accessToken),refreshToken:e.refreshToken?lt(e.refreshToken):null,scope:e.scope??null,expiresAt:e.expiresAt??null})}async function Un(e){let t=await ut.findByPk(e);if(!t)return null;let n=t.get({plain:!0});if(n.userId!==E())return null;let r=n.refreshToken??null;return{connectionId:e,provider:String(n.provider),accessToken:pt(String(n.accessToken)),refreshToken:r?pt(r):null,scope:n.scope??null,expiresAt:n.expiresAt??null}}async function Ti(e){await ut.destroy({where:{connectionId:e,userId:E()}})}async function Gr(e,t,n){if(!t.refreshToken)return null;let r=await n.refresh(t.provider,t.refreshToken);return r?(await n.saveToken({connectionId:e,provider:t.provider,accessToken:r.accessToken,refreshToken:r.refreshToken??t.refreshToken,scope:r.scope??t.scope,expiresAt:r.expiresAt??t.expiresAt}),r.accessToken):null}async function _i(e,t){let n=await t.getToken(e);if(!n)return null;let r=t.now?t.now():Date.now();return(n.expiresAt?Date.parse(n.expiresAt)-r<6e4:!1)?Gr(e,n,t):n.accessToken}function hd(e,t){return e.filter(n=>n.provider!=="local"&&n.linkStatus==="linked"&&(n.authStatus==="connected"||n.authStatus==="needs_refresh")&&(!t||n.workspaceId!=null&&t.includes(n.workspaceId)))}async function kd(e){if(e.isMock())return;let t=hd(e.listConnections(),e.connectedWorkspaces());for(let n of t)try{await e.syncOne(n)}catch{}}var Ur=null;function Ai(e,t=6e5){Ur||(Ur=setInterval(()=>void kd(e),t),Ur.unref?.())}import{execFile as wd}from"node:child_process";function qn(e){return new Promise(t=>{wd("gh",e,{maxBuffer:10*1024*1024},(n,r)=>{t({code:n&&typeof n.code=="number"?n.code:n?1:0,stdout:String(r??"")})})})}var bd=new Set(["FAILURE","CANCELLED","TIMED_OUT","ACTION_REQUIRED","STARTUP_FAILURE","STALE"]),Sd=new Set(["FAILURE","ERROR"]),Ni=new Set(["QUEUED","IN_PROGRESS","WAITING","PENDING","REQUESTED"]);function Id(e){if(!e.length)return{ci:"none",failing:[]};let t=[],n=!1;for(let r of e){let s=r.name||r.context||"check",o=r.conclusion&&bd.has(r.conclusion)||r.state&&Sd.has(r.state),i=r.status&&Ni.has(r.status)||r.state&&Ni.has(r.state)||r.__typename==="CheckRun"&&r.status!=="COMPLETED"&&!r.conclusion;o?t.push(s):i&&(n=!0)}return t.length?{ci:"failing",failing:t}:n?{ci:"pending",failing:[]}:{ci:"passing",failing:[]}}async function xd(e){let t=await qn(["pr","view",e,"--json","state,statusCheckRollup"]);if(t.code!==0)return{state:"unknown",ci:"unknown",failingChecks:[]};let n;try{n=JSON.parse(t.stdout)}catch{return{state:"unknown",ci:"unknown",failingChecks:[]}}let r=n.state==="MERGED"?"merged":n.state==="CLOSED"?"closed":n.state==="OPEN"?"open":"unknown",{ci:s,failing:o}=Id(n.statusCheckRollup??[]);return{state:r,ci:s,failingChecks:o}}function Ei(e){let t=/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/.exec(e);return t?{owner:t[1],repo:t[2],num:Number(t[3])}:null}function Ci(e){let t=Ei(e);return t?`${t.repo}#${t.num}`:e}function vd(e){if(!e.length)return{state:"unknown",ci:"unknown",failingChecks:[],perPr:[]};let t=e.map(i=>i.status.state),n=e.map(i=>i.status.ci),r=t.some(i=>i==="open")?"open":t.every(i=>i==="merged")?"merged":t.every(i=>i==="merged"||i==="closed")?"closed":"unknown",s=n.some(i=>i==="failing")?"failing":n.some(i=>i==="pending")?"pending":n.some(i=>i==="unknown")?"unknown":n.some(i=>i==="passing")?"passing":"none",o=[];for(let i of e){if(i.status.ci!=="failing")continue;let c=Ci(i.url);if(i.status.failingChecks.length)for(let d of i.status.failingChecks)o.push(`${c} ${d}`);else o.push(`${c} checks`)}return{state:r,ci:s,failingChecks:o,perPr:e}}async function Pi(e){let t=await Promise.all(e.map(async n=>({url:n,status:await xd(n)})));return vd(t)}async function Rd(e){let t=Ei(e);if(!t)return{count:0,digest:[]};let r=await qn(["api","graphql","-f",`query=query($owner:String!,$repo:String!,$num:Int!){
102
102
  repository(owner:$owner,name:$repo){ pullRequest(number:$num){
103
103
  reviewThreads(first:100){ nodes {
104
104
  isResolved isOutdated
105
105
  comments(first:1){ nodes { body path line author { login } } }
106
106
  } } } } }`,"-F",`owner=${t.owner}`,"-F",`repo=${t.repo}`,"-F",`num=${t.num}`]);if(r.code!==0)return{count:0,digest:[]};try{let s=JSON.parse(r.stdout)?.data?.repository?.pullRequest?.reviewThreads?.nodes??[],o=[];for(let i of s){if(i.isResolved)continue;let c=i.comments?.nodes?.[0];if(!c)continue;let d=c.path?`${c.path}${c.line?`:${c.line}`:""}`:"PR",u=i.isOutdated?" [outdated \u2014 the line has since changed]":"";o.push(`${d}${u} \u2014 ${String(c.body??"").split(`
107
- `)[0].slice(0,160)}`)}return{count:o.length,digest:o}}catch{return{count:0,digest:[]}}}async function Yo(e){let t=await Promise.all(e.map(async r=>({tag:zo(r),c:await Uc(r)}))),n=[];for(let{tag:r,c:s}of t)for(let o of s.digest)n.push(`${r} ${o}`);return{count:n.length,digest:n}}var Vo="<!-- superclawd:related -->",Zo="<!-- /superclawd:related -->";function Bc(e,t,n){let r=t.filter(s=>s!==n);return r.length?[Vo,`**Ticket:** ${e}`,"","**Related PRs (same ticket):**",...r.map(s=>`- ${s}`),Zo].join(`
108
- `):""}function qc(e,t){let n=o=>o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`\\n*${n(Vo)}[\\s\\S]*?${n(Zo)}`),s=e.replace(r,"").trimEnd();return t?(s?s+`
107
+ `)[0].slice(0,160)}`)}return{count:o.length,digest:o}}catch{return{count:0,digest:[]}}}async function Oi(e){let t=await Promise.all(e.map(async r=>({tag:Ci(r),c:await Rd(r)}))),n=[];for(let{tag:r,c:s}of t)for(let o of s.digest)n.push(`${r} ${o}`);return{count:n.length,digest:n}}var Di="<!-- superclawd:related -->",ji="<!-- /superclawd:related -->";function Td(e,t,n){let r=t.filter(s=>s!==n);return r.length?[Di,`**Ticket:** ${e}`,"","**Related PRs (same ticket):**",...r.map(s=>`- ${s}`),ji].join(`
108
+ `):""}function _d(e,t){let n=o=>o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`\\n*${n(Di)}[\\s\\S]*?${n(ji)}`),s=e.replace(r,"").trimEnd();return t?(s?s+`
109
109
 
110
- `:"")+t:s}async function ei(e,t){if(!(t.length<2))for(let n of t){let r=await bn(["pr","view",n,"--json","body"]);if(r.code!==0)continue;let s="";try{s=JSON.parse(r.stdout)?.body??""}catch{continue}let o=qc(s,Bc(e,t,n));o!==s&&await bn(["pr","edit",n,"--body",o])}}function Wc(e){return Math.max(1,e.prMonitorIntervalMinutes??30)*6e4}function Lt(e){return e.prMonitorMaxEngagements??5}function ti(e,t,n){return e.prMonitorLastAt?n-Date.parse(e.prMonitorLastAt)>=Wc(t):!0}function ni(e,t,n,r){if(n.state==="merged")return{kind:"disarm",note:"PR merged \u2014 monitoring stopped."};if(n.state==="closed")return{kind:"disarm",note:"PR was closed \u2014 monitoring stopped."};let s=(e.prMonitorCount??0)>=Lt(t);return n.ci==="failing"?s?{kind:"disarm",note:`Monitor reached its ${Lt(t)}-engagement cap with CI still failing \u2014 needs a human.`}:{kind:"engage",reason:"ci",prompt:Kc(e,n)}:n.ci==="passing"?t.prMonitorReplyToComments&&(r?.count??0)>0?s?{kind:"disarm",note:`Monitor reached its ${Lt(t)}-engagement cap with review comments still open \u2014 needs a human.`}:{kind:"engage",reason:"comments",prompt:Qc(e,r)}:{kind:"disarm",note:t.prMonitorReplyToComments?"CI green and no open review comments \u2014 ready for review.":"CI is green \u2014 ready for review."}:{kind:"stamp"}}function ri(e){let t=(e.prLinks??[]).map(n=>n.url).filter(Boolean);return t.length===0?"the open PR":t.length===1?t[0]:`this ticket's PRs:
110
+ `:"")+t:s}async function Mi(e,t){if(!(t.length<2))for(let n of t){let r=await qn(["pr","view",n,"--json","body"]);if(r.code!==0)continue;let s="";try{s=JSON.parse(r.stdout)?.body??""}catch{continue}let o=_d(s,Td(e,t,n));o!==s&&await qn(["pr","edit",n,"--body",o])}}function Nd(e){return Math.max(1,e.prMonitorIntervalMinutes??30)*6e4}function on(e){return e.prMonitorMaxEngagements??5}function $i(e,t,n){return e.prMonitorLastAt?n-Date.parse(e.prMonitorLastAt)>=Nd(t):!0}function Bi(e,t,n,r){if(n.state==="merged")return{kind:"disarm",note:"PR merged \u2014 monitoring stopped."};if(n.state==="closed")return{kind:"disarm",note:"PR was closed \u2014 monitoring stopped."};let s=(e.prMonitorCount??0)>=on(t);return n.ci==="failing"?s?{kind:"disarm",note:`Monitor reached its ${on(t)}-engagement cap with CI still failing \u2014 needs a human.`}:{kind:"engage",reason:"ci",prompt:Ed(e,n)}:n.ci==="passing"?t.prMonitorReplyToComments&&(r?.count??0)>0?s?{kind:"disarm",note:`Monitor reached its ${on(t)}-engagement cap with review comments still open \u2014 needs a human.`}:{kind:"engage",reason:"comments",prompt:Cd(e,r)}:{kind:"disarm",note:t.prMonitorReplyToComments?"CI green and no open review comments \u2014 ready for review.":"CI is green \u2014 ready for review."}:{kind:"stamp"}}function Li(e){let t=(e.prLinks??[]).map(n=>n.url).filter(Boolean);return t.length===0?"the open PR":t.length===1?t[0]:`this ticket's PRs:
111
111
  ${t.map(n=>`- ${n}`).join(`
112
- `)}`}function Kc(e,t){let n=ri(e),r=t.failingChecks.length?t.failingChecks.join(", "):"one or more checks";return[`This is an automated PR-monitor pass for ${n}
112
+ `)}`}function Ed(e,t){let n=Li(e),r=t.failingChecks.length?t.failingChecks.join(", "):"one or more checks";return[`This is an automated PR-monitor pass for ${n}
113
113
 
114
114
  CI is FAILING (${r}).`,"Continue in your existing worktree(s)/branch(es) (per the note above): diagnose and FIX the failing checks, commit, and push to the SAME branch(es) to update the affected PR(s).","Do EXACTLY ONE pass of work, then STOP \u2014 the system re-checks CI on its own schedule, so do NOT wait, poll, sleep, or loop. If you conclude the failures aren't something you can or should fix, record a short note (add_note) explaining why and stop."].join(`
115
115
 
116
- `)}function Qc(e,t){let n=ri(e),r=t.digest.map(s=>`- ${s}`).join(`
116
+ `)}function Cd(e,t){let n=Li(e),r=t.digest.map(s=>`- ${s}`).join(`
117
117
  `);return[`This is an automated PR-monitor pass for ${n}
118
118
 
119
119
  CI is green, but there are unresolved review comments:`,r,"In your existing worktree(s)/branch(es) (per the note above), address each one: make the requested change and reply on the thread, OR \u2014 if a comment is wrong or doesn't make sense \u2014 reply explaining why you're not making the change. Commit and push any code changes to the SAME branch(es), then RESOLVE the threads you've handled (`gh api graphql` with resolveReviewThread). Keep replies concise and factual.","Do EXACTLY ONE pass, then STOP \u2014 the system re-checks on its own schedule, so do NOT wait, poll, sleep, or loop."].join(`
120
120
 
121
- `)}var It=3,f=In();f.use(Jc());f.use(In.json());var Gt=Number(process.env.PIPELINES_PORT||process.env.PIPELINES_MOCK_PORT||63210),br=Number(process.env.PIPELINES_PUBLIC_PORT||Gt),Xc=e=>new Promise(t=>setTimeout(t,e)),fe=e=>S[e]??"backlog";function Ut(e,t){return t instanceof re?e.status(t.status).json({error:t.message,...t.code?{code:t.code}:{},...t.extra??{}}):(console.error(t),e.status(500).json({error:"internal error"}))}function ge(e,t){return t instanceof N?e.status(t.status).json({error:t.message,...t.extra??{}}):(console.error(t),e.status(500).json({error:"internal error"}))}var ii=()=>new Set(l.connectedWorkspaces??[]),xn=e=>l.workspaceDirs?.[e]??"~";function vn(){let e=ii();j.length=0,j.push(...At().filter(t=>e.has(t.id)))}async function Yc(){let e=At();if(_()){l.connectedWorkspaces=e.map(r=>r.id);return}if(!Array.isArray(l.connectedWorkspaces)){let r=[...new Set(y.filter(s=>s.workspaceId).map(s=>s.workspaceId))].filter(s=>e.some(o=>o.id===s)).slice(0,en);l.connectedWorkspaces=r,await X()}vn();let t={...l.workspaceDirs??{}},n=!1;for(let r of j)t[r.id]||(t[r.id]="~",n=!0);n&&(l.workspaceDirs=t,await X()),await Ft()}f.get("/api/session",(e,t)=>t.json(he));f.get("/api/workspaces",(e,t)=>t.json(j));f.get("/api/teams",async(e,t)=>{if(_())return t.json(Re);let n=typeof e.query.workspaceId=="string"?e.query.workspaceId:"";if(!n)return t.json([]);let r=await Nt(n);t.json(r?.teams??[])});f.get("/api/agents",async(e,t)=>{if(_())return t.json(Te);let n=typeof e.query.workspaceId=="string"?e.query.workspaceId:"";if(!n)return t.json([]);let r=await Nt(n);t.json(r?.agents??[])});f.get("/api/workspaces/available",(e,t)=>{let n=ii();t.json(At().map(r=>({...r,connected:n.has(r.id),workingDir:xn(r.id)})))});f.post("/api/workspaces/:id/connect",async(e,t)=>{let n=At().find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"workspace not accessible"});let r=l.connectedWorkspaces??[];if(!r.includes(n.id)){if(r.length>=en)return t.status(409).json({error:`You can connect at most ${en} workspaces.`});l.connectedWorkspaces=[...r,n.id]}return l.workspaceDirs?.[n.id]||(l.workspaceDirs={...l.workspaceDirs??{},[n.id]:"~"}),await X(),vn(),_()||await Ft(),t.json({id:n.id,connected:!0})});f.post("/api/workspaces/:id/working-dir",async(e,t)=>{let n=e.params.id,r=String(e.body?.workingDir??"").trim()||"~";return l.workspaceDirs={...l.workspaceDirs??{},[n]:r},await X(),t.json({id:n,workingDir:r})});f.post("/api/workspaces/:id/disconnect",async(e,t)=>{let n=e.params.id,r=l.connectedWorkspaces??[];return r.includes(n)&&(l.connectedWorkspaces=r.filter(s=>s!==n),await X(),vn()),t.json({id:n,connected:!1})});f.get("/api/database/export",(e,t)=>{let n=y.map(r=>({...r,ticketCount:h.filter(s=>s.connectionId===r.id).length}));t.json({version:2,workspaces:j,teams:Re,agents:Te,connections:n,tickets:h,settings:l,schedules:E,scheduleOrder:H,scheduleRuns:B,searchable:J,notes:P,openQuestions:C,messagePresets:G,state:L})});f.post("/api/database/import",async(e,t)=>{let n=e.body;if(!n||typeof n!="object")return t.status(400).json({error:"invalid snapshot"});let r=(o,i)=>{Array.isArray(i)&&(o.length=0,o.push(...i))},s=(o,i)=>{if(i&&typeof i=="object"){for(let c of Object.keys(o))delete o[c];Object.assign(o,i)}};r(j,n.workspaces),r(Re,n.teams),r(Te,n.agents),r(y,n.connections);for(let o of y)o.provider!=="local"&&(o.authStatus="expired");r(h,n.tickets),r(J,n.searchable),r(P,n.notes),r(C,n.openQuestions),r(G,n.messagePresets),r(H,n.scheduleOrder),s(E,n.schedules),s(B,n.scheduleRuns),n.settings&&typeof n.settings=="object"&&Object.assign(l,n.settings),n.state&&typeof n.state=="object"&&Object.assign(L,n.state);for(let o of Object.keys(I))delete I[o];for(let o of Object.keys(x))delete x[o];for(let o of Object.keys(S))delete S[o];for(let o of Object.keys(M))delete M[o];return q.length=0,te.length=0,await Jr(),t.json({ok:!0})});f.post("/api/database/reset",async(e,t)=>(await zr(),vn(),t.json({ok:!0})));f.get("/api/fs/browse",(e,t)=>{let n=String(e.query.path??"").trim(),r=e.query.files==="1",s=n||Sn.homedir();s==="~"?s=Sn.homedir():s.startsWith("~/")&&(s=Q.join(Sn.homedir(),s.slice(2))),s=Q.resolve(s);try{let o=ve.readdirSync(s,{withFileTypes:!0}).filter(c=>!c.name.startsWith(".")).filter(c=>c.isDirectory()||r&&c.isFile()).map(c=>({name:c.name,path:Q.join(s,c.name),type:c.isDirectory()?"dir":"file"})).sort((c,d)=>c.type!==d.type?c.type==="dir"?-1:1:c.name.localeCompare(d.name)),i=Q.dirname(s);return t.json({path:s,parent:i===s?null:i,home:Sn.homedir(),entries:o})}catch(o){return t.status(400).json({error:`can't read ${s}: ${String(o)}`})}});f.get("/api/connections",(e,t)=>t.json(y));function Sr(e){let t=e??{},n=Array.isArray(t.labels)?t.labels.map(i=>String(i).trim()).filter(Boolean).slice(0,3):[],r=!!t.assignedToMe,s=r?"":String(t.assignee??"").trim(),o={};return n.length&&(o.labels=n),r?o.assignedToMe=!0:s&&(o.assignee=s),Object.keys(o).length?o:null}var ai={linear:"Linear",jira:"Jira",asana:"Asana",clickup:"ClickUp",monday:"Monday"},Vc=new Set(Object.keys(ai));function ci(e,t,n){return e==="jira"?Ro(t,n):e==="asana"?No(t,n):e==="clickup"?Do(t,n):e==="monday"?Go(t,n):Io(t,n)}f.post("/api/connections",async(e,t)=>{let n=String(e.body?.provider??"");if(!Vc.has(n))return t.status(400).json({error:"unsupported provider"});let r=ai[n],s=String(e.body?.name??"").trim(),o=String(e.body?.workingDir??"").trim(),i=j.find(m=>m.id===e.body?.workspaceId);if(e.body?.workspaceId&&!i)return t.status(400).json({error:"workspace not accessible"});if(i&&y.filter(g=>g.provider!=="local"&&g.linkStatus==="linked"&&g.workspaceId===i.id).length>=It)return t.json({configured:!0,message:`That workspace already has ${It} connections (the max).`});let d={id:`conn_${Ke().slice(0,8)}`,provider:n,providerAccountName:_()?`${r} (demo)`:r,...s?{displayName:s}:{},workspaceId:i?.id??null,workspaceName:i?.name??null,workingDir:o||null,linkStatus:i?"linked":"unlinked",authStatus:_()?"connected":"needs_refresh",lastSyncedAt:null,ticketCount:0,syncFilters:Sr(e.body?.syncFilters)};if(_())return y.push(d),await R(d),t.status(201).json({connection:d,mock:!0});let u=await ci(n,d.id,br);return u.url?(y.push(d),await R(d),t.status(201).json({connection:d,url:u.url})):t.json({configured:u.configured===!1?!1:void 0,message:u.error??`Couldn't start the ${r} connection.`})});f.post("/api/connections/:id/link",async(e,t)=>{let n=y.find(o=>o.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});let r=j.find(o=>o.id===e.body?.workspaceId);return r?y.filter(o=>o.id!==n.id&&o.provider!=="local"&&o.linkStatus==="linked"&&o.workspaceId===r.id).length>=It?t.status(409).json({error:`A workspace can have at most ${It} connections.`}):(n.workspaceId=r.id,n.workspaceName=r.name,typeof e.body?.workingDir=="string"&&e.body.workingDir.trim()&&(n.workingDir=e.body.workingDir.trim()),typeof e.body?.name=="string"&&e.body.name.trim()&&(n.displayName=e.body.name.trim()),"syncFilters"in(e.body??{})&&n.provider!=="local"&&(n.syncFilters=Sr(e.body.syncFilters)),n.linkStatus="linked",delete n.linkLostReason,n.lastSyncedAt=new Date().toISOString(),await R(n),t.json(n)):t.status(400).json({error:"workspace not accessible"})});f.patch("/api/connections/:id",async(e,t)=>{let n=y.find(r=>r.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});if(typeof e.body?.name=="string"){let r=e.body.name.trim();r?n.displayName=r:delete n.displayName}if(e.body?.unlink===!0){if(n.provider==="local")return t.status(400).json({error:"a local board can't be unlinked"});n.workspaceId=null,n.workspaceName=null,n.workingDir=null,n.linkStatus="unlinked"}if(typeof e.body?.workspaceId=="string"&&n.provider!=="local"){let r=j.find(s=>s.id===e.body.workspaceId);if(!r)return t.status(400).json({error:"workspace not accessible"});if(r.id!==n.workspaceId&&y.filter(o=>o.id!==n.id&&o.provider!=="local"&&o.linkStatus==="linked"&&o.workspaceId===r.id).length>=It)return t.status(409).json({error:`A workspace can have at most ${It} connections.`});n.workspaceId=r.id,n.workspaceName=r.name,n.linkStatus="linked"}return typeof e.body?.workingDir=="string"&&e.body.workingDir.trim()&&(n.workingDir=e.body.workingDir.trim()),"syncFilters"in(e.body??{})&&n.provider!=="local"&&(n.syncFilters=Sr(e.body.syncFilters)),await R(n),t.json(n)});f.delete("/api/connections/:id",async(e,t)=>{let n=y.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});if(n.provider==="local")return t.status(400).json({error:"a local board can't be disconnected"});for(let s of h.filter(o=>o.connectionId===n.id)){let o=x[s.id];o&&(await it(o),delete I[o],delete x[s.id]),delete S[s.id],await Wt(s.id)}for(let s=h.length-1;s>=0;s--)h[s].connectionId===n.id&&h.splice(s,1);for(let s=J.length-1;s>=0;s--)J[s].connectionId===n.id&&J.splice(s,1);let r=y.findIndex(s=>s.id===n.id);return r!==-1&&y.splice(r,1),await $r(n.id),await Wo(n.id),t.status(204).end()});f.post("/api/connections/:id/oauth/start",async(e,t)=>{let n=y.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});if(!Mt(n.provider))return t.status(400).json({error:"not a vendor connection"});let r=await ci(n.provider,n.id,br);return r.url?t.json({url:r.url}):t.status(r.configured===!1?501:502).json({error:r.error??"Couldn't start OAuth."})});f.get("/api/oauth/linear/deposit",async(e,t)=>{let n=String(e.query.code??""),r=String(e.query.connectionId??""),s=y.find(i=>i.id===r);if(!n||!s)return t.redirect("/settings/connections?linear=error");let o=await xo(n);return o?(await Fe({connectionId:s.id,provider:"linear",accessToken:o.accessToken,refreshToken:o.refreshToken,scope:o.scope,expiresAt:o.expiresAt}),s.authStatus="connected",await R(s),t.redirect("/settings/connections?linear=connected")):(s.authStatus="error",await R(s),t.redirect("/settings/connections?linear=error"))});f.get("/api/oauth/jira/deposit",async(e,t)=>{let n=String(e.query.code??""),r=String(e.query.connectionId??""),s=y.find(u=>u.id===r);if(!n||!s)return t.redirect("/settings/connections?jira=error");let o=await To(n);if(!o)return s.authStatus="error",await R(s),t.redirect("/settings/connections?jira=error");let c=(await Ao(o.accessToken))[0];if(!c?.id)return s.authStatus="error",await R(s),t.redirect("/settings/connections?jira=error");await Fe({connectionId:s.id,provider:"jira",accessToken:o.accessToken,refreshToken:o.refreshToken,scope:o.scope,expiresAt:o.expiresAt}),s.cloudId=c.id;let d=c.url?c.url.replace(/^https?:\/\//,"").replace(/\/+$/,""):void 0;return s.providerAccountName=d||c.name||"Jira",s.authStatus="connected",await R(s),t.redirect("/settings/connections?jira=connected")});f.get("/api/oauth/asana/deposit",async(e,t)=>{let n=String(e.query.code??""),r=String(e.query.connectionId??""),s=y.find(d=>d.id===r);if(!n||!s)return t.redirect("/settings/connections?asana=error");let o=await Eo(n);if(!o)return s.authStatus="error",await R(s),t.redirect("/settings/connections?asana=error");let c=(await po(o.accessToken))[0];return c?.gid?(await Fe({connectionId:s.id,provider:"asana",accessToken:o.accessToken,refreshToken:o.refreshToken,scope:o.scope,expiresAt:o.expiresAt}),s.providerAccountId=c.gid,s.providerAccountName=c.name||"Asana",s.authStatus="connected",await R(s),t.redirect("/settings/connections?asana=connected")):(s.authStatus="error",await R(s),t.redirect("/settings/connections?asana=error"))});f.get("/api/oauth/clickup/deposit",async(e,t)=>{let n=String(e.query.code??""),r=String(e.query.connectionId??""),s=y.find(d=>d.id===r);if(!n||!s)return t.redirect("/settings/connections?clickup=error");let o=await jo(n);if(!o)return s.authStatus="error",await R(s),t.redirect("/settings/connections?clickup=error");let c=(await ho(o.accessToken))[0];return c?.id?(await Fe({connectionId:s.id,provider:"clickup",accessToken:o.accessToken}),s.providerAccountId=c.id,s.providerAccountName=c.name||"ClickUp",s.authStatus="connected",await R(s),t.redirect("/settings/connections?clickup=connected")):(s.authStatus="error",await R(s),t.redirect("/settings/connections?clickup=error"))});f.get("/api/oauth/monday/deposit",async(e,t)=>{let n=String(e.query.code??""),r=String(e.query.connectionId??""),s=y.find(c=>c.id===r);if(!n||!s)return t.redirect("/settings/connections?monday=error");let o=await Uo(n);if(!o)return s.authStatus="error",await R(s),t.redirect("/settings/connections?monday=error");let i=await So(o.accessToken);return await Fe({connectionId:s.id,provider:"monday",accessToken:o.accessToken}),i?.slug&&(s.providerAccountId=i.slug),s.providerAccountName=i?.name||"Monday",s.authStatus="connected",await R(s),t.redirect("/settings/connections?monday=connected")});var Zc=6e4,si={getToken:wn,saveToken:Fe,refresh:(e,t)=>{let n=Mt(e);return n?n.refresh(t):Promise.resolve(null)}};async function ed(e){let t=Mt(e.provider);if(!t)throw Object.assign(new Error("not a vendor connection"),{terminal:!0});let n=await Ko(e.id,si);if(!n)throw Object.assign(new Error("no usable token"),{terminal:!0});let r=h.filter(u=>u.connectionId===e.id&&u.id.startsWith(t.idPrefix)).map(u=>u.id.slice(t.idPrefix.length)),s=u=>Promise.all([t.fetchDiscovery(e,u,e.syncFilters),t.fetchByIds(e,u,r)]),o,i;try{[o,i]=await s(n)}catch(u){let m=u?.status;if(m!==401&&m!==403)throw u;let g=await wn(e.id),p=g?await mr(e.id,g,si):null;if(!p){let w=u instanceof Error?u:new Error(String(u));throw Object.assign(w,{terminal:!0})}[o,i]=await s(p)}let{refreshed:c,pool:d}=Js(o,i,e.id,h,J);for(let u of c)await T(u);return e.lastSyncedAt=new Date().toISOString(),e.ticketCount=h.filter(u=>u.connectionId===e.id).length,e.authStatus="connected",await R(e),{refreshed:c.length,available:d.length}}async function Ir(e){if(_())return e.lastSyncedAt=new Date().toISOString(),await R(e),{synced:!0};if(!Mt(e.provider))return{synced:!1,skipped:"not_syncable"};if(!await wn(e.id))return e.authStatus==="connected"&&(e.authStatus="expired",await R(e)),{synced:!1,skipped:"not_syncable"};let t=J.filter(r=>r.connectionId===e.id).length;if((e.lastSyncedAt?Date.now()-Date.parse(e.lastSyncedAt):1/0)<Zc&&t>0)return{synced:!1,skipped:"fresh"};try{return{synced:!0,...await ed(e)}}catch(r){return e.authStatus=r?.terminal?"expired":"needs_refresh",await R(e),{synced:!1,error:String(r)}}}function td(){return async(e,t,n)=>{let r=h.find(o=>o.id===e.params.id),s=r?y.find(o=>o.id===r.connectionId):void 0;s&&await Ir(s),n()}}f.post("/api/connections/:id/sync",async(e,t)=>{let n=y.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});let r=await Ir(n);return r.error?t.status(502).json({error:`sync failed: ${r.error}`}):t.json({synced:r.synced,skipped:r.skipped,refreshed:r.refreshed??0,available:r.available})});f.get("/api/board",(e,t)=>{let n=String(e.query.connectionId??""),r=new Set(y.filter(o=>o.linkStatus==="linked").map(o=>o.id)),s=h.filter(o=>r.has(o.connectionId)&&(!n||o.connectionId===n)).map(o=>{let i=x[o.id],c=i?I[i]:void 0;return{ticket:o,column:fe(o.id),blockedByDeps:Ct(o,d=>h.find(u=>u.id===d),fe).length>0,run:c?{id:c.id,ticketId:c.ticketId,status:c.status,stopReason:c.stopReason,branchName:c.branchName,assignmentKind:c.assignmentKind,teamName:c.teamName,agentName:c.agentName,autonomy:c.autonomy,prUrl:c.prUrl,blocker:c.blocker}:void 0}});t.json(s)});f.post("/api/tickets/:id/move",async(e,t)=>{try{return t.json(await ft(e.params.id,e.body?.column))}catch(n){return ge(t,n)}});f.post("/api/tickets/:id/reorder",async(e,t)=>{let n=h.findIndex(i=>i.id===e.params.id);if(n===-1)return t.status(404).json({error:"ticket not found"});let[r]=h.splice(n,1),s=e.body?.beforeId,o=s?h.findIndex(i=>i.id===s):-1;return o===-1?h.push(r):h.splice(o,0,r),await Mr(),t.json({ticketId:r.id})});f.get("/api/tickets/:id",td(),async(e,t)=>{let n=h.find(d=>d.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=x[n.id],s=r?I[r]:null;if(s&&s.sessionId&&s.status!=="running"){let d=q.some(u=>u.ticketId===n.id);if(!s.resultText||!d){let u=Dn(s.sessionId);if(u.response&&!s.resultText&&(s.resultText=u.response.slice(0,5e4),await $(s.id)),u.response&&!d){let m={id:`rr_${Ke()}`,ticketId:n.id,runId:s.id,sessionId:s.sessionId,prompt:(u.prompt??"").slice(0,5e4),response:u.response.slice(0,5e4),status:"completed",createdAt:s.updatedAt??new Date().toISOString()};q.unshift(m),await Qt(m)}}}let o=q.find(d=>d.ticketId===n.id)??null,i=y.find(d=>d.id===n.connectionId),c=(n.dependsOn??[]).map(d=>{let u=h.find(m=>m.id===d);return{id:d,identifier:u?.externalIdentifier??null,title:u?.title??null,column:u?fe(d):null,done:!!u&&fe(d)==="done",missing:!u}});return t.json({ticket:n,column:fe(n.id),run:s,latestResult:o,connectionName:i?.displayName??i?.providerAccountName??"\u2014",workspaceName:i?.workspaceName??null,dependencies:c,blockedByDeps:c.some(d=>!d.done)})});f.get("/api/tickets/:id/history",async(e,t)=>{let n=Math.min(Math.max(Number(e.query.limit)||10,1),100),r=Math.max(Number(e.query.offset)||0,0);t.json(await qr(e.params.id,n,r))});f.get("/api/tickets/:id/notes",(e,t)=>{t.json(lt(e.params.id))});f.post("/api/tickets/:id/notes",async(e,t)=>{try{let n=await ht(e.params.id,{body:String(e.body?.body??""),author:e.body?.author});return t.status(201).json(n)}catch(n){return ge(t,n)}});f.get("/api/schedules/:id/notes",(e,t)=>{let n=P.filter(r=>r.scheduleId===e.params.id).slice().reverse();t.json(n)});f.post("/api/schedules/:id/notes",async(e,t)=>{let n=E[e.params.id];if(!n)return t.status(404).json({error:"schedule not found"});let r=String(e.body?.body??"").trim();if(!r)return t.status(400).json({error:"empty note"});let s=e.body?.author==="assistant"?"assistant":"user",o=new Date().toISOString(),i={id:`note_${Ke()}`,scheduleId:n.id,author:s,body:r.slice(0,5e3),createdAt:o,updatedAt:o};return P.push(i),await et(i),t.status(201).json(i)});f.patch("/api/notes/:id",async(e,t)=>{try{return t.json(await kt(e.params.id,String(e.body?.body??"")))}catch(n){return ge(t,n)}});f.delete("/api/notes/:id",async(e,t)=>{try{return await yt(e.params.id),t.json({ok:!0})}catch(n){return ge(t,n)}});f.get("/api/tickets/:id/open-questions",(e,t)=>{t.json(pt(e.params.id))});f.post("/api/tickets/:id/open-questions",async(e,t)=>{try{let n=await wt(e.params.id,String(e.body?.question??""));return t.status(201).json(n)}catch(n){return ge(t,n)}});f.patch("/api/open-questions/:qid",async(e,t)=>{try{return t.json(await bt(e.params.qid,e.body??{}))}catch(n){return ge(t,n)}});f.delete("/api/open-questions/:qid",async(e,t)=>{try{return await St(e.params.qid),t.json({ok:!0})}catch(n){return ge(t,n)}});var We=Q.join(Q.dirname(Bt),"pipelines-uploads"),nd={png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",pdf:"application/pdf",json:"application/json",txt:"text/plain",md:"text/markdown",csv:"text/csv"},rd=/^paste-[a-f0-9]+(\.[a-z0-9]+)?$/i,sd=e=>(e.split(".").pop()??"").toLowerCase().replace(/[^a-z0-9]/g,"").slice(0,8);f.get("/api/uploads/stats",async(e,t)=>{let n=0,r=0,s=await ve.promises.readdir(We).catch(()=>[]);for(let o of s){let i=await ve.promises.stat(Q.join(We,o)).catch(()=>null);i?.isFile()&&(n++,r+=i.size)}return t.json({count:n,bytes:r})});f.post("/api/uploads/clear",async(e,t)=>{let n=0,r=0,s=await ve.promises.readdir(We).catch(()=>[]);for(let o of s){let i=Q.join(We,o),c=await ve.promises.stat(i).catch(()=>null);c?.isFile()&&(r+=c.size,await ve.promises.unlink(i).catch(()=>{}),n++)}return t.json({removed:n,bytes:r})});f.post("/api/uploads",In.raw({type:"application/octet-stream",limit:"25mb"}),async(e,t)=>{let n=e.body;if(!Buffer.isBuffer(n)||n.length===0)return t.status(400).json({error:"empty upload"});let r=sd(String(e.query.name??""));await ve.promises.mkdir(We,{recursive:!0});let s=`paste-${Ke().slice(0,8)}${r?`.${r}`:""}`,o=Q.join(We,s);return await ve.promises.writeFile(o,n),t.status(201).json({path:o,filename:s})});f.get("/api/uploads/:name",(e,t)=>{let n=e.params.name;if(!rd.test(n))return t.status(400).end();let r=n.split(".").pop().toLowerCase();return t.type(nd[r]??"application/octet-stream"),t.sendFile(n,{root:We},s=>{s&&!t.headersSent&&t.status(404).end()})});var di=e=>e.split(/[/\\]/).pop()??e,oi=10;f.get("/api/message-presets",(e,t)=>{t.json(G.slice().sort((n,r)=>n.position-r.position))});f.post("/api/message-presets",async(e,t)=>{if(G.length>=oi)return t.status(422).json({error:`at most ${oi} presets`});let n=String(e.body?.title??"").trim(),r=String(e.body?.prompt??"").trim();if(!n||!r)return t.status(400).json({error:"title and prompt are required"});let s=new Date().toISOString(),o={id:`preset_${Ke()}`,title:n.slice(0,50),prompt:r.slice(0,5e3),enabled:e.body?.enabled!==!1,position:G.length,createdAt:s,updatedAt:s};return G.push(o),await Jt(o.id),t.status(201).json(o)});f.patch("/api/message-presets/:id",async(e,t)=>{let n=G.find(r=>r.id===e.params.id);if(!n)return t.status(404).json({error:"preset not found"});if(typeof e.body?.title=="string"){let r=e.body.title.trim();if(!r)return t.status(400).json({error:"empty title"});n.title=r.slice(0,50)}if(typeof e.body?.prompt=="string"){let r=e.body.prompt.trim();if(!r)return t.status(400).json({error:"empty prompt"});n.prompt=r.slice(0,5e3)}return typeof e.body?.enabled=="boolean"&&(n.enabled=e.body.enabled),n.updatedAt=new Date().toISOString(),await Jt(n.id),t.json(n)});f.delete("/api/message-presets/:id",async(e,t)=>{let n=G.findIndex(r=>r.id===e.params.id);return n===-1?t.status(404).json({error:"preset not found"}):(G.splice(n,1),G.forEach((r,s)=>r.position=s),await Wr(e.params.id),await Kr(),t.json({ok:!0}))});f.post("/api/tickets/:id/refresh",async(e,t)=>{let n=h.find(r=>r.id===e.params.id);return n?(await Xc(400),t.json({ticket:n,refreshedAt:new Date().toISOString()})):t.status(404).json({error:"ticket not found"})});f.get("/api/search",(e,t)=>{let n=String(e.query.q??"").trim().toLowerCase(),r=String(e.query.connectionId??""),s=Math.min(Math.max(Number(e.query.limit)||20,1),100),o=Math.max(Number(e.query.offset)||0,0),i=new Set(y.filter(m=>m.linkStatus==="linked").map(m=>m.id)),c=new Set(h.map(m=>m.externalIdentifier)),d=J.filter(m=>r?m.connectionId===r:i.has(m.connectionId)).filter(m=>i.has(m.connectionId)).filter(m=>!n||m.title.toLowerCase().includes(n)||m.externalIdentifier.toLowerCase().includes(n)),u=d.slice(o,o+s).map(m=>({externalId:m.id,externalIdentifier:m.externalIdentifier,title:m.title,status:m.status,statusRaw:m.statusRaw,provider:m.provider,connectionId:m.connectionId,url:m.url,imported:c.has(m.externalIdentifier)}));t.json({hits:u,total:d.length})});f.post("/api/import",async(e,t)=>{let n=J.findIndex(s=>s.id===e.body?.externalId);if(n===-1)return t.status(404).json({error:"ticket not in search results"});let[r]=J.splice(n,1);return r.workspaceId&&(r.workingDir=xn(r.workspaceId)),r.model=ye(l.defaultModel),r.effort=we(l.defaultEffort),h.push(r),S[r.id]="backlog",await T(r.id),t.status(201).json(r)});f.patch("/api/tickets/:id",async(e,t)=>{try{return t.json(await Ie(e.params.id,e.body??{}))}catch(n){return ge(t,n)}});f.post("/api/board/:connectionId/tickets",async(e,t)=>{try{let n=await gt(e.params.connectionId,e.body??{});return t.status(201).json(n)}catch(n){return ge(t,n)}});f.post("/api/tickets/:id/duplicate",async(e,t)=>{let n=h.find(c=>c.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});if(n.provider!=="local")return t.status(400).json({error:"only local tickets can be duplicated"});let r=y.find(c=>c.id===n.connectionId),s=(String(e.body?.title??"").trim()||n.title).slice(0,200),o=++L.localSeq,i={id:`t_local${o}`,connectionId:n.connectionId,provider:"local",externalIdentifier:`LOCAL-${o}`,project:"Local",title:s,status:"todo",statusRaw:"Backlog",priority:0,labels:[],url:"",workspaceId:n.workspaceId,workingDir:n.workspaceId?xn(n.workspaceId):"~",model:ye(l.defaultModel),effort:we(l.defaultEffort),description:n.description,additionalContext:n.additionalContext,additionalContextUpdatedAt:n.additionalContext?new Date().toISOString():void 0,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};h.push(i),S[i.id]="backlog",r&&(r.ticketCount+=1),await T(i.id),r&&await R(r);for(let c of P.filter(d=>d.ticketId===n.id)){let d=new Date().toISOString(),u={id:`note_${Ke()}`,ticketId:i.id,author:c.author,body:c.body,createdAt:d,updatedAt:d};P.push(u),await et(u)}return t.status(201).json(i)});f.put("/api/tickets/:id/dependencies",async(e,t)=>{let n=h.find(o=>o.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=o=>h.find(i=>i.id===o),s=Is(n.id,n.connectionId,e.body?.dependsOn,r);return Ss(n.id,s,r)?t.status(409).json({error:"that would create a dependency cycle",code:"dependency_cycle"}):(n.dependsOn=s.length?s:void 0,await T(n.id),t.json({dependsOn:s,unmet:Ct(n,r,fe)}))});f.get("/api/runs/:id",(e,t)=>{let n=I[e.params.id];return n?t.json(n):t.status(404).json({error:"run not found"})});f.get("/api/runs/:id/transcript",(e,t)=>{let n=I[e.params.id];if(!n)return t.status(404).json({error:"run not found"});let r=n.sessionId?jn(n.sessionId):[];return t.json({events:r,status:n.status,running:n.status==="running"})});f.get("/api/sessions/:sessionId/transcript",(e,t)=>{let n=jn(e.params.sessionId);return t.json({events:n,status:"ended",running:!1})});f.post("/api/runs",async(e,t)=>{try{let n=await Kn(e.body);return t.status(201).json(n)}catch(n){return Ut(t,n)}});f.post("/api/runs/:id/start",async(e,t)=>{try{let n=await at(e.params.id,{details:String(e.body?.additionalDetails??""),attachments:xr(e.body)});return t.json(n)}catch(n){return Ut(t,n)}});f.post("/api/runs/:id/pause",async(e,t)=>{try{return t.json(await ct(e.params.id))}catch(n){return Ut(t,n)}});f.post("/api/runs/:id/resume",async(e,t)=>{try{return t.json(await dt(e.params.id))}catch(n){return Ut(t,n)}});f.post("/api/tickets/:id/unblock",async(e,t)=>{try{let n=await mt(e.params.id,{resume:e.body?.resume===!0});return t.json(n)}catch(n){return ge(t,n)}});f.get("/api/tickets/:id/repos",async(e,t)=>{let n=h.find(o=>o.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=n.workingDir?.trim();if(!r)return t.json({repos:[],note:"ticket has no working dir set"});let s=await De(r);return t.json({repos:s.map(o=>o.name),singleRepo:s.length===1&&s[0].name==="."})});f.post("/api/tickets/:id/worktree",async(e,t)=>{let n=h.find(Qe=>Qe.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=x[n.id],s=r?I[r]:void 0;if(!s)return t.status(409).json({error:"ticket has no run"});let o=n.workingDir?.trim();if(!o)return t.status(409).json({error:"ticket has no working dir set"});let i=await is(o,e.body?.repo);if(!i){let Qe=await De(o);return t.status(400).json({error:Qe.length===0?"no git repositories found in the working dir":`name the repo to work on; found: ${Qe.map(yi=>yi.name).join(", ")}`})}let c=s.worktrees??=[],d=c.find(Qe=>Qe.repo===i.name);if(d)return t.json(d);let u=(l.branchPrefix||"feature").trim().replace(/\/+$/,""),m=i.name==="."?"":`-${i.name}`,g=n.attempt??1,p=g>1?`-v${g}`:"",w=`${u}/${n.externalIdentifier}${m}${p}`,Y=await as(i.path),hi=await Gn(i.path,Y),ki=(i.name==="."?"repo":i.name)+p,vr=Q.join(Ln,n.externalIdentifier,ki),Rr=await cs({repoPath:i.path,worktreePath:vr,branch:w,base:Y,startPoint:hi});if(!Rr.ok)return t.status(500).json({error:Rr.error});let Tr={repo:i.name,branch:w,worktreePath:vr,base:Y,compareUrl:await ls(i.path,Y,w),createdAt:new Date().toISOString()};return c.push(Tr),s.branchName=s.branchName||w,s.events.push({id:`e${s.events.length+1}`,ts:me(),kind:"mcp_tool",text:`claimed worktree for ${i.name} \u2192 ${w}`}),await $(s.id),t.json(Tr)});f.post("/api/tickets/:id/pr-links",async(e,t)=>{let n=h.find(i=>i.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=String(e.body?.url??"").trim();if(!/^https?:\/\//.test(r))return t.status(400).json({error:"a valid http(s) PR url is required"});let s=n.prLinks??=[];s.some(i=>i.url===r)||s.push({url:r,title:String(e.body?.title??"").trim()||void 0,createdAt:new Date().toISOString()}),await T(n.id);let o=I[x[n.id]];return o&&(o.prUrl=r,await $(o.id)),!_()&&s.length>1&&ei(n.externalIdentifier,s.map(i=>i.url)).catch(()=>{}),t.status(201).json({prLinks:s})});f.get("/api/tickets/:id/pr-links",(e,t)=>{let n=h.find(r=>r.id===e.params.id);return t.json({prLinks:n?.prLinks??[]})});f.post("/api/tickets/:id/monitor",async(e,t)=>{let n=h.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});if(e.body?.on===!0){if(!n.prLinks?.length)return t.status(409).json({error:"no PR to monitor yet"});if(!x[n.id])return t.status(409).json({error:"no run/session to continue from"});n.prMonitor=!0,n.prMonitorNote=void 0,n.prMonitorLastAt=void 0,(n.prMonitorCount??0)>=Lt(l)&&(n.prMonitorCount=0)}else n.prMonitor=!1;return await T(n.id),t.json({prMonitor:n.prMonitor})});var hr=null,kr=!1;async function od(e,t,n){let r=new Date().toISOString(),s=o=>t.events.push({id:`e${t.events.length+1}`,ts:me(),kind:"state_change",text:o});if(n.kind==="stamp"){e.prMonitorLastAt=r,await T(e.id);return}if(n.kind==="engage"){e.prMonitorCount=(e.prMonitorCount??0)+1,e.prMonitorLastAt=r,await T(e.id),t.status="running",t.stopReason=void 0,t.updatedAt=r,s(`PR monitor: ${n.reason==="comments"?"open review comments":"CI failing"} \u2192 engaging agent (pass ${e.prMonitorCount})`),await $(t.id),be(t.id,!0,n.prompt);return}e.prMonitor=!1,e.prMonitorNote=n.note,e.prMonitorLastAt=r,s(`PR monitor: ${n.note}`),await $(t.id),await T(e.id)}async function id(){if(!(_()||kr)){kr=!0;try{let e=Date.now();for(let t of h){if(!t.prMonitor)continue;let n=fe(t.id);if(n!=="in_review"&&n!=="done")continue;let r=x[t.id]?I[x[t.id]]:void 0;if(!r||r.status==="running"||!ti(t,l,e))continue;let s=(t.prLinks??[]).map(c=>c.url).filter(Boolean);if(!s.length){t.prMonitorLastAt=new Date().toISOString(),await T(t.id);continue}let o=await Xo(s),i=o.ci==="passing"&&l.prMonitorReplyToComments?await Yo(s):void 0;await od(t,r,ni(t,l,o,i))}}finally{kr=!1}}}function ad(){hr||(hr=setInterval(()=>void id(),6e4),hr.unref?.())}f.post("/api/runs/:id/stop",async(e,t)=>{try{return t.json(await ut(e.params.id))}catch(n){return Ut(t,n)}});f.post("/api/runs/:id/complete",async(e,t)=>{let n=I[e.params.id];return n?(n.status="stopped",n.stopReason="completed",n.blocker=void 0,n.events.push({id:`e${n.events.length+1}`,ts:me(),kind:"mcp_tool",text:"mark_complete(...)"}),n.updatedAt=new Date().toISOString(),S[n.ticketId]="in_review",await $(n.id),await T(n.ticketId),t.json(n)):t.status(404).json({error:"run not found"})});f.post("/api/runs/:id/answer",async(e,t)=>{let n=I[e.params.id];if(!n||!n.blocker)return t.status(409).json({error:"no open blocker"});n.blocker.status="answered";let r=e.body?.decision?`human: ${e.body.decision}`:`human answered: ${e.body?.response??""}`;n.events.push({id:`e${n.events.length+1}`,ts:me(),kind:"mcp_tool",text:r}),n.blocker=void 0,n.status="running",n.updatedAt=new Date().toISOString(),S[n.ticketId]="in_progress",await $(n.id),await T(n.ticketId);let s=String(e.body?.decision??e.body?.response??"").trim();return _()||be(n.id,!0,`The human responded: ${s}`),t.json(n)});f.post("/api/runs/:id/approve",async(e,t)=>{let n=I[e.params.id];return n?n.status!=="stopped"?t.status(409).json({error:"can only approve a stopped run"}):(n.events.push({id:`e${n.events.length+1}`,ts:me(),kind:"state_change",text:"approved by human \u2192 Done"}),n.updatedAt=new Date().toISOString(),S[n.ticketId]="done",await $(n.id),await T(n.ticketId),t.json(n)):t.status(404).json({error:"run not found"})});f.post("/api/runs/:id/respond",async(e,t)=>{let n=I[e.params.id];if(!n)return t.status(404).json({error:"run not found"});if(h.find(c=>c.id===n.ticketId)?.prMonitor)return t.status(409).json({error:"PR monitor is armed \u2014 turn it off to send a message"});if(n.status!=="stopped"&&n.status!=="blocked")return t.status(409).json({error:"run is not waiting for a response"});let r=String(e.body?.text??"").trim(),s=Array.isArray(e.body?.attachments)?e.body.attachments.map(c=>String(c)).filter(Boolean):[];if(!r&&s.length===0)return t.status(400).json({error:"empty response"});let o=n.status==="blocked";n.blocker&&(n.blocker=void 0),n.status="running",n.stopReason=void 0,n.events.push({id:`e${n.events.length+1}`,ts:me(),kind:o?"mcp_tool":"state_change",text:`human responded: ${r.slice(0,80)}${s.length?` (+${s.length} file${s.length>1?"s":""})`:""}`}),n.updatedAt=new Date().toISOString(),S[n.ticketId]="in_progress",await $(n.id),await T(n.ticketId);let i=r+(s.length?`
121
+ `)}var Ut=3,f=Wn();f.use(Od());f.use(Wn.json());var an=Number(process.env.PIPELINES_PORT||process.env.PIPELINES_MOCK_PORT||63210),Hr=Number(process.env.PIPELINES_PUBLIC_PORT||an),jd=e=>new Promise(t=>setTimeout(t,e)),we=e=>S[e]??"backlog";function cn(e,t){return t instanceof le?e.status(t.status).json({error:t.message,...t.code?{code:t.code}:{},...t.extra??{}}):(console.error(t),e.status(500).json({error:"internal error"}))}function Se(e,t){return t instanceof P?e.status(t.status).json({error:t.message,...t.extra??{}}):(console.error(t),e.status(500).json({error:"internal error"}))}function it(e,t){return t instanceof G?e.status(t.status).json({error:t.message,...t.code?{code:t.code}:{},...t.extra??{}}):(console.error(t),e.status(500).json({error:"internal error"}))}var qi=()=>new Set(l.connectedWorkspaces??[]),Kn=e=>l.workspaceDirs?.[e]??"~";function Hn(){let e=qi();$.length=0,$.push(...Jt().filter(t=>e.has(t.id)))}async function Md(){let e=Jt();if(C()){l.connectedWorkspaces=e.map(r=>r.id);return}if(!Array.isArray(l.connectedWorkspaces)){let r=[...new Set(b.filter(s=>s.workspaceId).map(s=>s.workspaceId))].filter(s=>e.some(o=>o.id===s)).slice(0,In);l.connectedWorkspaces=r,await se()}Hn();let t={...l.workspaceDirs??{}},n=!1;for(let r of $)t[r.id]||(t[r.id]="~",n=!0);n&&(l.workspaceDirs=t,await se()),await ln()}f.get("/api/session",(e,t)=>t.json(Ie));f.get("/api/workspaces",(e,t)=>t.json($));f.get("/api/teams",async(e,t)=>{if(C())return t.json(Ce);let n=typeof e.query.workspaceId=="string"?e.query.workspaceId:"";if(!n)return t.json([]);let r=await zt(n);t.json(r?.teams??[])});f.get("/api/agents",async(e,t)=>{if(C())return t.json(Pe);let n=typeof e.query.workspaceId=="string"?e.query.workspaceId:"";if(!n)return t.json([]);let r=await zt(n);t.json(r?.agents??[])});f.get("/api/workspaces/available",(e,t)=>{let n=qi();t.json(Jt().map(r=>({...r,connected:n.has(r.id),workingDir:Kn(r.id)})))});f.post("/api/workspaces/:id/connect",async(e,t)=>{let n=Jt().find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"workspace not accessible"});let r=l.connectedWorkspaces??[];if(!r.includes(n.id)){if(r.length>=In)return t.status(409).json({error:`You can connect at most ${In} workspaces.`});l.connectedWorkspaces=[...r,n.id]}return l.workspaceDirs?.[n.id]||(l.workspaceDirs={...l.workspaceDirs??{},[n.id]:"~"}),await se(),Hn(),C()||await ln(),t.json({id:n.id,connected:!0})});f.post("/api/workspaces/:id/working-dir",async(e,t)=>{let n=e.params.id,r=String(e.body?.workingDir??"").trim()||"~";return l.workspaceDirs={...l.workspaceDirs??{},[n]:r},await se(),t.json({id:n,workingDir:r})});f.post("/api/workspaces/:id/disconnect",async(e,t)=>{let n=e.params.id,r=l.connectedWorkspaces??[];return r.includes(n)&&(l.connectedWorkspaces=r.filter(s=>s!==n),await se(),Hn()),t.json({id:n,connected:!1})});f.get("/api/database/export",(e,t)=>{let n=b.map(r=>({...r,ticketCount:h.filter(s=>s.connectionId===r.id).length}));t.json({version:2,workspaces:$,teams:Ce,agents:Pe,connections:n,tickets:h,settings:l,schedules:O,scheduleOrder:ne,scheduleRuns:z,searchable:re,notes:j,openQuestions:D,messagePresets:H,state:B})});f.post("/api/database/import",async(e,t)=>{let n=e.body;if(!n||typeof n!="object")return t.status(400).json({error:"invalid snapshot"});let r=(o,i)=>{Array.isArray(i)&&(o.length=0,o.push(...i))},s=(o,i)=>{if(i&&typeof i=="object"){for(let c of Object.keys(o))delete o[c];Object.assign(o,i)}};r($,n.workspaces),r(Ce,n.teams),r(Pe,n.agents),r(b,n.connections);for(let o of b)o.provider!=="local"&&(o.authStatus="expired");r(h,n.tickets),r(re,n.searchable),r(j,n.notes),r(D,n.openQuestions),r(H,n.messagePresets),r(ne,n.scheduleOrder),s(O,n.schedules),s(z,n.scheduleRuns),n.settings&&typeof n.settings=="object"&&Object.assign(l,n.settings),n.state&&typeof n.state=="object"&&Object.assign(B,n.state);for(let o of Object.keys(x))delete x[o];for(let o of Object.keys(T))delete T[o];for(let o of Object.keys(S))delete S[o];for(let o of Object.keys(F))delete F[o];return X.length=0,ce.length=0,await bs(),t.json({ok:!0})});f.post("/api/database/reset",async(e,t)=>(await Ss(),Hn(),t.json({ok:!0})));f.get("/api/fs/browse",(e,t)=>{let n=String(e.query.path??"").trim(),r=e.query.files==="1",s=n||Fn.homedir();s==="~"?s=Fn.homedir():s.startsWith("~/")&&(s=ee.join(Fn.homedir(),s.slice(2))),s=ee.resolve(s);try{let o=Ee.readdirSync(s,{withFileTypes:!0}).filter(c=>!c.name.startsWith(".")).filter(c=>c.isDirectory()||r&&c.isFile()).map(c=>({name:c.name,path:ee.join(s,c.name),type:c.isDirectory()?"dir":"file"})).sort((c,d)=>c.type!==d.type?c.type==="dir"?-1:1:c.name.localeCompare(d.name)),i=ee.dirname(s);return t.json({path:s,parent:i===s?null:i,home:Fn.homedir(),entries:o})}catch(o){return t.status(400).json({error:`can't read ${s}: ${String(o)}`})}});f.get("/api/connections",(e,t)=>t.json(b));function Qr(e){let t=e??{},n=Array.isArray(t.labels)?t.labels.map(i=>String(i).trim()).filter(Boolean).slice(0,3):[],r=!!t.assignedToMe,s=r?"":String(t.assignee??"").trim(),o={};return n.length&&(o.labels=n),r?o.assignedToMe=!0:s&&(o.assignee=s),Object.keys(o).length?o:null}var Fi={linear:"Linear",jira:"Jira",asana:"Asana",clickup:"ClickUp",monday:"Monday"},$d=new Set(Object.keys(Fi));function Wi(e,t,n){return e==="jira"?ai(t,n):e==="asana"?li(t,n):e==="clickup"?hi(t,n):e==="monday"?Si(t,n):si(t,n)}f.post("/api/connections",async(e,t)=>{let n=String(e.body?.provider??"");if(!$d.has(n))return t.status(400).json({error:"unsupported provider"});let r=Fi[n],s=String(e.body?.name??"").trim(),o=String(e.body?.workingDir??"").trim(),i=$.find(m=>m.id===e.body?.workspaceId);if(e.body?.workspaceId&&!i)return t.status(400).json({error:"workspace not accessible"});if(i&&b.filter(g=>g.provider!=="local"&&g.linkStatus==="linked"&&g.workspaceId===i.id).length>=Ut)return t.json({configured:!0,message:`That workspace already has ${Ut} connections (the max).`});let d={id:`conn_${ot().slice(0,8)}`,provider:n,providerAccountName:C()?`${r} (demo)`:r,...s?{displayName:s}:{},workspaceId:i?.id??null,workspaceName:i?.name??null,workingDir:o||null,linkStatus:i?"linked":"unlinked",authStatus:C()?"connected":"needs_refresh",lastSyncedAt:null,ticketCount:0,syncFilters:Qr(e.body?.syncFilters)};if(C())return b.push(d),await A(d),t.status(201).json({connection:d,mock:!0});let u=await Wi(n,d.id,Hr);return u.url?(b.push(d),await A(d),t.status(201).json({connection:d,url:u.url})):t.json({configured:u.configured===!1?!1:void 0,message:u.error??`Couldn't start the ${r} connection.`})});f.post("/api/connections/:id/link",async(e,t)=>{let n=b.find(o=>o.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});let r=$.find(o=>o.id===e.body?.workspaceId);return r?b.filter(o=>o.id!==n.id&&o.provider!=="local"&&o.linkStatus==="linked"&&o.workspaceId===r.id).length>=Ut?t.status(409).json({error:`A workspace can have at most ${Ut} connections.`}):(n.workspaceId=r.id,n.workspaceName=r.name,typeof e.body?.workingDir=="string"&&e.body.workingDir.trim()&&(n.workingDir=e.body.workingDir.trim()),typeof e.body?.name=="string"&&e.body.name.trim()&&(n.displayName=e.body.name.trim()),"syncFilters"in(e.body??{})&&n.provider!=="local"&&(n.syncFilters=Qr(e.body.syncFilters)),n.linkStatus="linked",delete n.linkLostReason,n.lastSyncedAt=new Date().toISOString(),await A(n),t.json(n)):t.status(400).json({error:"workspace not accessible"})});f.patch("/api/connections/:id",async(e,t)=>{let n=b.find(r=>r.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});if(typeof e.body?.name=="string"){let r=e.body.name.trim();r?n.displayName=r:delete n.displayName}if(e.body?.unlink===!0){if(n.provider==="local")return t.status(400).json({error:"a local board can't be unlinked"});n.workspaceId=null,n.workspaceName=null,n.workingDir=null,n.linkStatus="unlinked"}if(typeof e.body?.workspaceId=="string"&&n.provider!=="local"){let r=$.find(s=>s.id===e.body.workspaceId);if(!r)return t.status(400).json({error:"workspace not accessible"});if(r.id!==n.workspaceId&&b.filter(o=>o.id!==n.id&&o.provider!=="local"&&o.linkStatus==="linked"&&o.workspaceId===r.id).length>=Ut)return t.status(409).json({error:`A workspace can have at most ${Ut} connections.`});n.workspaceId=r.id,n.workspaceName=r.name,n.linkStatus="linked"}return typeof e.body?.workingDir=="string"&&e.body.workingDir.trim()&&(n.workingDir=e.body.workingDir.trim()),"syncFilters"in(e.body??{})&&n.provider!=="local"&&(n.syncFilters=Qr(e.body.syncFilters)),await A(n),t.json(n)});f.delete("/api/connections/:id",async(e,t)=>{let n=b.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});if(n.provider==="local")return t.status(400).json({error:"a local board can't be disconnected"});for(let s of h.filter(o=>o.connectionId===n.id)){let o=T[s.id];o&&(await St(o),delete x[o],delete T[s.id]),delete S[s.id],await En(s.id),await pn(s.id)}for(let s=h.length-1;s>=0;s--)h[s].connectionId===n.id&&h.splice(s,1);for(let s=re.length-1;s>=0;s--)re[s].connectionId===n.id&&re.splice(s,1);let r=b.findIndex(s=>s.id===n.id);return r!==-1&&b.splice(r,1),await cs(n.id),await Ti(n.id),t.status(204).end()});f.post("/api/connections/:id/oauth/start",async(e,t)=>{let n=b.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});if(!sn(n.provider))return t.status(400).json({error:"not a vendor connection"});let r=await Wi(n.provider,n.id,Hr);return r.url?t.json({url:r.url}):t.status(r.configured===!1?501:502).json({error:r.error??"Couldn't start OAuth."})});f.get("/api/oauth/linear/deposit",async(e,t)=>{let n=String(e.query.code??""),r=String(e.query.connectionId??""),s=b.find(i=>i.id===r);if(!n||!s)return t.redirect("/settings/connections?linear=error");let o=await oi(n);return o?(await rt({connectionId:s.id,provider:"linear",accessToken:o.accessToken,refreshToken:o.refreshToken,scope:o.scope,expiresAt:o.expiresAt}),s.authStatus="connected",await A(s),t.redirect("/settings/connections?linear=connected")):(s.authStatus="error",await A(s),t.redirect("/settings/connections?linear=error"))});f.get("/api/oauth/jira/deposit",async(e,t)=>{let n=String(e.query.code??""),r=String(e.query.connectionId??""),s=b.find(u=>u.id===r);if(!n||!s)return t.redirect("/settings/connections?jira=error");let o=await ci(n);if(!o)return s.authStatus="error",await A(s),t.redirect("/settings/connections?jira=error");let c=(await ui(o.accessToken))[0];if(!c?.id)return s.authStatus="error",await A(s),t.redirect("/settings/connections?jira=error");await rt({connectionId:s.id,provider:"jira",accessToken:o.accessToken,refreshToken:o.refreshToken,scope:o.scope,expiresAt:o.expiresAt}),s.cloudId=c.id;let d=c.url?c.url.replace(/^https?:\/\//,"").replace(/\/+$/,""):void 0;return s.providerAccountName=d||c.name||"Jira",s.authStatus="connected",await A(s),t.redirect("/settings/connections?jira=connected")});f.get("/api/oauth/asana/deposit",async(e,t)=>{let n=String(e.query.code??""),r=String(e.query.connectionId??""),s=b.find(d=>d.id===r);if(!n||!s)return t.redirect("/settings/connections?asana=error");let o=await pi(n);if(!o)return s.authStatus="error",await A(s),t.redirect("/settings/connections?asana=error");let c=(await Jo(o.accessToken))[0];return c?.gid?(await rt({connectionId:s.id,provider:"asana",accessToken:o.accessToken,refreshToken:o.refreshToken,scope:o.scope,expiresAt:o.expiresAt}),s.providerAccountId=c.gid,s.providerAccountName=c.name||"Asana",s.authStatus="connected",await A(s),t.redirect("/settings/connections?asana=connected")):(s.authStatus="error",await A(s),t.redirect("/settings/connections?asana=error"))});f.get("/api/oauth/clickup/deposit",async(e,t)=>{let n=String(e.query.code??""),r=String(e.query.connectionId??""),s=b.find(d=>d.id===r);if(!n||!s)return t.redirect("/settings/connections?clickup=error");let o=await ki(n);if(!o)return s.authStatus="error",await A(s),t.redirect("/settings/connections?clickup=error");let c=(await Vo(o.accessToken))[0];return c?.id?(await rt({connectionId:s.id,provider:"clickup",accessToken:o.accessToken}),s.providerAccountId=c.id,s.providerAccountName=c.name||"ClickUp",s.authStatus="connected",await A(s),t.redirect("/settings/connections?clickup=connected")):(s.authStatus="error",await A(s),t.redirect("/settings/connections?clickup=error"))});f.get("/api/oauth/monday/deposit",async(e,t)=>{let n=String(e.query.code??""),r=String(e.query.connectionId??""),s=b.find(c=>c.id===r);if(!n||!s)return t.redirect("/settings/connections?monday=error");let o=await Ii(n);if(!o)return s.authStatus="error",await A(s),t.redirect("/settings/connections?monday=error");let i=await ri(o.accessToken);return await rt({connectionId:s.id,provider:"monday",accessToken:o.accessToken}),i?.slug&&(s.providerAccountId=i.slug),s.providerAccountName=i?.name||"Monday",s.authStatus="connected",await A(s),t.redirect("/settings/connections?monday=connected")});var Bd=6e4,Gi={getToken:Un,saveToken:rt,refresh:(e,t)=>{let n=sn(e);return n?n.refresh(t):Promise.resolve(null)}};async function Ld(e){let t=sn(e.provider);if(!t)throw Object.assign(new Error("not a vendor connection"),{terminal:!0});let n=await _i(e.id,Gi);if(!n)throw Object.assign(new Error("no usable token"),{terminal:!0});let r=h.filter(u=>u.connectionId===e.id&&u.id.startsWith(t.idPrefix)).map(u=>u.id.slice(t.idPrefix.length)),s=u=>Promise.all([t.fetchDiscovery(e,u,e.syncFilters),t.fetchByIds(e,u,r)]),o,i;try{[o,i]=await s(n)}catch(u){let m=u?.status;if(m!==401&&m!==403)throw u;let g=await Un(e.id),I=g?await Gr(e.id,g,Gi):null;if(!I){let p=u instanceof Error?u:new Error(String(u));throw Object.assign(p,{terminal:!0})}[o,i]=await s(I)}let{refreshed:c,pool:d}=Co(o,i,e.id,h,re);for(let u of c)await N(u);return e.lastSyncedAt=new Date().toISOString(),e.ticketCount=h.filter(u=>u.connectionId===e.id).length,e.authStatus="connected",await A(e),{refreshed:c.length,available:d.length}}async function Jr(e){if(C())return e.lastSyncedAt=new Date().toISOString(),await A(e),{synced:!0};if(!sn(e.provider))return{synced:!1,skipped:"not_syncable"};if(!await Un(e.id))return e.authStatus==="connected"&&(e.authStatus="expired",await A(e)),{synced:!1,skipped:"not_syncable"};let t=re.filter(r=>r.connectionId===e.id).length;if((e.lastSyncedAt?Date.now()-Date.parse(e.lastSyncedAt):1/0)<Bd&&t>0)return{synced:!1,skipped:"fresh"};try{return{synced:!0,...await Ld(e)}}catch(r){return e.authStatus=r?.terminal?"expired":"needs_refresh",await A(e),{synced:!1,error:String(r)}}}function Gd(){return async(e,t,n)=>{let r=h.find(o=>o.id===e.params.id),s=r?b.find(o=>o.id===r.connectionId):void 0;s&&await Jr(s),n()}}f.post("/api/connections/:id/sync",async(e,t)=>{let n=b.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});let r=await Jr(n);return r.error?t.status(502).json({error:`sync failed: ${r.error}`}):t.json({synced:r.synced,skipped:r.skipped,refreshed:r.refreshed??0,available:r.available})});f.get("/api/board",(e,t)=>{let n=String(e.query.connectionId??""),r=new Set(b.filter(o=>o.linkStatus==="linked").map(o=>o.id)),s=h.filter(o=>r.has(o.connectionId)&&(!n||o.connectionId===n)).map(o=>{let i=T[o.id],c=i?x[i]:void 0;return{ticket:o,column:we(o.id),blockedByDeps:Vt(o,d=>h.find(u=>u.id===d),we).length>0,run:c?{id:c.id,ticketId:c.ticketId,status:c.status,stopReason:c.stopReason,branchName:c.branchName,assignmentKind:c.assignmentKind,teamName:c.teamName,agentName:c.agentName,autonomy:c.autonomy,prUrl:c.prUrl,blocker:c.blocker}:void 0}});t.json(s)});f.post("/api/tickets/:id/move",async(e,t)=>{try{return t.json(await _t(e.params.id,e.body?.column))}catch(n){return Se(t,n)}});f.post("/api/tickets/:id/reorder",async(e,t)=>{let n=h.findIndex(i=>i.id===e.params.id);if(n===-1)return t.status(404).json({error:"ticket not found"});let[r]=h.splice(n,1),s=e.body?.beforeId,o=s?h.findIndex(i=>i.id===s):-1;return o===-1?h.push(r):h.splice(o,0,r),await ds(),t.json({ticketId:r.id})});f.get("/api/tickets/:id",Gd(),async(e,t)=>{let n=h.find(d=>d.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=T[n.id],s=r?x[r]:null;if(s&&s.sessionId&&s.status!=="running"){let d=X.some(u=>u.ticketId===n.id);if(!s.resultText||!d){let u=nr(s.sessionId);if(u.response&&!s.resultText&&(s.resultText=u.response.slice(0,5e4),await L(s.id)),u.response&&!d){let m={id:`rr_${ot()}`,ticketId:n.id,runId:s.id,sessionId:s.sessionId,prompt:(u.prompt??"").slice(0,5e4),response:u.response.slice(0,5e4),status:"completed",createdAt:s.updatedAt??new Date().toISOString()};X.unshift(m),await mn(m)}}}let o=X.find(d=>d.ticketId===n.id)??null,i=b.find(d=>d.id===n.connectionId),c=(n.dependsOn??[]).map(d=>{let u=h.find(m=>m.id===d);return{id:d,identifier:u?.externalIdentifier??null,title:u?.title??null,column:u?we(d):null,done:!!u&&we(d)==="done",missing:!u}});return t.json({ticket:n,column:we(n.id),run:s,latestResult:o,connectionName:i?.displayName??i?.providerAccountName??"\u2014",workspaceName:i?.workspaceName??null,dependencies:c,blockedByDeps:c.some(d=>!d.done)})});f.get("/api/tickets/:id/history",async(e,t)=>{let n=Math.min(Math.max(Number(e.query.limit)||10,1),100),r=Math.max(Number(e.query.offset)||0,0);t.json(await ms(e.params.id,n,r))});f.get("/api/tickets/:id/notes",(e,t)=>{t.json(Rt(e.params.id))});f.post("/api/tickets/:id/notes",async(e,t)=>{try{let n=await Et(e.params.id,{body:String(e.body?.body??""),author:e.body?.author});return t.status(201).json(n)}catch(n){return Se(t,n)}});f.get("/api/schedules/:id/notes",(e,t)=>{let n=j.filter(r=>r.scheduleId===e.params.id).slice().reverse();t.json(n)});f.post("/api/schedules/:id/notes",async(e,t)=>{let n=O[e.params.id];if(!n)return t.status(404).json({error:"schedule not found"});let r=String(e.body?.body??"").trim();if(!r)return t.status(400).json({error:"empty note"});let s=e.body?.author==="assistant"?"assistant":"user",o=new Date().toISOString(),i={id:`note_${ot()}`,scheduleId:n.id,author:s,body:r.slice(0,5e3),createdAt:o,updatedAt:o};return j.push(i),await ht(i),t.status(201).json(i)});f.patch("/api/notes/:id",async(e,t)=>{try{return t.json(await Ct(e.params.id,String(e.body?.body??"")))}catch(n){return Se(t,n)}});f.delete("/api/notes/:id",async(e,t)=>{try{return await Pt(e.params.id),t.json({ok:!0})}catch(n){return Se(t,n)}});f.get("/api/tickets/:id/open-questions",(e,t)=>{t.json(Tt(e.params.id))});f.post("/api/tickets/:id/open-questions",async(e,t)=>{try{let n=await Ot(e.params.id,String(e.body?.question??""));return t.status(201).json(n)}catch(n){return Se(t,n)}});f.patch("/api/open-questions/:qid",async(e,t)=>{try{return t.json(await Dt(e.params.qid,e.body??{}))}catch(n){return Se(t,n)}});f.delete("/api/open-questions/:qid",async(e,t)=>{try{return await jt(e.params.qid),t.json({ok:!0})}catch(n){return Se(t,n)}});var st=ee.join(ee.dirname(dn),"pipelines-uploads"),Ud={png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",pdf:"application/pdf",json:"application/json",txt:"text/plain",md:"text/markdown",csv:"text/csv"},qd=/^paste-[a-f0-9]+(\.[a-z0-9]+)?$/i,Fd=e=>(e.split(".").pop()??"").toLowerCase().replace(/[^a-z0-9]/g,"").slice(0,8);f.get("/api/uploads/stats",async(e,t)=>{let n=0,r=0,s=await Ee.promises.readdir(st).catch(()=>[]);for(let o of s){let i=await Ee.promises.stat(ee.join(st,o)).catch(()=>null);i?.isFile()&&(n++,r+=i.size)}return t.json({count:n,bytes:r})});f.post("/api/uploads/clear",async(e,t)=>{let n=0,r=0,s=await Ee.promises.readdir(st).catch(()=>[]);for(let o of s){let i=ee.join(st,o),c=await Ee.promises.stat(i).catch(()=>null);c?.isFile()&&(r+=c.size,await Ee.promises.unlink(i).catch(()=>{}),n++)}return t.json({removed:n,bytes:r})});f.post("/api/uploads",Wn.raw({type:"application/octet-stream",limit:"25mb"}),async(e,t)=>{let n=e.body;if(!Buffer.isBuffer(n)||n.length===0)return t.status(400).json({error:"empty upload"});let r=Fd(String(e.query.name??""));await Ee.promises.mkdir(st,{recursive:!0});let s=`paste-${ot().slice(0,8)}${r?`.${r}`:""}`,o=ee.join(st,s);return await Ee.promises.writeFile(o,n),t.status(201).json({path:o,filename:s})});f.get("/api/uploads/:name",(e,t)=>{let n=e.params.name;if(!qd.test(n))return t.status(400).end();let r=n.split(".").pop().toLowerCase();return t.type(Ud[r]??"application/octet-stream"),t.sendFile(n,{root:st},s=>{s&&!t.headersSent&&t.status(404).end()})});var Ki=e=>e.split(/[/\\]/).pop()??e,Ui=10;f.get("/api/message-presets",(e,t)=>{t.json(H.slice().sort((n,r)=>n.position-r.position))});f.post("/api/message-presets",async(e,t)=>{if(H.length>=Ui)return t.status(422).json({error:`at most ${Ui} presets`});let n=String(e.body?.title??"").trim(),r=String(e.body?.prompt??"").trim();if(!n||!r)return t.status(400).json({error:"title and prompt are required"});let s=new Date().toISOString(),o={id:`preset_${ot()}`,title:n.slice(0,50),prompt:r.slice(0,5e3),enabled:e.body?.enabled!==!1,position:H.length,createdAt:s,updatedAt:s};return H.push(o),await hn(o.id),t.status(201).json(o)});f.patch("/api/message-presets/:id",async(e,t)=>{let n=H.find(r=>r.id===e.params.id);if(!n)return t.status(404).json({error:"preset not found"});if(typeof e.body?.title=="string"){let r=e.body.title.trim();if(!r)return t.status(400).json({error:"empty title"});n.title=r.slice(0,50)}if(typeof e.body?.prompt=="string"){let r=e.body.prompt.trim();if(!r)return t.status(400).json({error:"empty prompt"});n.prompt=r.slice(0,5e3)}return typeof e.body?.enabled=="boolean"&&(n.enabled=e.body.enabled),n.updatedAt=new Date().toISOString(),await hn(n.id),t.json(n)});f.delete("/api/message-presets/:id",async(e,t)=>{let n=H.findIndex(r=>r.id===e.params.id);return n===-1?t.status(404).json({error:"preset not found"}):(H.splice(n,1),H.forEach((r,s)=>r.position=s),await hs(e.params.id),await ks(),t.json({ok:!0}))});f.post("/api/tickets/:id/refresh",async(e,t)=>{let n=h.find(r=>r.id===e.params.id);return n?(await jd(400),t.json({ticket:n,refreshedAt:new Date().toISOString()})):t.status(404).json({error:"ticket not found"})});f.get("/api/search",(e,t)=>{let n=String(e.query.q??"").trim().toLowerCase(),r=String(e.query.connectionId??""),s=Math.min(Math.max(Number(e.query.limit)||20,1),100),o=Math.max(Number(e.query.offset)||0,0),i=new Set(b.filter(m=>m.linkStatus==="linked").map(m=>m.id)),c=new Set(h.map(m=>m.externalIdentifier)),d=re.filter(m=>r?m.connectionId===r:i.has(m.connectionId)).filter(m=>i.has(m.connectionId)).filter(m=>!n||m.title.toLowerCase().includes(n)||m.externalIdentifier.toLowerCase().includes(n)),u=d.slice(o,o+s).map(m=>({externalId:m.id,externalIdentifier:m.externalIdentifier,title:m.title,status:m.status,statusRaw:m.statusRaw,provider:m.provider,connectionId:m.connectionId,url:m.url,imported:c.has(m.externalIdentifier)}));t.json({hits:u,total:d.length})});f.post("/api/import",async(e,t)=>{let n=re.findIndex(s=>s.id===e.body?.externalId);if(n===-1)return t.status(404).json({error:"ticket not in search results"});let[r]=re.splice(n,1);return r.workspaceId&&(r.workingDir=Kn(r.workspaceId)),r.model=ve(l.defaultModel),r.effort=Re(l.defaultEffort),h.push(r),S[r.id]="backlog",await N(r.id),t.status(201).json(r)});f.patch("/api/tickets/:id",async(e,t)=>{try{return t.json(await _e(e.params.id,e.body??{}))}catch(n){return Se(t,n)}});f.post("/api/board/:connectionId/tickets",async(e,t)=>{try{let n=await Nt(e.params.connectionId,e.body??{});return t.status(201).json(n)}catch(n){return Se(t,n)}});f.post("/api/tickets/:id/duplicate",async(e,t)=>{let n=h.find(c=>c.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});if(n.provider!=="local")return t.status(400).json({error:"only local tickets can be duplicated"});let r=b.find(c=>c.id===n.connectionId),s=(String(e.body?.title??"").trim()||n.title).slice(0,200),o=++B.localSeq,i={id:`t_local${o}`,connectionId:n.connectionId,provider:"local",externalIdentifier:`LOCAL-${o}`,project:"Local",title:s,status:"todo",statusRaw:"Backlog",priority:0,labels:[],url:"",workspaceId:n.workspaceId,workingDir:n.workspaceId?Kn(n.workspaceId):"~",model:ve(l.defaultModel),effort:Re(l.defaultEffort),description:n.description,additionalContext:n.additionalContext,additionalContextUpdatedAt:n.additionalContext?new Date().toISOString():void 0,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};h.push(i),S[i.id]="backlog",r&&(r.ticketCount+=1),await N(i.id),r&&await A(r);for(let c of j.filter(d=>d.ticketId===n.id)){let d=new Date().toISOString(),u={id:`note_${ot()}`,ticketId:i.id,author:c.author,body:c.body,createdAt:d,updatedAt:d};j.push(u),await ht(u)}return t.status(201).json(i)});f.put("/api/tickets/:id/dependencies",async(e,t)=>{let n=h.find(o=>o.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=o=>h.find(i=>i.id===o),s=zs(n.id,n.connectionId,e.body?.dependsOn,r);return Js(n.id,s,r)?t.status(409).json({error:"that would create a dependency cycle",code:"dependency_cycle"}):(n.dependsOn=s.length?s:void 0,await N(n.id),t.json({dependsOn:s,unmet:Vt(n,r,we)}))});f.get("/api/runs/:id",(e,t)=>{let n=x[e.params.id];return n?t.json(n):t.status(404).json({error:"run not found"})});f.get("/api/runs/:id/transcript",(e,t)=>{let n=x[e.params.id];if(!n)return t.status(404).json({error:"run not found"});let r=n.sessionId?rr(n.sessionId):[];return t.json({events:r,status:n.status,running:n.status==="running"})});f.get("/api/sessions/:sessionId/transcript",(e,t)=>{let n=rr(e.params.sessionId);return t.json({events:n,status:"ended",running:!1})});f.post("/api/runs",async(e,t)=>{try{let n=await mr(e.body);return t.status(201).json(n)}catch(n){return cn(t,n)}});f.post("/api/runs/:id/start",async(e,t)=>{try{let n=await Fe(e.params.id,{details:String(e.body?.additionalDetails??""),attachments:zr(e.body)});return t.json(n)}catch(n){return cn(t,n)}});f.post("/api/runs/:id/pause",async(e,t)=>{try{return t.json(await xt(e.params.id))}catch(n){return cn(t,n)}});f.post("/api/runs/:id/resume",async(e,t)=>{try{return t.json(await vt(e.params.id))}catch(n){return cn(t,n)}});f.post("/api/tickets/:id/unblock",async(e,t)=>{try{let n=await At(e.params.id,{resume:e.body?.resume===!0});return t.json(n)}catch(n){return Se(t,n)}});f.get("/api/tickets/:id/repos",async(e,t)=>{let n=h.find(o=>o.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=n.workingDir?.trim();if(!r)return t.json({repos:[],note:"ticket has no working dir set"});let s=await Ue(r);return t.json({repos:s.map(o=>o.name),singleRepo:s.length===1&&s[0].name==="."})});f.post("/api/tickets/:id/worktree",async(e,t)=>{let n=h.find(at=>at.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=T[n.id],s=r?x[r]:void 0;if(!s)return t.status(409).json({error:"ticket has no run"});let o=n.workingDir?.trim();if(!o)return t.status(409).json({error:"ticket has no working dir set"});let i=await Ps(o,e.body?.repo);if(!i){let at=await Ue(o);return t.status(400).json({error:at.length===0?"no git repositories found in the working dir":`name the repo to work on; found: ${at.map(Zi=>Zi.name).join(", ")}`})}let c=s.worktrees??=[],d=c.find(at=>at.repo===i.name);if(d)return t.json(d);let u=(l.branchPrefix||"feature").trim().replace(/\/+$/,""),m=i.name==="."?"":`-${i.name}`,g=n.attempt??1,I=g>1?`-v${g}`:"",p=`${u}/${n.externalIdentifier}${m}${I}`,w=await Os(i.path),te=await ar(i.path,w),Qe=so(n.id,i.name);if(Qe.ambiguous)return t.status(409).json({error:`${n.externalIdentifier} depends on multiple tickets that both changed ${i.name} (${Qe.ambiguous.join(", ")}) \u2014 chain them (make one depend on the other) so there's a single base to build on.`});Qe.startPoint&&(w=Qe.startPoint,te=Qe.startPoint);let Vi=(i.name==="."?"repo":i.name)+I,Xr=ee.join(ir,n.externalIdentifier,Vi),Yr=await Ds({repoPath:i.path,worktreePath:Xr,branch:p,base:w,startPoint:te});if(!Yr.ok)return t.status(500).json({error:Yr.error});let Vr={repo:i.name,branch:p,worktreePath:Xr,base:w,compareUrl:await $s(i.path,w,p),createdAt:new Date().toISOString()};return c.push(Vr),s.branchName=s.branchName||p,s.events.push({id:`e${s.events.length+1}`,ts:be(),kind:"mcp_tool",text:`claimed worktree for ${i.name} \u2192 ${p}`}),await L(s.id),t.json(Vr)});f.post("/api/tickets/:id/pr-links",async(e,t)=>{let n=h.find(i=>i.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=String(e.body?.url??"").trim();if(!/^https?:\/\//.test(r))return t.status(400).json({error:"a valid http(s) PR url is required"});let s=n.prLinks??=[];s.some(i=>i.url===r)||s.push({url:r,title:String(e.body?.title??"").trim()||void 0,createdAt:new Date().toISOString()}),await N(n.id);let o=x[T[n.id]];return o&&(o.prUrl=r,await L(o.id)),!C()&&s.length>1&&Mi(n.externalIdentifier,s.map(i=>i.url)).catch(()=>{}),t.status(201).json({prLinks:s})});f.get("/api/tickets/:id/pr-links",(e,t)=>{let n=h.find(r=>r.id===e.params.id);return t.json({prLinks:n?.prLinks??[]})});f.post("/api/tickets/:id/monitor",async(e,t)=>{let n=h.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});if(e.body?.on===!0){if(!n.prLinks?.length)return t.status(409).json({error:"no PR to monitor yet"});if(!T[n.id])return t.status(409).json({error:"no run/session to continue from"});n.prMonitor=!0,n.prMonitorNote=void 0,n.prMonitorLastAt=void 0,(n.prMonitorCount??0)>=on(l)&&(n.prMonitorCount=0)}else n.prMonitor=!1;return await N(n.id),t.json({prMonitor:n.prMonitor})});var qr=null,Fr=!1;async function Wd(e,t,n){let r=new Date().toISOString(),s=o=>t.events.push({id:`e${t.events.length+1}`,ts:be(),kind:"state_change",text:o});if(n.kind==="stamp"){e.prMonitorLastAt=r,await N(e.id);return}if(n.kind==="engage"){e.prMonitorCount=(e.prMonitorCount??0)+1,e.prMonitorLastAt=r,await N(e.id),t.status="running",t.stopReason=void 0,t.updatedAt=r,s(`PR monitor: ${n.reason==="comments"?"open review comments":"CI failing"} \u2192 engaging agent (pass ${e.prMonitorCount})`),await L(t.id),Te(t.id,!0,n.prompt);return}e.prMonitor=!1,e.prMonitorNote=n.note,e.prMonitorLastAt=r,s(`PR monitor: ${n.note}`),await L(t.id),await N(e.id)}async function Kd(){if(!(C()||Fr)){Fr=!0;try{let e=Date.now();for(let t of h){if(!t.prMonitor)continue;let n=we(t.id);if(n!=="in_review"&&n!=="done")continue;let r=T[t.id]?x[T[t.id]]:void 0;if(!r||r.status==="running"||!$i(t,l,e))continue;let s=(t.prLinks??[]).map(c=>c.url).filter(Boolean);if(!s.length){t.prMonitorLastAt=new Date().toISOString(),await N(t.id);continue}let o=await Pi(s),i=o.ci==="passing"&&l.prMonitorReplyToComments?await Oi(s):void 0;await Wd(t,r,Bi(t,l,o,i))}}finally{Fr=!1}}}function Hd(){qr||(qr=setInterval(()=>void Kd(),6e4),qr.unref?.())}f.post("/api/runs/:id/stop",async(e,t)=>{try{return t.json(await We(e.params.id))}catch(n){return cn(t,n)}});f.post("/api/runs/:id/complete",async(e,t)=>{let n=x[e.params.id];return n?(n.status="stopped",n.stopReason="completed",n.blocker=void 0,n.events.push({id:`e${n.events.length+1}`,ts:be(),kind:"mcp_tool",text:"mark_complete(...)"}),n.updatedAt=new Date().toISOString(),S[n.ticketId]="in_review",await L(n.id),await N(n.ticketId),t.json(n)):t.status(404).json({error:"run not found"})});f.post("/api/runs/:id/answer",async(e,t)=>{let n=x[e.params.id];if(!n||!n.blocker)return t.status(409).json({error:"no open blocker"});n.blocker.status="answered";let r=e.body?.decision?`human: ${e.body.decision}`:`human answered: ${e.body?.response??""}`;n.events.push({id:`e${n.events.length+1}`,ts:be(),kind:"mcp_tool",text:r}),n.blocker=void 0,n.status="running",n.updatedAt=new Date().toISOString(),S[n.ticketId]="in_progress",await L(n.id),await N(n.ticketId);let s=String(e.body?.decision??e.body?.response??"").trim();return C()||Te(n.id,!0,`The human responded: ${s}`),t.json(n)});f.post("/api/runs/:id/approve",async(e,t)=>{let n=x[e.params.id];return n?n.status!=="stopped"?t.status(409).json({error:"can only approve a stopped run"}):(n.events.push({id:`e${n.events.length+1}`,ts:be(),kind:"state_change",text:"approved by human \u2192 Done"}),n.updatedAt=new Date().toISOString(),S[n.ticketId]="done",await L(n.id),await N(n.ticketId),t.json(n)):t.status(404).json({error:"run not found"})});f.post("/api/runs/:id/respond",async(e,t)=>{let n=x[e.params.id];if(!n)return t.status(404).json({error:"run not found"});if(h.find(c=>c.id===n.ticketId)?.prMonitor)return t.status(409).json({error:"PR monitor is armed \u2014 turn it off to send a message"});if(n.status!=="stopped"&&n.status!=="blocked")return t.status(409).json({error:"run is not waiting for a response"});let r=String(e.body?.text??"").trim(),s=Array.isArray(e.body?.attachments)?e.body.attachments.map(c=>String(c)).filter(Boolean):[];if(!r&&s.length===0)return t.status(400).json({error:"empty response"});let o=n.status==="blocked";n.blocker&&(n.blocker=void 0),n.status="running",n.stopReason=void 0,n.events.push({id:`e${n.events.length+1}`,ts:be(),kind:o?"mcp_tool":"state_change",text:`human responded: ${r.slice(0,80)}${s.length?` (+${s.length} file${s.length>1?"s":""})`:""}`}),n.updatedAt=new Date().toISOString(),S[n.ticketId]="in_progress",await L(n.id),await N(n.ticketId);let i=r+(s.length?`
122
122
 
123
123
  Attached files (read these):
124
124
  ${s.map(c=>`- ${c}`).join(`
125
- `)}`:"");return _()||be(n.id,!0,i),t.json(n)});f.post("/api/tickets/:id/start-over",async(e,t)=>{let n=h.find(d=>d.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=x[n.id],s=(r?I[r]?.worktrees:void 0)??[];r&&(await it(r),delete I[r],delete x[n.id],await Lr(r)),await rn(n.externalIdentifier);let o=n.workingDir?.trim();if(o)for(let d of s){let u=d.repo==="."?o:Q.join(o,d.repo);await us(u,d.branch)}let i=e.body?.keep??{},c=d=>i[d]===!1;n.prLinks=void 0,n.attempt=(n.attempt??1)+1;for(let d=q.length-1;d>=0;d--)q[d].ticketId===n.id&&q.splice(d,1);if(await Br(n.id),c("plan")&&(n.plan=void 0,n.planUpdatedAt=void 0),c("conclusion")&&(n.conclusion=void 0,n.conclusionUpdatedAt=void 0),c("context")&&(n.additionalContext=void 0,n.additionalContextUpdatedAt=void 0),c("questions")){for(let d=C.length-1;d>=0;d--)if(C[d].ticketId===n.id){let[u]=C.splice(d,1);await zt(u.id)}}if(c("notes")){for(let d=P.length-1;d>=0;d--)if(P[d].ticketId===n.id){let[u]=P.splice(d,1);await Ht(u.id)}}return S[n.id]="backlog",await T(n.id),t.json({ticketId:n.id,column:"backlog"})});f.post("/api/tickets/:id/summarize",async(e,t)=>{let n=h.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=await fd(n);return r?t.json({summary:r}):t.status(502).json({error:"could not generate a summary"})});f.delete("/api/tickets/:id",async(e,t)=>{let n=h.findIndex(o=>o.id===e.params.id);if(n===-1)return t.status(404).json({error:"ticket not found"});let[r]=h.splice(n,1),s=x[r.id];return s&&(delete I[s],delete x[r.id]),delete S[r.id],J.push(r),await rn(r.externalIdentifier),await Wt(r.id),t.status(204).end()});f.post("/api/board/:connectionId/clear-done",async(e,t)=>{let n=e.params.connectionId,r=h.filter(s=>s.connectionId===n&&fe(s.id)==="done").map(s=>s.id);for(let s of r){let o=h.findIndex(d=>d.id===s),i=o!==-1?h[o].externalIdentifier:null;o!==-1&&h.splice(o,1);let c=x[s];c&&(delete I[c],delete x[s]),delete S[s],i&&await rn(i),await Wt(s)}return t.json({removed:r.length})});f.get("/api/conversations",(e,t)=>{let n=te.map(r=>M[r]).filter(Boolean).sort((r,s)=>r.updatedAt<s.updatedAt?1:-1).map(r=>({id:r.id,title:r.title,updatedAt:r.updatedAt,workspaceId:r.workspaceId,workspaceName:r.workspaceName,tier:r.tier,preview:r.messages.length?r.messages[r.messages.length-1].text:"",messageCount:r.messages.length,starred:r.starred}));t.json(n)});f.get("/api/conversations/:id",(e,t)=>{let n=M[e.params.id];return n?t.json(n):t.status(404).json({error:"conversation not found"})});var cd={Instant:"haiku",Medium:"sonnet",High:"opus"},dd=["low","medium","high","xhigh","max"],ui=e=>{let t=String(e??"").trim();return dd.includes(t)?t:"low"};async function li(e,t,n,r=[]){if(_())return md(t,e.workspaceName,e.tier);let o=(t||(r.length?"Please look at the attached image(s).":""))+(r.length?`
125
+ `)}`:"");return C()||Te(n.id,!0,i),t.json(n)});f.post("/api/tickets/:id/start-over",async(e,t)=>{let n=h.find(d=>d.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=T[n.id],s=(r?x[r]?.worktrees:void 0)??[];r&&(await St(r),delete x[r],delete T[n.id],await us(r)),await Rn(n.externalIdentifier);let o=n.workingDir?.trim();if(o)for(let d of s){let u=d.repo==="."?o:ee.join(o,d.repo);await Ms(u,d.branch)}let i=e.body?.keep??{},c=d=>i[d]===!1;n.prLinks=void 0,n.attempt=(n.attempt??1)+1;for(let d=X.length-1;d>=0;d--)X[d].ticketId===n.id&&X.splice(d,1);if(await fs(n.id),c("plan")&&(n.plan=void 0,n.planUpdatedAt=void 0),c("conclusion")&&(n.conclusion=void 0,n.conclusionUpdatedAt=void 0),c("context")&&(n.additionalContext=void 0,n.additionalContextUpdatedAt=void 0),c("questions")){for(let d=D.length-1;d>=0;d--)if(D[d].ticketId===n.id){let[u]=D.splice(d,1);await kn(u.id)}}if(c("notes")){for(let d=j.length-1;d>=0;d--)if(j[d].ticketId===n.id){let[u]=j.splice(d,1);await gn(u.id)}}return S[n.id]="backlog",await N(n.id),t.json({ticketId:n.id,column:"backlog"})});f.post("/api/tickets/:id/summarize",async(e,t)=>{let n=h.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=await Vd(n);return r?t.json({summary:r}):t.status(502).json({error:"could not generate a summary"})});f.delete("/api/tickets/:id",async(e,t)=>{let n=h.findIndex(o=>o.id===e.params.id);if(n===-1)return t.status(404).json({error:"ticket not found"});let[r]=h.splice(n,1),s=T[r.id];return s&&(delete x[s],delete T[r.id]),delete S[r.id],re.push(r),await Rn(r.externalIdentifier),await En(r.id),await pn(r.id),t.status(204).end()});f.post("/api/board/:connectionId/clear-done",async(e,t)=>{let n=e.params.connectionId,r=h.filter(s=>s.connectionId===n&&we(s.id)==="done").map(s=>s.id);for(let s of r){let o=h.findIndex(d=>d.id===s),i=o!==-1?h[o].externalIdentifier:null;o!==-1&&h.splice(o,1);let c=T[s];c&&(delete x[c],delete T[s]),delete S[s],i&&await Rn(i),await En(s),await pn(s)}return t.json({removed:r.length})});f.get("/api/conversations",(e,t)=>{let n=ce.map(r=>F[r]).filter(Boolean).sort((r,s)=>r.updatedAt<s.updatedAt?1:-1).map(r=>({id:r.id,title:r.title,updatedAt:r.updatedAt,workspaceId:r.workspaceId,workspaceName:r.workspaceName,tier:r.tier,preview:r.messages.length?r.messages[r.messages.length-1].text:"",messageCount:r.messages.length,starred:r.starred}));t.json(n)});f.get("/api/conversations/:id",(e,t)=>{let n=F[e.params.id];return n?t.json(n):t.status(404).json({error:"conversation not found"})});var Qd={Instant:"haiku",Medium:"sonnet",High:"opus"},Jd=["low","medium","high","xhigh","max"],Hi=e=>{let t=String(e??"").trim();return Jd.includes(t)?t:"low"};async function Qi(e,t,n,r=[]){if(C())return Zd(t,e.workspaceName,e.tier);let o=(t||(r.length?"Please look at the attached image(s).":""))+(r.length?`
126
126
 
127
127
  Attached files (read these):
128
128
  ${r.map(d=>`- ${d}`).join(`
129
- `)}`:""),i=n?`${fn}
129
+ `)}`:""),i=n?`${jn}
130
130
 
131
- ${o}`:o,c=await Ue({prompt:i,workspace:e.workspaceId,workingDir:e.workingDir,model:cd[e.tier],effort:e.effort,sessionId:n?e.sessionId:null,resume:n?null:e.sessionId,pipelinesTools:!0,pipelinesToolsMode:"restricted",sandbox:!0,sandboxRepos:await mn(e.workingDir)});return c.code===0?c.stdout.trim()||"(the agent returned no output)":`\u26A0\uFE0F The run failed (exit ${c.code}).
131
+ ${o}`:o,c=await Ve({prompt:i,workspace:e.workspaceId,workingDir:e.workingDir,model:Qd[e.tier],effort:e.effort,sessionId:n?e.sessionId:null,resume:n?null:e.sessionId,pipelinesTools:!0,pipelinesToolsMode:"restricted",sandbox:!0,sandboxRepos:await Mn(e.workingDir)});return c.code===0?c.stdout.trim()||"(the agent returned no output)":`\u26A0\uFE0F The run failed (exit ${c.code}).
132
132
 
133
- ${(c.stderr||c.stdout).trim().slice(0,500)}`}async function pi(e,t){if(_()||!t.trim())return null;let n=`Write a concise title (3\u20136 words, Title Case, no surrounding quotes, no trailing punctuation) that captures the conversation below. Reply with ONLY the title.
133
+ ${(c.stderr||c.stdout).trim().slice(0,500)}`}async function Ji(e,t){if(C()||!t.trim())return null;let n=`Write a concise title (3\u20136 words, Title Case, no surrounding quotes, no trailing punctuation) that captures the conversation below. Reply with ONLY the title.
134
134
 
135
135
  """
136
136
  ${t.slice(0,4e3)}
137
- """`;try{let r=await Ue({prompt:n,workspace:e.workspaceId,workingDir:e.workingDir,model:"haiku",effort:"low",noCapture:!0});if(r.code!==0)return null;let o=r.stdout.split(`
138
- `).map(i=>i.trim()).find(Boolean)?.replace(/^["'“”\s]+|["'“”.\s]+$/g,"").trim();return o?o.length>48?`${o.slice(0,48).trimEnd()}\u2026`:o:null}catch{return null}}function fi(e){return e.messages.map(t=>`${t.role==="assistant"?"Assistant":"User"}: ${t.text}`).join(`
137
+ """`;try{let r=await Ve({prompt:n,workspace:e.workspaceId,workingDir:e.workingDir,model:"haiku",effort:"low",noCapture:!0});if(r.code!==0)return null;let o=r.stdout.split(`
138
+ `).map(i=>i.trim()).find(Boolean)?.replace(/^["'“”\s]+|["'“”.\s]+$/g,"").trim();return o?o.length>48?`${o.slice(0,48).trimEnd()}\u2026`:o:null}catch{return null}}function zi(e){return e.messages.map(t=>`${t.role==="assistant"?"Assistant":"User"}: ${t.text}`).join(`
139
139
 
140
- `).slice(0,8e3)}async function ud(e){if(_())return null;let t=fi(e);if(!t.trim())return null;let n=`Summarize the conversation below in 2\u20134 short sentences (or a few concise bullet points): what the user wanted and the key points or outcome. Reply with ONLY the summary.
140
+ `).slice(0,8e3)}async function zd(e){if(C())return null;let t=zi(e);if(!t.trim())return null;let n=`Summarize the conversation below in 2\u20134 short sentences (or a few concise bullet points): what the user wanted and the key points or outcome. Reply with ONLY the summary.
141
141
 
142
142
  """
143
143
  ${t}
144
- """`;try{let r=await Ue({prompt:n,workspace:e.workspaceId,workingDir:e.workingDir,model:"haiku",effort:"low",noCapture:!0});return r.code!==0?null:r.stdout.trim()||null}catch{return null}}var ld={backlog:"Backlog",in_progress:"In Progress",needs_input:"Blocked",in_review:"In Review",done:"Done"};function pd(e){let t=(g,p)=>g&&g.trim()?g.trim():p,n=x[e.id]?I[x[e.id]]:void 0,r=["No priority","Urgent","High","Medium","Low"][e.priority??0]??"No priority",s=[`Task: ${e.externalIdentifier} \u2014 ${e.title} (source: ${e.provider})`,`Board stage: ${ld[fe(e.id)]??fe(e.id)}`,`Source status: ${t(e.statusRaw,"\u2014")}`,`Priority: ${r}`,`Assignee: ${e.assignee?.name??"unassigned"} | Reporter: ${e.reporter?.name??"\u2014"}`,`Project: ${e.project??"\u2014"}${e.parent?` | Parent: ${e.parent.identifier} \xB7 ${e.parent.title}`:""}`,`Due date: ${e.dueDate??"\u2014"}`,e.labels.length?`Labels: ${e.labels.map(g=>g.name).join(", ")}`:"Labels: none",`Run: ${n?`${n.status}${n.stopReason?` (${n.stopReason})`:""}`:"not started"}`,e.blockedReason?`BLOCKED \u2014 reason: ${e.blockedReason}`:null].filter(Boolean).join(`
145
- `),o=C.filter(g=>g.ticketId===e.id).sort((g,p)=>g.position-p.position),i=o.length?o.map(g=>`- Q: ${g.question}
144
+ """`;try{let r=await Ve({prompt:n,workspace:e.workspaceId,workingDir:e.workingDir,model:"haiku",effort:"low",noCapture:!0});return r.code!==0?null:r.stdout.trim()||null}catch{return null}}var Xd={backlog:"Backlog",in_progress:"In Progress",needs_input:"Blocked",in_review:"In Review",done:"Done"};function Yd(e){let t=(g,I)=>g&&g.trim()?g.trim():I,n=T[e.id]?x[T[e.id]]:void 0,r=["No priority","Urgent","High","Medium","Low"][e.priority??0]??"No priority",s=[`Task: ${e.externalIdentifier} \u2014 ${e.title} (source: ${e.provider})`,`Board stage: ${Xd[we(e.id)]??we(e.id)}`,`Source status: ${t(e.statusRaw,"\u2014")}`,`Priority: ${r}`,`Assignee: ${e.assignee?.name??"unassigned"} | Reporter: ${e.reporter?.name??"\u2014"}`,`Project: ${e.project??"\u2014"}${e.parent?` | Parent: ${e.parent.identifier} \xB7 ${e.parent.title}`:""}`,`Due date: ${e.dueDate??"\u2014"}`,e.labels.length?`Labels: ${e.labels.map(g=>g.name).join(", ")}`:"Labels: none",`Run: ${n?`${n.status}${n.stopReason?` (${n.stopReason})`:""}`:"not started"}`,e.blockedReason?`BLOCKED \u2014 reason: ${e.blockedReason}`:null].filter(Boolean).join(`
145
+ `),o=D.filter(g=>g.ticketId===e.id).sort((g,I)=>g.position-I.position),i=o.length?o.map(g=>`- Q: ${g.question}
146
146
  A: ${t(g.answer,"(unanswered)")} [${g.resolved?"resolved":"open"}]`).join(`
147
- `):"No open questions.",c=P.filter(g=>g.ticketId===e.id),d=c.length?c.map(g=>`- [${g.author==="assistant"?"AI":"Me"}] ${g.body.slice(0,500)}`).join(`
148
- `):"No notes.",u=q.filter(g=>g.ticketId===e.id).slice(-8),m=u.length?u.map((g,p)=>`Turn ${p+1} [${g.status}${g.model?`, ${g.model}`:""}]:
147
+ `):"No open questions.",c=j.filter(g=>g.ticketId===e.id),d=c.length?c.map(g=>`- [${g.author==="assistant"?"AI":"Me"}] ${g.body.slice(0,500)}`).join(`
148
+ `):"No notes.",u=X.filter(g=>g.ticketId===e.id).slice(-8),m=u.length?u.map((g,I)=>`Turn ${I+1} [${g.status}${g.model?`, ${g.model}`:""}]:
149
149
  Request: ${String(g.prompt??"").slice(0,800)}
150
150
  Response: ${String(g.response??"").slice(0,1500)}`).join(`
151
151
 
@@ -164,12 +164,12 @@ ${d}`,`
164
164
  ${t(e.conclusion,"No conclusion yet.")}`,`
165
165
  === Run history (oldest \u2192 newest) ===
166
166
  ${m}`].join(`
167
- `).slice(0,14e3)}async function fd(e){if(_())return null;let t=`You are briefing a teammate on the current state of a task. Using the task data below, write a concise summary: what the task is about, what's been done so far, what's still pending or not started yet (explicitly call out empty parts \u2014 no description, no plan, no runs, unanswered questions, etc.), and any blockers. A few short paragraphs or bullet points. Reply with ONLY the summary.
167
+ `).slice(0,14e3)}async function Vd(e){if(C())return null;let t=`You are briefing a teammate on the current state of a task. Using the task data below, write a concise summary: what the task is about, what's been done so far, what's still pending or not started yet (explicitly call out empty parts \u2014 no description, no plan, no runs, unanswered questions, etc.), and any blockers. A few short paragraphs or bullet points. Reply with ONLY the summary.
168
168
 
169
169
  """
170
- ${pd(e)}
171
- """`;try{let n=await Ue({prompt:t,workspace:e.workspaceId,workingDir:e.workingDir,model:"haiku",effort:"low",noCapture:!0});return n.code!==0?null:n.stdout.trim()||null}catch{return null}}f.post("/api/conversations",async(e,t)=>{let n=String(e.body?.text??"").trim(),r=xr(e.body);if(!n&&r.length===0)return t.status(400).json({error:"empty message"});let s=j.find(g=>g.id===e.body?.workspaceId)??j[0];if(!s)return t.status(409).json({error:"no workspace available"});let o=String(e.body?.tier??"Instant"),i=ui(e.body?.effort),c=String(e.body?.workingDir??"").trim(),d=`conv_${++L.convSeq}`,u=gi(n,r),m={id:d,title:mi(u),workspaceId:s.id,workspaceName:s.name,tier:o,effort:i,workingDir:c||void 0,sessionId:Ke(),messages:[{id:"m1",role:"user",text:u,ts:me(),...r.length?{attachments:r.map(di)}:{}}],starred:!1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};M[d]=m,te.push(d),await Ge(d),t.status(201).json(m),(async()=>{let g=pi(m,n),p;try{p=await li(m,n,!0,r)}catch(Y){p=`\u26A0\uFE0F The run failed.
170
+ ${Yd(e)}
171
+ """`;try{let n=await Ve({prompt:t,workspace:e.workspaceId,workingDir:e.workingDir,model:"haiku",effort:"low",noCapture:!0});return n.code!==0?null:n.stdout.trim()||null}catch{return null}}f.post("/api/conversations",async(e,t)=>{let n=String(e.body?.text??"").trim(),r=zr(e.body);if(!n&&r.length===0)return t.status(400).json({error:"empty message"});let s=$.find(g=>g.id===e.body?.workspaceId)??$[0];if(!s)return t.status(409).json({error:"no workspace available"});let o=String(e.body?.tier??"Instant"),i=Hi(e.body?.effort),c=String(e.body?.workingDir??"").trim(),d=`conv_${++B.convSeq}`,u=Yi(n,r),m={id:d,title:Xi(u),workspaceId:s.id,workspaceName:s.name,tier:o,effort:i,workingDir:c||void 0,sessionId:ot(),messages:[{id:"m1",role:"user",text:u,ts:be(),...r.length?{attachments:r.map(Ki)}:{}}],starred:!1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};F[d]=m,ce.push(d),await Ye(d),t.status(201).json(m),(async()=>{let g=Ji(m,n),I;try{I=await Qi(m,n,!0,r)}catch(w){I=`\u26A0\uFE0F The run failed.
172
172
 
173
- ${String(Y).slice(0,500)}`}let w=await Promise.race([g,new Promise(Y=>setTimeout(()=>Y(null),3e3))]);w&&(m.title=w),m.messages.push({id:"m2",role:"assistant",text:p,ts:me()}),m.updatedAt=new Date().toISOString(),await Ge(d),w||g.then(Y=>{Y&&(m.title=Y,Ge(d))})})()});f.post("/api/conversations/:id/messages",async(e,t)=>{let n=M[e.params.id];if(!n)return t.status(404).json({error:"conversation not found"});let r=String(e.body?.text??"").trim(),s=xr(e.body);if(!r&&s.length===0)return t.status(400).json({error:"empty message"});n.messages.push({id:`m${n.messages.length+1}`,role:"user",text:gi(r,s),ts:me(),...s.length?{attachments:s.map(di)}:{}});let o=await li(n,r,!1,s);return n.messages.push({id:`m${n.messages.length+1}`,role:"assistant",text:o,ts:me()}),n.updatedAt=new Date().toISOString(),await Ge(n.id),t.json(n)});f.patch("/api/conversations/:id",async(e,t)=>{let n=M[e.params.id];if(!n)return t.status(404).json({error:"conversation not found"});let r=String(e.body?.title??"").trim();r&&(n.title=r),typeof e.body?.starred=="boolean"&&(n.starred=e.body.starred);let s=String(e.body?.tier??"").trim();return s&&(n.tier=s),"effort"in(e.body??{})&&(n.effort=ui(e.body.effort)),await Ge(n.id),t.json(n)});f.post("/api/conversations/:id/retitle",async(e,t)=>{let n=M[e.params.id];if(!n)return t.status(404).json({error:"conversation not found"});let r=await pi(n,fi(n));return r&&(n.title=r,await Ge(n.id)),t.json(n)});f.post("/api/conversations/:id/summarize",async(e,t)=>{let n=M[e.params.id];if(!n)return t.status(404).json({error:"conversation not found"});let r=await ud(n);return r?t.json({summary:r}):t.status(502).json({error:"could not generate a summary"})});f.delete("/api/conversations/:id",async(e,t)=>{let n=e.params.id;if(!M[n])return t.status(404).json({error:"conversation not found"});delete M[n];let r=te.indexOf(n);return r!==-1&&te.splice(r,1),await Ur(n),t.status(204).end()});function mi(e){let t=e.split(`
174
- `)[0].trim();return t.length>48?`${t.slice(0,48).trimEnd()}\u2026`:t}function xr(e){let t=e?.attachments;return Array.isArray(t)?t.map(n=>String(n)).filter(Boolean):[]}function gi(e,t){if(e)return e;let n=t.length;return n?`(${n} image${n>1?"s":""})`:""}function md(e,t,n){let r=mi(e);return[`Running under ${t} (${n}) \u2014 your team, guardrails and memory are in context.`,"",`Here's how I'd approach "${r}":`,"\u2022 Start with the smallest shippable change.","\u2022 Reuse what's already in the repo before adding anything new.","\u2022 Verify with the existing tests, then tighten from there.","","(Mocked reply \u2014 the real chat drives your own claude on the same owned runtime.)"].join(`
175
- `)}f.get("/api/schedules",(e,t)=>{t.json(H.map(n=>E[n]).filter(Boolean))});f.get("/api/schedules/:id",(e,t)=>{let n=E[e.params.id];return n?t.json(n):t.status(404).json({error:"schedule not found"})});f.get("/api/schedules/:id/runs",async(e,t)=>{if(!E[e.params.id])return t.status(404).json({error:"schedule not found"});let n=Math.max(0,Number(e.query.offset??0)),r=Math.min(Math.max(1,Number(e.query.limit??6)),100),{runs:s,total:o}=await Fr(e.params.id,r,n),i=n+r<o?n+r:null;return t.json({runs:s,nextOffset:i,total:o})});f.post("/api/schedules",async(e,t)=>{let n=String(e.body?.name??"").trim()||"Untitled schedule",r=String(e.body?.prompt??"").trim(),s=j.find(g=>g.id===e.body?.workspaceId)??j[0],o=["team","agent","anyone"].includes(e.body?.assignmentKind)?e.body.assignmentKind:"anyone",i=o==="team"?Re.find(g=>g.id===e.body?.teamId):void 0,c=o==="agent"?Te.find(g=>g.id===e.body?.agentId):void 0,d=String(e.body?.cadence??"Every 1 hour").trim(),u=`sched_${++L.schedSeq}`,m={id:u,name:n,prompt:r,workspaceId:s.id,workspaceName:s.name,assignmentKind:o,teamId:i?.id,teamName:i?.name,agentId:c?.id,agentName:c?.name,cadence:d,workingDir:String(e.body?.workingDir??"").trim()||xn(s.id),model:ye(e.body?.model??l.defaultModel),effort:we(e.body?.effort??l.defaultEffort),enabled:!0,starred:!1,createdAt:new Date().toISOString(),lastRunAt:null,nextRunAt:jt(Date.now(),d)};return E[u]=m,H.unshift(u),B[u]=[],await _t(u),t.status(201).json(m)});f.post("/api/schedules/:id/run",async(e,t)=>{let n=E[e.params.id];if(!n)return t.status(404).json({error:"schedule not found"});let r=await Zn(n.id,!1);return r?t.status(201).json(r):t.status(409).json({error:"schedule is already running"})});f.patch("/api/schedules/:id",async(e,t)=>{let n=E[e.params.id];if(!n)return t.status(404).json({error:"schedule not found"});let r=e.body??{};if(typeof r.enabled=="boolean"&&(n.enabled=r.enabled,n.nextRunAt=r.enabled?jt(Date.now(),n.cadence):null),typeof r.starred=="boolean"&&(n.starred=r.starred),typeof r.name=="string"&&r.name.trim()&&(n.name=r.name.trim()),typeof r.prompt=="string"&&(n.prompt=r.prompt),typeof r.workingDir=="string"&&(n.workingDir=r.workingDir.trim()||void 0),r.model!==void 0&&(n.model=ye(r.model,n.model||ce)),r.effort!==void 0&&(n.effort=we(r.effort,n.effort||de)),typeof r.cadence=="string"&&r.cadence.trim()&&(n.cadence=r.cadence.trim()),typeof r.workspaceId=="string"){let s=j.find(o=>o.id===r.workspaceId);s&&(n.workspaceId=s.id,n.workspaceName=s.name)}if(["team","agent","anyone"].includes(r.assignmentKind)){n.assignmentKind=r.assignmentKind;let s=r.assignmentKind==="team"?Re.find(i=>i.id===r.teamId):void 0,o=r.assignmentKind==="agent"?Te.find(i=>i.id===r.agentId):void 0;n.teamId=s?.id,n.teamName=s?.name,n.agentId=o?.id,n.agentName=o?.name}return await _t(n.id),t.json(n)});f.delete("/api/schedules/:id",async(e,t)=>{let n=e.params.id;if(!E[n])return t.status(404).json({error:"schedule not found"});delete E[n],delete B[n];let r=H.indexOf(n);return r!==-1&&H.splice(r,1),await Gr(n),t.status(204).end()});var wr=["publicApiEnabled","apiKeyHash","apiKeyLast4","apiKeyCreatedAt","webhookEnabled","webhookUrl","webhookHeaders","webhookEvents","webhookSecret"];f.get("/api/settings",(e,t)=>{let n={...l};for(let r of wr)delete n[r];t.json(n)});f.put("/api/settings",async(e,t)=>{let n={...e.body??{}};for(let s of wr)delete n[s];Object.assign(l,n),"defaultModel"in n&&(l.defaultModel=ye(l.defaultModel)),"defaultEffort"in n&&(l.defaultEffort=we(l.defaultEffort)),await X();let r={...l};for(let s of wr)delete r[s];t.json(r)});f.get("/api/public-api",(e,t)=>t.json(Dt()));f.post("/api/public-api/enable",async(e,t)=>{t.json(await Os(e.body?.enabled===!0))});f.post("/api/public-api/key",async(e,t)=>{t.status(201).json(await Ds())});f.delete("/api/public-api/key",async(e,t)=>{t.json(await js())});f.put("/api/public-api/webhook",async(e,t)=>{try{t.json(await $s(e.body??{}))}catch(n){if(n instanceof xe)return t.status(n.status).json({error:n.message});throw n}});f.post("/api/public-api/webhook/secret",async(e,t)=>{t.status(201).json(await Ms())});f.post("/api/public-api/webhook/test",async(e,t)=>{t.json(await Ls())});function me(){let e=new Date;return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}Ws(f,Gt);var yr=Q.join(Q.dirname(zc(import.meta.url)),"..","dist");Gt===br&&ve.existsSync(Q.join(yr,"index.html"))&&(f.use(In.static(yr)),f.get("*",(e,t,n)=>{if(e.path.startsWith("/api"))return n();t.sendFile(Q.join(yr,"index.html"))}));process.env.PIPELINES_TEST||rs().then(e=>{console.log(e.loggedIn?`[pipelines] authenticated as ${e.email??e.userId}`:`[pipelines] not authenticated: ${e.error}`)}).then(()=>Cr()).then(()=>jr()).then(()=>Yc()).then(()=>bs()).then(()=>Qs()).then(()=>Ks()).then(()=>Qo({listConnections:()=>y,connectedWorkspaces:()=>l.connectedWorkspaces,syncOne:Ir,isMock:_})).then(()=>ad()).then(()=>f.listen(Gt,()=>{console.log(`[pipelines] ready http://localhost:${Gt} (sqlite)`)})).then(()=>{l.publicApiEnabled&&un(ln)}).catch(e=>{console.error("[pipelines] startup failed:",e),process.exit(1)});export{f as app};
173
+ ${String(w).slice(0,500)}`}let p=await Promise.race([g,new Promise(w=>setTimeout(()=>w(null),3e3))]);p&&(m.title=p),m.messages.push({id:"m2",role:"assistant",text:I,ts:be()}),m.updatedAt=new Date().toISOString(),await Ye(d),p||g.then(w=>{w&&(m.title=w,Ye(d))})})()});f.post("/api/conversations/:id/messages",async(e,t)=>{let n=F[e.params.id];if(!n)return t.status(404).json({error:"conversation not found"});let r=String(e.body?.text??"").trim(),s=zr(e.body);if(!r&&s.length===0)return t.status(400).json({error:"empty message"});n.messages.push({id:`m${n.messages.length+1}`,role:"user",text:Yi(r,s),ts:be(),...s.length?{attachments:s.map(Ki)}:{}});let o=await Qi(n,r,!1,s);return n.messages.push({id:`m${n.messages.length+1}`,role:"assistant",text:o,ts:be()}),n.updatedAt=new Date().toISOString(),await Ye(n.id),t.json(n)});f.patch("/api/conversations/:id",async(e,t)=>{let n=F[e.params.id];if(!n)return t.status(404).json({error:"conversation not found"});let r=String(e.body?.title??"").trim();r&&(n.title=r),typeof e.body?.starred=="boolean"&&(n.starred=e.body.starred);let s=String(e.body?.tier??"").trim();return s&&(n.tier=s),"effort"in(e.body??{})&&(n.effort=Hi(e.body.effort)),await Ye(n.id),t.json(n)});f.post("/api/conversations/:id/retitle",async(e,t)=>{let n=F[e.params.id];if(!n)return t.status(404).json({error:"conversation not found"});let r=await Ji(n,zi(n));return r&&(n.title=r,await Ye(n.id)),t.json(n)});f.post("/api/conversations/:id/summarize",async(e,t)=>{let n=F[e.params.id];if(!n)return t.status(404).json({error:"conversation not found"});let r=await zd(n);return r?t.json({summary:r}):t.status(502).json({error:"could not generate a summary"})});f.delete("/api/conversations/:id",async(e,t)=>{let n=e.params.id;if(!F[n])return t.status(404).json({error:"conversation not found"});delete F[n];let r=ce.indexOf(n);return r!==-1&&ce.splice(r,1),await ps(n),t.status(204).end()});function Xi(e){let t=e.split(`
174
+ `)[0].trim();return t.length>48?`${t.slice(0,48).trimEnd()}\u2026`:t}function zr(e){let t=e?.attachments;return Array.isArray(t)?t.map(n=>String(n)).filter(Boolean):[]}function Yi(e,t){if(e)return e;let n=t.length;return n?`(${n} image${n>1?"s":""})`:""}function Zd(e,t,n){let r=Xi(e);return[`Running under ${t} (${n}) \u2014 your team, guardrails and memory are in context.`,"",`Here's how I'd approach "${r}":`,"\u2022 Start with the smallest shippable change.","\u2022 Reuse what's already in the repo before adding anything new.","\u2022 Verify with the existing tests, then tighten from there.","","(Mocked reply \u2014 the real chat drives your own claude on the same owned runtime.)"].join(`
175
+ `)}f.get("/api/schedules",(e,t)=>{t.json(ne.map(n=>O[n]).filter(Boolean))});f.get("/api/schedules/:id",(e,t)=>{let n=O[e.params.id];return n?t.json(n):t.status(404).json({error:"schedule not found"})});f.get("/api/schedules/:id/runs",async(e,t)=>{if(!O[e.params.id])return t.status(404).json({error:"schedule not found"});let n=Math.max(0,Number(e.query.offset??0)),r=Math.min(Math.max(1,Number(e.query.limit??6)),100),{runs:s,total:o}=await gs(e.params.id,r,n),i=n+r<o?n+r:null;return t.json({runs:s,nextOffset:i,total:o})});f.post("/api/schedules",async(e,t)=>{let n=String(e.body?.name??"").trim()||"Untitled schedule",r=String(e.body?.prompt??"").trim(),s=$.find(g=>g.id===e.body?.workspaceId)??$[0],o=["team","agent","anyone"].includes(e.body?.assignmentKind)?e.body.assignmentKind:"anyone",i=o==="team"?Ce.find(g=>g.id===e.body?.teamId):void 0,c=o==="agent"?Pe.find(g=>g.id===e.body?.agentId):void 0,d=String(e.body?.cadence??"Every 1 hour").trim(),u=`sched_${++B.schedSeq}`,m={id:u,name:n,prompt:r,workspaceId:s.id,workspaceName:s.name,assignmentKind:o,teamId:i?.id,teamName:i?.name,agentId:c?.id,agentName:c?.name,cadence:d,workingDir:String(e.body?.workingDir??"").trim()||Kn(s.id),model:ve(e.body?.model??l.defaultModel),effort:Re(e.body?.effort??l.defaultEffort),enabled:!0,starred:!1,createdAt:new Date().toISOString(),lastRunAt:null,nextRunAt:nn(Date.now(),d)};return O[u]=m,ne.unshift(u),z[u]=[],await Ht(u),t.status(201).json(m)});f.post("/api/schedules/:id/run",async(e,t)=>{let n=O[e.params.id];if(!n)return t.status(404).json({error:"schedule not found"});let r=await Rr(n.id,!1);return r?t.status(201).json(r):t.status(409).json({error:"schedule is already running"})});f.patch("/api/schedules/:id",async(e,t)=>{let n=O[e.params.id];if(!n)return t.status(404).json({error:"schedule not found"});let r=e.body??{};if(typeof r.enabled=="boolean"&&(n.enabled=r.enabled,n.nextRunAt=r.enabled?nn(Date.now(),n.cadence):null),typeof r.starred=="boolean"&&(n.starred=r.starred),typeof r.name=="string"&&r.name.trim()&&(n.name=r.name.trim()),typeof r.prompt=="string"&&(n.prompt=r.prompt),typeof r.workingDir=="string"&&(n.workingDir=r.workingDir.trim()||void 0),r.model!==void 0&&(n.model=ve(r.model,n.model||he)),r.effort!==void 0&&(n.effort=Re(r.effort,n.effort||ke)),typeof r.cadence=="string"&&r.cadence.trim()&&(n.cadence=r.cadence.trim()),typeof r.workspaceId=="string"){let s=$.find(o=>o.id===r.workspaceId);s&&(n.workspaceId=s.id,n.workspaceName=s.name)}if(["team","agent","anyone"].includes(r.assignmentKind)){n.assignmentKind=r.assignmentKind;let s=r.assignmentKind==="team"?Ce.find(i=>i.id===r.teamId):void 0,o=r.assignmentKind==="agent"?Pe.find(i=>i.id===r.agentId):void 0;n.teamId=s?.id,n.teamName=s?.name,n.agentId=o?.id,n.agentName=o?.name}return await Ht(n.id),t.json(n)});f.delete("/api/schedules/:id",async(e,t)=>{let n=e.params.id;if(!O[n])return t.status(404).json({error:"schedule not found"});delete O[n],delete z[n];let r=ne.indexOf(n);return r!==-1&&ne.splice(r,1),await ls(n),t.status(204).end()});f.get("/api/batches",(e,t)=>t.json(Mt()));f.get("/api/batches/:id",(e,t)=>{try{return t.json($t(e.params.id))}catch(n){return it(t,n)}});f.post("/api/batches",async(e,t)=>{try{let n=await et(e.body??{});return t.status(201).json(n)}catch(n){return it(t,n)}});f.patch("/api/batches/:id",async(e,t)=>{try{return t.json(await Zs(e.params.id,e.body??{}))}catch(n){return it(t,n)}});f.delete("/api/batches/:id",async(e,t)=>{try{return await An(e.params.id),t.status(204).end()}catch(n){return it(t,n)}});f.post("/api/batches/:id/start",async(e,t)=>{try{return t.json(await Bt(e.params.id))}catch(n){return it(t,n)}});f.post("/api/batches/:id/pause",async(e,t)=>{try{return t.json(await Lt(e.params.id))}catch(n){return it(t,n)}});f.post("/api/batches/:id/stop",async(e,t)=>{try{return t.json(await Gt(e.params.id))}catch(n){return it(t,n)}});var Kr=["publicApiEnabled","apiKeyHash","apiKeyLast4","apiKeyCreatedAt","webhookEnabled","webhookUrl","webhookHeaders","webhookEvents","webhookSecret"];f.get("/api/settings",(e,t)=>{let n={...l};for(let r of Kr)delete n[r];t.json(n)});f.put("/api/settings",async(e,t)=>{let n={...e.body??{}};for(let s of Kr)delete n[s];Object.assign(l,n),"defaultModel"in n&&(l.defaultModel=ve(l.defaultModel)),"defaultEffort"in n&&(l.defaultEffort=Re(l.defaultEffort)),await se();let r={...l};for(let s of Kr)delete r[s];t.json(r)});f.get("/api/public-api",(e,t)=>t.json(tn()));f.post("/api/public-api/enable",async(e,t)=>{t.json(await ho(e.body?.enabled===!0))});f.post("/api/public-api/key",async(e,t)=>{t.status(201).json(await ko())});f.delete("/api/public-api/key",async(e,t)=>{t.json(await yo())});f.put("/api/public-api/webhook",async(e,t)=>{try{t.json(await wo(e.body??{}))}catch(n){if(n instanceof Ne)return t.status(n.status).json({error:n.message});throw n}});f.post("/api/public-api/webhook/secret",async(e,t)=>{t.status(201).json(await bo())});f.post("/api/public-api/webhook/test",async(e,t)=>{t.json(await So())});function be(){let e=new Date;return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}_o(f,an);var Wr=ee.join(ee.dirname(Dd(import.meta.url)),"..","dist");an===Hr&&Ee.existsSync(ee.join(Wr,"index.html"))&&(f.use(Wn.static(Wr)),f.get("*",(e,t,n)=>{if(e.path.startsWith("/api"))return n();t.sendFile(ee.join(Wr,"index.html"))}));process.env.PIPELINES_TEST||Ns().then(e=>{console.log(e.loggedIn?`[pipelines] authenticated as ${e.email??e.userId}`:`[pipelines] not authenticated: ${e.error}`)}).then(()=>rs()).then(()=>as()).then(()=>Md()).then(()=>Qs()).then(()=>No()).then(()=>ao()).then(()=>Ao()).then(()=>Ai({listConnections:()=>b,connectedWorkspaces:()=>l.connectedWorkspaces,syncOne:Jr,isMock:C})).then(()=>Hd()).then(()=>f.listen(an,()=>{console.log(`[pipelines] ready http://localhost:${an} (sqlite)`)})).then(()=>{l.publicApiEnabled&&Pn(On)}).catch(e=>{console.error("[pipelines] startup failed:",e),process.exit(1)});export{f as app};