@dendelion/paper-camp 0.12.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/assets/index-BMsByqaB.js +3 -0
- package/dist/app/assets/index-BMsByqaB.js.map +1 -0
- package/dist/app/assets/index-Bwc1cGPX.js +6 -0
- package/dist/app/assets/index-Bwc1cGPX.js.map +1 -0
- package/dist/app/assets/index-CQB12bDI.js +2 -0
- package/dist/app/assets/index-CQB12bDI.js.map +1 -0
- package/dist/app/assets/index-D-k_o5eq.js +2 -0
- package/dist/app/assets/index-D-k_o5eq.js.map +1 -0
- package/dist/app/assets/index-D6bamXbC.js +2 -0
- package/dist/app/assets/index-D6bamXbC.js.map +1 -0
- package/dist/app/assets/index-V3ou3lzT.js +4 -0
- package/dist/app/assets/index-V3ou3lzT.js.map +1 -0
- package/dist/app/assets/main-0sfOZaxl.js +207 -0
- package/dist/app/assets/main-0sfOZaxl.js.map +1 -0
- package/dist/app/assets/main-CZ1b3UwB.css +1 -0
- package/dist/app/assets/sidebar-section-DLMrMf9C.js +2 -0
- package/dist/app/assets/sidebar-section-DLMrMf9C.js.map +1 -0
- package/dist/app/assets/tokens-C9JyAXxm.js +2 -0
- package/dist/app/assets/tokens-C9JyAXxm.js.map +1 -0
- package/dist/app/index.html +2 -2
- package/dist/chunks/{scaffold.B_3sY6Rg.js → scaffold.CuJP4koY.js} +1832 -1914
- package/dist/chunks/scaffold.CuJP4koY.js.map +1 -0
- package/dist/cli/index.js +8845 -8571
- package/dist/cli/index.js.map +1 -1
- package/dist/core/git-pr/pr-lookup.d.ts.map +1 -1
- package/dist/core/git-pr/pr.d.ts.map +1 -1
- package/dist/core/index.js +74 -82
- package/dist/core/parse/parser.d.ts +2 -4
- package/dist/core/parse/parser.d.ts.map +1 -1
- package/dist/core/parse/schemas.d.ts +0 -20
- package/dist/core/parse/schemas.d.ts.map +1 -1
- package/dist/core/readers.d.ts.map +1 -1
- package/dist/core/roadmap.d.ts.map +1 -1
- package/dist/core/scaffold/templates.d.ts +1 -1
- package/dist/core/scaffold/templates.d.ts.map +1 -1
- package/dist/core/sections.d.ts +5 -1
- package/dist/core/sections.d.ts.map +1 -1
- package/dist/core/serialize/serializer.d.ts +4 -26
- package/dist/core/serialize/serializer.d.ts.map +1 -1
- package/dist/core/stats.d.ts +10 -0
- package/dist/core/stats.d.ts.map +1 -0
- package/dist/core/stats.test.d.ts +2 -0
- package/dist/core/stats.test.d.ts.map +1 -0
- package/dist/core/status/status.d.ts +1 -0
- package/dist/core/status/status.d.ts.map +1 -1
- package/dist/core/thread.d.ts +15 -0
- package/dist/core/thread.d.ts.map +1 -0
- package/dist/types/index.d.ts +92 -45
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +9 -4
- package/dist/app/assets/index-B6eOrr41.js +0 -4
- package/dist/app/assets/index-B6eOrr41.js.map +0 -1
- package/dist/app/assets/index-BajRXbXg.js +0 -2
- package/dist/app/assets/index-BajRXbXg.js.map +0 -1
- package/dist/app/assets/index-DAexv1XS.js +0 -3
- package/dist/app/assets/index-DAexv1XS.js.map +0 -1
- package/dist/app/assets/index-DFJlDY3W.js +0 -2
- package/dist/app/assets/index-DFJlDY3W.js.map +0 -1
- package/dist/app/assets/main-Bno8vU-0.js +0 -288
- package/dist/app/assets/main-Bno8vU-0.js.map +0 -1
- package/dist/app/assets/main-RP3LpwgH.css +0 -1
- package/dist/app/assets/sidebar-section-BrJbBK_b.js +0 -2
- package/dist/app/assets/sidebar-section-BrJbBK_b.js.map +0 -1
- package/dist/chunks/scaffold.B_3sY6Rg.js.map +0 -1
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as p,g as G,j as e,s as n,i as z,O as N,p as P,Z as T,k,m as $,n as V,q as se,b as v,t as te,v as R,w as ne,x as ae,a as Z,y as X,P as ie,z as le,X as O,c as oe,D,A as re,B as L,Y as _,C as ce,E as de,o as M}from"./main-Bno8vU-0.js";import{S as W}from"./sidebar-section-BrJbBK_b.js";const me=async()=>{try{const s=await fetch("/api/merge-policy");return s.ok?await s.json():null}catch{return null}},pe=async()=>{try{const s=await fetch("/api/merge-policy/apply",{method:"POST"});return s.ok?await s.json():null}catch{return null}},K={allowSquashMerge:!0,allowMergeCommit:!1,allowRebaseMerge:!1,squashMergeCommitTitle:"PR_TITLE",squashMergeCommitMessage:"PR_BODY"},U=[{key:"allowSquashMerge",label:"Allow squash merge"},{key:"allowMergeCommit",label:"Allow merge commit"},{key:"allowRebaseMerge",label:"Allow rebase merge"},{key:"squashMergeCommitTitle",label:"Squash commit title"},{key:"squashMergeCommitMessage",label:"Squash commit message"}];function Y(s){return typeof s=="boolean"?s?"Yes":"No":s}function he(s){return U.every(t=>s[t.key]===K[t.key])}const ge=({label:s,current:t,recommended:o,isLast:i})=>{const m=t===o;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingBottom:n[2],paddingTop:n[2]},children:[e.jsx("span",{style:{flex:1},children:s}),e.jsx("span",{style:{opacity:m?.65:1,fontWeight:m?400:600},children:Y(t)}),!m&&e.jsxs("span",{style:{opacity:.45},children:["→ ",Y(o)]})]}),!i&&e.jsx(k,{})]})},ue=()=>{const[s,t]=p.useState(void 0),[o,i]=p.useState(!1),{toast:m}=G();p.useEffect(()=>{me().then(t)},[]);const g=async()=>{i(!0);const r=await pe();i(!1),(r==null?void 0:r.status)==="ok"?(t(r),m({title:"Merge policy applied",variant:"success"})):m({title:"Failed to apply merge policy",description:(r==null?void 0:r.status)==="unavailable"?r.reason:void 0,variant:"error"})},h=(s==null?void 0:s.status)==="ok"&&he(s.policy);return e.jsxs("div",{children:[e.jsxs("div",{style:{marginBottom:n[6]},children:[e.jsx("h2",{style:{margin:0},children:"Merge Policy"}),e.jsx("p",{style:{opacity:.5,marginTop:n[1]},children:"Paper Camp's canonical policy: squash-only merges, with the commit title and body taken from the PR."})]}),s===void 0&&e.jsx("p",{children:"Loading…"}),s===null&&e.jsx(z,{variant:"warning",children:"Failed to load merge policy."}),(s==null?void 0:s.status)==="unavailable"&&e.jsx(z,{variant:"warning",children:s.reason}),(s==null?void 0:s.status)==="ok"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],marginBottom:n[3]},children:[e.jsx("span",{style:{fontWeight:500},children:s.repo}),e.jsx(N,{size:"small",fillColor:h?"rgba(143, 185, 150, 0.25)":"rgba(212, 163, 115, 0.25)",textColor:h?"#5E8A66":"#A67B4F",children:h?"Matches recommended policy":"Differs from recommended policy"})]}),e.jsx(P,{size:"small",children:U.map((r,y)=>e.jsx(ge,{label:r.label,current:s.policy[r.key],recommended:K[r.key],isLast:y===U.length-1},r.key))}),e.jsx("div",{style:{marginTop:n[4]},children:e.jsx(T,{size:"small",onClick:g,disabled:o||h,children:o?"Applying…":"Apply recommended policy"})})]})]})},xe={ok:{fill:"rgba(143, 185, 150, 0.25)",text:"#5E8A66",label:"Ready"},warn:{fill:"rgba(212, 163, 115, 0.25)",text:"#A67B4F",label:"Needs attention"},missing:{fill:"rgba(201, 139, 139, 0.25)",text:"#6E3A3A",label:"Missing"}},ye=({connection:s,onConnect:t,connecting:o})=>{const{connect:i}=s;return i?i.kind==="command"&&i.runnable?e.jsx(T,{size:"small",variant:"secondary",onClick:()=>t(s.id),disabled:o,children:o?"Running…":`Run \`${i.command}\``}):i.kind==="command"?e.jsx("div",{style:{marginTop:n[2]},children:e.jsx(ne,{code:i.command})}):i.kind==="link"?e.jsx(T,{size:"small",variant:"secondary",onClick:()=>window.open(i.url,"_blank","noopener,noreferrer"),children:i.label}):e.jsx("p",{style:{opacity:.65,fontSize:v.sm,margin:`${n[2]} 0 0`},children:i.message}):null},je=({connection:s,isLast:t,onRecheck:o,rechecking:i,onConnect:m,connecting:g})=>{const h=xe[s.status];return e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{paddingBottom:n[3],paddingTop:n[3]},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3]},children:[e.jsx("span",{style:{flex:1,fontWeight:500},children:s.label}),s.authenticated===!1&&e.jsx(se,{content:"Installed, but not signed in",children:e.jsx(N,{size:"small",variant:"warning",children:"Not signed in"})}),e.jsx(N,{size:"small",fillColor:h.fill,textColor:h.text,children:h.label}),e.jsx(T,{size:"small",variant:"secondary",onClick:()=>o(s.id),disabled:i,children:i?"Checking…":"Recheck"})]}),e.jsxs("p",{style:{opacity:.65,fontSize:v.sm,margin:`${n[1]} 0 0`},children:["Unlocks: ",s.unlocks]}),e.jsx("p",{style:{opacity:.5,fontSize:v.sm,margin:`${n[1]} 0 0`},children:s.detail}),e.jsx("div",{style:{marginTop:n[2]},children:e.jsx(ye,{connection:s,onConnect:m,connecting:g})})]}),!t&&e.jsx(k,{})]})},fe=()=>{const[s,t]=p.useState(null),[o,i]=p.useState(!1),[m,g]=p.useState(null),[h,r]=p.useState(null),[y,w]=p.useState(!1),{toast:S}=G(),b=p.useCallback(l=>{if(l===null){i(!0);return}i(!1),t(l)},[]);p.useEffect(()=>{$().then(b),V().then(l=>w((l==null?void 0:l.setupDismissed)??!1))},[b]);const C=async l=>{g(l),b(await $()),g(null)},d=async l=>{r(l);const j=await te(l);j?t(I=>(I==null?void 0:I.map(a=>a.id===l?j:a))??I):S({title:"Failed to connect",variant:"error"}),r(null)},u=async()=>{const l=!y,{ok:j}=await R({setupDismissed:l});j?(w(l),S({title:"Saved",variant:"success"})):S({title:"Failed to save",variant:"error"})},A=(s==null?void 0:s.every(l=>l.status==="ok"))??!0;return e.jsxs("div",{children:[e.jsx("div",{style:{marginBottom:n[6]},children:e.jsx("h2",{style:{margin:0},children:"Setup"})}),s===null&&!o&&e.jsx("p",{children:"Loading…"}),o&&e.jsx("div",{style:{marginBottom:n[4]},children:e.jsx(z,{variant:"warning",children:"Failed to load connections. Try refreshing."})}),s&&e.jsxs(e.Fragment,{children:[!A&&e.jsx("div",{style:{marginBottom:n[4]},children:e.jsx(z,{variant:"warning",children:"Some connections are incomplete — features that depend on them stay disabled until fixed. Run the connect command below, then recheck."})}),e.jsx(P,{size:"small",children:s.map((l,j)=>e.jsx(je,{connection:l,isLast:j===s.length-1,onRecheck:C,rechecking:m===l.id,onConnect:d,connecting:h===l.id},l.id))}),e.jsx("div",{style:{marginTop:n[4]},children:e.jsx(T,{variant:"secondary",size:"small",onClick:u,children:y?"Show Setup on open again":"Don't show Setup on open"})})]})]})},ve=()=>{const{subjects:s,loading:t,available:o}=ae(),i=Z();return e.jsxs("div",{children:[e.jsxs("div",{style:{marginBottom:n[6]},children:[e.jsx("h2",{style:{margin:0},children:"Subjects"}),e.jsx("p",{style:{opacity:.5,marginTop:n[1]},children:"Subjects are the roadmap's bets and standing concerns. Edit the vocabulary on the Roadmap page."})]}),t&&e.jsx("p",{children:"Loading…"}),!t&&!o&&e.jsx("p",{style:{opacity:.6,margin:0},children:"Couldn't load subjects — check the server config."}),!t&&o&&e.jsxs(P,{size:"small",children:[s.length===0&&e.jsx("p",{style:{opacity:.45,margin:0,paddingBottom:n[2]},children:"No subjects yet."}),s.map((m,g)=>e.jsxs("div",{children:[e.jsx("div",{style:{paddingBottom:n[2],paddingTop:n[2]},children:m}),g<s.length-1&&e.jsx(k,{})]},m)),s.length>0&&e.jsx(k,{}),e.jsx("div",{style:{paddingTop:n[3]},children:e.jsx(T,{variant:"secondary",size:"small",onClick:()=>i({to:"/roadmap"}),children:"Go to Roadmap"})})]})]})},H=["phase","planDraft","ideaExtend","commitSuggest"],Se={phase:"Phase run",planDraft:"Plan draft",ideaExtend:"Idea extend",commitSuggest:"Commit suggest"},J=110,Q=140,q=160,ee=110,be=()=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingBottom:n[1]},children:[e.jsx("span",{style:{width:J,flexShrink:0,fontSize:v.sm,opacity:.45},children:"Task"}),e.jsx("span",{style:{width:Q,flexShrink:0,fontSize:v.sm,opacity:.45},children:"Agent"}),e.jsx("span",{style:{width:q,flexShrink:0,fontSize:v.sm,opacity:.45},children:"Model"}),e.jsx("span",{style:{width:ee,flexShrink:0,fontSize:v.sm,opacity:.45},children:"Effort"})]}),ke=({taskKey:s,agentConfig:t,isLast:o,onSave:i})=>{const m=L[t.agent]??L["claude-code"],g=m.model,h=m.effort,[r,y]=p.useState(t.model??"");p.useEffect(()=>{y(t.model??"")},[t.model]);const w=d=>{var j;const u=d,A=L[u],l={agent:u};t.model&&(A.model===null||(j=A.model)!=null&&j.includes(t.model))&&(l.model=t.model),t.effort&&Array.isArray(A.effort)&&(l.effort=t.effort),i(s,l)},S=d=>{i(s,{...t,model:d||void 0})},b=()=>{i(s,{...t,model:r||void 0})},C=d=>{i(s,{...t,effort:d||void 0})};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingBottom:n[2],paddingTop:n[2]},children:[e.jsx("span",{style:{width:J,flexShrink:0,fontSize:v.sm,opacity:.65},children:Se[s]}),e.jsx(_,{size:"small",width:Q,value:t.agent,onChange:w,options:ce.map(d=>({value:d,label:de[d]}))}),Array.isArray(g)?e.jsx(_,{size:"small",width:q,value:t.model??"",onChange:S,options:[{value:"",label:"Default"},...g.map(d=>({value:d,label:d}))]}):g===null?e.jsx(O,{size:"small",style:{width:q},value:r,placeholder:"Default model",onChange:d=>y(d.target.value),onBlur:b}):null,e.jsx("div",{style:{visibility:Array.isArray(h)?"visible":"hidden"},children:e.jsx(_,{size:"small",width:ee,value:t.effort??"",onChange:C,options:[{value:"",label:"Default"},...(Array.isArray(h)?h:[]).map(d=>({value:d,label:d}))]})})]}),!o&&e.jsx(k,{})]})},we=()=>{const s=p.useRef(null),[t,o]=p.useState(void 0),{iconDataUri:i,loading:m}=le(),[g,h]=p.useState(null),r=g??i,[y,w]=p.useState(!1),[S,b]=p.useState(""),[C,d]=p.useState(""),{toast:u}=G();p.useEffect(()=>{V().then(a=>{o(a),(a==null?void 0:a.port)!==void 0&&b(String(a.port)),(a==null?void 0:a.projectName)!==void 0&&d(a.projectName)})},[]);const A=async(a,f)=>{const c=t==null?void 0:t.defaultAgents,x={phase:(c==null?void 0:c.phase)??D.phase,planDraft:(c==null?void 0:c.planDraft)??D.planDraft,ideaExtend:(c==null?void 0:c.ideaExtend)??D.ideaExtend,commitSuggest:(c==null?void 0:c.commitSuggest)??D.commitSuggest,[a]:f},{ok:E,error:B}=await R({defaultAgents:x});E?(o(F=>F&&{...F,defaultAgents:x}),u({title:"Saved",variant:"success"})):u({title:"Failed to save",description:B,variant:"error"})},l=async()=>{const a=Number(S);if(!t||!Number.isInteger(a)||a<=0||a===t.port)return;const{ok:f,error:c}=await R({port:a});f?(o(x=>x&&{...x,port:a}),u({title:"Saved",variant:"success"})):u({title:"Failed to save",description:c,variant:"error"})},j=async()=>{const a=C.trim();if(!t||!a||a===t.projectName)return;const{ok:f,error:c}=await R({projectName:a});f?(o(x=>x&&{...x,projectName:a}),d(a),u({title:"Saved",variant:"success"})):u({title:"Failed to save",description:c,variant:"error"})},I=async a=>{var x;const f=(x=a.target.files)==null?void 0:x[0];if(!f)return;w(!0);const c=new FileReader;c.onloadend=async()=>{const E=c.result,B=await re(E);w(!1),B?(h(E),u({title:"Saved",variant:"success"})):u({title:"Failed to save",variant:"error"})},c.readAsDataURL(f)};return e.jsxs("div",{children:[e.jsx("div",{style:{marginBottom:n[6]},children:e.jsx("h2",{style:{margin:0},children:"Project Info"})}),t===void 0&&e.jsx("p",{children:"Loading…"}),t===null&&e.jsxs(z,{variant:"warning",children:["No papercamp/config.json found — run ",e.jsx("code",{children:"paper-camp init"})," in this directory first."]}),t&&e.jsxs(P,{size:"small",children:[e.jsxs("div",{style:{display:"flex",alignItems:"flex-end",gap:n[3],paddingBottom:n[3]},children:[e.jsx(O,{value:C,onChange:a=>d(a.target.value),onBlur:j,label:"Project Name"}),e.jsxs(N,{size:"small",fillColor:"rgba(143, 185, 150, 0.25)",textColor:oe.accentGreenDark,children:["v",t.version]})]}),e.jsx(k,{}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingBottom:n[3],paddingTop:n[3]},children:[r&&e.jsx("img",{src:r,alt:"Project icon",style:{width:40,height:40,objectFit:"contain",flexShrink:0,borderRadius:4}}),e.jsxs("div",{children:[e.jsx("input",{ref:s,type:"file",accept:".svg,.png,.jpg,.jpeg,.gif,.webp",onChange:I,style:{display:"none"}}),e.jsx(T,{variant:"secondary",size:"small",onClick:()=>{var a;return(a=s.current)==null?void 0:a.click()},disabled:y,children:y?"Uploading…":"Choose File"}),m&&e.jsx("p",{className:"text-sm",style:{opacity:.5,margin:`${n[1]} 0 0`},children:"Loading…"}),!m&&!r&&!y&&e.jsx("p",{className:"text-sm",style:{opacity:.45,margin:`${n[1]} 0 0`},children:"No icon set."})]})]}),e.jsx(k,{}),e.jsx("div",{style:{display:"flex",alignItems:"flex-end",gap:n[3],paddingBottom:n[3],paddingTop:n[3]},children:e.jsx(O,{type:"number",value:S,onChange:a=>b(a.target.value),onBlur:l,label:"Port",helperText:"Default for `paper-camp dev`. Does not affect the running server."})}),e.jsx(k,{}),e.jsx(be,{}),H.map((a,f)=>{var c;return e.jsx(ke,{taskKey:a,agentConfig:((c=t.defaultAgents)==null?void 0:c[a])??D[a],isLast:f===H.length-1,onSave:A},a)})]}),e.jsxs("p",{style:{opacity:.45,fontSize:v.sm,marginTop:n[4]},children:[e.jsx("strong",{children:"Initialized:"})," ",t?new Date(t.initializedAt).toLocaleString():"—"]})]})},Ce=()=>{const s=X();return e.jsxs("div",{children:[e.jsx(ie,{children:"Settings"}),s==="subjects"?e.jsx(ve,{}):s==="setup"?e.jsx(fe,{}):s==="merge-policy"?e.jsx(ue,{}):e.jsx(we,{})]})},Ie=()=>{const s=X(),t=Z();return e.jsxs(e.Fragment,{children:[e.jsxs(W,{label:"General",children:[e.jsx(M,{size:"small",active:s===null,onClick:()=>t({to:"/settings"}),children:"Project Info"}),e.jsx(M,{size:"small",active:s==="setup",onClick:()=>t({to:"/settings/$section",params:{section:"setup"}}),children:"Setup"}),e.jsx(M,{size:"small",active:s==="merge-policy",onClick:()=>t({to:"/settings/$section",params:{section:"merge-policy"}}),children:"Merge Policy"})]}),e.jsx(W,{label:"Ideas",children:e.jsx(M,{size:"small",active:s==="subjects",onClick:()=>t({to:"/settings/$section",params:{section:"subjects"}}),children:"Subjects"})})]})};export{Ce as SettingsPage,Ie as SettingsSidebar};
|
|
2
|
-
//# sourceMappingURL=index-BajRXbXg.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BajRXbXg.js","sources":["../../../src/app/services/system/merge-policy-api.ts","../../../src/app/features/settings/components/merge-policy-section.tsx","../../../src/app/features/settings/components/setup-section.tsx","../../../src/app/features/settings/components/subjects-section.tsx","../../../src/app/features/settings/settings-page.tsx","../../../src/app/features/settings/components/settings-sidebar.tsx"],"sourcesContent":["import type { MergePolicyResult } from '@/types/index';\n\nexport const fetchMergePolicy = async (): Promise<MergePolicyResult | null> => {\n try {\n const response = await fetch('/api/merge-policy');\n if (!response.ok) return null;\n return (await response.json()) as MergePolicyResult;\n } catch {\n return null;\n }\n};\n\nexport const applyMergePolicy = async (): Promise<MergePolicyResult | null> => {\n try {\n const response = await fetch('/api/merge-policy/apply', { method: 'POST' });\n if (!response.ok) return null;\n return (await response.json()) as MergePolicyResult;\n } catch {\n return null;\n }\n};\n","import { applyMergePolicy, fetchMergePolicy } from '@/app/services/system';\nimport { space } from '@/app/styles/tokens';\nimport type { MergePolicy, MergePolicyResult } from '@/types/index';\nimport { Alert, Button, Card, Divider, Stamp, useToast } from '@dendelion/paper-ui';\nimport { useEffect, useState } from 'react';\n\nconst RECOMMENDED: MergePolicy = {\n allowSquashMerge: true,\n allowMergeCommit: false,\n allowRebaseMerge: false,\n squashMergeCommitTitle: 'PR_TITLE',\n squashMergeCommitMessage: 'PR_BODY',\n};\n\nconst POLICY_ROWS: { key: keyof MergePolicy; label: string }[] = [\n { key: 'allowSquashMerge', label: 'Allow squash merge' },\n { key: 'allowMergeCommit', label: 'Allow merge commit' },\n { key: 'allowRebaseMerge', label: 'Allow rebase merge' },\n { key: 'squashMergeCommitTitle', label: 'Squash commit title' },\n { key: 'squashMergeCommitMessage', label: 'Squash commit message' },\n];\n\nfunction formatValue(value: boolean | string): string {\n return typeof value === 'boolean' ? (value ? 'Yes' : 'No') : value;\n}\n\nfunction matchesRecommended(policy: MergePolicy): boolean {\n return POLICY_ROWS.every((row) => policy[row.key] === RECOMMENDED[row.key]);\n}\n\ninterface PolicyRowProps {\n label: string;\n current: boolean | string;\n recommended: boolean | string;\n isLast: boolean;\n}\n\nconst PolicyRow = ({ label, current, recommended, isLast }: PolicyRowProps) => {\n const matches = current === recommended;\n return (\n <>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[3],\n paddingBottom: space[2],\n paddingTop: space[2],\n }}\n >\n <span style={{ flex: 1 }}>{label}</span>\n <span style={{ opacity: matches ? 0.65 : 1, fontWeight: matches ? 400 : 600 }}>\n {formatValue(current)}\n </span>\n {!matches && <span style={{ opacity: 0.45 }}>→ {formatValue(recommended)}</span>}\n </div>\n {!isLast && <Divider />}\n </>\n );\n};\n\nexport const MergePolicySection = () => {\n const [result, setResult] = useState<MergePolicyResult | null | undefined>(undefined);\n const [applying, setApplying] = useState(false);\n const { toast } = useToast();\n\n useEffect(() => {\n fetchMergePolicy().then(setResult);\n }, []);\n\n const handleApply = async () => {\n setApplying(true);\n const applied = await applyMergePolicy();\n setApplying(false);\n if (applied?.status === 'ok') {\n setResult(applied);\n toast({ title: 'Merge policy applied', variant: 'success' });\n } else {\n toast({\n title: 'Failed to apply merge policy',\n description: applied?.status === 'unavailable' ? applied.reason : undefined,\n variant: 'error',\n });\n }\n };\n\n const upToDate = result?.status === 'ok' && matchesRecommended(result.policy);\n\n return (\n <div>\n <div style={{ marginBottom: space[6] }}>\n <h2 style={{ margin: 0 }}>Merge Policy</h2>\n <p style={{ opacity: 0.5, marginTop: space[1] }}>\n Paper Camp's canonical policy: squash-only merges, with the commit title and body taken\n from the PR.\n </p>\n </div>\n {result === undefined && <p>Loading…</p>}\n {result === null && <Alert variant=\"warning\">Failed to load merge policy.</Alert>}\n {result?.status === 'unavailable' && <Alert variant=\"warning\">{result.reason}</Alert>}\n {result?.status === 'ok' && (\n <>\n <div\n style={{ display: 'flex', alignItems: 'center', gap: space[3], marginBottom: space[3] }}\n >\n <span style={{ fontWeight: 500 }}>{result.repo}</span>\n <Stamp\n size=\"small\"\n fillColor={upToDate ? 'rgba(143, 185, 150, 0.25)' : 'rgba(212, 163, 115, 0.25)'}\n textColor={upToDate ? '#5E8A66' : '#A67B4F'}\n >\n {upToDate ? 'Matches recommended policy' : 'Differs from recommended policy'}\n </Stamp>\n </div>\n <Card size=\"small\">\n {POLICY_ROWS.map((row, idx) => (\n <PolicyRow\n key={row.key}\n label={row.label}\n current={result.policy[row.key]}\n recommended={RECOMMENDED[row.key]}\n isLast={idx === POLICY_ROWS.length - 1}\n />\n ))}\n </Card>\n <div style={{ marginTop: space[4] }}>\n <Button size=\"small\" onClick={handleApply} disabled={applying || upToDate}>\n {applying ? 'Applying…' : 'Apply recommended policy'}\n </Button>\n </div>\n </>\n )}\n </div>\n );\n};\n","import { connectService, fetchConfig, fetchConnections, saveConfig } from '@/app/services/system';\nimport { fontSize, space } from '@/app/styles/tokens';\nimport type { CapabilityStatus, ConnectionResult } from '@/types/index';\nimport {\n Alert,\n Button,\n Card,\n CodeBlock,\n Divider,\n Stamp,\n Tooltip,\n useToast,\n} from '@dendelion/paper-ui';\nimport { useCallback, useEffect, useState } from 'react';\n\nconst STATUS_STAMP: Record<CapabilityStatus, { fill: string; text: string; label: string }> = {\n ok: { fill: 'rgba(143, 185, 150, 0.25)', text: '#5E8A66', label: 'Ready' },\n warn: { fill: 'rgba(212, 163, 115, 0.25)', text: '#A67B4F', label: 'Needs attention' },\n missing: { fill: 'rgba(201, 139, 139, 0.25)', text: '#6E3A3A', label: 'Missing' },\n};\n\nconst ConnectActionView = ({\n connection,\n onConnect,\n connecting,\n}: {\n connection: ConnectionResult;\n onConnect: (id: string) => void;\n connecting: boolean;\n}) => {\n const { connect } = connection;\n if (!connect) return null;\n if (connect.kind === 'command' && connect.runnable) {\n return (\n <Button\n size=\"small\"\n variant=\"secondary\"\n onClick={() => onConnect(connection.id)}\n disabled={connecting}\n >\n {connecting ? 'Running…' : `Run \\`${connect.command}\\``}\n </Button>\n );\n }\n if (connect.kind === 'command') {\n return (\n <div style={{ marginTop: space[2] }}>\n <CodeBlock code={connect.command} />\n </div>\n );\n }\n if (connect.kind === 'link') {\n return (\n <Button\n size=\"small\"\n variant=\"secondary\"\n onClick={() => window.open(connect.url, '_blank', 'noopener,noreferrer')}\n >\n {connect.label}\n </Button>\n );\n }\n return (\n <p style={{ opacity: 0.65, fontSize: fontSize.sm, margin: `${space[2]} 0 0` }}>\n {connect.message}\n </p>\n );\n};\n\nconst ConnectionRow = ({\n connection,\n isLast,\n onRecheck,\n rechecking,\n onConnect,\n connecting,\n}: {\n connection: ConnectionResult;\n isLast: boolean;\n onRecheck: (id: string) => void;\n rechecking: boolean;\n onConnect: (id: string) => void;\n connecting: boolean;\n}) => {\n const stamp = STATUS_STAMP[connection.status];\n return (\n <>\n <div style={{ paddingBottom: space[3], paddingTop: space[3] }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: space[3] }}>\n <span style={{ flex: 1, fontWeight: 500 }}>{connection.label}</span>\n {connection.authenticated === false && (\n <Tooltip content=\"Installed, but not signed in\">\n <Stamp size=\"small\" variant=\"warning\">\n Not signed in\n </Stamp>\n </Tooltip>\n )}\n <Stamp size=\"small\" fillColor={stamp.fill} textColor={stamp.text}>\n {stamp.label}\n </Stamp>\n <Button\n size=\"small\"\n variant=\"secondary\"\n onClick={() => onRecheck(connection.id)}\n disabled={rechecking}\n >\n {rechecking ? 'Checking…' : 'Recheck'}\n </Button>\n </div>\n <p style={{ opacity: 0.65, fontSize: fontSize.sm, margin: `${space[1]} 0 0` }}>\n Unlocks: {connection.unlocks}\n </p>\n <p style={{ opacity: 0.5, fontSize: fontSize.sm, margin: `${space[1]} 0 0` }}>\n {connection.detail}\n </p>\n <div style={{ marginTop: space[2] }}>\n <ConnectActionView\n connection={connection}\n onConnect={onConnect}\n connecting={connecting}\n />\n </div>\n </div>\n {!isLast && <Divider />}\n </>\n );\n};\n\nexport const SetupSection = () => {\n const [connections, setConnections] = useState<ConnectionResult[] | null>(null);\n const [loadFailed, setLoadFailed] = useState(false);\n const [reloadingId, setReloadingId] = useState<string | null>(null);\n const [connectingId, setConnectingId] = useState<string | null>(null);\n const [setupDismissed, setSetupDismissed] = useState(false);\n const { toast } = useToast();\n\n const applyConnections = useCallback((result: ConnectionResult[] | null) => {\n if (result === null) {\n setLoadFailed(true);\n return;\n }\n setLoadFailed(false);\n setConnections(result);\n }, []);\n\n useEffect(() => {\n fetchConnections().then(applyConnections);\n fetchConfig().then((c) => setSetupDismissed(c?.setupDismissed ?? false));\n }, [applyConnections]);\n\n const handleRecheck = async (id: string) => {\n setReloadingId(id);\n applyConnections(await fetchConnections());\n setReloadingId(null);\n };\n\n const handleConnect = async (id: string) => {\n setConnectingId(id);\n const updated = await connectService(id);\n if (updated) {\n setConnections((prev) => prev?.map((c) => (c.id === id ? updated : c)) ?? prev);\n } else {\n toast({ title: 'Failed to connect', variant: 'error' });\n }\n setConnectingId(null);\n };\n\n const handleDismissToggle = async () => {\n const next = !setupDismissed;\n const { ok } = await saveConfig({ setupDismissed: next });\n if (ok) {\n setSetupDismissed(next);\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', variant: 'error' });\n }\n };\n\n const allOk = connections?.every((c) => c.status === 'ok') ?? true;\n\n return (\n <div>\n <div style={{ marginBottom: space[6] }}>\n <h2 style={{ margin: 0 }}>Setup</h2>\n </div>\n {connections === null && !loadFailed && <p>Loading…</p>}\n {loadFailed && (\n <div style={{ marginBottom: space[4] }}>\n <Alert variant=\"warning\">Failed to load connections. Try refreshing.</Alert>\n </div>\n )}\n {connections && (\n <>\n {!allOk && (\n <div style={{ marginBottom: space[4] }}>\n <Alert variant=\"warning\">\n Some connections are incomplete — features that depend on them stay disabled until\n fixed. Run the connect command below, then recheck.\n </Alert>\n </div>\n )}\n <Card size=\"small\">\n {connections.map((c, idx) => (\n <ConnectionRow\n key={c.id}\n connection={c}\n isLast={idx === connections.length - 1}\n onRecheck={handleRecheck}\n rechecking={reloadingId === c.id}\n onConnect={handleConnect}\n connecting={connectingId === c.id}\n />\n ))}\n </Card>\n <div style={{ marginTop: space[4] }}>\n <Button variant=\"secondary\" size=\"small\" onClick={handleDismissToggle}>\n {setupDismissed ? 'Show Setup on open again' : \"Don't show Setup on open\"}\n </Button>\n </div>\n </>\n )}\n </div>\n );\n};\n","import { useSubjectVocabulary } from '@/app/hooks';\nimport { space } from '@/app/styles/tokens';\nimport { Button, Card, Divider } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\n\nexport const SubjectsSection = () => {\n const { subjects, loading, available } = useSubjectVocabulary();\n const navigate = useNavigate();\n\n return (\n <div>\n <div style={{ marginBottom: space[6] }}>\n <h2 style={{ margin: 0 }}>Subjects</h2>\n <p style={{ opacity: 0.5, marginTop: space[1] }}>\n Subjects are the roadmap's bets and standing concerns. Edit the vocabulary on the Roadmap\n page.\n </p>\n </div>\n {loading && <p>Loading…</p>}\n {!loading && !available && (\n <p style={{ opacity: 0.6, margin: 0 }}>Couldn't load subjects — check the server config.</p>\n )}\n {!loading && available && (\n <Card size=\"small\">\n {subjects.length === 0 && (\n <p style={{ opacity: 0.45, margin: 0, paddingBottom: space[2] }}>No subjects yet.</p>\n )}\n {subjects.map((name, idx) => (\n <div key={name}>\n <div style={{ paddingBottom: space[2], paddingTop: space[2] }}>{name}</div>\n {idx < subjects.length - 1 && <Divider />}\n </div>\n ))}\n {subjects.length > 0 && <Divider />}\n <div style={{ paddingTop: space[3] }}>\n <Button variant=\"secondary\" size=\"small\" onClick={() => navigate({ to: '/roadmap' })}>\n Go to Roadmap\n </Button>\n </div>\n </Card>\n )}\n </div>\n );\n};\n","import { PageTitle } from '@/app/components/page-title';\nimport { useActiveSettingsSection, useProjectIdentity } from '@/app/hooks';\nimport { fetchConfig, saveConfig, uploadIcon } from '@/app/services/system';\nimport { color, fontFamily, fontSize, space } from '@/app/styles/tokens';\nimport {\n AGENT_IDS,\n AGENT_LABELS,\n AGENT_OPTIONS,\n type AgentConfig,\n type AgentId,\n DEFAULT_AGENTS,\n type DefaultAgentsMap,\n type PaperCampConfig,\n} from '@/types/index';\nimport { Alert, Button, Card, Divider, Input, Select, Stamp, useToast } from '@dendelion/paper-ui';\nimport { useEffect, useRef, useState } from 'react';\nimport { MergePolicySection } from './components/merge-policy-section';\nimport { SetupSection } from './components/setup-section';\nimport { SubjectsSection } from './components/subjects-section';\n\nconst TASK_TYPE_KEYS = ['phase', 'planDraft', 'ideaExtend', 'commitSuggest'] as const;\ntype TaskTypeKey = (typeof TASK_TYPE_KEYS)[number];\n\nconst TASK_TYPE_LABELS: Record<TaskTypeKey, string> = {\n phase: 'Phase run',\n planDraft: 'Plan draft',\n ideaExtend: 'Idea extend',\n commitSuggest: 'Commit suggest',\n};\n\ninterface AgentTaskRowProps {\n taskKey: TaskTypeKey;\n agentConfig: AgentConfig;\n isLast: boolean;\n onSave: (key: TaskTypeKey, config: AgentConfig) => Promise<void>;\n}\n\nconst TASK_COLUMN_WIDTH = 110;\nconst AGENT_COLUMN_WIDTH = 140;\nconst MODEL_COLUMN_WIDTH = 160;\nconst EFFORT_COLUMN_WIDTH = 110;\n\nconst AgentTaskRowHeader = () => (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[3],\n paddingBottom: space[1],\n }}\n >\n <span style={{ width: TASK_COLUMN_WIDTH, flexShrink: 0, fontSize: fontSize.sm, opacity: 0.45 }}>\n Task\n </span>\n <span\n style={{ width: AGENT_COLUMN_WIDTH, flexShrink: 0, fontSize: fontSize.sm, opacity: 0.45 }}\n >\n Agent\n </span>\n <span\n style={{ width: MODEL_COLUMN_WIDTH, flexShrink: 0, fontSize: fontSize.sm, opacity: 0.45 }}\n >\n Model\n </span>\n <span\n style={{ width: EFFORT_COLUMN_WIDTH, flexShrink: 0, fontSize: fontSize.sm, opacity: 0.45 }}\n >\n Effort\n </span>\n </div>\n);\n\nconst AgentTaskRow = ({ taskKey, agentConfig, isLast, onSave }: AgentTaskRowProps) => {\n // Fall back if the config carries an unknown agent id — never white-screen the page.\n const opts = AGENT_OPTIONS[agentConfig.agent] ?? AGENT_OPTIONS['claude-code'];\n const modelOpts = opts.model;\n const effortOpts = opts.effort;\n const [localModel, setLocalModel] = useState(agentConfig.model ?? '');\n\n useEffect(() => {\n setLocalModel(agentConfig.model ?? '');\n }, [agentConfig.model]);\n\n const handleAgentChange = (v: string) => {\n const newId = v as AgentId;\n const newOpts = AGENT_OPTIONS[newId];\n const newConfig: AgentConfig = { agent: newId };\n // Only carry the model over if the new agent accepts it — otherwise a claude\n // model like 'opus' would leak into opencode and fail at launch.\n if (\n agentConfig.model &&\n (newOpts.model === null || newOpts.model?.includes(agentConfig.model))\n ) {\n newConfig.model = agentConfig.model;\n }\n if (agentConfig.effort && Array.isArray(newOpts.effort)) newConfig.effort = agentConfig.effort;\n onSave(taskKey, newConfig);\n };\n\n const handleModelSelectChange = (v: string) => {\n onSave(taskKey, { ...agentConfig, model: v || undefined });\n };\n\n const handleModelInputBlur = () => {\n onSave(taskKey, { ...agentConfig, model: localModel || undefined });\n };\n\n const handleEffortChange = (v: string) => {\n onSave(taskKey, { ...agentConfig, effort: v || undefined });\n };\n\n return (\n <>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[3],\n paddingBottom: space[2],\n paddingTop: space[2],\n }}\n >\n <span\n style={{ width: TASK_COLUMN_WIDTH, flexShrink: 0, fontSize: fontSize.sm, opacity: 0.65 }}\n >\n {TASK_TYPE_LABELS[taskKey]}\n </span>\n <Select\n size=\"small\"\n width={AGENT_COLUMN_WIDTH}\n value={agentConfig.agent}\n onChange={handleAgentChange}\n options={AGENT_IDS.map((id) => ({ value: id, label: AGENT_LABELS[id] }))}\n />\n {Array.isArray(modelOpts) ? (\n <Select\n size=\"small\"\n width={MODEL_COLUMN_WIDTH}\n value={agentConfig.model ?? ''}\n onChange={handleModelSelectChange}\n options={[\n { value: '', label: 'Default' },\n ...modelOpts.map((m) => ({ value: m, label: m })),\n ]}\n />\n ) : modelOpts === null ? (\n <Input\n size=\"small\"\n style={{ width: MODEL_COLUMN_WIDTH }}\n value={localModel}\n placeholder=\"Default model\"\n onChange={(e) => setLocalModel(e.target.value)}\n onBlur={handleModelInputBlur}\n />\n ) : null}\n {/* Reserve the effort slot even when the agent has no effort options, so\n switching agents doesn't change the control count and shift the row. */}\n <div style={{ visibility: Array.isArray(effortOpts) ? 'visible' : 'hidden' }}>\n <Select\n size=\"small\"\n width={EFFORT_COLUMN_WIDTH}\n value={agentConfig.effort ?? ''}\n onChange={handleEffortChange}\n options={[\n { value: '', label: 'Default' },\n ...(Array.isArray(effortOpts) ? effortOpts : []).map((e) => ({ value: e, label: e })),\n ]}\n />\n </div>\n </div>\n {!isLast && <Divider />}\n </>\n );\n};\n\nconst GeneralSection = () => {\n const fileRef = useRef<HTMLInputElement>(null);\n const [config, setConfig] = useState<PaperCampConfig | null | undefined>(undefined);\n const { iconDataUri: fetchedIconDataUri, loading: identityLoading } = useProjectIdentity();\n const [uploadedIconDataUri, setUploadedIconDataUri] = useState<string | null>(null);\n const iconDataUri = uploadedIconDataUri ?? fetchedIconDataUri;\n const [uploading, setUploading] = useState(false);\n const [portInput, setPortInput] = useState('');\n const [nameInput, setNameInput] = useState('');\n const { toast } = useToast();\n\n useEffect(() => {\n fetchConfig().then((c) => {\n setConfig(c);\n if (c?.port !== undefined) setPortInput(String(c.port));\n if (c?.projectName !== undefined) setNameInput(c.projectName);\n });\n }, []);\n\n const handleSaveAgentConfig = async (key: TaskTypeKey, newEntry: AgentConfig) => {\n const current = config?.defaultAgents;\n const updated: DefaultAgentsMap = {\n phase: current?.phase ?? DEFAULT_AGENTS.phase,\n planDraft: current?.planDraft ?? DEFAULT_AGENTS.planDraft,\n ideaExtend: current?.ideaExtend ?? DEFAULT_AGENTS.ideaExtend,\n commitSuggest: current?.commitSuggest ?? DEFAULT_AGENTS.commitSuggest,\n [key]: newEntry,\n };\n const { ok, error } = await saveConfig({ defaultAgents: updated });\n if (ok) {\n setConfig((prev) => (prev ? { ...prev, defaultAgents: updated } : prev));\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', description: error, variant: 'error' });\n }\n };\n\n const handleSavePort = async () => {\n const port = Number(portInput);\n if (!config || !Number.isInteger(port) || port <= 0 || port === config.port) return;\n const { ok, error } = await saveConfig({ port });\n if (ok) {\n setConfig((prev) => (prev ? { ...prev, port } : prev));\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', description: error, variant: 'error' });\n }\n };\n\n const handleSaveName = async () => {\n const projectName = nameInput.trim();\n if (!config || !projectName || projectName === config.projectName) return;\n const { ok, error } = await saveConfig({ projectName });\n if (ok) {\n setConfig((prev) => (prev ? { ...prev, projectName } : prev));\n setNameInput(projectName);\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', description: error, variant: 'error' });\n }\n };\n\n const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n setUploading(true);\n const reader = new FileReader();\n reader.onloadend = async () => {\n const dataUri = reader.result as string;\n const ok = await uploadIcon(dataUri);\n setUploading(false);\n if (ok) {\n setUploadedIconDataUri(dataUri);\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', variant: 'error' });\n }\n };\n reader.readAsDataURL(file);\n };\n\n return (\n <div>\n <div style={{ marginBottom: space[6] }}>\n <h2 style={{ margin: 0 }}>Project Info</h2>\n </div>\n {config === undefined && <p>Loading…</p>}\n {config === null && (\n <Alert variant=\"warning\">\n No papercamp/config.json found — run <code>paper-camp init</code> in this directory first.\n </Alert>\n )}\n {config && (\n <Card size=\"small\">\n <div\n style={{\n display: 'flex',\n alignItems: 'flex-end',\n gap: space[3],\n paddingBottom: space[3],\n }}\n >\n <Input\n value={nameInput}\n onChange={(e) => setNameInput(e.target.value)}\n onBlur={handleSaveName}\n label=\"Project Name\"\n />\n <Stamp\n size=\"small\"\n fillColor=\"rgba(143, 185, 150, 0.25)\"\n textColor={color.accentGreenDark}\n >\n v{config.version}\n </Stamp>\n </div>\n <Divider />\n\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[3],\n paddingBottom: space[3],\n paddingTop: space[3],\n }}\n >\n {iconDataUri && (\n <img\n src={iconDataUri}\n alt=\"Project icon\"\n style={{\n width: 40,\n height: 40,\n objectFit: 'contain',\n flexShrink: 0,\n borderRadius: 4,\n }}\n />\n )}\n <div>\n {/* paper-ui has no file-input component, so this raw input is intentional */}\n <input\n ref={fileRef}\n type=\"file\"\n accept=\".svg,.png,.jpg,.jpeg,.gif,.webp\"\n onChange={handleFile}\n style={{ display: 'none' }}\n />\n <Button\n variant=\"secondary\"\n size=\"small\"\n onClick={() => fileRef.current?.click()}\n disabled={uploading}\n >\n {uploading ? 'Uploading…' : 'Choose File'}\n </Button>\n {identityLoading && (\n <p className=\"text-sm\" style={{ opacity: 0.5, margin: `${space[1]} 0 0` }}>\n Loading…\n </p>\n )}\n {!identityLoading && !iconDataUri && !uploading && (\n <p className=\"text-sm\" style={{ opacity: 0.45, margin: `${space[1]} 0 0` }}>\n No icon set.\n </p>\n )}\n </div>\n </div>\n <Divider />\n\n <div\n style={{\n display: 'flex',\n alignItems: 'flex-end',\n gap: space[3],\n paddingBottom: space[3],\n paddingTop: space[3],\n }}\n >\n <Input\n type=\"number\"\n value={portInput}\n onChange={(e) => setPortInput(e.target.value)}\n onBlur={handleSavePort}\n label=\"Port\"\n helperText=\"Default for `paper-camp dev`. Does not affect the running server.\"\n />\n </div>\n <Divider />\n\n <AgentTaskRowHeader />\n {TASK_TYPE_KEYS.map((key, idx) => (\n <AgentTaskRow\n key={key}\n taskKey={key}\n agentConfig={config.defaultAgents?.[key] ?? DEFAULT_AGENTS[key]}\n isLast={idx === TASK_TYPE_KEYS.length - 1}\n onSave={handleSaveAgentConfig}\n />\n ))}\n </Card>\n )}\n\n <p style={{ opacity: 0.45, fontSize: fontSize.sm, marginTop: space[4] }}>\n <strong>Initialized:</strong>{' '}\n {config ? new Date(config.initializedAt).toLocaleString() : '—'}\n </p>\n </div>\n );\n};\n\nexport const SettingsPage = () => {\n const section = useActiveSettingsSection();\n return (\n <div>\n <PageTitle>Settings</PageTitle>\n {section === 'subjects' ? (\n <SubjectsSection />\n ) : section === 'setup' ? (\n <SetupSection />\n ) : section === 'merge-policy' ? (\n <MergePolicySection />\n ) : (\n <GeneralSection />\n )}\n </div>\n );\n};\n","import { useActiveSettingsSection } from '@/app/hooks';\nimport { ListItem } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { SidebarSection } from '../../plans/components/sidebar-section';\n\nexport const SettingsSidebar = () => {\n const section = useActiveSettingsSection();\n const navigate = useNavigate();\n\n return (\n <>\n <SidebarSection label=\"General\">\n <ListItem\n size=\"small\"\n active={section === null}\n onClick={() => navigate({ to: '/settings' })}\n >\n Project Info\n </ListItem>\n <ListItem\n size=\"small\"\n active={section === 'setup'}\n onClick={() => navigate({ to: '/settings/$section', params: { section: 'setup' } })}\n >\n Setup\n </ListItem>\n <ListItem\n size=\"small\"\n active={section === 'merge-policy'}\n onClick={() =>\n navigate({ to: '/settings/$section', params: { section: 'merge-policy' } })\n }\n >\n Merge Policy\n </ListItem>\n </SidebarSection>\n <SidebarSection label=\"Ideas\">\n <ListItem\n size=\"small\"\n active={section === 'subjects'}\n onClick={() => navigate({ to: '/settings/$section', params: { section: 'subjects' } })}\n >\n Subjects\n </ListItem>\n </SidebarSection>\n </>\n );\n};\n"],"names":["fetchMergePolicy","response","applyMergePolicy","RECOMMENDED","POLICY_ROWS","formatValue","value","matchesRecommended","policy","row","PolicyRow","label","current","recommended","isLast","matches","jsxs","Fragment","space","jsx","Divider","MergePolicySection","result","setResult","useState","applying","setApplying","toast","useToast","useEffect","handleApply","applied","upToDate","Alert","Stamp","Card","idx","Button","STATUS_STAMP","ConnectActionView","connection","onConnect","connecting","connect","CodeBlock","fontSize","ConnectionRow","onRecheck","rechecking","stamp","Tooltip","SetupSection","connections","setConnections","loadFailed","setLoadFailed","reloadingId","setReloadingId","connectingId","setConnectingId","setupDismissed","setSetupDismissed","applyConnections","useCallback","fetchConnections","fetchConfig","c","handleRecheck","id","handleConnect","updated","connectService","prev","handleDismissToggle","next","ok","saveConfig","allOk","SubjectsSection","subjects","loading","available","useSubjectVocabulary","navigate","useNavigate","name","TASK_TYPE_KEYS","TASK_TYPE_LABELS","TASK_COLUMN_WIDTH","AGENT_COLUMN_WIDTH","MODEL_COLUMN_WIDTH","EFFORT_COLUMN_WIDTH","AgentTaskRowHeader","AgentTaskRow","taskKey","agentConfig","onSave","opts","AGENT_OPTIONS","modelOpts","effortOpts","localModel","setLocalModel","handleAgentChange","v","newId","newOpts","newConfig","_a","handleModelSelectChange","handleModelInputBlur","handleEffortChange","Select","AGENT_IDS","AGENT_LABELS","m","Input","e","GeneralSection","fileRef","useRef","config","setConfig","fetchedIconDataUri","identityLoading","useProjectIdentity","uploadedIconDataUri","setUploadedIconDataUri","iconDataUri","uploading","setUploading","portInput","setPortInput","nameInput","setNameInput","handleSaveAgentConfig","key","newEntry","DEFAULT_AGENTS","error","handleSavePort","port","handleSaveName","projectName","handleFile","file","reader","dataUri","uploadIcon","color","SettingsPage","section","useActiveSettingsSection","PageTitle","SettingsSidebar","SidebarSection","ListItem"],"mappings":"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"}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{u as m,F as L,r,j as e,P as T,s as x,p as f,b as g,E as A,f as v,O as D,c as j,G as N,Z as E}from"./main-Bno8vU-0.js";const b={phase:"Phase run",audit:"Audit","batch-reconcile":"Batch reconcile","run-all":"Run all phases",draft:"Draft",extend:"Extend",suggest:"Suggest ideas","commit-suggest":"Commit suggest","overlap-check":"Overlap check",prioritise:"Prioritise queue",sync:"Sync",reconcile:"Reconcile",rework:"Apply notes","fix-review":"Fix review","review-split":"Split review"},h=s=>String(s).padStart(2,"0"),R=s=>{const a=new Date(s);return`${a.getFullYear()}-${h(a.getMonth()+1)}-${h(a.getDate())}`},I=s=>new Date(s).toLocaleDateString(void 0,{weekday:"long",year:"numeric",month:"long",day:"numeric"}),w=s=>{const a=new Date(s);return`${h(a.getHours())}:${h(a.getMinutes())}:${h(a.getSeconds())}`},p={fontSize:g.sm,fontWeight:600,opacity:.6,whiteSpace:"nowrap",overflow:"hidden"},z=({id:s})=>{const[a,l]=r.useState(null),[o,c]=r.useState(!1),[i,u]=r.useState(0);r.useEffect(()=>{let n=!1,d;l(null),c(!1);const y=k=>{N(s).then(S=>{n||l(S.lines??[])}).catch(()=>{if(!n){if(k>0){d=setTimeout(()=>y(k-1),700);return}c(!0),l([])}})};return y(3),()=>{n=!0,d&&clearTimeout(d)}},[s,i]);const t=e.jsx(E,{variant:"ghost",size:"small",onClick:()=>u(n=>n+1),children:"Retry"});return a===null?e.jsx("p",{style:{opacity:.5,margin:0},children:"Loading…"}):o?e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:x[2]},children:[e.jsx("p",{style:{opacity:.5,margin:0},children:"Couldn't load this task's output."}),t]}):a.length===0?e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:x[2]},children:[e.jsx("p",{style:{opacity:.5,margin:0},children:"No output recorded."}),t]}):e.jsx("pre",{style:{fontFamily:v.mono,fontSize:g.xs,margin:0,maxHeight:320,overflowY:"auto",whiteSpace:"pre-wrap"},children:a.join(`
|
|
2
|
-
`)})},C=({size:s=14})=>e.jsx("svg",{width:s,height:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("polyline",{points:"9 18 15 12 9 6"})}),F=({entry:s,highlighted:a})=>{const[l,o]=r.useState(a);r.useEffect(()=>{a&&o(!0)},[a]);const c=()=>o(i=>!i);return e.jsxs("div",{className:a?"task-row-highlighted":void 0,style:{display:"flex",flexDirection:"column",gap:x[1],borderRadius:10},children:[e.jsx("div",{role:"button",tabIndex:0,onClick:c,onKeyDown:i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),c())},style:{cursor:"pointer",borderRadius:10},children:e.jsx(f,{size:"small",texture:"canvas",className:"plan-row-card",children:e.jsxs("div",{className:"task-rows-grid",children:[e.jsx("span",{className:"task-rows-chevron","aria-expanded":l,style:{display:"inline-flex",alignItems:"center",opacity:.5},children:e.jsx(C,{})}),e.jsx("span",{style:{fontWeight:600,whiteSpace:"nowrap",overflow:"hidden"},children:b[s.taskKind]}),e.jsx("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",opacity:.7},children:s.planTitle}),e.jsx("span",{className:"text-sm",style:{opacity:.5,whiteSpace:"nowrap"},children:A[s.agentId]}),e.jsxs("span",{className:"task-rows-cell-time",style:{fontFamily:v.mono,fontSize:g.xs,opacity:.55,whiteSpace:"nowrap"},children:[w(s.startedAt),"–",w(s.endedAt)]}),e.jsx("div",{style:{display:"flex",alignItems:"center"},children:e.jsx(D,{size:"small",fillColor:s.outcome==="done"?"rgba(143, 185, 150, 0.25)":"rgba(201, 139, 139, 0.25)",textColor:s.outcome==="done"?j.accentGreenDark:j.accentRoseDark,children:s.outcome})})]})})}),l&&e.jsx(f,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsx(z,{id:s.id})})]})},$=()=>{const s=m(t=>t.taskLog),a=m(t=>t.taskLogLoading),l=m(t=>t.loadTaskLog),{taskId:o}=L({from:"/tasks"}),c=r.useRef(null);r.useEffect(()=>{l()},[l]),r.useEffect(()=>{var n;if(!o)return;const t=(n=c.current)==null?void 0:n.querySelector(".task-row-highlighted");t==null||t.scrollIntoView({behavior:"smooth",block:"center"})},[o]);const i=[...s].sort((t,n)=>n.endedAt.localeCompare(t.endedAt)),u=[];for(const t of i){const n=R(t.endedAt),d=u.at(-1);(d==null?void 0:d.key)===n?d.entries.push(t):u.push({key:n,entries:[t]})}return e.jsxs("div",{ref:c,children:[e.jsx(T,{children:"Tasks"}),a&&e.jsx("p",{style:{opacity:.5},children:"Loading…"}),!a&&i.length===0&&e.jsx("p",{style:{opacity:.5},children:"No tasks have run yet."}),!a&&i.length>0&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:x[1]},children:[e.jsx(f,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsxs("div",{className:"task-rows-grid",children:[e.jsx("span",{}),e.jsx("span",{style:p,children:"Task"}),e.jsx("span",{style:p,children:"Plan"}),e.jsx("span",{style:p,children:"Agent"}),e.jsx("span",{className:"task-rows-cell-time",style:p,children:"Time"}),e.jsx("span",{style:p,children:"Outcome"})]})}),u.map(t=>e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:x[1]},children:[e.jsx(f,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsx("span",{style:{...p,opacity:.75},children:I(t.entries[0].endedAt)})}),t.entries.map(n=>e.jsx(F,{entry:n,highlighted:n.id===o},n.id))]},t.key))]})]})};export{$ as TasksPage};
|
|
3
|
-
//# sourceMappingURL=index-DAexv1XS.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-DAexv1XS.js","sources":["../../../src/app/features/tasks/tasks-page.tsx"],"sourcesContent":["import { PageTitle } from '@/app/components/page-title';\nimport { fetchTaskLogLines } from '@/app/services/content/docs-api';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { color, fontFamily, fontSize, space } from '@/app/styles/tokens';\nimport { AGENT_LABELS, type TaskKind, type TaskLogEntry } from '@/types/index';\nimport { Button, Card, Stamp } from '@dendelion/paper-ui';\nimport { useSearch } from '@tanstack/react-router';\nimport { useEffect, useRef, useState } from 'react';\n\nconst TASK_KIND_LABELS: Record<TaskKind, string> = {\n phase: 'Phase run',\n audit: 'Audit',\n 'batch-reconcile': 'Batch reconcile',\n 'run-all': 'Run all phases',\n draft: 'Draft',\n extend: 'Extend',\n suggest: 'Suggest ideas',\n 'commit-suggest': 'Commit suggest',\n 'overlap-check': 'Overlap check',\n prioritise: 'Prioritise queue',\n sync: 'Sync',\n reconcile: 'Reconcile',\n rework: 'Apply notes',\n 'fix-review': 'Fix review',\n 'review-split': 'Split review',\n};\n\nconst pad = (n: number) => String(n).padStart(2, '0');\n\nconst dayKey = (iso: string) => {\n const d = new Date(iso);\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n};\n\nconst formatDayHeader = (iso: string) =>\n new Date(iso).toLocaleDateString(undefined, {\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n\nconst formatTime = (iso: string) => {\n const d = new Date(iso);\n return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n};\n\nconst headerLabelStyle: React.CSSProperties = {\n fontSize: fontSize.sm,\n fontWeight: 600,\n opacity: 0.6,\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n};\n\nconst TaskLogLines = ({ id }: { id: string }) => {\n const [lines, setLines] = useState<string[] | null>(null);\n const [failed, setFailed] = useState(false);\n const [attempt, setAttempt] = useState(0);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: attempt is the retry trigger (re-runs the fetch), not a value read in the body.\n useEffect(() => {\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n setLines(null);\n setFailed(false);\n // Auto-retry first (dev server briefly drops requests on hot reload); manual Retry only if it stays down.\n const load = (remaining: number) => {\n fetchTaskLogLines(id)\n .then((data) => {\n if (cancelled) return;\n setLines(data.lines ?? []);\n })\n .catch(() => {\n if (cancelled) return;\n if (remaining > 0) {\n timer = setTimeout(() => load(remaining - 1), 700);\n return;\n }\n // Empty result != failed request: conflating them mislabels a fetch error as \"no output\".\n setFailed(true);\n setLines([]);\n });\n };\n load(3);\n return () => {\n cancelled = true;\n if (timer) clearTimeout(timer);\n };\n }, [id, attempt]);\n\n const retry = (\n <Button variant=\"ghost\" size=\"small\" onClick={() => setAttempt((n) => n + 1)}>\n Retry\n </Button>\n );\n\n if (lines === null) return <p style={{ opacity: 0.5, margin: 0 }}>Loading…</p>;\n if (failed)\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: space[2] }}>\n <p style={{ opacity: 0.5, margin: 0 }}>Couldn't load this task's output.</p>\n {retry}\n </div>\n );\n if (lines.length === 0)\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: space[2] }}>\n <p style={{ opacity: 0.5, margin: 0 }}>No output recorded.</p>\n {retry}\n </div>\n );\n return (\n <pre\n style={{\n fontFamily: fontFamily.mono,\n fontSize: fontSize.xs,\n margin: 0,\n maxHeight: 320,\n overflowY: 'auto',\n whiteSpace: 'pre-wrap',\n }}\n >\n {lines.join('\\n')}\n </pre>\n );\n};\n\nconst ChevronRightIcon = ({ size = 14 }: { size?: number }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n);\n\nconst TaskRow = ({ entry, highlighted }: { entry: TaskLogEntry; highlighted: boolean }) => {\n const [expanded, setExpanded] = useState(highlighted);\n useEffect(() => {\n if (highlighted) setExpanded(true);\n }, [highlighted]);\n const toggle = () => setExpanded((v) => !v);\n\n return (\n <div\n className={highlighted ? 'task-row-highlighted' : undefined}\n style={{ display: 'flex', flexDirection: 'column', gap: space[1], borderRadius: 10 }}\n >\n {/* biome-ignore lint/a11y/useSemanticElements: the clickable row wraps a Card whose block layout a native <button> would break; keyboard toggling is wired on the div. */}\n <div\n role=\"button\"\n tabIndex={0}\n onClick={toggle}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggle();\n }\n }}\n style={{ cursor: 'pointer', borderRadius: 10 }}\n >\n <Card size=\"small\" texture=\"canvas\" className=\"plan-row-card\">\n <div className=\"task-rows-grid\">\n <span\n className=\"task-rows-chevron\"\n aria-expanded={expanded}\n style={{ display: 'inline-flex', alignItems: 'center', opacity: 0.5 }}\n >\n <ChevronRightIcon />\n </span>\n <span style={{ fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden' }}>\n {TASK_KIND_LABELS[entry.taskKind]}\n </span>\n <span\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n opacity: 0.7,\n }}\n >\n {entry.planTitle}\n </span>\n <span className=\"text-sm\" style={{ opacity: 0.5, whiteSpace: 'nowrap' }}>\n {AGENT_LABELS[entry.agentId]}\n </span>\n <span\n className=\"task-rows-cell-time\"\n style={{\n fontFamily: fontFamily.mono,\n fontSize: fontSize.xs,\n opacity: 0.55,\n whiteSpace: 'nowrap',\n }}\n >\n {formatTime(entry.startedAt)}–{formatTime(entry.endedAt)}\n </span>\n <div style={{ display: 'flex', alignItems: 'center' }}>\n <Stamp\n size=\"small\"\n fillColor={\n entry.outcome === 'done'\n ? 'rgba(143, 185, 150, 0.25)'\n : 'rgba(201, 139, 139, 0.25)'\n }\n textColor={entry.outcome === 'done' ? color.accentGreenDark : color.accentRoseDark}\n >\n {entry.outcome}\n </Stamp>\n </div>\n </div>\n </Card>\n </div>\n {expanded && (\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <TaskLogLines id={entry.id} />\n </Card>\n )}\n </div>\n );\n};\n\nexport const TasksPage = () => {\n const taskLog = useAppStore((s) => s.taskLog);\n const taskLogLoading = useAppStore((s) => s.taskLogLoading);\n const loadTaskLog = useAppStore((s) => s.loadTaskLog);\n const { taskId } = useSearch({ from: '/tasks' });\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n loadTaskLog();\n }, [loadTaskLog]);\n\n useEffect(() => {\n if (!taskId) return;\n const row = containerRef.current?.querySelector('.task-row-highlighted');\n row?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }, [taskId]);\n\n const sorted = [...taskLog].sort((a, b) => b.endedAt.localeCompare(a.endedAt));\n\n const groups: { key: string; entries: TaskLogEntry[] }[] = [];\n for (const entry of sorted) {\n const key = dayKey(entry.endedAt);\n const group = groups.at(-1);\n if (group?.key === key) group.entries.push(entry);\n else groups.push({ key, entries: [entry] });\n }\n\n return (\n <div ref={containerRef}>\n <PageTitle>Tasks</PageTitle>\n {taskLogLoading && <p style={{ opacity: 0.5 }}>Loading…</p>}\n {!taskLogLoading && sorted.length === 0 && (\n <p style={{ opacity: 0.5 }}>No tasks have run yet.</p>\n )}\n {!taskLogLoading && sorted.length > 0 && (\n <div style={{ display: 'flex', flexDirection: 'column', gap: space[1] }}>\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <div className=\"task-rows-grid\">\n <span />\n <span style={headerLabelStyle}>Task</span>\n <span style={headerLabelStyle}>Plan</span>\n <span style={headerLabelStyle}>Agent</span>\n <span className=\"task-rows-cell-time\" style={headerLabelStyle}>\n Time\n </span>\n <span style={headerLabelStyle}>Outcome</span>\n </div>\n </Card>\n {groups.map((group) => (\n <div\n key={group.key}\n style={{ display: 'flex', flexDirection: 'column', gap: space[1] }}\n >\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <span style={{ ...headerLabelStyle, opacity: 0.75 }}>\n {formatDayHeader(group.entries[0].endedAt)}\n </span>\n </Card>\n {group.entries.map((entry) => (\n <TaskRow key={entry.id} entry={entry} highlighted={entry.id === taskId} />\n ))}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"names":["TASK_KIND_LABELS","pad","n","dayKey","iso","d","formatDayHeader","formatTime","headerLabelStyle","fontSize","TaskLogLines","id","lines","setLines","useState","failed","setFailed","attempt","setAttempt","useEffect","cancelled","timer","load","remaining","fetchTaskLogLines","data","retry","jsx","Button","jsxs","space","fontFamily","ChevronRightIcon","size","TaskRow","entry","highlighted","expanded","setExpanded","toggle","v","e","Card","AGENT_LABELS","Stamp","color","TasksPage","taskLog","useAppStore","s","taskLogLoading","loadTaskLog","taskId","useSearch","containerRef","useRef","row","_a","sorted","a","b","groups","key","group","PageTitle"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{u as a,a as m,j as e,s as d,Z as j,f as p,d as v,c as S,l as x,b as f,M as b,e as D,h as w,P as T,r as C,X as k,o as L}from"./main-Bno8vU-0.js";import{S as $}from"./sidebar-section-BrJbBK_b.js";const g=(t,r)=>t.toLowerCase().includes(r.toLowerCase()),Q=(t,r,c=120)=>{const l=t.toLowerCase().indexOf(r.toLowerCase());if(l===-1)return t.slice(0,c);const n=Math.max(0,l-40),i=Math.min(t.length,l+r.length+40);let h=t.slice(n,i);return n>0&&(h=`…${h}`),i<t.length&&(h=`${h}…`),h},z=({query:t})=>{const r=a(o=>o.repoDocs),c=a(o=>o.setActiveDocTitle),l=a(o=>o.setDocSearchQuery),n=m(),i=[];for(const o of r)(g(o.name,t)||g(o.content,t))&&i.push({title:o.name,snippet:Q(o.content,t)});const h=o=>{n({to:"/docs/$section",params:{section:"repo-docs"}}),c(o),l("")};return i.length===0?e.jsxs("p",{style:{opacity:.5},children:['No results found for "',t,'".']}):e.jsxs("div",{children:[e.jsxs("p",{className:"text-sm",style:{opacity:.5,marginBottom:d[3]},children:[i.length," result",i.length===1?"":"s",' for "',t,'"']}),e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:d[1]},children:i.map(o=>e.jsx(j,{variant:"ghost",size:"small",fullWidth:!0,onClick:()=>h(o.title),style:{justifyContent:"flex-start",padding:`${d[2]} ${d[3]}`},children:e.jsxs("span",{style:{textAlign:"left"},children:[e.jsx("span",{style:{fontFamily:p.serif,fontWeight:600,fontSize:"0.95rem",display:"block",marginBottom:"0.2rem"},children:o.title}),e.jsx("span",{className:"text-sm",style:{opacity:.6},children:o.snippet})]})},o.title))})]})},A=()=>{const t=a(n=>n.repoDocs),r=a(n=>n.activeDocTitle),c=t.find(n=>n.name===r);if(!c)return null;const l=c.name.endsWith(".md");return e.jsxs("div",{children:[e.jsx("h2",{style:{...v,margin:`0 0 ${d[4]}`},children:c.name}),l?e.jsx("div",{style:{fontFamily:p.body,fontSize:f.base,lineHeight:x.relaxed,color:S.textProse},children:e.jsx(b,{children:c.content})}):e.jsx("pre",{style:{fontFamily:p.mono,fontSize:f.xs,background:"rgba(0,0,0,0.04)",borderRadius:6,padding:d[4],overflowX:"auto",lineHeight:x.normal,whiteSpace:"pre-wrap"},children:c.content})]})},F=()=>{const t=a(i=>i.docSearchQuery),r=a(i=>i.activeDocTitle),c=m(),l=D(),n=()=>c({to:"/docs"});return t.trim()?e.jsx("div",{children:e.jsx(z,{query:t})}):l==="repo-docs"&&r?e.jsxs("div",{children:[e.jsx("div",{style:{marginBottom:d[4]},children:e.jsx(w,{items:[{id:"docs",label:"Docs",onClick:n},{id:"repo-doc",label:r}]})}),e.jsx(A,{})]}):e.jsxs("div",{children:[e.jsx(T,{children:"Docs"}),e.jsx("p",{style:{opacity:.5},children:"Pick a doc from the sidebar — start with a repo doc if you're new here."})]})},R=t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase(),u=({children:t})=>e.jsx("span",{className:"text-sm",style:{display:"block",padding:`${d[1]} ${d[3]}`,opacity:.35,fontStyle:"italic"},children:t}),M=()=>{const t=a(s=>s.repoDocs),r=a(s=>s.repoDocsLoading),c=a(s=>s.loadRepoDocs),l=a(s=>s.activeDocTitle),n=a(s=>s.setActiveDocTitle),i=a(s=>s.docSearchQuery),h=a(s=>s.setDocSearchQuery),o=D(),y=m();return C.useEffect(()=>{c()},[c]),e.jsxs(e.Fragment,{children:[e.jsx("div",{style:{marginBottom:d[4]},children:e.jsx(k,{size:"small","aria-label":"Search docs",placeholder:"Search docs…",value:i,onChange:s=>h(s.target.value)})}),e.jsx($,{label:"Repo Docs",children:r&&t.length===0?e.jsx(u,{children:"Loading…"}):t.length>0?t.map(s=>e.jsx(L,{size:"small",active:o==="repo-docs"&&l===s.name,onClick:()=>{y({to:"/docs/$section",params:{section:"repo-docs"}}),n(s.name)},children:R(s.name)},s.name)):e.jsx(u,{children:"No repo docs found"})})]})};export{F as DocsPage,M as DocsSidebar};
|
|
2
|
-
//# sourceMappingURL=index-DFJlDY3W.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-DFJlDY3W.js","sources":["../../../src/app/features/docs/components/docs-search.tsx","../../../src/app/features/docs/components/repo-doc-detail.tsx","../../../src/app/features/docs/docs-page.tsx","../../../src/app/features/docs/components/docs-sidebar.tsx"],"sourcesContent":["import { useAppStore } from '@/app/stores/app-store';\nimport { fontFamily, space } from '@/app/styles/tokens';\nimport { Button } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\n\ninterface SearchMatch {\n title: string;\n snippet: string;\n}\n\ninterface DocsSearchProps {\n query: string;\n}\n\nconst searchIn = (text: string, query: string): boolean =>\n text.toLowerCase().includes(query.toLowerCase());\n\nconst snippet = (text: string, query: string, maxLen = 120): string => {\n const idx = text.toLowerCase().indexOf(query.toLowerCase());\n if (idx === -1) return text.slice(0, maxLen);\n const start = Math.max(0, idx - 40);\n const end = Math.min(text.length, idx + query.length + 40);\n let s = text.slice(start, end);\n if (start > 0) s = `…${s}`;\n if (end < text.length) s = `${s}…`;\n return s;\n};\n\nexport const DocsSearch = ({ query }: DocsSearchProps) => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const setActiveDocTitle = useAppStore((s) => s.setActiveDocTitle);\n const setDocSearchQuery = useAppStore((s) => s.setDocSearchQuery);\n const navigate = useNavigate();\n\n const results: SearchMatch[] = [];\n\n for (const f of repoDocs) {\n if (searchIn(f.name, query) || searchIn(f.content, query)) {\n results.push({\n title: f.name,\n snippet: snippet(f.content, query),\n });\n }\n }\n\n const handleSelect = (title: string) => {\n navigate({ to: '/docs/$section', params: { section: 'repo-docs' } });\n setActiveDocTitle(title);\n setDocSearchQuery('');\n };\n\n if (results.length === 0) {\n return <p style={{ opacity: 0.5 }}>No results found for \"{query}\".</p>;\n }\n\n return (\n <div>\n <p className=\"text-sm\" style={{ opacity: 0.5, marginBottom: space[3] }}>\n {results.length} result{results.length === 1 ? '' : 's'} for \"{query}\"\n </p>\n <div style={{ display: 'flex', flexDirection: 'column', gap: space[1] }}>\n {results.map((m) => (\n <Button\n key={m.title}\n variant=\"ghost\"\n size=\"small\"\n fullWidth\n onClick={() => handleSelect(m.title)}\n style={{ justifyContent: 'flex-start', padding: `${space[2]} ${space[3]}` }}\n >\n <span style={{ textAlign: 'left' }}>\n <span\n style={{\n fontFamily: fontFamily.serif,\n fontWeight: 600,\n fontSize: '0.95rem',\n display: 'block',\n marginBottom: '0.2rem',\n }}\n >\n {m.title}\n </span>\n <span className=\"text-sm\" style={{ opacity: 0.6 }}>\n {m.snippet}\n </span>\n </span>\n </Button>\n ))}\n </div>\n </div>\n );\n};\n","import { detailHeadingStyle } from '@/app/components/detail-heading-style';\nimport { Markdown } from '@/app/components/markdown';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { color, fontFamily, fontSize, lineHeight, space } from '@/app/styles/tokens';\n\nexport const RepoDocDetail = () => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n\n const file = repoDocs.find((f) => f.name === activeDocTitle);\n if (!file) return null;\n\n const isMarkdown = file.name.endsWith('.md');\n\n return (\n <div>\n <h2 style={{ ...detailHeadingStyle, margin: `0 0 ${space[4]}` }}>{file.name}</h2>\n\n {isMarkdown ? (\n <div\n style={{\n fontFamily: fontFamily.body,\n fontSize: fontSize.base,\n lineHeight: lineHeight.relaxed,\n color: color.textProse,\n }}\n >\n <Markdown>{file.content}</Markdown>\n </div>\n ) : (\n <pre\n style={{\n fontFamily: fontFamily.mono,\n fontSize: fontSize.xs,\n background: 'rgba(0,0,0,0.04)',\n borderRadius: 6,\n padding: space[4],\n overflowX: 'auto',\n lineHeight: lineHeight.normal,\n whiteSpace: 'pre-wrap',\n }}\n >\n {file.content}\n </pre>\n )}\n </div>\n );\n};\n","import { PageTitle } from '@/app/components/page-title';\nimport { useResolvedDocSection } from '@/app/hooks';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { space } from '@/app/styles/tokens';\nimport { Breadcrumb } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { DocsSearch } from './components/docs-search';\nimport { RepoDocDetail } from './components/repo-doc-detail';\n\nexport const DocsPage = () => {\n const docSearchQuery = useAppStore((s) => s.docSearchQuery);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n const navigate = useNavigate();\n const activeDocSection = useResolvedDocSection();\n\n const handleBackToDocs = () => navigate({ to: '/docs' });\n\n if (docSearchQuery.trim()) {\n return (\n <div>\n <DocsSearch query={docSearchQuery} />\n </div>\n );\n }\n\n if (activeDocSection === 'repo-docs' && activeDocTitle) {\n return (\n <div>\n <div style={{ marginBottom: space[4] }}>\n <Breadcrumb\n items={[\n { id: 'docs', label: 'Docs', onClick: handleBackToDocs },\n { id: 'repo-doc', label: activeDocTitle },\n ]}\n />\n </div>\n <RepoDocDetail />\n </div>\n );\n }\n\n return (\n <div>\n <PageTitle>Docs</PageTitle>\n <p style={{ opacity: 0.5 }}>\n Pick a doc from the sidebar — start with a repo doc if you're new here.\n </p>\n </div>\n );\n};\n","import { useResolvedDocSection } from '@/app/hooks';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { space } from '@/app/styles/tokens';\nimport { Input, ListItem } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { useEffect } from 'react';\nimport { SidebarSection } from '../../plans/components/sidebar-section';\n\nconst simplecaseLabel = (name: string) =>\n name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();\n\nconst EmptyState = ({ children }: { children: React.ReactNode }) => (\n <span\n className=\"text-sm\"\n style={{\n display: 'block',\n padding: `${space[1]} ${space[3]}`,\n opacity: 0.35,\n fontStyle: 'italic',\n }}\n >\n {children}\n </span>\n);\n\nexport const DocsSidebar = () => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const repoDocsLoading = useAppStore((s) => s.repoDocsLoading);\n const loadRepoDocs = useAppStore((s) => s.loadRepoDocs);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n const setActiveDocTitle = useAppStore((s) => s.setActiveDocTitle);\n const docSearchQuery = useAppStore((s) => s.docSearchQuery);\n const setDocSearchQuery = useAppStore((s) => s.setDocSearchQuery);\n const activeDocSection = useResolvedDocSection();\n const navigate = useNavigate();\n\n useEffect(() => {\n loadRepoDocs();\n }, [loadRepoDocs]);\n\n return (\n <>\n <div style={{ marginBottom: space[4] }}>\n <Input\n size=\"small\"\n aria-label=\"Search docs\"\n placeholder=\"Search docs…\"\n value={docSearchQuery}\n onChange={(e) => setDocSearchQuery(e.target.value)}\n />\n </div>\n\n <SidebarSection label=\"Repo Docs\">\n {repoDocsLoading && repoDocs.length === 0 ? (\n <EmptyState>Loading…</EmptyState>\n ) : repoDocs.length > 0 ? (\n repoDocs.map((f) => (\n <ListItem\n key={f.name}\n size=\"small\"\n active={activeDocSection === 'repo-docs' && activeDocTitle === f.name}\n onClick={() => {\n navigate({ to: '/docs/$section', params: { section: 'repo-docs' } });\n setActiveDocTitle(f.name);\n }}\n >\n {simplecaseLabel(f.name)}\n </ListItem>\n ))\n ) : (\n <EmptyState>No repo docs found</EmptyState>\n )}\n </SidebarSection>\n </>\n );\n};\n"],"names":["searchIn","text","query","snippet","maxLen","idx","start","end","s","DocsSearch","repoDocs","useAppStore","setActiveDocTitle","setDocSearchQuery","navigate","useNavigate","results","f","handleSelect","title","jsxs","space","m","jsx","Button","fontFamily","RepoDocDetail","activeDocTitle","file","isMarkdown","detailHeadingStyle","fontSize","lineHeight","color","Markdown","DocsPage","docSearchQuery","activeDocSection","useResolvedDocSection","handleBackToDocs","Breadcrumb","PageTitle","simplecaseLabel","name","EmptyState","children","DocsSidebar","repoDocsLoading","loadRepoDocs","useEffect","Fragment","Input","e","SidebarSection","ListItem"],"mappings":"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"}
|