@superclawd-ai/pipelines 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,171 @@
1
+ import { createRequire as __cr } from 'module'; const require = __cr(import.meta.url);
2
+ var si=Object.defineProperty;var bn=(e,t)=>()=>(e&&(t=e(e=0)),t);var oi=(e,t)=>{for(var n in t)si(e,n,{get:t[n],enumerable:!0})};var ke,j,Re,Te,w,k,I,x,S,l,$,ee,N,H,B,L,q,C,E,G,J,V=bn(()=>{"use strict";ke={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"}],w=[{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}],k=[{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"},$={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
+
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
+
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
+
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()}},ee=["conv_3","conv_2","conv_1"],N={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=[],C=[],E=[],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 Sn={};oi(Sn,{seedFromFixtures:()=>ii});async function ii(){let e=_();await Me.bulkCreate(w.map(n=>({...n,userId:e}))),await he.bulkCreate(k.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 $e.bulkCreate(H.map(n=>({...N[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(ee.map(n=>({...$[n],userId:e}))),await Ee.bulkCreate(q.map(n=>({...n,userId:e}))),await Le.bulkCreate(C.map(n=>({...n,userId:e}))),await Pe.bulkCreate(E.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 In=bn(()=>{"use strict";V();Je()});import ai from"node:os";import xr from"node:path";import ci from"node:fs";import{Sequelize as di,DataTypes as a}from"sequelize";import{Umzug as ui}from"umzug";function _(){return vr}function Ut(e){vr=e}async function Ir(e){try{return await e.count()}catch{return 0}}async function Tr(){if(ci.mkdirSync(xr.dirname(Gt),{recursive:!0}),await h.authenticate(),await li.up(),await Ir(he)===0&&await Ir(Ne)===0&&_()===xt){let{seedFromFixtures:t}=await Promise.resolve().then(()=>(In(),Sn));await t()}}var Gt,xt,vr,h,Me,he,_e,$e,Ae,Ne,He,ze,Ee,Le,Ce,Pe,Rr,li,Je=bn(()=>{"use strict";Gt=process.env.PIPELINES_DB_PATH??xr.join(ai.homedir(),".superclawd","pipelines.db"),xt=process.env.PIPELINES_DEV_USER_ID??"dev-user",vr=xt;h=new di({dialect:"sqlite",storage:Gt,logging:!1}),Me=h.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}),he=h.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,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=h.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}),$e=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.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}),Rr={Connection:Me,Ticket:he,Run:_e,Schedule:$e,ScheduleRun:Ae,Conversation:Ne,Setting:He,OAuthToken:ze,RunResult:Ee,Note:Le,MessagePreset:Ce,OpenQuestion:Pe},li=new ui({context:h.getQueryInterface(),storage:{async logMigration({name:e}){await h.query("INSERT INTO pipelines_migrations (name) VALUES (:name)",{replacements:{name:e}})},async unlogMigration({name:e}){await h.query("DELETE FROM pipelines_migrations WHERE name = :name",{replacements:{name:e}})},async executed(){await h.query("CREATE TABLE IF NOT EXISTS pipelines_migrations (name TEXT PRIMARY KEY)");let[e]=await h.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 h.sync()}},{name:"0002-oauth-tokens",async up(){await ze.sync()}},{name:"0003-settings-branch-prefix",async up(){let e=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.getQueryInterface();(await e.describeTable("tickets")).parent||await e.addColumn("tickets","parent",{type:a.JSON,allowNull:!0})}},{name:"0017-conversations-effort",async up(){let e=h.getQueryInterface();(await e.describeTable("conversations")).effort||await e.addColumn("conversations","effort",{type:a.STRING,allowNull:!0})}},{name:"0018-model-effort",async up(){let e=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.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=h.getQueryInterface();(await e.describeTable("runs")).worktrees||await e.addColumn("runs","worktrees",{type:a.JSON,allowNull:!0})}},{name:"0028-ticket-attempt",async up(){let e=h.getQueryInterface();(await e.describeTable("tickets")).attempt||await e.addColumn("tickets","attempt",{type:a.INTEGER,allowNull:!0})}},{name:"0029-pr-monitor",async up(){let e=h.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=h.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=h.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=h.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=h.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=h.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=h.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)}}]})});V();Je();import hn from"express";import jc from"cors";import{randomUUID as Ke}from"node:crypto";import Q from"node:path";import ve from"node:fs";import kn from"node:os";import{fileURLToPath as Mc}from"node:url";V();import De from"node:crypto";import xn from"node:fs";import pi from"node:os";import Tn from"node:path";var Rn="enc:v1:",fi=process.env.SUPERCLAWD_HOME||Tn.join(pi.homedir(),".superclawd"),vn=process.env.PIPELINES_KEY_FILE||Tn.join(fi,"pipelines.key"),vt=null;function _r(){if(vt)return vt;xn.mkdirSync(Tn.dirname(vn),{recursive:!0});try{let t=xn.readFileSync(vn);if(t.length===32)return vt=t,vt}catch{}let e=De.randomBytes(32);return xn.writeFileSync(vn,e,{mode:384}),vt=e,e}function Xe(e){let t=De.randomBytes(12),n=De.createCipheriv("aes-256-gcm",_r(),t),r=Buffer.concat([n.update(e,"utf8"),n.final()]),s=n.getAuthTag();return`${Rn}${t.toString("base64")}:${s.toString("base64")}:${r.toString("base64")}`}function Ye(e){if(!e.startsWith(Rn))return e;let[t,n,r]=e.slice(Rn.length).split(":"),s=De.createDecipheriv("aes-256-gcm",_r(),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 De.createHash("sha256").update(e,"utf8").digest("hex")}function Ze(e="",t=32){return e+De.randomBytes(t).toString("base64url")}function Rt(e,t){let n=Buffer.from(e),r=Buffer.from(t);return n.length!==r.length?!1:De.timingSafeEqual(n,r)}function Ar(e,t){return De.createHmac("sha256",e).update(t,"utf8").digest("hex")}Je();function mi(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}),te=(e,t)=>{let n={...e};for(let r of t)delete n[r];return mi(n)};function Nr(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 Er(){let e={where:{userId:_()}},t=await Me.findAll(e);w.length=0,w.push(...t.map(p=>te(z(p),["userId"])));let n=await he.findAll({...e,order:[["position","ASC"]]});k.length=0;for(let p of Object.keys(S))delete S[p];for(let p of n){let y=z(p);S[y.id]=y.column??"backlog",k.push(te(y,["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 y=te(z(p),["userId","pid","pgid"]);I[y.id]=y,x[y.ticketId]=y.id}let s=await $e.findAll({...e,order:[["createdAt","ASC"]]});for(let p of Object.keys(N))delete N[p];H.length=0;for(let p of s){let y=te(z(p),["userId"]);N[y.id]=y,H.push(y.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 y=z(p),Y=te(y,["userId","seq"]);(B[y.scheduleId]??=[]).push(Y)}let i=await Ne.findAll({...e,order:[["updatedAt","DESC"]]});for(let p of Object.keys($))delete $[p];ee.length=0;for(let p of i){let y=te(z(p),["userId"]);y.messages||(y.messages=[]),$[y.id]=y,ee.push(y.id)}let c=await Ee.findAll({...e,order:[["createdAt","DESC"]]});q.length=0;for(let p of c)q.push(te(z(p),["userId"]));let d=await Le.findAll({...e,order:[["createdAt","ASC"]]});C.length=0;for(let p of d)C.push(te(z(p),["userId"]));let u=await Ce.findAll({...e,order:[["position","ASC"]]});G.length=0;for(let p of u)G.push(te(z(p),["userId"]));let m=await Pe.findAll({...e,order:[["position","ASC"]]});E.length=0;for(let p of m)E.push(te(z(p),["userId"]));let g=await He.findByPk(_());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(y=>({key:y.key,value:Ye(String(y.value??""))}))),Array.isArray(p.webhookEvents)&&(l.webhookEvents=p.webhookEvents),typeof p.webhookSecret=="string"&&(l.webhookSecret=Ye(p.webhookSecret))}L.convSeq=Tt(Object.keys($),"conv"),L.schedSeq=Tt(Object.keys(N),"sched"),L.localSeq=Math.max(L.localSeq,Tt(k.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 Me.upsert({...e,userId:_()})}async function Cr(e){await Me.destroy({where:{id:e}})}async function Bt(){for(let e of j){let t=`conn_local_${e.id}`;if(w.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};w.push(n),await R(n)}}async function T(e){let t=k.find(n=>n.id===e);t&&await he.upsert(Nr({...t,userId:_(),column:S[e]??"backlog",position:k.indexOf(t)}))}async function Pr(){await Promise.all(k.map((e,t)=>he.update({position:t,column:S[e.id]??"backlog"},{where:{id:e.id}})))}async function qt(e){await he.destroy({where:{id:e}}),await _e.destroy({where:{ticketId:e}})}async function M(e){let t=I[e];t&&await _e.upsert({...t,userId:_()})}async function Dr(e){await _e.destroy({where:{id:e}})}async function _t(e){let t=N[e];t&&await $e.upsert({...t,userId:_()})}async function Or(e){await $e.destroy({where:{id:e}}),await Ae.destroy({where:{scheduleId:e}})}async function Ft(e,t){await Ae.upsert({...e,userId:_(),seq:t})}async function Ge(e){let t=$[e];t&&await Ne.upsert({...t,userId:_()})}async function jr(e){await Ne.destroy({where:{id:e}})}async function Wt(e){await Ee.upsert({...e,userId:_()})}async function Mr(e){await Ee.destroy({where:{ticketId:e,userId:_()}})}async function $r(e,t,n){let{count:r,rows:s}=await Ee.findAndCountAll({where:{ticketId:e,userId:_()},order:[["createdAt","DESC"]],limit:t,offset:n});return{entries:s.map(o=>te(z(o),["userId"])),total:r}}async function Lr(e,t,n){let{count:r,rows:s}=await Ae.findAndCountAll({where:{scheduleId:e,userId:_()},order:[["seq","DESC"]],limit:t,offset:n});return{runs:s.map(o=>te(z(o),["userId","seq"])),total:r}}async function et(e){await Le.upsert({...e,userId:_()})}async function Kt(e){await Le.destroy({where:{id:e}})}async function Qt(e){let t=G.find(n=>n.id===e);t&&await Ce.upsert({...t,userId:_()})}async function Gr(e){await Ce.destroy({where:{id:e}})}async function Ur(){await Promise.all(G.map((e,t)=>Ce.update({position:t},{where:{id:e.id}})))}async function _n(e){let t=E.find(n=>n.id===e);t&&await Pe.upsert(Nr({...t,userId:_()}))}async function Ht(e){await Pe.destroy({where:{id:e}})}async function Br(){await Promise.all(E.map((e,t)=>Pe.update({position:t},{where:{id:e.id}})))}async function X(){await He.upsert({userId:_(),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 qr(){let e={where:{userId:_()}};await Promise.all(Object.values(Rr).map(t=>t.destroy(e)))}async function Fr(){await qr();let{seedFromFixtures:e}=await Promise.resolve().then(()=>(In(),Sn));await e()}async function Wr(){let e=new Set(j.map(o=>o.id)),t=[],n=new Set;for(let o of w)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(w),w.push(...t),r(k),r(J),r(q),r(C),r(E),r(H),r(ee),s(I),s(x),s(S),s(N),s(B),s($),await qr();for(let o of t)await R(o);await Bt(),await X();for(let o of G)await Qt(o.id)}import An from"node:fs";import gi from"node:os";import Nn from"node:path";function ki(){let e=process.env.CLAUDE_CONFIG_DIR||Nn.join(gi.homedir(),".claude");return Nn.join(e,"projects")}function hi(e){let t=ki(),n;try{n=An.readdirSync(t)}catch{return null}let r=`${e}.jsonl`;for(let s of n){let o=Nn.join(t,s,r);if(An.existsSync(o))return o}return null}function wi(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 Jt(e){return En(e).response}function En(e){let t=hi(e);if(!t)return{prompt:null,response:null};let n;try{n=An.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=wi(d.message?.content);u&&(d.type==="user"&&r===null&&(r=u),d.type==="assistant"&&(s=u))}return{prompt:r,response:s}}Je();V();import yi from"node:fs";import bi from"node:os";import Qr from"node:path";import{randomUUID as Si}from"node:crypto";var Ii=process.env.SUPERCLAWD_HOME||Qr.join(bi.homedir(),".superclawd"),xi=Qr.join(Ii,"config.json"),vi=process.env.SUPERCLAWD_MCP_API_URL||"https://mcp-api.superclawd.com",Hr=process.env.PIPELINES_BACKEND==="mock"||process.env.SUPERCLAWD_BACKEND==="mock",Yt=3,Cn="__logged_out__";function P(){return Hr}var nt={loggedIn:!1,userId:Cn,email:null};function ae(){return Jr()}function Jr(){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(yi.readFileSync(xi,"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 Xt=[];function At(){return Xt}function Ri(e){return e.map(t=>({id:t.slug,name:t.name,tier:t.tier==="paid"?"paid":"free"}))}function Kr(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 zt(e){return Ut(Cn),ke.loggedIn=!1,delete ke.account,j.length=0,Xt=[],nt={loggedIn:!1,userId:Cn,email:null,error:e},nt}async function zr(){if(Hr)return Ut(xt),ke.loggedIn=!0,Xt=[...j],nt={loggedIn:!0,userId:xt,email:ke.account?.email??null},nt;let e=Jr();if(!e)return zt("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(`${vi}/api/prompt/workspaces`,{headers:{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret,"x-request-id":Si()}});if(s=u.status,o=await u.json().catch(()=>null),u.ok){i=!0;break}if(s<500)return zt(Kr(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 zt(Kr(s));let c=o?.userId;return c?(Ut(c),ke.loggedIn=!0,ke.account={email:o?.email??"",org:"SuperClawd"},Xt=Ri(o?.workspaces??[]),j.length=0,nt={loggedIn:!0,userId:c,email:o?.email??null},nt):zt("The backend didn't return an account id. Update the CLI/backend.")}V();import{execFile as Ti}from"node:child_process";import{existsSync as Zt}from"node:fs";import{rm as _i}from"node:fs/promises";import{homedir as Ai}from"node:os";import{dirname as Ni,join as Vt,resolve as Xr}from"node:path";var Pn=Vt(Ai(),".superclawd","pipelines-worktrees");function Z(e,t){return new Promise(n=>{Ti("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 Yr(e){if(!e||!Zt(e))return!1;let t=await Z(e,["rev-parse","--is-inside-work-tree"]);return t.code===0&&t.stdout==="true"}async function Oe(e){if(!e||!Zt(e))return[];if(await Yr(e))return[{name:".",path:Xr(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=Vt(e,s.name);await Yr(o)&&r.push({name:s.name,path:Xr(o)})}return r}async function Vr(e,t){let n=await Oe(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 Zr(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 Dn(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 es(e){if(Zt(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 ts(e,t,n){let r=await Dn(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 ns(e,t){await Z(e,["branch","-D",t])}async function en(e){let t=Vt(Pn,e);if(!Zt(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=Vt(t,s.name),i=await Z(o,["rev-parse","--path-format=absolute","--git-common-dir"]);if(i.code===0&&i.stdout){let c=Ni(i.stdout);await Z(c,["worktree","remove","--force",o])}}await _i(t,{recursive:!0,force:!0}).catch(()=>{})}function Ei(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 rs(e,t,n){let r=await Z(e,["remote","get-url","origin"]);if(r.code!==0||!r.stdout)return null;let s=Ei(r.stdout);return s?`${s}/compare/${t}...${n}?expand=1`:null}import{spawn as $i,spawnSync as Li}from"node:child_process";import jn from"node:fs";import Mn from"node:os";import rt from"node:path";import{fileURLToPath as Gi}from"node:url";import{execFileSync as Ci}from"node:child_process";import{realpathSync as Pi}from"node:fs";function Di(){if(process.platform!=="darwin")return!1;try{return Ci("which",["sandbox-exec"],{stdio:"ignore"}),!0}catch{return!1}}function Oi(e){try{return Pi(e)}catch{return e}}function ji(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Mi(e){let t=["(version 1)","(allow default)"];for(let n of e)t.push(`(deny file-write* (subpath "${ji(Oi(n))}"))`);return t.push('(allow file-write* (regex #"/\\.git/"))'),t.push('(allow file-write* (regex #"/\\.claude/"))'),t.join(`
10
+ `)}function ss(e){let{cmd:t,args:n,repoPaths:r,enabled:s}=e;return!s||!r.length||!Di()?{cmd:t,args:n,sandboxed:!1}:{cmd:"sandbox-exec",args:["-p",Mi(r),t,...n],sandboxed:!0}}function Nt(e){if(!e||!e.trim())return process.cwd();let t=e.trim();return t==="~"?t=Mn.homedir():(t.startsWith("~/")||t.startsWith("~\\"))&&(t=rt.join(Mn.homedir(),t.slice(2))),rt.resolve(t)}function Ui(){return`http://127.0.0.1:${Number(process.env.PIPELINES_PORT||process.env.PIPELINES_MOCK_PORT||63210)}`}function Bi(){let e=process.env.SUPERCLAWD_BIN;if(e)return{cmd:e,baseArgs:[]};let t=rt.dirname(Gi(import.meta.url));for(let n=0;n<8;n++){let r=rt.join(t,"apps","cli","dist","index.js");if(jn.existsSync(r))return{cmd:process.execPath,baseArgs:[r]};let s=rt.dirname(t);if(s===t)break;t=s}return{cmd:"superclawd",baseArgs:[]}}function $n(e){let{cmd:t,baseArgs:n}=Bi(),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=Ui(),e.ticketId&&(s.SUPERCLAWD_PIPELINES_TICKET=e.ticketId));let o=Nt(e.workingDir);if(!jn.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=ss({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{jn.appendFileSync(rt.join(Mn.homedir(),".superclawd","pipelines-debug.log"),`${new Date().toISOString()} ${p}
11
+ `)}catch{}}let c=$i(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",y=>p({code:127,stdout:d,stderr:`${u}
12
+ ${String(y)}`})),c.on("close",y=>p({code:y??0,stdout:d,stderr:u}))}),g=c.pid??0;return{pid:g,pgid:g,done:m}}function os(e,t="SIGTERM"){if(e){if(process.platform==="win32"){try{Li("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 $n(e).done}var qi=["haiku","sonnet","opus","fable"],Fi=["low","medium","high","xhigh","max"],ce="opus",de="high",we=(e,t=ce)=>{let n=String(e??"").trim();return qi.includes(n)?n:t},ye=(e,t=de)=>{let n=String(e??"").trim();return Fi.includes(n)?n:t};function Wi(){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:Wi(),kind:t,text:n};return e.events.push(r),r}V();import{randomUUID as as}from"node:crypto";var Ki=1e4,is=3,Qi=1e3,Hi=new Set(["host","content-length","content-type","user-agent","x-superclawd-event","x-superclawd-signature","transfer-encoding","connection"]),Ji=e=>new Promise(t=>setTimeout(t,e));function cs(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=${Ar(l.webhookSecret,t)}`);for(let r of l.webhookHeaders??[])r.key&&!Hi.has(r.key.toLowerCase())&&(n[r.key]=r.value);return n}async function ds(e,t,n){let r=new AbortController,s=setTimeout(()=>r.abort(),Ki);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_${as()}`,event:e,occurredAt:new Date().toISOString(),workspaceId:n.workspaceId,data:t},i=JSON.stringify(o),c=cs(e,i);(async()=>{for(let d=1;d<=is;d++){let u=await ds(s,i,c);if(u>=200&&u<300)return;d<is&&await Ji(Qi*d)}})().catch(()=>{})}async function us(){let e=l.webhookUrl;if(!e)return{ok:!1,error:"no webhook URL configured"};let t={id:`evt_${as()}`,event:"webhook.test",occurredAt:new Date().toISOString(),data:{message:"SuperClawd Pipelines test event"}},n=JSON.stringify(t),r=cs("webhook.test",n),s=await ds(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 re(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 zi}from"node:crypto";var Xi=3,Yi=1,Vi=10,st=new Map,ot=[];function Zi(){let e=l.maxConcurrentRuns??Xi;return Math.max(Yi,Math.min(Vi,e))}function be(e,t=!1,n){st.has(e)||ot.some(r=>r.runId===e)||(ot.push({runId:e,resume:t,prompt:n}),ls())}function ls(){for(;st.size<Zi()&&ot.length>0;){let e=ot.shift();na(e.runId,e.resume,e.prompt)}}function ea(e,t,n){let s=[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}".`,"","Use the SuperClawd Pipelines tools for this task:","- 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.","- 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."];t.autonomy==="autonomous"&&s.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."),s.push("","Then do the work the ticket asks for.");let o=s.join(`
13
+ `),i=(n??"").trim();return i?`${o}
14
+
15
+ Additional instructions from the human:
16
+ ${i}`:o}async function ta(e){let t=e.worktrees??[];if(!t.length)return"";let n=[],r=!1;for(let o of t){let{behind:i}=await ts(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(`
17
+ `)}async function na(e,t,n){let r=I[e];if(!r)return;let s=k.find(y=>y.id===r.ticketId),o=n??(s?`${s.title}
18
+
19
+ ${s.description??""}`.trim():r.title),i=t?await ta(r)+o:ea(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 Oe(Nt(c))).map(y=>y.path):void 0,g=$n({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 M(e);let p=await g.done;st.delete(e),await ra(e,p.code,p.stdout,p.stderr,i),ls()}async function ra(e,t,n,r,s){let o=I[e];if(!o||o.status!=="running")return;let i;if(t===0)i=((o.sessionId?Jt(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
+
21
+ ${d}`:""}`}if(i&&(o.resultText=i.slice(0,5e4)),s||i){let d=k.find(m=>m.id===o.ticketId),u={id:`rr_${zi()}`,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 Wt(u)}let c=!!k.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"),re(o,"stopped",{stopReason:"completed",clearBlocker:!0,webhookEvent:"run.completed"}),!c){S[o.ticketId]="in_review";let u=k.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}`:""}`),re(o,"stopped",{stopReason:"error",webhookEvent:"run.failed"})}o.updatedAt=new Date().toISOString(),await M(e),await T(o.ticketId)}async function it(e){let t=st.get(e);t&&(os(t.pgid),st.delete(e));let n=ot.findIndex(r=>r.runId===e);n!==-1&&ot.splice(n,1)}async function ps(){let e=Object.values(I).filter(t=>t.status==="running");for(let t of e)je(t,"error","interrupted by daemon restart"),re(t,"stopped",{stopReason:"error"}),await M(t.id);e.length&&console.log(`[pipelines] reconciled ${e.length} interrupted run(s)`)}V();function Et(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 fs(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 ms(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 sa}from"node:crypto";var ne=class extends Error{constructor(n,r,s,o){super(s);this.status=n;this.code=r;this.extra=o;this.name="RunError"}},oa=e=>S[e]??"backlog";function nn(e){let t=I[e];if(!t)throw new ne(404,void 0,"run not found");return t}function Se(e){let t=x[e];return t?I[t]:void 0}async function Gn(e){let t=k.find(c=>c.id===e.ticketId);if(!t)throw new ne(404,void 0,"ticket not found");let n=w.find(c=>c.id===t.connectionId);if(!n||n.linkStatus!=="linked"||!n.workspaceId)throw new ne(409,void 0,"ticket connection is not linked to a workspace");let r=`run_${L.runSeq++}`,s=Re.find(c=>c.id===e.teamId),o=Te.find(c=>c.id===e.agentId),i={id:r,ticketId:t.id,ticketKey:t.externalIdentifier,title:t.title,provider:t.provider,workspaceId:n.workspaceId,workspaceName:n.workspaceName,assignmentKind:e.assignmentKind,teamName:s?.name,agentName:o?.name,autonomy:e.autonomy,status:"not_started",plan:[],events:[],createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return I[r]=i,x[t.id]=r,await M(r),i}async function rn(e,t={}){let n=Se(e);return n||Gn({ticketId:e,assignmentKind:"anyone",autonomy:t.autonomy??l.defaultAutonomy})}async function at(e,t={}){let n=nn(e);if(n.status==="not_started"){let i=k.find(d=>d.id===n.ticketId),c=i?Et(i,d=>k.find(u=>u.id===d),oa):[];if(c.length)throw new ne(409,"unmet_dependencies","blocked by dependencies",{unmet:c})}let r=(t.details??"").trim(),s=t.attachments??[],o=r+(s.length?`
22
+
23
+ Attached files (read these):
24
+ ${s.map(i=>`- ${i}`).join(`
25
+ `)}`:"");return n.sessionId||(n.sessionId=sa()),re(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 M(n.id),await T(n.ticketId),P()||be(n.id,!1,o||void 0),n}async function ct(e){let t=nn(e);return re(t,"paused",{event:{kind:"state_change",text:"paused by user"},webhookEvent:"run.paused"}),await it(t.id),await M(t.id),t}async function dt(e){let t=nn(e);return re(t,"running",{event:{kind:"state_change",text:"resumed (continue)"},webhookEvent:"run.resumed"}),S[t.ticketId]="in_progress",await M(t.id),await T(t.ticketId),P()||be(t.id,!0),t}async function ut(e){let t=nn(e);return re(t,"stopped",{stopReason:"user",clearBlocker:!0,event:{kind:"state_change",text:"stopped by user"},webhookEvent:"run.stopped"}),await it(t.id),await M(t.id),t}V();import{randomUUID as hs}from"node:crypto";var A=class extends Error{constructor(n,r,s){super(r);this.status=n;this.extra=s;this.name="TicketError"}},ia=["backlog","in_progress","needs_input","in_review","done"],ks=e=>S[e]??"backlog",Bn=e=>w.find(t=>t.id===e.connectionId)?.workspaceId??void 0;function Ct(e){let t=k.find(n=>n.id===e);if(!t)throw new A(404,"ticket not found");return t}function sn(e){return k.find(t=>t.id===e)}function lt(e){return C.filter(t=>t.ticketId===e).slice().reverse()}function pt(e){return E.filter(t=>t.ticketId===e)}async function ft(e,t){let n=Ct(e);if(!ia.includes(t))throw new A(400,"invalid column");if(n.blockedReason&&t!==ks(n.id))throw new A(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 A(409,"a task can only enter Done once its session is stopped")}let r=ks(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:Bn(n)}),{ticketId:n.id,column:t}}async function Ie(e,t){let n=Ct(e),r=[],s=null;if(typeof t.workingDir=="string"&&(n.workingDir=t.workingDir.trim()||void 0),t.model!==void 0&&(n.model=we(t.model,n.model||ce)),t.effort!==void 0&&(n.effort=ye(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=E.filter(m=>m.ticketId===n.id&&!m.resolved).length;if(u>0)throw new A(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=Bn(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=Ct(e);if(!n.blockedReason)throw new A(409,"ticket is not blocked");let r=E.filter(d=>d.ticketId===n.id&&!d.resolved).length;if(r>0)throw new A(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=Bn(n);return ue("ticket.unblocked",{ticketId:n.id,ticketKey:n.externalIdentifier},{workspaceId:c}),i&&o?(re(o,"running",{stopReason:null,clearBlocker:!0,event:{kind:"state_change",text:"unblocked & resumed"},webhookEvent:"run.resumed"}),S[n.id]="in_progress",await M(o.id),await T(n.id),P()||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=w.find(u=>u.id===e);if(!n)throw new A(404,"board not found");if(n.provider!=="local")throw new A(400,"tickets can only be created on the Local board");let r=String(t.title??"").trim();if(!r)throw new A(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:we(t.model??l.defaultModel),effort:ye(t.effort??l.defaultEffort),description:String(t.description??"").trim()||void 0,createdAt:c,updatedAt:c};return k.push(d),S[d.id]="backlog",n.ticketCount+=1,await T(d.id),await R(n),d}async function kt(e,t){Ct(e);let n=String(t.body??"").trim();if(!n)throw new A(400,"empty note");let r=t.author==="assistant"?"assistant":"user",s=new Date().toISOString(),o={id:`note_${hs()}`,ticketId:e,author:r,body:n.slice(0,5e3),createdAt:s,updatedAt:s};return C.push(o),await et(o),o}async function ht(e,t){let n=C.find(s=>s.id===e);if(!n)throw new A(404,"note not found");let r=String(t??"").trim();if(!r)throw new A(400,"empty note");return n.body=r.slice(0,5e3),n.updatedAt=new Date().toISOString(),await et(n),n}async function wt(e){let t=C.findIndex(n=>n.id===e);if(t===-1)throw new A(404,"note not found");C.splice(t,1),await Kt(e)}async function yt(e,t){Ct(e);let n=String(t??"").trim();if(!n)throw new A(400,"empty question");let r=new Date().toISOString(),s=E.filter(i=>i.ticketId===e).length,o={id:`oq_${hs()}`,ticketId:e,question:n.slice(0,5e3),answer:void 0,resolved:!1,position:s,createdAt:r,updatedAt:r};return E.push(o),await _n(o.id),o}async function bt(e,t){let n=E.find(r=>r.id===e);if(n===void 0)throw new A(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 _n(n.id),n}async function St(e){let t=E.findIndex(n=>n.id===e);if(t===-1)throw new A(404,"question not found");E.splice(t,1),await Ht(e),await Br()}V();V();import ys from"express";import ca from"cors";import{createRequire as da}from"node:module";import{dirname as bs,join as Fn}from"node:path";import{existsSync as ua}from"node:fs";var on=["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}`}),D=e=>({description:e,content:{"application/json":{schema:v("Error")}}});function aa(){let e={};for(let t of on)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 ws={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:D("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:D("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:D("Not a local board, or title missing"),404:D("Board not found")}}},"/v1/tickets/{id}":{get:{tags:["Tickets"],summary:"Get a ticket",security:U,parameters:[K],responses:{200:F(v("Ticket"),"Ticket"),404:D("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:D("Ticket not found"),409:D("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:D("Invalid column"),404:D("Ticket not found"),409:D("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:D("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:D("Empty note"),404:D("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:D("Note not found")}},delete:{tags:["Notes"],summary:"Delete a note",security:U,parameters:[K],responses:{200:F(v("Ok"),"Deleted"),404:D("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:D("Empty question"),404:D("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:D("Question not found")}},delete:{tags:["Questions"],summary:"Delete a question",security:U,parameters:[K],responses:{200:F(v("Ok"),"Deleted"),404:D("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:D("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:D("Unknown action"),404:D("No run for this ticket"),409:D("Unmet dependencies (on first start)")}}}},webhooks:aa(),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}}},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 la(){let e="dist/browser/standalone.js",t=bs(da(import.meta.url).resolve("@scalar/api-reference"));for(let n=0;n<6;n++){if(ua(Fn(t,e)))return Fn(t,e);t=bs(t)}return Fn(t,e)}var pa=la(),fa=`<!doctype html>
26
+ <html>
27
+ <head>
28
+ <meta charset="utf-8" />
29
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
30
+ <title>SuperClawd Pipelines \u2014 API reference</title>
31
+ </head>
32
+ <body>
33
+ <script id="api-reference" data-url="/openapi.json"></script>
34
+ <script src="/docs/scalar.js"></script>
35
+ <script>
36
+ // Strip Scalar's built-in cloud features ("Ask AI", "Generate MCP") \u2014 both upload the spec to
37
+ // Scalar's servers, which we don't want on a self-hosted, offline reference. No config flag
38
+ // exists in this version, so hide by button text (re-applied on re-render; pierces shadow DOM).
39
+ (function () {
40
+ var KILL = ["ask ai", "generate mcp"];
41
+ function sweep(root) {
42
+ if (!root || !root.querySelectorAll) return;
43
+ root.querySelectorAll('button, a, [role="button"]').forEach(function (el) {
44
+ if (el.dataset && el.dataset.scHidden) return;
45
+ var t = (el.textContent || "").replace(/\\s+/g, " ").trim().toLowerCase();
46
+ if (KILL.some(function (k) { return t === k || t.indexOf(k) === 0; })) {
47
+ if (el.dataset) el.dataset.scHidden = "1";
48
+ el.style.display = "none";
49
+ }
50
+ });
51
+ root.querySelectorAll("*").forEach(function (el) {
52
+ if (el.shadowRoot) sweep(el.shadowRoot);
53
+ });
54
+ }
55
+ var run = function () { sweep(document); };
56
+ new MutationObserver(run).observe(document.documentElement, { childList: true, subtree: true });
57
+ run();
58
+ setTimeout(run, 500);
59
+ setTimeout(run, 1500);
60
+ })();
61
+ </script>
62
+ </body>
63
+ </html>`,Ss=e=>S[e]??"backlog";function ma(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 se(e,t){return t instanceof ne?e.status(t.status).json({error:t.message,...t.code?{code:t.code}:{},...t.extra??{}}):t instanceof A?e.status(t.status).json({error:t.message,...t.extra??{}}):(console.error("[public-api]",t),e.status(500).json({error:"internal error"}))}function ga(e){let t=sn(e);return t?{...t,column:Ss(t.id)}:null}function ka(){let e=ys();return e.use(ca()),e.use(ys.json()),e.get("/openapi.json",(t,n)=>n.json(ws)),e.get("/docs/scalar.js",(t,n)=>n.sendFile(pa)),e.get("/docs",(t,n)=>n.type("html").send(fa)),e.use("/v1",ma),e.get("/v1/boards",(t,n)=>{n.json(w.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=k.filter(s=>s.connectionId===t.params.id).map(s=>({...s,column:Ss(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 se(n,r)}}),e.get("/v1/tickets/:id",(t,n)=>{let r=ga(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 se(n,r)}}),e.patch("/v1/tickets/:id",async(t,n)=>{try{return n.json(await Ie(t.params.id,t.body??{}))}catch(r){return se(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 se(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 kt(t.params.id,{body:String(t.body?.body??""),author:t.body?.author});return n.status(201).json(r)}catch(r){return se(n,r)}}),e.patch("/v1/notes/:id",async(t,n)=>{try{return n.json(await ht(t.params.id,String(t.body?.body??"")))}catch(r){return se(n,r)}}),e.delete("/v1/notes/:id",async(t,n)=>{try{return await wt(t.params.id),n.json({ok:!0})}catch(r){return se(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 yt(t.params.id,String(t.body?.question??""));return n.status(201).json(r)}catch(r){return se(n,r)}}),e.patch("/v1/questions/:id",async(t,n)=>{try{return n.json(await bt(t.params.id,t.body??{}))}catch(r){return se(n,r)}}),e.delete("/v1/questions/:id",async(t,n)=>{try{return await St(t.params.id),n.json({ok:!0})}catch(r){return se(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 rn(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 se(n,s)}}),e}var Pt=null;function Is(){return Pt!==null}function an(e){if(Pt)return;Pt=ka().listen(e,()=>{console.log(`[pipelines] public API ready http://localhost:${e}/v1`)})}async function xs(){let e=Pt;e&&(Pt=null,await new Promise(t=>e.close(()=>t())),console.log("[pipelines] public API stopped"))}var cn=Number(process.env.PIPELINES_PUBLIC_API_PORT||63211),vs=4,ha=/^[a-zA-Z0-9-]+$/,wa=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:cn,running:Is(),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 Rs(e){return l.publicApiEnabled=e,await X(),e?an(cn):await xs(),Dt()}async function Ts(){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 _s(){return l.apiKeyHash=void 0,l.apiKeyLast4=void 0,l.apiKeyCreatedAt=void 0,await X(),Dt()}async function As(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>vs)throw new xe(400,`at most ${vs} custom headers`);for(let r of n){if(!ha.test(r.key)||r.key.length>64)throw new xe(400,`invalid header name: ${r.key}`);if(wa.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(on);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 Ns(){let e=Ze("whsec_",32);return l.webhookSecret=e,await X(),{secret:e}}async function Es(){return us()}V();import Kn from"node:fs";import ba from"node:os";import Ps from"node:path";import{McpServer as Sa}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Ia}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as b}from"zod";var Ds=process.env.SUPERCLAWD_HOME||Ps.join(ba.homedir(),".superclawd"),Os=Ps.join(Ds,"pipelines-mcp.json"),dn=null;function js(){if(dn)return dn;try{let e=JSON.parse(Kn.readFileSync(Os,"utf8"));if(typeof e?.token=="string"&&e.token)return dn=e.token}catch{}return dn=Ze("scpmcp_")}function xa(e){Kn.mkdirSync(Ds,{recursive:!0}),Kn.writeFileSync(Os,JSON.stringify({port:e,token:js()}),{mode:384})}var Cs=e=>S[e]??"backlog";function Wn(e,t,n){let s=/^Bearer\s+(.+)$/i.exec(e.headers.authorization??"")?.[1]?.trim();if(s){if(Rt(s,js()))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 O=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 ne||e instanceof A?Be(e.message):(console.error("[pipelines-mcp]",e),Be("internal error"))}function va(){let e=new Sa({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()=>O(w.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})=>O(k.filter(n=>n.connectionId===t).map(n=>({...n,column:Cs(n.id)})))),e.tool("get_ticket","Get a single ticket (full fields + its current board column).",{ticketId:b.string()},async({ticketId:t})=>{let n=sn(t);return n?O({...n,column:Cs(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 O(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 O(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 O(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 O(await kt(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})=>O(lt(t))),e.tool("edit_note","Edit a note's body.",{noteId:b.string(),body:b.string()},async({noteId:t,body:n})=>{try{return O(await ht(t,n))}catch(r){return W(r)}}),e.tool("delete_note","Delete a note.",{noteId:b.string()},async({noteId:t})=>{try{return await wt(t),O({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 O(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 O(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 O(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 O(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 O(await yt(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})=>O(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 O(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),O({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 rn(t,r?{autonomy:r}:{});return O(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 O(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 O(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 O(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?O(n):Be("no run for this ticket")}),e}function Ms(e,t){xa(t),e.post("/mcp",Wn,async(r,s)=>{let o=va(),i=new Ia({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",Wn,n),e.delete("/mcp",Wn,n),console.log("[pipelines] MCP endpoint ready at /mcp")}V();import{randomUUID as Na}from"node:crypto";import{homedir as Ra}from"node:os";var un=["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(`
64
+ `);async function ln(e){if(!e)return[];let t=Nt(e);return t===Ra()?[]:(await Oe(t)).map(n=>n.path)}var _a={min:6e4,minute:6e4,minutes:6e4,hour:36e5,hours:36e5,hr:36e5,hrs:36e5,day:864e5,days:864e5,week:6048e5,weeks:6048e5};function Aa(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=_a[n[2]];if(s&&r>0)return Math.max(6e4,r*s)}return 36e5}function Ot(e,t){return new Date(e+Aa(t)).toISOString()}var Ea=3e4,pn=new Set,Qn=null;async function Hn(e,t=!0){let n=N[e];if(!n||pn.has(e))return null;pn.add(e);let r=++L.schedRunSeq,s={id:`srun_${r}`,scheduleId:e,status:"running",sessionId:Na(),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=Ot(Date.now(),n.cadence)),await Ft(s,r),await _t(e),ue("schedule.run.started",{scheduleId:e,scheduleRunId:s.id,scheduleName:n.name,status:s.status},{workspaceId:n.workspaceId}),Ca(n,s,r),s}async function Ca(e,t,n){try{if(P())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:`${un}
65
+
66
+ ${e.prompt}`,workspace:e.workspaceId,workingDir:r,model:t.model,effort:t.effort,sessionId:t.sessionId,pipelinesTools:!0,pipelinesToolsMode:"restricted",sandbox:!0,sandboxRepos:await ln(r)}),o=s.code===0?Jt(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 Ft(t,n),pn.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 Pa(){let e=Date.now(),t=l.connectedWorkspaces,n=Object.values(N).filter(r=>r.enabled&&r.nextRunAt&&Date.parse(r.nextRunAt)<=e&&!pn.has(r.id)&&(!t||t.includes(r.workspaceId)));for(let r of n)Hn(r.id,!0)}function $s(){Qn||(Qn=setInterval(()=>void Pa(),Ea),Qn.unref?.())}async function Ls(){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 Ft(n,Number(n.id.replace(/^srun_/,""))||0),e++);e&&console.log(`[pipelines] reconciled ${e} interrupted schedule run(s)`)}async function fn(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 Da(e){return new Promise(t=>setTimeout(t,e))}async function oe(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 Da(s),fetch(e,t)}var Oa="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 Jn(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 Gs(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.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 Us=`id identifier title description url priority createdAt updatedAt dueDate
67
+ state { name type } assignee { name avatarUrl } creator { name avatarUrl } project { name }
68
+ parent { identifier title }
69
+ labels { nodes { name color } }`,Ma=`query Issues($filter: IssueFilter, $after: String) {
70
+ issues(first: 100, filter: $filter, after: $after) {
71
+ nodes { ${Us} }
72
+ pageInfo { hasNextPage endCursor }
73
+ } }`,$a=`query IssuesById($ids: [ID!]) {
74
+ issues(first: 250, filter: { id: { in: $ids } }) { nodes { ${Us} } } }`;function La(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 Bs(e,t,n){let r=await oe(Oa,{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 qs(e,t){let n=La(t),r=[],s;for(let o=0;o<5;o++){let{nodes:i,pageInfo:c}=await Bs(e,Ma,{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 Fs(e,t){return t.length?(await Bs(e,$a,{ids:t})).nodes:[]}var Ba=e=>`https://api.atlassian.com/ex/jira/${e}/rest/api/3`;function qa(e){switch(e){case"new":return"todo";case"indeterminate":return"in_progress";case"done":return"done";default:return"todo"}}function Fa(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 Wa(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(`
75
+ `);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(`
76
+ `)};return n(e),t.join("").replace(/\n{3,}/g,`
77
+
78
+ `).trim()||void 0}function Xn(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:Wa(s.description),status:qa(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:Fa(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 Ka=["summary","description","status","assignee","reporter","duedate","priority","labels","project","parent","created","updated"];function zn(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Qa(e){let t=["statusCategory != Done"],n=(e?.labels??[]).map(r=>r.trim()).filter(Boolean);return n.length&&t.push(`labels in (${n.map(r=>`"${zn(r)}"`).join(", ")})`),e?.assignedToMe?t.push("assignee = currentUser()"):e?.assignee?.trim()&&t.push(`assignee = "${zn(e.assignee.trim())}"`),`${t.join(" AND ")} ORDER BY updated DESC`}async function Ws(e,t,n,r,s=!1){let o=[],i,c=s?5:1;for(let d=0;d<c;d++){let u=await oe(`${Ba(e)}/search/jql`,{method:"POST",headers:{"content-type":"application/json",accept:"application/json",authorization:`Bearer ${t}`},body:JSON.stringify({jql:n,fields:Ka,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 Ks(e,t,n){return Ws(e,t,Qa(n),100,!0)}function Qs(e,t,n){if(!n.length)return Promise.resolve([]);let r=n.map(s=>`"${zn(s)}"`).join(", ");return Ws(e,t,`id in (${r})`,250)}var Hs="https://app.asana.com/api/1.0",Js=["name","notes","completed","assignee.name","due_on","tags.name","projects.name","parent.name","parent.gid","created_at","modified_at","permalink_url"].join(",");function Ja(e){return e?"done":"todo"}function Yn(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:Ja(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(`
79
+ `)||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 zs(e,t){let n=await oe(`${Hs}${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 za(e,t){let n=await oe(`${Hs}${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 Xa(e,t){let n=t?.assignee?.trim()||"me";return new URLSearchParams({workspace:e,assignee:n,completed_since:"now",limit:"100",opt_fields:Js}).toString()}async function Xs(e,t,n){let r=Xa(e,n),s=[],o;for(let i=0;i<5;i++){let{data:c,nextOffset:d}=await za(`/tasks?${r}${o?`&offset=${o}`:""}`,t);if(s.push(...c),!d)return s;o=d}return pe("Asana",s.length),s}async function Ys(e,t){return t.length?(await fn(t,5,r=>zs(`/tasks/${r}?opt_fields=${Js}`,e).catch(()=>null))).filter(r=>!!r):[]}async function Vs(e){try{let t=await zs("/workspaces?opt_fields=name",e);return Array.isArray(t)?t:[]}catch{return[]}}var Va="https://api.clickup.com/api/v2";function Za(e){switch((e??"").toLowerCase()){case"done":case"closed":return"done";case"open":return"todo";default:return"in_progress"}}function ec(e){return(e??"").replace(/\b\w/g,t=>t.toUpperCase())}function tc(e){switch((e??"").toLowerCase()){case"urgent":return 1;case"high":return 2;case"normal":return 3;case"low":return 4;default:return}}function Vn(e){if(e==null||e==="")return;let t=Number(e);return Number.isFinite(t)?new Date(t).toISOString():void 0}function nc(e){return Vn(e)?.slice(0,10)}function Zn(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:Za(e.status?.type),statusRaw:ec(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:nc(e.due_date),priority:tc(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:Vn(e.date_created),updatedAt:Vn(e.date_updated)}}async function er(e,t){let n=await oe(`${Va}${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 rc(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 Zs(e,t,n){let r=rc(n),s=[];for(let o=0;o<5;o++){let i=await er(`/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 eo(e,t){return t.length?(await fn(t,5,r=>er(`/task/${r}`,e).catch(()=>null))).filter(r=>!!r):[]}async function to(e){try{return(await er("/team",e)).teams??[]}catch{return[]}}var oc="https://api.monday.com/v2";function ic(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 tr(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:ic(i?.text??void 0),statusRaw:i?.text?.trim()||e.group?.title||"",assignee:c.length?{name:c.join(`
80
+ `)}: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 no=`
81
+ id
82
+ name
83
+ created_at
84
+ updated_at
85
+ group { title }
86
+ board { id name }
87
+ column_values { id type text column { title } }
88
+ `;async function nr(e,t){let n=await oe(oc,{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 ro(e,t){let r=(await nr(`query { boards (limit: 50) { id name items_page (limit: 100) { cursor items { ${no} } } } }`,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 so(e,t){if(!t.length)return[];let n=t.map(s=>JSON.stringify(s)).join(", ");return(await nr(`query { items (ids: [${n}]) { ${no} } }`,e)).items??[]}async function oo(e){try{return(await nr(`
89
+ query {
90
+ me {
91
+ account {
92
+ name
93
+ slug
94
+ }
95
+ }
96
+ }
97
+ `,e)).me?.account??null}catch{return null}}var rr=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function sr(){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=sr();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${rr}/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 ao(e){let t=sr();if(!t)return null;try{let n=await fetch(`${rr}/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 co(e){let t=sr();if(!t)return null;try{let n=await fetch(`${rr}/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 or=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com",cc="https://api.atlassian.com/oauth/token/accessible-resources";function ir(){let e=ae();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function uo(e,t){let n=ir();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${or}/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 lo(e){let t=ir();if(!t)return null;try{let n=await fetch(`${or}/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 po(e){let t=ir();if(!t)return null;try{let n=await fetch(`${or}/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 fo(e){try{let t=await fetch(cc,{headers:{authorization:`Bearer ${e}`,accept:"application/json"}});if(!t.ok)return[];let n=await t.json();return Array.isArray(n)?n:[]}catch{return[]}}var ar=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function cr(){let e=ae();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function mo(e,t){let n=cr();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${ar}/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 go(e){let t=cr();if(!t)return null;try{let n=await fetch(`${ar}/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 ko(e){let t=cr();if(!t)return null;try{let n=await fetch(`${ar}/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 ho=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function wo(){let e=ae();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function yo(e,t){let n=wo();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${ho}/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 bo(e){let t=wo();if(!t)return null;try{let n=await fetch(`${ho}/api/oauth/clickup/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}function So(){return Promise.resolve(null)}var Io=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com";function xo(){let e=ae();return e?{"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret}:null}async function vo(e,t){let n=xo();if(!n)return{error:"Not authenticated. Run `superclawd login`."};try{let r=await fetch(`${Io}/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 Ro(e){let t=xo();if(!t)return null;try{let n=await fetch(`${Io}/api/oauth/monday/claim`,{method:"POST",headers:t,body:JSON.stringify({code:e})});return n.ok?await n.json():null}catch{return null}}function To(){return Promise.resolve(null)}var dc={idPrefix:"lin_",async fetchDiscovery(e,t,n){return(await qs(t,n)).map(r=>Jn(r,e.id,e.workspaceId))},async fetchByIds(e,t,n){return(await Fs(t,n)).map(r=>Jn(r,e.id,e.workspaceId))},refresh:co};function _o(e){if(!e.cloudId)throw Object.assign(new Error("Jira connection has no cloudId (reconnect)"),{terminal:!0});return e.cloudId}var uc={idPrefix:"jira_",async fetchDiscovery(e,t,n){let r=e.providerAccountName??"";return(await Ks(_o(e),t,n)).map(s=>Xn(s,e.id,e.workspaceId,r))},async fetchByIds(e,t,n){let r=e.providerAccountName??"";return(await Qs(_o(e),t,n)).map(s=>Xn(s,e.id,e.workspaceId,r))},refresh:po};function Ao(e,t){if(!e.providerAccountId)throw Object.assign(new Error(`${t} connection has no account scope (reconnect)`),{terminal:!0});return e.providerAccountId}var lc={idPrefix:"asana_",async fetchDiscovery(e,t,n){return(await Xs(Ao(e,"Asana"),t,n)).map(r=>Yn(r,e.id,e.workspaceId))},async fetchByIds(e,t,n){return(await Ys(t,n)).map(r=>Yn(r,e.id,e.workspaceId))},refresh:ko},pc={idPrefix:"clickup_",async fetchDiscovery(e,t,n){return(await Zs(Ao(e,"ClickUp"),t,n)).map(r=>Zn(r,e.id,e.workspaceId))},async fetchByIds(e,t,n){return(await eo(t,n)).map(r=>Zn(r,e.id,e.workspaceId))},refresh:So},fc={idPrefix:"monday_",async fetchDiscovery(e,t,n){return(await ro(t,n)).map(r=>tr(r,e.providerAccountId,e.id,e.workspaceId))},async fetchByIds(e,t,n){return(await so(t,n)).map(r=>tr(r,e.providerAccountId,e.id,e.workspaceId))},refresh:To},mc={linear:dc,jira:uc,asana:lc,clickup:pc,monday:fc};function jt(e){return mc[e]??null}Je();async function Fe(e){await ze.upsert({connectionId:e.connectionId,userId:_(),provider:e.provider,accessToken:Xe(e.accessToken),refreshToken:e.refreshToken?Xe(e.refreshToken):null,scope:e.scope??null,expiresAt:e.expiresAt??null})}async function mn(e){let t=await ze.findByPk(e);if(!t)return null;let n=t.get({plain:!0});if(n.userId!==_())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 No(e){await ze.destroy({where:{connectionId:e,userId:_()}})}async function dr(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 Eo(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)?dr(e,n,t):n.accessToken}function wc(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 yc(e){if(e.isMock())return;let t=wc(e.listConnections(),e.connectedWorkspaces());for(let n of t)try{await e.syncOne(n)}catch{}}var ur=null;function Co(e,t=6e5){ur||(ur=setInterval(()=>void yc(e),t),ur.unref?.())}import{execFile as Sc}from"node:child_process";function gn(e){return new Promise(t=>{Sc("gh",e,{maxBuffer:10*1024*1024},(n,r)=>{t({code:n&&typeof n.code=="number"?n.code:n?1:0,stdout:String(r??"")})})})}var Ic=new Set(["FAILURE","CANCELLED","TIMED_OUT","ACTION_REQUIRED","STARTUP_FAILURE","STALE"]),xc=new Set(["FAILURE","ERROR"]),Po=new Set(["QUEUED","IN_PROGRESS","WAITING","PENDING","REQUESTED"]);function vc(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&&Ic.has(r.conclusion)||r.state&&xc.has(r.state),i=r.status&&Po.has(r.status)||r.state&&Po.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 Rc(e){let t=await gn(["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}=vc(n.statusCheckRollup??[]);return{state:r,ci:s,failingChecks:o}}function Do(e){let t=/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/.exec(e);return t?{owner:t[1],repo:t[2],num:Number(t[3])}:null}function Oo(e){let t=Do(e);return t?`${t.repo}#${t.num}`:e}function Tc(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=Oo(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 jo(e){let t=await Promise.all(e.map(async n=>({url:n,status:await Rc(n)})));return Tc(t)}async function _c(e){let t=Do(e);if(!t)return{count:0,digest:[]};let r=await gn(["api","graphql","-f",`query=query($owner:String!,$repo:String!,$num:Int!){
98
+ repository(owner:$owner,name:$repo){ pullRequest(number:$num){
99
+ reviewThreads(first:100){ nodes {
100
+ isResolved isOutdated
101
+ comments(first:1){ nodes { body path line author { login } } }
102
+ } } } } }`,"-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(`
103
+ `)[0].slice(0,160)}`)}return{count:o.length,digest:o}}catch{return{count:0,digest:[]}}}async function Mo(e){let t=await Promise.all(e.map(async r=>({tag:Oo(r),c:await _c(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 $o="<!-- superclawd:related -->",Lo="<!-- /superclawd:related -->";function Ac(e,t,n){let r=t.filter(s=>s!==n);return r.length?[$o,`**Ticket:** ${e}`,"","**Related PRs (same ticket):**",...r.map(s=>`- ${s}`),Lo].join(`
104
+ `):""}function Nc(e,t){let n=o=>o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`\\n*${n($o)}[\\s\\S]*?${n(Lo)}`),s=e.replace(r,"").trimEnd();return t?(s?s+`
105
+
106
+ `:"")+t:s}async function Go(e,t){if(!(t.length<2))for(let n of t){let r=await gn(["pr","view",n,"--json","body"]);if(r.code!==0)continue;let s="";try{s=JSON.parse(r.stdout)?.body??""}catch{continue}let o=Nc(s,Ac(e,t,n));o!==s&&await gn(["pr","edit",n,"--body",o])}}function Cc(e){return Math.max(1,e.prMonitorIntervalMinutes??30)*6e4}function Mt(e){return e.prMonitorMaxEngagements??5}function Uo(e,t,n){return e.prMonitorLastAt?n-Date.parse(e.prMonitorLastAt)>=Cc(t):!0}function Bo(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)>=Mt(t);return n.ci==="failing"?s?{kind:"disarm",note:`Monitor reached its ${Mt(t)}-engagement cap with CI still failing \u2014 needs a human.`}:{kind:"engage",reason:"ci",prompt:Pc(e,n)}:n.ci==="passing"?t.prMonitorReplyToComments&&(r?.count??0)>0?s?{kind:"disarm",note:`Monitor reached its ${Mt(t)}-engagement cap with review comments still open \u2014 needs a human.`}:{kind:"engage",reason:"comments",prompt:Dc(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 qo(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:
107
+ ${t.map(n=>`- ${n}`).join(`
108
+ `)}`}function Pc(e,t){let n=qo(e),r=t.failingChecks.length?t.failingChecks.join(", "):"one or more checks";return[`This is an automated PR-monitor pass for ${n}
109
+
110
+ 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(`
111
+
112
+ `)}function Dc(e,t){let n=qo(e),r=t.digest.map(s=>`- ${s}`).join(`
113
+ `);return[`This is an automated PR-monitor pass for ${n}
114
+
115
+ 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(`
116
+
117
+ `)}var It=3,f=hn();f.use(jc());f.use(hn.json());var $t=Number(process.env.PIPELINES_PORT||process.env.PIPELINES_MOCK_PORT||63210),gr=Number(process.env.PIPELINES_PUBLIC_PORT||$t),$c=e=>new Promise(t=>setTimeout(t,e)),fe=e=>S[e]??"backlog";function Lt(e,t){return t instanceof ne?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 A?e.status(t.status).json({error:t.message,...t.extra??{}}):(console.error(t),e.status(500).json({error:"internal error"}))}var Ko=()=>new Set(l.connectedWorkspaces??[]),wn=e=>l.workspaceDirs?.[e]??"~";function yn(){let e=Ko();j.length=0,j.push(...At().filter(t=>e.has(t.id)))}async function Lc(){let e=At();if(P()){l.connectedWorkspaces=e.map(r=>r.id);return}if(!Array.isArray(l.connectedWorkspaces)){let r=[...new Set(w.filter(s=>s.workspaceId).map(s=>s.workspaceId))].filter(s=>e.some(o=>o.id===s)).slice(0,Yt);l.connectedWorkspaces=r,await X()}yn();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 Bt()}f.get("/api/session",(e,t)=>t.json(ke));f.get("/api/workspaces",(e,t)=>t.json(j));f.get("/api/teams",(e,t)=>t.json(Re));f.get("/api/agents",(e,t)=>t.json(Te));f.get("/api/workspaces/available",(e,t)=>{let n=Ko();t.json(At().map(r=>({...r,connected:n.has(r.id),workingDir:wn(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>=Yt)return t.status(409).json({error:`You can connect at most ${Yt} workspaces.`});l.connectedWorkspaces=[...r,n.id]}return l.workspaceDirs?.[n.id]||(l.workspaceDirs={...l.workspaceDirs??{},[n.id]:"~"}),await X(),yn(),P()||await Bt(),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(),yn()),t.json({id:n,connected:!1})});f.get("/api/database/export",(e,t)=>{let n=w.map(r=>({...r,ticketCount:k.filter(s=>s.connectionId===r.id).length}));t.json({version:2,workspaces:j,teams:Re,agents:Te,connections:n,tickets:k,settings:l,schedules:N,scheduleOrder:H,scheduleRuns:B,searchable:J,notes:C,openQuestions:E,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(w,n.connections);for(let o of w)o.provider!=="local"&&(o.authStatus="expired");r(k,n.tickets),r(J,n.searchable),r(C,n.notes),r(E,n.openQuestions),r(G,n.messagePresets),r(H,n.scheduleOrder),s(N,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($))delete $[o];return q.length=0,ee.length=0,await Fr(),t.json({ok:!0})});f.post("/api/database/reset",async(e,t)=>(await Wr(),yn(),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||kn.homedir();s==="~"?s=kn.homedir():s.startsWith("~/")&&(s=Q.join(kn.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:kn.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(w));function kr(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 Qo={linear:"Linear",jira:"Jira",asana:"Asana",clickup:"ClickUp",monday:"Monday"},Gc=new Set(Object.keys(Qo));function Ho(e,t,n){return e==="jira"?uo(t,n):e==="asana"?mo(t,n):e==="clickup"?yo(t,n):e==="monday"?vo(t,n):io(t,n)}f.post("/api/connections",async(e,t)=>{let n=String(e.body?.provider??"");if(!Gc.has(n))return t.status(400).json({error:"unsupported provider"});let r=Qo[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&&w.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:P()?`${r} (demo)`:r,...s?{displayName:s}:{},workspaceId:i?.id??null,workspaceName:i?.name??null,workingDir:o||null,linkStatus:i?"linked":"unlinked",authStatus:P()?"connected":"needs_refresh",lastSyncedAt:null,ticketCount:0,syncFilters:kr(e.body?.syncFilters)};if(P())return w.push(d),await R(d),t.status(201).json({connection:d,mock:!0});let u=await Ho(n,d.id,gr);return u.url?(w.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=w.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?w.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=kr(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=w.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&&w.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=kr(e.body.syncFilters)),await R(n),t.json(n)});f.delete("/api/connections/:id",async(e,t)=>{let n=w.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 k.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 qt(s.id)}for(let s=k.length-1;s>=0;s--)k[s].connectionId===n.id&&k.splice(s,1);for(let s=J.length-1;s>=0;s--)J[s].connectionId===n.id&&J.splice(s,1);let r=w.findIndex(s=>s.id===n.id);return r!==-1&&w.splice(r,1),await Cr(n.id),await No(n.id),t.status(204).end()});f.post("/api/connections/:id/oauth/start",async(e,t)=>{let n=w.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});if(!jt(n.provider))return t.status(400).json({error:"not a vendor connection"});let r=await Ho(n.provider,n.id,gr);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=w.find(i=>i.id===r);if(!n||!s)return t.redirect("/settings/connections?linear=error");let o=await ao(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=w.find(u=>u.id===r);if(!n||!s)return t.redirect("/settings/connections?jira=error");let o=await lo(n);if(!o)return s.authStatus="error",await R(s),t.redirect("/settings/connections?jira=error");let c=(await fo(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=w.find(d=>d.id===r);if(!n||!s)return t.redirect("/settings/connections?asana=error");let o=await go(n);if(!o)return s.authStatus="error",await R(s),t.redirect("/settings/connections?asana=error");let c=(await Vs(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=w.find(d=>d.id===r);if(!n||!s)return t.redirect("/settings/connections?clickup=error");let o=await bo(n);if(!o)return s.authStatus="error",await R(s),t.redirect("/settings/connections?clickup=error");let c=(await to(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=w.find(c=>c.id===r);if(!n||!s)return t.redirect("/settings/connections?monday=error");let o=await Ro(n);if(!o)return s.authStatus="error",await R(s),t.redirect("/settings/connections?monday=error");let i=await oo(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 Uc=6e4,Fo={getToken:mn,saveToken:Fe,refresh:(e,t)=>{let n=jt(e);return n?n.refresh(t):Promise.resolve(null)}};async function Bc(e){let t=jt(e.provider);if(!t)throw Object.assign(new Error("not a vendor connection"),{terminal:!0});let n=await Eo(e.id,Fo);if(!n)throw Object.assign(new Error("no usable token"),{terminal:!0});let r=k.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 mn(e.id),p=g?await dr(e.id,g,Fo):null;if(!p){let y=u instanceof Error?u:new Error(String(u));throw Object.assign(y,{terminal:!0})}[o,i]=await s(p)}let{refreshed:c,pool:d}=Gs(o,i,e.id,k,J);for(let u of c)await T(u);return e.lastSyncedAt=new Date().toISOString(),e.ticketCount=k.filter(u=>u.connectionId===e.id).length,e.authStatus="connected",await R(e),{refreshed:c.length,available:d.length}}async function hr(e){if(P())return e.lastSyncedAt=new Date().toISOString(),await R(e),{synced:!0};if(!jt(e.provider))return{synced:!1,skipped:"not_syncable"};if(!await mn(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)<Uc&&t>0)return{synced:!1,skipped:"fresh"};try{return{synced:!0,...await Bc(e)}}catch(r){return e.authStatus=r?.terminal?"expired":"needs_refresh",await R(e),{synced:!1,error:String(r)}}}function qc(){return async(e,t,n)=>{let r=k.find(o=>o.id===e.params.id),s=r?w.find(o=>o.id===r.connectionId):void 0;s&&await hr(s),n()}}f.post("/api/connections/:id/sync",async(e,t)=>{let n=w.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"connection not found"});let r=await hr(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(w.filter(o=>o.linkStatus==="linked").map(o=>o.id)),s=k.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:Et(o,d=>k.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=k.findIndex(i=>i.id===e.params.id);if(n===-1)return t.status(404).json({error:"ticket not found"});let[r]=k.splice(n,1),s=e.body?.beforeId,o=s?k.findIndex(i=>i.id===s):-1;return o===-1?k.push(r):k.splice(o,0,r),await Pr(),t.json({ticketId:r.id})});f.get("/api/tickets/:id",qc(),async(e,t)=>{let n=k.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=En(s.sessionId);if(u.response&&!s.resultText&&(s.resultText=u.response.slice(0,5e4),await M(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 Wt(m)}}}let o=q.find(d=>d.ticketId===n.id)??null,i=w.find(d=>d.id===n.connectionId),c=(n.dependsOn??[]).map(d=>{let u=k.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 $r(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 kt(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=C.filter(r=>r.scheduleId===e.params.id).slice().reverse();t.json(n)});f.post("/api/schedules/:id/notes",async(e,t)=>{let n=N[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 C.push(i),await et(i),t.status(201).json(i)});f.patch("/api/notes/:id",async(e,t)=>{try{return t.json(await ht(e.params.id,String(e.body?.body??"")))}catch(n){return ge(t,n)}});f.delete("/api/notes/:id",async(e,t)=>{try{return await wt(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 yt(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(Gt),"pipelines-uploads"),Fc={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"},Wc=/^paste-[a-f0-9]+(\.[a-z0-9]+)?$/i,Kc=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",hn.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=Kc(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(!Wc.test(n))return t.status(400).end();let r=n.split(".").pop().toLowerCase();return t.type(Fc[r]??"application/octet-stream"),t.sendFile(n,{root:We},s=>{s&&!t.headersSent&&t.status(404).end()})});var Jo=e=>e.split(/[/\\]/).pop()??e,Wo=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>=Wo)return t.status(422).json({error:`at most ${Wo} 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 Qt(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 Qt(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 Gr(e.params.id),await Ur(),t.json({ok:!0}))});f.post("/api/tickets/:id/refresh",async(e,t)=>{let n=k.find(r=>r.id===e.params.id);return n?(await $c(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(w.filter(m=>m.linkStatus==="linked").map(m=>m.id)),c=new Set(k.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=wn(r.workspaceId)),r.model=we(l.defaultModel),r.effort=ye(l.defaultEffort),k.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=k.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=w.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?wn(n.workspaceId):"~",model:we(l.defaultModel),effort:ye(l.defaultEffort),description:n.description,additionalContext:n.additionalContext,additionalContextUpdatedAt:n.additionalContext?new Date().toISOString():void 0,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};k.push(i),S[i.id]="backlog",r&&(r.ticketCount+=1),await T(i.id),r&&await R(r);for(let c of C.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};C.push(u),await et(u)}return t.status(201).json(i)});f.put("/api/tickets/:id/dependencies",async(e,t)=>{let n=k.find(o=>o.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=o=>k.find(i=>i.id===o),s=ms(n.id,n.connectionId,e.body?.dependsOn,r);return fs(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:Et(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.post("/api/runs",async(e,t)=>{try{let n=await Gn(e.body);return t.status(201).json(n)}catch(n){return Lt(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:wr(e.body)});return t.json(n)}catch(n){return Lt(t,n)}});f.post("/api/runs/:id/pause",async(e,t)=>{try{return t.json(await ct(e.params.id))}catch(n){return Lt(t,n)}});f.post("/api/runs/:id/resume",async(e,t)=>{try{return t.json(await dt(e.params.id))}catch(n){return Lt(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=k.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 Oe(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=k.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 Vr(o,e.body?.repo);if(!i){let Qe=await Oe(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(ri=>ri.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}`:"",y=`${u}/${n.externalIdentifier}${m}${p}`,Y=await Zr(i.path),ti=await Dn(i.path,Y),ni=(i.name==="."?"repo":i.name)+p,yr=Q.join(Pn,n.externalIdentifier,ni),br=await es({repoPath:i.path,worktreePath:yr,branch:y,base:Y,startPoint:ti});if(!br.ok)return t.status(500).json({error:br.error});let Sr={repo:i.name,branch:y,worktreePath:yr,base:Y,compareUrl:await rs(i.path,Y,y),createdAt:new Date().toISOString()};return c.push(Sr),s.branchName=s.branchName||y,s.events.push({id:`e${s.events.length+1}`,ts:me(),kind:"mcp_tool",text:`claimed worktree for ${i.name} \u2192 ${y}`}),await M(s.id),t.json(Sr)});f.post("/api/tickets/:id/pr-links",async(e,t)=>{let n=k.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 M(o.id)),!P()&&s.length>1&&Go(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=k.find(r=>r.id===e.params.id);return t.json({prLinks:n?.prLinks??[]})});f.post("/api/tickets/:id/monitor",async(e,t)=>{let n=k.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)>=Mt(l)&&(n.prMonitorCount=0)}else n.prMonitor=!1;return await T(n.id),t.json({prMonitor:n.prMonitor})});var lr=null,pr=!1;async function Qc(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 M(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 M(t.id),await T(e.id)}async function Hc(){if(!(P()||pr)){pr=!0;try{let e=Date.now();for(let t of k){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"||!Uo(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 jo(s),i=o.ci==="passing"&&l.prMonitorReplyToComments?await Mo(s):void 0;await Qc(t,r,Bo(t,l,o,i))}}finally{pr=!1}}}function Jc(){lr||(lr=setInterval(()=>void Hc(),6e4),lr.unref?.())}f.post("/api/runs/:id/stop",async(e,t)=>{try{return t.json(await ut(e.params.id))}catch(n){return Lt(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 M(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 M(n.id),await T(n.ticketId);let s=String(e.body?.decision??e.body?.response??"").trim();return P()||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 M(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(k.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 M(n.id),await T(n.ticketId);let i=r+(s.length?`
118
+
119
+ Attached files (read these):
120
+ ${s.map(c=>`- ${c}`).join(`
121
+ `)}`:"");return P()||be(n.id,!0,i),t.json(n)});f.post("/api/tickets/:id/start-over",async(e,t)=>{let n=k.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 Dr(r)),await en(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 ns(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 Mr(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=E.length-1;d>=0;d--)if(E[d].ticketId===n.id){let[u]=E.splice(d,1);await Ht(u.id)}}if(c("notes")){for(let d=C.length-1;d>=0;d--)if(C[d].ticketId===n.id){let[u]=C.splice(d,1);await Kt(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=k.find(s=>s.id===e.params.id);if(!n)return t.status(404).json({error:"ticket not found"});let r=await ed(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=k.findIndex(o=>o.id===e.params.id);if(n===-1)return t.status(404).json({error:"ticket not found"});let[r]=k.splice(n,1),s=x[r.id];return s&&(delete I[s],delete x[r.id]),delete S[r.id],J.push(r),await en(r.externalIdentifier),await qt(r.id),t.status(204).end()});f.post("/api/board/:connectionId/clear-done",async(e,t)=>{let n=e.params.connectionId,r=k.filter(s=>s.connectionId===n&&fe(s.id)==="done").map(s=>s.id);for(let s of r){let o=k.findIndex(d=>d.id===s),i=o!==-1?k[o].externalIdentifier:null;o!==-1&&k.splice(o,1);let c=x[s];c&&(delete I[c],delete x[s]),delete S[s],i&&await en(i),await qt(s)}return t.json({removed:r.length})});f.get("/api/conversations",(e,t)=>{let n=ee.map(r=>$[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=$[e.params.id];return n?t.json(n):t.status(404).json({error:"conversation not found"})});var zc={Instant:"haiku",Medium:"sonnet",High:"opus"},Xc=["low","medium","high","xhigh","max"],zo=e=>{let t=String(e??"").trim();return Xc.includes(t)?t:"low"};async function Xo(e,t,n,r=[]){if(P())return td(t,e.workspaceName,e.tier);let o=(t||(r.length?"Please look at the attached image(s).":""))+(r.length?`
122
+
123
+ Attached files (read these):
124
+ ${r.map(d=>`- ${d}`).join(`
125
+ `)}`:""),i=n?`${un}
126
+
127
+ ${o}`:o,c=await Ue({prompt:i,workspace:e.workspaceId,workingDir:e.workingDir,model:zc[e.tier],effort:e.effort,sessionId:n?e.sessionId:null,resume:n?null:e.sessionId,pipelinesTools:!0,pipelinesToolsMode:"restricted",sandbox:!0,sandboxRepos:await ln(e.workingDir)});return c.code===0?c.stdout.trim()||"(the agent returned no output)":`\u26A0\uFE0F The run failed (exit ${c.code}).
128
+
129
+ ${(c.stderr||c.stdout).trim().slice(0,500)}`}async function Yo(e,t){if(P()||!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.
130
+
131
+ """
132
+ ${t.slice(0,4e3)}
133
+ """`;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(`
134
+ `).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 Vo(e){return e.messages.map(t=>`${t.role==="assistant"?"Assistant":"User"}: ${t.text}`).join(`
135
+
136
+ `).slice(0,8e3)}async function Yc(e){if(P())return null;let t=Vo(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.
137
+
138
+ """
139
+ ${t}
140
+ """`;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 Vc={backlog:"Backlog",in_progress:"In Progress",needs_input:"Blocked",in_review:"In Review",done:"Done"};function Zc(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: ${Vc[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(`
141
+ `),o=E.filter(g=>g.ticketId===e.id).sort((g,p)=>g.position-p.position),i=o.length?o.map(g=>`- Q: ${g.question}
142
+ A: ${t(g.answer,"(unanswered)")} [${g.resolved?"resolved":"open"}]`).join(`
143
+ `):"No open questions.",c=C.filter(g=>g.ticketId===e.id),d=c.length?c.map(g=>`- [${g.author==="assistant"?"AI":"Me"}] ${g.body.slice(0,500)}`).join(`
144
+ `):"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}`:""}]:
145
+ Request: ${String(g.prompt??"").slice(0,800)}
146
+ Response: ${String(g.response??"").slice(0,1500)}`).join(`
147
+
148
+ `):"No runs yet \u2014 this task hasn't been executed.";return[s,`
149
+ === Description ===
150
+ ${t(e.description,"No task description provided.")}`,`
151
+ === Plan ===
152
+ ${t(e.plan,"No plan yet.")}`,`
153
+ === Open questions ===
154
+ ${i}`,`
155
+ === Additional context ===
156
+ ${t(e.additionalContext,"No additional context provided.")}`,`
157
+ === Notes ===
158
+ ${d}`,`
159
+ === Conclusion ===
160
+ ${t(e.conclusion,"No conclusion yet.")}`,`
161
+ === Run history (oldest \u2192 newest) ===
162
+ ${m}`].join(`
163
+ `).slice(0,14e3)}async function ed(e){if(P())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.
164
+
165
+ """
166
+ ${Zc(e)}
167
+ """`;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=wr(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=zo(e.body?.effort),c=String(e.body?.workingDir??"").trim(),d=`conv_${++L.convSeq}`,u=ei(n,r),m={id:d,title:Zo(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(Jo)}:{}}],starred:!1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};$[d]=m,ee.push(d),await Ge(d),t.status(201).json(m),(async()=>{let g=Yo(m,n),p;try{p=await Xo(m,n,!0,r)}catch(Y){p=`\u26A0\uFE0F The run failed.
168
+
169
+ ${String(Y).slice(0,500)}`}let y=await Promise.race([g,new Promise(Y=>setTimeout(()=>Y(null),3e3))]);y&&(m.title=y),m.messages.push({id:"m2",role:"assistant",text:p,ts:me()}),m.updatedAt=new Date().toISOString(),await Ge(d),y||g.then(Y=>{Y&&(m.title=Y,Ge(d))})})()});f.post("/api/conversations/:id/messages",async(e,t)=>{let n=$[e.params.id];if(!n)return t.status(404).json({error:"conversation not found"});let r=String(e.body?.text??"").trim(),s=wr(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:ei(r,s),ts:me(),...s.length?{attachments:s.map(Jo)}:{}});let o=await Xo(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=$[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=zo(e.body.effort)),await Ge(n.id),t.json(n)});f.post("/api/conversations/:id/retitle",async(e,t)=>{let n=$[e.params.id];if(!n)return t.status(404).json({error:"conversation not found"});let r=await Yo(n,Vo(n));return r&&(n.title=r,await Ge(n.id)),t.json(n)});f.post("/api/conversations/:id/summarize",async(e,t)=>{let n=$[e.params.id];if(!n)return t.status(404).json({error:"conversation not found"});let r=await Yc(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(!$[n])return t.status(404).json({error:"conversation not found"});delete $[n];let r=ee.indexOf(n);return r!==-1&&ee.splice(r,1),await jr(n),t.status(204).end()});function Zo(e){let t=e.split(`
170
+ `)[0].trim();return t.length>48?`${t.slice(0,48).trimEnd()}\u2026`:t}function wr(e){let t=e?.attachments;return Array.isArray(t)?t.map(n=>String(n)).filter(Boolean):[]}function ei(e,t){if(e)return e;let n=t.length;return n?`(${n} image${n>1?"s":""})`:""}function td(e,t,n){let r=Zo(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(`
171
+ `)}f.get("/api/schedules",(e,t)=>{t.json(H.map(n=>N[n]).filter(Boolean))});f.get("/api/schedules/:id",(e,t)=>{let n=N[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(!N[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 Lr(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()||wn(s.id),model:we(e.body?.model??l.defaultModel),effort:ye(e.body?.effort??l.defaultEffort),enabled:!0,starred:!1,createdAt:new Date().toISOString(),lastRunAt:null,nextRunAt:Ot(Date.now(),d)};return N[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=N[e.params.id];if(!n)return t.status(404).json({error:"schedule not found"});let r=await Hn(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=N[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?Ot(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=we(r.model,n.model||ce)),r.effort!==void 0&&(n.effort=ye(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(!N[n])return t.status(404).json({error:"schedule not found"});delete N[n],delete B[n];let r=H.indexOf(n);return r!==-1&&H.splice(r,1),await Or(n),t.status(204).end()});var mr=["publicApiEnabled","apiKeyHash","apiKeyLast4","apiKeyCreatedAt","webhookEnabled","webhookUrl","webhookHeaders","webhookEvents","webhookSecret"];f.get("/api/settings",(e,t)=>{let n={...l};for(let r of mr)delete n[r];t.json(n)});f.put("/api/settings",async(e,t)=>{let n={...e.body??{}};for(let s of mr)delete n[s];Object.assign(l,n),"defaultModel"in n&&(l.defaultModel=we(l.defaultModel)),"defaultEffort"in n&&(l.defaultEffort=ye(l.defaultEffort)),await X();let r={...l};for(let s of mr)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 Rs(e.body?.enabled===!0))});f.post("/api/public-api/key",async(e,t)=>{t.status(201).json(await Ts())});f.delete("/api/public-api/key",async(e,t)=>{t.json(await _s())});f.put("/api/public-api/webhook",async(e,t)=>{try{t.json(await As(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 Ns())});f.post("/api/public-api/webhook/test",async(e,t)=>{t.json(await Es())});function me(){let e=new Date;return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}Ms(f,$t);var fr=Q.join(Q.dirname(Mc(import.meta.url)),"..","dist");$t===gr&&ve.existsSync(Q.join(fr,"index.html"))&&(f.use(hn.static(fr)),f.get("*",(e,t,n)=>{if(e.path.startsWith("/api"))return n();t.sendFile(Q.join(fr,"index.html"))}));process.env.PIPELINES_TEST||zr().then(e=>{console.log(e.loggedIn?`[pipelines] authenticated as ${e.email??e.userId}`:`[pipelines] not authenticated: ${e.error}`)}).then(()=>Tr()).then(()=>Er()).then(()=>Lc()).then(()=>ps()).then(()=>Ls()).then(()=>$s()).then(()=>Co({listConnections:()=>w,connectedWorkspaces:()=>l.connectedWorkspaces,syncOne:hr,isMock:P})).then(()=>Jc()).then(()=>f.listen($t,()=>{console.log(`[pipelines] ready http://localhost:${$t} (sqlite)`)})).then(()=>{l.publicApiEnabled&&an(cn)}).catch(e=>{console.error("[pipelines] startup failed:",e),process.exit(1)});export{f as app};