@hienlh/ppm 0.6.7 → 0.7.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 (52) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +86 -313
  3. package/dist/web/assets/chat-tab-CbNbBMGw.js +7 -0
  4. package/dist/web/assets/{code-editor-BUg7alP6.js → code-editor-D6OuzcC-.js} +1 -1
  5. package/dist/web/assets/{database-viewer-CAgZOkZc.js → database-viewer-BxUpM_uA.js} +1 -1
  6. package/dist/web/assets/{diff-viewer-DVvY1aFb.js → diff-viewer-DAhrHpNM.js} +1 -1
  7. package/dist/web/assets/{dist-Jb3Tnkpc.js → dist-CNRrBoQi.js} +14 -14
  8. package/dist/web/assets/git-graph-BpTt5iOd.js +1 -0
  9. package/dist/web/assets/index-BU_07_oW.js +29 -0
  10. package/dist/web/assets/index-CBQhXXeV.css +2 -0
  11. package/dist/web/assets/keybindings-store-C0m8_V9X.js +1 -0
  12. package/dist/web/assets/{markdown-renderer-z99RjIxZ.js → markdown-renderer-CvGYO9sH.js} +2 -2
  13. package/dist/web/assets/postgres-viewer-BL99auSm.js +1 -0
  14. package/dist/web/assets/{settings-tab-BnDkeQWk.js → settings-tab-Bwsxb41F.js} +1 -1
  15. package/dist/web/assets/{sqlite-viewer-EwHWc37J.js → sqlite-viewer-DfgaCbWT.js} +1 -1
  16. package/dist/web/assets/{terminal-tab-CTN18lb6.js → terminal-tab-D27e4ZTD.js} +2 -2
  17. package/dist/web/index.html +4 -3
  18. package/dist/web/sw.js +1 -1
  19. package/package.json +1 -1
  20. package/src/lib/network-utils.ts +12 -0
  21. package/src/providers/claude-agent-sdk.ts +61 -3
  22. package/src/server/routes/chat.ts +5 -1
  23. package/src/server/routes/settings.ts +52 -0
  24. package/src/server/routes/tunnel.ts +1 -12
  25. package/src/server/ws/chat.ts +42 -12
  26. package/src/services/config.service.ts +1 -1
  27. package/src/services/notification.service.ts +42 -0
  28. package/src/services/telegram-notification.service.ts +106 -0
  29. package/src/types/config.ts +6 -0
  30. package/src/web/app.tsx +40 -1
  31. package/src/web/components/layout/draggable-tab.tsx +10 -2
  32. package/src/web/components/layout/mobile-nav.tsx +42 -3
  33. package/src/web/components/layout/project-bar.tsx +16 -8
  34. package/src/web/components/layout/tab-bar.tsx +55 -4
  35. package/src/web/components/settings/settings-tab.tsx +135 -94
  36. package/src/web/components/settings/telegram-settings-section.tsx +113 -0
  37. package/src/web/components/ui/accordion.tsx +64 -0
  38. package/src/web/hooks/use-chat.ts +29 -0
  39. package/src/web/hooks/use-notification-badge.ts +20 -0
  40. package/src/web/hooks/use-tab-overflow.ts +91 -0
  41. package/src/web/hooks/use-url-sync.ts +5 -2
  42. package/src/web/index.html +1 -0
  43. package/src/web/lib/favicon.ts +21 -0
  44. package/src/web/lib/notification-sounds.ts +61 -0
  45. package/src/web/stores/notification-store.ts +83 -0
  46. package/dist/web/assets/chat-tab-CWhxhPKH.js +0 -7
  47. package/dist/web/assets/git-graph-xD6TLRVv.js +0 -1
  48. package/dist/web/assets/index-CigdXBuQ.css +0 -2
  49. package/dist/web/assets/index-DBdw8tN_.js +0 -22
  50. package/dist/web/assets/keybindings-store-kHLASnRb.js +0 -1
  51. package/dist/web/assets/postgres-viewer-CaMySHpD.js +0 -1
  52. /package/dist/web/assets/{tab-store-DIyJSjtr.js → tab-store-Bm1Hw8OR.js} +0 -0
@@ -0,0 +1 @@
1
+ import{i as e,t}from"./react-CYzKIDNi.js";import{A as n,t as r}from"./input-nI4xe1Y9.js";import{n as i,t as a}from"./jsx-runtime-wQxeESYQ.js";import{a as o,t as s}from"./tab-store-Bm1Hw8OR.js";import{t as c}from"./utils-siJJ3uG0.js";import{i as l,t as u}from"./api-client-4Ni0i4Hl.js";import{M as d,N as f,O as p,T as m,a as h,c as g,d as _,f as v,i as ee,j as te,l as y,m as b,o as ne,p as x,q as S,s as re,u as ie,z as ae}from"./index-BU_07_oW.js";var oe=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`}]]),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`}]]),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=a(),D=[`#4fc3f7`,`#81c784`,`#ffb74d`,`#e57373`,`#ba68c8`,`#4dd0e1`,`#aed581`,`#ff8a65`,`#f06292`,`#7986cb`],O=32,k=20,se=5;function A({metadata:e}){let t=e?.projectName,[i,a]=(0,T.useState)(null),[o,m]=(0,T.useState)(!0),[S,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)([]),[le,B]=(0,T.useState)(!1),{openTab:V}=s(),H=(0,T.useCallback)(async()=>{if(t)try{m(!0),a(await u.get(`${l(t)}/git/graph?max=200`)),C(null)}catch(e){C(e instanceof Error?e.message:`Failed to fetch graph`)}finally{m(!1)}},[t]);(0,T.useEffect)(()=>{H();let e=setInterval(H,1e4);return()=>clearInterval(e)},[H]);let U=async(e,n)=>{if(t){j(!0);try{await u.post(`${l(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}),ue=e=>U(`/git/cherry-pick`,{hash:e}),de=e=>U(`/git/revert`,{hash:e}),fe=e=>U(`/git/merge`,{source:e}),pe=e=>U(`/git/branch/delete`,{name:e}),me=e=>U(`/git/push`,{branch:e}),G=async(e,t)=>{if(i?.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}),he=async e=>{if(t)try{let n=await u.get(`${l(t)}/git/pr-url?branch=${encodeURIComponent(e)}`);n.url&&window.open(n.url,`_blank`)}catch{}},q=e=>{navigator.clipboard.writeText(e)},ge=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 u.get(`${l(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)}},_e=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:ve}=(0,T.useMemo)(()=>{let e=new Map;if(!i)return{laneMap:e,maxLane:0};let t=0,n=new Map;for(let r of i.commits){let i=n.get(r.hash);i===void 0&&(i=t++),e.set(r.hash,i),n.delete(r.hash);for(let e=0;e<r.parents.length;e++){let a=r.parents[e];n.has(a)||n.set(a,e===0?i:t++)}}return{laneMap:e,maxLane:Math.max(t-1,0)}},[i]),Y=i?.branches.find(e=>e.current),ye=(0,T.useMemo)(()=>{let e=new Map;if(!i)return e;for(let t of i.branches){let n=e.get(t.commitHash)??[];n.push({name:t.name,type:`branch`}),e.set(t.commitHash,n)}for(let t of i.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},[i]),be=(0,T.useMemo)(()=>{if(!i)return[];let e=[];for(let t=0;t<i.commits.length;t++){let n=i.commits[t],r=J.get(n.hash)??0,a=D[r%D.length];for(let o of n.parents){let s=i.commits.findIndex(e=>e.hash===o);if(s<0)continue;let c=J.get(o)??0,l=D[c%D.length],u=r*k+k/2,d=t*O+O/2,f=c*k+k/2,p=s*O+O/2,m,h=n.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=n.parents.indexOf(o)===0?a:l;e.push({d:m,color:g})}}return e},[i,J]);(ve+1)*k+k;let X=(i?.commits.length??0)*O,[Z,xe]=(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;xe(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]),Se=(0,T.useCallback)(e=>{e.preventDefault(),$(e.clientX)},[$]),Ce=(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(o&&!i)return(0,E.jsxs)(`div`,{className:`flex items-center justify-center h-full gap-2 text-muted-foreground`,children:[(0,E.jsx)(te,{className:`size-5 animate-spin`}),(0,E.jsx)(`span`,{className:`text-sm`,children:`Loading git graph...`})]});if(S&&!i)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:S}),(0,E.jsx)(y,{variant:`outline`,size:`sm`,onClick:H,children:`Retry`})]});function we(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)(y,{variant:`ghost`,size:`icon-xs`,onClick:H,disabled:A,children:(0,E.jsx)(p,{className:o?`animate-spin`:``})})]}),S&&(0,E.jsx)(`div`,{className:`px-3 py-1.5 text-xs text-destructive bg-destructive/10`,children:S}),(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:[be.map((e,t)=>(0,E.jsx)(`path`,{d:e.d,stroke:e.color,strokeWidth:2,fill:`none`},t)),i?.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:se,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:Se,onTouchStart:Ce,children:(0,E.jsx)(d,{className:`size-3 text-muted-foreground md:opacity-0 md:hover:opacity-100`})})]}),(0,E.jsx)(`div`,{className:`flex-1 min-w-[400px]`,children:i?.commits.map((e,t)=>{let r=D[(J.get(e.hash)??0)%D.length],i=ye.get(e.hash)??[],a=i.filter(e=>e.type===`branch`),o=i.filter(e=>e.type===`tag`);return(0,E.jsxs)(ie,{children:[(0,E.jsx)(b,{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:()=>ge(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}),a.map(e=>(0,E.jsx)(ce,{label:e,color:r,currentBranch:Y,onCheckout:W,onMerge:fe,onPush:me,onCreatePr:he,onDelete:pe},`branch-${e.name}`)),o.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:we(e.authorDate)})]})})}),(0,E.jsxs)(_,{children:[(0,E.jsx)(v,{onClick:()=>W(e.hash),children:`Checkout`}),(0,E.jsxs)(v,{onClick:()=>{N({type:`branch`,hash:e.hash}),F(``)},children:[(0,E.jsx)(f,{className:`size-3`}),`Create Branch...`]}),(0,E.jsx)(x,{}),(0,E.jsxs)(v,{onClick:()=>ue(e.hash),children:[(0,E.jsx)(oe,{className:`size-3`}),`Cherry Pick`]}),(0,E.jsxs)(v,{onClick:()=>de(e.hash),children:[(0,E.jsx)(n,{className:`size-3`}),`Revert`]}),(0,E.jsxs)(v,{onClick:()=>{N({type:`tag`,hash:e.hash}),F(``)},children:[(0,E.jsx)(w,{className:`size-3`}),`Create Tag...`]}),(0,E.jsx)(x,{}),(0,E.jsx)(v,{onClick:()=>_e(e),children:`View Diff`}),(0,E.jsxs)(v,{onClick:()=>q(e.hash),children:[(0,E.jsx)(ae,{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)(y,{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:le?`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 ${c(e.path)}`,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)(ee,{open:M.type!==null,onOpenChange:e=>{e||N({type:null})},children:(0,E.jsxs)(h,{children:[(0,E.jsx)(re,{children:(0,E.jsx)(g,{children:M.type===`branch`?`Create Branch`:`Create Tag`})}),(0,E.jsx)(r,{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)(ne,{children:[(0,E.jsx)(y,{variant:`outline`,onClick:()=>N({type:null}),children:`Cancel`}),(0,E.jsx)(y,{disabled:!P.trim(),onClick:()=>{M.type===`branch`?G(P.trim(),M.hash):K(P.trim(),M.hash),N({type:null})},children:`Create`})]})]})})]})}function ce({label:e,color:t,currentBranch:n,onCheckout:r,onMerge:i,onPush:a,onCreatePr:s,onDelete:c}){return(0,E.jsxs)(ie,{children:[(0,E.jsx)(b,{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)(f,{className:`size-2.5`}),e.name]})}),(0,E.jsxs)(_,{children:[(0,E.jsx)(v,{onClick:()=>r(e.name),children:`Checkout`}),(0,E.jsxs)(v,{onClick:()=>i(e.name),disabled:e.name===n?.name,children:[(0,E.jsx)(C,{className:`size-3`}),`Merge into current`]}),(0,E.jsx)(x,{}),(0,E.jsxs)(v,{onClick:()=>a(e.name),children:[(0,E.jsx)(S,{className:`size-3`}),`Push`]}),(0,E.jsxs)(v,{onClick:()=>s(e.name),children:[(0,E.jsx)(o,{className:`size-3`}),`Create PR`]}),(0,E.jsx)(x,{}),(0,E.jsxs)(v,{variant:`destructive`,onClick:()=>c(e.name),disabled:e.name===n?.name,children:[(0,E.jsx)(m,{className:`size-3`}),`Delete`]})]})]})}export{A as GitGraph};