epiq 0.7.1 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/gui/main.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/readme.md +28 -26
package/dist/gui/main.js
CHANGED
|
@@ -24911,7 +24911,7 @@ var User = ({
|
|
|
24911
24911
|
);
|
|
24912
24912
|
|
|
24913
24913
|
// source/version.ts
|
|
24914
|
-
var EPIQ_VERSION = "0.7.
|
|
24914
|
+
var EPIQ_VERSION = "0.7.3";
|
|
24915
24915
|
|
|
24916
24916
|
// source/gui/client/components/Header.tsx
|
|
24917
24917
|
var import_jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
|
package/dist/index.js
CHANGED
|
@@ -54,7 +54,7 @@ ${m}
|
|
|
54
54
|
|
|
55
55
|
${c}
|
|
56
56
|
`,xs.writeFileSync(t,n,"utf8"),ee.info(`Added ${s.join(", ")} to .gitignore (epiq local state)`),l("Local epiq paths ignored",!0)};var vp=async e=>{let t=await B({cwd:e,args:["status","--porcelain"]});return d(t)?t:l("Checked git diff",t.value.stdout.trim().length>0)},z=(e,t)=>a(`[${e}] ${t}`),md=async()=>{$("");let e=tn(),t=await ht(process.cwd());if(d(t))return z(1,t.message);let n=t.value,o=await io(n);if(d(o))return z(2,o.message);if(o.value)return z(2,`Cannot initialize Epiq while a git operation is in progress: ${o.value}`);let r=await vp(n);if(d(r))return z(2.5,r.message);if(r.value)return z(3,"Cannot initialize Epiq with uncommitted changes. Commit or stash your changes first.");if(Cr(n))return z(4,"Epiq project already initialized");let s=St();if(!s.isSetupDone||!s.userName)return z(5,"Missing Epiq user configuration (userId / userName). Run setup first.");let i=_(),c=i.userName,u=i.userId;if(!u||!c)return z(5,"Missing Epiq user id");let m=e.stateBranch,p=await co({repoRoot:n,branch:m});if(d(p))return z(6,p.message);if(p.value)return z(6,`State branch already exists: ${m}`);let v=await kr({repoRoot:n,stateBranchName:m});if(d(v))return z(6,v.message);let C=mo();if(d(C))return z(7,C.message);let E=ud.join(uo(),e.projectId),S=await $t({repoRoot:n,stateBranchRoot:E,stateBranchName:m});if(d(S))return z(8,S.message);let R=ud.join(E,".epiq");fp.mkdirSync(R,{recursive:!0});let D=oa({userId:u,userName:c});if(d(D))return z(9,D.message);for(let Ir of D.value){let js=So({event:Ir,rootDir:E});if(d(js))return z(9,js.message)}let P=await po({stateBranchRoot:E,eventFileName:Vt({userId:u,userName:c})});if(d(P))return z(10,P.message);let V=await on({cwd:E,message:"[epiq:init]"});if(d(V))return z(10,V.message);let O=await ld(n);if(d(O))return z(11,O.message);let k=zs({repoRoot:n,fileContents:e});if(d(k))return z(12,k.message);let Ee=await te.stage({cwd:n,pathspec:[".epiq/project.json",".gitignore"]});if(d(Ee))return z(13,Ee.message);let ft=await te.commit({cwd:n,message:"[epiq:init-project]"});if(d(ft))return z(13,ft.message);let vt="Project initialized!",yt=await B({cwd:n,args:["push","-u","origin","HEAD"]});d(yt)&&(vt+=` Warn: [init:14] ${yt.message}`);let le=await Rn({repoRoot:n,stateBranchRoot:E});d(le)&&(vt+=` Warn: [init:15] ${le.message}`);let en=Ht(D.value).filter(d);if(en.length>0)return z(16,en.map(Ir=>Ir.message).join(`
|
|
57
|
-
`));let Ot=ze();if(d(Ot))return z(16,Ot.message);let{rootNodeId:zc,nodes:qc}=Ot.value,_s=qc[zc];return _s?(T.navigate({contextNode:_s,selectedIndex:0}),N({hasProjectDefinition:!0,mode:f.DEFAULT}),l(vt,null)):z(16,"Unable to resolve initialized root node")};import{ulid as xp}from"ulid";import{ulid as yp}from"ulid";var pd=null,Pt=()=>structuredClone(pd),jn=e=>{pd=e},gd=()=>{let{contextNode:e,selectedIndex:t}=g(),o=j(e.id)[t];return o?l("Resolved selected child",o):a("Target node not found")},hs=({id:e,parentId:t,position:n={at:"end"}})=>{let o=j(t).filter(r=>r.id!==e);return Eo(o,n)},fd=({id:e,parentId:t,position:n={at:"end"}})=>{let o=X();if(d(o))return a("Unable to resolve user ID");let r=hs({parentId:t,id:e,position:n});return d(r)?r:l("Created pending move state",{id:yp(),...o.value,action:"move.node",payload:{id:e,parent:t,rank:r.value.rank}})},vd=e=>{jn(e);let t=Pn(e,!0);return d(t)?t:l("Node moved successfully",t.value)};function Is(e){let t=gd();if(d(t))return t;let{contextNode:n,nodes:o}=g();if(!n.parentNodeId)return a("Missing parent node id");let r=o[n.parentNodeId];if(!r)return a("Missing parent node");let s=j(r.id),i=s.findIndex(({id:m})=>m===n.id);if(i<0)return a("Current node not found among siblings");let c=s[i+e];if(!c)return a("Missing sibling node");let u=fd({id:t.value.id,parentId:c.id,position:{at:"end"}});return d(u)?u:vd(u.value)}function bs(e){let t=gd();if(d(t))return t;let{contextNode:n,selectedIndex:o}=g(),s=j(n.id)[o+e];if(!s)return a("Missing sibling node");let i=fd({id:t.value.id,parentId:n.id,position:{at:e===1?"after":"before",sibling:s.id}});return d(i)?i:vd(i.value)}var yd=()=>{let e=Pt();if(!e)return a("No pending move state");let t=e.payload.id,n=e.payload.parent,o=g().nodes[n];if(!o)return a("Move parent not found");let r=j(n).findIndex(s=>s.id===t);return r===-1?a("Moved node not found among rendered children"):(T.navigate({contextNode:o,selectedIndex:r}),l("Synchronized navigation to moved node",null))},qo=(e,t="Moved preview")=>{if(d(e))return e;let n=yd();return d(n)?n:(N({mode:f.MOVE}),l(t,null))},xd=async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{modifier:t}=q().commandMeta,{contextNode:n,selectedIndex:o}=g(),r=j(n.id)[o];if(!r)return N({mode:f.DEFAULT}),a("No move target");if(t==="start"){if(r.readonly)return a("Target node is read-only");if(o===-1)return a("No item selected");if(!r.parentNodeId)return a("Target has no parent");let s=j(r.parentNodeId),i=s.findIndex(({id:v})=>v===r.id);if(i===-1)return a("Target not found among siblings");let c=s[i-1],u=s[i+1],m=u!=null?{at:"before",sibling:u.id}:c!=null?{at:"after",sibling:c.id}:{at:"start"},p=hs({parentId:r.parentNodeId,id:r.id,position:m});return d(p)?p:(jn({id:xp(),action:"move.node",payload:{id:r.id,parent:r.parentNodeId,rank:p.value.rank},...e.value}),N({mode:f.MOVE}),l("Move initialized",null))}if(t==="next")return qo(bs(1));if(t==="previous")return qo(bs(-1));if(t==="to-next")return qo(Is(1));if(t==="to-previous")return qo(Is(-1));if(t==="confirm"){let s=Pt();if(!s)return a("No pending move to confirm");let i=await je();if(d(i))return i;let c=F([s],i.value);if(d(c))return c;let u=yd();return d(u)?u:(jn(null),N({mode:f.DEFAULT}),l("Moved item",null))}return t==="cancel"?(jn(null),N({mode:f.DEFAULT}),l("Cancelling move",null)):a("Invalid move modifier")};import{ulid as Xo}from"ulid";import{monotonicFactory as hp,ulid as Ip}from"ulid";var bp=hp(),Yo=({name:e,parent:t,rank:n,user:{userId:o,userName:r}})=>{let s=bp();return l("Created issue events",[{id:Ip(),userId:o,userName:r,action:"add.issue",payload:{id:s,parent:t,name:e,rank:n}}])};var hd=async(e,t)=>{let n=X();if(d(n))return a("Unable to resolve user ID");let o=await je();if(d(o))return o;let r=o.value;if(!t.inputString)return a(`provide a name for your ${t.modifier}`);let{breadCrumb:s,contextNode:i,selectedIndex:c}=g(),u=m=>{let p=F([m],r);if(d(p))return p;let v=I.getNode(p.value[0].result.id);if(!v)return a("Created node not found");if(!v.parentNodeId)return p;let C=I.getNode(v.parentNodeId);return C?(T.navigate({contextNode:C,selectedIndex:I.getSiblings(v.parentNodeId).findIndex(({id:E})=>E===v.id)}),p):a("Parent node not found")};if(t.modifier==="board"){let{rootNodeId:m}=g(),p=I.getNode(m);if(!p)return a("Workspace not found");let v=cn(p.id,n.value,r);return d(v)?v:u({id:Xo(),action:"add.board",payload:{id:Xo(),name:t.inputString,parent:p.id,rank:v.value},...n.value})}if(t.modifier==="swimlane"){let m=Se(s,"BOARD");if(d(m))return a("Unable to add swimlane in this context");let p=cn(m.value.id,n.value,r);return d(p)?p:u({id:Xo(),action:"add.swimlane",payload:{id:Xo(),name:t.inputString,parent:m.value.id,rank:p.value},...n.value})}if(t.modifier==="issue"){let m=W(i.id)[c],p=i.context==="SWIMLANE"?i:i.context==="BOARD"&&m?.context==="SWIMLANE"?m:(()=>{let V=Se(s,"SWIMLANE");return d(V)?null:V.value})();if(!p)return a("Unable to add issue in this context");let v=cn(p.id,n.value,r);if(d(v))return v;let C=Yo({name:t.inputString,parent:p.id,rank:v.value,user:n.value});if(d(C))return C;let E=C.value,S=F([...E],r);if(d(S))return S;if(!S.value[0])return a("Issue creation failed");let P=E.find(V=>V.action==="add.issue")?.payload.id;return P?(T.navigate({contextNode:p,selectedIndex:I.getSiblings(p.id).findIndex(({id:V})=>V===P)}),l("Issue created",null)):a("Unable to determine ticket id")}return l("Success",null)};var Id=async()=>{let e=Se(g().breadCrumb,"BOARD");if(d(e))return e;let t=await ht(process.cwd());if(d(t))return a("Unable to locate repo root");let n=Oe({repoRoot:t.value});if(d(n))throw new Error(n.message);let{modifier:o}=q().commandMeta;if(o==="now"){let S=at(n.value);if(d(S))return a(S.message);let R=Hn();if(d(R))return R;let P=Ht(S.value).filter(d);return P.length>0?a(P.map(V=>V.message).join(", ")):(N({mode:f.DEFAULT,readOnly:!1,timeMode:"live",unappliedEvents:[]}),l("Peeking now",!0))}let r;if(o==="prev"){let S=g().eventLog.at(-1),R=_r(S);if(R===null)return a("No previous event to peek");r=R}else if(o==="next"){let S=g().unappliedEvents.at(0),R=_r(S);if(R===null)return a("No next event to peek");r=R+1}else{let S=ko(o);if(!S)return a("Invalid peek date");r=S.getTime()}let s=g(),i=e.value.id,c=Wi(n.value,r);if(d(c))return a(c.message);let{appliedEvents:u,unappliedEvents:m}=c.value,p=Hn();if(d(p))return p;let C=Ht(u).filter(d);if(C.length>0)return Hn(),N(s),a(C.map(S=>S.message).join(", "));let E=g().nodes[i];return E?(T.navigate({contextNode:E,selectedIndex:0}),N({mode:f.DEFAULT,readOnly:!0,timeMode:"peek",unappliedEvents:m}),l("Peeking",!0)):(Hn(),N(s),a("Board did not exist at peek date"))};import Cp from"zod";var bd=()=>{let e=q().commandMeta.inputString,t=Cp.coerce.number().int().min(3e3).safeParse(e);if(!t.success)return a("Auto sync duration must be a number of at least 3000 ms");let n=mt({autoSyncDebounceMs:t.data});return d(n)?n:(Fe({autoSyncIntervalMs:t.data}),N({mode:f.DEFAULT}),l(`Auto sync interval set to ${t.data}ms`,null))};var Cd=()=>{let e=q().commandMeta.inputString.trim();if(e!=="on"&&e!=="off")return a("Invalid response");let t=la(e),n=mt({autoSync:t});return d(n)?n:(Fe({autoSync:t}),N({mode:f.DEFAULT}),l(`Auto sync set to "${e}"`,null))};var Nd=()=>{let e=q().commandMeta.inputString.trim();if(!["debug","error","info"].includes(e))return a("Invalid response");let n=mt({logLevel:e});return d(n)?n:(Fe({logLevel:e}),N({mode:f.DEFAULT}),l(`Auto sync set to "${e}"`,null))};var Sd=async()=>{$(""),N({mode:f.DEFAULT});let e=ze();if(d(e))return a(e.message);if(e.value.syncStatus.status==="syncing")return a("Sync already in progress");N({syncStatus:{msg:"Syncing",status:"syncing"}});let t=await Ao();return d(t)?(N({syncStatus:{msg:t.message,status:"failed"}}),t):(N({mode:f.DEFAULT,syncStatus:{msg:"Synced",status:"synced"}}),t)};var Np=e=>e.action==="add.issue.comment",Ed=e=>Object.values(g().tags).find(t=>t.name===e),Rd=e=>Object.values(g().contributors).find(t=>t.name===e),pt=async()=>{let e=await je();return d(e)?e:l("Resolved persist root",e.value)},Jo=[{systemOnly:!0,intent:M.Move,description:"Internal move-state command",mode:f.COMMAND_LINE,action:xd},{intent:M.Delete,description:"Delete the currently selected node",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{contextNode:t,selectedIndex:n}=g(),o=W(t.id)[n];if(!o)return a("Unable to resolve child to delete");let r=await pt();if(d(r))return r;if(o.context==="COMMENT"){let s=o.id,i=A(t)?t.id:t.parentNodeId;if(!i)return a("Unable to resolve comment issue");let c=g().nodes[i];if(!c||!A(c))return a("Unable to resolve comment issue");let u=c.log?.filter(Np).find(m=>m.payload.id===s);return u?u.payload.author!==e.value.userId?a("You can only delete your own comments"):F([{id:fe(),action:"delete.issue.comment",payload:{id:s,issue:i},...e.value}],r.value):a("Unable to resolve comment")}return F([{id:fe(),action:"delete.node",payload:{id:o.id},...e.value}],r.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Filter,description:"Filter the board, for example `:filter tag urgent`",mode:f.COMMAND_LINE,action:()=>{let{modifier:e,inputString:t}=q().commandMeta,n=/(!=|=)/,[o]=e.split(n);if(!o||!(i=>ie(h.FILTER).map(c=>c.split(n)[0]).includes(i))(o))return a("Invalid filter modifier");let s={target:o,operator:"=",value:t.trim()};return ue(i=>({...i,filters:e==="clear"?[]:[...i.filters,s],mode:f.DEFAULT})),l("Filter updated",null)}},{intent:M.ViewHelp,description:"Open the help screen",mode:f.COMMAND_LINE,action:()=>{let{contextNode:e,selectedIndex:t,selectedNode:n,breadCrumb:o}=g();return Mt({pendingNavTarget:{contextNode:e,breadCrumb:o,selectedIndex:t,selectedNode:n}}),N({mode:f.HELP}),l("Viewing help",null)}},{intent:M.CloseIssue,description:"Move the selected issue to the closed swimlane",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{contextNode:t,selectedIndex:n}=g(),o=W(t.id)[n];if(!o)return a("Unable to close issue, no target found");if(!A(o))return a("Cannot close in this context");let r=g().nodes[de];if(!r)return a("Unable to locate closed swimlane");if(o.parentNodeId===r.id)return a("Issue is already closed");let s=await pt();if(d(s))return s;let i=s.value,c=Gt(r.id,o.id,{at:"end"},e.value,i);if(d(c))return c;let u=F([{id:fe(),action:"close.issue",payload:{id:o.id,parent:r.id,rank:c.value},...e.value}],i);return d(u)?u:l("Issue closed",null)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.ReopenIssue,description:"Move a closed issue back to its previous swimlane",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{contextNode:t,selectedIndex:n}=g(),o=W(t.id)[n];if(!o)return a("Unable to reopen issue, no target found");let r=o.context==="TICKET"?l("Resolved ticket",o):it(o.id,"TICKET");if(d(r))return a("Cannot reopen in this context");let s=r.value,i=g().nodes[de];if(!i)return a("Unable to locate closed swimlane");if(s.parentNodeId!==i.id)return a("Issue is not closed");if(!A(s))return a("Target node is not issue");let c=Ko(s);if(!c)return a("Unable to resolve previous parent from issue history");if(c===i.id)return a("Previous parent resolves to closed swimlane");let u=g().nodes[c];if(!u)return a("Previous parent no longer exists");let m=await pt();if(d(m))return m;let p=m.value,v=Gt(u.id,s.id,{at:"end"},e.value,p);if(d(v))return v;let C=F([{id:fe(),action:"reopen.issue",payload:{id:s.id,parent:u.id,rank:v.value},...e.value}],p);return d(C)?C:l("Issue reopened",null)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Init,description:"Initialize Epiq in the current git repository",mode:f.COMMAND_LINE,action:md},{intent:M.NewItem,description:"Create a new board, swimlane, or issue",mode:f.COMMAND_LINE,action:hd,onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Rename,description:"itle] Rename the currently selected node",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{contextNode:t,selectedIndex:n}=g(),o=W(t.id)[n];if(!o)return a("Missing node");if(o.readonly)return a("Cannot rename readonly node");let r=Pa();if(!r)return a("Provide a title");let s=await pt();return d(s)?s:F([{id:fe(),action:"edit.title",payload:{id:o.id,name:r},...e.value}],s.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.UntagTicket,description:"Remove a tag from the selected issue",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{modifier:t,inputString:n}=q().commandMeta,o=(t||n).trim();if(!o)return a("Provide a tag");let r=Ed(o);if(!r)return a(`Tag "${o}" does not exist`);let{selectedNode:s}=g();if(!s)return a("Invalid untag target");let i=it(s.id,"TICKET");if(d(i))return a("Unable to untag issue in this context");let c=i.value;if(!A(c))return a("Target node is not issue");if(!(c.props.tags??[]).includes(r.id))return a("Issue is not tagged with that tag");let m=await pt();return d(m)?m:F([{id:fe(),action:"remove.issue.tag",payload:{id:c.id,tag:r.id},...e.value}],m.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.TagTicket,description:"Add or create a tag on the selected issue",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{modifier:t,inputString:n}=q().commandMeta,o=(t||n).trim();if(!o)return a("Provide a tag");let{selectedNode:r}=g();if(!r)return a("Invalid tag target");let s=it(r.id,"TICKET");if(d(s))return a("Unable to tag issue in this context");let i=s.value;if(!A(i))return a("Target node is not issue");let c=await pt();if(d(c))return c;let u=Ed(o),m=u?.id??fe();return(i.props.tags??[]).includes(m)?a("Already tagged with that tag"):F([...u?[]:[{id:fe(),action:"create.tag",payload:{id:m,name:o},...e.value}],{id:fe(),action:"add.issue.tag",payload:{id:i.id,tag:m},...e.value}],c.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.AssignUserToTicket,description:"Assign a user to the selected issue",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{modifier:t,inputString:n}=q().commandMeta,o=(t||n).trim();if(!o)return a("Provide an assignee");let{selectedIndex:r,contextNode:s}=g(),i=W(s.id)[r];if(!i)return a("Invalid assign target");let c=it(i.id,"TICKET");if(d(c))return a("Unable to assign issue in this context");let u=c.value;if(!A(u))return a("Target node is not issue");let m=await pt();if(d(m))return m;let p=Rd(o),v=p?.id??fe();return(u.props.assignees??[]).includes(v)?a("Assignee already assigned"):F([...p?[]:[{id:fe(),action:"create.contributor",payload:{id:v,name:o},...e.value}],{id:fe(),action:"add.issue.assignee",payload:{id:u.id,assignee:v},...e.value}],m.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.UnassignUserFromTicket,description:"Remove an assignee from the selected issue",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{modifier:t,inputString:n}=q().commandMeta,o=(t||n).trim();if(!o)return a("Provide an assignee to remove");let r=Rd(o);if(!r)return a(`Assignee "${o}" does not exist`);let{selectedNode:s}=g();if(!s)return a("Invalid unassign target");let i=it(s.id,"TICKET");if(d(i))return a("Unable to unassign in this context");let c=i.value;if(!A(c))return a("Target node is not issue");if(!(c.props.assignees??[]).includes(r.id))return a(`Issue is not assigned to "${o}"`);let m=await pt();return d(m)?m:F([{id:fe(),action:"remove.issue.assignee",payload:{id:c.id,assignee:r.id},...e.value}],m.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Comment,description:"Add a comment to the selected issue",mode:f.COMMAND_LINE,action:async(e,t)=>{let n=t.inputString.trim();if(!n)return a("Provide a comment");if(n.length>mn)return a(`Cannot exceed ${mn} characters`);let o=X();if(d(o))return a("Unable to resolve user ID");let{breadCrumb:r,selectedNode:s}=g(),i=Se([...r,s],"TICKET");if(d(i))return a("Edit target must be an issue");let c=i.value;if(!c)return a("Invalid comment target");let u=c.context==="TICKET"?l("Resolved ticket",c):it(c.id,"TICKET");if(d(u))return a("Unable to comment on issue in this context");let m=u.value;if(!A(m))return a("Target node is not issue");let p=await pt();return d(p)?p:F([{id:fe(),action:"add.issue.comment",payload:{id:fe(),issue:m.id,author:o.value.userId,md:n},...o.value}],p.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Sync,description:"Pull, commit, and push Epiq state",mode:f.COMMAND_LINE,action:Sd},{intent:M.Peek,description:"View board state at another point in time",mode:f.COMMAND_LINE,action:Id},{intent:M.Export,description:"Export the current board layout to markdown",mode:f.COMMAND_LINE,action:async()=>{let e=await Ja();return d(e)?e:(N({mode:f.DEFAULT}),l("Export successful",!0))}},{intent:M.Exit,description:"Exit the application",mode:f.COMMAND_LINE,action:async()=>(T.exit(),l("Exit successful",!0))},{intent:M.Edit,description:"Edit title or description",mode:f.COMMAND_LINE,action:async(e,t)=>cd(t),onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Config,description:"Update editor, username, view, autosync, or sync debounce",mode:f.COMMAND_LINE,action:(e,t)=>{let n=t.inputString.trim();switch(t.modifier){case re.USERNAME:{let{userId:o,preferredEditor:r,userName:s}=_(),i=n||s,c=o??fe();if(!i||!c)return a("Unable to resolve user name or id");let u=mt({userName:i,userId:c,preferredEditor:r??""});return d(u)?u:(Fe({userName:i,userId:c}),N({mode:f.DEFAULT}),l(`Username set to "${i}"`,null))}case re.EDITOR:{if(!n)return a("No editor provided");let o=mt({preferredEditor:n});return d(o)?o:(Fe({preferredEditor:n}),N({mode:f.DEFAULT}),l(`Editor configuration set to "${n}"`,null))}case re.VIEW:return n!=="wide"&&n!=="dense"?a("Invalid view mode"):(Fe({viewMode:n}),l(`View set to "${n}"`,null));case re.AUTOSYNC:return Cd();case re.LOG_LEVEL:return Nd();case re.SYNC_DEBOUNCE_MS:return bd();default:return a("Unknown config command")}}},{intent:M.Coffee,description:"Sponsor the development of Epiq!",mode:f.COMMAND_LINE,action:()=>{let e=q().commandMeta.modifier;return e==="custom"?vs("https://github.com/sponsors/ljtn?frequency=one-time&sponsor=ljtn"):vs(`https://github.com/sponsors/ljtn/sponsorships?sponsor=ljtn&preview=true&frequency=one-time&amount=${e}`),$(""),l("Thanks you!",null)}}];var Sp=new Set(["peek","filter","view-help"]),Ze=async({isForceExecutedBySystem:e=!1}={})=>{let{commandMeta:{command:t,validity:n,modifier:o,inputString:r}}=q();if(!t)return a("No command to confirm");if(!e&&n===Et.Invalid)return a("Invalid command");let s=Uo(t);Ra();let{readOnly:i}=g();if(i&&!Sp.has(s))return Bn({status:xt.Fail,message:"Command not available in readonly state",value:null});let c=Jo.filter(m=>e||m.systemOnly!==!0).find(m=>m.intent===s);if(!c)return Bn({status:xt.Fail,message:"Command not found",value:null});let u;try{u=await c.action(c,{command:t,inputString:r,modifier:o})}catch(m){return Bn({status:xt.Fail,message:m instanceof Error?m.message:"Command failed",value:null})}return d(u)?Bn(u):(Ta({addToHistory:!e}),c.onSuccess?.(),_().autoSync&&Mo(),u)};var Qo=[{intent:x.Exit,mode:f.MOVE,description:"[<Esc>] exit context / cancel",action:()=>(N({mode:f.COMMAND_LINE}),$("move cancel"),Ze({isForceExecutedBySystem:!0}))},{intent:x.InitMove,mode:f.DEFAULT,description:"[m] move (init/confirm)",action:()=>(N({mode:f.COMMAND_LINE}),$("move start"),Ze({isForceExecutedBySystem:!0}))},{intent:x.ConfirmMove,mode:f.MOVE,action:()=>(N({mode:f.COMMAND_LINE}),$("move confirm"),Ze({isForceExecutedBySystem:!0}))}],Zo=[{intent:x.MovePreviousItem,mode:f.MOVE,action:()=>Pt()?(N({mode:f.COMMAND_LINE}),$("move previous"),Ze({isForceExecutedBySystem:!0})):a("No pending move")},{intent:x.MoveNextItem,mode:f.MOVE,action:()=>Pt()?(N({mode:f.COMMAND_LINE}),$("move next"),Ze({isForceExecutedBySystem:!0})):a("No pending move")}],Td=[{intent:x.MoveToNextContainer,mode:f.MOVE,action:()=>Pt()?(N({mode:f.COMMAND_LINE}),$("move to-next"),Ze({isForceExecutedBySystem:!0})):a("No pending move")},{intent:x.MoveToPreviousContainer,mode:f.MOVE,action:()=>Pt()?(N({mode:f.COMMAND_LINE}),$("move to-previous"),Ze({isForceExecutedBySystem:!0})):a("No pending move")}];var Ad={[w.WORKSPACE]:[...Qo,...Zo],[w.BOARD]:[...Qo,...Zo],[w.SWIMLANE]:[...Qo,...Zo,...Td],[w.TICKET]:[],[w.FIELD]:[],[w.FIELD_LIST]:[],[w.TEXT]:[],[w.COMMENT]:[]};var wd=()=>{$("");let{pendingNavTarget:e}=wt();N({mode:f.DEFAULT}),e&&T.navigate(e),Mt({pendingNavTarget:void 0})},Md=[{intent:x.ExitCommandLine,mode:f.HELP,action:()=>(wd(),l("Exiting help",null))},{intent:x.Exit,mode:f.HELP,action:()=>(wd(),l("Closed help",null))},{intent:x.NavPreviousItem,mode:f.HELP,description:"[arrows/hjkl] navigate",action:()=>(T.navigateToPreviousItem(),l("Navigating to previous help item",null))},{intent:x.NavNextItem,mode:f.HELP,action:()=>(T.navigateToNextItem(),l("Navigating to next help item",null))},{intent:x.NavToPreviousContainer,mode:f.HELP,action:()=>(T.navigateToPreviousContainer(),l("Navigating to previous help container",null))},{intent:x.NavToNextContainer,mode:f.HELP,action:()=>(T.navigateToNextContainer(),l("Navigating to next help container",null))}];var Ep=e=>{N({mode:f.COMMAND_LINE});let{pendingNavTarget:t}=wt();t&&T.navigate(t),Mt({pendingNavTarget:void 0}),$(`${e} `)},Pd=()=>{$("");let{pendingNavTarget:e}=wt();e&&T.navigate(e),Mt({pendingNavTarget:void 0}),N({mode:f.DEFAULT})},Ld=[{intent:x.InitCommandPalette,mode:f.DEFAULT,description:"[?] view command palette (explore descriptions for every command)",action:()=>{$("");let{contextNode:e,selectedIndex:t,selectedNode:n,breadCrumb:o}=g();return Mt({pendingNavTarget:{contextNode:e,selectedIndex:t,selectedNode:n,breadCrumb:o}}),N({mode:f.PALETTE}),l("Opening command palette",null)}},{intent:x.Confirm,mode:f.PALETTE,action:()=>{let{selectedNode:e}=g();if(!e||!bt(e))return a("Command only applicable on text nodes");if(e.props.disabled)return a("Command is not available in this context");let t=e.title;return t?(Ep(t),l("Selected command",t)):l("No command selected",null)}},{intent:x.ExitCommandLine,mode:f.PALETTE,action:()=>(Pd(),l("Exiting palette",null))},{intent:x.Exit,mode:f.PALETTE,action:()=>(Pd(),l("Closed command palette",null))},{intent:x.NavPreviousItem,mode:f.PALETTE,description:"[arrows/hjkl] navigate",action:()=>(T.navigateToPreviousItem(),l("Navigating to previous item",null))},{intent:x.NavNextItem,mode:f.PALETTE,action:()=>(T.navigateToNextItem(),l("Navigating to next item",null))},{intent:x.NavToPreviousContainer,mode:f.PALETTE,action:()=>(T.navigateToPreviousContainer(),l("Navigating to previous container",null))},{intent:x.NavToNextContainer,mode:f.PALETTE,action:()=>(T.navigateToNextContainer(),l("Navigating to next container",null))}];var kd=[...Md,...Ld,{intent:x.AddItem,mode:f.DEFAULT,description:"[n] new...",action:()=>(N({mode:f.COMMAND_LINE}),$(`${h.NEW} `),l("Adding new item",null))},{intent:x.Delete,mode:f.DEFAULT,description:"[d] delete",action:()=>(N({mode:f.COMMAND_LINE}),$(`${h.DELETE} `),l("Deleting item",null))},{intent:x.InitCommandLine,mode:f.DEFAULT,description:"[:] focus command line",action:()=>(N({mode:f.COMMAND_LINE}),$(""),l("Entering command line mode",null))},{intent:x.Confirm,mode:f.DEFAULT,description:"[<Enter>] confirm/enter",action:()=>{let{selectedNode:e,contextNode:t}=g();if(!j(e?.id??"")?.length){if(e?.title===ne.DESCRIPTION)return N({mode:f.COMMAND_LINE}),$(`${h.EDIT} description `),l("Propose command",!0);if(e?.title===ne.ASSIGNEES)return N({mode:f.COMMAND_LINE}),$(`${h.ASSIGN} `),l("Propose command",!0);if(e?.title===ne.TAGS)return N({mode:f.COMMAND_LINE}),$(`${h.TAG} `),l("Propose command",!0);if(t.title===ne.DESCRIPTION&&e?.context==="TEXT")return N({mode:f.COMMAND_LINE}),$(`${h.EDIT} description `),l("Propose command",!0)}return T.enterChildNode(),l("Entering context",null)}},{intent:x.EditTitle,mode:f.DEFAULT,description:"[r] rename title",action:()=>(N({mode:f.COMMAND_LINE}),$(`${h.EDIT} title ${g().selectedNode?.title}`),l("Exiting context",null))},{intent:x.EditDescription,mode:f.DEFAULT,description:"[e] edit description",action:()=>(N({mode:f.COMMAND_LINE}),$(`${h.EDIT} description `),l("Exiting context",null))},{intent:x.Exit,mode:f.DEFAULT,description:"[q] exit context",action:()=>(T.enterParentNode(),l("Exiting context",null))},{intent:x.NavPreviousItem,mode:f.DEFAULT,description:"[arrows/hjkl] navigate",action:()=>(T.navigateToPreviousItem(),l("Navigating to previous item",null))},{intent:x.NavNextItem,mode:f.DEFAULT,action:()=>(T.navigateToNextItem(),l("Navigating to next item",null))},{intent:x.NavToPreviousContainer,mode:f.DEFAULT,action:()=>(T.navigateToPreviousContainer(),l("Navigating to previous container",null))},{intent:x.NavToNextContainer,mode:f.DEFAULT,action:()=>(T.navigateToNextContainer(),l("Navigating to next container",null))}];var Rp=500,Tp=e=>e.replace(/[\r\n]/g,"").replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g,""),Dd=e=>{let t=Tp(e);t&&pn(n=>(n+t).slice(0,Rp))};var Ap=[f.COMMAND_LINE,f.PALETTE],wp=e=>[{intent:x.MoveCursorLeft,mode:e,action:()=>(ss(-1),l("Moving cursor left",null))},{intent:x.MoveCursorRight,mode:e,action:()=>(ss(1),l("Moving cursor right",null))},{intent:x.MoveCursorLeftOfWord,mode:e,action:()=>(is("left"),l("Moving cursor left of word",null))},{intent:x.MoveCursorRightOfWord,mode:e,action:()=>(is("right"),l("Moving cursor right of word",null))},{intent:x.AutoCompleteCommand,mode:e,action:()=>(pn((t,{remainder:n})=>{let o=n?t+n:t,r="";return o==="edit title "&&(r=g().selectedNode?.title??""),o+r}),l("Auto-completing command",null))},{intent:x.CaptureInput,mode:e,action:(t,{sequence:n})=>(Dd(n??""),l("Capturing input",null))},{intent:x.EraseInput,mode:e,action:()=>(Sa(),l("Erasing input",null))},{intent:x.EraseInputWord,mode:e,action:()=>(Ea(),l("Erasing input word",null))}],Fd=[{intent:x.Confirm,mode:f.COMMAND_LINE,action:()=>(Ze(),l("Executing command",null))},{intent:x.ViewHelp,mode:f.DEFAULT,action:()=>(N({mode:f.HELP}),l("Viewing help",null))},...Ap.flatMap(wp),{intent:x.ExitCommandLine,mode:f.COMMAND_LINE,action:()=>(N({mode:f.DEFAULT}),l("Exiting command line",null))},{intent:x.GetLastCommandFromHistory,mode:f.COMMAND_LINE,action:()=>(Aa(),l("Getting last command from history",null))},{intent:x.GetNextCommandFromHistory,mode:f.COMMAND_LINE,action:()=>(wa(),l("Getting next command from history",null))}];import Od from"chalk";var er=Od.dim.hex(y.secondary2)(": for command line"),Bd="q to exit",Ud=`${Od.hex(y.accent)("m")} to confirm`,Cs={[w.WORKSPACE]:[er],[w.BOARD]:[er],[w.BOARD+f.COMMAND_LINE]:[er],[w.SWIMLANE]:[er],[w.TICKET+f.HELP]:[Bd],[w.SWIMLANE+f.HELP]:[Bd],[w.TICKET]:[],[w.FIELD]:[],[w.SWIMLANE+f.MOVE]:[Ud],[w.TICKET+f.MOVE]:[Ud]};var Vn=e=>e.trim().toLocaleLowerCase(),Mp=e=>{let{tags:t}=g();return(e.props.tags??[]).map(n=>t[n]?.name).filter(n=>!!n)},Pp=e=>{let{contributors:t}=g();return(e.props.assignees??[]).map(n=>t[n]?.name).filter(n=>!!n)},$d=(e,t)=>{let n=Vn(t.value);if(!n)return!0;switch(t.target){case"title":return Vn(e.title??"").includes(n);case"description":return Vn(e.props.description??"").includes(n);case"tag":return Mp(e).map(Vn).some(r=>r.includes(n));case"assignee":return Pp(e).map(Vn).some(r=>r.includes(n));default:return!0}};function Wd(e,t,n){let o=t[e];if(!o)return a("buildBreadCrumb(): current node not found");let r=[],s=o;for(;s&&(r.push(s),!(s.id===n||!s.parentNodeId));)s=t[s.parentNodeId];let i=r[r.length-1];return!i||i.id!==n?a("buildBreadCrumb(): node is not connected to root"):(r.reverse(),l("Breadcrumb built",r))}var _d=e=>{let t={};for(let n of e)n.intent&&(t[n.mode]||(t[n.mode]={}),t[n.mode][n.intent]=n);return t};var Qt,Ns,Ss=new Set,jd=()=>{for(let e of Ss)e()},kp=e=>(Ss.add(e),()=>Ss.delete(e));function Hd(e){let{contextNodeId:t,mode:n,rootNodeId:o,nodes:r,filters:s}=e;if(!t)return a("derive(): contextNodeId is missing");if(!o)return a("derive(): rootNode is missing");if(!r[o])return a("derive(): unable to find root node");let c=r[t];if(!c)return a("Unable to derive state, contextNode not found");let u=Wd(t,r,o);if(d(u))return logger.error(u.message),u;let m=u.value,{context:p}=c,v=Cs[p+n]??Cs[p]??[],C=[...kd,...Ad[p]??[],...Fd],E=_d(C),S=Dp(r,s),R=S[t]?.[e.selectedIndex]??null;return l("Derived successfully",{...e,contextNode:c,breadCrumb:m,availableHints:v,availableActions:C,actionIndex:E,selectedNode:R,renderedChildrenIndex:S})}var g=()=>{if(!Qt)throw new Error("State not initialized. Call initWorkspaceState() first.");return Qt},ze=()=>Qt?l("Retrieved state",Qt):a("State not initialized. Call initWorkspaceState() first.");function Ln(e){Ns=e;let t=_e(process.cwd()),n=!1;if(!d(t)){let s=It(t.value);if(d(s))return a(s.message);n=!0}let o={readOnly:!1,filters:[],tags:{},contributors:{},mode:f.DEFAULT,nodes:{[e.id]:e},rootNodeId:e.id,contextNodeId:e.id,renderedChildrenIndex:{},selectedIndex:-1,syncStatus:{status:"synced",msg:""},eventLog:[],unappliedEvents:[],timeMode:"live",hasProjectDefinition:n,hasInitializingEvents:!1,comments:{}},r=Hd(o);return d(r)?r:(Qt=r.value,jd(),l("State initialized",null))}function ue(e){let t=g(),n=e(t),o=Hd(n);return d(o)?a(o.message??"Unable to update state"):(Qt=o.value,jd(),l("State updated",null))}var N=e=>ue(t=>({...t,...e}));var K=()=>Lp(kp,g,g),Dp=(e,t)=>{let n={};for(let o of Object.values(e))A(o)&&t.length>0&&!t.every(r=>$d(o,r))||!o.parentNodeId||o.isDeleted||((!o.parentNodeId||!n[o.parentNodeId])&&(n[o.parentNodeId]=[]),n[o.parentNodeId].push(o));for(let o of Object.keys(n))n[o].sort((r,s)=>{let i=e[r.id],c=e[s.id];return!i||!c?0:i.rank.localeCompare(c.rank)});return n},W=e=>g()?.renderedChildrenIndex[e]??[],Hn=()=>Ns?Ln(Ns):a("Cannot reset state: no initial workspace found"),un=()=>Qt!==void 0;var Es=e=>{un()&&(N({syncStatus:e}),Wt({type:"sync-status",payload:e}))},tr=(e="Syncing...")=>{Es({status:"syncing",msg:e})},nr=(e="Synced")=>{Es({status:"synced",msg:e})},Rs=e=>{Es({status:"failed",msg:e})},Ue=e=>(Rs(e),a(e));import{decodeTime as FA}from"ulid";var Fp=async({cwd:e,ensureUpstream:t})=>{logger.debug("[sync] ensureSyncReady:start",{cwd:e,ensureUpstream:t});let n=G("getRepoRootDir",await ht(e));if(d(n))return a(n.message);let o=n.value;logger.debug("[sync] repo root",o);let r=G("getStateBranchRoot",Oe({repoRoot:o}));if(d(r))return a(r.message);let s=r.value;logger.debug("[sync] state branch root",s);let i=G("ensureInitialCommit",await mi(o));if(d(i))return a(i.message);logger.debug("[sync] initial commit result",{created:i.value}),logger.debug("[sync] bootstrapping state branch storage",{repoRoot:o,stateBranchRoot:s,ensureUpstream:t});let c=G("bootstrapStateBranchStorage",await gi({repoRoot:o,stateBranchRoot:s,ensureUpstream:t}));if(d(c))return a(c.message);logger.debug("[sync] bootstrap result",{bootstrapped:c.value,stateBranchRoot:s}),logger.debug("[sync] checking state branch git operation",{stateBranchRoot:s});let u=G("hasInProgressGitOperation(stateBranchRoot)",await io(s));if(d(u))return a(u.message);if(logger.debug("[sync] state branch git operation check result",{inProgress:u.value}),u.value)return logger.info("[sync] state branch git operation in progress"),a("Cannot sync while a git operation is in progress in the state branch");logger.debug("[sync] ensuring state branch layout",{repoRoot:o,stateBranchRoot:s});let m=G("ensureStateBranchLayout",ci(o,s));return d(m)?a(m.message):(logger.debug("[sync] state branch layout ready"),logger.debug("[sync] ensureSyncReady:done",{repoRoot:o,stateBranchRoot:s,bootstrapped:c.value}),l("Sync preconditions satisfied",{repoRoot:o,stateBranchRoot:s,bootstrapped:c.value}))},Bp=async({repoRoot:e,stateBranchRoot:t,ownEventFileName:n})=>{logger.debug("[sync] committing own event file from state branch",{ownEventFileName:n,stateBranchRoot:t}),logger.debug("[sync] staging own event file",{stateBranchRoot:t,ownEventFileName:n});let o=G("stageStateBranchOwnEventFile",await po({stateBranchRoot:t,eventFileName:n}));if(d(o))return a(o.message);let r=G("hasStagedChanges(after stage)",await oi(t));if(d(r))return a(r.message);if(logger.debug("[sync] state branch change check after stage result",{changed:r.value}),!r.value)return logger.info("[sync] no own event file changes to commit"),l("No own event file changes to commit",{createdCommit:!1});logger.debug("[sync] creating sync commit");let s=G("createStateBranchSyncCommit",await pi({repoRoot:e,stateBranchRoot:t}));return d(s)?a(s.message):(logger.debug("[sync] created sync commit",s.value),l("Committed own event file",{createdCommit:!0,commitSha:s.value}))},wo=async({cwd:e=process.cwd(),ownEventFileName:t})=>{if(logger.debug("[sync] syncEpiqWithRemote:start",{cwd:e,ownEventFileName:t}),t.includes("/")||t.includes("\\"))return logger.error("[sync] invalid own event file name: contains path separator",{ownEventFileName:t}),a("Own event file must be a file name, not a path");if(!t.endsWith(".jsonl"))return logger.error("[sync] invalid own event file name: missing .jsonl suffix",{ownEventFileName:t}),a("Own event file must end with .jsonl");tr();let n=G("ensureSyncReady",await Fp({cwd:e,ensureUpstream:!0}));if(d(n))return Ue(n.message);let{repoRoot:o,stateBranchRoot:r,bootstrapped:s}=n.value,i=G("isDetachedHead(stateBranchRoot)",await ri(r));if(d(i))return Ue(i.message);if(logger.debug("[sync] detached state branch check result",{detached:i.value}),i.value)return Ue("Cannot run :sync while the state branch is in detached HEAD state");let c=!1,u,m=!1,p=!1,v=G("getStateBranch",nn(o));if(d(v))return Ue(v.message);let C=v.value;logger.debug("[sync] resolved state branch",{stateBranch:C,stateBranchRoot:r});let E=G("commitOwnEventFileToStateBranch",await Bp({repoRoot:o,stateBranchRoot:r,ownEventFileName:t}));if(d(E))return Ue(E.message);c=E.value.createdCommit,u=E.value.commitSha;let S=G("pullBranchRebaseIfPresent",await Mr({cwd:r,branch:C}));if(d(S))return Ue(S.message);if(m=S.value,c||s){logger.info("[sync] pushing state branch",{createdCommit:c,bootstrapped:s,stateBranchRoot:r});let R=G("pushStateBranch",await Rn({stateBranchRoot:r,repoRoot:o}));if(d(R)&&ni(R.message)){let D=G("pullBranchRebaseIfPresent(retry)",await Mr({cwd:r,branch:C}));if(d(D))return Ue(D.message);m=m||D.value,R=G("pushStateBranch(retry)",await Rn({stateBranchRoot:r,repoRoot:o}))}if(d(R))return Ue(R.message);p=R.value}if(c){logger.debug("[sync] resolving final sync commit sha",{stateBranchRoot:r});let R=G("git rev-parse HEAD",await B({args:["rev-parse","HEAD"],cwd:r}));if(d(R))return Ue(R.message);u=R.value.stdout.trim(),logger.debug("[sync] final sync commit sha",u)}return nr(p?"Synced and pushed":m||c?"Synced local state":"Already synced"),logger.debug("[sync] syncEpiqWithRemote:done"),l("Synced event logs with state branch",{repoRoot:o,stateBranchRoot:r,createdCommit:c,commitSha:u,pulled:m,pushed:p,bootstrapped:s})};var Ts=e=>{let t=_e(e??process.cwd());return d(t)?a(t.message):l("Resolved Epiq repo root",t.value)},we=async e=>{let t=Ts(e);if(d(t))return t;let n=Oe({repoRoot:t.value});if(d(n))return a(n.message);let o=tn(),r=await $t({repoRoot:t.value,stateBranchRoot:n.value,stateBranchName:o.stateBranch});if(d(r))return a(r.message);let s=await B({cwd:n.value,args:["pull","--ff-only"]});d(s)&&ee.info(3,s.message);let i=at(n.value);if(d(i))return a(i.message);let c=Kt(i.value);return d(c)?a(c.message):l("Booted Epiq state",{repoRoot:t.value,stateBranchRoot:n.value})},Me=()=>{let e=_n();return d(e)?a(e.message):e.value.userId?e.value.userName?l("Resolved actor",{userId:e.value.userId,userName:e.value.userName}):a("Unable to retrieve user name"):a("Unable to retrieve user id")},$e=()=>{let e=ze();return d(e)?a(e.message):e},Vd=e=>(e.props.tags??[]).map(t=>I.getTag(t)).filter(t=>t!=null).map(t=>({id:t.id,name:t.name,color:oe(t.name)})),Gd=e=>(e.props.assignees??[]).map(t=>I.getContributor(t)).filter(t=>t!=null).map(t=>({id:t.id,name:t.name,color:oe(t.name)}));var Kd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=$e();if(d(n))return n;let o=Object.values(n.value.nodes).filter(A).filter(r=>e.includeClosed||r.parentNodeId!==de).map(r=>({id:r.id,title:Nt(r.title),description:r.props.description??"",parentNodeId:r.parentNodeId,isClosed:r.parentNodeId===de,readonly:!!r.readonly,tags:Vd(r),assignees:Gd(r)}));return l("Listed issues",o)},zd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=cn(e.parentId,n.value,t.value.stateBranchRoot);if(d(o))return o;let r=Yo({name:e.title,parent:e.parentId,user:n.value,rank:o.value});if(d(r))return r;let s=r.value,i=F([...s],t.value.stateBranchRoot);if(d(i))return a(i.message);let c=s.find(u=>u.action==="add.issue")?.payload.id;return c?l("Created issue",{id:c,title:e.title,parentId:e.parentId}):a("Unable to determine created issue id")},qd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=Gt(de,e.issueId,{at:"end"},n.value,t.value.stateBranchRoot);if(d(o))return o;let r={id:ve(),...n.value,action:"close.issue",payload:{id:e.issueId,parent:de,rank:o.value}},s=F([r],t.value.stateBranchRoot);return d(s)?a(s.message):l("Closed issue",{id:e.issueId})},Yd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Target node is not issue");if(r.parentNodeId!==de)return a("Issue is not closed");let s=Ko(r);if(!s)return a("Unable to resolve previous parent from issue history");if(s===de)return a("Previous parent resolves to closed swimlane");let i=o.value.nodes[s];if(!i)return a("Previous parent no longer exists");let c=Gt(i.id,r.id,{at:"end"},n.value,t.value.stateBranchRoot);if(d(c))return c;let u={id:ve(),...n.value,action:"reopen.issue",payload:{id:r.id,parent:i.id,rank:c.value}},m=F([u],t.value.stateBranchRoot);return d(m)?a(m.message):l("Reopened issue",{id:r.id,parentId:i.id})},Xd=async e=>{let t=Ts(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=Oe({repoRoot:t.value});if(d(o))return o;let r=at(o.value);if(d(r))return r;let s=Kt(r.value);if(d(s))return s;let i=Gt(e.parentId,e.issueId,e.position??{at:"end"},n.value,o.value);if(d(i))return i;let c={id:ve(),...n.value,action:"move.node",payload:{id:e.issueId,parent:e.parentId,rank:i.value}},u=F([c],o.value);return d(u)?a(u.message):l("Moved issue",{id:e.issueId,parentId:e.parentId})},or=async(e={})=>{tr();let t=Ts(e.repoRoot);if(d(t))return a("Sync failed");let n=Me();if(d(n))return n;let o=await wo({cwd:t.value,ownEventFileName:Vt(n.value)});return d(o)?(Rs(o.message),o):(nr(),l("Synced",o.value))};var Lt=async(e={})=>{let t=await we(e.repoRoot);if(d(t))return t;let n=$e();if(d(n))return n;let o=Object.values(n.value.nodes),r=o.filter(m=>fo(m)&&!m.isDeleted),s=new Map,i=new Map;for(let m of o)if(!m.isDeleted){if(Ct(m)&&m.parentNodeId){let p=s.get(m.parentNodeId)??[];p.push(m),s.set(m.parentNodeId,p)}if(A(m)&&m.parentNodeId){let p=i.get(m.parentNodeId)??[];p.push(m),i.set(m.parentNodeId,p)}}let c=_n();if(d(c))return c;let u={};for(let m of o.filter(A))m.isDeleted||(u[m.id]=I.getCommentsByIssue(m.id).map(p=>{let v=I.getContributor(p.authorId);return{id:p.id,issueId:p.issue,body:p.md,author:{id:p.authorId,name:v?.name??"Unknown",color:oe(v?.name??p.authorId)},createdAt:Up(p.id)}}));return l("Retrieved Epiq GUI state",{boards:r.sort((m,p)=>m.rank.localeCompare(p.rank)).map(m=>({id:m.id,title:m.title,swimlanes:(s.get(m.id)??[]).sort((p,v)=>p.rank.localeCompare(v.rank)).map(p=>({id:p.id,title:p.title,readonly:!!p.readonly,issues:(i.get(p.id)??[]).sort((v,C)=>v.rank.localeCompare(C.rank)).map(v=>({id:v.id,title:Nt(v.title),description:v.props.description??"",readonly:!!v.readonly,tags:Vd(v),assignees:Gd(v),parentNodeId:v.parentNodeId,isClosed:v.parentNodeId===de})),parentNodeId:p.parentNodeId}))})),tags:Object.values(n.value.tags).map(m=>({...m,color:oe(m.name)})),contributors:Object.values(n.value.contributors).map(m=>({...m,color:oe(m.name)})),user:{name:c.value.userName??"",id:c.value.userId??"",color:oe(c.value.userName??"")},commentsByIssueId:u})},Jd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Edit target must be an issue");if(r.readonly)return a("Cannot edit readonly issue");let s=r.props.description??"";if(s===e.description)return l("No changes made",{id:e.issueId,description:s});let i={id:ve(),...n.value,action:"edit.description",payload:{id:e.issueId,md:e.description}},c=F([i],t.value.stateBranchRoot);return d(c)?a(c.message):l("Edited issue description",{id:e.issueId,description:e.description})},Qd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Edit target must be an issue");if(r.readonly)return a("Cannot edit readonly issue");let s=Nt(e.title);if(!s.trim())return a("Issue title cannot be empty");if(r.title===s)return l("No changes made",{id:e.issueId,title:s});let i={id:ve(),...n.value,action:"edit.title",payload:{id:e.issueId,name:s}},c=F([i],t.value.stateBranchRoot);return d(c)?a(c.message):l("Edited issue title",{id:e.issueId,title:s})},Zd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Tag target must be an issue");if(r.readonly)return a("Cannot tag readonly issue");let s=Nt(e.tagName).trim();if(!s)return a("Tag name cannot be empty");let i=Object.values(o.value.tags).find(p=>p.name===s),c=i?.id??ve(),u=[...i?[]:[{id:ve(),...n.value,action:"create.tag",payload:{id:c,name:s}}],{id:ve(),...n.value,action:"add.issue.tag",payload:{id:e.issueId,tag:c}}],m=F(u,t.value.stateBranchRoot);return d(m)?a(m.message):l("Added issue tag",{id:e.issueId,tag:{id:c,name:s}})},ec=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Untag target must be an issue");if(r.readonly)return a("Cannot untag readonly issue");if(!o.value.tags[e.tagId])return a("Tag not found");let s={id:ve(),...n.value,action:"remove.issue.tag",payload:{id:e.issueId,tag:e.tagId}},i=F([s],t.value.stateBranchRoot);return d(i)?a(i.message):l("Removed issue tag",{id:e.issueId,tagId:e.tagId})},tc=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Assign target must be an issue");if(r.readonly)return a("Cannot assign readonly issue");let s=Nt(e.assigneeName).trim();if(!s)return a("Assignee name cannot be empty");let i=Object.values(o.value.contributors).find(p=>p.name===s),c=i?.id??ve(),u=[...i?[]:[{id:ve(),...n.value,action:"create.contributor",payload:{id:c,name:s}}],{id:ve(),...n.value,action:"add.issue.assignee",payload:{id:e.issueId,assignee:c}}],m=F(u,t.value.stateBranchRoot);return d(m)?a(m.message):l("Added issue assignee",{id:e.issueId,assignee:{id:c,name:s}})},nc=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Unassign target must be an issue");if(r.readonly)return a("Cannot unassign readonly issue");if(!o.value.contributors[e.assigneeId])return a("Assignee not found");let s={id:ve(),...n.value,action:"remove.issue.assignee",payload:{id:e.issueId,assignee:e.assigneeId}},i=F([s],t.value.stateBranchRoot);return d(i)?a(i.message):l("Removed issue assignee",{id:e.issueId,assigneeId:e.assigneeId})},rr=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Comment target must be an issue");if(r.readonly)return a("Cannot comment on readonly issue");let s=e.body.trim();if(!s)return a("Comment cannot be empty");let i=ve(),c={id:ve(),...n.value,action:"add.issue.comment",payload:{id:i,issue:e.issueId,md:s,author:n.value.userId}},u=F([c],t.value.stateBranchRoot);return d(u)?a(u.message):l("Added issue comment",{id:i,issueId:e.issueId,body:s})},sr=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.eventLog.find(m=>m.action==="add.issue.comment"&&m.payload.id===e.commentId);if(!r)return a("Unable to resolve comment");if(r.payload.author!==n.value.userId)return a("You can only delete your own comments");let s=o.value.nodes[r.payload.issue];if(!s)return a("Issue not found");if(!A(s))return a("Comment target must be an issue");if(s.readonly)return a("Cannot delete comment on readonly issue");if(o.value.eventLog.some(m=>m.action==="delete.issue.comment"&&m.payload.id===e.commentId))return l("Comment already deleted",{id:e.commentId,issueId:r.payload.issue});let c={id:ve(),...n.value,action:"delete.issue.comment",payload:{id:e.commentId,issue:r.payload.issue}},u=F([c],t.value.stateBranchRoot);return d(u)?a(u.message):l("Deleted issue comment",{id:e.commentId,issueId:r.payload.issue})};var oc=e=>{let t,n,o=!1,r=!1,s=!1,i=()=>{let p=Wn();if(d(p))return ee.error(p.message);let{autoSync:v,userName:C,preferredEditor:E}=p.value;return!!(v&&C&&E)},c=async()=>{if(!o){if(r){s=!0;return}r=!0;try{await or({repoRoot:e.repoRoot}),Wt({type:"state",payload:await Lt({repoRoot:e.repoRoot})})}finally{r=!1,s&&(s=!1,c())}}},u=(p=750)=>{o||(n&&clearTimeout(n),n=setTimeout(()=>{c()},p))},m=()=>{if(o)return;let p=Wn();if(d(p))return ee.error(p.message);let{autoSyncDebounceMs:v}=p.value;i()&&(t=setTimeout(()=>{c(),m()},v??15e3))};return m(),{scheduleSync:u,dispose:()=>{o=!0,t&&clearTimeout(t),n&&clearTimeout(n)}}};import{WebSocketServer as Op}from"ws";var Pe=(e,t)=>{e.send(JSON.stringify(t))},Gn=async(e,t)=>Pe(e,{type:"state",payload:await Lt({repoRoot:t})}),et=async(e,t,n,o,r)=>{if(Pe(e,{type:o,payload:r}),d(r))return Pe(e,{type:"failed",payload:r.message});n(),Gn(e,t)},rc=(e,t,{onStateChanged:n})=>{new Op({server:e,path:"/ws"}).on("connection",r=>{fi(r),r.on("message",async s=>{try{let i=JSON.parse(s.toString()),{type:c}=i;if(c==="state:get")return Gn(r,t);if(c==="sync"){let u=await or({repoRoot:t});return Pe(r,{type:"sync:result",payload:u}),n(),Gn(r,t)}if(c==="issue:comment:add"){let u=await rr({repoRoot:t,...i.payload});return et(r,t,n,"issue:comment:add:result",u)}if(c==="issue:comment:delete"){let u=await sr({repoRoot:t,...i.payload});return Pe(r,{type:"issue:comment:delete:result",payload:u}),d(u)?Pe(r,{type:"failed",payload:u.message}):(n(),Gn(r,t))}if(c==="issue:edit:description"){let u=await Jd({repoRoot:t,...i.payload});return et(r,t,n,"issue:edit:description:result",u)}if(c==="issue:edit:title"){let u=await Qd({repoRoot:t,...i.payload});return et(r,t,n,"issue:edit:title:result",u)}if(c==="issue:tag:add"){let u=await Zd({repoRoot:t,...i.payload});return et(r,t,n,"issue:tag:add:result",u)}if(c==="issue:tag:remove"){let u=await ec({repoRoot:t,...i.payload});return et(r,t,n,"issue:tag:remove:result",u)}if(c==="issue:assignee:add"){let u=await tc({repoRoot:t,...i.payload});return et(r,t,n,"issue:assignee:add:result",u)}if(c==="issue:assignee:remove"){let u=await nc({repoRoot:t,...i.payload});return et(r,t,n,"issue:assignee:remove:result",u)}if(c==="issues:list")return Pe(r,{type:"issues",payload:await Kd({repoRoot:t})});if(c==="issues:create"){let u=await zd({...i.payload,repoRoot:t});return Pe(r,{type:"issues:create:result",payload:u}),d(u)?Wt({type:"failed",payload:u.message}):(Wt({type:"issue:created",payload:u.value}),n(),Gn(r,t))}if(c==="issues:move"){if(!i.payload.position)return Pe(r,{type:"error",message:"Missing move position"});let u=await Xd({...i.payload,repoRoot:t});return et(r,t,n,"issues:move:result",u)}if(c==="issue:close"){if(!i.payload.issueId)return Pe(r,{type:"error",message:"Missing issueId"});let u=await qd({repoRoot:t,issueId:i.payload.issueId});return et(r,t,n,"issue:close:result",u)}if(c==="issue:reopen"){if(!i.payload.issueId)return Pe(r,{type:"error",message:"Missing issueId"});let u=await Yd({repoRoot:t,issueId:i.payload.issueId});return et(r,t,n,"issue:reopen:result",u)}return Pe(r,{type:"error",message:"Unknown message type"})}catch(i){return Pe(r,{type:"error",message:i instanceof Error?i.message:String(i)})}})})};var jp=Zt.dirname(_p(import.meta.url)),Hp=process.env.IS_LOCAL==="true"?Zt.resolve(process.cwd(),"dist/gui"):Zt.join(jp,"gui"),tt=(e,t,n)=>{e.writeHead(t,{"content-type":"application/json"}),e.end(JSON.stringify(n))},Vp=async e=>new Promise((t,n)=>{let o="";e.on("data",r=>{o+=r}),e.on("end",()=>{try{t(o?JSON.parse(o):{})}catch{n(new Error("Invalid JSON body"))}}),e.on("error",n)}),Gp=e=>e.endsWith(".html")?"text/html; charset=utf-8":e.endsWith(".js")?"text/javascript; charset=utf-8":e.endsWith(".css")?"text/css; charset=utf-8":e.endsWith(".json")?"application/json; charset=utf-8":e.endsWith(".ico")?"image/x-icon":"application/octet-stream",sc=async(e,t)=>{let n=e==="/"?"index.html":decodeURIComponent(e).replace(/^\/+/,""),o=Zt.resolve(Hp),r=Zt.resolve(o,n),s=Zt.relative(o,r);if(s.startsWith("..")||Zt.isAbsolute(s))return tt(t,403,{isError:!0,message:"Forbidden"});try{let i=await $p(r);return t.writeHead(200,{"content-type":Gp(r)}),t.end(i)}catch{return tt(t,404,{isError:!0,message:`Not found: ${n}`})}},Kp=async(e,t=3710)=>new Promise((n,o)=>{let r=s=>{let i=u=>{if(e.off("listening",c),u.code==="EADDRINUSE"&&s===t){e.removeListener("error",i),r(0);return}o(u)},c=()=>{e.off("error",i);let u=e.address();if(!u||typeof u=="string"){o(new Error("Unable to resolve address"));return}n(u.port)};e.once("error",i),e.once("listening",c),e.listen(s,"127.0.0.1")};r(t)}),ic=async e=>{let t=Wp.createServer(async(r,s)=>{let i=new URL(r.url??"/","http://127.0.0.1");if(i.pathname==="/api/state")return tt(s,200,await Lt({repoRoot:e.repoRoot}));if(r.method==="POST"&&i.pathname==="/api/comments")try{let c=await Vp(r);if(!c.issueId||!c.body?.trim())return tt(s,400,{isError:!0,message:"Missing issueId or body"});let u=await rr({repoRoot:e.repoRoot,issueId:c.issueId,body:c.body});return"isError"in u&&u.isError?tt(s,400,u):tt(s,200,await Lt({repoRoot:e.repoRoot}))}catch(c){return tt(s,400,{isError:!0,message:c instanceof Error?c.message:"Unable to add comment"})}if(r.method==="DELETE"&&i.pathname.startsWith("/api/comments/")){let c=decodeURIComponent(i.pathname.replace("/api/comments/",""));if(!c)return tt(s,400,{isError:!0,message:"Missing comment id"});let u=await sr({repoRoot:e.repoRoot,commentId:c});return"isError"in u&&u.isError?tt(s,400,u):tt(s,200,await Lt({repoRoot:e.repoRoot}))}return i.pathname.startsWith("/board/")?sc("/",s):sc(i.pathname,s)});try{await Kp(t)}catch(r){return a(r instanceof Error?`Unable to start GUI server: ${r.message}`:`Unable to start GUI server: ${String(r)}`)}let n=oc({repoRoot:e.repoRoot});rc(t,e.repoRoot,{onStateChanged:()=>n.scheduleSync()}),t.on("close",n.dispose);let o=t.address();return!o||typeof o=="string"?(t.close(),a("Unable to resolve GUI server address")):l("Started GUI server",{url:`http://epiq.localhost:${o.port}${e.boardId?`/board/${e.boardId}`:""}`,server:t})};var ac=async e=>{let t=await ic({...e,boardId:""});if(d(t))return t;let{url:n}=t.value;return console.log(`Epiq GUI running at ${zp.cyan(n)}`),Hs(n),l("Started GUI",{url:n})};import{Box as Bt}from"ink";import J from"react";import{Box as As,Text as Kn}from"ink";import We,{useEffect as qp,useMemo as Yp}from"react";import{ulid as Xp}from"ulid";var dc=({text:e,match:t,color:n,highlightColor:o=y.secondary,dimColor:r=!1})=>{if(!t)return We.createElement(Kn,{color:n,dimColor:r},e);let s=e.toLowerCase(),i=t.toLowerCase(),c=s.indexOf(i);return c===-1?We.createElement(Kn,{color:n,dimColor:r},e):We.createElement(Kn,{color:n,dimColor:r},e.slice(0,c),We.createElement(Kn,{backgroundColor:o,bold:!0},e.slice(c,c+t.length)),e.slice(c+t.length))},cc=Xp(),Jp=e=>`${e}`,Qp=e=>{let{pendingNavTarget:t}=wt();if(!t)return[];let{breadCrumb:n,contextNode:o,selectedNode:r}=t,s=new Set(ie(h.NONE,{breadCrumb:n,contextNode:o,readOnly:g().readOnly,selectedNode:r}));return[...new Set(Object.values(h))].filter(i=>i!=="move").filter(i=>i.length>0).filter(i=>i!==h.PALETTE).map(i=>{let c=Uo(i),u=Jo.find(m=>m.intent===c);return{command:i,description:u?.description??`[${i}] Run command`,isAvailable:s.has(i)}}).filter(i=>i.command.toLowerCase().startsWith(e)||e.length>=2&&i.description.toLowerCase().includes(e)).sort((i,c)=>i.isAvailable!==c.isAvailable?i.isAvailable?-1:1:i.command.localeCompare(c.command))},Zp=e=>Y.text({id:cc,parentNodeId:e,rank:"000000",name:"Command Palette",props:{},readonly:!0,isVirtual:!0}),eg=(e,t,n)=>Y.text({id:Jp(e.command),parentNodeId:n,rank:String(t).padStart(6,"0"),name:e.command,props:{value:e.description,disabled:!e.isAvailable},readonly:!0,isVirtual:!0}),ws=[],tg=e=>{lc();let t=I.createNode(Zp(g().rootNodeId));d(t)||!bt(t.value)||(ws=[t.value,...e.map((n,o)=>eg(n,o,cc)).map(I.createNode).filter(Q).map(({value:n})=>n).filter(bt)],T.navigate({contextNode:t.value,selectedIndex:0}))},lc=()=>{let e=ws.map(t=>t.id);ws=[];for(let t of e)I.deleteNode(t)};function uc({width:e,height:t}){let o=Ma().value.trim().toLowerCase(),r=Yp(()=>Qp(o),[o]);qp(()=>(tg(r),()=>{lc()}),[r]);let s=g().selectedIndex;return We.createElement(As,{flexDirection:"column",width:e,height:t-2},We.createElement(Je,{height:t-4,itemHeight:3,selectedIndex:s},r.map((i,c)=>{let u=c===s,m=i.isAvailable?y.accent:y.secondary2,p=i.isAvailable?"":"[unavailable] ";return We.createElement(As,{key:i.command,flexDirection:"column",paddingX:1,borderLeft:!1,borderBottom:!1,borderRight:!1,borderColor:y.secondary,borderStyle:"single"},We.createElement(Kn,{color:m,dimColor:!i.isAvailable},u?"\u276F ":" ",We.createElement(dc,{text:bi(i.command),match:o,color:m,dimColor:!i.isAvailable})),We.createElement(As,{paddingLeft:2},We.createElement(dc,{text:p+i.description,match:o.length>=2?o:"",color:u&&i.isAvailable?y.primary:y.secondary2,dimColor:!i.isAvailable})))})))}import{Box as gg}from"ink";import Ps from"react";import qn from"chalk";import{Box as Ms,Text as mc}from"ink";import zn,{useEffect as ng,useMemo as og,useState as rg}from"react";var pc=qn.gray,sg=qn.inverse,ig=qn.inverse.gray,ag={hint:"",hints:[],overlap:0,remainder:""},fc=({value:e,command:t})=>{if(!t)return null;let n=e.trimStart(),r=e.length-n.length;return e.slice(r,r+t.length)!==t?null:{start:r,end:r+t.length}},dg=({command:e,modifier:t})=>{if(!t)return null;if(e==="tag"||e==="assign"){let n=oe(t);return{bg:o=>qn.bgHex(n).black(o),bgCursor:o=>qn.bgHex(n).inverse.black(o)}}return Wr(t)},cg=({value:e,command:t,modifier:n})=>{if(!t||!n)return null;let o=fc({value:e,command:t});if(!o)return null;let s=e.slice(o.end).match(/^\s*/)?.[0].length??0,i=o.end+s;return e.slice(i,i+n.length)!==n?null:{start:i,end:i+n.length}},gc=()=>({value:ge.value,cursorPosition:ge.cursorPosition,commandIsPending:ge.commandIsPending,autoCompletion:ge.commandMeta.autoCompletion??ag,infoMessage:ge.commandMeta.infoMessage,validationStatus:ge.commandMeta.validity,command:ge.commandMeta.command,inputString:ge.commandMeta.inputString,modifier:ge.commandMeta.modifier}),lg=(e,t)=>e.value===t.value&&e.cursorPosition===t.cursorPosition&&e.commandIsPending===t.commandIsPending&&e.infoMessage===t.infoMessage&&e.autoCompletion.hint===t.autoCompletion.hint&&e.autoCompletion.overlap===t.autoCompletion.overlap&&e.autoCompletion.remainder===t.autoCompletion.remainder&&e.validationStatus===t.validationStatus&&e.command===t.command&&e.modifier===t.modifier&&e.inputString===t.inputString,vc=({width:e,mode:t})=>{let[n,o]=rg(gc());ng(()=>{let C=()=>{let S=gc();o(R=>lg(R,S)?R:S)},E=rs(C);return C(),()=>{E()}},[]);let{value:r,cursorPosition:s,infoMessage:i,commandIsPending:c,autoCompletion:u,command:m,modifier:p}=n,v=og(()=>{let C=Math.max(0,Math.min(s,r.length)),E=fc({value:r,command:m}),S=cg({value:r,command:m,modifier:p}),R=m?Wr(m):null,D=dg({command:m,modifier:p}),P=(le,be)=>{let en=E&&be>=E.start&&be<E.end,Ot=S&&be>=S.start&&be<S.end;return en&&R?R.fg(le):Ot&&D?D.bg(le):le},V=(le,be)=>{let en=E&&be>=E.start&&be<E.end,Ot=S&&be>=S.start&&be<S.end;return en&&R?R.fgCursor(le):Ot&&D?D.bgCursor(le):sg(le)},O=r.slice(0,C),k=r[C]??" ",Ee=C<r.length?r.slice(C+1):"",ft=Array.from(O).map((le,be)=>P(le,be)).join(""),vt=V(k,C),yt=Array.from(Ee).map((le,be)=>P(le,C+1+be)).join("");if(u.hint){let le=u.hint[u.overlap]??k;vt=ig(le),yt=pc(u.remainder.slice(1)+Ee)}return pc(t===f.PALETTE?"?":":")+ft+vt+yt},[r,s,u,m,p]);return zn.createElement(Ms,{flexDirection:"column",justifyContent:"flex-start"},zn.createElement(Ms,{flexDirection:"column",paddingX:1,borderColor:y.secondary,borderStyle:"round",width:e},zn.createElement(Ms,null,zn.createElement(mc,null,v),i&&zn.createElement(mc,{wrap:"truncate",color:c?y.red:y.secondary2},` ${i} `))))};import{Box as ug,Text as mg}from"ink";import yc from"react";var pg=(e,t)=>{let n=[],o=0;for(let r of e){let i=(n.length>0?" | ":"").length+r.length;if(o+i>t-4)break;n.push(r),o+=i}return n},xc=({width:e,availableHints:t})=>{let n=pg(t,e).join(" | ");return yc.createElement(ug,{width:e,borderStyle:"round",borderColor:y.secondary,paddingX:1},yc.createElement(mg,{color:y.secondary2},n.length?n:"\xA0"))};var Yn=({width:e,mode:t,availableHints:n})=>{let o=[],r=0;for(let s of n){let c=(o.length>0?" | ":"").length+s.length;if(r+c>e+2)break;o.push(s),r+=c}return Ps.createElement(gg,null,t===f.COMMAND_LINE||t===f.PALETTE?Ps.createElement(vc,{width:e,mode:t}):Ps.createElement(xc,{width:e,mode:t,availableHints:n}))};import{Box as kt,Text as yn}from"ink";import Ie,{useEffect as fg,useMemo as vg}from"react";import{ulid as hc}from"ulid";var ar=hc(),yg=()=>[...new Set([...g().availableActions].map(e=>e.description).filter(e=>e!==void 0))].map(e=>{let[t,n]=e.split("]"),o=t?.replace("[",""),r=n?.trim();return[o,r]}).filter(e=>e[0]!==void 0&&e[1]!==void 0).sort(([e],[t])=>e.length===1&&t.length!==1?-1:e.length!==1&&t.length===1?1:e.localeCompare(t,void 0,{sensitivity:"base"})).map(([e,t])=>({keys:e,action:t})),xg=e=>Y.text({id:ar,parentNodeId:e,rank:"000000",name:"Help",props:{},isVirtual:!0,readonly:!0}),hg=(e,t,n)=>Y.text({id:hc(),parentNodeId:n,rank:String(t).padStart(6,"0"),name:e.keys,props:{value:e.action},readonly:!0,isVirtual:!0}),ir=[],Ic=()=>{let e=ir.filter(n=>n.id!==ar).map(n=>n.id),t=ir.filter(n=>n.id===ar).map(n=>n.id);ir=[];for(let n of[...e,...t])I.deleteNode(n)},Ig=e=>{Ic();let t=I.createNode(xg(g().rootNodeId));if(d(t)||!bt(t.value))return logger.error("Could not attach help nodes");ir=[t.value,...e.map((n,o)=>hg(n,o,ar)).map(I.createNode).filter(Q).map(({value:n})=>n).filter(bt)],T.navigate({contextNode:t.value,selectedIndex:0})},bc=({width:e,height:t})=>{let n=vg(()=>yg(),[]);fg(()=>(Ig(n),()=>{Ic()}),[n]);let o=g().selectedIndex;return Ie.createElement(kt,{flexDirection:"column",marginTop:3,borderColor:y.secondary,borderStyle:"round",width:e,height:t-2},Ie.createElement(kt,{paddingX:1,justifyContent:"center"},Ie.createElement(yn,{color:y.accent},"Help"),Ie.createElement(yn,{dimColor:!0}," \u2014 navigate with arrows/hjkl, press q to close")),Ie.createElement(kt,{paddingX:1,marginTop:1},Ie.createElement(kt,{width:20,justifyContent:"flex-end"},Ie.createElement(yn,{color:y.secondary},"Key(s)")),Ie.createElement(kt,{flexGrow:1,width:40,paddingLeft:2},Ie.createElement(yn,{color:y.secondary},"Action"))),Ie.createElement(Je,{height:t-7,itemHeight:1,selectedIndex:o},n.map(({keys:r,action:s},i)=>{let c=i===o;return Ie.createElement(kt,{paddingX:1,key:`${r}-${s}-${i}`,flexDirection:"row"},Ie.createElement(kt,{width:20,justifyContent:"flex-end"},Ie.createElement(yn,{color:y.accent},r)),Ie.createElement(kt,{flexGrow:1,width:40,paddingLeft:2},Ie.createElement(yn,{color:c?y.primary:y.secondary2},s)))})))};import bg from"chalk";import{Box as dr,Text as gt}from"ink";import Le from"react";var Cc=({width:e,height:t})=>Le.createElement(dr,{height:t-4,flexDirection:"column",width:e,paddingTop:1,paddingLeft:2,borderStyle:"round",borderColor:y.secondary,rowGap:1},Le.createElement(gt,{color:y.accent,bold:!0},"Initialize project"),Le.createElement(gt,null,`This folder is not an ${bg.hex(y.accent)("epiq")} project yet.`),Le.createElement(gt,{color:y.primary},"To start tracking issues here, we need to initialize a new",Le.createElement(gt,{color:y.primary,backgroundColor:y.secondary}," .epiq/project.json "),"file in this repository."),Le.createElement(dr,{marginTop:1,flexDirection:"column"},Le.createElement(dr,null,Le.createElement(gt,{color:y.accent}," "),Le.createElement(gt,{color:y.primary},"Type "),Le.createElement(gt,{backgroundColor:y.secondary}," :init "))),Le.createElement(dr,{marginTop:1},Le.createElement(gt,{color:y.secondary2},"This will create, commit and push "),Le.createElement(gt,{color:y.primary,backgroundColor:y.secondary}," .epiq/project.json ")));import{Box as cr,Text as nt}from"ink";import ce from"react";var Cg=({isDone:e,command:t,value:n})=>ce.createElement(cr,null,ce.createElement(nt,{color:y.accent,dimColor:e},e?" \u2714 ":" "),ce.createElement(nt,{dimColor:e},"Type "),ce.createElement(nt,{backgroundColor:y.secondary,dimColor:e}," "+t+" "),n!==void 0&&ce.createElement(ce.Fragment,null,ce.createElement(nt,{dimColor:e}," "),ce.createElement(nt,{color:y.secondary,dimColor:e},"<"+n+">"))),Ng=e=>{if(typeof e=="string")return e;if(typeof e=="boolean")return e?"on":"off"};function Ls({width:e,height:t}){let{isSetPreferredEditor:n,isSetUserName:o,userName:r,preferredEditor:s,autoSync:i,isSetAutoSync:c}=St(),u=[{key:"username",done:o,command:":config username",value:r,message:"First, choose your username."},{key:"editor",done:n,command:":config editor",value:s,message:"Nice. Now pick your editor."},{key:"autosync",done:c,command:":config autosync",value:i,message:"Almost there. Configure auto sync."}],m=u.findIndex(v=>!v.done),p=m===-1?void 0:u[m];return ce.createElement(cr,{height:t-4,flexDirection:"column",width:e,paddingTop:1,paddingLeft:2,borderStyle:"round",borderColor:y.secondary,rowGap:1},ce.createElement(nt,{color:y.accent,bold:!0},"Welcome! \u{1F539}"),ce.createElement(nt,null,"Let's get you started - it's a breeze."),ce.createElement(nt,{color:y.secondary2},"Remember - you can always search available commands by typing:",ce.createElement(nt,{color:y.accent}," ? ")),p&&ce.createElement(nt,{color:y.secondary2},p.message),ce.createElement(cr,{flexDirection:"column"},u.map((v,C)=>m===-1||C<=m?ce.createElement(cr,{key:v.key,marginBottom:1},ce.createElement(Cg,{isDone:v.done,command:v.command,value:v.done?Ng(v.value):void 0})):null)))}import gr from"chalk";import{Box as pr,Text as Jn}from"ink";import ye from"react";import{Box as lr,Text as Nc}from"ink";import Dt from"react";var Sg=e=>(I.getTag(e)?.name??"").length+3,Eg=e=>(I.getContributor(e)?.name??"").length+3,Sc=({width:e})=>{let{viewMode:t}=_(),n=K(),{breadCrumb:o,contextNode:r,selectedIndex:s,renderedChildrenIndex:i}=n,c=i[r.id]?.[s],u=it(c?.id??r.id,"TICKET"),m=Q(u)?u.value:void 0,p=m?.props.tags??[],v=m?.props.assignees??[],C=m?.parentNodeId?!Ur(r.id,m.parentNodeId)&&t==="dense":!1,E=o.map((k,Ee)=>{let ft=Ee===o.length-1,vt=j(k.id),yt=ft?vt?.[s]?.title:void 0;return`${Ee?" / ":""}${k.title??""}${yt?` \u25B8 ${yt}`:""}`}).join(""),S=m?I.getCommentsByIssue(m.id):[],R=S.length?String(S.length).length+11:0,D=C?p.reduce((k,Ee)=>k+Sg(Ee),0)+v.reduce((k,Ee)=>k+Eg(Ee),0)+R:0,P=Math.max(0,e-D),V=E.substring(0,P),O=C?[...p.map(k=>Dt.createElement(lr,{key:`tag-${k}`,paddingLeft:1},Dt.createElement(fn,{id:k}))),...v.map(k=>Dt.createElement(lr,{key:`assignee-${k}`,paddingLeft:1},Dt.createElement(Rt,{id:k}))),S.length?Dt.createElement(lr,{key:"comments",paddingLeft:1},Dt.createElement(Nc,{color:y.accent},"[",S.length," comment",S.length===1?"":"s","]")):null]:[];return Dt.createElement(lr,{overflow:"hidden",justifyContent:"flex-start",alignItems:"flex-start"},Dt.createElement(Nc,{color:y.secondary2},V),O)};import{Box as Rg,Text as Ec}from"ink";import ur from"react";var Tg=({filters:e})=>ur.createElement(Rg,{columnGap:1},ur.createElement(Ec,{color:"red"},"APPLIED FILTERS:"),e.map(({value:t,target:n,operator:o})=>ur.createElement(Ec,{backgroundColor:"black",color:"white"},` ${n}${o}"${t}" `))),Rc=ur.memo(Tg);import{Box as Ag,Text as mr}from"ink";import Xn from"react";function Tc(){let{eventLog:e,unappliedEvents:t}=K(),n=e.at(-1)?.id,o=bo(n??""),r=Q(o)?Di(o.value):"INVALID DATE";return Xn.createElement(Ag,{paddingLeft:1},Xn.createElement(mr,{backgroundColor:y.accent}," Readonly "),Xn.createElement(mr,{color:y.accent}," "+t.length+" edits ago at "+r+"."),Xn.createElement(mr,{color:y.accent}," Resume with "),Xn.createElement(mr,{backgroundColor:y.accent}," :peek now "))}import ks from"chalk";import{Box as wg,Text as Ac}from"ink";import Ds,{useEffect as Mg,useState as Pg}from"react";var Lg=["#4c567a","#9d7cd8","#7aa2f7","#7dcfff","#9d7cd8"],wc=e=>{let t=e.replace("#","");return{r:parseInt(t.slice(0,2),16),g:parseInt(t.slice(2,4),16),b:parseInt(t.slice(4,6),16)}},kg=({r:e,g:t,b:n})=>{let o=r=>Math.round(Math.max(0,Math.min(255,r))).toString(16).padStart(2,"0");return`#${o(e)}${o(t)}${o(n)}`},Dg=(e,t,n)=>{let o=wc(e),r=wc(t);return kg({r:o.r+(r.r-o.r)*n,g:o.g+(r.g-o.g)*n,b:o.b+(r.b-o.b)*n})},Fg=(e,t)=>{if(e.length===1)return e[0];let n=t*(e.length-1),o=Math.floor(n),r=n-o,s=e[o],i=e[Math.min(o+1,e.length-1)];return Dg(s,i,r)};function Mc({syncStatus:e,autoSync:t}){let[n,o]=Pg(0);Mg(()=>{if(e.status!=="syncing"){o(0);return}let c=setInterval(()=>{o(u=>u+1)},50);return()=>clearInterval(c)},[e.status]);let r={synced:" ",failed:"---",syncing:"...",pending:"idle"},i={synced:y.secondary2,failed:y.yellow,pending:y.secondary2,syncing:Fg(Lg,(Math.sin(n*.12)+1)/2)??""}[e.status];return Ds.createElement(wg,null,Ds.createElement(Ac,null,ks.hex(y.secondary2).dim(t?"Sync (auto): ":"Sync: ")),Ds.createElement(Ac,null,ks.hex(i)("\u25CF")+ks.hex(y.secondary2).dim(` ${r[e.status].padEnd(4)} `)))}import Fc from"chalk";import{Text as Bc}from"ink";import Uc,{useEffect as $g,useState as Wg}from"react";var xn="0.7.1";import Fs from"chalk";var Bg="https://registry.npmjs.org/epiq/latest",Bs=null,Pc=0,Ug=1e3*60*60*24,Lc=e=>e.replace(/^v/,""),Og=(e,t)=>{let n=Lc(e).split(".").map(Number),o=Lc(t).split(".").map(Number);for(let r=0;r<Math.max(n.length,o.length);r++){let s=n[r]??0,i=o[r]??0;if(s>i)return 1;if(s<i)return-1}return 0},kc=async e=>{if(process.env.IS_CI==="true")return{current:"1.2.3",latest:"1.2.3",updateAvailable:!1};if(Bs&&Date.now()-Pc<Ug)return Bs;try{let t=await fetch(Bg);if(!t.ok)throw new Error(`Failed to fetch latest version: ${t.status}`);let o=(await t.json()).version??null,r={current:e,latest:o,updateAvailable:o?Og(o,e)>0:!1};return Bs=r,Pc=Date.now(),r}catch{return{current:e,latest:null,updateAvailable:!1}}},Dc=(e,t)=>{let n=e.split("."),o=t.split("."),r=o.findIndex((s,i)=>s!=n[i]);return o.map((s,i)=>i>=r?Fs.hex(y.accent).dim(s):Fs.hex(y.secondary).dim(s)).join(Fs.hex(y.secondary2).dim("."))};function Oc(){let[e,t]=Wg({current:xn,latest:null,updateAvailable:!1});return $g(()=>{let n=!0;return kc(xn).then(o=>{n&&t(o)}),()=>{n=!1}},[]),!e.updateAvailable||!e.latest?Uc.createElement(Bc,{dimColor:!0,color:y.secondary2},xn+" "):Uc.createElement(Bc,null,Fc.hex(y.secondary2).dim(xn),Fc.hex(y.accent).dim(" \u2197 "),Dc(xn,e.latest))}function Qn({filters:e,hideBreadCrumb:t=!1}){let{timeMode:n,syncStatus:o,mode:r}=K(),{userName:s,preferredEditor:i,autoSync:c}=_(),u=64,m=process.stdout.columns-u-8;return ye.createElement(pr,{justifyContent:"space-between",flexDirection:"row","max-width":process.stdout.columns-40,overflow:"hidden"},t?ye.createElement(Jn,null," "):r===f.PALETTE?ye.createElement(pr,null,ye.createElement(Jn,{color:y.accent},"Command Palette"),ye.createElement(Jn,{dimColor:!0,color:y.secondary2}," ","- search, select and press enter")):ye.createElement(pr,{paddingLeft:1},e.length>0?ye.createElement(Rc,{filters:e}):ye.createElement(Sc,{width:m})),n==="live"?ye.createElement(pr,{columnGap:1,paddingRight:2,"max-width":u,overflow:"hidden",justifyContent:"flex-end"},ye.createElement(Mc,{autoSync:!!c,syncStatus:o}),ye.createElement(Jn,null,gr.hex(y.secondary2).dim("Mode: ")+gr.hex(y.secondary2).dim(r.padEnd(8," "))," "),ye.createElement($c,{icon:"@",value:s}),ye.createElement($c,{icon:"\u276F",value:i}),ye.createElement(Oc,null)):"",n==="peek"?ye.createElement(Tc,null):"")}function $c({icon:e,value:t}){return ye.createElement(Jn,null,gr.dim(e)+gr.hex(y.accent)(` ${t??"-"} `))}import{Box as _g,Text as jg}from"ink";import Zn from"react";import{Box as fr,Text as Us}from"ink";import Ft from"react";function Os(){let e=K(),t=e.nodes[e.rootNodeId],r=process.stdout.rows-1-3,s=process.stdout.columns||120,i=t?.id?W(t?.id):[];return Ft.createElement(fr,{flexDirection:"column",height:r,padding:1,borderStyle:"round",borderColor:y.secondary,width:s},Ft.createElement(fr,{padding:1,paddingTop:0,paddingBottom:0},Ft.createElement(Us,null,"Select a board:")),Ft.createElement(fr,{padding:1,flexDirection:"column"},i.map((c,u)=>{let m=e.contextNode.context==="WORKSPACE"&&e.selectedIndex===u,v=W(c.id).flatMap(({id:C})=>j(C)).length;return Ft.createElement(fr,{key:c.id??u},Ft.createElement(Us,{color:m?y.accent:y.secondary2},Ft.createElement(he,{isSelected:m})),Ft.createElement(Us,{color:m?y.accent:y.secondary2},c.title," (",v," issues)",c.readonly?" \u{1F512}":""))})))}var Hg=({contextNode:e,selectedIndex:t,breadCrumb:n,mode:o,viewMode:r,height:s,width:i})=>{let{renderedChildrenIndex:c}=K(),u=n.find(({context:C})=>C==="BOARD"),v=s-1-3;return Zn.createElement(_g,{flexDirection:"row"},e.context==="WORKSPACE"?Zn.createElement(Os,null):u?Zn.createElement(Vo,{height:v,width:i,swimlanes:(c[u.id]??[]).filter(C=>C!==void 0&&Ct(C)),contextNode:e,selectedIndex:t,breadCrumb:n,viewMode:r,mode:o}):Zn.createElement(jg,null))},Wc=Zn.memo(Hg);import{useEffect as Vg}from"react";var Gg=e=>{Vg(()=>{if(!e)return;let t,n=!1,o=()=>{if(n)return;let{autoSyncIntervalMs:r,userName:s,preferredEditor:i}=_();i&&s&&r&&(t=setTimeout(()=>{if(n)return;let{readOnly:c,mode:u}=g();u==="default"&&!c&&Mo(),o()},r))};return o(),()=>{n=!0,t&&clearTimeout(t)}},[e])},_c=({autoSync:e})=>(Gg(e),null);function $s({width:e,height:t}){let n=K(),{autoSync:o,viewMode:r}=Ti(),s=n.filters;if(n.mode===f.HELP)return J.createElement(Bt,{flexDirection:"column"},J.createElement(bc,{width:e,height:t}));if(n.mode===f.PALETTE)return J.createElement(Bt,{flexDirection:"column"},J.createElement(Qn,{filters:s}),J.createElement(uc,{width:e,height:t-2}),J.createElement(Yn,{width:e,mode:n.mode,availableHints:n.availableHints}));let{isSetupDone:i}=St(),c=!i,u=i&&!n.hasProjectDefinition;if(c)return J.createElement(Bt,{flexDirection:"column"},J.createElement(Bt,{flexDirection:"column"},J.createElement(Qn,{hideBreadCrumb:!0,filters:s}),J.createElement(Ls,{height:t,width:e})),J.createElement(Yn,{width:e,mode:n.mode,availableHints:n.availableHints}));if(u)return J.createElement(Bt,{flexDirection:"column"},J.createElement(Bt,{flexDirection:"column"},J.createElement(Qn,{hideBreadCrumb:!0,filters:s}),J.createElement(Cc,{height:t,width:e})),J.createElement(Yn,{width:e,mode:n.mode,availableHints:n.availableHints}));let m=Se(n.breadCrumb??[],"BOARD");if(Q(m)){let p=m.value.id,v=W(p).length,C=3,E=Math.floor(e/C),S=Math.floor(e/Math.max(v,1));e=Math.min(S,E)*Math.max(v,C)}return J.createElement(Bt,{flexDirection:"column"},J.createElement(_c,{autoSync:o}),J.createElement(Bt,{flexDirection:"column"},J.createElement(Qn,{filters:s}),J.createElement(Wc,{width:e,height:t,contextNode:n.contextNode,selectedIndex:n.selectedIndex,breadCrumb:n.breadCrumb,viewMode:r??"dense",mode:n.mode})),J.createElement(Yn,{width:e,mode:n.mode,availableHints:n.availableHints}))}import Kg from"readline";var vr,yr,ot,zg=new Set([x.MoveCursorLeft,x.EraseInputWord,x.MoveCursorLeftOfWord,x.MoveCursorRight,x.MoveCursorRightOfWord,x.NavToPreviousContainer,x.NavToNextContainer,x.NavPreviousItem,x.NavNextItem,x.SetViewDense,x.SetViewWide,x.Confirm,x.Exit,x.InitCommandLine,x.InitCommandPalette,x.ExitCommandLine,x.CaptureInput,x.EraseInput,x.EraseInputWord,x.HideHelp,x.ViewHelp,x.SetViewDense,x.SetViewWide,x.GetLastCommandFromHistory,x.GetNextCommandFromHistory,x.AutoCompleteCommand]),jc=async e=>{if(e.ctrl&&e.name==="c")return T.exit();let{actionIndex:t,mode:n,readOnly:o}=g(),r=La(e,n);if(!r||o&&!zg.has(r))return;let s=t[n]?.[r];if(s?.action)try{await s.action(s,e)}catch(i){logger.error(i)}},qg=()=>async function(t,n){n.name!=="escape"&&(ot&&(clearTimeout(ot),ot=void 0),await jc(n))},Yg=()=>async function(t){if(t.length===1&&t[0]===27){ot&&clearTimeout(ot),ot=setTimeout(()=>{jc({name:"escape",ctrl:!1,meta:!1,shift:!1,sequence:"\x1B"}),ot=void 0},25);return}ot&&(clearTimeout(ot),ot=void 0)};function Hc(){vr&&process.stdin.removeListener("keypress",vr),yr&&process.stdin.removeListener("data",yr),vr=qg(),yr=Yg(),Kg.emitKeypressEvents(process.stdin),process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.on("data",yr),process.stdin.on("keypress",vr)}async function Vc(){try{let e=_n();Q(e)&&Fe(e.value);let t=_e(process.cwd()),n=[];if(Q(t)){let s=Oe({repoRoot:t.value});if(d(s))return zt(3,s.message);let i=tn(),c=await $t({repoRoot:t.value,stateBranchRoot:s.value,stateBranchName:i.stateBranch});if(d(c))return zt(3,c.message);let u=await B({cwd:s.value,args:["pull","--ff-only"]});d(u)&&logger.info(3,u.message);let m=at(s.value);if(d(m))return zt(3,m.message);n=m.value}let o=Kt(n);if(d(o))return zt(4,o.message);N({hasProjectDefinition:Q(t),hasInitializingEvents:!!n.length});let r=Ws();return d(r)?zt(6,r.message):(Hc(),l("Booted Epiq",void 0))}catch(e){return zt(0,To(e))}}id();var Zg=`${Ut.bold("Epiq CLI")}
|
|
57
|
+
`));let Ot=ze();if(d(Ot))return z(16,Ot.message);let{rootNodeId:zc,nodes:qc}=Ot.value,_s=qc[zc];return _s?(T.navigate({contextNode:_s,selectedIndex:0}),N({hasProjectDefinition:!0,mode:f.DEFAULT}),l(vt,null)):z(16,"Unable to resolve initialized root node")};import{ulid as xp}from"ulid";import{ulid as yp}from"ulid";var pd=null,Pt=()=>structuredClone(pd),jn=e=>{pd=e},gd=()=>{let{contextNode:e,selectedIndex:t}=g(),o=j(e.id)[t];return o?l("Resolved selected child",o):a("Target node not found")},hs=({id:e,parentId:t,position:n={at:"end"}})=>{let o=j(t).filter(r=>r.id!==e);return Eo(o,n)},fd=({id:e,parentId:t,position:n={at:"end"}})=>{let o=X();if(d(o))return a("Unable to resolve user ID");let r=hs({parentId:t,id:e,position:n});return d(r)?r:l("Created pending move state",{id:yp(),...o.value,action:"move.node",payload:{id:e,parent:t,rank:r.value.rank}})},vd=e=>{jn(e);let t=Pn(e,!0);return d(t)?t:l("Node moved successfully",t.value)};function Is(e){let t=gd();if(d(t))return t;let{contextNode:n,nodes:o}=g();if(!n.parentNodeId)return a("Missing parent node id");let r=o[n.parentNodeId];if(!r)return a("Missing parent node");let s=j(r.id),i=s.findIndex(({id:m})=>m===n.id);if(i<0)return a("Current node not found among siblings");let c=s[i+e];if(!c)return a("Missing sibling node");let u=fd({id:t.value.id,parentId:c.id,position:{at:"end"}});return d(u)?u:vd(u.value)}function bs(e){let t=gd();if(d(t))return t;let{contextNode:n,selectedIndex:o}=g(),s=j(n.id)[o+e];if(!s)return a("Missing sibling node");let i=fd({id:t.value.id,parentId:n.id,position:{at:e===1?"after":"before",sibling:s.id}});return d(i)?i:vd(i.value)}var yd=()=>{let e=Pt();if(!e)return a("No pending move state");let t=e.payload.id,n=e.payload.parent,o=g().nodes[n];if(!o)return a("Move parent not found");let r=j(n).findIndex(s=>s.id===t);return r===-1?a("Moved node not found among rendered children"):(T.navigate({contextNode:o,selectedIndex:r}),l("Synchronized navigation to moved node",null))},qo=(e,t="Moved preview")=>{if(d(e))return e;let n=yd();return d(n)?n:(N({mode:f.MOVE}),l(t,null))},xd=async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{modifier:t}=q().commandMeta,{contextNode:n,selectedIndex:o}=g(),r=j(n.id)[o];if(!r)return N({mode:f.DEFAULT}),a("No move target");if(t==="start"){if(r.readonly)return a("Target node is read-only");if(o===-1)return a("No item selected");if(!r.parentNodeId)return a("Target has no parent");let s=j(r.parentNodeId),i=s.findIndex(({id:v})=>v===r.id);if(i===-1)return a("Target not found among siblings");let c=s[i-1],u=s[i+1],m=u!=null?{at:"before",sibling:u.id}:c!=null?{at:"after",sibling:c.id}:{at:"start"},p=hs({parentId:r.parentNodeId,id:r.id,position:m});return d(p)?p:(jn({id:xp(),action:"move.node",payload:{id:r.id,parent:r.parentNodeId,rank:p.value.rank},...e.value}),N({mode:f.MOVE}),l("Move initialized",null))}if(t==="next")return qo(bs(1));if(t==="previous")return qo(bs(-1));if(t==="to-next")return qo(Is(1));if(t==="to-previous")return qo(Is(-1));if(t==="confirm"){let s=Pt();if(!s)return a("No pending move to confirm");let i=await je();if(d(i))return i;let c=F([s],i.value);if(d(c))return c;let u=yd();return d(u)?u:(jn(null),N({mode:f.DEFAULT}),l("Moved item",null))}return t==="cancel"?(jn(null),N({mode:f.DEFAULT}),l("Cancelling move",null)):a("Invalid move modifier")};import{ulid as Xo}from"ulid";import{monotonicFactory as hp,ulid as Ip}from"ulid";var bp=hp(),Yo=({name:e,parent:t,rank:n,user:{userId:o,userName:r}})=>{let s=bp();return l("Created issue events",[{id:Ip(),userId:o,userName:r,action:"add.issue",payload:{id:s,parent:t,name:e,rank:n}}])};var hd=async(e,t)=>{let n=X();if(d(n))return a("Unable to resolve user ID");let o=await je();if(d(o))return o;let r=o.value;if(!t.inputString)return a(`provide a name for your ${t.modifier}`);let{breadCrumb:s,contextNode:i,selectedIndex:c}=g(),u=m=>{let p=F([m],r);if(d(p))return p;let v=I.getNode(p.value[0].result.id);if(!v)return a("Created node not found");if(!v.parentNodeId)return p;let C=I.getNode(v.parentNodeId);return C?(T.navigate({contextNode:C,selectedIndex:I.getSiblings(v.parentNodeId).findIndex(({id:E})=>E===v.id)}),p):a("Parent node not found")};if(t.modifier==="board"){let{rootNodeId:m}=g(),p=I.getNode(m);if(!p)return a("Workspace not found");let v=cn(p.id,n.value,r);return d(v)?v:u({id:Xo(),action:"add.board",payload:{id:Xo(),name:t.inputString,parent:p.id,rank:v.value},...n.value})}if(t.modifier==="swimlane"){let m=Se(s,"BOARD");if(d(m))return a("Unable to add swimlane in this context");let p=cn(m.value.id,n.value,r);return d(p)?p:u({id:Xo(),action:"add.swimlane",payload:{id:Xo(),name:t.inputString,parent:m.value.id,rank:p.value},...n.value})}if(t.modifier==="issue"){let m=W(i.id)[c],p=i.context==="SWIMLANE"?i:i.context==="BOARD"&&m?.context==="SWIMLANE"?m:(()=>{let V=Se(s,"SWIMLANE");return d(V)?null:V.value})();if(!p)return a("Unable to add issue in this context");let v=cn(p.id,n.value,r);if(d(v))return v;let C=Yo({name:t.inputString,parent:p.id,rank:v.value,user:n.value});if(d(C))return C;let E=C.value,S=F([...E],r);if(d(S))return S;if(!S.value[0])return a("Issue creation failed");let P=E.find(V=>V.action==="add.issue")?.payload.id;return P?(T.navigate({contextNode:p,selectedIndex:I.getSiblings(p.id).findIndex(({id:V})=>V===P)}),l("Issue created",null)):a("Unable to determine ticket id")}return l("Success",null)};var Id=async()=>{let e=Se(g().breadCrumb,"BOARD");if(d(e))return e;let t=await ht(process.cwd());if(d(t))return a("Unable to locate repo root");let n=Oe({repoRoot:t.value});if(d(n))throw new Error(n.message);let{modifier:o}=q().commandMeta;if(o==="now"){let S=at(n.value);if(d(S))return a(S.message);let R=Hn();if(d(R))return R;let P=Ht(S.value).filter(d);return P.length>0?a(P.map(V=>V.message).join(", ")):(N({mode:f.DEFAULT,readOnly:!1,timeMode:"live",unappliedEvents:[]}),l("Peeking now",!0))}let r;if(o==="prev"){let S=g().eventLog.at(-1),R=_r(S);if(R===null)return a("No previous event to peek");r=R}else if(o==="next"){let S=g().unappliedEvents.at(0),R=_r(S);if(R===null)return a("No next event to peek");r=R+1}else{let S=ko(o);if(!S)return a("Invalid peek date");r=S.getTime()}let s=g(),i=e.value.id,c=Wi(n.value,r);if(d(c))return a(c.message);let{appliedEvents:u,unappliedEvents:m}=c.value,p=Hn();if(d(p))return p;let C=Ht(u).filter(d);if(C.length>0)return Hn(),N(s),a(C.map(S=>S.message).join(", "));let E=g().nodes[i];return E?(T.navigate({contextNode:E,selectedIndex:0}),N({mode:f.DEFAULT,readOnly:!0,timeMode:"peek",unappliedEvents:m}),l("Peeking",!0)):(Hn(),N(s),a("Board did not exist at peek date"))};import Cp from"zod";var bd=()=>{let e=q().commandMeta.inputString,t=Cp.coerce.number().int().min(3e3).safeParse(e);if(!t.success)return a("Auto sync duration must be a number of at least 3000 ms");let n=mt({autoSyncDebounceMs:t.data});return d(n)?n:(Fe({autoSyncIntervalMs:t.data}),N({mode:f.DEFAULT}),l(`Auto sync interval set to ${t.data}ms`,null))};var Cd=()=>{let e=q().commandMeta.inputString.trim();if(e!=="on"&&e!=="off")return a("Invalid response");let t=la(e),n=mt({autoSync:t});return d(n)?n:(Fe({autoSync:t}),N({mode:f.DEFAULT}),l(`Auto sync set to "${e}"`,null))};var Nd=()=>{let e=q().commandMeta.inputString.trim();if(!["debug","error","info"].includes(e))return a("Invalid response");let n=mt({logLevel:e});return d(n)?n:(Fe({logLevel:e}),N({mode:f.DEFAULT}),l(`Auto sync set to "${e}"`,null))};var Sd=async()=>{$(""),N({mode:f.DEFAULT});let e=ze();if(d(e))return a(e.message);if(e.value.syncStatus.status==="syncing")return a("Sync already in progress");N({syncStatus:{msg:"Syncing",status:"syncing"}});let t=await Ao();return d(t)?(N({syncStatus:{msg:t.message,status:"failed"}}),t):(N({mode:f.DEFAULT,syncStatus:{msg:"Synced",status:"synced"}}),t)};var Np=e=>e.action==="add.issue.comment",Ed=e=>Object.values(g().tags).find(t=>t.name===e),Rd=e=>Object.values(g().contributors).find(t=>t.name===e),pt=async()=>{let e=await je();return d(e)?e:l("Resolved persist root",e.value)},Jo=[{systemOnly:!0,intent:M.Move,description:"Internal move-state command",mode:f.COMMAND_LINE,action:xd},{intent:M.Delete,description:"Delete the currently selected node",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{contextNode:t,selectedIndex:n}=g(),o=W(t.id)[n];if(!o)return a("Unable to resolve child to delete");let r=await pt();if(d(r))return r;if(o.context==="COMMENT"){let s=o.id,i=A(t)?t.id:t.parentNodeId;if(!i)return a("Unable to resolve comment issue");let c=g().nodes[i];if(!c||!A(c))return a("Unable to resolve comment issue");let u=c.log?.filter(Np).find(m=>m.payload.id===s);return u?u.payload.author!==e.value.userId?a("You can only delete your own comments"):F([{id:fe(),action:"delete.issue.comment",payload:{id:s,issue:i},...e.value}],r.value):a("Unable to resolve comment")}return F([{id:fe(),action:"delete.node",payload:{id:o.id},...e.value}],r.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Filter,description:"Filter the board, for example `:filter tag urgent`",mode:f.COMMAND_LINE,action:()=>{let{modifier:e,inputString:t}=q().commandMeta,n=/(!=|=)/,[o]=e.split(n);if(!o||!(i=>ie(h.FILTER).map(c=>c.split(n)[0]).includes(i))(o))return a("Invalid filter modifier");let s={target:o,operator:"=",value:t.trim()};return ue(i=>({...i,filters:e==="clear"?[]:[...i.filters,s],mode:f.DEFAULT})),l("Filter updated",null)}},{intent:M.ViewHelp,description:"Open the help screen",mode:f.COMMAND_LINE,action:()=>{let{contextNode:e,selectedIndex:t,selectedNode:n,breadCrumb:o}=g();return Mt({pendingNavTarget:{contextNode:e,breadCrumb:o,selectedIndex:t,selectedNode:n}}),N({mode:f.HELP}),l("Viewing help",null)}},{intent:M.CloseIssue,description:"Move the selected issue to the closed swimlane",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{contextNode:t,selectedIndex:n}=g(),o=W(t.id)[n];if(!o)return a("Unable to close issue, no target found");if(!A(o))return a("Cannot close in this context");let r=g().nodes[de];if(!r)return a("Unable to locate closed swimlane");if(o.parentNodeId===r.id)return a("Issue is already closed");let s=await pt();if(d(s))return s;let i=s.value,c=Gt(r.id,o.id,{at:"end"},e.value,i);if(d(c))return c;let u=F([{id:fe(),action:"close.issue",payload:{id:o.id,parent:r.id,rank:c.value},...e.value}],i);return d(u)?u:l("Issue closed",null)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.ReopenIssue,description:"Move a closed issue back to its previous swimlane",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{contextNode:t,selectedIndex:n}=g(),o=W(t.id)[n];if(!o)return a("Unable to reopen issue, no target found");let r=o.context==="TICKET"?l("Resolved ticket",o):it(o.id,"TICKET");if(d(r))return a("Cannot reopen in this context");let s=r.value,i=g().nodes[de];if(!i)return a("Unable to locate closed swimlane");if(s.parentNodeId!==i.id)return a("Issue is not closed");if(!A(s))return a("Target node is not issue");let c=Ko(s);if(!c)return a("Unable to resolve previous parent from issue history");if(c===i.id)return a("Previous parent resolves to closed swimlane");let u=g().nodes[c];if(!u)return a("Previous parent no longer exists");let m=await pt();if(d(m))return m;let p=m.value,v=Gt(u.id,s.id,{at:"end"},e.value,p);if(d(v))return v;let C=F([{id:fe(),action:"reopen.issue",payload:{id:s.id,parent:u.id,rank:v.value},...e.value}],p);return d(C)?C:l("Issue reopened",null)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Init,description:"Initialize Epiq in the current git repository",mode:f.COMMAND_LINE,action:md},{intent:M.NewItem,description:"Create a new board, swimlane, or issue",mode:f.COMMAND_LINE,action:hd,onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Rename,description:"itle] Rename the currently selected node",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{contextNode:t,selectedIndex:n}=g(),o=W(t.id)[n];if(!o)return a("Missing node");if(o.readonly)return a("Cannot rename readonly node");let r=Pa();if(!r)return a("Provide a title");let s=await pt();return d(s)?s:F([{id:fe(),action:"edit.title",payload:{id:o.id,name:r},...e.value}],s.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.UntagTicket,description:"Remove a tag from the selected issue",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{modifier:t,inputString:n}=q().commandMeta,o=(t||n).trim();if(!o)return a("Provide a tag");let r=Ed(o);if(!r)return a(`Tag "${o}" does not exist`);let{selectedNode:s}=g();if(!s)return a("Invalid untag target");let i=it(s.id,"TICKET");if(d(i))return a("Unable to untag issue in this context");let c=i.value;if(!A(c))return a("Target node is not issue");if(!(c.props.tags??[]).includes(r.id))return a("Issue is not tagged with that tag");let m=await pt();return d(m)?m:F([{id:fe(),action:"remove.issue.tag",payload:{id:c.id,tag:r.id},...e.value}],m.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.TagTicket,description:"Add or create a tag on the selected issue",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{modifier:t,inputString:n}=q().commandMeta,o=(t||n).trim();if(!o)return a("Provide a tag");let{selectedNode:r}=g();if(!r)return a("Invalid tag target");let s=it(r.id,"TICKET");if(d(s))return a("Unable to tag issue in this context");let i=s.value;if(!A(i))return a("Target node is not issue");let c=await pt();if(d(c))return c;let u=Ed(o),m=u?.id??fe();return(i.props.tags??[]).includes(m)?a("Already tagged with that tag"):F([...u?[]:[{id:fe(),action:"create.tag",payload:{id:m,name:o},...e.value}],{id:fe(),action:"add.issue.tag",payload:{id:i.id,tag:m},...e.value}],c.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.AssignUserToTicket,description:"Assign a user to the selected issue",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{modifier:t,inputString:n}=q().commandMeta,o=(t||n).trim();if(!o)return a("Provide an assignee");let{selectedIndex:r,contextNode:s}=g(),i=W(s.id)[r];if(!i)return a("Invalid assign target");let c=it(i.id,"TICKET");if(d(c))return a("Unable to assign issue in this context");let u=c.value;if(!A(u))return a("Target node is not issue");let m=await pt();if(d(m))return m;let p=Rd(o),v=p?.id??fe();return(u.props.assignees??[]).includes(v)?a("Assignee already assigned"):F([...p?[]:[{id:fe(),action:"create.contributor",payload:{id:v,name:o},...e.value}],{id:fe(),action:"add.issue.assignee",payload:{id:u.id,assignee:v},...e.value}],m.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.UnassignUserFromTicket,description:"Remove an assignee from the selected issue",mode:f.COMMAND_LINE,action:async()=>{let e=X();if(d(e))return a("Unable to resolve user ID");let{modifier:t,inputString:n}=q().commandMeta,o=(t||n).trim();if(!o)return a("Provide an assignee to remove");let r=Rd(o);if(!r)return a(`Assignee "${o}" does not exist`);let{selectedNode:s}=g();if(!s)return a("Invalid unassign target");let i=it(s.id,"TICKET");if(d(i))return a("Unable to unassign in this context");let c=i.value;if(!A(c))return a("Target node is not issue");if(!(c.props.assignees??[]).includes(r.id))return a(`Issue is not assigned to "${o}"`);let m=await pt();return d(m)?m:F([{id:fe(),action:"remove.issue.assignee",payload:{id:c.id,assignee:r.id},...e.value}],m.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Comment,description:"Add a comment to the selected issue",mode:f.COMMAND_LINE,action:async(e,t)=>{let n=t.inputString.trim();if(!n)return a("Provide a comment");if(n.length>mn)return a(`Cannot exceed ${mn} characters`);let o=X();if(d(o))return a("Unable to resolve user ID");let{breadCrumb:r,selectedNode:s}=g(),i=Se([...r,s],"TICKET");if(d(i))return a("Edit target must be an issue");let c=i.value;if(!c)return a("Invalid comment target");let u=c.context==="TICKET"?l("Resolved ticket",c):it(c.id,"TICKET");if(d(u))return a("Unable to comment on issue in this context");let m=u.value;if(!A(m))return a("Target node is not issue");let p=await pt();return d(p)?p:F([{id:fe(),action:"add.issue.comment",payload:{id:fe(),issue:m.id,author:o.value.userId,md:n},...o.value}],p.value)},onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Sync,description:"Pull, commit, and push Epiq state",mode:f.COMMAND_LINE,action:Sd},{intent:M.Peek,description:"View board state at another point in time",mode:f.COMMAND_LINE,action:Id},{intent:M.Export,description:"Export the current board layout to markdown",mode:f.COMMAND_LINE,action:async()=>{let e=await Ja();return d(e)?e:(N({mode:f.DEFAULT}),l("Export successful",!0))}},{intent:M.Exit,description:"Exit the application",mode:f.COMMAND_LINE,action:async()=>(T.exit(),l("Exit successful",!0))},{intent:M.Edit,description:"Edit title or description",mode:f.COMMAND_LINE,action:async(e,t)=>cd(t),onSuccess:()=>N({mode:f.DEFAULT})},{intent:M.Config,description:"Update editor, username, view, autosync, or sync debounce",mode:f.COMMAND_LINE,action:(e,t)=>{let n=t.inputString.trim();switch(t.modifier){case re.USERNAME:{let{userId:o,preferredEditor:r,userName:s}=_(),i=n||s,c=o??fe();if(!i||!c)return a("Unable to resolve user name or id");let u=mt({userName:i,userId:c,preferredEditor:r??""});return d(u)?u:(Fe({userName:i,userId:c}),N({mode:f.DEFAULT}),l(`Username set to "${i}"`,null))}case re.EDITOR:{if(!n)return a("No editor provided");let o=mt({preferredEditor:n});return d(o)?o:(Fe({preferredEditor:n}),N({mode:f.DEFAULT}),l(`Editor configuration set to "${n}"`,null))}case re.VIEW:return n!=="wide"&&n!=="dense"?a("Invalid view mode"):(Fe({viewMode:n}),l(`View set to "${n}"`,null));case re.AUTOSYNC:return Cd();case re.LOG_LEVEL:return Nd();case re.SYNC_DEBOUNCE_MS:return bd();default:return a("Unknown config command")}}},{intent:M.Coffee,description:"Sponsor the development of Epiq!",mode:f.COMMAND_LINE,action:()=>{let e=q().commandMeta.modifier;return e==="custom"?vs("https://github.com/sponsors/ljtn?frequency=one-time&sponsor=ljtn"):vs(`https://github.com/sponsors/ljtn/sponsorships?sponsor=ljtn&preview=true&frequency=one-time&amount=${e}`),$(""),l("Thanks you!",null)}}];var Sp=new Set(["peek","filter","view-help"]),Ze=async({isForceExecutedBySystem:e=!1}={})=>{let{commandMeta:{command:t,validity:n,modifier:o,inputString:r}}=q();if(!t)return a("No command to confirm");if(!e&&n===Et.Invalid)return a("Invalid command");let s=Uo(t);Ra();let{readOnly:i}=g();if(i&&!Sp.has(s))return Bn({status:xt.Fail,message:"Command not available in readonly state",value:null});let c=Jo.filter(m=>e||m.systemOnly!==!0).find(m=>m.intent===s);if(!c)return Bn({status:xt.Fail,message:"Command not found",value:null});let u;try{u=await c.action(c,{command:t,inputString:r,modifier:o})}catch(m){return Bn({status:xt.Fail,message:m instanceof Error?m.message:"Command failed",value:null})}return d(u)?Bn(u):(Ta({addToHistory:!e}),c.onSuccess?.(),_().autoSync&&Mo(),u)};var Qo=[{intent:x.Exit,mode:f.MOVE,description:"[<Esc>] exit context / cancel",action:()=>(N({mode:f.COMMAND_LINE}),$("move cancel"),Ze({isForceExecutedBySystem:!0}))},{intent:x.InitMove,mode:f.DEFAULT,description:"[m] move (init/confirm)",action:()=>(N({mode:f.COMMAND_LINE}),$("move start"),Ze({isForceExecutedBySystem:!0}))},{intent:x.ConfirmMove,mode:f.MOVE,action:()=>(N({mode:f.COMMAND_LINE}),$("move confirm"),Ze({isForceExecutedBySystem:!0}))}],Zo=[{intent:x.MovePreviousItem,mode:f.MOVE,action:()=>Pt()?(N({mode:f.COMMAND_LINE}),$("move previous"),Ze({isForceExecutedBySystem:!0})):a("No pending move")},{intent:x.MoveNextItem,mode:f.MOVE,action:()=>Pt()?(N({mode:f.COMMAND_LINE}),$("move next"),Ze({isForceExecutedBySystem:!0})):a("No pending move")}],Td=[{intent:x.MoveToNextContainer,mode:f.MOVE,action:()=>Pt()?(N({mode:f.COMMAND_LINE}),$("move to-next"),Ze({isForceExecutedBySystem:!0})):a("No pending move")},{intent:x.MoveToPreviousContainer,mode:f.MOVE,action:()=>Pt()?(N({mode:f.COMMAND_LINE}),$("move to-previous"),Ze({isForceExecutedBySystem:!0})):a("No pending move")}];var Ad={[w.WORKSPACE]:[...Qo,...Zo],[w.BOARD]:[...Qo,...Zo],[w.SWIMLANE]:[...Qo,...Zo,...Td],[w.TICKET]:[],[w.FIELD]:[],[w.FIELD_LIST]:[],[w.TEXT]:[],[w.COMMENT]:[]};var wd=()=>{$("");let{pendingNavTarget:e}=wt();N({mode:f.DEFAULT}),e&&T.navigate(e),Mt({pendingNavTarget:void 0})},Md=[{intent:x.ExitCommandLine,mode:f.HELP,action:()=>(wd(),l("Exiting help",null))},{intent:x.Exit,mode:f.HELP,action:()=>(wd(),l("Closed help",null))},{intent:x.NavPreviousItem,mode:f.HELP,description:"[arrows/hjkl] navigate",action:()=>(T.navigateToPreviousItem(),l("Navigating to previous help item",null))},{intent:x.NavNextItem,mode:f.HELP,action:()=>(T.navigateToNextItem(),l("Navigating to next help item",null))},{intent:x.NavToPreviousContainer,mode:f.HELP,action:()=>(T.navigateToPreviousContainer(),l("Navigating to previous help container",null))},{intent:x.NavToNextContainer,mode:f.HELP,action:()=>(T.navigateToNextContainer(),l("Navigating to next help container",null))}];var Ep=e=>{N({mode:f.COMMAND_LINE});let{pendingNavTarget:t}=wt();t&&T.navigate(t),Mt({pendingNavTarget:void 0}),$(`${e} `)},Pd=()=>{$("");let{pendingNavTarget:e}=wt();e&&T.navigate(e),Mt({pendingNavTarget:void 0}),N({mode:f.DEFAULT})},Ld=[{intent:x.InitCommandPalette,mode:f.DEFAULT,description:"[?] view command palette (explore descriptions for every command)",action:()=>{$("");let{contextNode:e,selectedIndex:t,selectedNode:n,breadCrumb:o}=g();return Mt({pendingNavTarget:{contextNode:e,selectedIndex:t,selectedNode:n,breadCrumb:o}}),N({mode:f.PALETTE}),l("Opening command palette",null)}},{intent:x.Confirm,mode:f.PALETTE,action:()=>{let{selectedNode:e}=g();if(!e||!bt(e))return a("Command only applicable on text nodes");if(e.props.disabled)return a("Command is not available in this context");let t=e.title;return t?(Ep(t),l("Selected command",t)):l("No command selected",null)}},{intent:x.ExitCommandLine,mode:f.PALETTE,action:()=>(Pd(),l("Exiting palette",null))},{intent:x.Exit,mode:f.PALETTE,action:()=>(Pd(),l("Closed command palette",null))},{intent:x.NavPreviousItem,mode:f.PALETTE,description:"[arrows/hjkl] navigate",action:()=>(T.navigateToPreviousItem(),l("Navigating to previous item",null))},{intent:x.NavNextItem,mode:f.PALETTE,action:()=>(T.navigateToNextItem(),l("Navigating to next item",null))},{intent:x.NavToPreviousContainer,mode:f.PALETTE,action:()=>(T.navigateToPreviousContainer(),l("Navigating to previous container",null))},{intent:x.NavToNextContainer,mode:f.PALETTE,action:()=>(T.navigateToNextContainer(),l("Navigating to next container",null))}];var kd=[...Md,...Ld,{intent:x.AddItem,mode:f.DEFAULT,description:"[n] new...",action:()=>(N({mode:f.COMMAND_LINE}),$(`${h.NEW} `),l("Adding new item",null))},{intent:x.Delete,mode:f.DEFAULT,description:"[d] delete",action:()=>(N({mode:f.COMMAND_LINE}),$(`${h.DELETE} `),l("Deleting item",null))},{intent:x.InitCommandLine,mode:f.DEFAULT,description:"[:] focus command line",action:()=>(N({mode:f.COMMAND_LINE}),$(""),l("Entering command line mode",null))},{intent:x.Confirm,mode:f.DEFAULT,description:"[<Enter>] confirm/enter",action:()=>{let{selectedNode:e,contextNode:t}=g();if(!j(e?.id??"")?.length){if(e?.title===ne.DESCRIPTION)return N({mode:f.COMMAND_LINE}),$(`${h.EDIT} description `),l("Propose command",!0);if(e?.title===ne.ASSIGNEES)return N({mode:f.COMMAND_LINE}),$(`${h.ASSIGN} `),l("Propose command",!0);if(e?.title===ne.TAGS)return N({mode:f.COMMAND_LINE}),$(`${h.TAG} `),l("Propose command",!0);if(t.title===ne.DESCRIPTION&&e?.context==="TEXT")return N({mode:f.COMMAND_LINE}),$(`${h.EDIT} description `),l("Propose command",!0)}return T.enterChildNode(),l("Entering context",null)}},{intent:x.EditTitle,mode:f.DEFAULT,description:"[r] rename title",action:()=>(N({mode:f.COMMAND_LINE}),$(`${h.EDIT} title ${g().selectedNode?.title}`),l("Exiting context",null))},{intent:x.EditDescription,mode:f.DEFAULT,description:"[e] edit description",action:()=>(N({mode:f.COMMAND_LINE}),$(`${h.EDIT} description `),l("Exiting context",null))},{intent:x.Exit,mode:f.DEFAULT,description:"[q] exit context",action:()=>(T.enterParentNode(),l("Exiting context",null))},{intent:x.NavPreviousItem,mode:f.DEFAULT,description:"[arrows/hjkl] navigate",action:()=>(T.navigateToPreviousItem(),l("Navigating to previous item",null))},{intent:x.NavNextItem,mode:f.DEFAULT,action:()=>(T.navigateToNextItem(),l("Navigating to next item",null))},{intent:x.NavToPreviousContainer,mode:f.DEFAULT,action:()=>(T.navigateToPreviousContainer(),l("Navigating to previous container",null))},{intent:x.NavToNextContainer,mode:f.DEFAULT,action:()=>(T.navigateToNextContainer(),l("Navigating to next container",null))}];var Rp=500,Tp=e=>e.replace(/[\r\n]/g,"").replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g,""),Dd=e=>{let t=Tp(e);t&&pn(n=>(n+t).slice(0,Rp))};var Ap=[f.COMMAND_LINE,f.PALETTE],wp=e=>[{intent:x.MoveCursorLeft,mode:e,action:()=>(ss(-1),l("Moving cursor left",null))},{intent:x.MoveCursorRight,mode:e,action:()=>(ss(1),l("Moving cursor right",null))},{intent:x.MoveCursorLeftOfWord,mode:e,action:()=>(is("left"),l("Moving cursor left of word",null))},{intent:x.MoveCursorRightOfWord,mode:e,action:()=>(is("right"),l("Moving cursor right of word",null))},{intent:x.AutoCompleteCommand,mode:e,action:()=>(pn((t,{remainder:n})=>{let o=n?t+n:t,r="";return o==="edit title "&&(r=g().selectedNode?.title??""),o+r}),l("Auto-completing command",null))},{intent:x.CaptureInput,mode:e,action:(t,{sequence:n})=>(Dd(n??""),l("Capturing input",null))},{intent:x.EraseInput,mode:e,action:()=>(Sa(),l("Erasing input",null))},{intent:x.EraseInputWord,mode:e,action:()=>(Ea(),l("Erasing input word",null))}],Fd=[{intent:x.Confirm,mode:f.COMMAND_LINE,action:()=>(Ze(),l("Executing command",null))},{intent:x.ViewHelp,mode:f.DEFAULT,action:()=>(N({mode:f.HELP}),l("Viewing help",null))},...Ap.flatMap(wp),{intent:x.ExitCommandLine,mode:f.COMMAND_LINE,action:()=>(N({mode:f.DEFAULT}),l("Exiting command line",null))},{intent:x.GetLastCommandFromHistory,mode:f.COMMAND_LINE,action:()=>(Aa(),l("Getting last command from history",null))},{intent:x.GetNextCommandFromHistory,mode:f.COMMAND_LINE,action:()=>(wa(),l("Getting next command from history",null))}];import Od from"chalk";var er=Od.dim.hex(y.secondary2)(": for command line"),Bd="q to exit",Ud=`${Od.hex(y.accent)("m")} to confirm`,Cs={[w.WORKSPACE]:[er],[w.BOARD]:[er],[w.BOARD+f.COMMAND_LINE]:[er],[w.SWIMLANE]:[er],[w.TICKET+f.HELP]:[Bd],[w.SWIMLANE+f.HELP]:[Bd],[w.TICKET]:[],[w.FIELD]:[],[w.SWIMLANE+f.MOVE]:[Ud],[w.TICKET+f.MOVE]:[Ud]};var Vn=e=>e.trim().toLocaleLowerCase(),Mp=e=>{let{tags:t}=g();return(e.props.tags??[]).map(n=>t[n]?.name).filter(n=>!!n)},Pp=e=>{let{contributors:t}=g();return(e.props.assignees??[]).map(n=>t[n]?.name).filter(n=>!!n)},$d=(e,t)=>{let n=Vn(t.value);if(!n)return!0;switch(t.target){case"title":return Vn(e.title??"").includes(n);case"description":return Vn(e.props.description??"").includes(n);case"tag":return Mp(e).map(Vn).some(r=>r.includes(n));case"assignee":return Pp(e).map(Vn).some(r=>r.includes(n));default:return!0}};function Wd(e,t,n){let o=t[e];if(!o)return a("buildBreadCrumb(): current node not found");let r=[],s=o;for(;s&&(r.push(s),!(s.id===n||!s.parentNodeId));)s=t[s.parentNodeId];let i=r[r.length-1];return!i||i.id!==n?a("buildBreadCrumb(): node is not connected to root"):(r.reverse(),l("Breadcrumb built",r))}var _d=e=>{let t={};for(let n of e)n.intent&&(t[n.mode]||(t[n.mode]={}),t[n.mode][n.intent]=n);return t};var Qt,Ns,Ss=new Set,jd=()=>{for(let e of Ss)e()},kp=e=>(Ss.add(e),()=>Ss.delete(e));function Hd(e){let{contextNodeId:t,mode:n,rootNodeId:o,nodes:r,filters:s}=e;if(!t)return a("derive(): contextNodeId is missing");if(!o)return a("derive(): rootNode is missing");if(!r[o])return a("derive(): unable to find root node");let c=r[t];if(!c)return a("Unable to derive state, contextNode not found");let u=Wd(t,r,o);if(d(u))return logger.error(u.message),u;let m=u.value,{context:p}=c,v=Cs[p+n]??Cs[p]??[],C=[...kd,...Ad[p]??[],...Fd],E=_d(C),S=Dp(r,s),R=S[t]?.[e.selectedIndex]??null;return l("Derived successfully",{...e,contextNode:c,breadCrumb:m,availableHints:v,availableActions:C,actionIndex:E,selectedNode:R,renderedChildrenIndex:S})}var g=()=>{if(!Qt)throw new Error("State not initialized. Call initWorkspaceState() first.");return Qt},ze=()=>Qt?l("Retrieved state",Qt):a("State not initialized. Call initWorkspaceState() first.");function Ln(e){Ns=e;let t=_e(process.cwd()),n=!1;if(!d(t)){let s=It(t.value);if(d(s))return a(s.message);n=!0}let o={readOnly:!1,filters:[],tags:{},contributors:{},mode:f.DEFAULT,nodes:{[e.id]:e},rootNodeId:e.id,contextNodeId:e.id,renderedChildrenIndex:{},selectedIndex:-1,syncStatus:{status:"synced",msg:""},eventLog:[],unappliedEvents:[],timeMode:"live",hasProjectDefinition:n,hasInitializingEvents:!1,comments:{}},r=Hd(o);return d(r)?r:(Qt=r.value,jd(),l("State initialized",null))}function ue(e){let t=g(),n=e(t),o=Hd(n);return d(o)?a(o.message??"Unable to update state"):(Qt=o.value,jd(),l("State updated",null))}var N=e=>ue(t=>({...t,...e}));var K=()=>Lp(kp,g,g),Dp=(e,t)=>{let n={};for(let o of Object.values(e))A(o)&&t.length>0&&!t.every(r=>$d(o,r))||!o.parentNodeId||o.isDeleted||((!o.parentNodeId||!n[o.parentNodeId])&&(n[o.parentNodeId]=[]),n[o.parentNodeId].push(o));for(let o of Object.keys(n))n[o].sort((r,s)=>{let i=e[r.id],c=e[s.id];return!i||!c?0:i.rank.localeCompare(c.rank)});return n},W=e=>g()?.renderedChildrenIndex[e]??[],Hn=()=>Ns?Ln(Ns):a("Cannot reset state: no initial workspace found"),un=()=>Qt!==void 0;var Es=e=>{un()&&(N({syncStatus:e}),Wt({type:"sync-status",payload:e}))},tr=(e="Syncing...")=>{Es({status:"syncing",msg:e})},nr=(e="Synced")=>{Es({status:"synced",msg:e})},Rs=e=>{Es({status:"failed",msg:e})},Ue=e=>(Rs(e),a(e));import{decodeTime as FA}from"ulid";var Fp=async({cwd:e,ensureUpstream:t})=>{logger.debug("[sync] ensureSyncReady:start",{cwd:e,ensureUpstream:t});let n=G("getRepoRootDir",await ht(e));if(d(n))return a(n.message);let o=n.value;logger.debug("[sync] repo root",o);let r=G("getStateBranchRoot",Oe({repoRoot:o}));if(d(r))return a(r.message);let s=r.value;logger.debug("[sync] state branch root",s);let i=G("ensureInitialCommit",await mi(o));if(d(i))return a(i.message);logger.debug("[sync] initial commit result",{created:i.value}),logger.debug("[sync] bootstrapping state branch storage",{repoRoot:o,stateBranchRoot:s,ensureUpstream:t});let c=G("bootstrapStateBranchStorage",await gi({repoRoot:o,stateBranchRoot:s,ensureUpstream:t}));if(d(c))return a(c.message);logger.debug("[sync] bootstrap result",{bootstrapped:c.value,stateBranchRoot:s}),logger.debug("[sync] checking state branch git operation",{stateBranchRoot:s});let u=G("hasInProgressGitOperation(stateBranchRoot)",await io(s));if(d(u))return a(u.message);if(logger.debug("[sync] state branch git operation check result",{inProgress:u.value}),u.value)return logger.info("[sync] state branch git operation in progress"),a("Cannot sync while a git operation is in progress in the state branch");logger.debug("[sync] ensuring state branch layout",{repoRoot:o,stateBranchRoot:s});let m=G("ensureStateBranchLayout",ci(o,s));return d(m)?a(m.message):(logger.debug("[sync] state branch layout ready"),logger.debug("[sync] ensureSyncReady:done",{repoRoot:o,stateBranchRoot:s,bootstrapped:c.value}),l("Sync preconditions satisfied",{repoRoot:o,stateBranchRoot:s,bootstrapped:c.value}))},Bp=async({repoRoot:e,stateBranchRoot:t,ownEventFileName:n})=>{logger.debug("[sync] committing own event file from state branch",{ownEventFileName:n,stateBranchRoot:t}),logger.debug("[sync] staging own event file",{stateBranchRoot:t,ownEventFileName:n});let o=G("stageStateBranchOwnEventFile",await po({stateBranchRoot:t,eventFileName:n}));if(d(o))return a(o.message);let r=G("hasStagedChanges(after stage)",await oi(t));if(d(r))return a(r.message);if(logger.debug("[sync] state branch change check after stage result",{changed:r.value}),!r.value)return logger.info("[sync] no own event file changes to commit"),l("No own event file changes to commit",{createdCommit:!1});logger.debug("[sync] creating sync commit");let s=G("createStateBranchSyncCommit",await pi({repoRoot:e,stateBranchRoot:t}));return d(s)?a(s.message):(logger.debug("[sync] created sync commit",s.value),l("Committed own event file",{createdCommit:!0,commitSha:s.value}))},wo=async({cwd:e=process.cwd(),ownEventFileName:t})=>{if(logger.debug("[sync] syncEpiqWithRemote:start",{cwd:e,ownEventFileName:t}),t.includes("/")||t.includes("\\"))return logger.error("[sync] invalid own event file name: contains path separator",{ownEventFileName:t}),a("Own event file must be a file name, not a path");if(!t.endsWith(".jsonl"))return logger.error("[sync] invalid own event file name: missing .jsonl suffix",{ownEventFileName:t}),a("Own event file must end with .jsonl");tr();let n=G("ensureSyncReady",await Fp({cwd:e,ensureUpstream:!0}));if(d(n))return Ue(n.message);let{repoRoot:o,stateBranchRoot:r,bootstrapped:s}=n.value,i=G("isDetachedHead(stateBranchRoot)",await ri(r));if(d(i))return Ue(i.message);if(logger.debug("[sync] detached state branch check result",{detached:i.value}),i.value)return Ue("Cannot run :sync while the state branch is in detached HEAD state");let c=!1,u,m=!1,p=!1,v=G("getStateBranch",nn(o));if(d(v))return Ue(v.message);let C=v.value;logger.debug("[sync] resolved state branch",{stateBranch:C,stateBranchRoot:r});let E=G("commitOwnEventFileToStateBranch",await Bp({repoRoot:o,stateBranchRoot:r,ownEventFileName:t}));if(d(E))return Ue(E.message);c=E.value.createdCommit,u=E.value.commitSha;let S=G("pullBranchRebaseIfPresent",await Mr({cwd:r,branch:C}));if(d(S))return Ue(S.message);if(m=S.value,c||s){logger.info("[sync] pushing state branch",{createdCommit:c,bootstrapped:s,stateBranchRoot:r});let R=G("pushStateBranch",await Rn({stateBranchRoot:r,repoRoot:o}));if(d(R)&&ni(R.message)){let D=G("pullBranchRebaseIfPresent(retry)",await Mr({cwd:r,branch:C}));if(d(D))return Ue(D.message);m=m||D.value,R=G("pushStateBranch(retry)",await Rn({stateBranchRoot:r,repoRoot:o}))}if(d(R))return Ue(R.message);p=R.value}if(c){logger.debug("[sync] resolving final sync commit sha",{stateBranchRoot:r});let R=G("git rev-parse HEAD",await B({args:["rev-parse","HEAD"],cwd:r}));if(d(R))return Ue(R.message);u=R.value.stdout.trim(),logger.debug("[sync] final sync commit sha",u)}return nr(p?"Synced and pushed":m||c?"Synced local state":"Already synced"),logger.debug("[sync] syncEpiqWithRemote:done"),l("Synced event logs with state branch",{repoRoot:o,stateBranchRoot:r,createdCommit:c,commitSha:u,pulled:m,pushed:p,bootstrapped:s})};var Ts=e=>{let t=_e(e??process.cwd());return d(t)?a(t.message):l("Resolved Epiq repo root",t.value)},we=async e=>{let t=Ts(e);if(d(t))return t;let n=Oe({repoRoot:t.value});if(d(n))return a(n.message);let o=tn(),r=await $t({repoRoot:t.value,stateBranchRoot:n.value,stateBranchName:o.stateBranch});if(d(r))return a(r.message);let s=await B({cwd:n.value,args:["pull","--ff-only"]});d(s)&&ee.info(3,s.message);let i=at(n.value);if(d(i))return a(i.message);let c=Kt(i.value);return d(c)?a(c.message):l("Booted Epiq state",{repoRoot:t.value,stateBranchRoot:n.value})},Me=()=>{let e=_n();return d(e)?a(e.message):e.value.userId?e.value.userName?l("Resolved actor",{userId:e.value.userId,userName:e.value.userName}):a("Unable to retrieve user name"):a("Unable to retrieve user id")},$e=()=>{let e=ze();return d(e)?a(e.message):e},Vd=e=>(e.props.tags??[]).map(t=>I.getTag(t)).filter(t=>t!=null).map(t=>({id:t.id,name:t.name,color:oe(t.name)})),Gd=e=>(e.props.assignees??[]).map(t=>I.getContributor(t)).filter(t=>t!=null).map(t=>({id:t.id,name:t.name,color:oe(t.name)}));var Kd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=$e();if(d(n))return n;let o=Object.values(n.value.nodes).filter(A).filter(r=>e.includeClosed||r.parentNodeId!==de).map(r=>({id:r.id,title:Nt(r.title),description:r.props.description??"",parentNodeId:r.parentNodeId,isClosed:r.parentNodeId===de,readonly:!!r.readonly,tags:Vd(r),assignees:Gd(r)}));return l("Listed issues",o)},zd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=cn(e.parentId,n.value,t.value.stateBranchRoot);if(d(o))return o;let r=Yo({name:e.title,parent:e.parentId,user:n.value,rank:o.value});if(d(r))return r;let s=r.value,i=F([...s],t.value.stateBranchRoot);if(d(i))return a(i.message);let c=s.find(u=>u.action==="add.issue")?.payload.id;return c?l("Created issue",{id:c,title:e.title,parentId:e.parentId}):a("Unable to determine created issue id")},qd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=Gt(de,e.issueId,{at:"end"},n.value,t.value.stateBranchRoot);if(d(o))return o;let r={id:ve(),...n.value,action:"close.issue",payload:{id:e.issueId,parent:de,rank:o.value}},s=F([r],t.value.stateBranchRoot);return d(s)?a(s.message):l("Closed issue",{id:e.issueId})},Yd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Target node is not issue");if(r.parentNodeId!==de)return a("Issue is not closed");let s=Ko(r);if(!s)return a("Unable to resolve previous parent from issue history");if(s===de)return a("Previous parent resolves to closed swimlane");let i=o.value.nodes[s];if(!i)return a("Previous parent no longer exists");let c=Gt(i.id,r.id,{at:"end"},n.value,t.value.stateBranchRoot);if(d(c))return c;let u={id:ve(),...n.value,action:"reopen.issue",payload:{id:r.id,parent:i.id,rank:c.value}},m=F([u],t.value.stateBranchRoot);return d(m)?a(m.message):l("Reopened issue",{id:r.id,parentId:i.id})},Xd=async e=>{let t=Ts(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=Oe({repoRoot:t.value});if(d(o))return o;let r=at(o.value);if(d(r))return r;let s=Kt(r.value);if(d(s))return s;let i=Gt(e.parentId,e.issueId,e.position??{at:"end"},n.value,o.value);if(d(i))return i;let c={id:ve(),...n.value,action:"move.node",payload:{id:e.issueId,parent:e.parentId,rank:i.value}},u=F([c],o.value);return d(u)?a(u.message):l("Moved issue",{id:e.issueId,parentId:e.parentId})},or=async(e={})=>{tr();let t=Ts(e.repoRoot);if(d(t))return a("Sync failed");let n=Me();if(d(n))return n;let o=await wo({cwd:t.value,ownEventFileName:Vt(n.value)});return d(o)?(Rs(o.message),o):(nr(),l("Synced",o.value))};var Lt=async(e={})=>{let t=await we(e.repoRoot);if(d(t))return t;let n=$e();if(d(n))return n;let o=Object.values(n.value.nodes),r=o.filter(m=>fo(m)&&!m.isDeleted),s=new Map,i=new Map;for(let m of o)if(!m.isDeleted){if(Ct(m)&&m.parentNodeId){let p=s.get(m.parentNodeId)??[];p.push(m),s.set(m.parentNodeId,p)}if(A(m)&&m.parentNodeId){let p=i.get(m.parentNodeId)??[];p.push(m),i.set(m.parentNodeId,p)}}let c=_n();if(d(c))return c;let u={};for(let m of o.filter(A))m.isDeleted||(u[m.id]=I.getCommentsByIssue(m.id).map(p=>{let v=I.getContributor(p.authorId);return{id:p.id,issueId:p.issue,body:p.md,author:{id:p.authorId,name:v?.name??"Unknown",color:oe(v?.name??p.authorId)},createdAt:Up(p.id)}}));return l("Retrieved Epiq GUI state",{boards:r.sort((m,p)=>m.rank.localeCompare(p.rank)).map(m=>({id:m.id,title:m.title,swimlanes:(s.get(m.id)??[]).sort((p,v)=>p.rank.localeCompare(v.rank)).map(p=>({id:p.id,title:p.title,readonly:!!p.readonly,issues:(i.get(p.id)??[]).sort((v,C)=>v.rank.localeCompare(C.rank)).map(v=>({id:v.id,title:Nt(v.title),description:v.props.description??"",readonly:!!v.readonly,tags:Vd(v),assignees:Gd(v),parentNodeId:v.parentNodeId,isClosed:v.parentNodeId===de})),parentNodeId:p.parentNodeId}))})),tags:Object.values(n.value.tags).map(m=>({...m,color:oe(m.name)})),contributors:Object.values(n.value.contributors).map(m=>({...m,color:oe(m.name)})),user:{name:c.value.userName??"",id:c.value.userId??"",color:oe(c.value.userName??"")},commentsByIssueId:u})},Jd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Edit target must be an issue");if(r.readonly)return a("Cannot edit readonly issue");let s=r.props.description??"";if(s===e.description)return l("No changes made",{id:e.issueId,description:s});let i={id:ve(),...n.value,action:"edit.description",payload:{id:e.issueId,md:e.description}},c=F([i],t.value.stateBranchRoot);return d(c)?a(c.message):l("Edited issue description",{id:e.issueId,description:e.description})},Qd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Edit target must be an issue");if(r.readonly)return a("Cannot edit readonly issue");let s=Nt(e.title);if(!s.trim())return a("Issue title cannot be empty");if(r.title===s)return l("No changes made",{id:e.issueId,title:s});let i={id:ve(),...n.value,action:"edit.title",payload:{id:e.issueId,name:s}},c=F([i],t.value.stateBranchRoot);return d(c)?a(c.message):l("Edited issue title",{id:e.issueId,title:s})},Zd=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Tag target must be an issue");if(r.readonly)return a("Cannot tag readonly issue");let s=Nt(e.tagName).trim();if(!s)return a("Tag name cannot be empty");let i=Object.values(o.value.tags).find(p=>p.name===s),c=i?.id??ve(),u=[...i?[]:[{id:ve(),...n.value,action:"create.tag",payload:{id:c,name:s}}],{id:ve(),...n.value,action:"add.issue.tag",payload:{id:e.issueId,tag:c}}],m=F(u,t.value.stateBranchRoot);return d(m)?a(m.message):l("Added issue tag",{id:e.issueId,tag:{id:c,name:s}})},ec=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Untag target must be an issue");if(r.readonly)return a("Cannot untag readonly issue");if(!o.value.tags[e.tagId])return a("Tag not found");let s={id:ve(),...n.value,action:"remove.issue.tag",payload:{id:e.issueId,tag:e.tagId}},i=F([s],t.value.stateBranchRoot);return d(i)?a(i.message):l("Removed issue tag",{id:e.issueId,tagId:e.tagId})},tc=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Assign target must be an issue");if(r.readonly)return a("Cannot assign readonly issue");let s=Nt(e.assigneeName).trim();if(!s)return a("Assignee name cannot be empty");let i=Object.values(o.value.contributors).find(p=>p.name===s),c=i?.id??ve(),u=[...i?[]:[{id:ve(),...n.value,action:"create.contributor",payload:{id:c,name:s}}],{id:ve(),...n.value,action:"add.issue.assignee",payload:{id:e.issueId,assignee:c}}],m=F(u,t.value.stateBranchRoot);return d(m)?a(m.message):l("Added issue assignee",{id:e.issueId,assignee:{id:c,name:s}})},nc=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Unassign target must be an issue");if(r.readonly)return a("Cannot unassign readonly issue");if(!o.value.contributors[e.assigneeId])return a("Assignee not found");let s={id:ve(),...n.value,action:"remove.issue.assignee",payload:{id:e.issueId,assignee:e.assigneeId}},i=F([s],t.value.stateBranchRoot);return d(i)?a(i.message):l("Removed issue assignee",{id:e.issueId,assigneeId:e.assigneeId})},rr=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.nodes[e.issueId];if(!r)return a("Issue not found");if(!A(r))return a("Comment target must be an issue");if(r.readonly)return a("Cannot comment on readonly issue");let s=e.body.trim();if(!s)return a("Comment cannot be empty");let i=ve(),c={id:ve(),...n.value,action:"add.issue.comment",payload:{id:i,issue:e.issueId,md:s,author:n.value.userId}},u=F([c],t.value.stateBranchRoot);return d(u)?a(u.message):l("Added issue comment",{id:i,issueId:e.issueId,body:s})},sr=async e=>{let t=await we(e.repoRoot);if(d(t))return t;let n=Me();if(d(n))return n;let o=$e();if(d(o))return o;let r=o.value.eventLog.find(m=>m.action==="add.issue.comment"&&m.payload.id===e.commentId);if(!r)return a("Unable to resolve comment");if(r.payload.author!==n.value.userId)return a("You can only delete your own comments");let s=o.value.nodes[r.payload.issue];if(!s)return a("Issue not found");if(!A(s))return a("Comment target must be an issue");if(s.readonly)return a("Cannot delete comment on readonly issue");if(o.value.eventLog.some(m=>m.action==="delete.issue.comment"&&m.payload.id===e.commentId))return l("Comment already deleted",{id:e.commentId,issueId:r.payload.issue});let c={id:ve(),...n.value,action:"delete.issue.comment",payload:{id:e.commentId,issue:r.payload.issue}},u=F([c],t.value.stateBranchRoot);return d(u)?a(u.message):l("Deleted issue comment",{id:e.commentId,issueId:r.payload.issue})};var oc=e=>{let t,n,o=!1,r=!1,s=!1,i=()=>{let p=Wn();if(d(p))return ee.error(p.message);let{autoSync:v,userName:C,preferredEditor:E}=p.value;return!!(v&&C&&E)},c=async()=>{if(!o){if(r){s=!0;return}r=!0;try{await or({repoRoot:e.repoRoot}),Wt({type:"state",payload:await Lt({repoRoot:e.repoRoot})})}finally{r=!1,s&&(s=!1,c())}}},u=(p=750)=>{o||(n&&clearTimeout(n),n=setTimeout(()=>{c()},p))},m=()=>{if(o)return;let p=Wn();if(d(p))return ee.error(p.message);let{autoSyncDebounceMs:v}=p.value;i()&&(t=setTimeout(()=>{c(),m()},v??15e3))};return m(),{scheduleSync:u,dispose:()=>{o=!0,t&&clearTimeout(t),n&&clearTimeout(n)}}};import{WebSocketServer as Op}from"ws";var Pe=(e,t)=>{e.send(JSON.stringify(t))},Gn=async(e,t)=>Pe(e,{type:"state",payload:await Lt({repoRoot:t})}),et=async(e,t,n,o,r)=>{if(Pe(e,{type:o,payload:r}),d(r))return Pe(e,{type:"failed",payload:r.message});n(),Gn(e,t)},rc=(e,t,{onStateChanged:n})=>{new Op({server:e,path:"/ws"}).on("connection",r=>{fi(r),r.on("message",async s=>{try{let i=JSON.parse(s.toString()),{type:c}=i;if(c==="state:get")return Gn(r,t);if(c==="sync"){let u=await or({repoRoot:t});return Pe(r,{type:"sync:result",payload:u}),n(),Gn(r,t)}if(c==="issue:comment:add"){let u=await rr({repoRoot:t,...i.payload});return et(r,t,n,"issue:comment:add:result",u)}if(c==="issue:comment:delete"){let u=await sr({repoRoot:t,...i.payload});return Pe(r,{type:"issue:comment:delete:result",payload:u}),d(u)?Pe(r,{type:"failed",payload:u.message}):(n(),Gn(r,t))}if(c==="issue:edit:description"){let u=await Jd({repoRoot:t,...i.payload});return et(r,t,n,"issue:edit:description:result",u)}if(c==="issue:edit:title"){let u=await Qd({repoRoot:t,...i.payload});return et(r,t,n,"issue:edit:title:result",u)}if(c==="issue:tag:add"){let u=await Zd({repoRoot:t,...i.payload});return et(r,t,n,"issue:tag:add:result",u)}if(c==="issue:tag:remove"){let u=await ec({repoRoot:t,...i.payload});return et(r,t,n,"issue:tag:remove:result",u)}if(c==="issue:assignee:add"){let u=await tc({repoRoot:t,...i.payload});return et(r,t,n,"issue:assignee:add:result",u)}if(c==="issue:assignee:remove"){let u=await nc({repoRoot:t,...i.payload});return et(r,t,n,"issue:assignee:remove:result",u)}if(c==="issues:list")return Pe(r,{type:"issues",payload:await Kd({repoRoot:t})});if(c==="issues:create"){let u=await zd({...i.payload,repoRoot:t});return Pe(r,{type:"issues:create:result",payload:u}),d(u)?Wt({type:"failed",payload:u.message}):(Wt({type:"issue:created",payload:u.value}),n(),Gn(r,t))}if(c==="issues:move"){if(!i.payload.position)return Pe(r,{type:"error",message:"Missing move position"});let u=await Xd({...i.payload,repoRoot:t});return et(r,t,n,"issues:move:result",u)}if(c==="issue:close"){if(!i.payload.issueId)return Pe(r,{type:"error",message:"Missing issueId"});let u=await qd({repoRoot:t,issueId:i.payload.issueId});return et(r,t,n,"issue:close:result",u)}if(c==="issue:reopen"){if(!i.payload.issueId)return Pe(r,{type:"error",message:"Missing issueId"});let u=await Yd({repoRoot:t,issueId:i.payload.issueId});return et(r,t,n,"issue:reopen:result",u)}return Pe(r,{type:"error",message:"Unknown message type"})}catch(i){return Pe(r,{type:"error",message:i instanceof Error?i.message:String(i)})}})})};var jp=Zt.dirname(_p(import.meta.url)),Hp=process.env.IS_LOCAL==="true"?Zt.resolve(process.cwd(),"dist/gui"):Zt.join(jp,"gui"),tt=(e,t,n)=>{e.writeHead(t,{"content-type":"application/json"}),e.end(JSON.stringify(n))},Vp=async e=>new Promise((t,n)=>{let o="";e.on("data",r=>{o+=r}),e.on("end",()=>{try{t(o?JSON.parse(o):{})}catch{n(new Error("Invalid JSON body"))}}),e.on("error",n)}),Gp=e=>e.endsWith(".html")?"text/html; charset=utf-8":e.endsWith(".js")?"text/javascript; charset=utf-8":e.endsWith(".css")?"text/css; charset=utf-8":e.endsWith(".json")?"application/json; charset=utf-8":e.endsWith(".ico")?"image/x-icon":"application/octet-stream",sc=async(e,t)=>{let n=e==="/"?"index.html":decodeURIComponent(e).replace(/^\/+/,""),o=Zt.resolve(Hp),r=Zt.resolve(o,n),s=Zt.relative(o,r);if(s.startsWith("..")||Zt.isAbsolute(s))return tt(t,403,{isError:!0,message:"Forbidden"});try{let i=await $p(r);return t.writeHead(200,{"content-type":Gp(r)}),t.end(i)}catch{return tt(t,404,{isError:!0,message:`Not found: ${n}`})}},Kp=async(e,t=3710)=>new Promise((n,o)=>{let r=s=>{let i=u=>{if(e.off("listening",c),u.code==="EADDRINUSE"&&s===t){e.removeListener("error",i),r(0);return}o(u)},c=()=>{e.off("error",i);let u=e.address();if(!u||typeof u=="string"){o(new Error("Unable to resolve address"));return}n(u.port)};e.once("error",i),e.once("listening",c),e.listen(s,"127.0.0.1")};r(t)}),ic=async e=>{let t=Wp.createServer(async(r,s)=>{let i=new URL(r.url??"/","http://127.0.0.1");if(i.pathname==="/api/state")return tt(s,200,await Lt({repoRoot:e.repoRoot}));if(r.method==="POST"&&i.pathname==="/api/comments")try{let c=await Vp(r);if(!c.issueId||!c.body?.trim())return tt(s,400,{isError:!0,message:"Missing issueId or body"});let u=await rr({repoRoot:e.repoRoot,issueId:c.issueId,body:c.body});return"isError"in u&&u.isError?tt(s,400,u):tt(s,200,await Lt({repoRoot:e.repoRoot}))}catch(c){return tt(s,400,{isError:!0,message:c instanceof Error?c.message:"Unable to add comment"})}if(r.method==="DELETE"&&i.pathname.startsWith("/api/comments/")){let c=decodeURIComponent(i.pathname.replace("/api/comments/",""));if(!c)return tt(s,400,{isError:!0,message:"Missing comment id"});let u=await sr({repoRoot:e.repoRoot,commentId:c});return"isError"in u&&u.isError?tt(s,400,u):tt(s,200,await Lt({repoRoot:e.repoRoot}))}return i.pathname.startsWith("/board/")?sc("/",s):sc(i.pathname,s)});try{await Kp(t)}catch(r){return a(r instanceof Error?`Unable to start GUI server: ${r.message}`:`Unable to start GUI server: ${String(r)}`)}let n=oc({repoRoot:e.repoRoot});rc(t,e.repoRoot,{onStateChanged:()=>n.scheduleSync()}),t.on("close",n.dispose);let o=t.address();return!o||typeof o=="string"?(t.close(),a("Unable to resolve GUI server address")):l("Started GUI server",{url:`http://epiq.localhost:${o.port}${e.boardId?`/board/${e.boardId}`:""}`,server:t})};var ac=async e=>{let t=await ic({...e,boardId:""});if(d(t))return t;let{url:n}=t.value;return console.log(`Epiq GUI running at ${zp.cyan(n)}`),Hs(n),l("Started GUI",{url:n})};import{Box as Bt}from"ink";import J from"react";import{Box as As,Text as Kn}from"ink";import We,{useEffect as qp,useMemo as Yp}from"react";import{ulid as Xp}from"ulid";var dc=({text:e,match:t,color:n,highlightColor:o=y.secondary,dimColor:r=!1})=>{if(!t)return We.createElement(Kn,{color:n,dimColor:r},e);let s=e.toLowerCase(),i=t.toLowerCase(),c=s.indexOf(i);return c===-1?We.createElement(Kn,{color:n,dimColor:r},e):We.createElement(Kn,{color:n,dimColor:r},e.slice(0,c),We.createElement(Kn,{backgroundColor:o,bold:!0},e.slice(c,c+t.length)),e.slice(c+t.length))},cc=Xp(),Jp=e=>`${e}`,Qp=e=>{let{pendingNavTarget:t}=wt();if(!t)return[];let{breadCrumb:n,contextNode:o,selectedNode:r}=t,s=new Set(ie(h.NONE,{breadCrumb:n,contextNode:o,readOnly:g().readOnly,selectedNode:r}));return[...new Set(Object.values(h))].filter(i=>i!=="move").filter(i=>i.length>0).filter(i=>i!==h.PALETTE).map(i=>{let c=Uo(i),u=Jo.find(m=>m.intent===c);return{command:i,description:u?.description??`[${i}] Run command`,isAvailable:s.has(i)}}).filter(i=>i.command.toLowerCase().startsWith(e)||e.length>=2&&i.description.toLowerCase().includes(e)).sort((i,c)=>i.isAvailable!==c.isAvailable?i.isAvailable?-1:1:i.command.localeCompare(c.command))},Zp=e=>Y.text({id:cc,parentNodeId:e,rank:"000000",name:"Command Palette",props:{},readonly:!0,isVirtual:!0}),eg=(e,t,n)=>Y.text({id:Jp(e.command),parentNodeId:n,rank:String(t).padStart(6,"0"),name:e.command,props:{value:e.description,disabled:!e.isAvailable},readonly:!0,isVirtual:!0}),ws=[],tg=e=>{lc();let t=I.createNode(Zp(g().rootNodeId));d(t)||!bt(t.value)||(ws=[t.value,...e.map((n,o)=>eg(n,o,cc)).map(I.createNode).filter(Q).map(({value:n})=>n).filter(bt)],T.navigate({contextNode:t.value,selectedIndex:0}))},lc=()=>{let e=ws.map(t=>t.id);ws=[];for(let t of e)I.deleteNode(t)};function uc({width:e,height:t}){let o=Ma().value.trim().toLowerCase(),r=Yp(()=>Qp(o),[o]);qp(()=>(tg(r),()=>{lc()}),[r]);let s=g().selectedIndex;return We.createElement(As,{flexDirection:"column",width:e,height:t-2},We.createElement(Je,{height:t-4,itemHeight:3,selectedIndex:s},r.map((i,c)=>{let u=c===s,m=i.isAvailable?y.accent:y.secondary2,p=i.isAvailable?"":"[unavailable] ";return We.createElement(As,{key:i.command,flexDirection:"column",paddingX:1,borderLeft:!1,borderBottom:!1,borderRight:!1,borderColor:y.secondary,borderStyle:"single"},We.createElement(Kn,{color:m,dimColor:!i.isAvailable},u?"\u276F ":" ",We.createElement(dc,{text:bi(i.command),match:o,color:m,dimColor:!i.isAvailable})),We.createElement(As,{paddingLeft:2},We.createElement(dc,{text:p+i.description,match:o.length>=2?o:"",color:u&&i.isAvailable?y.primary:y.secondary2,dimColor:!i.isAvailable})))})))}import{Box as gg}from"ink";import Ps from"react";import qn from"chalk";import{Box as Ms,Text as mc}from"ink";import zn,{useEffect as ng,useMemo as og,useState as rg}from"react";var pc=qn.gray,sg=qn.inverse,ig=qn.inverse.gray,ag={hint:"",hints:[],overlap:0,remainder:""},fc=({value:e,command:t})=>{if(!t)return null;let n=e.trimStart(),r=e.length-n.length;return e.slice(r,r+t.length)!==t?null:{start:r,end:r+t.length}},dg=({command:e,modifier:t})=>{if(!t)return null;if(e==="tag"||e==="assign"){let n=oe(t);return{bg:o=>qn.bgHex(n).black(o),bgCursor:o=>qn.bgHex(n).inverse.black(o)}}return Wr(t)},cg=({value:e,command:t,modifier:n})=>{if(!t||!n)return null;let o=fc({value:e,command:t});if(!o)return null;let s=e.slice(o.end).match(/^\s*/)?.[0].length??0,i=o.end+s;return e.slice(i,i+n.length)!==n?null:{start:i,end:i+n.length}},gc=()=>({value:ge.value,cursorPosition:ge.cursorPosition,commandIsPending:ge.commandIsPending,autoCompletion:ge.commandMeta.autoCompletion??ag,infoMessage:ge.commandMeta.infoMessage,validationStatus:ge.commandMeta.validity,command:ge.commandMeta.command,inputString:ge.commandMeta.inputString,modifier:ge.commandMeta.modifier}),lg=(e,t)=>e.value===t.value&&e.cursorPosition===t.cursorPosition&&e.commandIsPending===t.commandIsPending&&e.infoMessage===t.infoMessage&&e.autoCompletion.hint===t.autoCompletion.hint&&e.autoCompletion.overlap===t.autoCompletion.overlap&&e.autoCompletion.remainder===t.autoCompletion.remainder&&e.validationStatus===t.validationStatus&&e.command===t.command&&e.modifier===t.modifier&&e.inputString===t.inputString,vc=({width:e,mode:t})=>{let[n,o]=rg(gc());ng(()=>{let C=()=>{let S=gc();o(R=>lg(R,S)?R:S)},E=rs(C);return C(),()=>{E()}},[]);let{value:r,cursorPosition:s,infoMessage:i,commandIsPending:c,autoCompletion:u,command:m,modifier:p}=n,v=og(()=>{let C=Math.max(0,Math.min(s,r.length)),E=fc({value:r,command:m}),S=cg({value:r,command:m,modifier:p}),R=m?Wr(m):null,D=dg({command:m,modifier:p}),P=(le,be)=>{let en=E&&be>=E.start&&be<E.end,Ot=S&&be>=S.start&&be<S.end;return en&&R?R.fg(le):Ot&&D?D.bg(le):le},V=(le,be)=>{let en=E&&be>=E.start&&be<E.end,Ot=S&&be>=S.start&&be<S.end;return en&&R?R.fgCursor(le):Ot&&D?D.bgCursor(le):sg(le)},O=r.slice(0,C),k=r[C]??" ",Ee=C<r.length?r.slice(C+1):"",ft=Array.from(O).map((le,be)=>P(le,be)).join(""),vt=V(k,C),yt=Array.from(Ee).map((le,be)=>P(le,C+1+be)).join("");if(u.hint){let le=u.hint[u.overlap]??k;vt=ig(le),yt=pc(u.remainder.slice(1)+Ee)}return pc(t===f.PALETTE?"?":":")+ft+vt+yt},[r,s,u,m,p]);return zn.createElement(Ms,{flexDirection:"column",justifyContent:"flex-start"},zn.createElement(Ms,{flexDirection:"column",paddingX:1,borderColor:y.secondary,borderStyle:"round",width:e},zn.createElement(Ms,null,zn.createElement(mc,null,v),i&&zn.createElement(mc,{wrap:"truncate",color:c?y.red:y.secondary2},` ${i} `))))};import{Box as ug,Text as mg}from"ink";import yc from"react";var pg=(e,t)=>{let n=[],o=0;for(let r of e){let i=(n.length>0?" | ":"").length+r.length;if(o+i>t-4)break;n.push(r),o+=i}return n},xc=({width:e,availableHints:t})=>{let n=pg(t,e).join(" | ");return yc.createElement(ug,{width:e,borderStyle:"round",borderColor:y.secondary,paddingX:1},yc.createElement(mg,{color:y.secondary2},n.length?n:"\xA0"))};var Yn=({width:e,mode:t,availableHints:n})=>{let o=[],r=0;for(let s of n){let c=(o.length>0?" | ":"").length+s.length;if(r+c>e+2)break;o.push(s),r+=c}return Ps.createElement(gg,null,t===f.COMMAND_LINE||t===f.PALETTE?Ps.createElement(vc,{width:e,mode:t}):Ps.createElement(xc,{width:e,mode:t,availableHints:n}))};import{Box as kt,Text as yn}from"ink";import Ie,{useEffect as fg,useMemo as vg}from"react";import{ulid as hc}from"ulid";var ar=hc(),yg=()=>[...new Set([...g().availableActions].map(e=>e.description).filter(e=>e!==void 0))].map(e=>{let[t,n]=e.split("]"),o=t?.replace("[",""),r=n?.trim();return[o,r]}).filter(e=>e[0]!==void 0&&e[1]!==void 0).sort(([e],[t])=>e.length===1&&t.length!==1?-1:e.length!==1&&t.length===1?1:e.localeCompare(t,void 0,{sensitivity:"base"})).map(([e,t])=>({keys:e,action:t})),xg=e=>Y.text({id:ar,parentNodeId:e,rank:"000000",name:"Help",props:{},isVirtual:!0,readonly:!0}),hg=(e,t,n)=>Y.text({id:hc(),parentNodeId:n,rank:String(t).padStart(6,"0"),name:e.keys,props:{value:e.action},readonly:!0,isVirtual:!0}),ir=[],Ic=()=>{let e=ir.filter(n=>n.id!==ar).map(n=>n.id),t=ir.filter(n=>n.id===ar).map(n=>n.id);ir=[];for(let n of[...e,...t])I.deleteNode(n)},Ig=e=>{Ic();let t=I.createNode(xg(g().rootNodeId));if(d(t)||!bt(t.value))return logger.error("Could not attach help nodes");ir=[t.value,...e.map((n,o)=>hg(n,o,ar)).map(I.createNode).filter(Q).map(({value:n})=>n).filter(bt)],T.navigate({contextNode:t.value,selectedIndex:0})},bc=({width:e,height:t})=>{let n=vg(()=>yg(),[]);fg(()=>(Ig(n),()=>{Ic()}),[n]);let o=g().selectedIndex;return Ie.createElement(kt,{flexDirection:"column",marginTop:3,borderColor:y.secondary,borderStyle:"round",width:e,height:t-2},Ie.createElement(kt,{paddingX:1,justifyContent:"center"},Ie.createElement(yn,{color:y.accent},"Help"),Ie.createElement(yn,{dimColor:!0}," \u2014 navigate with arrows/hjkl, press q to close")),Ie.createElement(kt,{paddingX:1,marginTop:1},Ie.createElement(kt,{width:20,justifyContent:"flex-end"},Ie.createElement(yn,{color:y.secondary},"Key(s)")),Ie.createElement(kt,{flexGrow:1,width:40,paddingLeft:2},Ie.createElement(yn,{color:y.secondary},"Action"))),Ie.createElement(Je,{height:t-7,itemHeight:1,selectedIndex:o},n.map(({keys:r,action:s},i)=>{let c=i===o;return Ie.createElement(kt,{paddingX:1,key:`${r}-${s}-${i}`,flexDirection:"row"},Ie.createElement(kt,{width:20,justifyContent:"flex-end"},Ie.createElement(yn,{color:y.accent},r)),Ie.createElement(kt,{flexGrow:1,width:40,paddingLeft:2},Ie.createElement(yn,{color:c?y.primary:y.secondary2},s)))})))};import bg from"chalk";import{Box as dr,Text as gt}from"ink";import Le from"react";var Cc=({width:e,height:t})=>Le.createElement(dr,{height:t-4,flexDirection:"column",width:e,paddingTop:1,paddingLeft:2,borderStyle:"round",borderColor:y.secondary,rowGap:1},Le.createElement(gt,{color:y.accent,bold:!0},"Initialize project"),Le.createElement(gt,null,`This folder is not an ${bg.hex(y.accent)("epiq")} project yet.`),Le.createElement(gt,{color:y.primary},"To start tracking issues here, we need to initialize a new",Le.createElement(gt,{color:y.primary,backgroundColor:y.secondary}," .epiq/project.json "),"file in this repository."),Le.createElement(dr,{marginTop:1,flexDirection:"column"},Le.createElement(dr,null,Le.createElement(gt,{color:y.accent}," "),Le.createElement(gt,{color:y.primary},"Type "),Le.createElement(gt,{backgroundColor:y.secondary}," :init "))),Le.createElement(dr,{marginTop:1},Le.createElement(gt,{color:y.secondary2},"This will create, commit and push "),Le.createElement(gt,{color:y.primary,backgroundColor:y.secondary}," .epiq/project.json ")));import{Box as cr,Text as nt}from"ink";import ce from"react";var Cg=({isDone:e,command:t,value:n})=>ce.createElement(cr,null,ce.createElement(nt,{color:y.accent,dimColor:e},e?" \u2714 ":" "),ce.createElement(nt,{dimColor:e},"Type "),ce.createElement(nt,{backgroundColor:y.secondary,dimColor:e}," "+t+" "),n!==void 0&&ce.createElement(ce.Fragment,null,ce.createElement(nt,{dimColor:e}," "),ce.createElement(nt,{color:y.secondary,dimColor:e},"<"+n+">"))),Ng=e=>{if(typeof e=="string")return e;if(typeof e=="boolean")return e?"on":"off"};function Ls({width:e,height:t}){let{isSetPreferredEditor:n,isSetUserName:o,userName:r,preferredEditor:s,autoSync:i,isSetAutoSync:c}=St(),u=[{key:"username",done:o,command:":config username",value:r,message:"First, choose your username."},{key:"editor",done:n,command:":config editor",value:s,message:"Nice. Now pick your editor."},{key:"autosync",done:c,command:":config autosync",value:i,message:"Almost there. Configure auto sync."}],m=u.findIndex(v=>!v.done),p=m===-1?void 0:u[m];return ce.createElement(cr,{height:t-4,flexDirection:"column",width:e,paddingTop:1,paddingLeft:2,borderStyle:"round",borderColor:y.secondary,rowGap:1},ce.createElement(nt,{color:y.accent,bold:!0},"Welcome! \u{1F539}"),ce.createElement(nt,null,"Let's get you started - it's a breeze."),ce.createElement(nt,{color:y.secondary2},"Remember - you can always search available commands by typing:",ce.createElement(nt,{color:y.accent}," ? ")),p&&ce.createElement(nt,{color:y.secondary2},p.message),ce.createElement(cr,{flexDirection:"column"},u.map((v,C)=>m===-1||C<=m?ce.createElement(cr,{key:v.key,marginBottom:1},ce.createElement(Cg,{isDone:v.done,command:v.command,value:v.done?Ng(v.value):void 0})):null)))}import gr from"chalk";import{Box as pr,Text as Jn}from"ink";import ye from"react";import{Box as lr,Text as Nc}from"ink";import Dt from"react";var Sg=e=>(I.getTag(e)?.name??"").length+3,Eg=e=>(I.getContributor(e)?.name??"").length+3,Sc=({width:e})=>{let{viewMode:t}=_(),n=K(),{breadCrumb:o,contextNode:r,selectedIndex:s,renderedChildrenIndex:i}=n,c=i[r.id]?.[s],u=it(c?.id??r.id,"TICKET"),m=Q(u)?u.value:void 0,p=m?.props.tags??[],v=m?.props.assignees??[],C=m?.parentNodeId?!Ur(r.id,m.parentNodeId)&&t==="dense":!1,E=o.map((k,Ee)=>{let ft=Ee===o.length-1,vt=j(k.id),yt=ft?vt?.[s]?.title:void 0;return`${Ee?" / ":""}${k.title??""}${yt?` \u25B8 ${yt}`:""}`}).join(""),S=m?I.getCommentsByIssue(m.id):[],R=S.length?String(S.length).length+11:0,D=C?p.reduce((k,Ee)=>k+Sg(Ee),0)+v.reduce((k,Ee)=>k+Eg(Ee),0)+R:0,P=Math.max(0,e-D),V=E.substring(0,P),O=C?[...p.map(k=>Dt.createElement(lr,{key:`tag-${k}`,paddingLeft:1},Dt.createElement(fn,{id:k}))),...v.map(k=>Dt.createElement(lr,{key:`assignee-${k}`,paddingLeft:1},Dt.createElement(Rt,{id:k}))),S.length?Dt.createElement(lr,{key:"comments",paddingLeft:1},Dt.createElement(Nc,{color:y.accent},"[",S.length," comment",S.length===1?"":"s","]")):null]:[];return Dt.createElement(lr,{overflow:"hidden",justifyContent:"flex-start",alignItems:"flex-start"},Dt.createElement(Nc,{color:y.secondary2},V),O)};import{Box as Rg,Text as Ec}from"ink";import ur from"react";var Tg=({filters:e})=>ur.createElement(Rg,{columnGap:1},ur.createElement(Ec,{color:"red"},"APPLIED FILTERS:"),e.map(({value:t,target:n,operator:o})=>ur.createElement(Ec,{backgroundColor:"black",color:"white"},` ${n}${o}"${t}" `))),Rc=ur.memo(Tg);import{Box as Ag,Text as mr}from"ink";import Xn from"react";function Tc(){let{eventLog:e,unappliedEvents:t}=K(),n=e.at(-1)?.id,o=bo(n??""),r=Q(o)?Di(o.value):"INVALID DATE";return Xn.createElement(Ag,{paddingLeft:1},Xn.createElement(mr,{backgroundColor:y.accent}," Readonly "),Xn.createElement(mr,{color:y.accent}," "+t.length+" edits ago at "+r+"."),Xn.createElement(mr,{color:y.accent}," Resume with "),Xn.createElement(mr,{backgroundColor:y.accent}," :peek now "))}import ks from"chalk";import{Box as wg,Text as Ac}from"ink";import Ds,{useEffect as Mg,useState as Pg}from"react";var Lg=["#4c567a","#9d7cd8","#7aa2f7","#7dcfff","#9d7cd8"],wc=e=>{let t=e.replace("#","");return{r:parseInt(t.slice(0,2),16),g:parseInt(t.slice(2,4),16),b:parseInt(t.slice(4,6),16)}},kg=({r:e,g:t,b:n})=>{let o=r=>Math.round(Math.max(0,Math.min(255,r))).toString(16).padStart(2,"0");return`#${o(e)}${o(t)}${o(n)}`},Dg=(e,t,n)=>{let o=wc(e),r=wc(t);return kg({r:o.r+(r.r-o.r)*n,g:o.g+(r.g-o.g)*n,b:o.b+(r.b-o.b)*n})},Fg=(e,t)=>{if(e.length===1)return e[0];let n=t*(e.length-1),o=Math.floor(n),r=n-o,s=e[o],i=e[Math.min(o+1,e.length-1)];return Dg(s,i,r)};function Mc({syncStatus:e,autoSync:t}){let[n,o]=Pg(0);Mg(()=>{if(e.status!=="syncing"){o(0);return}let c=setInterval(()=>{o(u=>u+1)},50);return()=>clearInterval(c)},[e.status]);let r={synced:" ",failed:"---",syncing:"...",pending:"idle"},i={synced:y.secondary2,failed:y.yellow,pending:y.secondary2,syncing:Fg(Lg,(Math.sin(n*.12)+1)/2)??""}[e.status];return Ds.createElement(wg,null,Ds.createElement(Ac,null,ks.hex(y.secondary2).dim(t?"Sync (auto): ":"Sync: ")),Ds.createElement(Ac,null,ks.hex(i)("\u25CF")+ks.hex(y.secondary2).dim(` ${r[e.status].padEnd(4)} `)))}import Fc from"chalk";import{Text as Bc}from"ink";import Uc,{useEffect as $g,useState as Wg}from"react";var xn="0.7.3";import Fs from"chalk";var Bg="https://registry.npmjs.org/epiq/latest",Bs=null,Pc=0,Ug=1e3*60*60*24,Lc=e=>e.replace(/^v/,""),Og=(e,t)=>{let n=Lc(e).split(".").map(Number),o=Lc(t).split(".").map(Number);for(let r=0;r<Math.max(n.length,o.length);r++){let s=n[r]??0,i=o[r]??0;if(s>i)return 1;if(s<i)return-1}return 0},kc=async e=>{if(process.env.IS_CI==="true")return{current:"1.2.3",latest:"1.2.3",updateAvailable:!1};if(Bs&&Date.now()-Pc<Ug)return Bs;try{let t=await fetch(Bg);if(!t.ok)throw new Error(`Failed to fetch latest version: ${t.status}`);let o=(await t.json()).version??null,r={current:e,latest:o,updateAvailable:o?Og(o,e)>0:!1};return Bs=r,Pc=Date.now(),r}catch{return{current:e,latest:null,updateAvailable:!1}}},Dc=(e,t)=>{let n=e.split("."),o=t.split("."),r=o.findIndex((s,i)=>s!=n[i]);return o.map((s,i)=>i>=r?Fs.hex(y.accent).dim(s):Fs.hex(y.secondary).dim(s)).join(Fs.hex(y.secondary2).dim("."))};function Oc(){let[e,t]=Wg({current:xn,latest:null,updateAvailable:!1});return $g(()=>{let n=!0;return kc(xn).then(o=>{n&&t(o)}),()=>{n=!1}},[]),!e.updateAvailable||!e.latest?Uc.createElement(Bc,{dimColor:!0,color:y.secondary2},xn+" "):Uc.createElement(Bc,null,Fc.hex(y.secondary2).dim(xn),Fc.hex(y.accent).dim(" \u2197 "),Dc(xn,e.latest))}function Qn({filters:e,hideBreadCrumb:t=!1}){let{timeMode:n,syncStatus:o,mode:r}=K(),{userName:s,preferredEditor:i,autoSync:c}=_(),u=64,m=process.stdout.columns-u-8;return ye.createElement(pr,{justifyContent:"space-between",flexDirection:"row","max-width":process.stdout.columns-40,overflow:"hidden"},t?ye.createElement(Jn,null," "):r===f.PALETTE?ye.createElement(pr,null,ye.createElement(Jn,{color:y.accent},"Command Palette"),ye.createElement(Jn,{dimColor:!0,color:y.secondary2}," ","- search, select and press enter")):ye.createElement(pr,{paddingLeft:1},e.length>0?ye.createElement(Rc,{filters:e}):ye.createElement(Sc,{width:m})),n==="live"?ye.createElement(pr,{columnGap:1,paddingRight:2,"max-width":u,overflow:"hidden",justifyContent:"flex-end"},ye.createElement(Mc,{autoSync:!!c,syncStatus:o}),ye.createElement(Jn,null,gr.hex(y.secondary2).dim("Mode: ")+gr.hex(y.secondary2).dim(r.padEnd(8," "))," "),ye.createElement($c,{icon:"@",value:s}),ye.createElement($c,{icon:"\u276F",value:i}),ye.createElement(Oc,null)):"",n==="peek"?ye.createElement(Tc,null):"")}function $c({icon:e,value:t}){return ye.createElement(Jn,null,gr.dim(e)+gr.hex(y.accent)(` ${t??"-"} `))}import{Box as _g,Text as jg}from"ink";import Zn from"react";import{Box as fr,Text as Us}from"ink";import Ft from"react";function Os(){let e=K(),t=e.nodes[e.rootNodeId],r=process.stdout.rows-1-3,s=process.stdout.columns||120,i=t?.id?W(t?.id):[];return Ft.createElement(fr,{flexDirection:"column",height:r,padding:1,borderStyle:"round",borderColor:y.secondary,width:s},Ft.createElement(fr,{padding:1,paddingTop:0,paddingBottom:0},Ft.createElement(Us,null,"Select a board:")),Ft.createElement(fr,{padding:1,flexDirection:"column"},i.map((c,u)=>{let m=e.contextNode.context==="WORKSPACE"&&e.selectedIndex===u,v=W(c.id).flatMap(({id:C})=>j(C)).length;return Ft.createElement(fr,{key:c.id??u},Ft.createElement(Us,{color:m?y.accent:y.secondary2},Ft.createElement(he,{isSelected:m})),Ft.createElement(Us,{color:m?y.accent:y.secondary2},c.title," (",v," issues)",c.readonly?" \u{1F512}":""))})))}var Hg=({contextNode:e,selectedIndex:t,breadCrumb:n,mode:o,viewMode:r,height:s,width:i})=>{let{renderedChildrenIndex:c}=K(),u=n.find(({context:C})=>C==="BOARD"),v=s-1-3;return Zn.createElement(_g,{flexDirection:"row"},e.context==="WORKSPACE"?Zn.createElement(Os,null):u?Zn.createElement(Vo,{height:v,width:i,swimlanes:(c[u.id]??[]).filter(C=>C!==void 0&&Ct(C)),contextNode:e,selectedIndex:t,breadCrumb:n,viewMode:r,mode:o}):Zn.createElement(jg,null))},Wc=Zn.memo(Hg);import{useEffect as Vg}from"react";var Gg=e=>{Vg(()=>{if(!e)return;let t,n=!1,o=()=>{if(n)return;let{autoSyncIntervalMs:r,userName:s,preferredEditor:i}=_();i&&s&&r&&(t=setTimeout(()=>{if(n)return;let{readOnly:c,mode:u}=g();u==="default"&&!c&&Mo(),o()},r))};return o(),()=>{n=!0,t&&clearTimeout(t)}},[e])},_c=({autoSync:e})=>(Gg(e),null);function $s({width:e,height:t}){let n=K(),{autoSync:o,viewMode:r}=Ti(),s=n.filters;if(n.mode===f.HELP)return J.createElement(Bt,{flexDirection:"column"},J.createElement(bc,{width:e,height:t}));if(n.mode===f.PALETTE)return J.createElement(Bt,{flexDirection:"column"},J.createElement(Qn,{filters:s}),J.createElement(uc,{width:e,height:t-2}),J.createElement(Yn,{width:e,mode:n.mode,availableHints:n.availableHints}));let{isSetupDone:i}=St(),c=!i,u=i&&!n.hasProjectDefinition;if(c)return J.createElement(Bt,{flexDirection:"column"},J.createElement(Bt,{flexDirection:"column"},J.createElement(Qn,{hideBreadCrumb:!0,filters:s}),J.createElement(Ls,{height:t,width:e})),J.createElement(Yn,{width:e,mode:n.mode,availableHints:n.availableHints}));if(u)return J.createElement(Bt,{flexDirection:"column"},J.createElement(Bt,{flexDirection:"column"},J.createElement(Qn,{hideBreadCrumb:!0,filters:s}),J.createElement(Cc,{height:t,width:e})),J.createElement(Yn,{width:e,mode:n.mode,availableHints:n.availableHints}));let m=Se(n.breadCrumb??[],"BOARD");if(Q(m)){let p=m.value.id,v=W(p).length,C=3,E=Math.floor(e/C),S=Math.floor(e/Math.max(v,1));e=Math.min(S,E)*Math.max(v,C)}return J.createElement(Bt,{flexDirection:"column"},J.createElement(_c,{autoSync:o}),J.createElement(Bt,{flexDirection:"column"},J.createElement(Qn,{filters:s}),J.createElement(Wc,{width:e,height:t,contextNode:n.contextNode,selectedIndex:n.selectedIndex,breadCrumb:n.breadCrumb,viewMode:r??"dense",mode:n.mode})),J.createElement(Yn,{width:e,mode:n.mode,availableHints:n.availableHints}))}import Kg from"readline";var vr,yr,ot,zg=new Set([x.MoveCursorLeft,x.EraseInputWord,x.MoveCursorLeftOfWord,x.MoveCursorRight,x.MoveCursorRightOfWord,x.NavToPreviousContainer,x.NavToNextContainer,x.NavPreviousItem,x.NavNextItem,x.SetViewDense,x.SetViewWide,x.Confirm,x.Exit,x.InitCommandLine,x.InitCommandPalette,x.ExitCommandLine,x.CaptureInput,x.EraseInput,x.EraseInputWord,x.HideHelp,x.ViewHelp,x.SetViewDense,x.SetViewWide,x.GetLastCommandFromHistory,x.GetNextCommandFromHistory,x.AutoCompleteCommand]),jc=async e=>{if(e.ctrl&&e.name==="c")return T.exit();let{actionIndex:t,mode:n,readOnly:o}=g(),r=La(e,n);if(!r||o&&!zg.has(r))return;let s=t[n]?.[r];if(s?.action)try{await s.action(s,e)}catch(i){logger.error(i)}},qg=()=>async function(t,n){n.name!=="escape"&&(ot&&(clearTimeout(ot),ot=void 0),await jc(n))},Yg=()=>async function(t){if(t.length===1&&t[0]===27){ot&&clearTimeout(ot),ot=setTimeout(()=>{jc({name:"escape",ctrl:!1,meta:!1,shift:!1,sequence:"\x1B"}),ot=void 0},25);return}ot&&(clearTimeout(ot),ot=void 0)};function Hc(){vr&&process.stdin.removeListener("keypress",vr),yr&&process.stdin.removeListener("data",yr),vr=qg(),yr=Yg(),Kg.emitKeypressEvents(process.stdin),process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.on("data",yr),process.stdin.on("keypress",vr)}async function Vc(){try{let e=_n();Q(e)&&Fe(e.value);let t=_e(process.cwd()),n=[];if(Q(t)){let s=Oe({repoRoot:t.value});if(d(s))return zt(3,s.message);let i=tn(),c=await $t({repoRoot:t.value,stateBranchRoot:s.value,stateBranchName:i.stateBranch});if(d(c))return zt(3,c.message);let u=await B({cwd:s.value,args:["pull","--ff-only"]});d(u)&&logger.info(3,u.message);let m=at(s.value);if(d(m))return zt(3,m.message);n=m.value}let o=Kt(n);if(d(o))return zt(4,o.message);N({hasProjectDefinition:Q(t),hasInitializingEvents:!!n.length});let r=Ws();return d(r)?zt(6,r.message):(Hc(),l("Booted Epiq",void 0))}catch(e){return zt(0,To(e))}}id();var Zg=`${Ut.bold("Epiq CLI")}
|
|
58
58
|
|
|
59
59
|
${Ut.dim("Boot in directory:")}
|
|
60
60
|
${Ut.cyan("$ epiq")}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "epiq",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "EPIQ - CLI based issue tracker",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"build:gui:types": "tsc --noEmit -p source/gui/client/tsconfig.json",
|
|
31
31
|
"build:gui": "npm run build:gui:types && mkdir -p dist/gui && cp source/gui/index.html dist/gui/index.html && cp source/gui/favicon.ico dist/gui/favicon.ico && esbuild source/gui/client/main.tsx --bundle --format=esm --target=es2020 --outfile=dist/gui/main.js",
|
|
32
32
|
"build:npm": "node source/scripts/write-version.mjs && rm -rf ./dist && npm run build:gui && esbuild source/Index.tsx --bundle --packages=external --platform=node --format=esm --target=node18 --minify --outfile=dist/index.js --banner:js='#!/usr/bin/env node' && esbuild source/mcp/index.ts --bundle --packages=external --platform=node --format=esm --target=node18 --minify --outfile=dist/mcp.js --banner:js='#!/usr/bin/env node'",
|
|
33
|
-
"build:sea:bundle": "node source/scripts/write-version.mjs &&
|
|
34
|
-
"build:sea": "node
|
|
33
|
+
"build:sea:bundle": "node source/scripts/write-version.mjs && node source/scripts/build-sea.mjs",
|
|
34
|
+
"build:sea": "node source/scripts/build-sea.mjs",
|
|
35
35
|
"build:publish": "npm run build:npm",
|
|
36
|
-
"build:binary": "
|
|
36
|
+
"build:binary": "node source/scripts/write-version.mjs && node source/scripts/build-sea.mjs",
|
|
37
37
|
"watch:npm": "node source/scripts/write-version.mjs && rm -rf ./dist && node source/scripts/watch-npm.mjs",
|
|
38
38
|
"dev": "IS_LOCAL=true tsc --watch --noEmit",
|
|
39
39
|
"dev:start": "IS_LOCAL=true tsx source/Index.tsx",
|
package/readme.md
CHANGED
|
@@ -6,15 +6,15 @@ _Distributed terminal-native issue tracker backed by Git._
|
|
|
6
6
|
|
|
7
7
|
Issue tracking is a core part of software development, but it often becomes a painful context-switching exercise with poor ergonomics. Epiq provides issue tracking as a portable, integrated part of the development environment, with access to all the powerful tooling developers are used to.
|
|
8
8
|
|
|
9
|
-
> Manage your projects in a visual terminal kanban board or through the browser GUI, while keeping all state local, Git-backed, and versioned.
|
|
9
|
+
> Manage your projects in a visual terminal kanban board (or through the browser GUI), while keeping all state local, Git-backed, and versioned.
|
|
10
10
|
|
|
11
|
-
With great attention to user ergonomics and developer experience, epiq
|
|
11
|
+
With great attention to user ergonomics and developer experience, epiq strives to make project management painless and friction free.
|
|
12
12
|
|
|
13
13
|

|
|
14
14
|
|
|
15
|
-
## Terminal
|
|
15
|
+
## Terminal + Browser
|
|
16
16
|
|
|
17
|
-
Epiq also
|
|
17
|
+
Epiq originated from the command line, but also features a browser interface powered by the same Git-backed event engine.
|
|
18
18
|
|
|
19
19
|

|
|
20
20
|
|
|
@@ -22,24 +22,9 @@ Epiq also includes a browser-based interface powered by the same Git-backed even
|
|
|
22
22
|
|
|
23
23
|
Epiq is a self hosted, vim-inspired issue tracker that brings developer experience to project management. It renders either as ASCII, or as a web GUI, and persists state as an immutable distributed event log, versioned and synchronized through Git.
|
|
24
24
|
|
|
25
|
-
An easy to use browser GUI is available, powered by the same Git-backed state engine.
|
|
26
|
-
|
|
27
25
|

|
|
28
26
|

|
|
29
27
|
|
|
30
|
-
## Features
|
|
31
|
-
|
|
32
|
-
- Issue tracking — track work in tickets with name, description, tags, assignees, history log, etc.
|
|
33
|
-
- Ergonomics — fast keyboard-driven UX, command line with history, syntax highlighting etc.
|
|
34
|
-
- Command palette — press `?` to open a scrollable overview of all available commands and descriptions
|
|
35
|
-
- Time travel — inspect your app 1h, 1 week or 1 year ago
|
|
36
|
-
- Filtering — query issues by description, tags, assignees, etc.
|
|
37
|
-
- Autocompletion — minimize typing, stay in flow, reuse previous commands
|
|
38
|
-
- Multi-user — collaborative synchronization via Git
|
|
39
|
-
- Traceable event log — state is a full history of every change ever made
|
|
40
|
-
- Browser GUI — graphical interface powered by the same Git-backed state
|
|
41
|
-
- MCP integration — Model Context Protocol support for agent interaction
|
|
42
|
-
|
|
43
28
|
## Why Epiq?
|
|
44
29
|
|
|
45
30
|
Most issue trackers live outside your workflow. Epiq brings issue tracking where you already work - you editor.
|
|
@@ -54,6 +39,19 @@ These design choices result in a system that is:
|
|
|
54
39
|
- **Command driven** — scriptable and automation-friendly, ready for the agentic era
|
|
55
40
|
- **Versioned** — changes are tracked and recoverable through Git
|
|
56
41
|
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- Issue tracking — track work in tickets with name, description, tags, assignees, history log, etc.
|
|
45
|
+
- Ergonomics — fast keyboard-driven UX, command line with history, syntax highlighting etc.
|
|
46
|
+
- Command palette — press `?` to open a scrollable overview of all available commands and descriptions
|
|
47
|
+
- Time travel — inspect your app 1h, 1 week or 1 year ago
|
|
48
|
+
- Filtering — query issues by description, tags, assignees, etc.
|
|
49
|
+
- Autocompletion — minimize typing, stay in flow, reuse previous commands
|
|
50
|
+
- Multi-user — collaborative synchronization via Git
|
|
51
|
+
- Traceable event log — state is a full history of every change ever made
|
|
52
|
+
- Browser GUI — graphical interface powered by the same Git-backed state
|
|
53
|
+
- MCP integration — Model Context Protocol support for agent interaction
|
|
54
|
+
|
|
57
55
|
---
|
|
58
56
|
|
|
59
57
|
## Installation
|
|
@@ -88,16 +86,16 @@ Git init
|
|
|
88
86
|
epiq
|
|
89
87
|
```
|
|
90
88
|
|
|
91
|
-
If
|
|
89
|
+
If it is your first run, this opens the interactive setup wizard that sets you up in about 30 seconds.
|
|
90
|
+
|
|
91
|
+
That’s it!
|
|
92
|
+
|
|
93
|
+
Once your project is set up, you can also launch the browser user interface with:
|
|
92
94
|
|
|
93
95
|
```bash
|
|
94
96
|
epiq gui
|
|
95
97
|
```
|
|
96
98
|
|
|
97
|
-
If it is your first run, this opens the interactive setup wizard that sets you up in about 30 seconds.
|
|
98
|
-
|
|
99
|
-
That’s it!
|
|
100
|
-
|
|
101
99
|
> Setup wizard creates:
|
|
102
100
|
> User config persisted in `~/.epiq-global/config.json`.
|
|
103
101
|
|
|
@@ -108,7 +106,7 @@ That’s it!
|
|
|
108
106
|
> - Updates your `.gitignore` to ignore local-only `.epiq/log/`
|
|
109
107
|
> Epiq manages a dedicated Git state branch and worktree automatically as the source of truth for synchronization.
|
|
110
108
|
|
|
111
|
-
## Usage Guide
|
|
109
|
+
## Usage Guide (TUI)
|
|
112
110
|
|
|
113
111
|
### Help
|
|
114
112
|
|
|
@@ -129,6 +127,10 @@ That’s it!
|
|
|
129
127
|
|
|
130
128
|
- Create nodes with `:new issue|swimlane|board <Name of new node>`.
|
|
131
129
|
|
|
130
|
+
### Comment
|
|
131
|
+
|
|
132
|
+
- Comment on issues with `:comment <your-input>`. Comments can be edited or deleted with the regular ':edit ...' or ':delete' commands.
|
|
133
|
+
|
|
132
134
|
### Move nodes
|
|
133
135
|
|
|
134
136
|
- Move nodes by pressing `m`. This sets you in a move state, after which you can navigate as normal, navigate to the target location, then press m again to confirm new location.
|
|
@@ -226,4 +228,4 @@ Epiq follows a **local-first** model:
|
|
|
226
228
|
|
|
227
229
|
---
|
|
228
230
|
|
|
229
|
-
🫡
|
|
231
|
+
🫡 Never leave your editor!
|