claude-code-session-manager 0.86.0 → 0.87.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/AgentLibrary-DyLWzZDf.js +3 -0
- package/dist/assets/{DataModel-Q4jhl24R.js → DataModel--mISIJ6h.js} +1 -1
- package/dist/assets/{History-Cj2FejEo.js → History-C2ahUXTg.js} +2 -2
- package/dist/assets/{Hooks-CaelQI6t.js → Hooks-BiC6oyR2.js} +3 -3
- package/dist/assets/{HostBilko--v7cMR8I.js → HostBilko-BPleEOld.js} +1 -1
- package/dist/assets/{Library-DgI9oCCZ.js → Library-Dc8Qst1R.js} +1 -1
- package/dist/assets/{ListDetail-DYUZN-x-.js → ListDetail-DIXh-OLX.js} +1 -1
- package/dist/assets/MarkdownEditor-C90bkLXK.js +1 -0
- package/dist/assets/{McpServers-ypCYURh3.js → McpServers-DqcbLOLZ.js} +2 -2
- package/dist/assets/{Memory-C2qYp-3M.js → Memory-CW62MXlh.js} +4 -4
- package/dist/assets/{Panel-Cj2kw-Zv.js → Panel-Bw1FhRuF.js} +1 -1
- package/dist/assets/Permissions-BcUC-5y8.js +3 -0
- package/dist/assets/{Plugins-C1Vj8_dU.js → Plugins-BnKx9flD.js} +2 -2
- package/dist/assets/{ProvenanceBadge-DczPNM5U.js → ProvenanceBadge-Bw5vNVPT.js} +1 -1
- package/dist/assets/{SaveBar-Cd_7U6Gb.js → SaveBar-CWr0O_w-.js} +1 -1
- package/dist/assets/Scheduler-DYdLuUqq.js +14 -0
- package/dist/assets/{ScopeSwitcher-DVSyI44-.js → ScopeSwitcher-CrBLbg8s.js} +1 -1
- package/dist/assets/Settings-DluB-vN1.js +3 -0
- package/dist/assets/{SkillReferenceGraph-CUv1_Q2c.js → SkillReferenceGraph-CHLSseay.js} +1 -1
- package/dist/assets/{Skills-C_YHkAy-.js → Skills-gNdo_HNK.js} +2 -2
- package/dist/assets/{SystemPrompt-B8R7T9xn.js → SystemPrompt-Cru05-Ia.js} +1 -1
- package/dist/assets/{TagLibrary-dj9YHWyy.js → TagLibrary-DNHY0xou.js} +1 -1
- package/dist/assets/{TiptapBody-DnSBUjHE.js → TiptapBody-I4lmbCgP.js} +1 -1
- package/dist/assets/{Toggle-CjV_BJn6.js → Toggle-bWMHjmRh.js} +1 -1
- package/dist/assets/{index-CDo9xBR9.css → index-DV3PorRY.css} +1 -1
- package/dist/assets/{index-CXFQIPhO.js → index-fc_JjdxL.js} +724 -724
- package/dist/assets/settingsSchema-BfhtZnGD.js +3 -0
- package/dist/index.html +2 -2
- package/package.json +14 -14
- package/plugins/CLAUDE.md +61 -0
- package/plugins/session-manager-dev/.claude-plugin/plugin.json +1 -1
- package/plugins/session-manager-dev/skills/builder/4-manual/SKILL.md +1 -1
- package/plugins/session-manager-dev/skills/ops-sweep/SKILL.md +1 -1
- package/scripts/scheduler-mcp-server.cjs +7 -0
- package/src/main/__tests__/agentModelResolve.test.cjs +100 -9
- package/src/main/__tests__/broadcastCoalescer.test.cjs +18 -0
- package/src/main/__tests__/epicMint.test.cjs +2 -2
- package/src/main/__tests__/health-delegation-chain.test.cjs +2 -1
- package/src/main/__tests__/needsReviewLedger.test.cjs +162 -0
- package/src/main/__tests__/opsErrorLogTelemetryTap.test.cjs +3 -3
- package/src/main/__tests__/pollLoop-dispatch-on-failure.test.cjs +15 -1
- package/src/main/__tests__/prdCreateDisposition.test.cjs +201 -0
- package/src/main/__tests__/prdFrontmatterDisposition.test.cjs +125 -0
- package/src/main/__tests__/prdLocations.test.cjs +100 -2
- package/src/main/__tests__/prdLocationsArchived.test.cjs +43 -1
- package/src/main/__tests__/prdSetDisposition.test.cjs +222 -0
- package/src/main/__tests__/queue-health-verdict.test.cjs +170 -0
- package/src/main/__tests__/queue-starvation-per-project.test.cjs +14 -2
- package/src/main/__tests__/queueHistory.test.cjs +63 -0
- package/src/main/__tests__/reconcileTiming.test.cjs +135 -0
- package/src/main/__tests__/scheduleJobTransitions.test.cjs +101 -1
- package/src/main/__tests__/scheduler-boot-orphans.test.cjs +2 -2
- package/src/main/__tests__/scheduler-broadcast-reconcile.test.cjs +121 -0
- package/src/main/__tests__/scheduler-cross-project-batch.test.cjs +43 -0
- package/src/main/__tests__/scheduler-guard-verdict-autoresolve.test.cjs +344 -0
- package/src/main/__tests__/scheduler-job-budget.test.cjs +172 -0
- package/src/main/__tests__/scheduler-looks-done.test.cjs +93 -3
- package/src/main/__tests__/scheduler-porcelain-rename.test.cjs +164 -0
- package/src/main/__tests__/scheduler-reap-dead-running-jobs.test.cjs +160 -0
- package/src/main/__tests__/scheduler-reaper-helpers-basics.test.cjs +87 -0
- package/src/main/__tests__/scheduler-shared-tree-guard.test.cjs +88 -0
- package/src/main/__tests__/scheduler-starve-escalation.test.cjs +14 -4
- package/src/main/__tests__/scheduler-worktree-cap-defer.test.cjs +14 -0
- package/src/main/chatRunner.cjs +8 -5
- package/src/main/health.cjs +1 -1
- package/src/main/historyAggregator.cjs +5 -0
- package/src/main/index.cjs +95 -44
- package/src/main/ipcSchemas.cjs +47 -0
- package/src/main/lib/__tests__/active-sessions.test.cjs +251 -0
- package/src/main/lib/__tests__/bootSelfHeal.test.cjs +107 -0
- package/src/main/lib/__tests__/delegationReadiness.test.cjs +322 -43
- package/src/main/lib/__tests__/effectiveModelInfo.test.cjs +239 -0
- package/src/main/lib/__tests__/gitWorktree.test.cjs +89 -0
- package/src/main/lib/__tests__/guardShims.test.cjs +151 -0
- package/src/main/lib/__tests__/opsRootAbsoluteCwd.test.cjs +5 -5
- package/src/main/lib/__tests__/prdDisposition.test.cjs +224 -0
- package/src/main/lib/__tests__/reaperHelpers.test.cjs +179 -1
- package/src/main/lib/__tests__/usageCircuit.test.cjs +224 -0
- package/src/main/lib/__tests__/watchdog-helpers.test.cjs +312 -0
- package/src/main/lib/__tests__/watchdog-relaunch.test.cjs +193 -0
- package/{scripts → src/main}/lib/activeSessions.cjs +50 -4
- package/src/main/lib/agentModelResolve.cjs +65 -27
- package/src/main/lib/bootSelfHeal.cjs +88 -0
- package/src/main/lib/delegationReadiness.cjs +290 -225
- package/src/main/lib/effectiveModelInfo.cjs +333 -0
- package/src/main/lib/ephemeralCwd.cjs +1 -1
- package/src/main/lib/epicMint.cjs +3 -3
- package/src/main/lib/gitWorktree.cjs +42 -12
- package/src/main/lib/guardShims.cjs +156 -0
- package/src/main/lib/jobDirtFilter.cjs +7 -2
- package/src/main/lib/launchFailure.cjs +2 -1
- package/src/main/lib/mcpToolCatalog.cjs +4 -1
- package/src/main/lib/needsReviewLedger.cjs +205 -0
- package/src/main/lib/opsErrorLog.cjs +1 -1
- package/src/main/lib/opsOwnership.cjs +1 -1
- package/src/main/lib/prdCreate.cjs +56 -1
- package/src/main/lib/prdDisposition.cjs +199 -0
- package/src/main/lib/prdFrontmatter.cjs +8 -2
- package/src/main/lib/prdLocations.cjs +167 -45
- package/src/main/lib/projectHomeAdminRoutes.cjs +4 -4
- package/src/main/lib/projectPageSummarySchema.cjs +1 -1
- package/src/main/lib/projectRootResolve.cjs +1 -1
- package/src/main/lib/queueHistory.cjs +19 -1
- package/src/main/lib/queueStore.cjs +6 -1
- package/src/main/lib/reaperHelpers.cjs +181 -15
- package/src/main/lib/scheduleJobSchema.cjs +8 -0
- package/src/main/lib/scheduleJobTransitions.cjs +33 -0
- package/src/main/lib/schedulerConfig.cjs +24 -0
- package/src/main/lib/usageCircuit.cjs +159 -0
- package/{scripts → src/main}/lib/watchdogHelpers.cjs +1 -1
- package/src/main/scheduler/prdParser.cjs +13 -0
- package/src/main/scheduler.cjs +1285 -143
- package/src/main/templates/PRD_AUTHORING.md +50 -0
- package/src/main/templates/project-pages-catalog.json +1 -1
- package/src/main/usage.cjs +21 -3
- package/src/preload/api.d.ts +92 -1
- package/src/preload/index.cjs +10 -0
- package/web/README.md +41 -0
- package/{scripts/render-project-pages.cjs → web/project-pages/render.cjs} +4 -4
- package/{scripts/render-project-pages → web/project-pages/renderer}/dist/renderer.cjs +1 -1
- package/{scripts/validate-project-pages-summary.cjs → web/project-pages/validate-summary.cjs} +5 -5
- package/dist/assets/AgentLibrary-DTFL7y8G.js +0 -3
- package/dist/assets/MarkdownEditor-DCIubYWf.js +0 -1
- package/dist/assets/Permissions-BiYZNGYW.js +0 -3
- package/dist/assets/Scheduler-DcLBiJBq.js +0 -14
- package/dist/assets/Settings-Cv-pRyms.js +0 -3
- package/dist/assets/settingsSchema-BJVciriw.js +0 -3
- /package/{scripts/project-pages-logic → web/project-pages/logic}/dist/logic.cjs +0 -0
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import{a9 as e,aE as ve,ai as i,aB as Te,a as ue,Y as U,as as L,a3 as H,a5 as re,$ as z,ah as be,aC as le,am as we,an as je,a0 as Se,aH as ce,x as Le,ad as W,q as Me,L as Oe,m as Ue,k as Ne,s as ye,O as Qe,D as B,d as D,a1 as Fe,v as _e,T as Ye,ae as Pe,aw as $e,j as ae,r as Ce,i as We,aq as Ke,z as Xe,p as He,ay as Ze,av as se,w as et,C as tt,aF as st,aj as nt,y as at,aI as rt,aG as Ae,l as lt,n as he}from"./index-CXFQIPhO.js";import{l as it}from"./listSkills-QORduPIk.js";import{T as ot}from"./Toggle-CjV_BJn6.js";import"./monaco-editor-BW5C4Iv1.js";function dt({options:t,active:s,onChange:n}){return e.jsx("div",{className:"inline-flex gap-1 bg-bg-hi p-1 rounded-xl shadow-[inset_0_0_0_1px] shadow-line",children:t.map(({key:a,label:d})=>{const o=s===a;return e.jsx("button",{type:"button",onClick:()=>n(a),className:`px-[18px] py-[7px] rounded-lg text-[13.5px] transition-colors ${o?"bg-bg-elev shadow-[inset_0_0_0_1px] shadow-line font-semibold text-fg":"font-medium text-fg-dim hover:text-fg"}`,children:d},a)})})}const ct=5e3;let oe=null,ne=null;async function De(t){const s=Date.now();return!(t!=null&&t.fresh)&&oe&&s-oe.at<ct?oe.result:ne||(ne=(async()=>{try{const n=await window.api.schedule.lintQueue();return oe={result:n,at:Date.now()},n}finally{ne=null}})(),ne)}function qe({options:t,value:s,onChange:n,pillPadding:a="px-3 py-1.5"}){return e.jsx("div",{className:"flex gap-1.5 flex-wrap",children:t.map(d=>{const o=d.value===s;return e.jsxs("button",{type:"button",onClick:()=>n(d.value),className:`rounded-full ${a} text-[12.5px] border transition-colors ${o?"bg-accent text-white border-accent font-semibold":"bg-bg-hi text-fg-dim border-line hover:border-fg-faint font-medium"}`,children:[d.label,d.count!==void 0&&e.jsxs("span",{children:[" ",d.count]})]},d.value)})})}const ut=5,xt=1440*60*1e3,Be="sm.scheduler.hiddenCompletedSlugs",de="sm.scheduler.focusedJobIndex",Ge="sm.scheduler.queueFilter";function pt(t,s=60){const n=t.trim();return n.length<=s?n:`${n.slice(0,s-1)}…`}const mt=["all","running","investigating","pending","completed","skipped","needs_review","failed","quarantined"];function ht(){try{const t=localStorage.getItem(Ge);if(!t)return{text:"",status:"all"};const s=JSON.parse(t);return{text:"",status:mt.includes(s.status)?s.status:"all"}}catch{return{text:"",status:"all"}}}function ft(t){try{localStorage.setItem(Ge,JSON.stringify({status:t.status}))}catch{}}function gt(t,s){if(s.status==="all"&&!s.text)return t;const n=s.text.toLowerCase();return t.filter(a=>{if(s.status!=="all"&&a.status!==s.status)return!1;if(!n)return!0;const d=be(a.cwd)??"";return a.title.toLowerCase().includes(n)||a.slug.toLowerCase().includes(n)||d.toLowerCase().includes(n)})}function bt(){try{const t=localStorage.getItem(Be);if(!t)return new Set;const s=JSON.parse(t);return Array.isArray(s)?new Set(s.filter(n=>typeof n=="string")):new Set}catch{return new Set}}function Re(t){try{localStorage.setItem(Be,JSON.stringify([...t]))}catch{}}function vt({scopeCwd:t=null,navigate:s}){const n=ve(p=>p.snapshot),a=i.useMemo(()=>!n||!t?n:{...n,jobs:n.jobs.filter(p=>p.cwd===t)},[n,t]),[d,o]=i.useState(null),[r,u]=i.useState(!1),[x,c]=i.useState(()=>Date.now()),[b,v]=i.useState(()=>bt()),[h,j]=i.useState(!1),[k,C]=i.useState(()=>ht()),[w,y]=i.useState(!1),[N,g]=i.useState("queue"),f=i.useRef(null),[A,$]=i.useState(()=>{try{return Number(localStorage.getItem(de))||0}catch{return 0}}),[G,xe]=i.useState(""),J=Te();i.useEffect(()=>(window.api.schedule.health().then(o).catch(()=>{}),window.api.schedule.onState(()=>{window.api.schedule.health().then(o).catch(()=>{})})),[]),i.useEffect(()=>{if(!J)return;c(Date.now());const p=setInterval(()=>c(Date.now()),1e3);return()=>clearInterval(p)},[J]);const M=i.useMemo(()=>{if(!a)return 15e4;const p=[];for(const S of a.jobs)if(S.status==="completed"&&S.startedAt&&S.finishedAt){const T=Date.parse(S.finishedAt)-Date.parse(S.startedAt);T>0&&p.push(T)}return p.length===0?15e4:p.reduce((S,T)=>S+T,0)/p.length},[a]),K=i.useRef(new Map);i.useEffect(()=>{if(!a)return;const p=[];for(const S of a.jobs){const T=K.current.get(S.slug);T&&T!==S.status&&p.push(`${S.title}: ${T} → ${S.status}`),K.current.set(S.slug,S.status)}p.length>0&&xe(p.join("; "))},[a]);const X=i.useMemo(()=>{var S;const p=new Map;for(const T of((S=a==null?void 0:a.lastTick)==null?void 0:S.holds)??[])p.set(T.slug,T);return p},[a==null?void 0:a.lastTick]),Z=i.useCallback(p=>{var T,ie,ke;const S=(T=f.current)==null?void 0:T.querySelectorAll("[data-job-row]");if(!(!S||S.length===0)){if(p.key==="ArrowDown"){p.preventDefault();const V=Math.min(A+1,S.length-1);$(V);try{localStorage.setItem(de,String(V))}catch{}(ie=S[V])==null||ie.focus()}else if(p.key==="ArrowUp"){p.preventDefault();const V=Math.max(A-1,0);$(V);try{localStorage.setItem(de,String(V))}catch{}(ke=S[V])==null||ke.focus()}}},[A]),pe=i.useCallback(p=>{$(p);try{localStorage.setItem(de,String(p))}catch{}},[]);if(!a)return null;if(N==="supervisor")return e.jsx(Lt,{supervisorConfig:a.config.supervisor,onSetConfig:p=>window.api.schedule.setConfig({supervisor:p}),onBack:()=>g("queue")});const{config:ee,jobs:O,paused:me,lastRunAt:q,nextReset:Q,effectiveConcurrency:R}=a;if(O.length===0)return e.jsx(Nt,{navigate:s});const F={pending:0,running:0,investigating:0,completed:0,needs_review:0,failed:0};for(const p of O)p.status in F&&F[p.status]++;const te=O.filter(p=>p.status==="running"),l=yt({snap:a,now:x,avgDurationMs:M,runningJobs:te}),m=gt(O,k),P=kt(m),{inline:I,collapsedCount:E}=St(m,b,x,h),_=Rt(I,O,P,M,l.kind,x),Y=()=>{const p=new Set(b);for(const S of O)(S.status==="completed"||S.status==="failed")&&p.add(S.slug);v(p),Re(p)},Je=async()=>{const p=O.filter(ie=>ie.status!=="running").length;if(p===0)return;const S=`Archive ${p} non-running PRD${p===1?"":"s"} and remove from the queue?
|
|
2
|
-
|
|
3
|
-
Files are moved to prds-archived/<timestamp>/ and can be restored from disk. Running jobs are kept.`;if(!window.confirm(S))return;const T=await window.api.schedule.clearQueue();T.ok||L.error(`Clear queue failed: ${T.error??"unknown error"}`)},Ve=()=>{v(new Set),Re(new Set),j(!1)},ze=I.some(p=>p.status==="completed");return e.jsxs("div",{className:"overflow-y-auto h-full",children:[e.jsx("div",{"aria-live":"polite","aria-atomic":"true",className:"sr-only",children:G}),e.jsxs("div",{className:"px-9 py-6 max-w-[1100px] mx-auto space-y-4",children:[e.jsxs("div",{className:`flex flex-wrap items-center gap-3 px-4 py-3 rounded-xl border ${Pt(l.kind)}`,title:l.tooltip,children:[e.jsxs("div",{className:"flex items-center gap-3 min-w-0 flex-1",children:[e.jsx("div",{className:`w-[38px] h-[38px] rounded-xl bg-bg border border-line flex items-center justify-center shrink-0 ${$t(l.kind)}`,children:e.jsx(ue,{name:"clock",size:19})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-[14px] text-fg truncate",children:At(Dt(l.line1,a.utilization))}),l.line2&&e.jsx("div",{className:"text-[12px] text-fg-faint font-mono mt-0.5 truncate",children:l.line2})]})]}),e.jsxs("span",{className:"ml-auto font-mono text-[11.5px] text-fg-faint whitespace-nowrap",children:[(R==null?void 0:R.cap)??5," slot",((R==null?void 0:R.cap)??5)!==1?"s":""," · last batch ",U(q?Date.parse(q):null,x)]}),l.action&&e.jsx("button",{type:"button",onClick:l.action.onClick,className:"text-[12px] px-3 py-1.5 border border-line hover:border-fg-faint rounded-lg shrink-0 hover:bg-bg-hi text-fg-dim hover:text-fg",title:l.action.title,children:l.action.label})]}),d&&d.consecutiveFailures>5&&d.lastFailureKind==="meter_rate_limited"&&!me&&!w&&e.jsxs("div",{className:"flex items-center gap-3 px-4 py-3 bg-amber-400/15 border border-amber-400/30 rounded-xl",children:[e.jsx("span",{"aria-hidden":"true",children:"⚠"}),e.jsxs("span",{className:"text-[13.5px] text-amber-400/90",children:[e.jsx("strong",{className:"font-semibold",children:"Usage meter unavailable"})," — last good reading"," ",U(d.lastPollAt,x),". Firing on a conservative estimate until it recovers."]}),e.jsx("button",{type:"button",onClick:()=>y(!0),className:"ml-auto text-[12px] text-amber-400/70 hover:text-amber-400 shrink-0",title:"Dismiss this banner. The scheduler continues firing normally.",children:"Dismiss"})]}),e.jsxs("div",{className:"flex items-center gap-[18px] flex-wrap bg-bg-elev border border-line rounded-xl px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[13px] text-fg-dim",children:"Start jobs"}),e.jsxs("select",{value:ee.firePolicy??"when-available",onChange:p=>window.api.schedule.setConfig({firePolicy:p.target.value}),className:"appearance-none border border-line bg-bg-hi rounded-lg px-2.5 py-1.5 font-sans text-[13px] text-fg font-medium",title:"when-available: poll usage and fire when tokens are below threshold. on-reset: fire after each 5h reset. manual: only on Run now.",children:[e.jsx("option",{value:"when-available",children:"when available"}),e.jsx("option",{value:"on-reset",children:"only on reset"}),e.jsx("option",{value:"manual",children:"manually"})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[13px] text-fg-dim",children:"Up to"}),(R==null?void 0:R.source)==="env"&&e.jsx("span",{className:"text-[10px] font-semibold uppercase tracking-wide text-amber-400/90 bg-amber-400/10 border border-amber-400/30 rounded px-1.5 py-0.5",title:"Pinned by SM_SESSION_SLOTS — unset the env var to edit",children:"env"}),e.jsx("input",{type:"number",min:0,max:10,value:(R==null?void 0:R.cap)??5,disabled:(R==null?void 0:R.source)==="env",onChange:p=>{window.api.schedule.setSessionSlots(Number(p.target.value))},className:"w-11 text-center border border-line bg-bg-hi rounded-lg py-1.5 font-mono text-[13px] text-fg disabled:opacity-50 disabled:cursor-not-allowed",title:(R==null?void 0:R.source)==="env"?"pinned by SM_SESSION_SLOTS — unset the env var to edit":"Machine-wide claude -p session slots, shared with chat runs"}),e.jsx("span",{className:"text-[13px] text-fg-dim",children:"at once"})]}),(ee.firePolicy??"when-available")==="when-available"&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[13px] text-fg-dim",children:"Pause above"}),e.jsx("input",{type:"number",min:0,max:100,value:ee.utilizationThreshold??90,onChange:p=>window.api.schedule.setConfig({utilizationThreshold:Number(p.target.value)}),className:"w-11 text-center border border-line bg-bg-hi rounded-lg py-1.5 font-mono text-[13px] text-fg",title:"Fire only when 5h utilization is below this percent"}),e.jsx("span",{className:"text-[13px] text-fg-dim",children:"% of window"})]}),e.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[e.jsx("button",{type:"button",onClick:()=>window.api.schedule.forceTick().then(L.fromOutcome).catch(()=>L.error("Failed to fire batch")),disabled:F.pending===0&&F.running===0,className:"bg-accent text-white rounded-lg px-4 py-2 text-[13px] font-semibold whitespace-nowrap disabled:opacity-40 disabled:cursor-not-allowed hover:opacity-90",title:"Bypasses the billing-usage poll. Use when the meter is rate-limited or you want immediate progress.",children:"Fire next batch now"}),e.jsx("button",{type:"button",onClick:()=>window.api.schedule.rescan().then(L.fromOutcome).catch(()=>L.error("Failed to rescan")),className:"bg-bg-hi border border-line text-fg-dim hover:text-fg rounded-lg px-3.5 py-2 text-[13px] font-medium",title:"Re-scan the prds/ folder. Use when you've added or edited PRDs on disk and want the queue to reflect them immediately.",children:"Refresh"})]})]}),te.length>0&&(()=>{const p=(R==null?void 0:R.cap)??5,S=O.filter(T=>T.status==="pending").length;return e.jsxs("div",{className:"flex items-center gap-2 text-[12px] font-mono",children:[e.jsxs("span",{className:"px-2 py-0.5 rounded bg-amber-400/20 text-amber-400 shrink-0",children:[te.length,"/",p," running"]}),S>0&&e.jsxs("span",{className:"text-fg-faint",children:["+",S," ready in this group"]})]})})(),O.length>0&&e.jsx(Tt,{filter:k,onChange:p=>{C(p),ft(p)}}),e.jsxs("div",{className:"bg-bg-hi border border-line rounded-2xl overflow-hidden",children:[e.jsxs("div",{className:"flex items-center justify-between px-[18px] py-3 bg-bg-elev",children:[e.jsxs("span",{className:"font-serif text-base font-semibold text-fg",children:[m.length," job",m.length!==1?"s":""]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"font-mono text-[12px] text-fg-faint",children:[F.pending,"p · ",F.running,"r · ",F.completed,"d",F.failed>0&&e.jsxs("span",{className:"text-accent",children:[" · ",F.failed,"f"]})]}),ze&&e.jsx("button",{type:"button",onClick:Y,className:"text-[12.5px] text-fg-dim hover:text-fg bg-transparent border-0 cursor-pointer font-medium",title:"Hide completed jobs from this view (queue.json unchanged — they remain in history)",children:"Clear completed"}),e.jsx("button",{type:"button",onClick:Je,disabled:O.every(p=>p.status==="running"),className:"text-[12px] text-accent border border-accent/40 hover:bg-accent/10 rounded-md px-2.5 py-1 cursor-pointer font-medium disabled:opacity-40 disabled:cursor-not-allowed",title:"Archive every non-running PRD (moved to prds-archived/<timestamp>/) and remove them from the queue. Running jobs are kept.",children:"Archive & clear queue…"})]})]}),I.length===0&&E===0&&e.jsx("div",{className:"px-[18px] py-6 text-[13px] text-fg-faint italic",children:"no matching jobs"}),e.jsx("div",{ref:f,role:"list","aria-label":"Job queue",onKeyDown:Z,children:I.map((p,S)=>e.jsx(It,{job:p,eta:_.get(p.slug)??null,elapsedMs:p.status==="running"&&p.startedAt?x-Date.parse(p.startedAt):null,avgDurationMs:M,listIndex:S,hold:X.get(p.slug),onFocused:pe},p.slug))}),E>0&&e.jsxs("button",{type:"button",onClick:()=>j(p=>!p),className:"w-full text-left text-[12px] text-fg-faint hover:text-fg-dim px-[18px] py-3 border-t border-line",title:h?"Re-collapse old/cleared completed":"Show all completed (incl. cleared and >24h)",children:[h?"▾":"▸"," ",E," more completed",e.jsx("span",{className:"ml-1.5 font-mono text-[11.5px] text-fg-faint",children:"· fresh & capped at 5 shown inline"}),b.size>0&&e.jsx("span",{className:"ml-2 underline",onClick:p=>{p.stopPropagation(),Ve()},children:"un-hide"})]})]}),e.jsx(Ot,{snap:a,health:d,now:x,open:r,setOpen:u}),!me&&e.jsxs("div",{className:"flex gap-2.5 bg-sage/10 border border-sage/30 rounded-xl px-3.5 py-2.5 text-[13.5px] text-fg-dim leading-relaxed",children:[e.jsx("span",{"aria-hidden":"true",children:"✓"}),e.jsxs("span",{children:[e.jsx("strong",{className:"font-semibold text-fg",children:"Nothing needed from you."})," ","Close the app if you like — jobs keep running, and History shows how each one ended."]})]}),e.jsxs("div",{className:"flex items-center justify-between text-[12px] text-fg-faint pt-1 border-t border-line",children:[e.jsxs("span",{children:[Q&&e.jsxs("span",{title:`next 5h reset: ${Q}`,children:["reset ",H(Date.parse(Q)-x)]}),q&&e.jsxs("span",{className:"ml-2",title:q,children:["last run ",H(x-Date.parse(q))," ago"]})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("button",{type:"button",onClick:()=>g("supervisor"),className:"hover:text-fg-dim underline",title:"Open supervisor log and settings",children:"supervisor"}),e.jsx("button",{type:"button",onClick:()=>window.api.schedule.openFolder(),className:"hover:text-fg-dim underline",children:"folder"})]})]})]})]})}const wt=[{title:"Start a session",body:"In Sessions, pick an Agent and a Mission, describe the outcome you want, then Approve & start. Its thread writes the PRD files into that session's own folder."},{title:"Queue what it wrote",body:"The PRDs tab lists every file the session produced. Queue one, or the whole session, and they appear here."},{title:"Leave it alone",body:"Jobs start themselves inside your window, pause on rate-limit, and resume at the reset. History records how each ended."}],jt=[{term:"Session",def:"One goal, one Claude session, and the folder of PRDs written to reach it."},{term:"PRD",def:"One markdown file = one job. Authored by the session."},{term:"5-hour window",def:"Your Claude billing window, on a rolling clock."},{term:"Session pool",def:"5 slots shared with terminal and session chats."}];function Nt({navigate:t}){return e.jsx("div",{className:"overflow-y-auto h-full",children:e.jsx("div",{className:"px-9 py-6 max-w-[900px] mx-auto",children:e.jsxs("div",{className:"bg-bg-hi border border-line rounded-2xl px-9 py-8",children:[e.jsx("h2",{className:"m-0 font-serif text-[25px] font-semibold text-fg",children:"Nothing to run yet — the scheduler needs a session."}),e.jsx("p",{className:"mt-2 mb-6 text-[14.5px] text-fg-dim leading-relaxed max-w-[580px]",children:"You don't write PRDs here. A session breaks its goal into numbered PRD files, and this page runs them in order. Two steps, once."}),e.jsx("div",{className:"grid grid-cols-3 gap-3.5",children:wt.map((s,n)=>{const a=n===0;return e.jsxs("div",{className:`bg-bg border rounded-xl px-4 py-4 flex flex-col gap-2 ${a?"border-accent shadow-[0_0_0_3px_rgba(184,92,52,.09)]":"border-line"}`,children:[e.jsx("span",{className:`w-6 h-6 rounded-full grid place-items-center font-mono text-[12px] font-semibold ${a?"bg-accent text-white":"bg-bg-elev text-fg-dim"}`,children:n+1}),e.jsx("h3",{className:"m-0 text-[15px] font-semibold text-fg",children:s.title}),e.jsx("p",{className:"m-0 text-[13.5px] text-fg-dim leading-relaxed",children:s.body}),a&&e.jsx("button",{type:"button",onClick:()=>t==null?void 0:t("terminal"),className:"self-start bg-accent text-white rounded-lg px-3.5 py-1.5 text-[13px] font-semibold mt-1",children:"Go to Sessions →"})]},s.title)})}),e.jsx("dl",{className:"flex mt-[22px] pt-4 border-t border-line gap-5 flex-wrap",children:jt.map(({term:s,def:n})=>e.jsxs("div",{className:"flex-1 min-w-[150px]",children:[e.jsx("dt",{className:"text-[13.5px] font-semibold text-fg mb-0.5",children:s}),e.jsx("dd",{className:"m-0 text-[12.5px] text-fg-faint leading-relaxed",children:n})]},s))})]})})})}function yt({snap:t,now:s,avgDurationMs:n,runningJobs:a}){const{config:d,jobs:o,paused:r,nextReset:u,utilization:x,effectiveConcurrency:c}=t;let b=0,v=0;for(const y of o)y.status==="pending"?b++:y.status==="completed"&&v++;const h=a.length,j=b+h,k=(c==null?void 0:c.cap)??5;if(h>0){const y=a.reduce(($,G)=>($.startedAt??"")<(G.startedAt??"")?$:G),N=y.startedAt?s-Date.parse(y.startedAt):0,g=v+h,f=v+j,A=h>1?` · ${h}/${k} parallel`:"";return{kind:"running",line1:`Running ${g}/${f}${A} · ${re(N)}`,line2:h===1?y.title:a.map($=>$.title).join(", "),tooltip:a.map($=>`${$.slug} (g${$.parallelGroup})`).join("; ")}}if(r){const y=r.resumeAt?Date.parse(r.resumeAt)-s:null;return{kind:"paused",line1:{rate_limit:"Paused — tokens exhausted",auth:"Paused — authentication failed",network:"Paused — network unreachable",reset_failure:"Paused — billing data unavailable",manual:"Paused — manual"}[r.reason]??`Paused — ${r.reason}`,line2:r.reason==="auth"?"Run `claude` in any terminal to refresh credentials, then Resume":y!==null&&y>0?`auto-resume ${z(Date.parse(r.resumeAt))} (in ${H(y)})`:r.resumeAt?"resuming…":"no auto-resume scheduled",tooltip:r.resumeAt??"",action:{label:"Resume",onClick:()=>window.api.schedule.resume(),title:"Clear the pause and resume queue immediately"}}}if(j===0)return{kind:"idle",line1:"No work queued",line2:null};const C=d.firePolicy??"when-available";if(C==="manual")return{kind:"manual",line1:`Manual · ${b} pending`,line2:"click Fire next batch now to fire",action:{label:"Fire next batch now",onClick:()=>window.api.schedule.forceTick().then(L.fromOutcome).catch(()=>L.error("Failed to fire batch")),title:"Bypasses the billing-usage poll. Use when the meter is rate-limited or you want immediate progress."}};if(C==="on-reset"){if(!u)return{kind:"on-reset",line1:"On-reset · waiting for billing data",line2:null};const y=Date.parse(u)+d.offsetMinutes*6e4,N=y-s;return{kind:"on-reset",line1:`On-reset · ${b} pending`,line2:N>0?`fires ${z(y)} (in ${H(N)})`:"firing now…"}}const w=d.utilizationThreshold??90;if(x==null)return{kind:"auto-soon",line1:`Auto · ${b} pending`,line2:"checking token availability…"};if(x>=w){const y=u?Date.parse(u)-s:null;return{kind:"auto-throttled",line1:`Auto · throttled (util ${x.toFixed(0)}% ≥ ${w}%)`,line2:y&&y>0?`next reset ${z(Date.parse(u))} (in ${H(y)})`:"will fire when usage drops"}}return{kind:"auto-soon",line1:`Auto · ${b} pending · util ${x.toFixed(0)}%`,line2:"fires within 2 min (poll cycle)"}}function kt(t){const s=t.filter(a=>a.status==="running"||a.status==="pending").sort((a,d)=>a.parallelGroup-d.parallelGroup||a.slug.localeCompare(d.slug)),n=new Map;return s.forEach((a,d)=>n.set(a.slug,d)),n}function St(t,s,n,a){if(a)return{inline:t,collapsedCount:0};const d=t.filter(c=>c.status==="completed").sort((c,b)=>{const v=c.finishedAt?Date.parse(c.finishedAt):0;return(b.finishedAt?Date.parse(b.finishedAt):0)-v}),o=new Set;let r=0;for(const c of d){if(r>=ut)break;s.has(c.slug)||c.finishedAt&&n-Date.parse(c.finishedAt)>xt||(o.add(c.slug),r++)}const u=[];let x=0;for(const c of t){if(c.status==="failed"&&s.has(c.slug)){x++;continue}if(c.status!=="completed"){u.push(c);continue}o.has(c.slug)?u.push(c):x++}return{inline:u,collapsedCount:x}}function Pt(t){return t==="running"?"bg-amber-400/10 border-amber-400/25":t==="paused"?"bg-amber-500/10 border-amber-500/25":t==="auto-throttled"?"bg-amber-500/5 border-amber-500/15":"bg-bg-elev border-line"}function $t(t){return t==="running"||t==="auto-soon"?"text-accent":t==="idle"?"text-sage":t==="paused"||t==="auto-throttled"?"text-butter":"text-fg-faint"}const Ct=["Running","Paused","Manual","On-reset","Auto"];function At(t){for(const s of Ct)if(t.startsWith(s))return e.jsxs(e.Fragment,{children:[e.jsx("strong",{className:"font-bold",children:s}),t.slice(s.length)]});return t}function Dt(t,s){return s==null||t.includes("util")?t:`${t} · util ${Math.round(s)}%`}function Rt(t,s,n,a,d,o){const r=new Map;if(d==="paused"||d==="manual"||d==="auto-throttled"){for(const c of t)r.set(c.slug,null);return r}const u=s.find(c=>c.status==="running"&&c.startedAt),x=u!=null&&u.startedAt?o-Date.parse(u.startedAt):0;for(const c of t){if(c.status!=="pending"){r.set(c.slug,null);continue}const b=n.get(c.slug)??0;let v=b*a;b>0&&(v-=Math.min(a,x)),r.set(c.slug,v<=5e3?"~now":`~${re(v)}`)}return r}function Et({job:t,eta:s,elapsedMs:n,avgDurationMs:a,listIndex:d,onFocused:o,hold:r}){const[u,x]=i.useState(!1),[c,b]=i.useState(!1),v=le(A=>A.sessions),h=i.useMemo(()=>we(t,v),[t,v]),j=h.known&&h.epicId?v[h.epicId]:null,k=i.useCallback(A=>{je(A),window.dispatchEvent(new CustomEvent("sm:navigate",{detail:"terminal"}))},[]),C=t.status==="running",w=t.status==="failed";let y=null;C&&n!==null?y=`${Se(n)} elapsed`:t.status==="completed"&&t.startedAt&&t.finishedAt?y=`took ${re(Date.parse(t.finishedAt)-Date.parse(t.startedAt))}`:s&&(y=s);const N=t.error??null,g=w&&N?N.split(`
|
|
4
|
-
`)[0]:t.status==="needs_review"&&t.verifierVerdict?ce(t.verifierVerdict):null,f=C&&n!==null?Math.min(.99,n/a):0;return e.jsxs("div",{role:"listitem",className:"border-t border-line",children:[e.jsxs("button",{type:"button","data-job-row":!0,"data-job-index":d,onClick:()=>x(A=>!A),onFocus:()=>o(d),className:`w-full text-left grid grid-cols-[116px_1fr_auto_auto] items-center gap-4 px-[18px] py-3.5 hover:bg-bg/40 focus:outline-none focus:ring-1 focus:ring-accent focus:ring-inset ${u?"bg-bg-elev/40":""}`,"aria-expanded":u,"aria-label":`${W(t.slug)?`PRD ${W(t.slug)}, `:""}${t.title}, ${t.status}${y?`, ${y}`:""}`,title:t.title,children:[e.jsx(Le,{status:t.status}),e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-baseline gap-2 text-[14.5px] font-medium text-fg leading-snug",children:[W(t.slug)&&e.jsx(Me,{n:W(t.slug)}),t.title,e.jsx(Oe,{leaked:t.leakedDescendants}),e.jsx(Ue,{count:t.leftoverCount,truncated:t.leftoverPathsTruncated,salvagePatch:t.salvagePatch})]}),g&&e.jsx("div",{className:`text-[12.5px] mt-0.5 ${w?"text-accent/80":"text-fg-faint"}`,children:g}),r&&e.jsx("div",{className:"text-[12.5px] mt-0.5 text-amber-400/90 font-mono","data-testid":"job-row-hold",children:r.dep?e.jsxs(e.Fragment,{children:["held · waiting on ",r.dep," (",r.depStatus,")"]}):e.jsxs(e.Fragment,{children:["held · ",r.reason??"launch blocked"]})}),!r&&t.status==="pending"&&t.heldReason&&e.jsxs("div",{className:"text-[12.5px] mt-0.5 text-amber-400/90 font-mono","data-testid":"job-row-held-reason",children:["held · ",t.heldReason]}),e.jsx(Ne,{epicId:h.epicId,label:h.label?pt(h.label):null,onOpen:k,testId:"job-row-prompt-session-chip",className:"mt-0.5"})]}),e.jsx(ye,{cwd:t.cwd}),e.jsxs("span",{className:"inline-flex items-center gap-2.5 font-mono text-xs text-fg-faint shrink-0",children:[e.jsx(Qe,{status:t.status,overrun:t.overrun}),y,e.jsx("span",{className:`text-fg-faint inline-flex transition-transform duration-150 ${u?"rotate-90":""}`,"aria-hidden":"true",children:e.jsx(ue,{name:"chevron",size:14})})]})]}),C&&!u&&e.jsx("div",{className:"h-1 bg-line mx-[18px] mb-3 rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full bg-accent transition-all duration-1000",style:{width:`${Math.max(4,f*100)}%`}})}),u&&e.jsxs("div",{className:"px-[18px] py-5 grid grid-cols-[repeat(auto-fit,minmax(160px,1fr))] gap-5 bg-bg-elev/50 border-t border-line",children:[e.jsxs(B,{label:"Status",children:[e.jsx(D,{k:"result",v:t.exitCode!==null?`exit ${t.exitCode}`:"—"}),e.jsx(D,{k:"state",v:t.status.replace(/_/g," ")}),t.verifierVerdict&&e.jsx(D,{k:"verdict",v:ce(t.verifierVerdict)}),t.leakedDescendants&&t.leakedDescendants.length>0&&e.jsx(D,{k:"leaked",v:Fe(t.leakedDescendants),wrap:!0}),t.leftoverCount!=null&&t.leftoverCount>0&&e.jsx(D,{k:"uncommitted",v:`${t.leftoverCount} file${t.leftoverCount===1?"":"s"}${t.leftoverPathsTruncated?"+":""}: ${(t.leftoverPaths??[]).join(", ")}${t.salvagePatch?` — salvaged to ${t.salvagePatch}`:""}`,wrap:!0}),N&&e.jsx(D,{k:"error",v:N.split(`
|
|
5
|
-
`)[0],wrap:!0})]}),t.statusHistory&&t.statusHistory.length>0&&e.jsx(B,{label:"History",children:e.jsx("div",{className:"grid gap-1",children:t.statusHistory.map((A,$)=>e.jsxs("div",{className:"font-mono text-xs leading-relaxed",children:[e.jsxs("div",{className:"text-fg",children:[A.from??"(new)"," → ",A.to,e.jsxs("span",{className:"text-fg-faint",children:[" · ",z(Date.parse(A.at))]})]}),A.reason&&e.jsx("div",{className:"text-fg-faint break-words",children:A.reason})]},$))})}),e.jsxs(B,{label:"Timing",children:[e.jsx(D,{k:"started",v:t.startedAt?z(Date.parse(t.startedAt)):"—"}),e.jsx(D,{k:"finished",v:t.finishedAt?z(Date.parse(t.finishedAt)):"—"}),e.jsx(D,{k:"duration",v:t.startedAt&&t.finishedAt?re(Date.parse(t.finishedAt)-Date.parse(t.startedAt)):C&&n!==null?Se(n):"—"})]}),e.jsxs(B,{label:"Location",children:[e.jsx(D,{k:"group",v:`${t.parallelGroup} · ${t.slug}`}),e.jsx(D,{k:"cwd",v:t.cwd??"—",wrap:!0}),e.jsx(D,{k:"session",v:h.label??h.epicId??"—",wrap:!0}),e.jsx(D,{k:"session id",v:h.epicId??"—",wrap:!0}),e.jsx(D,{k:"prompt id",v:t.sourcePromptId??"—",wrap:!0}),e.jsx(D,{k:"source tab",v:t.sourceTabId??"—",wrap:!0})]}),e.jsx(B,{label:"Actions",children:e.jsxs("div",{className:"flex flex-col gap-1.5 items-start",children:[j&&e.jsx("button",{type:"button","data-testid":"job-row-prompt-session-link",title:j.goalText,onClick:()=>k(j.id),className:"text-[13px] font-semibold text-accent hover:text-accent/80 bg-transparent border-0 cursor-pointer p-0",children:"view epic →"}),t.runId&&e.jsx("button",{type:"button",onClick:()=>b(!0),className:"text-[13px] font-semibold text-fg-dim hover:text-fg bg-transparent border-0 cursor-pointer p-0",children:"view log →"}),t.status==="quarantined"&&e.jsx("button",{type:"button","data-testid":"job-row-adopt-prd",title:"Stamp this PRD's provenance so the scheduler will run it — no unstamped PRD runs automatically.",onClick:()=>{window.api.schedule.adoptPrd(t.slug).then(L.fromOutcome).catch(()=>L.error("Failed to adopt PRD"))},className:"text-[13px] font-semibold text-accent hover:text-accent/80 bg-transparent border-0 cursor-pointer p-0",children:"adopt PRD →"}),t.status!=="pending"&&t.status!=="running"&&t.status!=="quarantined"&&e.jsx("button",{type:"button",onClick:()=>window.api.schedule.resetJob(t.slug),className:"text-[13px] font-semibold text-fg-dim hover:text-fg bg-transparent border-0 cursor-pointer p-0",children:"reset to pending →"})]})})]}),c&&t.runId&&e.jsx(_e,{runId:t.runId,slug:t.slug,title:t.title||t.slug,onClose:()=>b(!1)})]})}const It=i.memo(Et);function Tt({filter:t,onChange:s}){const n=[{label:"All",value:"all"},{label:"Running",value:"running"},{label:"Investigating",value:"investigating"},{label:"Pending",value:"pending"},{label:"Completed",value:"completed"},{label:"Skipped",value:"skipped"},{label:"Needs review",value:"needs_review"},{label:"Failed",value:"failed"},{label:"Quarantined",value:"quarantined"}];return e.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[e.jsxs("div",{className:"relative flex-1 min-w-[200px] max-w-[320px]",children:[e.jsx("span",{className:"absolute left-2.5 top-1/2 -translate-y-1/2 text-fg-faint inline-flex","aria-hidden":"true",children:e.jsx(ue,{name:"search",size:15})}),e.jsx("input",{type:"text",value:t.text,onChange:a=>s({...t,text:a.target.value}),placeholder:"filter jobs…",className:"w-full bg-bg-hi border border-line rounded-xl py-2 pl-9 pr-3 text-[13.5px] text-fg placeholder:text-fg-faint focus:outline-none focus:border-fg-faint","aria-label":"Filter jobs by title, slug, or project"})]}),e.jsx(qe,{options:n,value:t.status,onChange:a=>s({...t,status:a})})]})}function Lt({supervisorConfig:t,onSetConfig:s,onBack:n}){const[a,d]=i.useState([]),[o,r]=i.useState(()=>Date.now()),u=Te();i.useEffect(()=>{if(!u)return;window.api.supervisor.getLog().then(d).catch(()=>{}),r(Date.now());const c=setInterval(()=>r(Date.now()),5e3);return()=>clearInterval(c)},[u]);const x={enabled:(t==null?void 0:t.enabled)??!0,intervalMinutes:(t==null?void 0:t.intervalMinutes)??15,maxConcurrentProbes:(t==null?void 0:t.maxConcurrentProbes)??2,probeStaleThresholdMinutes:(t==null?void 0:t.probeStaleThresholdMinutes)??10};return e.jsxs("div",{className:"bg-bg-elev/60",children:[e.jsxs("div",{className:"px-3 py-2 flex items-center gap-2 border-b border-line",children:[e.jsx("button",{type:"button",onClick:n,className:"text-[10px] text-fg-faint hover:text-fg-dim",title:"Back to queue",children:"← queue"}),e.jsx("span",{className:"text-[11px] font-medium text-fg-dim",children:"Supervisor"}),e.jsx("button",{type:"button",onClick:()=>window.api.supervisor.getLog().then(d).catch(()=>{}),className:"ml-auto text-[10px] text-fg-faint hover:text-fg-dim underline",title:"Refresh log",children:"refresh"})]}),e.jsxs("div",{className:"px-3 py-2 space-y-1.5 border-b border-line",children:[e.jsx("div",{className:"text-[9px] text-fg-faint uppercase tracking-wider",children:"Config"}),e.jsxs("div",{className:"flex items-center gap-3 flex-wrap text-[10px] text-fg-faint",children:[e.jsxs("label",{className:"flex items-center gap-1",children:[e.jsx("input",{type:"checkbox",checked:x.enabled,onChange:c=>s({enabled:c.target.checked}),className:"cursor-pointer"}),e.jsx("span",{children:"enabled"})]}),e.jsxs("label",{className:"flex items-center gap-1",title:"How often to check for wedged jobs (minutes)",children:[e.jsx("span",{children:"interval"}),e.jsx("input",{type:"number",min:5,max:60,value:x.intervalMinutes,onChange:c=>s({intervalMinutes:Number(c.target.value)}),className:"w-10 bg-bg border border-line rounded px-1 py-0.5 font-mono"}),e.jsx("span",{children:"min"})]}),e.jsxs("label",{className:"flex items-center gap-1",title:"Max concurrent Opus probes per tick",children:[e.jsx("span",{children:"probes"}),e.jsx("input",{type:"number",min:1,max:5,value:x.maxConcurrentProbes,onChange:c=>s({maxConcurrentProbes:Number(c.target.value)}),className:"w-8 bg-bg border border-line rounded px-1 py-0.5 font-mono"})]}),e.jsxs("label",{className:"flex items-center gap-1",title:"Probe a job only if no JSONL event in this many minutes",children:[e.jsx("span",{children:"stale"}),e.jsx("input",{type:"number",min:5,max:30,value:x.probeStaleThresholdMinutes,onChange:c=>s({probeStaleThresholdMinutes:Number(c.target.value)}),className:"w-8 bg-bg border border-line rounded px-1 py-0.5 font-mono"}),e.jsx("span",{children:"min"})]})]})]}),e.jsxs("div",{className:"px-3 py-2",children:[e.jsxs("div",{className:"text-[9px] text-fg-faint uppercase tracking-wider mb-1",children:["Recent probes (last ",a.length,")"]}),a.length===0?e.jsx("div",{className:"text-[10px] text-fg-faint italic",children:"No probes yet."}):e.jsx("div",{className:"space-y-0.5 max-h-64 overflow-y-auto",children:a.map((c,b)=>e.jsx(Mt,{entry:c,now:o},`${c.ts}-${b}`))})]})]})}function Mt({entry:t,now:s}){const n=t.action!=="none",a=H(s-t.ts);return e.jsxs("div",{className:`text-[10px] px-1.5 py-1 rounded font-mono ${n?"bg-red-500/10 border border-red-500/20":"bg-bg/40"}`,title:t.reason,children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsxs("span",{className:"text-fg-faint shrink-0",children:[a," ago"]}),e.jsx("span",{className:`shrink-0 px-1 rounded ${t.verdict==="stuck"?"text-red-400 bg-red-500/10":"text-green-500/70"}`,children:t.verdict}),e.jsx("span",{className:"truncate text-fg-dim",children:t.jobSlug}),n&&e.jsxs("span",{className:"shrink-0 text-red-400",children:[t.action,t.targetPid?` pid=${t.targetPid}`:""]}),t.costUsd!==null&&e.jsxs("span",{className:"shrink-0 text-fg-faint",children:["$",t.costUsd.toFixed(3)]})]}),e.jsx("div",{className:"text-fg-faint truncate mt-0.5",children:t.reason})]})}function Ot({snap:t,health:s,now:n,open:a,setOpen:d}){const[o,r]=i.useState(null),[u,x]=i.useState(!1),c=`${t.jobs.length}:${t.lastRunAt??""}`;i.useEffect(()=>{let g=!0;return x(!0),De().then(f=>{g&&r(f)}).catch(()=>{}).finally(()=>{g&&x(!1)}),()=>{g=!1}},[c]);let b=0,v=0;const h=o?o.reports.filter(g=>g.findings.length>0):[];for(const g of h)for(const f of g.findings)f.severity==="error"?b++:v++;const j=b===0&&v===0,k=o?j?`queue lint clear (${o.reports.length} scanned)`:`queue lint ${b} error${b===1?"":"s"}${v>0?`, ${v} warn${v===1?"":"s"}`:""}`:u?"scanning…":"idle",C=(s==null?void 0:s.consecutiveFailures)??0,w=s?`${C} poll failure${C===1?"":"s"} since boot`:null,y=C>0||((s==null?void 0:s.pauseReason)??null)!==null||!j,N=[w,k].filter(Boolean);return e.jsxs("div",{className:"flex flex-col gap-2 bg-bg-hi border border-line rounded-xl px-4 py-3 text-[13.5px] text-fg-dim",children:[e.jsxs("button",{type:"button",onClick:()=>d(!a),className:"flex items-center gap-2.5 w-full text-left","aria-expanded":a,title:"Scheduler poll health and queue-lint findings, in one place",children:[e.jsx("span",{className:`w-2 h-2 rounded-full shrink-0 ${y?"bg-butter":"bg-sage"}`,"aria-hidden":"true"}),e.jsx("strong",{className:"text-fg font-semibold shrink-0",children:"Diagnostics"}),e.jsx("span",{className:"truncate",children:N.join(" · ")}),e.jsx("span",{className:"ml-auto text-fg-faint shrink-0","aria-hidden":"true",children:a?"▾":"▸"})]}),a&&e.jsxs("div",{className:"pl-[18px] space-y-3 font-mono text-[12px]",children:[s&&e.jsxs("div",{className:"space-y-0.5",children:[e.jsxs("div",{children:["booted: ",U(s.bootedAt,n)]}),e.jsxs("div",{children:["last poll: ",U(s.lastPollAt,n)," · ",s.lastPollOk?"ok":"failed"]}),s.backoffNextAt!==null&&s.backoffNextAt>n&&e.jsxs("div",{children:["retry in: ",H(s.backoffNextAt-n)]}),s.nextResetCached&&e.jsxs("div",{children:["cached reset: ",z(Date.parse(s.nextResetCached))]}),s.runningJobs.length>0&&e.jsxs("div",{children:["running: ",s.runningJobs.map(g=>`${g.slug}(pid ${g.pid})`).join(", ")]})]}),o&&e.jsxs("div",{className:"space-y-1",children:[j?e.jsxs("div",{className:"text-sage",children:["✓ no issues in ",o.reports.length," PRD",o.reports.length!==1?"s":""]}):h.map(g=>e.jsxs("div",{children:[e.jsx("div",{className:"text-fg-dim truncate",title:g.slug,children:g.slug}),g.findings.map((f,A)=>e.jsxs("div",{className:`pl-3 truncate ${f.severity==="error"?"text-accent/80":"text-butter/90"}`,title:f.snippet,children:[f.severity==="error"?"✗":"⚠"," L",f.line,": ",f.snippet]},`${g.slug}-${A}`))]},g.slug)),e.jsx("button",{type:"button",onClick:()=>{x(!0),De({fresh:!0}).then(r).catch(()=>{}).finally(()=>x(!1))},className:"text-fg-faint hover:text-fg-dim underline",children:u?"…":"rerun lint"})]})]})]})}new Set(Ye.map(t=>t.tag).filter(t=>t!=="discussion"));const Ft=["title","cwd","estimateMinutes","parallelGroup","sourcePromptId","sourceTabId","tag","agentType","dependsOn"];function _t(t,s){return!Array.isArray(t)||!Array.isArray(s)?!1:t.length===s.length&&t.every((n,a)=>n===s[a])}function Ht(t){if(t==null)return"";if(typeof t=="boolean"||typeof t=="number")return String(t);const s=String(t);return s===""||/^(true|false|null|~)$/.test(s)||/^-?\d+(\.\d+)?$/.test(s)||/^\s|\s$/.test(s)||s.startsWith("'")||s.startsWith('"')||s.includes(`
|
|
6
|
-
`)?s.includes("'")?`"${s.replace(/"/g,'\\"')}"`:`'${s}'`:s}function qt(t,s){var d;const n=[];for(const o of Ft){const r=t[o];if(r==null||r===""||Array.isArray(r)&&r.length===0)continue;const u=(d=t._raw)==null?void 0:d[o];if(u&&(Array.isArray(r)?_t(u.parsed,r):u.parsed===r)){n.push(u.line);continue}if(typeof r=="number"){n.push(`${o}: ${r}`);continue}if(Array.isArray(r)){n.push(`${o}: [${r.join(", ")}]`);continue}n.push(`${o}: ${Ht(r)}`)}if(t.extras)for(const o of Object.keys(t.extras)){const r=t.extras[o];!r||!r.lines.length||n.push(r.lines.join(`
|
|
7
|
-
`))}return`---
|
|
8
|
-
${n.join(`
|
|
9
|
-
`)}
|
|
10
|
-
---
|
|
11
|
-
${s}`}function fe(t){return t.filter(s=>!s.archived)}function Bt(t){je(t),window.dispatchEvent(new CustomEvent("sm:navigate",{detail:"terminal"}))}function ge({label:t,tip:s,onClick:n,disabled:a,primary:d}){return e.jsx(Xe,{content:s,align:"bottom-center",children:e.jsx("button",{title:s,onClick:n,disabled:a,className:`px-2 py-0.5 text-xs rounded border disabled:opacity-40 disabled:cursor-not-allowed ${d?"text-accent border-accent/50 hover:bg-bg-hi":"text-fg-dim border-line hover:text-fg hover:bg-bg-hi"}`,children:t})})}function Gt({scopeCwd:t=null}){const[s,n]=i.useState([]),[a,d]=i.useState(null),[o,r]=i.useState(null),[u,x]=i.useState(null),[c,b]=i.useState(!1),[v,h]=i.useState(!0),[j,k]=i.useState(new Set),[C,w]=i.useState(!1),[y,N]=i.useState(!1),[g,f]=i.useState(!1),[A,$]=i.useState(null);i.useEffect(()=>{let l=!0;return window.api.schedule.listPrds().then(m=>{l&&(n(fe(m)),h(!1))}).catch(m=>{l&&(h(!1),L.error(`Scheduler: failed to load PRD list — ${m instanceof Error?m.message:"unknown error"}`))}),()=>{l=!1}},[]);const G=ve(l=>l.snapshot),xe=le(l=>l.sessions);i.useEffect(()=>{G&&d(G)},[G]);const J=i.useMemo(()=>[...s].filter(l=>!t||l.cwd===t).sort((l,m)=>m.mtimeMs-l.mtimeMs||l.slug.localeCompare(m.slug)),[s,t]);i.useEffect(()=>{const l=Ke();l&&r(l);const m=P=>r(P.detail);return window.addEventListener("sm:select-prd",m),()=>window.removeEventListener("sm:select-prd",m)},[]);const M=i.useMemo(()=>(a==null?void 0:a.jobs.find(l=>l.slug===o))??null,[a,o]),K=Pe(M);function X(l){var P;const m=(P=s.find(I=>I.slug===l))==null?void 0:P.cwd;return m?`${m}/session-manager-operations/scheduler/prds/${l}.md`:null}i.useEffect(()=>{if(!o)return;const l=X(o);l&&$e.getState().openFile(l)},[o,s]);function Z(l){r(l),x(null),b(!1)}function pe(){r(null)}async function ee(){if(!o)return;if(!(M!=null&&M.runId)){x("no log available (job has not run yet)"),b(m=>!m);return}const l=await window.api.schedule.readLog(M.runId,o);x(l.ok?l.text??"":`error: ${l.error}`),b(m=>!m)}if(v)return e.jsx(ae,{title:"loading PRDs…"});const O=l=>{k(m=>{const P=new Set(m);return P.has(l)?P.delete(l):P.add(l),P})};!(J.length>0&&J.every(l=>j.has(l.slug)))&&J.some(l=>j.has(l.slug));const q=()=>k(new Set);async function Q(){try{const l=await window.api.schedule.listPrds();n(fe(l))}catch{}}async function R(){const l=`new-prd-${Date.now()}`,m=qt({title:"New PRD",cwd:"",estimateMinutes:60,parallelGroup:99},`## Task
|
|
12
|
-
|
|
13
|
-
Describe the task here.
|
|
14
|
-
`);try{const P=await window.api.schedule.writePrd(l,m);if(!P.ok){L.error(`Failed to create PRD: ${P.error}`);return}const I=await window.api.schedule.listPrds();n(fe(I)),Z(l)}catch(P){L.error(`Failed to create PRD: ${P instanceof Error?P.message:String(P)}`)}}async function F(){var l;f(!0),$(null);try{const m=[...j],P=await window.api.schedule.archivePrds(m);if(!P.ok)$(P.error??"archive failed");else{const I=((l=P.results)==null?void 0:l.filter(E=>!E.ok))??[];I.length>0&&L.warn(`Archive: ${I.length} of ${P.results.length} PRD${I.length===1?"":"s"} failed to move`),q(),w(!1),await Q()}}catch(m){$(m instanceof Error?m.message:String(m))}finally{f(!1)}}async function te(l,m){f(!0),$(null);try{const P=[];for(const E of j){const _={slug:E};l!==null&&(_.parallelGroup=l),m!==null&&(_.estimateMinutes=m),P.push(_)}const I=await window.api.schedule.retagPrds(P);if(!I.ok)$(I.error??"retag failed");else{q(),N(!1),await Q();for(const E of I.results)if(E.newSlug&&E.newSlug!==E.slug){const _=X(E.slug),Y=X(E.newSlug);_&&Y&&$e.getState().renameOpenFile(_,Y)}o&&I.results.some(E=>E.slug===o&&E.newSlug&&E.newSlug!==E.slug)&&r(null)}}catch(P){$(P instanceof Error?P.message:String(P))}finally{f(!1)}}return e.jsxs(e.Fragment,{children:[o?e.jsxs("div",{className:"h-full flex flex-col min-h-0",children:[e.jsxs("div",{className:"flex items-center gap-2 px-3 py-2 border-b border-line flex-wrap shrink-0",children:[e.jsx("button",{type:"button",onClick:pe,className:"text-[11px] text-fg-faint hover:text-fg",children:"← PRDs"}),e.jsx("span",{className:"font-mono text-xs text-fg-dim truncate",children:o}),e.jsx(Ce,{status:K}),e.jsx("div",{className:"flex-1"}),e.jsx(ge,{label:"Reset",tip:"Reset failed job to pending",onClick:()=>{window.api.schedule.resetJob(o)},disabled:K!=="failed"}),e.jsx(ge,{label:"Run now",tip:"Run all pending jobs immediately",onClick:()=>{window.api.schedule.runNow()}}),e.jsx(ge,{label:c?"Hide log":"Last run log",tip:"Toggle most recent run log",onClick:ee})]}),e.jsx("div",{className:"flex-1 min-h-0",children:e.jsx(We,{})}),c&&u!==null&&e.jsxs("div",{className:"border-t border-line max-h-64 overflow-auto bg-bg-elev",children:[e.jsxs("div",{className:"px-3 py-1.5 flex items-center gap-2 border-b border-line sticky top-0 bg-bg-elev",children:[e.jsxs("span",{className:"text-[10px] text-fg-faint font-mono",children:["run log",M!=null&&M.runId?` — ${M.runId}`:""]}),e.jsx("button",{onClick:()=>b(!1),className:"ml-auto text-[10px] text-fg-faint hover:text-fg",children:"close"})]}),e.jsx("pre",{className:"p-3 text-[11px] font-mono text-fg-dim whitespace-pre-wrap",children:u})]})]}):e.jsxs("div",{className:"px-6 py-5 overflow-auto",children:[e.jsxs("div",{className:"flex items-start justify-between mb-5 gap-4",children:[e.jsxs("p",{className:"text-[14px] text-fg-dim leading-relaxed max-w-[560px]",children:["PRDs are the source the scheduler runs from. Each one becomes a"," ",e.jsx("code",{className:"font-mono text-[13px]",children:"claude -p"})," job when you queue it. This is where you write and edit the source — to watch a run in progress, use the Queue tab."]}),e.jsx("button",{type:"button",onClick:R,className:"shrink-0 bg-accent text-white rounded-lg px-4 py-[9px] text-[13.5px] font-semibold leading-none",children:"+ New PRD"})]}),j.size>0&&e.jsxs("div",{className:"mb-4 px-4 py-2 bg-bg border border-line rounded-lg flex items-center gap-2",children:[e.jsxs("span",{className:"text-xs text-fg-dim",children:[j.size," selected"]}),e.jsx("div",{className:"flex-1"}),e.jsx("button",{type:"button",onClick:()=>w(!0),className:"text-xs px-3 py-1.5 rounded border border-line text-fg-dim hover:text-fg hover:bg-bg-hi",children:"Archive…"}),e.jsx("button",{type:"button",onClick:()=>N(!0),className:"text-xs px-3 py-1.5 rounded border border-line text-fg-dim hover:text-fg hover:bg-bg-hi",children:"Retag…"}),e.jsx("button",{type:"button",onClick:q,className:"text-xs px-3 py-1.5 rounded border border-line text-fg-dim hover:text-fg hover:bg-bg-hi",children:"Clear"})]}),J.length===0?e.jsx(ae,{title:"no PRDs found"}):e.jsx("div",{className:"grid gap-3",children:J.map(l=>{const m=a==null?void 0:a.jobs.find(Y=>Y.slug===l.slug),P=Pe(m),I=we({epicId:l.epicId??(m==null?void 0:m.epicId)??null,sourcePromptId:l.sourcePromptId??(m==null?void 0:m.sourcePromptId)??null,sourceTabId:(m==null?void 0:m.sourceTabId)??null},xe),E=(m==null?void 0:m.status)==="running",_=(m==null?void 0:m.status)==="needs_review";return e.jsxs("div",{className:"flex items-stretch bg-bg-elev border border-line rounded-2xl overflow-hidden",children:[e.jsx("label",{className:"flex items-center px-3 cursor-pointer hover:bg-bg-hi",children:e.jsx("input",{type:"checkbox",checked:j.has(l.slug),onChange:()=>O(l.slug),className:"accent-accent w-3.5 h-3.5"})}),e.jsxs("div",{className:"flex-1 min-w-0 py-4 pr-2",children:[e.jsxs("div",{className:"flex items-center gap-2.5 mb-[5px] flex-wrap",children:[W(l.slug)&&e.jsx(Me,{n:W(l.slug)}),e.jsx("button",{type:"button",onClick:()=>Z(l.slug),className:"font-serif text-[18px] font-semibold text-fg leading-tight hover:underline text-left",children:l.title||l.slug}),e.jsx(Ce,{status:P}),(m==null?void 0:m.status)&&e.jsx("span",{className:"sr-only",children:m.status})]}),e.jsxs("div",{className:"flex items-center gap-4 font-mono text-xs text-fg-faint flex-wrap",children:[e.jsx(ye,{cwd:l.cwd}),e.jsx(Ne,{epicId:I.epicId,label:I.label,onOpen:Bt}),l.estimateMinutes!=null&&e.jsxs("span",{children:[l.estimateMinutes,"m"]}),e.jsxs("span",{children:["g",l.parallelGroup]}),e.jsxs("span",{children:["edited ",U(l.mtimeMs,Date.now())]})]}),e.jsx("button",{type:"button",onClick:()=>Z(l.slug),className:"mt-1.5 font-mono text-[11px] text-fg-faint hover:text-fg-dim leading-none",children:l.slug}),_&&e.jsxs("div",{className:"mt-3 space-y-2",children:[(m==null?void 0:m.verifierVerdict)&&e.jsxs("div",{className:"text-xs text-fg-faint",children:["verdict: ",e.jsx("span",{className:"font-mono",children:ce(m.verifierVerdict)})]}),e.jsx("button",{type:"button",onClick:()=>window.api.schedule.resetJob(l.slug),className:"text-xs px-2.5 py-1 rounded border border-line text-fg-dim hover:text-fg hover:bg-bg-hi",children:"Re-fire"})]})]}),e.jsx("div",{className:"flex flex-col gap-2 items-stretch px-[18px] py-4",children:e.jsx("button",{type:"button",onClick:()=>window.api.schedule.runNow(),disabled:E,className:"bg-fg text-bg rounded-lg px-[18px] py-2 text-[13px] font-semibold whitespace-nowrap disabled:opacity-50",children:E?"Running…":"Queue job"})})]},l.slug)})})]}),e.jsx(Jt,{open:C,count:j.size,busy:g,onClose:()=>w(!1),onConfirm:F}),e.jsx(Vt,{open:y,count:j.size,busy:g,onClose:()=>N(!1),onConfirm:te})]})}function Jt({open:t,count:s,busy:n,onClose:a,onConfirm:d}){return e.jsxs(He,{open:t,onClose:a,title:"Archive PRDs",children:[e.jsxs("p",{className:"text-xs text-fg-dim",children:["Move ",e.jsx("span",{className:"font-mono",children:s})," PRD",s===1?"":"s"," to"," ",e.jsx("span",{className:"font-mono",children:"prds-archived/<timestamp>/"}),"?"]}),e.jsx("p",{className:"text-[10px] text-fg-faint mt-2",children:"Files are renamed, never deleted. Restore manually from disk if needed."}),e.jsxs("div",{className:"flex justify-end gap-2 mt-4",children:[e.jsx("button",{type:"button",onClick:a,disabled:n,className:"px-2 py-1 text-xs border border-line rounded text-fg-dim hover:text-fg disabled:opacity-40",children:"Cancel"}),e.jsx("button",{type:"button",onClick:d,disabled:n||s===0,className:"px-2 py-1 text-xs border border-accent/60 text-accent rounded hover:bg-bg-hi disabled:opacity-40",children:n?"Archiving…":`Archive ${s}`})]})]})}function Vt({open:t,count:s,busy:n,onClose:a,onConfirm:d}){const[o,r]=i.useState(""),[u,x]=i.useState(""),[c,b]=i.useState(null);i.useEffect(()=>{t&&(r(""),x(""),b(null))},[t]);function v(){b(null);let h=null,j=null;if(o.trim()){const k=Number(o);if(!Number.isInteger(k)||k<0||k>999){b("parallelGroup must be 0–999");return}h=k}if(u.trim()){const k=Number(u);if(!Number.isInteger(k)||k<=0){b("estimateMinutes must be a positive integer");return}j=k}if(h===null&&j===null){b("set at least one field");return}d(h,j)}return e.jsxs(He,{open:t,onClose:a,title:"Retag PRDs",children:[e.jsxs("p",{className:"text-xs text-fg-dim",children:["Update ",e.jsx("span",{className:"font-mono",children:s})," PRD",s===1?"":"s",". Leave a field blank to keep its current value."]}),e.jsxs("p",{className:"text-[10px] text-fg-faint mt-2",children:["Changing parallelGroup on an ",e.jsx("span",{className:"font-mono",children:"NN-kebab"})," slug renames the file. Every change is logged to ",e.jsx("span",{className:"font-mono",children:"retag-log.jsonl"})," so it's reversible."]}),e.jsxs("div",{className:"mt-3 space-y-2",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs",children:[e.jsx("span",{className:"w-32 text-fg-faint",children:"parallelGroup:"}),e.jsx("input",{type:"number",min:0,max:999,value:o,onChange:h=>r(h.target.value),placeholder:"(unchanged)",className:"flex-1 bg-bg border border-line rounded px-2 py-1 font-mono text-xs"})]}),e.jsxs("label",{className:"flex items-center gap-2 text-xs",children:[e.jsx("span",{className:"w-32 text-fg-faint",children:"estimateMinutes:"}),e.jsx("input",{type:"number",min:1,value:u,onChange:h=>x(h.target.value),placeholder:"(unchanged)",className:"flex-1 bg-bg border border-line rounded px-2 py-1 font-mono text-xs"})]})]}),c&&e.jsx("div",{className:"mt-2 text-[10px] text-red-300",children:c}),e.jsxs("div",{className:"flex justify-end gap-2 mt-4",children:[e.jsx("button",{type:"button",onClick:a,disabled:n,className:"px-2 py-1 text-xs border border-line rounded text-fg-dim hover:text-fg disabled:opacity-40",children:"Cancel"}),e.jsx("button",{type:"button",onClick:v,disabled:n||s===0,className:"px-2 py-1 text-xs border border-accent/60 text-accent rounded hover:bg-bg-hi disabled:opacity-40",children:n?"Retagging…":`Retag ${s}`})]})]})}function zt(t){je(t),window.dispatchEvent(new CustomEvent("sm:navigate",{detail:"terminal"}))}function Ee(t){return t?t.slice(0,10):""}const Ut=[{value:"all",label:"All"},{value:"completed",label:"Completed"},{value:"skipped",label:"Skipped"},{value:"failed",label:"Failed"}];function Qt({scopeCwd:t=null}){const[s,n]=i.useState(null),[a,d]=i.useState(!0),[o,r]=i.useState(""),[u,x]=i.useState(""),[c,b]=i.useState(""),[v,h]=i.useState("all");i.useEffect(()=>{d(!0),window.api.schedule.getHistory().then(w=>n(w)).catch(w=>n({ok:!1,jobs:[],error:w instanceof Error?w.message:String(w)})).finally(()=>d(!1))},[]);const j=i.useMemo(()=>{if(!(s!=null&&s.jobs))return[];const w=new Set;for(const y of s.jobs){const N=be(y.cwd);N&&w.add(N)}return[...w].sort()},[s]),k=i.useMemo(()=>s!=null&&s.jobs?s.jobs.filter(w=>!(t&&w.cwd!==t||v!=="all"&&w.status!==v||o&&be(w.cwd)!==o||u&&Ee(w.finishedAt)<u||c&&Ee(w.finishedAt)>c)):[],[s,v,o,u,c,t]);if(a)return e.jsx(ae,{title:"Loading history…"});if(!(s!=null&&s.ok)||s.error)return e.jsxs("div",{className:"p-4 text-xs text-red-300",children:["Failed to load history: ",(s==null?void 0:s.error)??"unknown error"]});if(s.jobs.length===0)return e.jsx(ae,{title:"No history yet",hint:"Completed and failed jobs appear here."});const C=v!=="all"||!!o||!!u||!!c;return e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"shrink-0 flex items-center gap-2 px-4 py-2.5 border-b border-line flex-wrap",children:[e.jsx(qe,{options:Ut,value:v,onChange:h,pillPadding:"px-3 py-1"}),e.jsx("span",{className:"w-px h-4 bg-line mx-1","aria-hidden":"true"}),j.length>0&&e.jsxs("select",{value:o,onChange:w=>r(w.target.value),className:"bg-bg-hi border border-line rounded-lg px-2 py-1 text-[12.5px] text-fg-dim max-w-[12rem] font-medium",children:[e.jsx("option",{value:"",children:"All projects"}),j.map(w=>e.jsx("option",{value:w,children:w},w))]}),e.jsxs("div",{className:"flex items-center gap-1.5 text-[12px] text-fg-faint",children:[e.jsx("span",{children:"from"}),e.jsx("input",{type:"date",value:u,onChange:w=>x(w.target.value),className:"bg-bg-hi border border-line rounded-lg px-2 py-1 text-fg-dim font-mono text-[12px]"})]}),e.jsxs("div",{className:"flex items-center gap-1.5 text-[12px] text-fg-faint",children:[e.jsx("span",{children:"to"}),e.jsx("input",{type:"date",value:c,onChange:w=>b(w.target.value),className:"bg-bg-hi border border-line rounded-lg px-2 py-1 text-fg-dim font-mono text-[12px]"})]}),e.jsxs("span",{className:"text-[12px] text-fg-faint ml-auto font-mono",children:[k.length," / ",s.jobs.length]}),C&&e.jsx("button",{type:"button",onClick:()=>{h("all"),r(""),x(""),b("")},className:"text-[12px] text-fg-faint hover:text-fg-dim underline",children:"clear"})]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto",children:k.length===0?e.jsx(ae,{title:"No matches",hint:"Try adjusting the filters."}):e.jsxs("div",{className:"mx-4 my-3 bg-bg-hi border border-line rounded-2xl overflow-hidden",children:[e.jsx("div",{className:"flex items-center px-[18px] py-3 bg-bg-elev",children:e.jsxs("span",{className:"font-serif text-base font-semibold text-fg",children:[k.length," job",k.length!==1?"s":""]})}),k.map(w=>e.jsx(Yt,{job:w},`${w.slug}-${w.finishedAt??""}`))]})})]})}function Yt({job:t}){const[s,n]=i.useState(!1),[a,d]=i.useState(!1),o=le(h=>h.sessions),r=i.useMemo(()=>we(t,o),[t,o]),u=t.startedAt&&t.finishedAt?Date.parse(t.finishedAt)-Date.parse(t.startedAt):null,x=t.startedAt?new Date(t.startedAt).toLocaleString():"—",c=t.finishedAt?new Date(t.finishedAt).toLocaleString():"—",b=u!==null?re(u):"—",v=t.exitCode!==null?String(t.exitCode):"—";return e.jsxs("div",{className:"border-t border-line/60",children:[e.jsxs("button",{type:"button",className:`w-full text-left grid items-center gap-4 px-[18px] py-3.5 cursor-pointer transition-colors hover:bg-bg-elev ${s?"bg-bg-elev":"bg-transparent"}`,style:{gridTemplateColumns:"116px 1fr auto auto"},onClick:()=>n(h=>!h),"aria-expanded":s,children:[e.jsx(Le,{status:t.status}),e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-baseline gap-2 text-[14.5px] font-medium text-fg leading-snug text-pretty",children:[t.title,e.jsx(Oe,{leaked:t.leakedDescendants})]}),t.error&&!s&&(t.status==="failed"||t.status==="needs_review")&&e.jsx("div",{className:"text-[12.5px] mt-0.5 text-accent/80 truncate",children:t.error}),r.epicId&&e.jsx("span",{className:"flex mt-0.5",children:e.jsx(Ne,{epicId:r.epicId,label:r.label,onOpen:zt})})]}),e.jsx(ye,{cwd:t.cwd}),e.jsxs("span",{className:"inline-flex items-center gap-2.5 font-mono text-xs text-fg-faint whitespace-nowrap",children:[b,e.jsx("span",{className:"inline-flex transition-transform duration-150",style:{transform:s?"rotate(90deg)":"none"},"aria-hidden":"true",children:"›"})]})]}),s&&e.jsxs("div",{className:"grid gap-5 px-[18px] pt-1 pb-5 bg-bg-elev",style:{gridTemplateColumns:"repeat(auto-fit, minmax(160px, 1fr))"},children:[e.jsxs(B,{label:"Status",children:[e.jsx(D,{k:"result",v}),e.jsx(D,{k:"state",v:t.status.replace("_"," ")}),t.verifierVerdict&&e.jsx(D,{k:"verifier",v:ce(t.verifierVerdict)}),t.leakedDescendants&&t.leakedDescendants.length>0&&e.jsx(D,{k:"leaked",v:Fe(t.leakedDescendants),wrap:!0})]}),e.jsxs(B,{label:"Timing",children:[e.jsx(D,{k:"started",v:x}),e.jsx(D,{k:"finished",v:c}),e.jsx(D,{k:"duration",v:b})]}),e.jsxs(B,{label:"Location",children:[e.jsx(D,{k:"group",v:t.parallelGroup!=null?String(t.parallelGroup):"—"}),e.jsx(D,{k:"slug",v:t.slug}),e.jsx(D,{k:"epic",v:r.label??r.epicId??"—",wrap:!0}),t.cwd&&e.jsx(D,{k:"cwd",v:t.cwd,wrap:!0})]}),e.jsx(B,{label:"Actions",children:e.jsxs("div",{className:"flex flex-col gap-2 items-start",children:[t.runId&&e.jsx("button",{type:"button",onClick:h=>{h.stopPropagation(),d(!0)},className:"text-[13px] font-semibold text-fg-dim hover:text-fg bg-transparent border-0 p-0 cursor-pointer",children:"view log →"}),t.status!=="pending"&&e.jsx("button",{type:"button",onClick:h=>{h.stopPropagation(),window.api.schedule.resetJob(t.slug)},className:"text-[13px] font-semibold text-fg-dim hover:text-fg bg-transparent border-0 p-0 cursor-pointer",children:"reset to pending →"}),t.error&&e.jsx("p",{className:"text-[12px] text-accent/90 mt-1 break-words whitespace-pre-wrap max-w-sm m-0",children:t.error})]})})]}),a&&t.runId&&e.jsx(_e,{runId:t.runId,slug:t.slug,title:t.title||t.slug,onClose:()=>d(!1)})]})}function Wt(t){return t?Object.values(t).reduce((s,n)=>s+(n??[]).reduce((a,d)=>{var o;return a+(((o=d.hooks)==null?void 0:o.length)??0)},0),0):0}function Kt(t){var s,n,a;return t?(((s=t.allow)==null?void 0:s.length)??0)+(((n=t.deny)==null?void 0:n.length)??0)+(((a=t.ask)==null?void 0:a.length)??0):0}function Xt({navigate:t}){const s=Ze(),n=se(f=>f.files),a=se(f=>f.loadJson),d=se(f=>f.loadText),o=se(f=>f.watchFile),r=se(f=>f.unwatchFile),u=s?et.resolve("user",s,null):null,x=s?tt.resolve("user",s,null):null,c=s?`${s}/.claude.json`:null;i.useEffect(()=>{const f=[u,c].filter(Boolean);f.forEach($=>{n[$]||a($),o($)});const A=[x].filter(Boolean);return A.forEach($=>{n[$]||d($),o($)}),()=>{[...f,...A].forEach($=>r($))}},[u,x,c]);const[b,v]=i.useState(null);i.useEffect(()=>{if(!s)return;let f=!1;return(async()=>{const A=await it(`${s}/.claude/skills`);f||v(A.length)})(),()=>{f=!0}},[s]);const h=u?n[u]:null,j=c?n[c]:null,k=x?n[x]:null,C=i.useMemo(()=>{if(!(h!=null&&h.exists)||h.parseError)return null;const f=h.diskData;return f===null||typeof f!="object"||Array.isArray(f)?{}:f},[h]),w=i.useMemo(()=>{if(!(j!=null&&j.exists)||j.parseError)return null;const f=j.diskData;return f===null||typeof f!="object"||Array.isArray(f)?{}:f},[j]),y=h?h.parseError?"invalid JSON":null:"loading…",N=j?j.parseError?"invalid JSON":null:"loading…",g=[{key:"settings",title:"Settings",summary:y??(C?`${Object.keys(C).length} top-level key${Object.keys(C).length===1?"":"s"} configured`:"not configured")},{key:"permissions",title:"Permissions",summary:y??(C?`${Kt(C.permissions)} rule(s) configured`:"not configured")},{key:"hooks",title:"Hooks",summary:y??(C?`${Wt(C.hooks)} hook(s) configured`:"not configured")},{key:"mcp",title:"MCP Servers",summary:N??(w?`${Object.keys(w.mcpServers??{}).length} MCP server(s)`:"not configured")},{key:"system-prompt",title:"System Prompt",summary:k!=null&&k.exists&&k.diskRaw.trim().length>0?`configured (${k.diskRaw.length.toLocaleString()} chars)`:"not set"},{key:"skills",title:"Skills",summary:b===null?"loading…":`${b} skill(s) installed`}];return e.jsxs("section",{className:"border border-line rounded-xl bg-bg-hi px-5 py-4",children:[e.jsx("h2",{className:"m-0 mb-1 font-serif text-[18px] font-semibold text-fg",children:"Global Controls"}),e.jsx("p",{className:"mt-0 mb-3 text-[13px] text-fg-dim leading-relaxed",children:"Machine-wide (user-scope) config state for the tabs that default to global here on Home. Read-only summary — open a card to edit."}),e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 gap-3",children:g.map(f=>e.jsxs("button",{type:"button",onClick:()=>t==null?void 0:t(f.key),className:"text-left border border-line rounded-lg bg-bg px-3 py-2.5 hover:border-accent transition-colors",children:[e.jsx("div",{className:"text-[13px] font-medium text-fg",children:f.title}),e.jsx("div",{className:"mt-0.5 text-[12px] text-fg-dim",children:f.summary})]},f.key))})]})}function Zt({navigate:t}){const s=st(),[n,a]=i.useState(!1),[d,o]=i.useState(!1);i.useEffect(()=>{let u=!0;return nt().then(x=>{u&&a(x.openToHomeOnLaunch===!0)}),()=>{u=!1}},[]);const r=async u=>{a(u),o(!0);try{await rt({openToHomeOnLaunch:u})}catch{a(!u),L.error('Failed to save "Open to Home on launch" — try again.')}finally{o(!1)}};return e.jsxs("div",{className:"max-w-[760px] space-y-6",children:[e.jsx(Xt,{navigate:t}),e.jsxs("section",{className:"border border-line rounded-xl bg-bg-hi px-5 py-4",children:[e.jsx("h2",{className:"m-0 mb-1 font-serif text-[18px] font-semibold text-fg",children:"Session pool"}),e.jsxs("p",{className:"mt-0 mb-3 text-[13px] text-fg-dim leading-relaxed",children:["One machine-wide pool of concurrent Claude sessions. Scheduler jobs and Epic chat runs each request a slot before launching; work waits when the pool is full. Adjustable from 0 (pauses new launches) to 10 on the Home tab, default 5 — or pin it with"," ",e.jsx("code",{className:"font-mono text-[12px]",children:"SM_SESSION_SLOTS"})," (clamped 0–10)."]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(at,{total:(s==null?void 0:s.total)??5,inUse:(s==null?void 0:s.inUse)??0,size:"md"}),e.jsx("span",{className:"ml-2 font-mono text-[12.5px] text-fg-faint",children:s?`${s.inUse} / ${s.total} in use`:"loading…"})]}),s&&s.holders.length>0&&e.jsx("ul",{className:"mt-2 mb-0 pl-0 list-none space-y-0.5",children:s.holders.map((u,x)=>e.jsxs("li",{className:"font-mono text-[12px] text-fg-dim",children:[u.owner," ",e.jsxs("span",{className:"text-fg-faint",children:["since ",new Date(u.at).toLocaleTimeString()]})]},x))})]}),e.jsxs("section",{className:"border border-line rounded-xl bg-bg-hi px-5 py-4",children:[e.jsx("h2",{className:"m-0 mb-1 font-serif text-[18px] font-semibold text-fg",children:"Behavior"}),e.jsx("p",{className:"mt-0 mb-3 text-[13px] text-fg-dim leading-relaxed",children:"Cross-project app behavior, independent of any single project's config."}),e.jsx(ot,{checked:n,onChange:r,disabled:d,label:"Open to Home on launch"})]}),e.jsxs("section",{className:"border border-line rounded-xl bg-bg-hi px-5 py-4",children:[e.jsx("h2",{className:"m-0 mb-1 font-serif text-[18px] font-semibold text-fg",children:"On disk"}),e.jsxs("p",{className:"mt-0 mb-2 text-[13px] text-fg-dim leading-relaxed",children:["Global runtime state is deliberately small — everything project-scoped lives inside that project's ",e.jsx("code",{className:"font-mono text-[12px]",children:"session-manager-operations/"})," folder."]}),e.jsxs("ul",{className:"m-0 pl-0 list-none space-y-1 font-mono text-[12px] text-fg-dim",children:[e.jsxs("li",{children:["~/.claude/session-manager/scheduler-machine.json ",e.jsx("span",{className:"text-fg-faint",children:"— policy + pause state"})]}),e.jsxs("li",{children:["<project>/session-manager-operations/scheduler/state/ ",e.jsx("span",{className:"text-fg-faint",children:"— per-project queue + history"})]}),e.jsxs("li",{children:["<project>/session-manager-operations/scheduler/epics/<epic>/prds/ ",e.jsx("span",{className:"text-fg-faint",children:"— PRD sources, per session"})]})]})]})]})}const Ie="sm.schedulerTab.subView",es=[{key:"queue",label:"Queue"},{key:"prds",label:"PRDs"},{key:"history",label:"History"}];function ts(t,s){const n=new Date(t),a=new Date(s);return n.getFullYear()===a.getFullYear()&&n.getMonth()===a.getMonth()&&n.getDate()===a.getDate()}function ss(t,s,n){if(t==="auth")return"Scheduler paused: Claude sign-in expired or invalid. Restart the app or re-run `claude login`, then Resume.";if(t==="rate_limit"){if(s){const d=new Date(s).getTime()-n;return d>0?`Paused for rate limit — resumes in ${H(d)}`:"Paused for rate limit — resume pending"}return"Paused for rate limit"}return t==="network"?"Paused: billing endpoint unreachable for 30+ min.":t==="manual"?"Scheduler paused manually. Click Resume to restart.":`Scheduler paused (${t})`}function ns({scopeCwd:t}){const{snapshot:s}=ve(),[n,a]=i.useState(()=>Date.now());if(i.useEffect(()=>{const N=setInterval(()=>a(Date.now()),3e4);return()=>clearInterval(N)},[]),!s)return null;const d=(s.jobs??[]).filter(N=>!t||N.cwd===t),o=d.filter(N=>N.status==="pending").length,r=d.filter(N=>N.status==="running").length,u=d.filter(N=>N.status==="completed"&&(N.finishedAt?ts(N.finishedAt,n):!1)).length,x=s.nextReset?new Date(s.nextReset).getTime():null,c=x?x>n?H(x-n):"soon":"—",b=U(s.lastRunAt?new Date(s.lastRunAt).getTime():null,n),v=s.paused,h=Object.entries(s.launchBlocks??{}),j=Object.entries(s.launchMitigations??{}),k=s.pollHealth,C=k!=null&&!k.lastPollOk,y=(v==null?void 0:v.reason)==="auth"||(v==null?void 0:v.reason)==="network"?"bg-red-950/60 border-red-700/50 text-red-200":"bg-amber-950/60 border-amber-700/50 text-amber-200";return e.jsxs("div",{className:"flex flex-col gap-2",children:[v&&e.jsxs("div",{className:`flex items-center gap-3 border rounded-xl px-4 py-2.5 text-[13px] ${y}`,children:[e.jsx("span",{className:"flex-1 leading-snug",children:ss(v.reason,v.resumeAt,n)}),e.jsx("button",{type:"button",onClick:()=>window.api.schedule.resume(),className:"shrink-0 px-2.5 py-1 rounded border border-current/40 hover:bg-white/10 transition-colors text-[12px] font-medium",children:"Resume"})]}),h.map(([N,g])=>e.jsxs("div",{"data-testid":"launch-block-banner",className:"flex items-start gap-3 border rounded-xl px-4 py-2.5 text-[13px] bg-red-950/60 border-red-700/50 text-red-200",children:[e.jsxs("div",{className:"flex-1 leading-snug min-w-0",children:[e.jsxs("div",{className:"font-medium",children:["Launches for ",e.jsx("span",{className:"font-mono",children:N})," jobs are failing before any work starts",g.httpStatus?` (HTTP ${g.httpStatus}, ${g.kind})`:` (${g.kind})`,g.exhausted?" — held until the Claude CLI version changes or you press Retry now.":g.until?` — next automatic probe ${new Date(g.until).getTime()>n?`in ${H(new Date(g.until).getTime()-n)}`:"on the next tick"}.`:"."]}),e.jsx("div",{className:"mt-0.5 text-red-200/80",children:g.hint}),e.jsxs("div",{className:"mt-0.5 font-mono text-[12px] text-red-200/70 truncate",title:g.message,children:[g.attempts," failed probe",g.attempts===1?"":"s",g.claudeVersion?` · CLI ${g.claudeVersion}`:"",g.lastSlug?` · last: ${g.lastSlug}`:""," · ",g.message]})]}),e.jsx("button",{type:"button",onClick:()=>window.api.schedule.resume(),className:"shrink-0 px-2.5 py-1 rounded border border-current/40 hover:bg-white/10 transition-colors text-[12px] font-medium",children:"Retry now"})]},`launch-block-${N}`)),j.map(([N,g])=>e.jsx("div",{"data-testid":"launch-mitigation-banner",className:"flex items-start gap-3 border rounded-xl px-4 py-2.5 text-[13px] bg-amber-950/60 border-amber-700/50 text-amber-200",children:e.jsxs("div",{className:"flex-1 leading-snug min-w-0",children:[e.jsxs("div",{className:"font-medium",children:[e.jsx("span",{className:"font-mono",children:N})," jobs are running in degraded mode"," ","(",e.jsx("span",{className:"font-mono",children:Object.entries(g.env).map(([f,A])=>`${f}=${A}`).join(" ")}),")",g.claudeVersion?` since CLI ${g.claudeVersion}`:"","."]}),e.jsx("div",{className:"mt-0.5 text-amber-200/80",children:g.hint})]})},`launch-mitigation-${N}`)),e.jsxs("div",{className:"flex items-center gap-5 flex-wrap bg-bg-hi border border-line rounded-xl px-4 py-3",children:[e.jsxs("span",{className:"inline-flex items-center gap-2 text-[13.5px] text-fg font-semibold whitespace-nowrap",children:[e.jsx("span",{className:"text-sage","aria-hidden":"true",children:e.jsx(ue,{name:"clock",size:15})}),"Window resets in ",c]}),e.jsx("span",{className:"w-px h-[18px] bg-rule shrink-0","aria-hidden":"true"}),e.jsx(he,{dotClass:"bg-fg-faint",n:o,label:"pending"}),e.jsx(he,{dotClass:"bg-accent",n:r,label:"running"}),e.jsx(he,{dotClass:"bg-sage",n:u,label:"completed today"}),s.utilization!==null&&s.utilization!==void 0&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"w-px h-[18px] bg-rule shrink-0","aria-hidden":"true"}),C?e.jsxs("span",{className:"font-mono text-[12.5px] text-amber-400/70",title:"Billing poll failing — this reading may be outdated",children:[Math.round(s.utilization),"% of window used · last good reading"," ",U(k.lastPollAt,n)]}):e.jsxs("span",{className:"font-mono text-[12.5px] text-fg-faint",children:[Math.round(s.utilization),"% of window used"]})]}),e.jsxs("span",{className:"ml-auto font-mono text-[12.5px] text-fg-faint whitespace-nowrap",children:["last batch ",b]})]})]})}function as({navigate:t}={}){var u;const[s,n]=i.useState(()=>{const x=localStorage.getItem(Ie);return x==="prds"||x==="history"||x==="machine"?x:"queue"}),a=Ae(x=>x.tabs),d=Ae(x=>x.activeTabId),o=((u=a.find(x=>x.id===d))==null?void 0:u.cwd)??null,r=o;return i.useEffect(()=>{o&&(le.getState().hydrate(o),le.getState().hydrateArchived(o))},[o]),i.useEffect(()=>{localStorage.setItem(Ie,s)},[s]),e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"shrink-0 px-9 pt-7 pb-0",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsx("div",{className:"text-xs font-bold text-fg-faint tracking-[0.8px] uppercase mb-1",children:"Workspace"}),e.jsx(lt,{active:"scheduler"})]}),e.jsx("h1",{className:"m-0 font-serif text-[40px] font-semibold leading-none tracking-tight text-fg",children:"Scheduler"}),e.jsxs("p",{className:"mt-2 text-[14.5px] text-fg-dim leading-relaxed max-w-[600px]",children:["Global scheduler policy and the machine-wide session pool, plus — when a project tab is active — that project's PRDs, run as"," ",e.jsx("code",{className:"font-mono text-[13.5px]",children:"claude -p"})," ","jobs against your 5-hour window. Jobs auto-pause on rate-limit and resume on the next reset."]}),e.jsx("div",{className:"mt-[18px] mb-[22px]",children:e.jsx(ns,{scopeCwd:r})}),e.jsxs("div",{className:"flex items-center gap-3 pb-0",children:[e.jsx(dt,{options:es,active:s,onChange:n}),e.jsxs("button",{type:"button",onClick:()=>n("machine"),"aria-pressed":s==="machine",className:`inline-flex items-center gap-1.5 px-[15px] py-2 rounded-lg text-[13.5px] transition-colors ${s==="machine"?"bg-bg-elev border border-line font-semibold text-fg":"text-fg-faint hover:text-fg-dim"}`,title:"Machine-wide config that applies to every project — not this project's live queue.",children:[e.jsx("span",{"aria-hidden":"true",children:"⚙"})," Machine"]})]}),s==="queue"&&e.jsx("p",{className:"mt-2 text-[14.5px] text-fg-dim leading-relaxed max-w-[600px]",children:"What's running right now, and what fires next."}),s==="prds"&&e.jsx("p",{className:"mt-2 text-[14.5px] text-fg-dim leading-relaxed max-w-[600px]",children:"Authored PRD source files on disk — edit, lint, archive, or queue them."}),s==="history"&&e.jsx("p",{className:"mt-2 text-[14.5px] text-fg-dim leading-relaxed max-w-[600px]",children:"The last 50 completed and failed jobs, for this project."}),s==="machine"&&e.jsx("p",{className:"mt-2 text-[14.5px] text-fg-dim leading-relaxed max-w-[600px]",children:"Machine-wide setup that applies to every project."})]}),e.jsxs("div",{className:"flex-1 min-h-0",children:[s==="queue"&&e.jsx(vt,{scopeCwd:r,navigate:t}),s==="prds"&&e.jsx(Gt,{scopeCwd:r}),s==="history"&&e.jsx(Qt,{scopeCwd:r}),s==="machine"&&e.jsx("div",{className:"h-full overflow-y-auto px-9 py-6",children:e.jsx(Zt,{navigate:t})})]})]})}const ds=i.memo(as);export{ds as Scheduler};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{ai as d,a9 as e,S as O,a as Q,j as R,aD as X,R as ee,as as te,ay as se,aG as $,aA as ne,av as I,J as ae,V as re,w as G}from"./index-CXFQIPhO.js";import{P as le}from"./Panel-Cj2kw-Zv.js";import{S as ie}from"./ScopeSwitcher-DVSyI44-.js";import{S as K}from"./SaveBar-Cd_7U6Gb.js";import{u as oe,m as ce,p as de,a as H,E as ue,s as xe}from"./settingsSchema-BJVciriw.js";import{T as L}from"./Toggle-CjV_BJn6.js";import"./monaco-editor-BW5C4Iv1.js";const pe=[{id:"essentials",title:"Essentials",summary:"The knobs you reach for first.",keys:["model","language","outputStyle","permissions"]},{id:"git",title:"Git & Commits",summary:"How Claude writes commits and pull requests on your behalf.",keys:["attribution","includeGitInstructions","includeCoAuthoredBy"]},{id:"memory",title:"Memory & Plans",summary:"Context Claude keeps between sessions and where it files plans.",keys:["autoMemoryEnabled","plansDirectory","claudeMdExcludes","respectGitignore"]},{id:"model",title:"Model & Reasoning",summary:"Model allow/override lists, reasoning depth, and fast-mode toggles — machine-wide, with no per-Epic override yet. An Epic's Agent persona model (Agent Library) still wins over Essentials' plain model default.",advanced:!0,keys:["availableModels","modelOverrides","effortLevel","fastMode","fastModePerSessionOptIn","alwaysThinkingEnabled"]},{id:"interface",title:"Interface",summary:"Visual polish — spinners, progress bars, motion.",keys:["spinnerTipsEnabled","spinnerTipsOverride","spinnerVerbs","terminalProgressBarEnabled","showTurnDuration","prefersReducedMotion","companyAnnouncements","statusLine","teammateMode"]},{id:"updates",title:"Updates & Cleanup",summary:"Release channel and how long transcripts stick around.",keys:["autoUpdatesChannel","cleanupPeriodDays"]},{id:"env",title:"Environment & Auth",summary:"Environment variables and auth-helper scripts.",keys:["env","apiKeyHelper","awsCredentialExport","awsAuthRefresh"]},{id:"hooks",title:"Hooks",summary:"Scripts Claude runs before/after tool use.",keys:["hooks","disableAllHooks","allowedHttpHookUrls","httpHookAllowedEnvVars"]},{id:"mcp",title:"MCP Servers",summary:"External tool providers Claude can talk to.",keys:["enableAllProjectMcpServers","enabledMcpjsonServers","disabledMcpjsonServers"]},{id:"plugins",title:"Plugins",summary:"Installed plugins, marketplaces, and per-plugin configuration.",keys:["enabledPlugins","extraKnownMarketplaces","skippedPlugins","skippedMarketplaces","pluginConfigs"]},{id:"filesystem",title:"File Picker & Sandbox",summary:"How Claude browses files and the sandbox it runs in.",keys:["fileSuggestion","sandbox","worktree"]},{id:"login",title:"Login",summary:"Which login method to force on startup.",keys:["forceLoginMethod","forceLoginOrgUUID"]},{id:"feedback",title:"Feedback",summary:"Session-quality surveys.",keys:["feedbackSurveyRate"]},{id:"advanced",title:"Advanced / Enterprise",summary:"Managed-settings-only keys and enterprise allow/denylists.",advanced:!0,keys:["allowedMcpServers","deniedMcpServers","allowManagedHooksOnly","allowManagedPermissionRulesOnly","allowManagedMcpServersOnly","strictKnownMarketplaces","blockedMarketplaces","pluginTrustMessage","otelHeadersHelper","skipWebFetchPreflight"]}],me={mcp:"MCP",url:"URL",urls:"URLs",http:"HTTP",ui:"UI",id:"ID",uuid:"UUID",api:"API",aws:"AWS",otel:"OTel",json:"JSON"};function W(s){return s.replace(/^\$/,"").replace(/([a-z])([A-Z])/g,"$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1 $2").toLowerCase().split(/\s+/).filter(Boolean).map((l,a)=>{const r=me[l];return r||(a===0?l.charAt(0).toUpperCase()+l.slice(1):l)}).join(" ")}function V(s){const n=new Set,t=[];for(const a of pe){const r=a.keys.filter(i=>s.has(i));r.forEach(i=>n.add(i)),r.length!==0&&t.push({id:a.id,title:a.title,summary:a.summary,advanced:!!a.advanced,keys:r})}const l=Array.from(s).filter(a=>!n.has(a)&&a!=="$schema").sort();return l.length>0&&t.push({id:"other",title:"Other",summary:"Keys not yet grouped.",advanced:!1,keys:l}),t}function fe(s,n){return V(s).map(t=>({id:t.id,title:t.title,advanced:t.advanced,total:t.keys.length,setCount:t.keys.filter(l=>n.has(l)).length}))}const he={};function q(s,n){if(n)return{text:n,authored:!1};const t=he[s];return t?{text:t,authored:!0}:null}const ge={essentials:"star",git:"link",memory:"memory",model:"sparkle",interface:"eye",updates:"reload",env:"keys",hooks:"hooks",mcp:"mcp",plugins:"plugins",filesystem:"folder",login:"lock",feedback:"send",advanced:"shield",other:"dot"},be=["user","project","local","default"],ye={user:"user",project:"project",local:"local",default:"default"};function je({node:s,targetScope:n,onOverride:t,schema:l}){const[a,r]=d.useState(""),[i,p]=d.useState(!1),[m,v]=d.useState(!0),x=s.kind==="object"?s:null,w=x?Object.keys(x.children):[],g=l.rootKeys(),y=new Set([...w,...g]),u=d.useMemo(()=>V(y),[Array.from(y).sort().join(",")]),b=d.useMemo(()=>fe(y,new Set(w)),[Array.from(y).sort().join(","),w.join(",")]),[C,E]=d.useState(null),f=d.useRef(null),S=o=>{const j=u.find(N=>N.id===o);j!=null&&j.advanced&&!i&&p(!0),E(o)};d.useEffect(()=>{if(!C)return;E(null);const o=f.current,j=document.getElementById(`settings-group-${C}`);if(!o||!j)return;const N=j.getBoundingClientRect().top-o.getBoundingClientRect().top;o.scrollBy({top:N,behavior:"smooth"})},[C]);const k=d.useMemo(()=>u.filter(o=>i||!o.advanced).map(o=>({...o,keys:o.keys.filter(j=>{const N=(x==null?void 0:x.children[j])!==void 0;if(!m&&!N)return!1;if(!a.trim())return!0;const h=l.at([j]);return[j,W(j),(h==null?void 0:h.description)??""].join(" ").toLowerCase().includes(a.toLowerCase())})})).filter(o=>o.keys.length>0),[u,a,i,m,x,l]);return e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"shrink-0 border-b border-line bg-bg-elev px-3 py-1.5 flex items-center gap-3 text-xs",children:[e.jsxs("span",{className:"text-fg-faint",children:["writing overrides to"," ",e.jsx("span",{className:"text-fg-dim font-medium",children:O[n].label})]}),e.jsxs("label",{className:"flex items-center gap-1 text-fg-faint cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:m,onChange:o=>v(o.target.checked),className:"accent-accent"}),"show not-yet-configured"]}),e.jsxs("label",{className:"flex items-center gap-1 text-fg-faint cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:i,onChange:o=>p(o.target.checked),className:"accent-accent"}),"show advanced"]}),e.jsx("div",{className:"flex-1"}),e.jsx("input",{value:a,onChange:o=>r(o.target.value),placeholder:"search settings…",className:"bg-bg border border-line rounded px-2 py-1 text-xs text-fg w-64"})]}),e.jsxs("div",{className:"flex-1 flex overflow-hidden",children:[e.jsx(ve,{groups:b,onJump:S}),e.jsxs("div",{ref:f,className:"flex-1 overflow-auto py-3",children:[k.map(o=>e.jsx(Ne,{id:o.id,title:o.title,summary:o.summary,advanced:o.advanced,children:o.keys.map(j=>{const N=x==null?void 0:x.children[j],h=l.at([j]);return e.jsx(we,{keyName:j,node:N,info:h,targetScope:n,onOverride:(c,T)=>t([j],c,T)},j)})},o.id)),k.length===0&&e.jsxs("div",{className:"px-6 py-12 text-center text-fg-faint text-sm",children:['no settings match "',a,'"']})]})]})]})}function ve({groups:s,onJump:n}){return e.jsx("nav",{className:"shrink-0 w-48 border-r border-line bg-bg-elev/30 overflow-y-auto py-3",children:s.map(t=>e.jsxs("button",{onClick:()=>n(t.id),className:"w-full flex items-center gap-2 px-3 py-2 text-left hover:bg-bg-hi transition-colors",title:`jump to ${t.title}`,children:[e.jsx(Q,{name:ge[t.id]??"dot",size:15,className:"text-fg-faint shrink-0"}),e.jsx("span",{className:"flex-1 min-w-0 truncate text-xs text-fg-dim",children:t.title}),e.jsxs("span",{className:"text-[10px] text-fg-faint font-mono shrink-0",children:[t.setCount,"/",t.total]})]},t.id))})}function Ne({id:s,title:n,summary:t,advanced:l,children:a}){const[r,i]=d.useState(!0);return e.jsxs("section",{id:`settings-group-${s}`,className:"mx-4 mb-4 rounded-lg border border-line shadow-sm bg-bg-elev/50 overflow-hidden",children:[e.jsxs("header",{className:"px-4 py-3 bg-bg-elev cursor-pointer hover:bg-bg-hi flex items-center gap-3 border-b border-line",onClick:()=>i(!r),children:[e.jsx("span",{className:"text-fg-faint w-3",children:r?"▾":"▸"}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h2",{className:"text-fg text-base font-semibold",children:n}),l&&e.jsx("span",{className:"text-[9px] px-1.5 py-0 rounded border border-yellow-900/40 bg-yellow-950/30 text-yellow-500/80 uppercase tracking-wide",children:"advanced"})]}),e.jsx("p",{className:"text-fg-dim text-sm mt-0.5",children:t})]})]}),r&&e.jsx("div",{className:"divide-y divide-line/60",children:a})]})}function we({keyName:s,node:n,info:t,targetScope:l,onOverride:a}){const[r,i]=d.useState(!1),[p,m]=d.useState(!1),v=W(s),x=n!==void 0,g=(n==null?void 0:n.kind)==="leaf"?n:null,y=(n==null?void 0:n.kind)==="object"||(n==null?void 0:n.kind)==="array",u=t==null?void 0:t.default,b=g&&u!==void 0&&Y(g.value,u),C=Pe({isSet:x,leafNode:g,defaultVal:u,isDefault:!!b,node:n}),E=Se(g,u),f=E.length>=2,S=!!g&&!b,k=q(s,t==null?void 0:t.description);return e.jsx("div",{className:"px-4 py-3 hover:bg-bg-elev/20",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("button",{onClick:()=>i(!r),className:"text-fg-faint hover:text-fg w-3 mt-0.5",title:r?"collapse":"expand",children:r?"▾":"▸"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-baseline gap-2 flex-wrap",children:[e.jsx("h3",{className:"text-fg text-sm",children:v}),e.jsx(Re,{kind:C.kind,label:C.label}),f&&e.jsxs("button",{onClick:o=>{o.stopPropagation(),r||i(!0),m(j=>!j)},className:"text-[9px] px-1.5 py-0 rounded border border-blue-900/40 bg-blue-950/30 text-blue-300/90 uppercase tracking-wide hover:bg-blue-900/40",title:"this key is defined in multiple scopes — click to expand",children:["drift · ",E.map(o=>ye[o]).join(" · ")]}),S&&g&&e.jsx("button",{onClick:o=>{o.stopPropagation(),a(void 0,g.winner)},className:"text-[9px] px-1.5 py-0 rounded border border-line bg-bg-elev text-fg-faint uppercase tracking-wide hover:text-fg hover:bg-bg-hi",title:`reset · delete from ${O[g.winner].label}`,children:"↺ reset"}),(t==null?void 0:t.deprecated)&&e.jsx("span",{className:"text-[9px] px-1 py-0 rounded border border-yellow-900/40 bg-yellow-950/30 text-yellow-500/80 uppercase tracking-wide",children:"deprecated"}),(t==null?void 0:t.required)&&!x&&e.jsx("span",{className:"text-[9px] px-1 py-0 rounded border border-red-900/40 bg-red-950/30 text-red-400/80 uppercase tracking-wide",children:"required"})]}),k&&e.jsx("p",{className:`text-fg-dim text-xs mt-0.5 leading-relaxed ${k.authored?"inline-block border-b border-dotted border-fg-faint/70 cursor-help":""}`,title:k.authored?"In-app-authored description — not from the official Claude Code schema":void 0,children:Ie(k.text)}),r&&p&&g&&e.jsx(ke,{leaf:g,defaultVal:u,onReset:o=>a(void 0,o)}),r&&e.jsx(Ce,{keyName:s,node:n,info:t,targetScope:l,onOverride:o=>a(o)})]}),e.jsx("div",{className:"shrink-0",children:!r&&e.jsx(Ae,{node:n,info:t,onSet:o=>{a(o)},disabled:y&&x})})]})})}function Se(s,n){if(!s)return[];const t=new Set;t.add(s.winner);for(const l of s.shadowed)t.add(l.scope);return n!==void 0&&t.add("default"),be.filter(l=>t.has(l))}function ke({leaf:s,defaultVal:n,onReset:t}){const l={};l[s.winner]={value:s.value,winner:!0};for(const a of s.shadowed)l[a.scope]={value:a.value,winner:!1};return e.jsxs("div",{className:"mt-2 border border-line rounded bg-bg-elev/40 text-xs",children:[e.jsx("div",{className:"px-2 py-1 text-fg-faint border-b border-line/60",children:"Values across all scopes (winner highlighted · reset removes that scope's value):"}),e.jsxs("div",{className:"divide-y divide-line/60",children:[["user","project","local"].map(a=>{const r=l[a],i=r!==void 0;return e.jsxs("div",{className:"grid grid-cols-[5rem_1fr_auto] gap-2 px-2 py-1 items-center",children:[e.jsx("span",{className:"text-fg-faint",children:O[a].label}),e.jsx("span",{className:`font-mono truncate ${r!=null&&r.winner?"text-accent":"text-fg-dim"}`,children:i?P(r.value):e.jsx("span",{className:"text-fg-faint",children:"—"})}),i?e.jsx("button",{onClick:()=>t(a),className:"text-[9px] px-1.5 py-0 rounded border border-line text-fg-faint uppercase tracking-wide hover:text-fg hover:bg-bg-hi",title:`delete this key from ${O[a].label}`,children:"↺"}):e.jsx("span",{})]},a)}),e.jsxs("div",{className:"grid grid-cols-[5rem_1fr_auto] gap-2 px-2 py-1 items-center",children:[e.jsx("span",{className:"text-fg-faint",children:"Default"}),e.jsx("span",{className:"font-mono text-fg-dim truncate",children:n!==void 0?P(n):e.jsx("span",{className:"text-fg-faint",children:"—"})}),e.jsx("span",{})]})]})]})}function Ce({keyName:s,node:n,info:t,targetScope:l,onOverride:a}){const i=(n==null?void 0:n.kind)==="leaf"?n:null,p=q(s,t==null?void 0:t.description);return e.jsxs("div",{className:"mt-3 space-y-2 text-xs",children:[p&&e.jsx("p",{className:`text-fg-dim leading-relaxed whitespace-pre-wrap ${p.authored?"inline-block border-b border-dotted border-fg-faint/70 cursor-help":""}`,title:p.authored?"In-app-authored description — not from the official Claude Code schema":void 0,children:p.text}),e.jsxs("dl",{className:"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-fg-faint",children:[(t==null?void 0:t.type)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:"Type"}),e.jsx("dd",{className:"text-fg-dim font-mono",children:Array.isArray(t.type)?t.type.join(" | "):t.type})]}),(t==null?void 0:t.default)!==void 0&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:"Default"}),e.jsx("dd",{className:"text-fg-dim font-mono",children:P(t.default)})]}),(t==null?void 0:t.enum)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:"Options"}),e.jsx("dd",{className:"text-fg-dim font-mono",children:t.enum.map(m=>String(m)).join(" | ")})]}),i&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:"Current"}),e.jsxs("dd",{className:"font-mono",children:[e.jsx("span",{className:"text-fg-dim",children:P(i.value)}),e.jsxs("span",{className:"ml-2 text-fg-faint",children:["from ",O[i.winner].label]})]})]}),i&&i.shadowed.length>0&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:"Shadowed"}),e.jsx("dd",{className:"space-y-0.5",children:i.shadowed.map((m,v)=>e.jsxs("div",{className:"font-mono text-fg-faint line-through",children:[P(m.value)," —"," ",e.jsx("span",{className:"no-underline",children:O[m.scope].label})]},v))})]}),(n==null?void 0:n.kind)==="array"&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:"Accumulated"}),e.jsxs("dd",{className:"text-fg-dim",children:[n.items.length," items across all scopes"]})]})]}),e.jsx("div",{className:"pt-2 flex items-center gap-2 flex-wrap border-t border-line/60",children:e.jsx(Ee,{keyName:s,node:n,info:t,onChange:a,targetScope:l})})]})}function Ee({node:s,info:n,onChange:t,targetScope:l}){const r=(s==null?void 0:s.kind)==="leaf"?s.value:n==null?void 0:n.default,i=z(n==null?void 0:n.type);if(i==="boolean"){const p=r===!0;return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg-faint",children:"Set to:"}),e.jsx("div",{className:"inline-flex rounded border border-line overflow-hidden",children:[{v:!0,label:"on"},{v:!1,label:"off"}].map(({v:m,label:v})=>e.jsx("button",{onClick:()=>t(m),className:`px-3 py-0.5 text-xs transition-colors ${p===m?"bg-accent text-bg":"bg-bg-elev text-fg-dim hover:bg-bg-hi hover:text-fg"}`,children:v},v))}),e.jsxs("span",{className:"text-fg-faint",children:["→ ",O[l].label]})]})}return n!=null&&n.enum?e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"text-fg-faint",children:"Choose:"}),n.enum.map(p=>{const m=Y(r,p);return e.jsx("button",{onClick:()=>t(p),className:`px-2 py-0.5 text-xs rounded border ${m?"bg-accent text-bg border-accent":"bg-bg-elev text-fg-dim border-line hover:text-fg hover:bg-bg-hi"}`,children:String(p)},String(p))}),e.jsxs("span",{className:"text-fg-faint",children:["→ ",O[l].label]})]}):i==="integer"||i==="number"?e.jsx(Oe,{value:typeof r=="number"?r:void 0,integer:i==="integer",onCommit:t,target:O[l].label}):i==="string"?e.jsx(Te,{value:typeof r=="string"?r:"",onCommit:t,target:O[l].label}):e.jsxs("div",{className:"text-fg-faint",children:["Complex value (",i??"object/array",") — use the"," ",e.jsx("span",{className:"text-fg-dim",children:"Raw"})," tab to edit."]})}function Oe({value:s,integer:n,onCommit:t,target:l}){const[a,r]=d.useState(s!==void 0?String(s):""),i=()=>{const p=n?parseInt(a,10):parseFloat(a);Number.isNaN(p)||t(p)};return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg-faint",children:"Set to:"}),e.jsx("input",{type:"number",value:a,onChange:p=>r(p.target.value),onBlur:i,onKeyDown:p=>{p.key==="Enter"&&p.target.blur()},className:"w-24 bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg"}),e.jsxs("button",{onClick:i,className:"px-2 py-0.5 text-xs border border-accent/50 rounded text-accent hover:bg-accent hover:text-bg",children:["save → ",l]})]})}function Te({value:s,onCommit:n,target:t}){const[l,a]=d.useState(s);return e.jsxs("div",{className:"flex items-center gap-2 flex-1 min-w-0",children:[e.jsx("span",{className:"text-fg-faint shrink-0",children:"Set to:"}),e.jsx("input",{type:"text",value:l,onChange:r=>a(r.target.value),onKeyDown:r=>{r.key==="Enter"&&n(l)},className:"flex-1 min-w-0 bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg"}),e.jsxs("button",{onClick:()=>n(l),className:"shrink-0 px-2 py-0.5 text-xs border border-accent/50 rounded text-accent hover:bg-accent hover:text-bg",children:["save → ",t]})]})}function Ae({node:s,info:n,onSet:t,disabled:l}){const a=(s==null?void 0:s.kind)==="leaf",r=z(n==null?void 0:n.type);if(l)return null;if(r==="boolean"){const i=a&&s.value===!0;return e.jsx("button",{onClick:()=>t(!i),className:`px-2.5 py-0.5 text-xs rounded border transition-colors ${i?"bg-accent/15 text-accent border-accent/40 hover:bg-accent hover:text-bg":"bg-bg-elev text-fg-dim border-line hover:text-fg hover:bg-bg-hi"}`,title:"toggle",children:i?"on":"off"})}return null}function Pe({isSet:s,leafNode:n,defaultVal:t,isDefault:l,node:a}){return s?(a==null?void 0:a.kind)==="array"?{kind:"accumulated",label:`${a.items.length} items`}:(a==null?void 0:a.kind)==="object"?{kind:"set",label:"configured"}:n?l?{kind:"default",label:`= default · ${O[n.winner].label}`}:n.shadowed.length>0?{kind:"override",label:`overriding ${n.shadowed.length} scope(s)`}:{kind:"set",label:`set in ${O[n.winner].label}`}:{kind:"set",label:"configured"}:t!==void 0?{kind:"default",label:`using default: ${P(t)}`}:{kind:"unset",label:"not configured"}}function Re({kind:s,label:n}){const t={set:"bg-accent/15 text-accent border-accent/30",default:"bg-bg-hi text-fg-dim border-line",unset:"bg-bg-elev text-fg-faint border-line",override:"bg-purple-950/30 text-purple-400/80 border-purple-900/40",accumulated:"bg-blue-950/30 text-blue-400/80 border-blue-900/40"}[s];return e.jsx("span",{className:`text-[9px] px-1.5 py-0 rounded border uppercase tracking-wide ${t}`,children:n})}function z(s){if(s)return Array.isArray(s)?s.find(t=>t!=="null")??s[0]:s}function Y(s,n){return s===n?!0:typeof s!=typeof n?!1:s&&n&&typeof s=="object"?JSON.stringify(s)===JSON.stringify(n):!1}function Ie(s){const n=s.trim().split(`
|
|
2
|
-
`)[0],t=n.match(/^([^.!?]+[.!?])/);return t?t[1]:n.length>120?n.slice(0,120)+"…":n}function P(s){if(typeof s=="string")return s===""?'""':JSON.stringify(s);if(s===null)return"null";if(s===void 0)return"—";if(typeof s=="object"){const n=JSON.stringify(s);return n.length>60?n.slice(0,60)+"…":n}return String(s)}const De=1440*60*1e3;function U(s){if(!s)return"never";const n=new Date(s).getTime();return Number.isNaN(n)?"never":new Date(n).toLocaleString()}function J(s){return s?new Date(s).toLocaleString():"never"}function Me(){return e.jsxs("div",{className:"p-4 max-w-3xl space-y-8 text-sm",children:[e.jsx(Le,{}),e.jsx("hr",{className:"border-line"}),e.jsx(_e,{})]})}function Le(){const[s,n]=d.useState(null),[t,l]=d.useState(null),[a,r]=d.useState(null),[i,p]=d.useState(null),[m,v]=d.useState(!1),[x,w]=d.useState(null),[g,y]=d.useState(null);if(d.useEffect(()=>{let f=!1;return Promise.all([window.api.otel.getConfig(),window.api.otel.status(),window.api.otel.configPath()]).then(([S,k,o])=>{f||(n(S),r(S),l(k),p(o))}).catch(S=>{console.warn("[telemetry] load failed:",S==null?void 0:S.message)}),()=>{f=!0}},[]),!a||!s)return e.jsx(R,{title:"loading…"});const u=JSON.stringify(a)!==JSON.stringify(s),b=(f,S)=>{w(null),r({...a,[f]:S})},C=async()=>{v(!0),w(null);try{const f=await window.api.otel.setConfig(a);!f.ok&&f.error&&w(f.error),n(f.config),r(f.config),l(f.status),y(Date.now())}catch(f){w(f instanceof Error?f.message:String(f))}finally{v(!1)}},E=()=>{w(null),r(s)};return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("header",{className:"space-y-1",children:[e.jsx("h2",{className:"text-fg text-base font-medium",children:"OpenTelemetry export"}),e.jsx("p",{className:"text-fg-dim text-xs leading-relaxed",children:"When enabled, every classified transcript event (tool_use, todo_write, plan, usage, agent_spawn) is mirrored as a 0-duration OTLP/HTTP span. Point this at a local collector (Jaeger, Grafana Tempo, SigNoz, Honeycomb) for cross-session analysis."}),i&&e.jsxs("p",{className:"text-fg-faint text-[11px]",children:["stored at ",e.jsx("span",{className:"font-mono",children:i})]})]}),e.jsxs("section",{className:"border border-line rounded p-3 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-fg",children:"Export transcripts to OTEL"}),e.jsx("div",{className:"text-fg-faint text-xs",children:"Toggle off to disable all span emission immediately."})]}),e.jsx(L,{checked:a.enabled,onChange:f=>b("enabled",f),label:a.enabled?"on":"off"})]}),e.jsxs("label",{className:"block space-y-1",children:[e.jsx("span",{className:"text-fg-dim text-xs",children:"OTLP/HTTP traces endpoint"}),e.jsx("input",{type:"text",value:a.endpoint,onChange:f=>b("endpoint",f.target.value),placeholder:"http://localhost:4318/v1/traces",className:"w-full bg-bg border border-line rounded px-2 py-1 text-fg font-mono text-xs"})]}),e.jsxs("label",{className:"block space-y-1",children:[e.jsxs("span",{className:"text-fg-dim text-xs",children:["Headers (newline-separated ",e.jsx("span",{className:"font-mono",children:"Key: Value"}),")"]}),e.jsx("textarea",{value:a.headers,onChange:f=>b("headers",f.target.value),placeholder:"x-honeycomb-team: YOUR_API_KEY",rows:3,className:"w-full bg-bg border border-line rounded px-2 py-1 text-fg font-mono text-xs"})]}),e.jsxs("label",{className:"block space-y-1",children:[e.jsx("span",{className:"text-fg-dim text-xs",children:"Service name"}),e.jsx("input",{type:"text",value:a.serviceName,onChange:f=>b("serviceName",f.target.value),placeholder:"session-manager",className:"w-full bg-bg border border-line rounded px-2 py-1 text-fg font-mono text-xs"})]}),e.jsxs("div",{className:"flex items-start justify-between gap-3 pt-1",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-fg",children:"Include content (PII)"}),e.jsxs("div",{className:"text-fg-faint text-xs leading-relaxed",children:["Adds tool inputs, plan text, and agent prompts to span attributes. Off by default — matches upstream Claude Code's ",e.jsx("span",{className:"font-mono",children:"OTEL_LOG_USER_PROMPTS"})," opt-in."]})]}),e.jsx(L,{checked:a.includeContent,onChange:f=>b("includeContent",f),label:a.includeContent?"on":"off"})]})]}),t&&e.jsxs("section",{className:"border border-line rounded p-3 text-xs space-y-1",children:[e.jsx("div",{className:"text-fg-dim",children:"Runtime status"}),e.jsxs("div",{children:[e.jsx("span",{className:"text-fg-faint",children:"enabled:"})," ",e.jsx("span",{className:t.enabled?"text-accent":"text-fg-dim",children:String(t.enabled)})]}),t.error&&e.jsxs("div",{className:"text-red-400 break-words",children:[e.jsx("span",{className:"text-fg-faint",children:"error:"})," ",t.error]}),!t.error&&t.enabled&&e.jsx("div",{className:"text-fg-faint",children:"spans batched and exported in the background. Verify by enabling and pointing at a local Jaeger."})]}),e.jsxs("footer",{className:"flex items-center gap-3 pt-2 border-t border-line",children:[e.jsx("button",{onClick:C,disabled:!u||m,className:"px-3 py-1 text-xs rounded bg-accent text-bg disabled:opacity-50 disabled:cursor-not-allowed",children:m?"saving…":"Save"}),e.jsx("button",{onClick:E,disabled:!u||m,className:"px-3 py-1 text-xs rounded border border-line text-fg-dim hover:text-fg disabled:opacity-50 disabled:cursor-not-allowed",children:"Revert"}),x&&e.jsx("span",{className:"text-red-400 text-xs",children:x}),!x&&g&&!u&&e.jsx("span",{className:"text-fg-faint text-xs",children:"saved"})]})]})}function _e(){const[s,n]=d.useState(null),[t,l]=d.useState(null),[a,r]=d.useState("Copy"),[i,p]=d.useState(!1),[m,v]=d.useState(null),[x,w]=d.useState(null),[g,y]=d.useState(null),[u,b]=d.useState(!1),C=()=>{window.api.telemetry.status().then(l).catch(h=>{console.warn("[product-telemetry] status reload failed:",h==null?void 0:h.message)})};if(d.useEffect(()=>{let h=!1;return Promise.all([window.api.telemetry.getConfig(),window.api.telemetry.status()]).then(([c,T])=>{h||(n(c),l(T))}).catch(c=>{console.warn("[product-telemetry] load failed:",c==null?void 0:c.message)}),()=>{h=!0}},[]),!s||!t)return e.jsx(R,{title:"loading…"});const E=async h=>{w(null);try{const c=await window.api.telemetry.setConfig(h);n(c.config),l(c.status)}catch(c){w(c instanceof Error?c.message:String(c))}},f=h=>{E({...s,enabled:h})},S=h=>{E({...s,enabled:h.turnOff?!1:s.enabled,noticeAckedAt:new Date().toISOString()})},k=async()=>{try{await navigator.clipboard.writeText(s.installId),r("Copied"),setTimeout(()=>r("Copy"),1500)}catch{}},o=async()=>{p(!0),v(null);try{const h=await window.api.telemetry.flushNow();v(`sent ${h.sent.length}, failed ${h.failed.length}`),C()}catch(h){v(h instanceof Error?h.message:String(h))}finally{p(!1)}},j=async()=>{if(u){b(!1);return}try{const h=await window.api.telemetry.recentRecords();y(h),b(!0)}catch(h){console.warn("[product-telemetry] recentRecords failed:",h instanceof Error?h.message:h)}},N=s.lastDailyFlushAt?new Date(s.lastDailyFlushAt).getTime()+De:null;return e.jsxs("div",{className:"space-y-5","data-testid":"product-telemetry-section",children:[e.jsxs("header",{className:"space-y-1",children:[e.jsx("h2",{className:"text-fg text-base font-medium",children:"Product telemetry (bilko.run)"}),e.jsxs("p",{className:"text-fg-dim text-xs leading-relaxed",children:["Anonymous, strictly non-identifying usage/error reporting that helps improve this app. On by default; switchable off in one click. See"," ",e.jsx("span",{className:"font-mono",children:"session-manager-operations/architecture/telemetry.md"})," for the full data model."]})]}),!s.noticeAckedAt&&e.jsxs("section",{"data-testid":"telemetry-first-run-notice",className:"border border-accent rounded p-3 space-y-2 text-xs",children:[e.jsx("div",{className:"text-fg font-medium",children:"This app sends anonymous product telemetry"}),e.jsx("p",{className:"text-fg-dim leading-relaxed",children:"Collected: a coarse machine profile (OS/arch/app version, no hardware id), error and warning counts, and session counts — sent on start-up, after an update, and once a day."}),e.jsx("p",{className:"text-fg-dim leading-relaxed",children:"Never collected: prompts, transcripts, file paths, project names, email, or username."}),e.jsxs("div",{className:"flex items-center gap-2 pt-1",children:[e.jsx("button",{onClick:()=>S({turnOff:!1}),className:"px-3 py-1 rounded bg-accent text-bg",children:"OK"}),e.jsx("button",{onClick:()=>S({turnOff:!0}),className:"px-3 py-1 rounded border border-line text-fg-dim hover:text-fg",children:"Turn off"})]})]}),e.jsxs("section",{className:"border border-line rounded p-3 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-fg",children:"Send anonymous product telemetry"}),e.jsx("div",{className:"text-fg-faint text-xs",children:"Sent on start-up, after an update, and once a day. Strictly anonymous — an install id only, never an email, name, or other identifier."})]}),e.jsx(L,{checked:s.enabled,onChange:f,label:s.enabled?"on":"off"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("div",{className:"text-fg-dim text-xs",children:"Anonymous install id"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"text",readOnly:!0,value:s.installId,"aria-label":"Anonymous install identifier",className:"flex-1 bg-bg border border-line rounded px-2 py-1 text-fg font-mono text-xs"}),e.jsx("button",{onClick:k,className:"px-2 py-1 text-xs rounded border border-line text-fg-dim hover:text-fg",children:a})]})]}),e.jsxs("div",{className:"space-y-1 text-xs",children:[e.jsx("div",{className:"text-fg-faint",children:"Endpoint"}),e.jsx("div",{className:"font-mono text-fg-dim break-all",children:s.endpoint})]}),e.jsxs("div",{className:"space-y-1 text-xs",children:[e.jsx("div",{className:"text-fg-faint",children:"Send cadence"}),e.jsx("div",{className:"text-fg-dim",children:"on start-up, after an update, and once a day"})]}),x&&e.jsx("div",{className:"text-red-400 text-xs",children:x})]}),t.pendingCount>0&&t.sentCount===0&&e.jsxs("section",{"data-testid":"telemetry-never-delivered-warning",className:"border border-red-400 rounded p-3 text-xs space-y-1 text-red-400",children:[e.jsx("div",{className:"font-medium",children:"Never delivered"}),e.jsxs("div",{className:"leading-relaxed",children:[t.pendingCount," record",t.pendingCount===1?"":"s",' queued but none have ever been sent to bilko.run on this install. Check the endpoint/network, or click "Send now" below.']})]}),e.jsxs("section",{className:"border border-line rounded p-3 text-xs space-y-1.5",children:[e.jsx("div",{className:"text-fg-dim",children:"Runtime status"}),e.jsxs("div",{children:[e.jsx("span",{className:"text-fg-faint",children:"last send:"})," ",J(t.lastFlushAt)]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-fg-faint",children:"next daily send due:"})," ",U(N?new Date(N).toISOString():null)]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-fg-faint",children:"queued records:"})," ",t.pendingCount]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-fg-faint",children:"delivered so far:"})," ",t.sentCount]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-fg-faint",children:"de-duplicated:"})," ",t.dedupedAppends]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-fg-faint",children:"evicted:"})," ",t.evictedCount]}),t.backlog&&e.jsxs("div",{className:"text-fg-faint",children:["last backlog drain (",t.backlog.reason,", ",U(t.backlog.ranAt),"):"," ",t.backlog.linesEnqueued," enqueued, ",t.backlog.linesConfirmed," confirmed,"," ",t.backlog.watermarksRewound," watermarks rewound"]}),t.lastError&&e.jsxs("div",{className:"text-red-400 break-words",children:[e.jsx("span",{className:"text-fg-faint",children:"last error:"})," ",t.lastError.message," ","(",J(t.lastError.at),")"]})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("button",{onClick:o,disabled:i,className:"px-3 py-1 text-xs rounded bg-accent text-bg disabled:opacity-50 disabled:cursor-not-allowed",children:i?"sending…":"Send now"}),m&&e.jsx("span",{className:"text-fg-faint text-xs",children:m})]}),e.jsxs("section",{className:"space-y-2",children:[e.jsx("button",{onClick:j,className:"px-3 py-1 text-xs rounded border border-line text-fg-dim hover:text-fg",children:u?"Hide last records":"Inspect last records sent"}),u&&e.jsx("pre",{"data-testid":"telemetry-inspector-json",className:"bg-bg border border-line rounded p-2 text-[11px] font-mono overflow-auto max-h-96 whitespace-pre-wrap",children:JSON.stringify(g??[],null,2)})]})]})}function Fe(){const{model:s,setModel:n}=X();return e.jsxs("div",{className:"p-4 max-w-3xl space-y-5 text-sm",children:[e.jsxs("header",{className:"space-y-1",children:[e.jsx("h2",{className:"text-fg text-base font-medium",children:"Session Manager preferences"}),e.jsx("p",{className:"text-fg-dim text-xs leading-relaxed",children:"Native app preferences, stored locally — not part of Claude Code's own settings."})]}),e.jsx("section",{className:"border border-line rounded p-3 space-y-3",children:e.jsxs("label",{className:"block space-y-1",children:[e.jsx("span",{className:"text-fg-dim text-xs",children:"Default model for raw sessions"}),e.jsx("select",{value:s,onChange:t=>n(t.target.value),className:"w-full bg-bg border border-line rounded px-2 py-1 text-fg font-mono text-xs",children:ee.map(t=>e.jsx("option",{value:t,children:t.charAt(0).toUpperCase()+t.slice(1)},t))}),e.jsx("span",{className:"text-fg-faint text-[11px]",children:"Used when opening a raw interactive session without an explicit per-launch override."})]})})]})}function $e({cwd:s}){const[n,t]=d.useState(!1),[l,a]=d.useState(!1),[r,i]=d.useState(!1),[p,m]=d.useState(!1);d.useEffect(()=>{var y,u;let g=!1;return t(!1),Promise.resolve((u=(y=window.api.promptSessions)==null?void 0:y.getWorktreeDisabled)==null?void 0:u.call(y,{cwd:s})).then(b=>{g||(a((b==null?void 0:b.disabled)??!1),i((b==null?void 0:b.disabled)??!1),t(!0))},()=>{g||t(!0)}),()=>{g=!0}},[s]);const v=n&&r!==l,x=()=>{var g,y;m(!0),Promise.resolve((y=(g=window.api.promptSessions)==null?void 0:g.setWorktreeDisabled)==null?void 0:y.call(g,{cwd:s,disabled:r})).then(u=>{a((u==null?void 0:u.disabled)??r),i((u==null?void 0:u.disabled)??r)}).catch(u=>te.error(u instanceof Error?u.message:String(u))).finally(()=>m(!1))},w=()=>i(l);return e.jsxs("div",{"data-testid":"settings-epic-isolation",className:"border-b border-line bg-bg-elev px-3 py-2.5 text-[11.5px] leading-snug",children:[e.jsxs("label",{className:"flex items-start gap-2",children:[e.jsx("input",{type:"checkbox",checked:r,disabled:!n||p,onChange:g=>i(g.target.checked),"data-testid":"settings-epic-isolation-checkbox",className:"mt-0.5"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-semibold text-fg",children:"Disable Epic worktree isolation for this project"}),e.jsxs("span",{className:"block text-fg-dim",children:["Off by default — each active Epic runs in its own isolated ",e.jsx("code",{children:"git worktree"})," (branch"," ",e.jsx("code",{children:"sm-epic/<id>"}),"), merged back to main at an explicit checkpoint. Turning this on makes every new Epic in this project run directly in the shared working tree instead, same as before this feature existed."]})]})]}),v&&e.jsx(K,{dirty:v,busy:p,onSave:x,onRevert:w})]})}const B={user:{title:"Global settings",body:"This is the real ~/.claude/settings.json on disk — the same file the claude CLI reads on every session it starts. Edits apply machine-wide, to every project and every session."},project:{title:"Project settings",body:"This is the real <project>/.claude/settings.json on disk, checked into git. Edits apply to every current and future session in this project, for anyone who clones it."},local:{title:"Local settings",body:"This is the real <project>/.claude/settings.local.json on disk, gitignored. Edits apply to every current and future session in this project, on this machine only."}};function Ge(){const s=se(),n=$(c=>c.tabs),t=$(c=>c.activeTabId),l=n.find(c=>c.id===t)??null,a=(l==null?void 0:l.cwd)??null,r=ne(c=>c.navFace),i=d.useRef(!1),p=d.useRef(r),[m,v]=d.useState(()=>r==="project"&&a?"project":"user"),[x,w]=d.useState("effective");d.useEffect(()=>{if(p.current!==r){if(p.current=r,i.current){i.current=!1;return}v(r==="project"&&a?"project":"user")}},[r,a]),d.useEffect(()=>{r==="project"&&(x==="telemetry"||x==="app")&&w("effective")},[r,x]);const g=c=>{i.current=!0,v(c)},y=oe(G,s,a),u=y[m]??null,b=I(c=>c.files),C=I(c=>c.setDraft),E=I(c=>c.saveJson),f=I(c=>c.revert),[S,k]=d.useState(null),o=d.useMemo(()=>ce(de(b,y)),[b,y]),j=(c,T,A)=>{var F;const D=y[A??m];if(!D)return;k(null);const _=((F=b[D])==null?void 0:F.draftRaw)??"";let M={};if(_.trim())try{M=JSON.parse(_)}catch{M={}}const Z=xe(M,c,T);C(D,JSON.stringify(Z,null,2)+`
|
|
3
|
-
`)};if(!s)return e.jsx(R,{title:"loading…"});const N=u?b[u]:null,h=c=>c!=="user"&&!a;return e.jsx(le,{toolbar:e.jsxs(e.Fragment,{children:[e.jsx(re,{options:[{key:"effective",label:"Guided"},{key:"tree",label:"Tree"},{key:"raw",label:"Raw"},...r==="home"?[{key:"telemetry",label:"Telemetry"},{key:"app",label:"Session Manager"}]:[]],active:x,onChange:w}),x!=="telemetry"&&x!=="app"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"mx-2 text-fg-faint",children:"·"}),e.jsx(ie,{scopes:G.scopes,active:m,onChange:g,annotate:c=>{if(h(c))return{exists:!1};const T=y[c];if(!T)return null;const A=b[T];return{exists:(A==null?void 0:A.exists)??!1,dirty:(A==null?void 0:A.dirty)??!1}}}),e.jsx("span",{className:"ml-3 text-fg-faint truncate",children:x==="effective"?`overrides → ${u??"—"}`:u??"—"})]}),e.jsx("div",{className:"flex-1"}),e.jsx("a",{href:"https://code.claude.com/docs/en/settings",target:"_blank",rel:"noreferrer",className:"text-fg-faint hover:text-fg-dim underline-offset-2 hover:underline",children:"schema reference ↗"})]}),footer:x!=="telemetry"&&x!=="app"&&u&&N?e.jsx(K,{dirty:N.dirty,busy:N.busy,parseError:S||N.parseError,lastSavedAt:N.lastSavedAt,leading:N.exists?null:e.jsx("span",{children:"file will be created on save"}),onSave:async()=>{k(null);const c=await E(u);c.ok||k(c.error??"save failed")},onRevert:()=>{k(null),f(u)}}):null,children:x==="telemetry"?e.jsx(Me,{}):x==="app"?e.jsx(Fe,{}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{"data-testid":"settings-scope-note",className:"sticky top-0 z-10 border-b border-line bg-bg-elev px-3 py-2 text-[11.5px] leading-snug",children:[e.jsx("span",{className:"font-semibold text-fg",children:B[m].title}),e.jsx("span",{className:"mx-1.5 text-fg-faint",children:"·"}),e.jsx("span",{className:"text-fg-dim",children:B[m].body}),u&&e.jsx("span",{className:"ml-1.5 font-mono text-fg-faint",children:u})]}),m==="project"&&a&&e.jsx($e,{cwd:a}),h(m)?e.jsx(R,{title:"no active project",hint:"open a tab in a project directory to edit project or local settings"}):x==="effective"?e.jsx(je,{node:o,targetScope:m,onOverride:j,schema:H()}):x==="tree"?e.jsx(ue,{node:o,targetScope:m,onOverride:j,schema:H()}):u&&N?e.jsx(ae,{path:u,value:N.draftRaw,onChange:c=>{k(null),C(u,c)}}):e.jsx(R,{title:"resolving…"})]})})}const ze=d.memo(Ge);export{B as SETTINGS_SCOPE_NOTES,ze as Settings};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{ai as x,a9 as o,S as j,av as P}from"./index-CXFQIPhO.js";function re({node:e,targetScope:t,onOverride:r,schema:n,rootLabel:m}){const[c,f]=x.useState(""),[d,l]=x.useState(!0),g=[],i=e.kind==="object"&&Object.keys(e.children).length===0,h=((n==null?void 0:n.rootKeys())??[]).length>0;return o.jsxs("div",{className:"h-full flex flex-col",children:[o.jsxs("div",{className:"shrink-0 border-b border-line bg-bg-elev px-3 py-1.5 flex items-center gap-2 text-xs",children:[o.jsxs("span",{className:"text-fg-faint",children:["merged · overrides → ",o.jsx("span",{className:"text-fg-dim",children:j[t].label})]}),h&&o.jsxs("label",{className:"flex items-center gap-1 text-fg-faint cursor-pointer",children:[o.jsx("input",{type:"checkbox",checked:d,onChange:s=>l(s.target.checked),className:"accent-accent"}),"show unset keys"]}),o.jsx("div",{className:"flex-1"}),o.jsx("input",{value:c,onChange:s=>f(s.target.value),placeholder:"filter keys or descriptions…",className:"bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg w-56"})]}),o.jsx("div",{className:"flex-1 overflow-auto px-3 py-2 font-mono text-xs",children:i&&!d?o.jsx("div",{className:"text-fg-faint italic px-2 py-4",children:"no settings resolved — all scope files empty or missing"}):o.jsx(O,{node:e,path:g,label:m??"(root)",targetScope:t,onOverride:r,filter:c,depth:0,schema:n,showGhosts:d,defaultOpen:!0})})]})}function O(e){return e.node.kind==="object"?o.jsx(D,{...e,node:e.node}):e.node.kind==="array"?o.jsx(R,{...e,node:e.node}):o.jsx($,{...e,node:e.node})}function L(e,t){return t.trim()?e.toLowerCase().includes(t.toLowerCase()):!0}function w(e,t,r){return!!(!r.trim()||e.some(n=>L(n,r))||t!=null&&t.description&&L(t.description,r))}function D({node:e,path:t,label:r,targetScope:n,onOverride:m,filter:c,depth:f,schema:d,showGhosts:l,defaultOpen:g}){const[i,b]=x.useState(g??f<2),h=(d==null?void 0:d.at(t))??null,s=new Set(Object.keys(e.children)),a=l?(h==null?void 0:h.knownChildren)??[]:[],u=Array.from(new Set([...s,...a])).sort(),p=x.useMemo(()=>c.trim()?u.filter(y=>{const v=(d==null?void 0:d.at([...t,y]))??null;return w([...t,y],v,c)?!0:s.has(y)?N(e.children[y],[...t,y],c,d):!1}):u,[u.join(","),c,e,t.join("."),d]);if(c.trim()&&p.length===0&&!w(t,h,c))return null;if(t.length===0)return o.jsx("div",{children:p.map(y=>k(y))});return o.jsxs("div",{children:[o.jsxs("div",{className:"flex items-center gap-1 py-0.5 hover:bg-bg-elev/50 rounded cursor-pointer",style:{paddingLeft:f*14},onClick:()=>b(!i),children:[o.jsx("span",{className:"text-fg-faint w-3 shrink-0",children:i?"▾":"▸"}),o.jsx("span",{className:"text-fg",children:r}),o.jsxs("span",{className:"text-fg-faint",children:[" {",s.size,a.length>s.size?`/${new Set([...s,...a]).size}`:"","}"]}),(h==null?void 0:h.description)&&o.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:h.description,children:["— ",h.description]})]}),i&&p.map(y=>k(y))]});function k(y){if(s.has(y))return o.jsx(O,{node:e.children[y],path:[...t,y],label:y,targetScope:n,onOverride:m,filter:c,depth:f+1,schema:d,showGhosts:l},y);const v=(d==null?void 0:d.at([...t,y]))??null;return v?o.jsx(_,{path:[...t,y],label:y,info:v,targetScope:n,onSet:m,depth:f+1,filter:c},y):null}}function N(e,t,r,n){const m=(n==null?void 0:n.at(t))??null;if(w(t,m,r))return!0;if(e.kind!=="object")return!1;for(const c of Object.keys(e.children))if(N(e.children[c],[...t,c],r,n))return!0;return!1}function R({node:e,path:t,label:r,filter:n,depth:m,schema:c}){const[f,d]=x.useState(!0),l=(c==null?void 0:c.at(t))??null;return w(t,l,n)?o.jsxs("div",{children:[o.jsxs("div",{className:"flex items-center gap-1 py-0.5 hover:bg-bg-elev/50 rounded cursor-pointer",style:{paddingLeft:m*14},onClick:()=>d(!f),children:[o.jsx("span",{className:"text-fg-faint w-3 shrink-0",children:f?"▾":"▸"}),o.jsx("span",{className:"text-fg",children:r}),o.jsxs("span",{className:"text-fg-faint",children:[" [",e.items.length,"]"]}),o.jsx(S,{tone:"warn",children:"accumulated"}),(l==null?void 0:l.description)&&o.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:l.description,children:["— ",l.description]})]}),f&&e.items.map((g,i)=>o.jsxs("div",{className:"flex items-start gap-2 py-0.5",style:{paddingLeft:(m+1)*14},children:[o.jsx("span",{className:"text-fg-faint w-3 shrink-0"}),o.jsxs("span",{className:"text-fg-faint",children:[i,":"]}),o.jsx("span",{className:"text-fg-dim truncate max-w-xl",children:E(g.value)}),o.jsx(M,{scope:g.fromScope})]},i))]}):null}function $({node:e,path:t,label:r,targetScope:n,onOverride:m,filter:c,depth:f,schema:d}){const[l,g]=x.useState(!1),i=(d==null?void 0:d.at(t))??null;if(!w(t,i,c))return null;const b=e.winner!==n,h=e.shadowed.length>0;return o.jsxs("div",{children:[o.jsxs("div",{className:"group flex items-center gap-2 py-0.5 hover:bg-bg-elev/50 rounded",style:{paddingLeft:f*14},children:[o.jsx("span",{className:`w-3 shrink-0 ${h?"text-fg-faint cursor-pointer":""}`,onClick:()=>h&&g(!l),children:h?l?"▾":"▸":""}),o.jsxs("span",{className:"text-fg",children:[r,":"]}),o.jsx("span",{className:"text-fg-dim truncate max-w-md",children:E(e.value)}),o.jsx(M,{scope:e.winner}),(i==null?void 0:i.deprecated)&&o.jsx(S,{tone:"warn",children:"deprecated"}),(i==null?void 0:i.default)!==void 0&&I(e.value,i.default)&&o.jsx(S,{tone:"dim",children:"= default"}),e.typeMismatch&&o.jsx("span",{className:"text-yellow-500/80",title:"shadowed scopes have a different value type",children:"⚠"}),(i==null?void 0:i.description)&&o.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:i.description,children:["— ",i.description]}),o.jsx("div",{className:"flex-1"}),(i==null?void 0:i.enum)&&o.jsx(T,{values:i.enum}),o.jsx("button",{disabled:!b,onClick:()=>m(t,e.value),className:`opacity-0 group-hover:opacity-100 px-1.5 py-0 text-[10px] border rounded transition-opacity ${b?"border-accent/50 text-accent hover:bg-accent hover:text-bg":"border-line text-fg-faint cursor-not-allowed"}`,title:b?`copy into ${j[n].label} draft`:`already winning in ${j[n].label}`,children:"override"})]}),l&&e.shadowed.map((s,a)=>o.jsxs("div",{className:"flex items-center gap-2 py-0.5 text-fg-faint line-through",style:{paddingLeft:(f+1)*14+12},children:[o.jsx("span",{children:"shadowed:"}),o.jsx("span",{className:"truncate max-w-xl",children:E(s.value)}),o.jsx(M,{scope:s.scope,dim:!0})]},a))]})}function _({path:e,label:t,info:r,targetScope:n,onSet:m,depth:c,filter:f}){if(!w(e,r,f))return null;const d=r.default!==void 0?r.default:H(r.type),l=Array.isArray(r.type)?r.type.join("|"):r.type??"?";return o.jsxs("div",{className:"group flex items-center gap-2 py-0.5 hover:bg-bg-elev/50 rounded opacity-60",style:{paddingLeft:c*14},children:[o.jsx("span",{className:"w-3 shrink-0"}),o.jsx("span",{className:"text-fg-dim",children:t}),o.jsx(S,{tone:"dim",children:l}),r.required&&o.jsx(S,{tone:"warn",children:"required"}),r.default!==void 0&&o.jsxs("span",{className:"text-fg-faint",children:["default: ",E(r.default)]}),r.description&&o.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:r.description,children:["— ",r.description]}),o.jsx("div",{className:"flex-1"}),r.enum&&o.jsx(T,{values:r.enum}),o.jsx("button",{onClick:()=>m(e,d),className:"opacity-0 group-hover:opacity-100 px-1.5 py-0 text-[10px] border border-accent/50 rounded text-accent hover:bg-accent hover:text-bg transition-opacity",title:`write to ${j[n].label} draft`,children:"set"})]})}function I(e,t){return e===t?!0:typeof e!=typeof t?!1:e&&t&&typeof e=="object"?JSON.stringify(e)===JSON.stringify(t):!1}function H(e){switch(Array.isArray(e)?e[0]:e){case"boolean":return!1;case"integer":case"number":return 0;case"string":return"";case"array":return[];case"object":return{};case"null":return null;default:return null}}function E(e){if(typeof e=="string")return JSON.stringify(e);if(e===null)return"null";if(typeof e=="object"){const t=JSON.stringify(e);return t.length>100?t.slice(0,100)+"…":t}return String(e)}function M({scope:e,dim:t}){const r=e==="user"?"bg-bg-hi text-fg-dim border-line":e==="project"?"bg-blue-950/30 text-blue-400/80 border-blue-900/40":"bg-purple-950/30 text-purple-400/80 border-purple-900/40";return o.jsx("span",{className:`text-[10px] px-1 py-0 rounded border uppercase tracking-wide shrink-0 ${r} ${t?"opacity-60":""}`,children:j[e].label})}function S({children:e,tone:t="default"}){const r={default:"bg-bg-hi text-fg-dim border-line",warn:"bg-yellow-950/30 text-yellow-500/80 border-yellow-900/40",dim:"bg-bg-elev text-fg-faint border-line"}[t];return o.jsx("span",{className:`text-[10px] px-1 py-0 rounded border uppercase tracking-wide shrink-0 ${r}`,children:e})}function T({values:e}){const t=e.map(r=>String(r)).join(" | ");return o.jsxs("span",{className:"text-[10px] text-fg-faint truncate max-w-xs",title:`allowed: ${t}`,children:["∈ ",t.length>30?t.slice(0,30)+"…":t]})}function ie(e,t,r){const n=P(l=>l.files),m=P(l=>l.loadJson),c=P(l=>l.watchFile),f=P(l=>l.unwatchFile),d=x.useMemo(()=>{const l={};for(const g of e.scopes){const i=e.resolve(g,t??"",r);i&&(l[g]=i)}return l},[e,t,r]);return x.useEffect(()=>{const l=Object.values(d).filter(Boolean);return l.forEach(g=>{n[g]||m(g),c(g)}),()=>{l.forEach(g=>f(g))}},[JSON.stringify(d)]),d}const q=[];function C(e){return Array.isArray(e)?"array":e!==null&&typeof e=="object"?"object":"scalar"}function ne(e){const t=e.filter(r=>r.data!==void 0);return t.length===0?{kind:"object",children:{}}:U(t,[])}function U(e,t){const r=q.includes(t.join(".")),n=e.every(i=>C(i.data)==="object"),m=e.every(i=>C(i.data)==="array");if(n){const i=new Set;for(const h of e)for(const s of Object.keys(h.data))i.add(s);const b={};for(const h of i){const s=e.filter(a=>h in a.data).map(a=>({scope:a.scope,data:a.data[h]}));b[h]=U(s,[...t,h])}return{kind:"object",children:b}}if(m&&!r){const i=[];for(const b of[...e].reverse())for(const h of b.data)i.push({value:h,fromScope:b.scope,index:i.length});return{kind:"array",items:i}}const c=[...e].reverse(),f=c[0],d=c.slice(1).map(i=>({scope:i.scope,value:i.data})),l=C(f.data),g=d.some(i=>C(i.value)!==l);return{kind:"leaf",value:f.data,winner:f.scope,shadowed:d,...g?{typeMismatch:!0}:{}}}function B(e,t){if(t.length===0)return e;if(e.kind!=="object")return null;const[r,...n]=t,m=e.children[r];return m?B(m,n):null}function G(e,t,r){if(t.length===0)return r;const[n,...m]=t,c=e&&typeof e=="object"&&!Array.isArray(e)?{...e}:{};return c[n]=G(c[n],m,r),c}const F=["user","project","local"];function ae(e,t){const r=[];for(const n of F){const m=t[n];if(!m)continue;const c=e[m];if(!c||!c.exists)continue;const f=c.draftRaw??"";if(f.trim())try{r.push({scope:n,data:JSON.parse(f)})}catch{}}return r}const W="http://json-schema.org/draft-07/schema#",K="https://json.schemastore.org/claude-code-settings.json",J={permissionRule:{type:"string",description:`Tool permission rule.
|
|
2
|
-
See https://code.claude.com/docs/en/settings#permission-rule-syntax
|
|
3
|
-
See https://code.claude.com/docs/en/settings#tools-available-to-claude for full list of tools available to Claude.`,pattern:"^((Agent|Bash|Edit|ExitPlanMode|Glob|Grep|KillShell|LSP|NotebookEdit|Read|Skill|TaskCreate|TaskGet|TaskList|TaskOutput|TaskStop|TaskUpdate|TodoWrite|ToolSearch|WebFetch|WebSearch|Write)(\\((?=.*[^)*?])[^)]+\\))?|mcp__.*)$",examples:["Bash","Bash(npm run build)","Bash(git commit *)","Bash(npm run *)","Bash(ls*)","Bash(git * main)","Edit","Edit(/src/**/*.ts)","Read(./.env)","Read(./secrets/**)","Read(//Users/alice/secrets/**)","Read(~/Documents/*.pdf)","Agent(Explore)","WebFetch","WebFetch(domain:example.com)","mcp__puppeteer","mcp__github__search_repositories"]},hookCommand:{anyOf:[{type:"object",description:"Bash command hook",additionalProperties:!1,required:["type","command"],properties:{type:{type:"string",description:"Hook type",const:"command"},command:{type:"string",description:"Shell command to execute",minLength:1},timeout:{type:"number",description:"Optional timeout in seconds",exclusiveMinimum:0},async:{type:"boolean",description:"Run this hook asynchronously without blocking Claude Code"},statusMessage:{type:"string",description:"Custom spinner message displayed while the hook runs"}}},{type:"object",description:"LLM prompt hook. See https://code.claude.com/docs/en/hooks#prompt-based-hooks",additionalProperties:!1,required:["type","prompt"],properties:{type:{type:"string",description:"Hook type",const:"prompt"},prompt:{type:"string",description:"Prompt to evaluate with LLM. Use $ARGUMENTS placeholder for hook input JSON.",minLength:1},model:{type:"string",description:"Model to use for evaluation. Defaults to a fast model"},timeout:{type:"number",description:"Optional timeout in seconds (default: 30)",exclusiveMinimum:0},statusMessage:{type:"string",description:"Custom spinner message displayed while the hook runs"}}},{type:"object",description:"Agent hook with multi-turn tool access for verification. See https://code.claude.com/docs/en/hooks#agent-based-hooks",additionalProperties:!1,required:["type","prompt"],properties:{type:{type:"string",description:"Hook type",const:"agent"},prompt:{type:"string",description:"Prompt describing what to verify. Use $ARGUMENTS placeholder for hook input JSON.",minLength:1},model:{type:"string",description:"Model to use for evaluation. Defaults to a fast model"},timeout:{type:"number",description:"Optional timeout in seconds (default: 60)",exclusiveMinimum:0},statusMessage:{type:"string",description:"Custom spinner message displayed while the hook runs"}}},{type:"object",description:"HTTP webhook hook. POST JSON to a URL and receive JSON response. See https://code.claude.com/docs/en/hooks#http-hooks",additionalProperties:!1,required:["type","url"],properties:{type:{type:"string",description:"Hook type",const:"http"},url:{type:"string",description:"URL to POST hook input JSON to. Endpoint must accept POST requests and return JSON.",minLength:1},headers:{type:"object",additionalProperties:{type:"string"},description:"Custom HTTP headers (e.g., Authorization: Bearer token). Values support $VAR_NAME or ${VAR_NAME} interpolation."},allowedEnvVars:{type:"array",items:{type:"string",minLength:1},description:"List of environment variable names permitted for interpolation in headers. If not set, no env var interpolation is allowed."},timeout:{type:"number",description:"Optional timeout in seconds (default: 30)",exclusiveMinimum:0},statusMessage:{type:"string",description:"Custom spinner message displayed while the hook runs"}}}]},hookMatcher:{type:"object",description:"Hook matcher configuration with multiple hooks",additionalProperties:!1,required:["hooks"],properties:{matcher:{type:"string",description:"Optional pattern to match event contexts, case-sensitive. Behavior depends on event type. See https://code.claude.com/docs/en/hooks#matcher-patterns for event-specific details and examples"},hooks:{type:"array",description:"Array of hooks to execute",items:{$ref:"#/$defs/hookCommand"}}}}},V="Configuration settings for Claude Code. Learn more: https://code.claude.com/docs/en/settings",z=!0,Y=!0,Z="object",X=JSON.parse(`{"$schema":{"type":"string","description":"JSON Schema reference for Claude Code settings"},"apiKeyHelper":{"type":"string","description":"Path to a script that outputs authentication values","examples":["/bin/generate_temp_api_key.sh"],"minLength":1},"autoMemoryEnabled":{"type":"boolean","description":"Enable automatic memory saves that capture useful context to .claude/memory/. Also configurable via CLAUDE_CODE_DISABLE_AUTO_MEMORY environment variable (set to 1 to disable, 0 to enable). See https://code.claude.com/docs/en/memory#auto-memory","default":true},"autoUpdatesChannel":{"type":"string","enum":["stable","latest"],"description":"Release channel to follow for updates. Use \\"stable\\" for a version that is typically about one week old and skips versions with major regressions, or \\"latest\\" (default) for the most recent release. Set DISABLE_AUTOUPDATER=1 to disable updates entirely.","default":"latest"},"awsCredentialExport":{"type":"string","description":"Path to a script that exports AWS credentials","examples":["/bin/generate_aws_grant.sh"],"minLength":1},"awsAuthRefresh":{"type":"string","description":"Path to a script that refreshes AWS authentication","examples":["aws sso login --profile myprofile"],"minLength":1},"claudeMdExcludes":{"type":"array","items":{"type":"string","minLength":1},"description":"Glob patterns for CLAUDE.md files to exclude from loading. Useful in monorepos to skip irrelevant instructions from other teams. Patterns match against absolute file paths. Arrays merge across settings layers. Managed policy CLAUDE.md files cannot be excluded. See https://code.claude.com/docs/en/memory#exclude-specific-claudemd-files","examples":[["**/monorepo/CLAUDE.md","/home/user/monorepo/other-team/.claude/rules/**"]]},"cleanupPeriodDays":{"type":"integer","minimum":0,"description":"Number of days to retain chat transcripts (0 to disable cleanup)","examples":[20,30,60],"default":30},"env":{"type":"object","additionalProperties":false,"description":"Environment variables to set for Claude Code sessions. Many environment variables provide settings dimensions not available as dedicated settings.json properties (e.g., thinking tokens, prompt caching, bash timeouts, shell configuration). See https://code.claude.com/docs/en/settings#environment-variables for the full list.\\nUNDOCUMENTED: CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS (plugin marketplace git timeout in ms, default 120000, see https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#2151).\\nUNDOCUMENTED: ENABLE_CLAUDEAI_MCP_SERVERS (set to false to opt out of claude.ai MCP servers, see https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#2163).","examples":[{"ANTHROPIC_MODEL":"claude-opus-4-1","ANTHROPIC_SMALL_FAST_MODEL":"claude-3-5-haiku-latest"}],"default":{},"patternProperties":{"^[A-Z_][A-Z0-9_]*$":{"type":"string","description":"Environment variable value"}}},"attribution":{"type":"object","description":"Customize attribution for git commits and pull requests. See https://code.claude.com/docs/en/settings#attribution-settings","additionalProperties":false,"properties":{"commit":{"type":"string","description":"Attribution for git commits, including any trailers. Empty string hides commit attribution"},"pr":{"type":"string","description":"Attribution for pull request descriptions. Empty string hides pull request attribution"}}},"includeGitInstructions":{"type":"boolean","description":"Include built-in git commit and PR workflow instructions in Claude's system prompt. Also configurable via CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS environment variable (set to 1 to disable). See https://code.claude.com/docs/en/settings#available-settings","default":true},"includeCoAuthoredBy":{"type":"boolean","description":"DEPRECATED. Use 'attribution' instead. Whether to include the co-authored-by Claude byline in git commits and pull requests (default: true)","default":true},"plansDirectory":{"type":"string","description":"Customize where plan files are stored. Path is relative to project root (default: ~/.claude/plans)","default":"~/.claude/plans","examples":["./plans"]},"respectGitignore":{"type":"boolean","description":"Control whether the @ file picker respects .gitignore patterns. When true (default), files matching .gitignore patterns are excluded from suggestions","default":true},"permissions":{"type":"object","properties":{"allow":{"type":"array","items":{"$ref":"#/$defs/permissionRule"},"description":"List of permission rules for allowed operations","uniqueItems":true},"deny":{"type":"array","items":{"$ref":"#/$defs/permissionRule"},"description":"List of permission rules for denied operations","uniqueItems":true},"ask":{"type":"array","items":{"$ref":"#/$defs/permissionRule"},"description":"List of permission rules that should always prompt for confirmation","uniqueItems":true},"defaultMode":{"type":"string","enum":["acceptEdits","bypassPermissions","default","delegate","dontAsk","plan"],"description":"Default permission mode.\\n\\"default\\": prompts on first use.\\n\\"acceptEdits\\": auto-accepts file edits.\\n\\"plan\\": read-only, no modifications.\\nUNDOCUMENTED. \\"delegate\\": coordination-only for agent team leads (agent teams are experimental; enable via CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS).\\n\\"dontAsk\\": auto-denies unless pre-approved via permissions.\\n\\"bypassPermissions\\": skips all prompts (use only in isolated environments).\\nSee https://code.claude.com/docs/en/permissions"},"disableBypassPermissionsMode":{"type":"string","enum":["disable"],"description":"Disable the ability to bypass permission prompts"},"additionalDirectories":{"type":"array","items":{"type":"string","minLength":1},"description":"Additional directories to include in the permission scope","examples":[["//Users/alice/Documents","~/projects"]],"uniqueItems":true}},"additionalProperties":false,"description":"Tool usage permissions configuration.\\nSee https://code.claude.com/docs/en/permissions and https://code.claude.com/docs/en/settings#permission-settings\\nSee https://code.claude.com/docs/en/settings#tools-available-to-claude for full list of tools available to Claude.","examples":[{"allow":["Bash(git add:*)"],"ask":["Bash(gh pr create:*)","Bash(git commit:*)"],"deny":["Read(*.env)","Bash(rm:*)","Bash(curl:*)"],"defaultMode":"default"}]},"language":{"type":"string","description":"Preferred language for Claude's responses","examples":["japanese","spanish","french"]},"model":{"type":"string","enum":["opus","sonnet","haiku","default"],"description":"Override the default model used by Claude Code. Accepts a short alias (opus|sonnet|haiku) or a full model ID. For finer control, use environment variables: ANTHROPIC_MODEL (runtime override), ANTHROPIC_DEFAULT_OPUS_MODEL, ANTHROPIC_DEFAULT_SONNET_MODEL, ANTHROPIC_DEFAULT_HAIKU_MODEL (per-class pinning), CLAUDE_CODE_SUBAGENT_MODEL (subagent model). See https://code.claude.com/docs/en/model-config"},"availableModels":{"type":"array","items":{"type":"string"},"description":"Restrict which models users can select. When defined at multiple settings levels (user, project, etc.), arrays are merged and deduplicated. See https://code.claude.com/docs/en/model-config#restrict-model-selection","examples":[["sonnet","haiku"]]},"modelOverrides":{"type":"object","additionalProperties":{"type":"string"},"description":"Map Anthropic model IDs to provider-specific model IDs such as Bedrock inference profile ARNs, Vertex AI version names, or Foundry deployment names. Each model picker entry uses its mapped value when calling the provider API. Unknown keys are ignored. See https://code.claude.com/docs/en/model-config#override-model-ids-per-version","examples":[{"claude-opus-4-6":"arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-prod"}]},"effortLevel":{"type":"string","enum":["low","medium","high"],"description":"Control Opus 4.6 adaptive reasoning effort. Lower effort is faster and cheaper for straightforward tasks, higher effort provides deeper reasoning. Defaults vary by model and plan (Opus 4.6 defaults to medium for Max and Team subscribers). Use /effort auto to reset to model default. Also configurable via CLAUDE_CODE_EFFORT_LEVEL environment variable. See https://code.claude.com/docs/en/model-config#adjust-effort-level"},"fastMode":{"type":"boolean","description":"Enable fast mode for Opus 4.6 (research preview). Fast mode uses the same model with 2.5x faster output at higher per-token cost. Requires extra usage enabled. Alternatively, toggle with /fast command. See https://code.claude.com/docs/en/fast-mode","default":false},"fastModePerSessionOptIn":{"type":"boolean","description":"Require per-session opt-in for fast mode. When true, fast mode does not persist across sessions and users must enable it with /fast each session. Useful for controlling costs. See https://code.claude.com/docs/en/fast-mode","default":false},"feedbackSurveyRate":{"type":"number","minimum":0,"maximum":1,"description":"Probability (0–1) that the session quality survey appears when eligible. A value of 0.05 means 5% of eligible sessions. See https://code.claude.com/docs/en/settings","examples":[0.05]},"editorMode":{"type":"string","enum":["normal","vim"],"default":"normal","description":"Editor input mode for the Claude Code terminal prompt. 'vim' enables modal editing (Esc for normal mode, i for insert). See https://code.claude.com/docs/en/settings"},"skillOverrides":{"type":"object","additionalProperties":{"type":"string","enum":["on","name-only","user-invocable-only","off"]},"description":"Per-skill availability override map. Keys are skill names; values are one of 'on' (default), 'name-only' (skill name listed but not auto-loaded), 'user-invocable-only' (load only when user explicitly invokes), or 'off' (hidden). Requires Claude Code v2.1.129+. See https://code.claude.com/docs/en/settings","examples":[{"playwright-debug":"user-invocable-only","init":"off"}]},"disableAgentView":{"type":"boolean","default":false,"description":"Disable the Agent View feature (read-only inspection of sub-agent activity). Useful when administering managed deployments. Requires Claude Code v2.1.139+. See https://code.claude.com/docs/en/settings"},"disableRemoteControl":{"type":"boolean","default":false,"description":"Block the \`claude remote-control\` channel that allows external clients to drive this Claude Code instance. Recommended default for shared/CI environments. Requires Claude Code v2.1.128+. See https://code.claude.com/docs/en/settings"},"enableAllProjectMcpServers":{"type":"boolean","description":"Whether to automatically approve all MCP servers in the project. See https://code.claude.com/docs/en/mcp","examples":[true]},"enabledMcpjsonServers":{"type":"array","items":{"type":"string","minLength":1},"description":"List of approved MCP servers from .mcp.json. See https://code.claude.com/docs/en/mcp","examples":[["memory","github"]]},"disabledMcpjsonServers":{"type":"array","items":{"type":"string","minLength":1},"description":"List of rejected MCP servers from .mcp.json. See https://code.claude.com/docs/en/mcp","examples":[["filesystem"]]},"allowedMcpServers":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"serverName":{"type":"string","pattern":"^[a-zA-Z0-9_-]+$","description":"Name of the MCP server that users are allowed to configure"}},"required":["serverName"],"additionalProperties":false},{"type":"object","properties":{"serverCommand":{"type":"array","items":{"type":"string"},"description":"Exact command and arguments used to start stdio servers"}},"required":["serverCommand"],"additionalProperties":false},{"type":"object","properties":{"serverUrl":{"type":"string","description":"URL pattern for remote servers, supports wildcards (e.g., https://*.example.com/*)"}},"required":["serverUrl"],"additionalProperties":false}]},"description":"Enterprise allowlist of MCP servers that can be used. Applies to all scopes including enterprise servers from managed-mcp.json. If undefined, all servers are allowed. If empty array, no servers are allowed. Denylist takes precedence - if a server is on both lists, it is denied. See https://code.claude.com/docs/en/mcp#restriction-options"},"deniedMcpServers":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"serverName":{"type":"string","pattern":"^[a-zA-Z0-9_-]+$","description":"Name of the MCP server that is explicitly blocked"}},"required":["serverName"],"additionalProperties":false},{"type":"object","properties":{"serverCommand":{"type":"array","items":{"type":"string"},"description":"Exact command and arguments used to start stdio servers"}},"required":["serverCommand"],"additionalProperties":false},{"type":"object","properties":{"serverUrl":{"type":"string","description":"URL pattern for remote servers, supports wildcards (e.g., https://*.example.com/*)"}},"required":["serverUrl"],"additionalProperties":false}]},"description":"Enterprise denylist of MCP servers that are explicitly blocked. If a server is on the denylist, it will be blocked across all scopes including enterprise. Denylist takes precedence over allowlist - if a server is on both lists, it is denied. See https://code.claude.com/docs/en/mcp#restriction-options"},"httpHookAllowedEnvVars":{"type":"array","items":{"type":"string","minLength":1},"description":"Allowlist of environment variable names HTTP hooks may interpolate into headers. When set, each hook's effective allowedEnvVars is the intersection with this list. Undefined = no restriction. Arrays merge across settings sources. See https://code.claude.com/docs/en/settings#hook-configuration","examples":[["MY_TOKEN","HOOK_SECRET"]]},"hooks":{"type":"object","additionalProperties":false,"description":"Custom commands to run before/after tool executions. See https://code.claude.com/docs/en/hooks","examples":[{"PostToolUse":[{"matcher":"Edit|Write","hooks":[{"type":"command","command":"prettier --write","timeout":5}]}]}],"properties":{"PreToolUse":{"type":"array","description":"Hooks that run before tool calls","items":{"$ref":"#/$defs/hookMatcher"}},"PostToolUse":{"type":"array","description":"Hooks that run after tool completion","items":{"$ref":"#/$defs/hookMatcher"}},"PostToolUseFailure":{"type":"array","description":"Hooks that run after a tool fails","items":{"$ref":"#/$defs/hookMatcher"}},"PermissionRequest":{"type":"array","description":"Hooks that run when a permission dialog appears","items":{"$ref":"#/$defs/hookMatcher"}},"Notification":{"type":"array","description":"Hooks that trigger on notifications","items":{"$ref":"#/$defs/hookMatcher"}},"UserPromptSubmit":{"type":"array","description":"Hooks that run when a user submits a prompt","items":{"$ref":"#/$defs/hookMatcher"}},"Stop":{"type":"array","description":"Hooks that run when agents finish responding. Does not run on user interrupt","items":{"$ref":"#/$defs/hookMatcher"}},"SubagentStart":{"type":"array","description":"Hooks that run when a subagent is spawned","items":{"$ref":"#/$defs/hookMatcher"}},"SubagentStop":{"type":"array","description":"Hooks that run when subagents finish responding","items":{"$ref":"#/$defs/hookMatcher"}},"PreCompact":{"type":"array","description":"Hooks that run before the context is compacted","items":{"$ref":"#/$defs/hookMatcher"}},"PostCompact":{"type":"array","description":"Hooks that run after the context is compacted. See https://code.claude.com/docs/en/hooks","items":{"$ref":"#/$defs/hookMatcher"}},"Elicitation":{"type":"array","description":"Hooks that run when an MCP server requests user input during a tool call. See https://code.claude.com/docs/en/hooks","items":{"$ref":"#/$defs/hookMatcher"}},"ElicitationResult":{"type":"array","description":"Hooks that run after a user responds to an MCP elicitation, before the response is sent back to the server. See https://code.claude.com/docs/en/hooks","items":{"$ref":"#/$defs/hookMatcher"}},"TeammateIdle":{"type":"array","description":"Hooks that run when an agent team teammate is about to go idle. Exit code 2 sends feedback and keeps the teammate working. Does not support matchers. Agent teams are experimental. See https://code.claude.com/docs/en/hooks#teammateidle","items":{"$ref":"#/$defs/hookMatcher"}},"TaskCompleted":{"type":"array","description":"Hooks that run when a task is being marked as completed. Exit code 2 prevents completion and sends feedback. Does not support matchers. See https://code.claude.com/docs/en/hooks#taskcompleted","items":{"$ref":"#/$defs/hookMatcher"}},"Setup":{"type":"array","description":"UNDOCUMENTED. Hooks that run during repository initialization (--init, --init-only) or maintenance (--maintenance)","items":{"$ref":"#/$defs/hookMatcher"}},"InstructionsLoaded":{"type":"array","description":"Hooks that run when a CLAUDE.md or .claude/rules/*.md file is loaded into context. Fires at session start and when files are lazily loaded (e.g., nested traversal, path glob match). No decision control; used for audit logging and observability. Does not support matchers. See https://code.claude.com/docs/en/hooks#instructionsloaded","items":{"$ref":"#/$defs/hookMatcher"}},"ConfigChange":{"type":"array","description":"Hooks that run when settings, managed settings, or skill files change during a session. Supports matchers: user_settings, project_settings, local_settings, policy_settings, skills. Command handlers only. Exit code 2 blocks the change (except policy_settings which is audit-only). See https://code.claude.com/docs/en/hooks#configchange","items":{"$ref":"#/$defs/hookMatcher"}},"WorktreeCreate":{"type":"array","description":"Hooks that run when a worktree is created via --worktree or isolation: \\"worktree\\" in subagents. Command handlers only, no matchers. Hook must print absolute path to created worktree on stdout; non-zero exit fails creation. See https://code.claude.com/docs/en/hooks#worktreecreate","items":{"$ref":"#/$defs/hookMatcher"}},"WorktreeRemove":{"type":"array","description":"Hooks that run when a worktree is being removed at session exit or when a subagent finishes. Command handlers only, no matchers. Used for cleanup tasks; cannot block removal. See https://code.claude.com/docs/en/hooks#worktreeremove","items":{"$ref":"#/$defs/hookMatcher"}},"SessionStart":{"type":"array","description":"Hooks that run when a new session starts","items":{"$ref":"#/$defs/hookMatcher"}},"SessionEnd":{"type":"array","description":"Hooks that run when a session ends","items":{"$ref":"#/$defs/hookMatcher"}}}},"disableAllHooks":{"type":"boolean","description":"Disable all hooks and statusLine execution. When true in managed settings, user and project-level disableAllHooks cannot override it. See https://code.claude.com/docs/en/hooks#disable-or-remove-hooks"},"allowedHttpHookUrls":{"type":"array","items":{"type":"string","minLength":1},"description":"Allowlist of URL patterns that HTTP hooks may target. Supports * as a wildcard. When set, hooks with non-matching URLs are blocked. Undefined = no restriction, empty array = block all HTTP hooks. Arrays merge across settings sources. See https://code.claude.com/docs/en/settings#hook-configuration","examples":[["https://hooks.example.com/*","http://localhost:*"]]},"allowManagedHooksOnly":{"type":"boolean","description":"(Managed settings only) Prevent loading of user, project, and plugin hooks. Only allows managed hooks and SDK hooks. See https://code.claude.com/docs/en/settings#hook-configuration"},"allowManagedPermissionRulesOnly":{"type":"boolean","description":"(Managed settings only) Prevent user and project settings from defining allow, ask, or deny permission rules. Only rules in managed settings apply. See https://code.claude.com/docs/en/settings#permission-settings"},"statusLine":{"type":"object","properties":{"type":{"type":"string","description":"The type of status line handler; must be set to \\"command\\" to run a custom shell script that receives JSON session data via stdin.","const":"command"},"command":{"type":"string","description":"A shell command or path to a script that displays session information (context usage, costs, git status, etc.) by reading JSON data from stdin and writing output to stdout. See https://code.claude.com/docs/en/statusline"},"padding":{"type":"number","description":"Optional number of extra horizontal spacing characters added to the status line content; defaults to 0."}},"required":["type","command"],"additionalProperties":false,"description":"Custom status line display configuration. See https://code.claude.com/docs/en/statusline","examples":[{"type":"command","command":"~/.claude/statusline.sh"}]},"fileSuggestion":{"type":"object","properties":{"type":{"type":"string","description":"The type of file suggestion handler; must be set to \\"command\\" to execute a custom shell script that generates file suggestions for the @ file picker.","const":"command"},"command":{"type":"string","description":"Shell command to execute for file suggestions"}},"required":["type","command"],"additionalProperties":false,"description":"Configure a custom script for @ file autocomplete. See https://code.claude.com/docs/en/settings#file-suggestion-settings","examples":[{"type":"command","command":"~/.claude/file-suggestion.sh"}]},"enabledPlugins":{"type":"object","additionalProperties":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"boolean"},{"not":{}}]},"description":"Enabled plugins using plugin-id@marketplace-id format. Example: { \\"formatter@anthropic-tools\\": true }. See https://code.claude.com/docs/en/plugins"},"extraKnownMarketplaces":{"type":"object","additionalProperties":{"type":"object","properties":{"source":{"anyOf":[{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"url"},"url":{"type":"string","format":"uri","description":"Direct URL to marketplace.json file"}},"required":["source","url"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"hostPattern"},"hostPattern":{"type":"string","description":"Git host pattern to trust for repositories in source specifications"}},"required":["source","hostPattern"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"github"},"repo":{"type":"string","description":"GitHub repository in owner/repo format"},"ref":{"type":"string","description":"Git branch or tag to use (e.g., \\"main\\", \\"v1.0.0\\"). Defaults to repository default branch."},"path":{"type":"string","description":"Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"}},"required":["source","repo"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"git"},"url":{"type":"string","pattern":"\\\\.git$","description":"Full git repository URL"},"ref":{"type":"string","description":"Git branch or tag to use (e.g., \\"main\\", \\"v1.0.0\\"). Defaults to repository default branch."},"path":{"type":"string","description":"Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"}},"required":["source","url"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"npm"},"package":{"type":"string","description":"NPM package containing marketplace.json"}},"required":["source","package"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"file"},"path":{"type":"string","description":"Local file path to marketplace.json"}},"required":["source","path"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"directory"},"path":{"type":"string","description":"Local directory containing .claude-plugin/marketplace.json"}},"required":["source","path"],"additionalProperties":false}],"description":"Where to fetch the marketplace from"},"installLocation":{"type":"string","description":"Local cache path where marketplace manifest is stored (auto-generated if not provided)"}},"required":["source"],"additionalProperties":false},"description":"Additional marketplaces to make available for this repository. Typically used in repository .claude/settings.json to ensure team members have required plugin sources. See https://code.claude.com/docs/en/plugin-marketplaces"},"strictKnownMarketplaces":{"type":"array","description":"(Managed settings only) Allowlist of plugin marketplaces users can add. Undefined = no restrictions, empty array = lockdown. Uses exact matching for source specifications. See https://code.claude.com/docs/en/settings#strictknownmarketplaces","items":{"anyOf":[{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"hostPattern"},"hostPattern":{"type":"string","description":"Git host pattern to trust for repositories in source specifications"}},"required":["source","hostPattern"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"github"},"repo":{"type":"string","description":"GitHub repository in owner/repo format"},"ref":{"type":"string","description":"Git branch, tag, or SHA"},"path":{"type":"string","description":"Subdirectory path"}},"required":["source","repo"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"git"},"url":{"type":"string","description":"Full git repository URL"},"ref":{"type":"string","description":"Git branch, tag, or SHA"},"path":{"type":"string","description":"Subdirectory path"}},"required":["source","url"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"url"},"url":{"type":"string","format":"uri","description":"Direct URL to marketplace.json"},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"HTTP headers for authenticated access"}},"required":["source","url"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"npm"},"package":{"type":"string","description":"NPM package name (supports scoped packages)"}},"required":["source","package"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"file"},"path":{"type":"string","description":"Absolute path to marketplace.json file"}},"required":["source","path"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"directory"},"path":{"type":"string","description":"Absolute path to directory containing .claude-plugin/marketplace.json"}},"required":["source","path"],"additionalProperties":false},{"type":"object","properties":{"source":{"type":"string","description":"Identifies the marketplace source type","const":"pathPattern"},"pathPattern":{"type":"string","description":"Regex pattern to match file or directory paths for marketplace sources"}},"required":["source","pathPattern"],"additionalProperties":false}]},"examples":[[{"source":"github","repo":"acme-corp/approved-plugins"},{"source":"npm","package":"@acme-corp/compliance-plugins"}]]},"skippedMarketplaces":{"type":"array","items":{"type":"string","minLength":1},"description":"List of marketplace names the user has chosen not to install when prompted"},"skippedPlugins":{"type":"array","items":{"type":"string","minLength":1},"description":"List of plugin IDs (plugin@marketplace format) the user has chosen not to install when prompted"},"forceLoginMethod":{"type":"string","enum":["claudeai","console"],"description":"Force a specific login method: \\"claudeai\\" for Claude Pro/Max, \\"console\\" for Console billing","examples":["claudeai"]},"forceLoginOrgUUID":{"type":"string","description":"Organization UUID to use for OAuth login","examples":["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"],"minLength":1},"otelHeadersHelper":{"type":"string","description":"Path to a script that outputs OpenTelemetry headers","minLength":1},"outputStyle":{"type":"string","description":"Controls the output style for assistant responses. Built-in styles: default, Explanatory, Learning. Custom styles can be added in ~/.claude/output-styles/ or .claude/output-styles/. See https://code.claude.com/docs/en/output-styles","examples":["default","Explanatory","Learning"],"minLength":1},"skipWebFetchPreflight":{"type":"boolean","description":"Skip the WebFetch blocklist check for enterprise environments with restrictive security policies"},"sandbox":{"type":"object","description":"Sandbox execution configuration. See https://code.claude.com/docs/en/sandboxing","properties":{"network":{"type":"object","description":"Configures network isolation settings for the sandboxed bash environment, including domain restrictions, Unix socket access, and custom proxy configuration.","properties":{"allowUnixSockets":{"type":"array","items":{"type":"string"},"description":"Allow Unix domain sockets for local IPC (SSH agent, Docker, etc.). Provide an array of specific paths. Defaults to blocking if not specified"},"allowLocalBinding":{"type":"boolean","description":"Allow binding to local network addresses (e.g., localhost ports). Defaults to false if not specified"},"httpProxyPort":{"type":"integer","minimum":1,"maximum":65535,"description":"HTTP proxy port to use for network filtering. If not specified, a proxy server will be started automatically"},"socksProxyPort":{"type":"integer","minimum":1,"maximum":65535,"description":"SOCKS proxy port to use for network filtering. If not specified, a proxy server will be started automatically"},"allowAllUnixSockets":{"type":"boolean","description":"Allow all Unix domain socket connections. If true, this overrides allowUnixSockets"},"allowedDomains":{"type":"array","items":{"type":"string","minLength":1},"description":"Allowlist of network domains for sandboxed commands. Supports wildcard patterns like *.example.com"},"allowManagedDomainsOnly":{"type":"boolean","description":"(Managed settings only) Only allowedDomains and WebFetch(domain:...) allow rules from managed settings are respected. User, project, local, and flag settings domains are ignored. Denied domains are still respected from all sources. Non-allowed domains are automatically blocked without user prompts."}},"additionalProperties":false},"ignoreViolations":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"},"description":"List of filesystem paths to ignore sandbox violations for when this command pattern matches"},"description":"Map of command patterns to filesystem paths to ignore violations for. Use \\"*\\" to match all commands"},"excludedCommands":{"type":"array","items":{"type":"string"},"description":"Commands that should never run in the sandbox (e.g., [\\"git\\", \\"docker\\"])"},"autoAllowBashIfSandboxed":{"type":"boolean","description":"Automatically allow bash commands without prompting when they run in the sandbox. Only applies to commands that will run sandboxed.","default":true},"enableWeakerNetworkIsolation":{"type":"boolean","description":"macOS only. Allow access to the system TLS trust service (com.apple.trustd.agent) in the sandbox. Required for Go-based tools like gh, gcloud, and terraform to verify TLS certificates when using httpProxyPort with a MITM proxy and custom CA. Reduces security by opening a potential data exfiltration path. Default: false. See https://code.claude.com/docs/en/settings#sandbox-settings","default":false},"enableWeakerNestedSandbox":{"type":"boolean","description":"Enable weaker sandbox mode for unprivileged docker environments where --proc mounting fails. This significantly reduces the strength of the sandbox and should only be used when this risk is acceptable.Default: false (secure)."},"allowUnsandboxedCommands":{"type":"boolean","description":"Allow commands to run outside the sandbox via the dangerouslyDisableSandbox parameter. When false, the dangerouslyDisableSandbox parameter is completely ignored and all commands must run sandboxed. Default: true."},"enabled":{"type":"boolean","description":"Enable sandboxed bash"},"filesystem":{"type":"object","description":"Filesystem access control for sandboxed commands. See https://code.claude.com/docs/en/sandboxing#filesystem-isolation","properties":{"allowWrite":{"type":"array","items":{"type":"string","minLength":1},"description":"Paths where subprocesses are allowed to write. Supports prefixes: // (absolute), ~/ (home directory), / (relative to settings file), ./ or no prefix (relative path)"},"denyWrite":{"type":"array","items":{"type":"string","minLength":1},"description":"Paths where subprocesses are explicitly denied write access. Takes precedence over allowWrite"},"denyRead":{"type":"array","items":{"type":"string","minLength":1},"description":"Paths where subprocesses are explicitly denied read access"},"allowRead":{"type":"array","items":{"type":"string","minLength":1},"description":"Paths to re-allow reading within denyRead regions. Takes precedence over denyRead for matching paths"},"allowManagedReadPathsOnly":{"type":"boolean","description":"When true (managed settings only), only allowRead paths from managed settings are used"}},"additionalProperties":false}},"additionalProperties":false},"spinnerVerbs":{"type":"object","description":"Customize the verbs shown in spinner progress messages","properties":{"mode":{"type":"string","enum":["append","replace"],"description":"How to combine custom verbs with default spinner verbs: 'append' adds custom verbs to the default list, 'replace' uses only custom verbs"},"verbs":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Custom verbs used in spinner progress text"}},"required":["verbs"],"additionalProperties":false},"spinnerTipsEnabled":{"type":"boolean","description":"Show tips in the spinner while Claude is working. Set to false to disable tips (default: true)","default":true},"spinnerTipsOverride":{"type":"object","description":"Customize the tips displayed in the spinner while Claude is working. See https://code.claude.com/docs/en/settings#available-settings","properties":{"excludeDefault":{"type":"boolean","description":"If true, only show custom tips. If false or absent, custom tips merge with built-in tips","default":false},"tips":{"type":"array","items":{"type":"string","minLength":1},"description":"Custom tip strings to display in the spinner","minItems":1}},"required":["tips"],"additionalProperties":false},"terminalProgressBarEnabled":{"type":"boolean","description":"Enable the terminal progress bar that shows progress in supported terminals like Windows Terminal and iTerm2 (default: true)","default":true},"showTurnDuration":{"type":"boolean","description":"Show turn duration messages after responses (e.g., \\"Cooked for 1m 6s\\"). Set to false to hide these messages (default: true)","default":true},"prefersReducedMotion":{"type":"boolean","description":"Reduce or disable UI animations (spinners, shimmer, flash effects) for accessibility","default":false},"alwaysThinkingEnabled":{"type":"boolean","description":"Enable extended thinking by default for all sessions. Typically configured via the /config command rather than editing directly. See https://code.claude.com/docs/en/common-workflows#use-extended-thinking-thinking-mode"},"companyAnnouncements":{"type":"array","items":{"type":"string","minLength":1},"description":"Company announcements to display at startup (one will be randomly selected if multiple are provided)"},"teammateMode":{"type":"string","enum":["auto","in-process","tmux"],"description":"How agent team teammates display: \\"auto\\" picks split panes in tmux or iTerm2, in-process otherwise. Agent teams are experimental and disabled by default. Enable them by adding CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS to your settings.json or environment. See https://code.claude.com/docs/en/agent-teams","default":"auto"},"worktree":{"type":"object","additionalProperties":false,"description":"Configuration for --worktree sessions. See https://code.claude.com/docs/en/settings","properties":{"sparsePaths":{"type":"array","items":{"type":"string","minLength":1},"description":"Directories to check out in each worktree via git sparse-checkout (cone mode). Only the listed paths are written to disk, which is faster in large monorepos.","examples":[["packages/my-app","shared/utils"]]}}},"pluginTrustMessage":{"type":"string","description":"(Managed settings only) Custom message appended to the plugin trust warning shown before installation. Use to provide organization-specific context about approved plugins. See https://code.claude.com/docs/en/settings#plugin-settings","minLength":1},"pluginConfigs":{"type":"object","additionalProperties":{"type":"object","properties":{"mcpServers":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}},"description":"User configuration values for MCP servers keyed by server name"}},"additionalProperties":false},"description":"Per-plugin configuration including MCP server user configs, keyed by plugin ID (plugin@marketplace format). See https://code.claude.com/docs/en/plugins"},"allowManagedMcpServersOnly":{"type":"boolean","description":"(Managed settings only) Only allowedMcpServers from managed settings are respected. deniedMcpServers still merges from all sources. Users can still add their own MCP servers, but only the admin-defined allowlist applies."},"blockedMarketplaces":{"type":"array","description":"(Managed settings only) Blocklist of marketplace sources. These exact sources are blocked from being added as marketplaces. The check happens before downloading, so blocked sources never touch the filesystem.","items":{"anyOf":[{"type":"object","additionalProperties":false,"properties":{"source":{"type":"string","const":"url","description":"Block marketplace fetched from direct URL"},"url":{"type":"string","format":"uri","description":"Direct URL to marketplace.json file"},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom HTTP headers (e.g., for authentication)"}},"required":["source","url"]},{"type":"object","additionalProperties":false,"properties":{"source":{"type":"string","const":"github","description":"Block marketplace from GitHub repository"},"repo":{"type":"string","description":"GitHub repository in owner/repo format"},"ref":{"type":"string","description":"Git branch or tag to use"},"path":{"type":"string","description":"Path to marketplace.json within repo"}},"required":["source","repo"]},{"type":"object","additionalProperties":false,"properties":{"source":{"type":"string","const":"git","description":"Block marketplace from git repository URL"},"url":{"type":"string","pattern":".*\\\\.git$","description":"Full git repository URL"},"ref":{"type":"string","description":"Git branch or tag to use"},"path":{"type":"string","description":"Path to marketplace.json within repo"}},"required":["source","url"]},{"type":"object","additionalProperties":false,"properties":{"source":{"type":"string","const":"npm","description":"Block marketplace from NPM package"},"package":{"type":"string","description":"NPM package containing marketplace.json"}},"required":["source","package"]},{"type":"object","additionalProperties":false,"properties":{"source":{"type":"string","const":"file","description":"Block marketplace from local file"},"path":{"type":"string","description":"Local file path to marketplace.json"}},"required":["source","path"]},{"type":"object","additionalProperties":false,"properties":{"source":{"type":"string","const":"directory","description":"Block marketplace from local directory"},"path":{"type":"string","description":"Local directory containing .claude-plugin/marketplace.json"}},"required":["source","path"]},{"type":"object","additionalProperties":false,"properties":{"source":{"type":"string","const":"hostPattern","description":"Block marketplace by host pattern matching"},"hostPattern":{"type":"string","description":"Regex pattern to match the host/domain extracted from any marketplace source type"}},"required":["source","hostPattern"]},{"type":"object","additionalProperties":false,"properties":{"source":{"type":"string","const":"pathPattern","description":"Block marketplace by file/directory path pattern matching"},"pathPattern":{"type":"string","description":"Regex pattern to match file or directory paths for marketplace sources"}},"required":["source","pathPattern"]}]}}}`),Q="Claude Code Settings",ee={$schema:W,$id:K,$defs:J,description:V,allowTrailingCommas:z,additionalProperties:Y,type:Z,properties:X,title:Q};function te(e){const t=e??{},r={...t.$defs??{},...t.definitions??{}},n=s=>{if(!s)return{};if(!s.$ref)return f(s);const a=/^#\/(\$defs|definitions)\/(.+)$/.exec(s.$ref);if(!a)return f(s);const u=r[a[2]];return u?n({...u,...d(s)}):f(s)},m=new Set(["__proto__","constructor","prototype"]),c=s=>{if(!s)return{};const a={};for(const[u,p]of Object.entries(s))m.has(u)||(a[u]=p);return a},f=s=>{if(!s.allOf||s.allOf.length===0)return s;const a={...s};delete a.allOf;for(const u of s.allOf){const p=n(u);Object.assign(a,{properties:{...c(a.properties),...c(p.properties)},required:se([...a.required??[],...p.required??[]])}),!a.description&&p.description&&(a.description=p.description),a.default===void 0&&p.default!==void 0&&(a.default=p.default),!a.type&&p.type&&(a.type=p.type)}return a},d=s=>{const{$ref:a,...u}=s;return u},l=(s,a)=>{let u=n(s);for(const p of a){if(!u)return null;if(/^\d+$/.test(p)){const v=Array.isArray(u.items)?u.items[Number(p)]:u.items;u=v?n(v):null;continue}const k=u.properties;if(k&&!m.has(p)&&p in k){u=n(k[p]);continue}const y=u.additionalProperties;if(y&&typeof y=="object"){u=n(y);continue}return null}return u},g=(s,a,u)=>{if(!s)return null;const p={};if(s.description&&(p.description=s.description),s.type&&(p.type=s.type),s.default!==void 0&&(p.default=s.default),s.enum&&(p.enum=s.enum),s.const!==void 0&&(p.const=s.const),s.deprecated&&(p.deprecated=!0),s.examples&&(p.examples=s.examples),s.properties&&(p.knownChildren=Object.keys(s.properties)),u&&(a!=null&&a.includes(u))&&(p.required=!0),s.items&&!Array.isArray(s.items)){const k=n(s.items),y=g(k,void 0,null);y&&(p.itemsInfo=y)}return(s.additionalProperties===!0||typeof s.additionalProperties=="object")&&(p.open=!0),p},i=s=>a=>{if(a.length===0)return g(n(s),void 0,null);const u=l(s,a.slice(0,-1));if(!u)return null;const p=a[a.length-1],k=l(u,[p]);return g(k,u.required,p)},b=s=>{const a=n(s);return Object.keys(a.properties??{})},h=s=>({at:i(s),rootKeys:()=>b(s),rootedAt:a=>{const u=l(s,a);return h(u??{})}});return h(t)}function se(e){return Array.from(new Set(e))}let A=null;function ce(){return A||(A=te(ee)),A}export{re as E,ce as a,B as g,ne as m,ae as p,G as s,ie as u};
|
|
File without changes
|