failproofai 0.0.11-beta.1 → 0.0.11-beta.2
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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +9 -9
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +9 -9
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js +1 -1
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d_ob4n._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_0z7w.hh._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-wn51s._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__12y7xmt._.js → [root-of-the-server]__01as125._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0agrcb8._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ehh6vp._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__09i-rsi._.js → [root-of-the-server]__0k5n2kz._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0yaqw._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0t8juvy._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ts150~._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0uylufv._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ymlddl._.js +5 -5
- package/.next/standalone/.next/server/chunks/ssr/app_0cdqd9w._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0a_7sdg.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +9 -9
- package/.next/standalone/.next/static/chunks/07kpqoo7kuckx.js +6 -0
- package/.next/standalone/.next/static/chunks/{0zg~cpc5ysg6d.js → 0azb~vy9ds_uy.js} +1 -1
- package/.next/standalone/.next/static/chunks/{13-bt.3~irg00.js → 0bke.~atnsbeb.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0_vk1wsgf~q3o.js → 0bv1oyxspkpkb.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0wtiofzdt-l2u.js → 0dvhi-prcsh3~.js} +1 -1
- package/.next/standalone/.next/static/chunks/0spktq7xqab9h.js +1 -0
- package/.next/standalone/.next/static/chunks/{16vev.do1oho7.js → 118q3uljozd5z.js} +1 -1
- package/.next/standalone/.next/static/chunks/{07kfzzinhsl7e.js → 11w14gnqzprir.js} +1 -1
- package/.next/standalone/app/policies/hooks-client.tsx +102 -13
- package/.next/standalone/lib/claude-sessions.ts +181 -0
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/server.js +1 -1
- package/README.md +2 -2
- package/bin/failproofai.mjs +229 -72
- package/dist/cli.mjs +3025 -1450
- package/lib/claude-sessions.ts +181 -0
- package/package.json +1 -1
- package/scripts/postinstall.mjs +89 -1
- package/src/audit/cache.ts +113 -0
- package/src/audit/cli-adapters/claude.ts +97 -0
- package/src/audit/cli-adapters/codex.ts +56 -0
- package/src/audit/cli-adapters/copilot.ts +51 -0
- package/src/audit/cli-adapters/cursor.ts +51 -0
- package/src/audit/cli-adapters/gemini.ts +51 -0
- package/src/audit/cli-adapters/index.ts +70 -0
- package/src/audit/cli-adapters/opencode.ts +52 -0
- package/src/audit/cli-adapters/pi.ts +51 -0
- package/src/audit/cli-adapters/shared.ts +85 -0
- package/src/audit/detectors/find-from-root.ts +27 -0
- package/src/audit/detectors/git-commit-no-verify.ts +22 -0
- package/src/audit/detectors/index.ts +33 -0
- package/src/audit/detectors/prefer-edit-over-read-cat.ts +31 -0
- package/src/audit/detectors/prefer-edit-over-sed-awk.ts +27 -0
- package/src/audit/detectors/prefer-write-over-heredoc.ts +36 -0
- package/src/audit/detectors/redundant-cd-cwd.ts +28 -0
- package/src/audit/detectors/reread-after-edit.ts +58 -0
- package/src/audit/detectors/sleep-polling-loop.ts +34 -0
- package/src/audit/index.ts +369 -0
- package/src/audit/replay.ts +121 -0
- package/src/audit/report.ts +349 -0
- package/src/audit/telemetry.ts +113 -0
- package/src/audit/types.ts +193 -0
- package/src/hooks/builtin-policies.ts +78 -0
- package/src/hooks/custom-hooks-loader.ts +19 -3
- package/src/hooks/first-run-nudge.ts +146 -0
- package/src/hooks/handler.ts +21 -102
- package/src/hooks/install-prompt.ts +34 -4
- package/src/hooks/manager.ts +72 -5
- package/src/hooks/policy-evaluator.ts +16 -1
- package/src/hooks/policy-types.ts +9 -0
- package/src/hooks/tool-name-canonicalize.ts +65 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__101v4_7._.js +0 -3
- package/.next/standalone/.next/static/chunks/03xhjwk6zhi8f.js +0 -1
- package/.next/standalone/.next/static/chunks/0wq808vlc8l04.js +0 -6
- package/src/auth/login.ts +0 -104
- package/src/auth/logout.ts +0 -50
- package/src/auth/token-store.ts +0 -64
- package/src/relay/daemon.ts +0 -362
- package/src/relay/pid.ts +0 -76
- package/src/relay/queue.ts +0 -225
- /package/.next/standalone/.next/static/{s5Nn6KwDdLpPhjG3l2WNf → tGVQM5SE3NvbVu0gbAJm7}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{s5Nn6KwDdLpPhjG3l2WNf → tGVQM5SE3NvbVu0gbAJm7}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{s5Nn6KwDdLpPhjG3l2WNf → tGVQM5SE3NvbVu0gbAJm7}/_ssgManifest.js +0 -0
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,64245,e=>{"use strict";var t=e.i(43476),r=e.i(71645),s=e.i(74080),n=e.i(22016),a=e.i(56420);let o=(0,a.default)("arrow-left",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]]);var l=e.i(84026),i=e.i(29407),d=e.i(16306),c=e.i(82954),m=e.i(16327),x=e.i(8734),u=e.i(89664),p=e.i(66794);let h=(0,a.default)("code",[["path",{d:"m16 18 6-6-6-6",key:"eg8j8"}],["path",{d:"m8 6-6 6 6 6",key:"ppft3o"}]]);var f=e.i(63676),g=e.i(73520),b=e.i(95187);let j=(0,b.createServerReference)("40c1a392c702d0bb5283b21e8f2fad4591e3d0f8ec",b.callServer,void 0,b.findSourceMapURL,"getHookActivityAction");var v=e.i(13941);let y=(0,b.createServerReference)("00f12dc89e39da1f0fcc1d6cabc2b8165ba6c74734",b.callServer,void 0,b.findSourceMapURL,"getHooksConfigAction"),N=(0,b.createServerReference)("60ad18ea3b3944468669ad87b7cc9fba1f9cc8f8ed",b.callServer,void 0,b.findSourceMapURL,"togglePolicyAction"),w=(0,b.createServerReference)("60042e3f2226907eb5d69a7f49e030522f0f2fb9d1",b.callServer,void 0,b.findSourceMapURL,"installHooksWebAction"),k=(0,b.createServerReference)("6028977d43ae56043b9078b9c3c29afba5d6fd8639",b.callServer,void 0,b.findSourceMapURL,"removeHooksWebAction"),C=(0,b.createServerReference)("60531b0745c090eb9dcf8123862633a2f44104cd9a",b.callServer,void 0,b.findSourceMapURL,"updatePolicyParamsAction");var S=e.i(85881),P=e.i(80060),I=e.i(2711),A=e.i(24578),$=e.i(34713),R=e.i(67881);function T({sessionId:e,transcriptPath:r,integration:s,cwd:a}){if(!e)return(0,t.jsx)("span",{className:"text-muted-foreground",children:"\\u2014"});let o=e?e.slice(0,8):"—",l="codex"===s||(r?.includes("/.codex/")??!1),i="copilot"===s||(r?.includes("/.copilot/session-state/")??!1),d="cursor"===s||(r?.includes("/.cursor/")??!1),c="opencode"===s||(r?.includes("/.local/share/opencode/")??!1)||(r?.includes("/.opencode/")??!1),m="pi"===s||(r?.includes("/.pi/")??!1),x="gemini"===s||(r?.includes("/.gemini/")??!1);if(l||i||d||c||m||x){let r,s=a?(r=/^([A-Za-z]):[\\/](.*)$/.exec(a))?r[1]+"--"+r[2].replace(/[\\/]/g,"-"):a.replace(/[\\/]/g,"-"):l?"codex":i?"copilot":d?"cursor":c?"opencode":m?"pi":"gemini";return(0,t.jsx)(n.default,{href:`/project/${encodeURIComponent(s)}/session/${encodeURIComponent(e)}`,className:"text-primary hover:underline font-mono",onClick:e=>e.stopPropagation(),children:o})}let u=r?function(e){let t=e.replace(/\\/g,"/").split("/").filter(Boolean);if(t.length<2)return null;let r=t[t.length-2];return!r||r.startsWith(".")?null:r}(r):null;return u?(0,t.jsx)(n.default,{href:`/project/${encodeURIComponent(u)}/session/${encodeURIComponent(e)}`,className:"text-primary hover:underline font-mono",onClick:e=>e.stopPropagation(),children:o}):(0,t.jsx)("span",{className:"text-muted-foreground font-mono",children:o})}function E({decision:e}){return"deny"===e?(0,t.jsxs)("span",{className:"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[0.65rem] font-semibold tracking-wide uppercase bg-red-500/10 text-red-400 border border-red-500/20",children:[(0,t.jsx)(i.ShieldX,{className:"h-3 w-3"}),"Deny"]}):"instruct"===e?(0,t.jsxs)("span",{className:"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[0.65rem] font-semibold tracking-wide uppercase bg-amber-500/10 text-amber-400 border border-amber-500/20",children:[(0,t.jsx)(d.ShieldAlert,{className:"h-3 w-3"}),"Instruct"]}):(0,t.jsxs)("span",{className:"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[0.65rem] font-semibold tracking-wide uppercase bg-emerald-500/10 text-emerald-400 border border-emerald-500/20",children:[(0,t.jsx)(l.ShieldCheck,{className:"h-3 w-3"}),"Allow"]})}function L({eventType:e}){return(0,t.jsx)("span",{className:"inline-flex items-center rounded px-1.5 py-0.5 text-[0.6rem] font-medium bg-muted text-muted-foreground border border-border/50",children:e})}function U({integration:e}){if(!e)return null;let r=(0,A.getCliLabel)(e),s=(0,A.getCliBadgeClasses)(e);return(0,t.jsx)("span",{className:`inline-flex items-center rounded px-1.5 py-0.5 text-[0.6rem] font-medium border ${s}`,title:`Agent CLI: ${r}`,children:r})}function F({mode:e}){let r="default"===e;return(0,t.jsx)("span",{className:`inline-flex items-center rounded px-1.5 py-0.5 text-[0.6rem] font-medium border ${r?"bg-sky-500/10 text-sky-400 border-sky-500/20":"bg-amber-500/10 text-amber-400 border-amber-500/20"}`,children:e})}function D({ms:e}){return(0,t.jsx)("span",{className:`font-mono text-[0.7rem] ${e>500?"text-red-400":e>100?"text-amber-400":"text-muted-foreground"}`,children:e<1e3?`${e}ms`:`${(e/1e3).toFixed(1)}s`})}function B({text:e}){let[s,n]=(0,r.useState)(!1),a=async t=>{t.stopPropagation();try{await navigator.clipboard.writeText(e),n(!0),setTimeout(()=>n(!1),1500)}catch{let t=document.createElement("textarea");t.value=e,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t),n(!0),setTimeout(()=>n(!1),1500)}};return(0,t.jsx)("button",{onClick:a,className:"inline-flex items-center justify-center h-5 w-5 rounded hover:bg-muted/50 text-muted-foreground hover:text-foreground transition-colors",title:"Copy",children:s?(0,t.jsx)(u.Check,{className:"h-3 w-3 text-emerald-400"}):(0,t.jsx)(x.Copy,{className:"h-3 w-3"})})}function M({value:e,onChange:r}){return(0,t.jsx)("div",{className:"inline-flex items-center rounded-md border border-border bg-muted/30 p-0.5",children:[{label:"All",value:""},{label:"Allow",value:"allow"},{label:"Instruct",value:"instruct"},{label:"Deny",value:"deny"}].map(s=>(0,t.jsx)("button",{onClick:()=>r(s.value),className:`px-2.5 py-1 text-[0.65rem] font-medium rounded transition-all ${e===s.value?"deny"===s.value?"bg-red-500/15 text-red-400 shadow-sm":"allow"===s.value?"bg-emerald-500/15 text-emerald-400 shadow-sm":"instruct"===s.value?"bg-amber-500/15 text-amber-400 shadow-sm":"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"}`,children:s.label},s.value))})}function z({stats:e}){let r=e.totalEvents>0?(e.denyCount/e.totalEvents*100).toFixed(0):"0";return(0,t.jsxs)("div",{className:"flex items-center gap-6 text-[0.7rem] text-muted-foreground",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-foreground font-mono font-semibold",children:e.totalEvents})," total events"]}),(0,t.jsxs)("div",{children:[(0,t.jsxs)("span",{className:`font-mono font-semibold ${e.denyCount>0?"text-red-400":"text-foreground"}`,children:[r,"%"]})," ","deny rate"]}),(0,t.jsxs)("div",{className:"hidden sm:block",children:["top policy:"," ",(0,t.jsx)("span",{className:"font-mono text-foreground",children:e.topPolicy??"—"})]})]})}function O({item:e}){return(0,t.jsx)("tr",{children:(0,t.jsx)("td",{colSpan:10,className:"px-0 py-0",children:(0,t.jsxs)("div",{className:"px-6 py-3 bg-muted/20 border-t border-border/30 space-y-2 text-xs animate-expand",children:[(0,t.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-1.5",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Session ID: "}),(0,t.jsx)("span",{className:"font-mono text-foreground",children:e.sessionId??"—"}),e.sessionId&&(0,t.jsx)(B,{text:e.sessionId})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"CWD: "}),(0,t.jsx)("span",{className:"font-mono text-foreground",children:e.cwd??"—"}),e.cwd&&(0,t.jsx)(B,{text:e.cwd})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Transcript: "}),(0,t.jsx)("span",{className:"font-mono text-foreground break-all",children:e.transcriptPath??"—"}),e.transcriptPath?.startsWith("opencode-db://")&&(0,t.jsx)("span",{className:"text-muted-foreground ml-1",children:"(stored in opencode DB)"})]})]}),e.policyNames&&e.policyNames.length>1&&(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Policies: "}),(0,t.jsx)("span",{className:"font-mono text-foreground",children:e.policyNames.join(", ")})]}),e.reason&&(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Full reason: "}),(0,t.jsx)("span",{className:"text-foreground",children:e.reason})]})]})})})}function W({hooksInstalled:e,onSwitchTab:s}){let{intervalSec:n}=(0,S.useAutoRefresh)(),a=(0,P.useUrlParams)(),o=(0,r.useRef)(!1),[l,i]=(0,r.useState)(()=>(0,I.paramToPage)(a.get("page"))),[d,x]=(0,r.useState)(null),[u,p]=(0,r.useState)(null),[h,f]=(0,r.useState)(()=>{let e=a.get("decision");return"allow"===e||"deny"===e||"instruct"===e?e:""}),[b,y]=(0,r.useState)(()=>a.get("event")??""),[N,w]=(0,r.useState)(()=>a.get("policy")??""),[k,C]=(0,r.useState)(()=>a.get("session")??""),[R,B]=(0,r.useState)(()=>{let e=a.get("cli");return(0,A.isKnownCli)(e)?e:""}),_=(0,r.useRef)(null),H=(0,r.useRef)({filterDecision:h,filterEventType:b,filterPolicy:N,filterSessionId:k,filterCli:R});H.current={filterDecision:h,filterEventType:b,filterPolicy:N,filterSessionId:k,filterCli:R},(0,r.useEffect)(()=>{if(!o.current){o.current=!0;return}a.setAll({decision:h||void 0,event:b||void 0,policy:N||void 0,session:k||void 0,cli:R||void 0,page:(0,I.pageToParam)(l)})},[h,b,N,k,R,l]);let X=""!==h||""!==b||""!==N||""!==k||""!==R,K=(0,r.useCallback)(async e=>{try{let t,{filterDecision:r,filterEventType:s,filterPolicy:n,filterSessionId:a,filterCli:o}=H.current;t=""!==r||""!==s||""!==n||""!==a||""!==o?await (0,v.searchHookActivityAction)({decision:r||void 0,eventType:s||void 0,policyName:n||void 0,sessionId:a||void 0,integration:o||void 0},e):await j(e),x(t)}catch{}},[]);(0,r.useEffect)(()=>{K(l);let e=setInterval(()=>K(l),n>0?1e3*n:5e3);return()=>clearInterval(e)},[l,K,n]),(0,r.useEffect)(()=>(_.current&&clearTimeout(_.current),_.current=setTimeout(()=>{i(1),p(null),K(1)},300),()=>{_.current&&clearTimeout(_.current)}),[h,b,N,k,R]);let J=d?.entries??[],q=d?.totalPages??1;return(0,t.jsxs)(t.Fragment,{children:[d?.stats&&d.stats.totalEvents>0&&(0,t.jsx)("div",{className:"mb-4",children:(0,t.jsx)(z,{stats:d.stats})}),(0,t.jsxs)("div",{className:"bg-card border border-border rounded-lg overflow-hidden",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-3 px-4 py-2.5 border-b border-border bg-muted/20",children:[(0,t.jsx)(M,{value:h,onChange:f}),(0,t.jsxs)("select",{value:b,onChange:e=>y(e.target.value),className:"h-7 rounded-md border border-border bg-background px-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-primary/40 focus:border-primary/40 transition-shadow",children:[(0,t.jsx)("option",{value:"",children:"All Events"}),(0,t.jsx)("option",{value:"PreToolUse",children:"PreToolUse"}),(0,t.jsx)("option",{value:"PostToolUse",children:"PostToolUse"}),(0,t.jsx)("option",{value:"SessionStart",children:"SessionStart"}),(0,t.jsx)("option",{value:"SessionEnd",children:"SessionEnd"}),(0,t.jsx)("option",{value:"UserPromptSubmit",children:"UserPromptSubmit"}),(0,t.jsx)("option",{value:"PermissionRequest",children:"PermissionRequest"})]}),(0,t.jsxs)("select",{value:R,onChange:e=>{let t=e.target.value;B(""===t||(0,A.isKnownCli)(t)?t:"")},className:"h-7 rounded-md border border-border bg-background px-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-primary/40 focus:border-primary/40 transition-shadow","aria-label":"Filter by CLI",children:[(0,t.jsx)("option",{value:"",children:"All CLIs"}),A.KNOWN_CLI_IDS.map(e=>(0,t.jsx)("option",{value:e,children:(0,A.getCliLabel)(e)},e))]}),(0,t.jsx)("div",{className:"relative",children:(0,t.jsx)("input",{type:"text",value:N,onChange:e=>w(e.target.value),placeholder:"Filter by policy\\u2026",className:"h-7 rounded-md border border-border bg-background px-2.5 text-xs text-foreground placeholder:text-muted-foreground w-44 focus:outline-none focus:ring-2 focus:ring-primary/40 focus:border-primary/40 transition-shadow"})}),(0,t.jsx)("div",{className:"relative",children:(0,t.jsx)("input",{type:"text",value:k,onChange:e=>C(e.target.value),placeholder:"Filter by session…",className:"h-7 rounded-md border border-border bg-background px-2.5 text-xs text-foreground placeholder:text-muted-foreground w-44 focus:outline-none focus:ring-2 focus:ring-primary/40 focus:border-primary/40 transition-shadow"})})]}),0===J.length?(0,t.jsxs)("div",{className:"flex flex-col items-center justify-center py-16 px-4 text-center",children:[(0,t.jsx)(c.Shield,{className:"h-12 w-12 text-muted-foreground/30"}),!1===e?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("p",{className:"text-sm text-muted-foreground mt-4 font-medium",children:"Policies are not installed"}),(0,t.jsxs)("p",{className:"text-xs text-muted-foreground mt-1 max-w-sm",children:["Go to the"," ",(0,t.jsx)("button",{className:"underline hover:text-foreground transition-colors",onClick:()=>s?.("policies"),children:"Policies tab"})," ","and click ",(0,t.jsx)("span",{className:"font-mono bg-muted px-1 rounded",children:"Install"})," to enable policy monitoring."]})]}):(0,t.jsx)("p",{className:"text-sm text-muted-foreground mt-4",children:X?"No matching activity.":"Waiting for hook events…"})]}):(0,t.jsx)("div",{className:"overflow-x-auto",children:(0,t.jsxs)("table",{className:"w-full text-xs",children:[(0,t.jsx)("thead",{children:(0,t.jsxs)("tr",{className:"text-left text-muted-foreground border-b border-border bg-muted/30",children:[(0,t.jsx)("th",{className:"px-4 py-2.5 font-medium w-6"}),(0,t.jsx)("th",{className:"px-3 py-2.5 font-medium",children:"Decision"}),(0,t.jsx)("th",{className:"px-3 py-2.5 font-medium",children:"Event"}),(0,t.jsx)("th",{className:"px-3 py-2.5 font-medium",children:"CLI"}),(0,t.jsx)("th",{className:"px-3 py-2.5 font-medium",children:"Tool"}),(0,t.jsx)("th",{className:"px-3 py-2.5 font-medium",children:"Policy"}),(0,t.jsx)("th",{className:"px-3 py-2.5 font-medium",children:"Reason"}),(0,t.jsx)("th",{className:"px-3 py-2.5 font-medium",children:"Duration"}),(0,t.jsx)("th",{className:"px-3 py-2.5 font-medium",children:"Session"}),(0,t.jsx)("th",{className:"px-3 py-2.5 font-medium",children:"Mode"}),(0,t.jsx)("th",{className:"px-3 py-2.5 font-medium text-right",children:"Time"})]})}),(0,t.jsx)("tbody",{className:"divide-y divide-border/30",children:J.map((e,s)=>{let n="deny"===e.decision,a=u===s,o="instruct"===e.decision;return(0,t.jsxs)(r.default.Fragment,{children:[(0,t.jsxs)("tr",{onClick:()=>{p(e=>e===s?null:s)},className:`cursor-pointer transition-colors ${n?"bg-red-500/[0.03] hover:bg-red-500/[0.07] border-l-2 border-l-red-500/40":o?"bg-amber-500/[0.03] hover:bg-amber-500/[0.07] border-l-2 border-l-amber-500/40":s%2==0?"hover:bg-muted/30":"bg-muted/[0.04] hover:bg-muted/30"} ${a?"bg-muted/20":""}`,children:[(0,t.jsx)("td",{className:"px-4 py-2",children:(0,t.jsx)(m.ChevronDown,{className:`h-3.5 w-3.5 text-muted-foreground transition-transform duration-150 ${a?"rotate-0":"-rotate-90"}`})}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(E,{decision:e.decision})}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(L,{eventType:e.eventType})}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(U,{integration:e.integration})}),(0,t.jsx)("td",{className:"px-3 py-2 font-mono text-foreground",children:e.toolName??"—"}),(0,t.jsx)("td",{className:"px-3 py-2 font-mono text-foreground",children:e.policyNames&&e.policyNames.length>1?(0,t.jsxs)("span",{title:e.policyNames.join(", "),children:[e.policyNames[0],(0,t.jsxs)("span",{className:"text-muted-foreground text-[0.6rem]",children:[" +",e.policyNames.length-1]})]}):e.policyName??"—"}),(0,t.jsx)("td",{className:"px-3 py-2 text-muted-foreground truncate max-w-[240px]",title:e.reason??"",children:e.reason??"—"}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(D,{ms:e.durationMs})}),(0,t.jsx)("td",{className:"px-3 py-2",title:e.sessionId??"",children:(0,t.jsx)(T,{sessionId:e.sessionId,transcriptPath:e.transcriptPath,integration:e.integration,cwd:e.cwd})}),(0,t.jsx)("td",{className:"px-3 py-2",children:e.permissionMode?(0,t.jsx)(F,{mode:e.permissionMode}):"—"}),(0,t.jsx)("td",{className:"px-3 py-2 text-right text-muted-foreground whitespace-nowrap",title:new Date(e.timestamp).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"}),children:(0,$.formatRelativeTime)(e.timestamp)})]}),a&&(0,t.jsx)(O,{item:e})]},`${e.timestamp}-${s}`)})})]})}),(0,t.jsx)(g.default,{currentPage:l,totalPages:q,onPageChange:e=>{i(e),p(null)}})]})]})}function _({enabled:e,onChange:r,disabled:s}){return(0,t.jsx)("button",{onClick:r,disabled:s,className:`relative inline-flex h-4 w-7 shrink-0 items-center rounded-full transition-colors disabled:opacity-40 ${e?"bg-emerald-500":"bg-muted-foreground/30"}`,"aria-label":e?"Disable policy":"Enable policy",children:(0,t.jsx)("span",{className:`inline-block h-3 w-3 rounded-full bg-white shadow transition-transform ${e?"translate-x-3.5":"translate-x-0.5"}`})})}function H({policy:e,onClose:s,onSave:n}){let a=e.params??{},o=e.currentParams??{},[l,i]=(0,r.useState)(()=>{let e={};for(let[t,r]of Object.entries(a)){let s=t in o?o[t]:r.default;e[t]=s}return e});(0,r.useEffect)(()=>{let e=e=>{"Escape"===e.key&&s()};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[s]);let d=(e,t)=>{i(r=>({...r,[e]:t}))};return(0,t.jsx)("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",onClick:e=>{e.target===e.currentTarget&&s()},children:(0,t.jsxs)("div",{className:"bg-card border border-border rounded-lg shadow-xl w-full max-w-lg mx-4 max-h-[80vh] flex flex-col",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between px-4 py-3 border-b border-border",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("p",{className:"text-sm font-mono font-semibold text-foreground",children:e.name}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground mt-0.5",children:e.description})]}),(0,t.jsx)("button",{onClick:s,className:"text-muted-foreground hover:text-foreground transition-colors",children:(0,t.jsx)(f.X,{className:"h-4 w-4"})})]}),(0,t.jsx)("div",{className:"overflow-y-auto flex-1 px-4 py-4 space-y-4",children:Object.entries(a).map(([e,r])=>(0,t.jsxs)("div",{children:[(0,t.jsx)("label",{className:"block text-xs font-semibold text-foreground mb-1 font-mono",children:e}),(0,t.jsx)("p",{className:"text-[0.65rem] text-muted-foreground mb-1.5",children:r.description}),((e,r)=>{let s=l[e];if("boolean"===r.type)return(0,t.jsxs)("label",{className:"flex items-center gap-2 cursor-pointer",children:[(0,t.jsx)("input",{type:"checkbox",checked:!!s,onChange:t=>d(e,t.target.checked),className:"rounded border-border"}),(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:r.description})]});if("number"===r.type)return(0,t.jsx)("input",{type:"number",value:"number"==typeof s?s:"",onChange:t=>d(e,Number(t.target.value)),className:"w-full h-7 rounded border border-border bg-background px-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-primary/40"});if("string[]"===r.type){let r=Array.isArray(s)?s.join("\n"):"";return(0,t.jsx)("textarea",{value:r,onChange:t=>d(e,t.target.value.split("\n").filter(e=>""!==e.trim())),rows:4,placeholder:"One entry per line",className:"w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground font-mono focus:outline-none focus:ring-2 focus:ring-primary/40 resize-y"})}if("pattern[]"===r.type){let r=Array.isArray(s)?s:[];return(0,t.jsxs)("div",{className:"space-y-1.5",children:[r.map((s,n)=>(0,t.jsxs)("div",{className:"flex gap-1.5 items-center",children:[(0,t.jsx)("input",{type:"text",value:s.regex,onChange:t=>{let s=[...r];s[n]={...s[n],regex:t.target.value},d(e,s)},placeholder:"regex",className:"flex-1 h-6 rounded border border-border bg-background px-2 text-xs font-mono focus:outline-none focus:ring-2 focus:ring-primary/40"}),(0,t.jsx)("input",{type:"text",value:s.label,onChange:t=>{let s=[...r];s[n]={...s[n],label:t.target.value},d(e,s)},placeholder:"label",className:"flex-1 h-6 rounded border border-border bg-background px-2 text-xs focus:outline-none focus:ring-2 focus:ring-primary/40"}),(0,t.jsx)("button",{onClick:()=>d(e,r.filter((e,t)=>t!==n)),className:"text-muted-foreground/50 hover:text-destructive transition-colors",children:(0,t.jsx)(f.X,{className:"h-3.5 w-3.5"})})]},n)),(0,t.jsx)("button",{onClick:()=>d(e,[...r,{regex:"",label:""}]),className:"text-xs text-primary hover:underline",children:"+ Add pattern"})]})}return(0,t.jsx)("input",{type:"text",value:"string"==typeof s?s:"",onChange:t=>d(e,t.target.value),className:"w-full h-7 rounded border border-border bg-background px-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-primary/40"})})(e,r)]},e))}),(0,t.jsxs)("div",{className:"flex items-center justify-end gap-2 px-4 py-3 border-t border-border",children:[(0,t.jsx)(R.Button,{variant:"outline",size:"sm",onClick:s,className:"h-7 text-xs",children:"Cancel"}),(0,t.jsx)(R.Button,{size:"sm",onClick:()=>n(l),className:"h-7 text-xs",children:"Save"})]})]})})}function X({message:e,onDismiss:r,onInstall:n,isPending:a}){return(0,s.createPortal)((0,t.jsxs)("div",{className:"fixed top-4 right-4 z-[9999] w-full max-w-sm",style:{animation:"slideInFromRight 0.25s ease-out"},children:[(0,t.jsx)("style",{children:`
|
|
2
|
-
@keyframes slideInFromRight {
|
|
3
|
-
from { transform: translateX(calc(100% + 1rem)); opacity: 0; }
|
|
4
|
-
to { transform: translateX(0); opacity: 1; }
|
|
5
|
-
}
|
|
6
|
-
`}),(0,t.jsxs)("div",{className:"rounded-lg border border-red-500/40 bg-red-950/95 shadow-2xl shadow-red-900/40 overflow-hidden backdrop-blur-sm",children:[(0,t.jsx)("div",{className:"h-0.5 w-full bg-gradient-to-r from-red-600 via-red-400 to-red-600"}),(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsxs)("div",{className:"flex items-start gap-3",children:[(0,t.jsx)("div",{className:"shrink-0 mt-0.5 flex h-5 w-5 items-center justify-center rounded-full bg-red-500 ring-2 ring-red-500/30",children:(0,t.jsx)(f.X,{className:"h-3 w-3 text-white",strokeWidth:3})}),(0,t.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,t.jsx)("p",{className:"text-[0.65rem] font-bold uppercase tracking-widest text-red-400 mb-0.5",children:"Error"}),(0,t.jsx)("p",{className:"text-sm text-red-100 leading-snug",children:e})]}),(0,t.jsx)("button",{onClick:r,className:"shrink-0 -mt-0.5 -mr-0.5 rounded p-0.5 text-red-400/60 transition-colors hover:bg-red-500/20 hover:text-red-200","aria-label":"Dismiss",children:(0,t.jsx)(f.X,{className:"h-4 w-4"})})]}),(0,t.jsxs)("div",{className:"mt-3 flex gap-2",children:[(0,t.jsx)(R.Button,{size:"sm",onClick:()=>{r(),n()},disabled:a,className:"h-7 flex-1 border-0 bg-red-500 px-3 text-xs font-semibold text-white hover:bg-red-400 disabled:opacity-50",children:"Install hooks"}),(0,t.jsx)(R.Button,{variant:"ghost",size:"sm",onClick:r,className:"h-7 px-3 text-xs text-red-400 hover:bg-red-500/10 hover:text-red-200",children:"Dismiss"})]})]})]})]}),document.body)}function K({onHooksInstallChange:e}){let[s,n]=(0,r.useState)(null),[a,o]=(0,r.useTransition)(),[l,i]=(0,r.useState)(null),[d,m]=(0,r.useState)(null),[x,u]=(0,r.useState)(null),[f,g]=(0,r.useState)(()=>new Set),b=(0,r.useRef)(!1),j=(0,r.useCallback)(async()=>{try{let t=await y();n(t),e?.(t.clis.some(e=>e.installed))}catch{}},[e]);(0,r.useEffect)(()=>{j()},[j]),(0,r.useEffect)(()=>{s&&(b.current?g(new Set(s.clis.filter(e=>e.installed).map(e=>e.id))):(b.current=!0,g(new Set(s.clis.filter(e=>e.installed||e.detected).map(e=>e.id)))))},[s?.clis]);let v=(0,r.useMemo)(()=>new Set((s?.clis??[]).filter(e=>e.installed).map(e=>e.id)),[s?.clis]),S=(0,r.useMemo)(()=>{let e=[],t=[];for(let r of s?.clis??[]){let s=f.has(r.id);s&&!v.has(r.id)&&e.push(r.id),!s&&v.has(r.id)&&t.push(r.id)}return{toInstall:e,toRemove:t}},[s?.clis,f,v]),P=S.toInstall.length>0||S.toRemove.length>0,I=()=>{let{toInstall:e,toRemove:t}=S;(0!==e.length||0!==t.length)&&o(async()=>{try{i(null),e.length>0&&await w("user",e),t.length>0&&await k("user",t)}catch(e){i(e instanceof Error?e.message:"Failed to apply changes.")}finally{await j()}})};if(!s)return(0,t.jsx)("div",{className:"flex items-center justify-center py-16",children:(0,t.jsx)("span",{className:"text-sm text-muted-foreground",children:"Loading\\u2026"})});let $=s.clis.some(e=>e.installed),T=v.size,E=f.size,L=Array.from(new Set(s.policies.map(e=>e.category)));return(0,t.jsxs)(t.Fragment,{children:[x&&(0,t.jsx)(H,{policy:x,onClose:()=>u(null),onSave:e=>{if(!x)return;let t=x.name;u(null),o(async()=>{try{i(null),await C(t,e),await j()}catch(e){i(e instanceof Error?e.message:"Failed to save configuration.")}})}}),(0,t.jsxs)("div",{className:"bg-card border border-border rounded-lg overflow-hidden",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between gap-4 px-5 py-3.5 border-b border-border/60 bg-muted/10",children:[(0,t.jsxs)("div",{className:"flex items-center gap-3 min-w-0 flex-wrap",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{className:`h-2 w-2 rounded-full transition-shadow ${$?"bg-emerald-400 shadow-[0_0_8px_rgba(52,211,153,0.6)]":"bg-muted-foreground/40"}`,"aria-hidden":!0}),(0,t.jsx)("span",{className:"text-[0.65rem] uppercase tracking-[0.2em] font-mono text-foreground/90",children:"Integrations"})]}),(0,t.jsx)("span",{className:"text-[0.65rem] font-mono text-muted-foreground/40",children:"·"}),(0,t.jsxs)("div",{className:"text-[0.65rem] uppercase tracking-[0.2em] font-mono text-muted-foreground",children:[(0,t.jsx)("span",{className:"text-foreground tabular-nums",children:T.toString().padStart(2,"0")}),(0,t.jsxs)("span",{className:"opacity-50",children:[" / 0",s.clis.length," active"]})]}),P&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("span",{className:"text-[0.65rem] font-mono text-muted-foreground/40",children:"·"}),(0,t.jsxs)("span",{className:"inline-flex items-center gap-1.5 text-[0.65rem] uppercase tracking-[0.2em] font-mono text-pink-400",children:[(0,t.jsx)("span",{className:"h-1 w-1 rounded-full bg-pink-400 animate-pulse"}),S.toInstall.length+S.toRemove.length," pending"]})]})]}),(0,t.jsxs)("div",{className:"flex items-center gap-2 shrink-0",children:[(0,t.jsx)(R.Button,{variant:"outline",size:"sm",onClick:()=>{let e=Array.from(v).filter(e=>f.has(e));0!==e.length&&o(async()=>{try{i(null),await w("user",e)}catch(e){i(e instanceof Error?e.message:"Failed to reinstall.")}finally{await j()}})},disabled:a||0===E,className:"text-xs h-7 px-3 font-mono",children:"Reinstall"}),(0,t.jsx)(R.Button,{variant:"default",size:"sm",onClick:I,disabled:a||!P,className:"text-xs h-7 px-3 font-mono",children:"Apply changes"})]})]}),(0,t.jsx)("div",{className:"divide-y divide-border/30 border-b border-border/60",children:s.clis.map((e,r)=>{let s=f.has(e.id),n=v.has(e.id),o=s!==n,l=(0,A.getCliBadgeClasses)(e.id),i=l.split(" ").find(e=>e.startsWith("text-"))??"text-foreground";return(0,t.jsxs)("label",{className:`group relative flex items-center gap-3 pl-6 pr-5 py-3 cursor-pointer transition-colors hover:bg-muted/15 ${o?"bg-pink-500/[0.04]":""}`,children:[(0,t.jsx)("div",{className:`absolute left-0 top-0 bottom-0 w-[3px] ${i} bg-current transition-opacity ${s?"opacity-100":"opacity-25 group-hover:opacity-60"}`,"aria-hidden":!0}),(0,t.jsx)("div",{className:"font-mono text-[0.65rem] text-muted-foreground/40 tabular-nums w-6 select-none",children:(r+1).toString().padStart(2,"0")}),(0,t.jsxs)("div",{className:"relative shrink-0",children:[(0,t.jsx)("input",{type:"checkbox",checked:s,onChange:()=>{var t;return t=e.id,void g(e=>{let r=new Set(e);return r.has(t)?r.delete(t):r.add(t),r})},disabled:a,className:"sr-only peer","aria-label":`Toggle ${e.label}`}),(0,t.jsx)("div",{className:`h-[18px] w-[18px] rounded-sm border transition-all peer-focus-visible:ring-2 peer-focus-visible:ring-primary/40 ${s?"bg-primary border-primary":"bg-background/50 border-border group-hover:border-foreground/40"}`,children:s&&(0,t.jsx)("svg",{viewBox:"0 0 18 18",className:"h-full w-full text-primary-foreground",fill:"none","aria-hidden":!0,children:(0,t.jsx)("path",{d:"M4 9.5L7.5 12.5L14 6",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),(0,t.jsx)("div",{className:"min-w-[150px] shrink-0",children:(0,t.jsx)("div",{className:"text-sm font-medium text-foreground",children:e.label})}),(0,t.jsxs)("div",{className:"flex items-center gap-1.5 shrink-0",children:[n?(0,t.jsxs)("span",{className:`inline-flex items-center gap-1.5 px-2 py-0.5 rounded-sm text-[0.6rem] uppercase tracking-[0.15em] font-mono border ${l}`,children:[(0,t.jsx)("span",{className:"h-1 w-1 rounded-full bg-current shadow-[0_0_4px_currentColor]"}),"Active"]}):e.detected?(0,t.jsxs)("span",{className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-sm text-[0.6rem] uppercase tracking-[0.15em] font-mono border border-border/60 text-muted-foreground/80 bg-muted/20",children:[(0,t.jsx)("span",{className:"h-1 w-1 rounded-full bg-current opacity-60"}),"Detected"]}):(0,t.jsx)("span",{className:"inline-flex items-center px-2 py-0.5 rounded-sm text-[0.6rem] uppercase tracking-[0.15em] font-mono border border-border/30 text-muted-foreground/40",children:"Inactive"}),o&&(0,t.jsx)("span",{className:"inline-flex items-center px-2 py-0.5 rounded-sm text-[0.6rem] uppercase tracking-[0.15em] font-mono border border-pink-500/40 text-pink-400 bg-pink-500/10",children:s?"+ install":"− remove"})]}),(0,t.jsx)("div",{className:"ml-auto hidden lg:block text-[0.7rem] font-mono text-muted-foreground/50 truncate max-w-[420px] group-hover:text-muted-foreground/80 transition-colors",title:e.settingsPath,children:e.settingsPath})]},e.id)})}),(0,t.jsxs)("div",{className:"flex items-center gap-2 px-4 py-2 border-b border-border/40 bg-muted/5",children:[(0,t.jsxs)("span",{className:"text-xs text-muted-foreground",children:[(0,t.jsx)("span",{className:"font-semibold text-foreground",children:s.enabledPolicies.length})," / ",s.policies.length+(s.customPolicies?.length??0)," ","policies enabled"]}),$&&(0,t.jsxs)("span",{className:"text-[0.65rem] text-muted-foreground/60",children:["· shared across ",T," active CLI",1===T?"":"s"]})]}),l&&(0,t.jsx)("div",{className:"px-4 py-2 bg-red-500/10 border-b border-red-500/20 text-xs text-red-400",children:l}),d&&(0,t.jsx)(X,{message:d,onDismiss:()=>m(null),onInstall:I,isPending:a}),L.map(e=>{let r=s.policies.filter(t=>t.category===e),l=r.filter(e=>e.enabled).length;return(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"flex items-center justify-between px-4 py-2.5 bg-muted/20 border-b border-border/50",children:[(0,t.jsx)("span",{className:"text-[0.7rem] font-semibold uppercase tracking-wider text-muted-foreground",children:e}),(0,t.jsxs)("span",{className:"text-[0.7rem] text-muted-foreground",children:[l," / ",r.length," enabled"]})]}),r.map(e=>(0,t.jsxs)("div",{className:"flex items-start gap-3 px-4 py-3 border-b border-border/20 hover:bg-muted/20 transition-colors",children:[(0,t.jsx)("div",{className:"mt-0.5 shrink-0",children:(0,t.jsx)(_,{enabled:e.enabled,onChange:()=>{var t,r;return t=e.name,r=e.enabled,void(!s||(!s.clis.some(e=>e.installed)?m("Policies are not installed. Install policies to continue."):(m(null),n(e=>e?{...e,policies:e.policies.map(e=>e.name===t?{...e,enabled:!r}:e),enabledPolicies:r?e.enabledPolicies.filter(e=>e!==t):[...e.enabledPolicies,t]}:e),o(async()=>{try{await N(t,!r)}catch{i("Failed to save policy change."),j()}}))))},disabled:a})}),(0,t.jsxs)("div",{className:"flex items-center gap-1.5 min-w-0 w-56 shrink-0 mt-0.5",children:[(0,t.jsx)("span",{className:"text-xs font-mono text-foreground truncate",children:e.name}),e.beta&&(0,t.jsx)("span",{className:"shrink-0 text-[0.6rem] px-1 py-0.5 rounded border bg-violet-500/10 text-violet-400 border-violet-500/20",children:"beta"})]}),(0,t.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,t.jsx)("span",{className:"text-xs text-muted-foreground leading-relaxed",children:e.description}),e.eventScope&&(0,t.jsx)("span",{className:"block text-[0.65rem] text-muted-foreground/40 font-mono mt-0.5 hidden lg:block",children:e.eventScope}),e.params&&Object.keys(e.params).length>0&&(0,t.jsx)("div",{className:"flex flex-wrap gap-1 mt-1.5",children:Object.entries(e.params).map(([r,s])=>{let n=e.currentParams?.[r]??s.default,a=JSON.stringify(n)!==JSON.stringify(s.default);return(0,t.jsxs)("span",{className:`inline-flex items-center gap-1 font-mono text-[0.6rem] px-1.5 py-0.5 rounded border ${a?"bg-primary/10 text-primary/70 border-primary/20":"bg-muted/40 text-muted-foreground/55 border-border/40"}`,children:[(0,t.jsxs)("span",{className:"opacity-70",children:[r,":"]}),(0,t.jsx)("span",{children:function(e,t){if("string[]"===e||"pattern[]"===e){let r=Array.isArray(t)?t:[];return 0===r.length?"none":"pattern[]"===e?`${r.length} pattern${1!==r.length?"s":""}`:1===r.length?String(r[0]).slice(0,24):`${r.length} values`}return"boolean"===e?t?"on":"off":null==t||""===t?"—":String(t).slice(0,32)}(s.type,n)})]},r)})})]}),e.params&&Object.keys(e.params).length>0&&(0,t.jsx)("button",{className:"shrink-0 mt-0.5 text-muted-foreground hover:text-primary transition-colors",onClick:()=>u(e),title:"Edit parameters",children:(0,t.jsx)(p.Settings,{className:"h-3.5 w-3.5"})})]},e.name))]},e)}),s.customPoliciesPath&&(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"flex items-center justify-between px-4 py-2.5 bg-muted/20 border-b border-border/50",children:[(0,t.jsx)("span",{className:"text-[0.7rem] font-semibold uppercase tracking-wider text-muted-foreground",children:"Custom Policies"}),(0,t.jsxs)("span",{className:"text-[0.7rem] text-muted-foreground",children:[s.customPolicies?.length??0," detected"]})]}),(0,t.jsxs)("div",{className:"flex items-center gap-3 px-4 py-3 border-b border-border/20",children:[(0,t.jsx)(h,{className:"h-3.5 w-3.5 text-muted-foreground shrink-0"}),(0,t.jsx)("span",{className:"text-xs font-mono text-muted-foreground truncate",children:s.customPoliciesPath})]}),(0,t.jsxs)("div",{className:"flex items-start gap-2 px-4 py-2.5 border-b border-border/20 bg-muted/10",children:[(0,t.jsx)(c.Shield,{className:"h-3.5 w-3.5 text-muted-foreground/60 shrink-0 mt-0.5"}),(0,t.jsx)("p",{className:"text-[0.7rem] text-muted-foreground/70 leading-relaxed",children:"Custom policies are always active. To add, remove, or reorder them, edit the JS file above."})]}),s.customPolicies?.map(e=>(0,t.jsxs)("div",{className:"flex items-start gap-3 px-4 py-3 border-b border-border/20 hover:bg-muted/20 transition-colors",children:[(0,t.jsx)("div",{className:"h-4 w-7 shrink-0 mt-0.5"}),(0,t.jsx)("div",{className:"flex items-center gap-1.5 min-w-0 w-56 shrink-0 mt-0.5",children:(0,t.jsx)("span",{className:"text-xs font-mono text-foreground truncate",children:e.name})}),(0,t.jsxs)("div",{className:"flex-1 min-w-0",children:[e.description&&(0,t.jsx)("span",{className:"text-xs text-muted-foreground leading-relaxed",children:e.description}),e.eventScope&&(0,t.jsx)("span",{className:"block text-[0.65rem] text-muted-foreground/40 font-mono mt-0.5 hidden lg:block",children:e.eventScope})]})]},e.name))]})]})]})}function J({activeTab:e,onChange:r}){return(0,t.jsx)("div",{className:"inline-flex items-center rounded-md border border-border bg-muted/30 p-0.5 mb-5",children:[{id:"activity",label:"Activity"},{id:"policies",label:"Configure"}].map(s=>(0,t.jsx)("button",{onClick:()=>r(s.id),className:`px-3 py-1.5 text-xs font-medium rounded transition-all ${e===s.id?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"}`,children:s.label},s.id))})}e.s(["default",0,function({initialTab:e="activity"}){let s=(0,P.useUrlParams)(),[a,l]=(0,r.useState)(e),[i,d]=(0,r.useState)(void 0),[c,m]=(0,r.useState)(null),[x,u]=(0,r.useState)([]);(0,r.useEffect)(()=>{y().then(e=>{d(e.clis.some(e=>e.installed)),m({enabled:e.enabledPolicies.length,total:e.policies.length+(e.customPolicies?.length??0)}),u(e.clis.filter(e=>e.installed).map(e=>e.label))}).catch(()=>d(void 0))},[]);let p=0===x.length?"Policy evaluations":x.length<=3?`Policy evaluations across ${x.join(", ")}`:`Policy evaluations across ${x.length} agents`,h=e=>{l(e),s.setAll({tab:"activity"===e?void 0:e})};return(0,t.jsxs)("div",{className:"min-h-screen bg-background px-4 py-6 sm:px-6 lg:px-10",children:[(0,t.jsxs)("div",{className:"mb-6",children:[(0,t.jsxs)(n.default,{href:"/projects",className:"inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",children:[(0,t.jsx)(o,{className:"h-3.5 w-3.5"}),"Back"]}),(0,t.jsxs)("div",{className:"flex items-center gap-3 mt-3",children:[(0,t.jsx)("h1",{className:"text-2xl font-bold text-foreground tracking-tight",children:"Policies"}),"activity"===a&&(0,t.jsxs)("span",{className:"relative flex h-2.5 w-2.5 mt-0.5",children:[(0,t.jsx)("span",{className:"animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"}),(0,t.jsx)("span",{className:"relative inline-flex rounded-full h-2.5 w-2.5 bg-emerald-500"})]})]}),(0,t.jsx)("p",{className:"text-sm text-muted-foreground mt-1",children:"activity"===a?(0,t.jsxs)(t.Fragment,{children:[p,c&&(0,t.jsxs)("span",{className:"text-muted-foreground/60",children:[" · ","enabled policies"," ",(0,t.jsxs)("span",{className:"font-mono text-foreground/70",children:[c.enabled,"/",c.total]})]}),(0,t.jsxs)("span",{className:"block text-xs text-muted-foreground/50 mt-0.5",children:["To configure policies,"," ",(0,t.jsx)("button",{className:"underline underline-offset-2 hover:text-foreground transition-colors",onClick:()=>h("policies"),children:"go here"})]})]}):"Configure Policies"})]}),(0,t.jsx)(J,{activeTab:a,onChange:h}),"activity"===a?(0,t.jsx)(W,{hooksInstalled:i,onSwitchTab:h}):(0,t.jsx)(K,{onHooksInstallChange:d})]})}],64245)}]);
|
package/src/auth/login.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import { platform } from "node:os";
|
|
3
|
-
import { writeTokens, type AuthTokens } from "./token-store";
|
|
4
|
-
|
|
5
|
-
const DEFAULT_SERVER_URL = process.env.FAILPROOFAI_SERVER_URL ?? "https://api.befailproof.ai";
|
|
6
|
-
const HTTP_TIMEOUT_MS = 10_000;
|
|
7
|
-
|
|
8
|
-
interface DeviceCodeResponse {
|
|
9
|
-
device_code: string;
|
|
10
|
-
user_code: string;
|
|
11
|
-
verification_url: string;
|
|
12
|
-
expires_in: number;
|
|
13
|
-
interval: number;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface TokenResponse {
|
|
17
|
-
access_token: string;
|
|
18
|
-
refresh_token: string;
|
|
19
|
-
expires_in: number;
|
|
20
|
-
user: { id: string; email: string; name?: string };
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function openBrowser(url: string): void {
|
|
24
|
-
const os = platform();
|
|
25
|
-
try {
|
|
26
|
-
if (os === "darwin") {
|
|
27
|
-
spawn("open", [url], { detached: true, stdio: "ignore" }).unref();
|
|
28
|
-
} else if (os === "win32") {
|
|
29
|
-
// On cmd's `start`, the first quoted token is treated as a window
|
|
30
|
-
// title. Pass an empty title so URLs containing "&" or spaces are
|
|
31
|
-
// interpreted as the target, not the title.
|
|
32
|
-
spawn("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore" }).unref();
|
|
33
|
-
} else {
|
|
34
|
-
spawn("xdg-open", [url], { detached: true, stdio: "ignore" }).unref();
|
|
35
|
-
}
|
|
36
|
-
} catch {
|
|
37
|
-
// Fallback: the URL is already printed above.
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function postJson<T>(url: string, body: unknown, timeoutMs = HTTP_TIMEOUT_MS): Promise<T> {
|
|
42
|
-
const resp = await fetch(url, {
|
|
43
|
-
method: "POST",
|
|
44
|
-
headers: { "Content-Type": "application/json" },
|
|
45
|
-
body: JSON.stringify(body),
|
|
46
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
47
|
-
});
|
|
48
|
-
if (!resp.ok) {
|
|
49
|
-
throw new Error(`${url} → ${resp.status} ${resp.statusText}`);
|
|
50
|
-
}
|
|
51
|
-
return (await resp.json()) as T;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export async function login(): Promise<void> {
|
|
55
|
-
const serverUrl = DEFAULT_SERVER_URL;
|
|
56
|
-
|
|
57
|
-
console.log("Requesting device code...");
|
|
58
|
-
const dc = await postJson<DeviceCodeResponse>(`${serverUrl}/api/v1/auth/device-code`, {});
|
|
59
|
-
|
|
60
|
-
console.log(`\n Open this URL in your browser (will be opened automatically):`);
|
|
61
|
-
console.log(` ${dc.verification_url}\n`);
|
|
62
|
-
console.log(` Your code: ${dc.user_code}\n`);
|
|
63
|
-
|
|
64
|
-
openBrowser(dc.verification_url);
|
|
65
|
-
|
|
66
|
-
const deadline = Date.now() + dc.expires_in * 1000;
|
|
67
|
-
const intervalMs = dc.interval * 1000;
|
|
68
|
-
|
|
69
|
-
while (Date.now() < deadline) {
|
|
70
|
-
await new Promise((r) => setTimeout(r, intervalMs));
|
|
71
|
-
try {
|
|
72
|
-
const result = await postJson<TokenResponse | { status: string }>(
|
|
73
|
-
`${serverUrl}/api/v1/auth/device-token`,
|
|
74
|
-
{ device_code: dc.device_code },
|
|
75
|
-
);
|
|
76
|
-
if ("access_token" in result) {
|
|
77
|
-
const tokens: AuthTokens = {
|
|
78
|
-
access_token: result.access_token,
|
|
79
|
-
refresh_token: result.refresh_token,
|
|
80
|
-
expires_at: Math.floor(Date.now() / 1000) + result.expires_in,
|
|
81
|
-
user_email: result.user.email,
|
|
82
|
-
user_id: result.user.id,
|
|
83
|
-
server_url: serverUrl,
|
|
84
|
-
};
|
|
85
|
-
writeTokens(tokens);
|
|
86
|
-
console.log(`Logged in as ${result.user.email}`);
|
|
87
|
-
|
|
88
|
-
// Auto-start relay daemon
|
|
89
|
-
try {
|
|
90
|
-
const { ensureRelayRunning } = await import("../relay/daemon");
|
|
91
|
-
ensureRelayRunning();
|
|
92
|
-
console.log("Relay daemon started.");
|
|
93
|
-
} catch (e) {
|
|
94
|
-
console.warn("Failed to auto-start relay daemon:", e);
|
|
95
|
-
}
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
} catch {
|
|
99
|
-
// Pending or transient error — keep polling
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
throw new Error("Login timed out. Run `failproofai login` again.");
|
|
104
|
-
}
|
package/src/auth/logout.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { readTokens, clearTokens } from "./token-store";
|
|
2
|
-
import { stopRelay } from "../relay/pid";
|
|
3
|
-
|
|
4
|
-
const LOGOUT_TIMEOUT_MS = 3_000;
|
|
5
|
-
|
|
6
|
-
export async function logout(): Promise<void> {
|
|
7
|
-
const tokens = readTokens();
|
|
8
|
-
if (!tokens) {
|
|
9
|
-
console.log("Not logged in.");
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Best-effort server revoke with a short timeout — the local logout
|
|
14
|
-
// must not block on a slow network.
|
|
15
|
-
try {
|
|
16
|
-
await fetch(`${tokens.server_url}/api/v1/auth/logout`, {
|
|
17
|
-
method: "POST",
|
|
18
|
-
headers: { "Content-Type": "application/json" },
|
|
19
|
-
body: JSON.stringify({ refresh_token: tokens.refresh_token }),
|
|
20
|
-
signal: AbortSignal.timeout(LOGOUT_TIMEOUT_MS),
|
|
21
|
-
});
|
|
22
|
-
} catch {
|
|
23
|
-
// Network or timeout — proceed to local clear anyway
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
stopRelay();
|
|
28
|
-
} catch {
|
|
29
|
-
// Best-effort daemon stop
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
clearTokens();
|
|
33
|
-
console.log("Logged out.");
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function whoami(): void {
|
|
37
|
-
const tokens = readTokens();
|
|
38
|
-
if (!tokens) {
|
|
39
|
-
console.log("Not logged in. Run `failproofai login` to authenticate.");
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
console.log(`Logged in as ${tokens.user_email}`);
|
|
43
|
-
console.log(`Server: ${tokens.server_url}`);
|
|
44
|
-
const expiresIn = tokens.expires_at - Math.floor(Date.now() / 1000);
|
|
45
|
-
if (expiresIn > 0) {
|
|
46
|
-
console.log(`Access token expires in ${Math.floor(expiresIn / 60)} minutes`);
|
|
47
|
-
} else {
|
|
48
|
-
console.log(`Access token expired (will refresh on next use)`);
|
|
49
|
-
}
|
|
50
|
-
}
|
package/src/auth/token-store.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
readFileSync,
|
|
3
|
-
writeFileSync,
|
|
4
|
-
existsSync,
|
|
5
|
-
mkdirSync,
|
|
6
|
-
unlinkSync,
|
|
7
|
-
renameSync,
|
|
8
|
-
openSync,
|
|
9
|
-
closeSync,
|
|
10
|
-
} from "node:fs";
|
|
11
|
-
import { join } from "node:path";
|
|
12
|
-
import { homedir } from "node:os";
|
|
13
|
-
|
|
14
|
-
export interface AuthTokens {
|
|
15
|
-
access_token: string;
|
|
16
|
-
refresh_token: string;
|
|
17
|
-
expires_at: number;
|
|
18
|
-
user_email: string;
|
|
19
|
-
user_id: string;
|
|
20
|
-
server_url: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const AUTH_DIR = join(homedir(), ".failproofai");
|
|
24
|
-
const AUTH_FILE = join(AUTH_DIR, "auth.json");
|
|
25
|
-
|
|
26
|
-
function ensureAuthDir(): void {
|
|
27
|
-
if (!existsSync(AUTH_DIR)) mkdirSync(AUTH_DIR, { recursive: true, mode: 0o700 });
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function readTokens(): AuthTokens | null {
|
|
31
|
-
if (!existsSync(AUTH_FILE)) return null;
|
|
32
|
-
try {
|
|
33
|
-
const raw = readFileSync(AUTH_FILE, "utf8");
|
|
34
|
-
return JSON.parse(raw) as AuthTokens;
|
|
35
|
-
} catch {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Write tokens atomically with 0600 permissions *from creation*.
|
|
42
|
-
* We open with O_WRONLY|O_CREAT|O_TRUNC and explicit mode 0600 so the
|
|
43
|
-
* file is never world-readable, not even briefly during the write.
|
|
44
|
-
* Then rename into place (atomic on POSIX).
|
|
45
|
-
*/
|
|
46
|
-
export function writeTokens(tokens: AuthTokens): void {
|
|
47
|
-
ensureAuthDir();
|
|
48
|
-
const tmpPath = `${AUTH_FILE}.tmp`;
|
|
49
|
-
const fd = openSync(tmpPath, "w", 0o600);
|
|
50
|
-
try {
|
|
51
|
-
writeFileSync(fd, JSON.stringify(tokens, null, 2));
|
|
52
|
-
} finally {
|
|
53
|
-
closeSync(fd);
|
|
54
|
-
}
|
|
55
|
-
renameSync(tmpPath, AUTH_FILE);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function clearTokens(): void {
|
|
59
|
-
if (existsSync(AUTH_FILE)) unlinkSync(AUTH_FILE);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function isLoggedIn(): boolean {
|
|
63
|
-
return existsSync(AUTH_FILE);
|
|
64
|
-
}
|