@hienlh/ppm 0.1.0 → 0.1.1

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.
Files changed (75) hide show
  1. package/dist/web/assets/api-client-Bnf9LAt4.js +1 -0
  2. package/dist/web/assets/arrow-up-from-line-BXL5dtbG.js +1 -0
  3. package/dist/web/assets/button-BxijdhtM.js +1 -0
  4. package/dist/web/assets/chat-tab-BZopEuub.js +61 -0
  5. package/dist/web/assets/code-editor-hbllHzj7.js +2 -0
  6. package/dist/web/assets/createLucideIcon-Dy1wlrF7.js +1 -0
  7. package/dist/web/assets/dialog-RczsXsmw.js +45 -0
  8. package/dist/web/assets/diff-viewer-D6ixPlNB.js +4 -0
  9. package/dist/web/assets/dist-CSp7ir0r.js +46 -0
  10. package/dist/web/assets/external-link-WSiY-639.js +1 -0
  11. package/dist/web/assets/git-graph-DXMB_DoT.js +1 -0
  12. package/dist/web/assets/git-status-panel-D8ZUQrRF.js +1 -0
  13. package/dist/web/assets/index-DGSLw2GE.js +10 -0
  14. package/dist/web/assets/index-DYd_2slk.css +2 -0
  15. package/dist/web/assets/jsx-runtime-BnxRlLMJ.js +1 -0
  16. package/dist/web/assets/project-list-DWVXEimw.js +1 -0
  17. package/dist/web/assets/react-Uzd0zARU.js +1 -0
  18. package/dist/web/assets/refresh-cw-DtopuYJf.js +1 -0
  19. package/dist/web/assets/settings-tab-DJRzIAuP.js +1 -0
  20. package/dist/web/assets/terminal-tab-BrP-ENHg.css +1 -0
  21. package/dist/web/assets/terminal-tab-CbwaI-oq.js +36 -0
  22. package/dist/web/assets/trash-2-CHLebaNh.js +1 -0
  23. package/dist/web/assets/utils-Cgi2TYRi.js +1 -0
  24. package/dist/web/assets/x-BISR7bpK.js +1 -0
  25. package/dist/web/icon-192.svg +5 -0
  26. package/dist/web/icon-512.svg +5 -0
  27. package/dist/web/index.html +25 -0
  28. package/dist/web/manifest.webmanifest +1 -0
  29. package/dist/web/registerSW.js +1 -0
  30. package/dist/web/sw.js +1 -0
  31. package/dist/web/workbox-3e722498.js +1 -0
  32. package/package.json +2 -1
  33. package/.claude/agent-memory/tester/MEMORY.md +0 -3
  34. package/.claude/agent-memory/tester/project-ppm-test-conventions.md +0 -32
  35. package/.github/workflows/release.yml +0 -46
  36. package/plans/260314-2009-ppm-implementation/phase-01-project-skeleton.md +0 -81
  37. package/plans/260314-2009-ppm-implementation/phase-02-backend-core.md +0 -148
  38. package/plans/260314-2009-ppm-implementation/phase-03-frontend-shell.md +0 -256
  39. package/plans/260314-2009-ppm-implementation/phase-04-file-explorer-editor.md +0 -120
  40. package/plans/260314-2009-ppm-implementation/phase-05-web-terminal.md +0 -174
  41. package/plans/260314-2009-ppm-implementation/phase-06-git-integration.md +0 -244
  42. package/plans/260314-2009-ppm-implementation/phase-07-ai-chat.md +0 -242
  43. package/plans/260314-2009-ppm-implementation/phase-08-cli-commands.md +0 -143
  44. package/plans/260314-2009-ppm-implementation/phase-09-pwa-build-deploy.md +0 -209
  45. package/plans/260314-2009-ppm-implementation/phase-10-testing.md +0 -311
  46. package/plans/260314-2009-ppm-implementation/plan.md +0 -202
  47. package/plans/260315-0356-project-scoped-api-refactor/phase-01-backend-project-router.md +0 -145
  48. package/plans/260315-0356-project-scoped-api-refactor/phase-02-frontend-api-migration.md +0 -107
  49. package/plans/260315-0356-project-scoped-api-refactor/phase-03-per-project-tabs.md +0 -100
  50. package/plans/260315-0356-project-scoped-api-refactor/phase-04-websocket-migration.md +0 -66
  51. package/plans/260315-0356-project-scoped-api-refactor/plan.md +0 -87
  52. package/plans/reports/brainstorm-260314-1938-final-techstack.md +0 -342
  53. package/plans/reports/docs-manager-260315-1314-documentation-creation.md +0 -386
  54. package/plans/reports/fullstack-developer-260314-2252-phase-02-backend-core.md +0 -57
  55. package/plans/reports/fullstack-developer-260314-2253-phase-03-frontend-shell.md +0 -70
  56. package/plans/reports/fullstack-developer-260314-2300-phase-04-05-file-api-terminal-ws.md +0 -49
  57. package/plans/reports/fullstack-developer-260314-2300-phase-04-05-file-explorer-editor-terminal.md +0 -52
  58. package/plans/reports/fullstack-developer-260314-2307-ai-chat-phase7.md +0 -58
  59. package/plans/reports/fullstack-developer-260314-2307-phase-06-git-integration.md +0 -33
  60. package/plans/reports/research-260314-1911-ppm-tech-stack.md +0 -318
  61. package/plans/reports/research-260314-1930-claude-code-integration.md +0 -293
  62. package/plans/reports/researcher-260314-2232-node-pty-bun-crash-analysis.md +0 -305
  63. package/plans/reports/researcher-260314-2232-ui-style.md +0 -942
  64. package/plans/reports/researcher-260315-0300-opcode-claude-interaction.md +0 -745
  65. package/plans/reports/researcher-260315-0303-opcode-deep-analysis.md +0 -742
  66. package/plans/reports/researcher-260315-0305-claude-agent-sdk-github-research.md +0 -423
  67. package/plans/reports/tester-260314-2053-initial-test-suite.md +0 -81
  68. package/repomix-output.xml +0 -23745
  69. package/tests/integration/api/chat-routes.test.ts +0 -95
  70. package/tests/integration/claude-agent-sdk-integration.test.ts +0 -228
  71. package/tests/integration/ws/chat-websocket.test.ts +0 -312
  72. package/tests/test-setup.ts +0 -5
  73. package/tests/unit/providers/claude-agent-sdk.test.ts +0 -339
  74. package/tests/unit/providers/mock-provider.test.ts +0 -143
  75. package/tests/unit/services/chat-service.test.ts +0 -100
@@ -0,0 +1 @@
1
+ import{t as e}from"./createLucideIcon-Dy1wlrF7.js";var t=e(`external-link`,[[`path`,{d:`M15 3h6v6`,key:`1q9fwt`}],[`path`,{d:`M10 14 21 3`,key:`gplh6r`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`,key:`a6xqqp`}]]);export{t};
@@ -0,0 +1 @@
1
+ import{i as e,n as t,t as n}from"./jsx-runtime-BnxRlLMJ.js";import{t as r}from"./button-BxijdhtM.js";import{t as i}from"./createLucideIcon-Dy1wlrF7.js";import{t as a}from"./arrow-up-from-line-BXL5dtbG.js";import{t as o}from"./external-link-WSiY-639.js";import{a as s,r as c,t as l}from"./api-client-Bnf9LAt4.js";import{t as u}from"./refresh-cw-DtopuYJf.js";import{t as d}from"./trash-2-CHLebaNh.js";import{a as f,i as p,n as m,o as h,t as g}from"./dialog-RczsXsmw.js";import{a as _,c as v,h as y,i as b,o as x,r as ee,s as S,u as te}from"./index-DGSLw2GE.js";var ne=i(`cherry`,[[`path`,{d:`M2 17a5 5 0 0 0 10 0c0-2.76-2.5-5-5-3-2.5-2-5 .24-5 3Z`,key:`cvxqlc`}],[`path`,{d:`M12 17a5 5 0 0 0 10 0c0-2.76-2.5-5-5-3-2.5-2-5 .24-5 3Z`,key:`1ostrc`}],[`path`,{d:`M7 14c3.22-2.91 4.29-8.75 5-12 1.66 2.38 4.94 9 5 12`,key:`hqx58h`}],[`path`,{d:`M22 9c-4.29 0-7.14-2.33-10-7 5.71 0 10 4.67 10 7Z`,key:`eykp1o`}]]),re=i(`copy`,[[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]),C=i(`git-merge`,[[`circle`,{cx:`18`,cy:`18`,r:`3`,key:`1xkwt0`}],[`circle`,{cx:`6`,cy:`6`,r:`3`,key:`1lh9wr`}],[`path`,{d:`M6 21V9a9 9 0 0 0 9 9`,key:`7kw0sc`}]]),ie=i(`grip-vertical`,[[`circle`,{cx:`9`,cy:`12`,r:`1`,key:`1vctgf`}],[`circle`,{cx:`9`,cy:`5`,r:`1`,key:`hp0tcf`}],[`circle`,{cx:`9`,cy:`19`,r:`1`,key:`fkjjf6`}],[`circle`,{cx:`15`,cy:`12`,r:`1`,key:`1tmaij`}],[`circle`,{cx:`15`,cy:`5`,r:`1`,key:`19l28e`}],[`circle`,{cx:`15`,cy:`19`,r:`1`,key:`f4zoj3`}]]),ae=i(`rotate-ccw`,[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`1357e3`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}]]),w=i(`tag`,[[`path`,{d:`M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z`,key:`vktsd0`}],[`circle`,{cx:`7.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`kqv944`}]]),T=e(t(),1),E=n(),D=[`#4fc3f7`,`#81c784`,`#ffb74d`,`#e57373`,`#ba68c8`,`#4dd0e1`,`#aed581`,`#ff8a65`,`#f06292`,`#7986cb`],O=32,k=20,oe=5;function A({metadata:e}){let t=e?.projectName,[n,i]=(0,T.useState)(null),[a,o]=(0,T.useState)(!0),[d,C]=(0,T.useState)(null),[A,j]=(0,T.useState)(!1),[M,N]=(0,T.useState)({type:null}),[P,F]=(0,T.useState)(``),[I,L]=(0,T.useState)(null),[R,z]=(0,T.useState)([]),[ce,B]=(0,T.useState)(!1),{openTab:V}=te(),H=(0,T.useCallback)(async()=>{if(t)try{o(!0),i(await l.get(`${c(t)}/git/graph?max=200`)),C(null)}catch(e){C(e instanceof Error?e.message:`Failed to fetch graph`)}finally{o(!1)}},[t]);(0,T.useEffect)(()=>{H()},[H]);let U=async(e,n)=>{if(t){j(!0);try{await l.post(`${c(t)}${e}`,n),await H()}catch(e){C(e instanceof Error?e.message:`Action failed`)}finally{j(!1)}}},W=e=>U(`/git/checkout`,{ref:e}),le=e=>U(`/git/cherry-pick`,{hash:e}),ue=e=>U(`/git/revert`,{hash:e}),de=e=>U(`/git/merge`,{source:e}),fe=e=>U(`/git/branch/delete`,{name:e}),pe=e=>U(`/git/push`,{branch:e}),G=async(e,t)=>{if(n?.branches.some(t=>t.name===e||t.name.endsWith(`/${e}`))){if(!window.confirm(`Branch "${e}" already exists.\nDelete it and recreate from this commit?`))return;await U(`/git/branch/delete`,{name:e})}await U(`/git/branch/create`,{name:e,from:t})},K=(e,t)=>U(`/git/tag`,{name:e,hash:t}),me=async e=>{if(t)try{let n=await l.get(`${c(t)}/git/pr-url?branch=${encodeURIComponent(e)}`);n.url&&window.open(n.url,`_blank`)}catch{}},q=e=>{navigator.clipboard.writeText(e)},he=async e=>{if(I?.hash===e.hash){L(null);return}L(e),B(!0);try{let n=e.parents[0]??``,r=n?`ref1=${encodeURIComponent(n)}&`:``,i=await l.get(`${c(t)}/git/diff-stat?${r}ref2=${encodeURIComponent(e.hash)}`);z(Array.isArray(i)?i:[])}catch(e){console.error(`diff-stat error:`,e),z([])}finally{B(!1)}},ge=e=>{let n=e.parents[0];V({type:`git-diff`,title:`Diff ${e.abbreviatedHash}`,closable:!0,metadata:{projectName:t,ref1:n??void 0,ref2:e.hash},projectId:t??null})},{laneMap:J,maxLane:_e}=(0,T.useMemo)(()=>{let e=new Map;if(!n)return{laneMap:e,maxLane:0};let t=0,r=new Map;for(let i of n.commits){let n=r.get(i.hash);n===void 0&&(n=t++),e.set(i.hash,n),r.delete(i.hash);for(let e=0;e<i.parents.length;e++){let a=i.parents[e];r.has(a)||r.set(a,e===0?n:t++)}}return{laneMap:e,maxLane:Math.max(t-1,0)}},[n]),Y=n?.branches.find(e=>e.current),ve=(0,T.useMemo)(()=>{let e=new Map;if(!n)return e;for(let t of n.branches){let n=e.get(t.commitHash)??[];n.push({name:t.name,type:`branch`}),e.set(t.commitHash,n)}for(let t of n.commits)for(let n of t.refs)if(n.startsWith(`tag: `)){let r=n.replace(`tag: `,``),i=e.get(t.hash)??[];i.push({name:r,type:`tag`}),e.set(t.hash,i)}return e},[n]),ye=(0,T.useMemo)(()=>{if(!n)return[];let e=[];for(let t=0;t<n.commits.length;t++){let r=n.commits[t],i=J.get(r.hash)??0,a=D[i%D.length];for(let o of r.parents){let s=n.commits.findIndex(e=>e.hash===o);if(s<0)continue;let c=J.get(o)??0,l=D[c%D.length],u=i*k+k/2,d=t*O+O/2,f=c*k+k/2,p=s*O+O/2,m,h=r.parents.indexOf(o)>0;if(u===f)m=`M ${u} ${d} L ${f} ${p}`;else if(h){let e=d+O;m=`M ${u} ${d} C ${u} ${e} ${f} ${d} ${f} ${e} L ${f} ${p}`}else{let e=p-O;m=`M ${u} ${d} L ${u} ${e} C ${u} ${p} ${f} ${e} ${f} ${p}`}let g=r.parents.indexOf(o)===0?a:l;e.push({d:m,color:g})}}return e},[n,J]);(_e+1)*k+k;let X=(n?.commits.length??0)*O,[Z,be]=(0,T.useState)((typeof window<`u`&&window.innerWidth<768?6:10)*k+k),Q=(0,T.useRef)(!1),$=(0,T.useCallback)(e=>{Q.current=!0;let t=Z,n=n=>{if(!Q.current)return;let r=`touches`in n?n.touches[0].clientX:n.clientX;be(Math.max(40,t+r-e))},r=()=>{Q.current=!1,window.removeEventListener(`mousemove`,n),window.removeEventListener(`mouseup`,r),window.removeEventListener(`touchmove`,n),window.removeEventListener(`touchend`,r)};window.addEventListener(`mousemove`,n),window.addEventListener(`mouseup`,r),window.addEventListener(`touchmove`,n,{passive:!1}),window.addEventListener(`touchend`,r)},[Z]),xe=(0,T.useCallback)(e=>{e.preventDefault(),$(e.clientX)},[$]),Se=(0,T.useCallback)(e=>{$(e.touches[0].clientX)},[$]);if(!t)return(0,E.jsx)(`div`,{className:`flex items-center justify-center h-full text-muted-foreground text-sm`,children:`No project selected.`});if(a&&!n)return(0,E.jsxs)(`div`,{className:`flex items-center justify-center h-full gap-2 text-muted-foreground`,children:[(0,E.jsx)(s,{className:`size-5 animate-spin`}),(0,E.jsx)(`span`,{className:`text-sm`,children:`Loading git graph...`})]});if(d&&!n)return(0,E.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-2 text-destructive text-sm`,children:[(0,E.jsx)(`p`,{children:d}),(0,E.jsx)(r,{variant:`outline`,size:`sm`,onClick:H,children:`Retry`})]});function Ce(e){let t=new Date(e),n=new Date().getTime()-t.getTime(),r=Math.floor(n/6e4);if(r<1)return`just now`;if(r<60)return`${r}m ago`;let i=Math.floor(r/60);if(i<24)return`${i}h ago`;let a=Math.floor(i/24);if(a<30)return`${a}d ago`;let o=Math.floor(a/30);return o<12?`${o}mo ago`:`${Math.floor(o/12)}y ago`}return(0,E.jsxs)(`div`,{className:`flex flex-col h-full`,children:[(0,E.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2 border-b`,children:[(0,E.jsxs)(`span`,{className:`text-sm font-medium`,children:[`Git Graph`,Y?` - ${Y.name}`:``]}),(0,E.jsx)(r,{variant:`ghost`,size:`icon-xs`,onClick:H,disabled:A,children:(0,E.jsx)(u,{className:a?`animate-spin`:``})})]}),d&&(0,E.jsx)(`div`,{className:`px-3 py-1.5 text-xs text-destructive bg-destructive/10`,children:d}),(0,E.jsx)(`div`,{className:`flex-1 overflow-y-auto overflow-x-auto md:overflow-x-hidden`,children:(0,E.jsxs)(`div`,{className:`flex min-w-max md:min-w-0`,style:{height:`${X}px`},children:[(0,E.jsxs)(`div`,{className:`sticky left-0 z-10 shrink-0 bg-background`,style:{width:`${Z}px`},children:[(0,E.jsxs)(`svg`,{width:Z,height:X,children:[ye.map((e,t)=>(0,E.jsx)(`path`,{d:e.d,stroke:e.color,strokeWidth:2,fill:`none`},t)),n?.commits.map((e,t)=>{let n=J.get(e.hash)??0,r=n*k+k/2,i=t*O+O/2,a=D[n%D.length];return(0,E.jsx)(`circle`,{cx:r,cy:i,r:oe,fill:a,stroke:`#0f1419`,strokeWidth:2},e.hash)})]}),(0,E.jsx)(`div`,{className:`absolute top-0 right-0 w-3 md:w-2 h-full cursor-col-resize hover:bg-primary/20 flex items-center justify-center bg-primary/10 md:bg-transparent`,onMouseDown:xe,onTouchStart:Se,children:(0,E.jsx)(ie,{className:`size-3 text-muted-foreground md:opacity-0 md:hover:opacity-100`})})]}),(0,E.jsx)(`div`,{className:`flex-1 min-w-[400px]`,children:n?.commits.map((e,t)=>{let n=D[(J.get(e.hash)??0)%D.length],r=ve.get(e.hash)??[],i=r.filter(e=>e.type===`branch`),a=r.filter(e=>e.type===`tag`);return(0,E.jsxs)(b,{children:[(0,E.jsx)(v,{asChild:!0,children:(0,E.jsx)(`div`,{className:`flex items-center hover:bg-muted/50 cursor-pointer text-sm border-b border-border/30 ${I?.hash===e.hash?`bg-primary/10`:``}`,style:{height:`${O}px`},onClick:()=>he(e),children:(0,E.jsxs)(`div`,{className:`flex items-center gap-2 flex-1 min-w-0 px-2`,children:[(0,E.jsx)(`span`,{className:`font-mono text-xs text-muted-foreground w-14 shrink-0`,children:e.abbreviatedHash}),i.map(e=>(0,E.jsx)(se,{label:e,color:n,currentBranch:Y,onCheckout:W,onMerge:de,onPush:pe,onCreatePr:me,onDelete:fe},`branch-${e.name}`)),a.map(e=>(0,E.jsxs)(`span`,{className:`inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 bg-amber-500/20 text-amber-500 border border-amber-500/30`,children:[(0,E.jsx)(w,{className:`size-2.5`}),e.name]},`tag-${e.name}`)),(0,E.jsx)(`span`,{className:`flex-1 truncate`,children:e.subject}),(0,E.jsx)(`span`,{className:`text-xs text-muted-foreground shrink-0 hidden sm:inline`,children:e.authorName}),(0,E.jsx)(`span`,{className:`text-xs text-muted-foreground shrink-0 w-14 text-right`,children:Ce(e.authorDate)})]})})}),(0,E.jsxs)(_,{children:[(0,E.jsx)(x,{onClick:()=>W(e.hash),children:`Checkout`}),(0,E.jsxs)(x,{onClick:()=>{N({type:`branch`,hash:e.hash}),F(``)},children:[(0,E.jsx)(y,{className:`size-3`}),`Create Branch...`]}),(0,E.jsx)(S,{}),(0,E.jsxs)(x,{onClick:()=>le(e.hash),children:[(0,E.jsx)(ne,{className:`size-3`}),`Cherry Pick`]}),(0,E.jsxs)(x,{onClick:()=>ue(e.hash),children:[(0,E.jsx)(ae,{className:`size-3`}),`Revert`]}),(0,E.jsxs)(x,{onClick:()=>{N({type:`tag`,hash:e.hash}),F(``)},children:[(0,E.jsx)(w,{className:`size-3`}),`Create Tag...`]}),(0,E.jsx)(S,{}),(0,E.jsx)(x,{onClick:()=>ge(e),children:`View Diff`}),(0,E.jsxs)(x,{onClick:()=>q(e.hash),children:[(0,E.jsx)(re,{className:`size-3`}),`Copy Hash`]})]})]},e.hash)})})]})}),I&&(0,E.jsxs)(`div`,{className:`border-t bg-muted/30 max-h-[40%] overflow-auto`,children:[(0,E.jsxs)(`div`,{className:`px-3 py-2 border-b flex items-center justify-between`,children:[(0,E.jsxs)(`span`,{className:`text-sm font-medium truncate`,children:[I.abbreviatedHash,` — `,I.subject]}),(0,E.jsx)(r,{variant:`ghost`,size:`icon-xs`,onClick:()=>L(null),children:`✕`})]}),(0,E.jsxs)(`div`,{className:`px-3 py-2 text-xs space-y-1`,children:[(0,E.jsxs)(`div`,{className:`flex gap-4`,children:[(0,E.jsx)(`span`,{className:`text-muted-foreground`,children:`Author`}),(0,E.jsxs)(`span`,{children:[I.authorName,` <`,I.authorEmail,`>`]})]}),(0,E.jsxs)(`div`,{className:`flex gap-4`,children:[(0,E.jsx)(`span`,{className:`text-muted-foreground`,children:`Date`}),(0,E.jsx)(`span`,{children:new Date(I.authorDate).toLocaleString()})]}),(0,E.jsxs)(`div`,{className:`flex gap-4`,children:[(0,E.jsx)(`span`,{className:`text-muted-foreground`,children:`Hash`}),(0,E.jsx)(`span`,{className:`font-mono cursor-pointer hover:text-primary`,onClick:()=>q(I.hash),children:I.hash})]}),I.parents.length>0&&(0,E.jsxs)(`div`,{className:`flex gap-4`,children:[(0,E.jsx)(`span`,{className:`text-muted-foreground`,children:`Parents`}),(0,E.jsx)(`span`,{className:`font-mono`,children:I.parents.map(e=>e.slice(0,7)).join(`, `)})]}),I.body&&(0,E.jsx)(`div`,{className:`mt-2 p-2 bg-background rounded text-xs whitespace-pre-wrap`,children:I.body})]}),(0,E.jsxs)(`div`,{className:`px-3 py-1 border-t`,children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground py-1`,children:ce?`Loading files...`:`${R.length} file${R.length===1?``:`s`} changed`}),R.map(e=>(0,E.jsxs)(`div`,{className:`flex items-center gap-2 py-0.5 text-xs hover:bg-muted/50 rounded px-1 cursor-pointer`,onClick:()=>V({type:`git-diff`,title:`Diff ${e.path.split(`/`).pop()}`,closable:!0,metadata:{projectName:t,ref1:I.parents[0]??void 0,ref2:I.hash,filePath:e.path},projectId:t??null}),children:[(0,E.jsx)(`span`,{className:`flex-1 truncate font-mono`,children:e.path}),e.additions>0&&(0,E.jsxs)(`span`,{className:`text-green-500`,children:[`+`,e.additions]}),e.deletions>0&&(0,E.jsxs)(`span`,{className:`text-red-500`,children:[`-`,e.deletions]})]},e.path))]})]}),(0,E.jsx)(g,{open:M.type!==null,onOpenChange:e=>{e||N({type:null})},children:(0,E.jsxs)(m,{children:[(0,E.jsx)(f,{children:(0,E.jsx)(h,{children:M.type===`branch`?`Create Branch`:`Create Tag`})}),(0,E.jsx)(ee,{placeholder:M.type===`branch`?`Branch name`:`Tag name`,value:P,onChange:e=>F(e.target.value),onKeyDown:e=>{e.key===`Enter`&&P.trim()&&(M.type===`branch`?G(P.trim(),M.hash):K(P.trim(),M.hash),N({type:null}))},autoFocus:!0}),(0,E.jsxs)(p,{children:[(0,E.jsx)(r,{variant:`outline`,onClick:()=>N({type:null}),children:`Cancel`}),(0,E.jsx)(r,{disabled:!P.trim(),onClick:()=>{M.type===`branch`?G(P.trim(),M.hash):K(P.trim(),M.hash),N({type:null})},children:`Create`})]})]})})]})}function se({label:e,color:t,currentBranch:n,onCheckout:r,onMerge:i,onPush:s,onCreatePr:c,onDelete:l}){return(0,E.jsxs)(b,{children:[(0,E.jsx)(v,{asChild:!0,children:(0,E.jsxs)(`span`,{className:`inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 cursor-context-menu`,style:{backgroundColor:`${t}30`,color:t,border:`1px solid ${t}50`},children:[(0,E.jsx)(y,{className:`size-2.5`}),e.name]})}),(0,E.jsxs)(_,{children:[(0,E.jsx)(x,{onClick:()=>r(e.name),children:`Checkout`}),(0,E.jsxs)(x,{onClick:()=>i(e.name),disabled:e.name===n?.name,children:[(0,E.jsx)(C,{className:`size-3`}),`Merge into current`]}),(0,E.jsx)(S,{}),(0,E.jsxs)(x,{onClick:()=>s(e.name),children:[(0,E.jsx)(a,{className:`size-3`}),`Push`]}),(0,E.jsxs)(x,{onClick:()=>c(e.name),children:[(0,E.jsx)(o,{className:`size-3`}),`Create PR`]}),(0,E.jsx)(S,{}),(0,E.jsxs)(x,{variant:`destructive`,onClick:()=>l(e.name),disabled:e.name===n?.name,children:[(0,E.jsx)(d,{className:`size-3`}),`Delete`]})]})]})}export{A as GitGraph};
@@ -0,0 +1 @@
1
+ import{i as e,n as t,t as n}from"./jsx-runtime-BnxRlLMJ.js";import{t as r}from"./button-BxijdhtM.js";import{t as i}from"./createLucideIcon-Dy1wlrF7.js";import{t as a}from"./arrow-up-from-line-BXL5dtbG.js";import{a as o,r as s,t as c}from"./api-client-Bnf9LAt4.js";import{t as l}from"./refresh-cw-DtopuYJf.js";import{a as u,i as d,n as f,o as p,r as m,t as h}from"./dialog-RczsXsmw.js";import{C as g,d as _,p as v,u as y,w as b}from"./index-DGSLw2GE.js";var x=i(`arrow-down-to-line`,[[`path`,{d:`M12 17V3`,key:`1cwfxf`}],[`path`,{d:`m6 11 6 6 6-6`,key:`12ii2o`}],[`path`,{d:`M19 21H5`,key:`150jfl`}]]),S=i(`folder-tree`,[[`path`,{d:`M20 10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-2.5a1 1 0 0 1-.8-.4l-.9-1.2A1 1 0 0 0 15 3h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z`,key:`hod4my`}],[`path`,{d:`M20 21a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1h-2.9a1 1 0 0 1-.88-.55l-.42-.85a1 1 0 0 0-.92-.6H13a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z`,key:`w4yl2u`}],[`path`,{d:`M3 5a2 2 0 0 0 2 2h3`,key:`f2jnh7`}],[`path`,{d:`M3 3v13a2 2 0 0 0 2 2h3`,key:`k8epm1`}]]),C=i(`list`,[[`path`,{d:`M3 5h.01`,key:`18ugdj`}],[`path`,{d:`M3 12h.01`,key:`nlz23k`}],[`path`,{d:`M3 19h.01`,key:`noohij`}],[`path`,{d:`M8 5h13`,key:`1pao27`}],[`path`,{d:`M8 12h13`,key:`1za7za`}],[`path`,{d:`M8 19h13`,key:`m83p4d`}]]),w=i(`minus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}]]),T=i(`undo-2`,[[`path`,{d:`M9 14 4 9l5-5`,key:`102s5s`}],[`path`,{d:`M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11`,key:`f3b9sd`}]]),E=e(t(),1),D=n(),O={M:`text-yellow-500`,A:`text-green-500`,D:`text-red-500`,R:`text-blue-500`,C:`text-purple-500`,"?":`text-gray-400`};function k(e){let t=[];for(let n of e){let e=n.path.split(`/`),r=t;for(let t=0;t<e.length;t++){let i=e[t],a=e.slice(0,t+1).join(`/`),o=t===e.length-1,s=r.find(e=>e.name===i);s||(s={name:i,fullPath:a,file:o?n:void 0,children:[]},r.push(s)),o&&(s.file=n),r=s.children}}return t}function A(e){let t=[];e.file&&t.push(e.file);for(let n of e.children)t.push(...A(n));return t}function j({metadata:e,tabId:t}){let n=e?.projectName,[i,g]=(0,E.useState)(null),[b,T]=(0,E.useState)(!0),[O,k]=(0,E.useState)(null),[A,j]=(0,E.useState)(``),[M,P]=(0,E.useState)(!1),[F,I]=(0,E.useState)(null),{openTab:L,updateTab:R}=y(),z=e?.viewMode===`tree`?`tree`:`flat`,B=n=>{t&&R(t,{metadata:{...e,viewMode:n}})},V=(0,E.useCallback)(async()=>{if(n)try{T(!0),g(await c.get(`${s(n)}/git/status`)),k(null)}catch(e){k(e instanceof Error?e.message:`Failed to fetch status`)}finally{T(!1)}},[n]);(0,E.useEffect)(()=>{V()},[V]);let H=async e=>{if(n){P(!0);try{await c.post(`${s(n)}/git/stage`,{files:e}),await V()}catch(e){k(e instanceof Error?e.message:`Stage failed`)}finally{P(!1)}}},U=async e=>{if(n){P(!0);try{await c.post(`${s(n)}/git/unstage`,{files:e}),await V()}catch(e){k(e instanceof Error?e.message:`Unstage failed`)}finally{P(!1)}}},W=async e=>{if(n){P(!0);try{await c.post(`${s(n)}/git/discard`,{files:e}),await V()}catch(e){k(e instanceof Error?e.message:`Discard failed`)}finally{P(!1)}}},G=async()=>{F&&(await W(F.files),I(null))},K=async()=>{if(!(!n||!A.trim()||!i?.staged.length)){P(!0);try{await c.post(`${s(n)}/git/commit`,{message:A.trim()}),j(``),await V()}catch(e){k(e instanceof Error?e.message:`Commit failed`)}finally{P(!1)}}},q=async()=>{if(n){P(!0);try{await c.post(`${s(n)}/git/push`,{}),await V()}catch(e){k(e instanceof Error?e.message:`Push failed`)}finally{P(!1)}}},J=async()=>{if(n){P(!0);try{await c.post(`${s(n)}/git/pull`,{}),await V()}catch(e){k(e instanceof Error?e.message:`Pull failed`)}finally{P(!1)}}},Y=e=>{L({type:`git-diff`,title:e.path.split(`/`).pop()??e.path,closable:!0,metadata:{projectName:n,filePath:e.path},projectId:n??null})},X=(0,E.useMemo)(()=>[...i?.unstaged??[],...i?.untracked.map(e=>({path:e,status:`?`}))??[]],[i]);return n?b&&!i?(0,D.jsxs)(`div`,{className:`flex items-center justify-center h-full gap-2 text-muted-foreground`,children:[(0,D.jsx)(o,{className:`size-5 animate-spin`}),(0,D.jsx)(`span`,{className:`text-sm`,children:`Loading git status...`})]}):O&&!i?(0,D.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-2 text-destructive text-sm`,children:[(0,D.jsx)(`p`,{children:O}),(0,D.jsx)(r,{variant:`outline`,size:`sm`,onClick:V,children:`Retry`})]}):(0,D.jsxs)(`div`,{className:`flex flex-col h-full overflow-hidden`,children:[(0,D.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2 border-b shrink-0`,children:[(0,D.jsx)(`span`,{className:`text-sm font-medium`,children:i?.current?`On: ${i.current}`:`Git Status`}),(0,D.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,D.jsx)(r,{variant:z===`flat`?`secondary`:`ghost`,size:`icon-xs`,onClick:()=>B(`flat`),title:`Flat view`,children:(0,D.jsx)(C,{className:`size-3.5`})}),(0,D.jsx)(r,{variant:z===`tree`?`secondary`:`ghost`,size:`icon-xs`,onClick:()=>B(`tree`),title:`Tree view`,children:(0,D.jsx)(S,{className:`size-3.5`})}),(0,D.jsx)(r,{variant:`ghost`,size:`icon-xs`,onClick:V,disabled:M,children:(0,D.jsx)(l,{className:b?`animate-spin`:``})})]})]}),O&&(0,D.jsx)(`div`,{className:`px-3 py-1.5 text-xs text-destructive bg-destructive/10 shrink-0`,children:O}),(0,D.jsx)(_,{className:`flex-1 overflow-hidden`,children:(0,D.jsxs)(`div`,{className:`p-2 space-y-3 overflow-hidden`,children:[(0,D.jsx)(N,{title:`Staged Changes`,count:i?.staged.length??0,files:i?.staged??[],viewMode:z,actionIcon:(0,D.jsx)(w,{className:`size-3.5`}),actionTitle:`Unstage`,onAction:e=>U([e.path]),onActionAll:i?.staged.length?()=>U(i.staged.map(e=>e.path)):void 0,actionAllLabel:`Unstage All`,onFolderAction:e=>U(e.map(e=>e.path)),onClickFile:Y,disabled:M}),(0,D.jsx)(N,{title:`Changes`,count:X.length,files:X,viewMode:z,actionIcon:(0,D.jsx)(v,{className:`size-3.5`}),actionTitle:`Stage`,onAction:e=>H([e.path]),onActionAll:X.length?()=>H(X.map(e=>e.path)):void 0,actionAllLabel:`Stage All`,onFolderAction:e=>H(e.map(e=>e.path)),onClickFile:Y,disabled:M,showRevert:!0,onRevert:e=>I({label:e.path,files:[e.path]}),onFolderRevert:(e,t)=>I({label:`${t}/ (${e.length} files)`,files:e.map(e=>e.path)})})]})}),(0,D.jsxs)(`div`,{className:`border-t p-2 space-y-2 shrink-0`,children:[(0,D.jsx)(`textarea`,{className:`w-full h-16 px-2 py-1.5 text-sm bg-muted/50 border rounded resize-none focus:outline-none focus:ring-1 focus:ring-ring`,placeholder:`Commit message...`,value:A,onChange:e=>j(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.metaKey||e.ctrlKey)&&K()}}),(0,D.jsx)(r,{size:`sm`,className:`w-full`,disabled:M||!A.trim()||!i?.staged.length,onClick:K,children:M?(0,D.jsx)(o,{className:`size-3 animate-spin`}):`Commit (${i?.staged.length??0})`}),(0,D.jsxs)(`div`,{className:`flex gap-2`,children:[(0,D.jsxs)(r,{variant:`outline`,size:`sm`,className:`flex-1`,disabled:M,onClick:q,children:[(0,D.jsx)(a,{className:`size-3`}),`Push`]}),(0,D.jsxs)(r,{variant:`outline`,size:`sm`,className:`flex-1`,disabled:M,onClick:J,children:[(0,D.jsx)(x,{className:`size-3`}),`Pull`]})]})]}),(0,D.jsx)(h,{open:!!F,onOpenChange:e=>!e&&I(null),children:(0,D.jsxs)(f,{showCloseButton:!1,children:[(0,D.jsxs)(u,{children:[(0,D.jsx)(p,{children:`Discard Changes`}),(0,D.jsxs)(m,{children:[`Are you sure you want to discard all changes to`,` `,(0,D.jsx)(`code`,{className:`px-1 py-0.5 rounded bg-muted text-sm font-mono`,children:F?.label}),`? This action cannot be undone.`]})]}),(0,D.jsxs)(d,{children:[(0,D.jsx)(r,{variant:`outline`,onClick:()=>I(null),children:`Cancel`}),(0,D.jsx)(r,{variant:`destructive`,onClick:G,disabled:M,children:M?(0,D.jsx)(o,{className:`size-3 animate-spin`}):`Discard`})]})]})})]}):(0,D.jsx)(`div`,{className:`flex items-center justify-center h-full text-muted-foreground text-sm`,children:`No project selected.`})}function M({showRevert:e,onRevert:t,onAction:n,actionIcon:r,actionTitle:i,disabled:a}){return(0,D.jsxs)(`div`,{className:`flex items-center gap-0.5 shrink-0 ml-1`,children:[e&&t&&(0,D.jsx)(`button`,{type:`button`,className:`flex items-center justify-center size-7 rounded border border-border/60 bg-muted/60 text-muted-foreground hover:bg-destructive/15 hover:text-destructive hover:border-destructive/40 active:scale-95 transition-colors`,onClick:e=>{e.stopPropagation(),t()},disabled:a,title:`Discard changes`,children:(0,D.jsx)(T,{className:`size-3.5`})}),(0,D.jsx)(`button`,{type:`button`,className:`flex items-center justify-center size-7 rounded border border-border/60 bg-muted/60 text-muted-foreground hover:bg-accent hover:text-accent-foreground active:scale-95 transition-colors`,onClick:e=>{e.stopPropagation(),n()},disabled:a,title:i,children:r})]})}function N({title:e,count:t,files:n,viewMode:i,actionIcon:a,actionTitle:o,onAction:s,onActionAll:c,actionAllLabel:l,onFolderAction:u,onClickFile:d,disabled:f,showRevert:p,onRevert:m,onFolderRevert:h}){return(0,D.jsxs)(`div`,{children:[(0,D.jsxs)(`div`,{className:`flex items-center justify-between mb-1`,children:[(0,D.jsxs)(`span`,{className:`text-xs font-medium text-muted-foreground uppercase`,children:[e,` (`,t,`)`]}),c&&t>0&&(0,D.jsx)(r,{variant:`ghost`,size:`xs`,onClick:c,disabled:f,title:l,children:l})]}),n.length===0?(0,D.jsx)(`p`,{className:`text-xs text-muted-foreground px-1`,children:`No changes`}):i===`flat`?(0,D.jsx)(`div`,{className:`divide-y divide-border/40 w-full overflow-hidden`,children:n.map(e=>(0,D.jsx)(P,{file:e,actionIcon:a,actionTitle:o,onAction:s,onClickFile:d,disabled:f,showRevert:p,onRevert:m},e.path))}):(0,D.jsx)(F,{files:n,actionIcon:a,actionTitle:o,onAction:s,onFolderAction:u,onClickFile:d,disabled:f,showRevert:p,onRevert:m,onFolderRevert:h})]})}function P({file:e,actionIcon:t,actionTitle:n,onAction:r,onClickFile:i,disabled:a,showRevert:o,onRevert:s,displayName:c}){return(0,D.jsxs)(`div`,{className:`flex items-center gap-1 hover:bg-muted/50 rounded px-1 py-1 w-full min-w-0`,children:[(0,D.jsx)(`span`,{className:`text-xs font-mono w-4 text-center shrink-0 ${O[e.status]??``}`,children:e.status}),(0,D.jsx)(`button`,{type:`button`,className:`flex-1 text-left text-xs font-mono truncate hover:underline min-w-0`,onClick:()=>i(e),title:e.path,children:c??e.path}),(0,D.jsx)(M,{showRevert:o,onRevert:s?()=>s(e):void 0,onAction:()=>r(e),actionIcon:t,actionTitle:n,disabled:a})]})}function F({files:e,actionIcon:t,actionTitle:n,onAction:r,onFolderAction:i,onClickFile:a,disabled:o,showRevert:s,onRevert:c,onFolderRevert:l}){let u=(0,E.useMemo)(()=>k(e),[e]);return(0,D.jsx)(`div`,{children:u.map((e,d)=>(0,D.jsx)(I,{node:e,depth:0,isLast:d===u.length-1,actionIcon:t,actionTitle:n,onAction:r,onFolderAction:i,onClickFile:a,disabled:o,showRevert:s,onRevert:c,onFolderRevert:l},e.fullPath))})}function I({node:e,depth:t,isLast:n,actionIcon:r,actionTitle:i,onAction:a,onFolderAction:o,onClickFile:s,disabled:c,showRevert:l,onRevert:u,onFolderRevert:d}){let[f,p]=(0,E.useState)(!0),m=e.children.length>0&&!e.file;if(e.file)return(0,D.jsxs)(`div`,{className:`relative overflow-hidden border-b border-border/30`,style:{paddingLeft:t*16},children:[t>0&&(0,D.jsx)(`div`,{className:`absolute top-0 bottom-0 border-l border-border/30`,style:{left:t*16-8}}),(0,D.jsx)(P,{file:e.file,displayName:e.name,actionIcon:r,actionTitle:i,onAction:a,onClickFile:s,disabled:c,showRevert:l,onRevert:u})]});if(m){let m=A(e);return(0,D.jsxs)(`div`,{className:`relative overflow-hidden`,children:[t>0&&(0,D.jsx)(`div`,{className:`absolute top-0 border-l border-border/30`,style:{left:t*16-8,bottom:n?`50%`:0}}),(0,D.jsxs)(`div`,{className:`flex items-center hover:bg-muted/50 rounded py-1 pr-1 border-b border-border/30`,style:{paddingLeft:t*16+4},children:[(0,D.jsxs)(`button`,{type:`button`,className:`flex items-center gap-1 flex-1 min-w-0 text-xs font-mono text-muted-foreground`,onClick:()=>p(!f),children:[f?(0,D.jsx)(b,{className:`size-3.5 shrink-0`}):(0,D.jsx)(g,{className:`size-3.5 shrink-0`}),(0,D.jsx)(`span`,{className:`truncate font-semibold`,children:e.name}),(0,D.jsxs)(`span`,{className:`text-[10px] opacity-60 shrink-0`,children:[`(`,m.length,`)`]})]}),(0,D.jsx)(M,{showRevert:l,onRevert:d?()=>d(m,e.fullPath):void 0,onAction:()=>o?.(m),actionIcon:r,actionTitle:`${i} ${e.name}/`,disabled:c})]}),f&&(0,D.jsxs)(`div`,{className:`relative`,children:[(0,D.jsx)(`div`,{className:`absolute top-0 bottom-0 border-l border-border/30`,style:{left:t*16+8}}),e.children.map((n,f)=>(0,D.jsx)(I,{node:n,depth:t+1,isLast:f===e.children.length-1,actionIcon:r,actionTitle:i,onAction:a,onFolderAction:o,onClickFile:s,disabled:c,showRevert:l,onRevert:u,onFolderRevert:d},n.fullPath))]})]})}return null}export{j as GitStatusPanel};