@dendelion/paper-camp 0.11.0 → 0.13.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/app/assets/index-BHrFKlRC.js +2 -0
- package/dist/app/assets/index-BHrFKlRC.js.map +1 -0
- package/dist/app/assets/index-BYaEopge.js +2 -0
- package/dist/app/assets/index-BYaEopge.js.map +1 -0
- package/dist/app/assets/index-CVlBKMF5.js +2 -0
- package/dist/app/assets/index-CVlBKMF5.js.map +1 -0
- package/dist/app/assets/index-DmvGoONp.js +6 -0
- package/dist/app/assets/index-DmvGoONp.js.map +1 -0
- package/dist/app/assets/index-DuSUXl7P.js +3 -0
- package/dist/app/assets/index-DuSUXl7P.js.map +1 -0
- package/dist/app/assets/index-Q6C6X2L9.js +4 -0
- package/dist/app/assets/index-Q6C6X2L9.js.map +1 -0
- package/dist/app/assets/main-CTwMgTvE.js +207 -0
- package/dist/app/assets/main-CTwMgTvE.js.map +1 -0
- package/dist/app/assets/main-CU7SFl1f.css +1 -0
- package/dist/app/assets/sidebar-section-C1uCSbsw.js +2 -0
- package/dist/app/assets/sidebar-section-C1uCSbsw.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/{roadmap.HCld8rN3.js → scaffold.CuJP4koY.js} +2050 -1876
- package/dist/chunks/scaffold.CuJP4koY.js.map +1 -0
- package/dist/cli/index.js +10112 -8165
- 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.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +81 -82
- package/dist/core/parse/parser.d.ts +2 -5
- package/dist/core/parse/parser.d.ts.map +1 -1
- package/dist/core/parse/schemas.d.ts +0 -19
- 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 +5 -1
- package/dist/core/roadmap.d.ts.map +1 -1
- package/dist/core/run-order-file.d.ts +8 -0
- package/dist/core/run-order-file.d.ts.map +1 -0
- package/dist/core/run-order-file.test.d.ts +2 -0
- package/dist/core/run-order-file.test.d.ts.map +1 -0
- package/dist/core/run-order.d.ts +28 -9
- package/dist/core/run-order.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 +7 -1
- package/dist/core/sections.d.ts.map +1 -1
- package/dist/core/serialize/serializer.d.ts +6 -24
- 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/core/trail.d.ts +7 -0
- package/dist/core/trail.d.ts.map +1 -0
- package/dist/core/trail.test.d.ts +2 -0
- package/dist/core/trail.test.d.ts.map +1 -0
- package/dist/types/index.d.ts +235 -29
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +12 -6
- package/dist/app/assets/index-CwotynaS.js +0 -2
- package/dist/app/assets/index-CwotynaS.js.map +0 -1
- package/dist/app/assets/index-DHHPg0hQ.js +0 -4
- package/dist/app/assets/index-DHHPg0hQ.js.map +0 -1
- package/dist/app/assets/index-DyLHu3dg.js +0 -2
- package/dist/app/assets/index-DyLHu3dg.js.map +0 -1
- package/dist/app/assets/index-DzMK8ayh.js +0 -3
- package/dist/app/assets/index-DzMK8ayh.js.map +0 -1
- package/dist/app/assets/main-B7k4s_9g.css +0 -1
- package/dist/app/assets/main-BNLbBO0E.js +0 -233
- package/dist/app/assets/main-BNLbBO0E.js.map +0 -1
- package/dist/app/assets/sidebar-section-DVSoUVEe.js +0 -2
- package/dist/app/assets/sidebar-section-DVSoUVEe.js.map +0 -1
- package/dist/chunks/roadmap.HCld8rN3.js.map +0 -1
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{u as k,t as F,r,g as L,j as e,J as N,s as l,Y as B,b,c as O,Z as v,F as _,G as M,a as G,C as H,H as C,P as A,f as z,M as T,p as D,O as I,S,I as W,X as E,L as q,N as U}from"./main-BNLbBO0E.js";import{Q as de}from"./main-BNLbBO0E.js";const w="__no-subject__",$=({horizonTitle:s,item:t,candidateName:n,onClose:d,onPromoted:c})=>{const x=k(a=>a.promoteRoadmapItem),i=k(a=>a.launchIdeaExtend),{subjects:f}=F(),[p,g]=r.useState(w),[u,y]=r.useState(!1),[j,h]=r.useState(null),{toast:R}=L();r.useEffect(()=>{t&&(g(n?t.name:w),y(!1),h(null))},[t,n]);const o=async()=>{if(!(!t||!s)){y(!0),h(null);try{const a=await x(s,t,p===w?void 0:p,n??void 0),m=k.getState().ideaEntries.find(P=>P.id===a);if(m)try{await i(a,_(m,s))}catch(P){R({title:"Idea created, but the refine agent failed to launch",description:M(P.message),variant:"error"})}c(),d()}catch(a){h(a.message)}finally{y(!1)}}};return e.jsx(N,{open:t!==null,onClose:d,title:n??(t==null?void 0:t.name)??"",size:"small",children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:l[4]},children:[!n&&e.jsx("p",{style:{margin:0,opacity:.8},children:t==null?void 0:t.description}),e.jsx("div",{children:e.jsx(B,{size:"small",value:p,onChange:g,disabled:u,options:[{value:w,label:"No subject"},...f.map(a=>({value:a,label:a}))]})}),j&&e.jsx("p",{style:{margin:0,color:O.accentRoseDark,fontSize:b.sm},children:j}),e.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:l[2]},children:[e.jsx(v,{type:"button",variant:"ghost",onClick:d,disabled:u,children:"Cancel"}),e.jsx(v,{type:"button",variant:"primary",onClick:o,disabled:u,children:u?"Promoting…":"Promote to idea"})]})]})})},J=s=>({shipped:s.filter(t=>t.status==="done").length,queued:s.filter(t=>t.status!=="done"&&t.status!=="dropped").length}),K={fontFamily:z.handwritten,fontSize:b.md,fontWeight:600,opacity:.7,lineHeight:1,padding:`${l[2]} ${l[1]} 0`},V={fontFamily:z.body,fontSize:b["2xs"],fontWeight:400,opacity:.5,padding:`0 ${l[1]}`},X=({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"})}),Y=({name:s,onPromote:t})=>e.jsx(D,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:l[3]},children:[e.jsx("span",{style:{flex:1},children:s}),e.jsx(v,{type:"button",variant:"ghost",size:"small",onClick:t,children:"Promote to idea"})]})}),Z=({onAdd:s})=>{const[t,n]=r.useState(""),[d,c]=r.useState(!1),x=async()=>{if(t.trim()){c(!0);try{await s(t.trim()),n("")}finally{c(!1)}}};return e.jsxs("div",{style:{display:"flex",gap:l[2]},children:[e.jsx(E,{size:"small",value:t,onChange:i=>n(i.target.value),onKeyDown:i=>{i.key==="Enter"&&x()},placeholder:"Add candidate…",disabled:d,style:{flex:1}}),e.jsx(v,{type:"button",variant:"ghost",size:"small",onClick:x,disabled:d||!t.trim(),children:"Add"})]})},Q=({onAdd:s})=>{const[t,n]=r.useState(!1),[d,c]=r.useState(""),[x,i]=r.useState(""),[f,p]=r.useState(!1),g=async()=>{if(d.trim()){p(!0);try{await s(d.trim(),x.trim()),c(""),i(""),n(!1)}finally{p(!1)}}};return t?e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:l[2]},children:[e.jsx(E,{size:"small",value:d,onChange:u=>c(u.target.value),placeholder:"Item name…",disabled:f,autoFocus:!0}),e.jsx(E,{size:"small",value:x,onChange:u=>i(u.target.value),onKeyDown:u=>{u.key==="Enter"&&g()},placeholder:"Description…",disabled:f}),e.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:l[2]},children:[e.jsx(v,{type:"button",variant:"ghost",size:"small",onClick:()=>n(!1),disabled:f,children:"Cancel"}),e.jsx(v,{type:"button",variant:"secondary",size:"small",onClick:g,disabled:f||!d.trim(),children:"Add"})]})]}):e.jsx(v,{type:"button",variant:"ghost",size:"small",onClick:()=>n(!0),children:"+ Add item"})},ee=({plan:s,onOpen:t})=>e.jsx(D,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsxs("button",{type:"button",onClick:t,style:{display:"flex",alignItems:"center",gap:l[3],width:"100%",background:"none",border:"none",padding:0,cursor:"pointer",font:"inherit",color:"inherit",textAlign:"left"},children:[e.jsx("span",{style:{flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:s.title}),e.jsx(I,{size:"small",fillColor:S[s.status].fill,textColor:S[s.status].text,children:U[s.status]})]})}),te=({item:s,graduated:t,highlighted:n,onPromote:d,onPromoteCandidate:c,onAddCandidate:x,onViewGraduated:i,onOpenGraduated:f})=>{const[p,g]=r.useState(n),u=s.candidates.length>0,{shipped:y,queued:j}=J(t);return e.jsxs("div",{className:n?"roadmap-item-highlighted":void 0,style:{display:"flex",flexDirection:"column",gap:l[1]},children:[e.jsx(D,{size:"small",texture:"canvas",className:"plan-row-card",children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:l[1]},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:l[2]},children:[e.jsx("button",{type:"button","aria-expanded":p,"aria-label":p?"Collapse item":"Expand item",onClick:()=>g(h=>!h),style:{display:"inline-flex",alignItems:"center",background:"none",border:"none",cursor:"pointer",opacity:.5,padding:0,transform:p?"rotate(90deg)":void 0},children:e.jsx(X,{})}),e.jsx("span",{style:{fontWeight:600,flex:1},children:s.name}),e.jsx(v,{type:"button",variant:"ghost",size:"small",onClick:d,children:"Promote to idea"})]}),e.jsx("span",{className:p?void 0:"roadmap-item-desc",style:{fontSize:b.sm,opacity:.7},children:s.description}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:l[1]},children:[(j>0||y>0)&&e.jsxs("button",{type:"button",onClick:i,style:{display:"flex",alignItems:"center",gap:l[1],background:"none",border:"none",padding:0,cursor:"pointer"},children:[j>0&&e.jsxs(I,{size:"small",fillColor:S.planned.fill,textColor:S.planned.text,children:[j," in queue"]}),y>0&&e.jsxs(I,{size:"small",fillColor:S.done.fill,textColor:S.done.text,children:[y," shipped"]})]}),u&&e.jsxs(I,{size:"small",fillColor:"rgba(0, 0, 0, 0.06)",textColor:"rgba(0, 0, 0, 0.55)",children:[s.candidates.length," candidate",s.candidates.length===1?"":"s"]})]})]})}),p&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:l[1],paddingLeft:l[6]},children:[s.candidates.map(h=>e.jsx(Y,{name:h,onPromote:()=>c(h)},h)),t.map(h=>e.jsx(ee,{plan:h,onOpen:()=>f(h.title)},h.title)),e.jsx(Z,{onAdd:x})]})]})},se=({goal:s})=>{const[t,n]=r.useState(!1),[d,...c]=s.split(/\n{2,}/),x=c.length>0;return e.jsxs("div",{style:{marginBottom:l[6],paddingBottom:l[4],borderBottom:"1px solid rgba(0, 0, 0, 0.08)"},children:[e.jsx("span",{style:{fontFamily:z.handwritten,fontSize:b.xs,fontWeight:600,opacity:.55},children:"The goal"}),e.jsxs("div",{style:{fontFamily:z.serif,fontSize:b.lg,lineHeight:1.4,marginTop:l[2]},children:[e.jsx("div",{className:t?void 0:"roadmap-goal-line-clamp",children:e.jsx(T,{children:d})}),t&&x&&e.jsx(T,{children:c.join(`
|
|
2
|
-
|
|
3
|
-
`)})]}),x&&e.jsx("button",{type:"button",onClick:()=>n(i=>!i),style:{background:"none",border:"none",padding:0,marginTop:l[2],cursor:"pointer",fontSize:b["2xs"],opacity:.65,textDecoration:"underline"},children:t?"Show less":"Show more"})]})},ae=({items:s,graduatedByItem:t})=>{const n=s.filter(c=>t(c).length>0).length,d=s.length-n;return e.jsxs("div",{style:V,children:[n," graduated · ",d," charted"]})},le=()=>{const[s,t]=r.useState(null),[n,d]=r.useState(!0),[c,x]=r.useState(!1),[i,f]=r.useState(null),p=k(o=>o.plans),g=G(),{item:u}=H({from:"/roadmap"}),y=r.useRef(null);if(r.useEffect(()=>{C().then(t).catch(()=>x(!0)).finally(()=>d(!1))},[]),r.useEffect(()=>{var a;if(!u||n)return;const o=(a=y.current)==null?void 0:a.querySelector(".roadmap-item-highlighted");o==null||o.scrollIntoView({behavior:"smooth",block:"center"})},[u,n]),n)return e.jsxs("div",{children:[e.jsx(A,{children:"Roadmap"}),e.jsx("p",{style:{opacity:.5},children:"Loading…"})]});if(c)return e.jsxs("div",{children:[e.jsx(A,{children:"Roadmap"}),e.jsx("p",{style:{opacity:.5},children:"Couldn't load the roadmap — the server may need a restart to pick up new routes."})]});if(!s||s.horizons.length===0)return e.jsxs("div",{children:[e.jsx(A,{children:"Roadmap"}),e.jsx("p",{style:{opacity:.5},children:"No `ROADMAP.md` found at the project root."})]});const j=o=>(p==null?void 0:p.entries.filter(a=>a.subject===o.name))??[],h=async(o,a,m)=>{await q(o,a,m),t(await C())},R=async(o,a,m)=>{await W(o,a,m),t(await C())};return e.jsxs("div",{ref:y,children:[e.jsx(se,{goal:s.goal}),e.jsx("div",{className:"roadmap-horizons-grid",children:s.horizons.map(o=>e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:l[1]},children:[e.jsxs("div",{style:{display:"flex",alignItems:"baseline",gap:l[2]},children:[e.jsx("div",{style:K,children:o.title}),e.jsx(ae,{items:o.items,graduatedByItem:j})]}),o.items.map(a=>e.jsx(te,{item:a,graduated:j(a),highlighted:a.name===u,onPromote:()=>f({horizonTitle:o.title,item:a}),onPromoteCandidate:m=>f({horizonTitle:o.title,item:a,candidateName:m}),onAddCandidate:m=>R(o.title,a.name,m),onViewGraduated:()=>g({to:"/",search:{subject:a.name}}),onOpenGraduated:m=>g({to:"/plans/$planId",params:{planId:encodeURIComponent(m)}})},a.name)),e.jsx(Q,{onAdd:(a,m)=>h(o.title,a,m)})]},o.title))}),e.jsx($,{horizonTitle:(i==null?void 0:i.horizonTitle)??null,item:(i==null?void 0:i.item)??null,candidateName:i==null?void 0:i.candidateName,onClose:()=>f(null),onPromoted:()=>C().then(t)})]})};export{le as RoadmapPage,de as useRoadmapItemNames};
|
|
4
|
-
//# sourceMappingURL=index-DHHPg0hQ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-DHHPg0hQ.js","sources":["../../../src/app/features/roadmap/promote-roadmap-item-modal.tsx","../../../src/app/features/roadmap/roadmap-page.tsx"],"sourcesContent":["import { buildRoadmapPromotePrompt } from '@/app/features/plans/prompts';\nimport { useProjectSubjects } from '@/app/hooks/use-project-subjects';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { color, fontSize, space } from '@/app/styles/tokens';\nimport { oneLineErrorSummary } from '@/app/utils/error-summary';\nimport type { RoadmapItem } from '@/types/index';\nimport { Button, Modal, Select, useToast } from '@dendelion/paper-ui';\nimport { useEffect, useState } from 'react';\n\nconst NO_SUBJECT = '__no-subject__';\n\ninterface PromoteRoadmapItemModalProps {\n horizonTitle: string | null;\n item: RoadmapItem | null;\n candidateName?: string | null;\n onClose: () => void;\n onPromoted: () => void;\n}\n\nexport const PromoteRoadmapItemModal = ({\n horizonTitle,\n item,\n candidateName,\n onClose,\n onPromoted,\n}: PromoteRoadmapItemModalProps) => {\n const promoteRoadmapItem = useAppStore((s) => s.promoteRoadmapItem);\n const launchIdeaExtend = useAppStore((s) => s.launchIdeaExtend);\n const { subjects } = useProjectSubjects();\n const [subject, setSubject] = useState(NO_SUBJECT);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const { toast } = useToast();\n\n useEffect(() => {\n if (item) {\n // A candidate defaults to its parent item's name — the \"big bet becomes a\n // Subject\" rule — but the picker still lets the user override it.\n setSubject(candidateName ? item.name : NO_SUBJECT);\n setLoading(false);\n setError(null);\n }\n }, [item, candidateName]);\n\n const handlePromote = async () => {\n if (!item || !horizonTitle) return;\n setLoading(true);\n setError(null);\n try {\n const id = await promoteRoadmapItem(\n horizonTitle,\n item,\n subject === NO_SUBJECT ? undefined : subject,\n candidateName ?? undefined,\n );\n const idea = useAppStore.getState().ideaEntries.find((e) => e.id === id);\n if (idea) {\n try {\n await launchIdeaExtend(id, buildRoadmapPromotePrompt(idea, horizonTitle));\n } catch (err) {\n // The idea was created either way — a failed refine launch just means\n // no background research ran, not that the promotion itself failed.\n toast({\n title: 'Idea created, but the refine agent failed to launch',\n description: oneLineErrorSummary((err as Error).message),\n variant: 'error',\n });\n }\n }\n onPromoted();\n onClose();\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <Modal\n open={item !== null}\n onClose={onClose}\n title={candidateName ?? item?.name ?? ''}\n size=\"small\"\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: space[4] }}>\n {!candidateName && <p style={{ margin: 0, opacity: 0.8 }}>{item?.description}</p>}\n <div>\n <Select\n size=\"small\"\n value={subject}\n onChange={setSubject}\n disabled={loading}\n options={[\n { value: NO_SUBJECT, label: 'No subject' },\n ...subjects.map((s) => ({ value: s, label: s })),\n ]}\n />\n </div>\n {error && (\n <p style={{ margin: 0, color: color.accentRoseDark, fontSize: fontSize.sm }}>{error}</p>\n )}\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: space[2] }}>\n <Button type=\"button\" variant=\"ghost\" onClick={onClose} disabled={loading}>\n Cancel\n </Button>\n <Button type=\"button\" variant=\"primary\" onClick={handlePromote} disabled={loading}>\n {loading ? 'Promoting…' : 'Promote to idea'}\n </Button>\n </div>\n </div>\n </Modal>\n );\n};\n","import { Markdown } from '@/app/components/markdown';\nimport { PageTitle } from '@/app/components/page-title';\nimport { STATUS_LABEL, STATUS_STAMP } from '@/app/features/plans/constants';\nimport { addRoadmapCandidate, addRoadmapItem, fetchRoadmap } from '@/app/services/content/docs-api';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { fontFamily, fontSize, space } from '@/app/styles/tokens';\nimport type { PlanEntry, Roadmap, RoadmapItem } from '@/types/index';\nimport { Button, Card, Input, Stamp } from '@dendelion/paper-ui';\nimport { useNavigate, useSearch } from '@tanstack/react-router';\nimport { useEffect, useRef, useState } from 'react';\nimport { PromoteRoadmapItemModal } from './promote-roadmap-item-modal';\n\nconst graduationCounts = (graduated: PlanEntry[]) => ({\n shipped: graduated.filter((p) => p.status === 'done').length,\n queued: graduated.filter((p) => p.status !== 'done' && p.status !== 'dropped').length,\n});\n\nconst horizonHeaderStyle: React.CSSProperties = {\n fontFamily: fontFamily.handwritten,\n fontSize: fontSize.md,\n fontWeight: 600,\n opacity: 0.7,\n lineHeight: 1,\n padding: `${space[2]} ${space[1]} 0`,\n};\n\nconst horizonPulseStyle: React.CSSProperties = {\n fontFamily: fontFamily.body,\n fontSize: fontSize['2xs'],\n fontWeight: 400,\n opacity: 0.5,\n padding: `0 ${space[1]}`,\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 CandidateRow = ({\n name,\n onPromote,\n}: {\n name: string;\n onPromote: () => void;\n}) => (\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <div style={{ display: 'flex', alignItems: 'center', gap: space[3] }}>\n <span style={{ flex: 1 }}>{name}</span>\n <Button type=\"button\" variant=\"ghost\" size=\"small\" onClick={onPromote}>\n Promote to idea\n </Button>\n </div>\n </Card>\n);\n\nconst AddCandidateForm = ({ onAdd }: { onAdd: (name: string) => Promise<void> }) => {\n const [name, setName] = useState('');\n const [saving, setSaving] = useState(false);\n\n const handleAdd = async () => {\n if (!name.trim()) return;\n setSaving(true);\n try {\n await onAdd(name.trim());\n setName('');\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <div style={{ display: 'flex', gap: space[2] }}>\n <Input\n size=\"small\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') handleAdd();\n }}\n placeholder=\"Add candidate…\"\n disabled={saving}\n style={{ flex: 1 }}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"small\"\n onClick={handleAdd}\n disabled={saving || !name.trim()}\n >\n Add\n </Button>\n </div>\n );\n};\n\nconst AddItemForm = ({\n onAdd,\n}: {\n onAdd: (name: string, description: string) => Promise<void>;\n}) => {\n const [open, setOpen] = useState(false);\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [saving, setSaving] = useState(false);\n\n const handleAdd = async () => {\n if (!name.trim()) return;\n setSaving(true);\n try {\n await onAdd(name.trim(), description.trim());\n setName('');\n setDescription('');\n setOpen(false);\n } finally {\n setSaving(false);\n }\n };\n\n if (!open) {\n return (\n <Button type=\"button\" variant=\"ghost\" size=\"small\" onClick={() => setOpen(true)}>\n + Add item\n </Button>\n );\n }\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: space[2] }}>\n <Input\n size=\"small\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"Item name…\"\n disabled={saving}\n autoFocus\n />\n <Input\n size=\"small\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') handleAdd();\n }}\n placeholder=\"Description…\"\n disabled={saving}\n />\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: space[2] }}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"small\"\n onClick={() => setOpen(false)}\n disabled={saving}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={handleAdd}\n disabled={saving || !name.trim()}\n >\n Add\n </Button>\n </div>\n </div>\n );\n};\n\nconst GraduatedRow = ({ plan, onOpen }: { plan: PlanEntry; onOpen: () => void }) => (\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <button\n type=\"button\"\n onClick={onOpen}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[3],\n width: '100%',\n background: 'none',\n border: 'none',\n padding: 0,\n cursor: 'pointer',\n font: 'inherit',\n color: 'inherit',\n textAlign: 'left',\n }}\n >\n <span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>\n {plan.title}\n </span>\n <Stamp\n size=\"small\"\n fillColor={STATUS_STAMP[plan.status].fill}\n textColor={STATUS_STAMP[plan.status].text}\n >\n {STATUS_LABEL[plan.status]}\n </Stamp>\n </button>\n </Card>\n);\n\nconst RoadmapItemRow = ({\n item,\n graduated,\n highlighted,\n onPromote,\n onPromoteCandidate,\n onAddCandidate,\n onViewGraduated,\n onOpenGraduated,\n}: {\n item: RoadmapItem;\n graduated: PlanEntry[];\n highlighted: boolean;\n onPromote: () => void;\n onPromoteCandidate: (candidateName: string) => void;\n onAddCandidate: (name: string) => Promise<void>;\n onViewGraduated: () => void;\n onOpenGraduated: (title: string) => void;\n}) => {\n const [expanded, setExpanded] = useState(highlighted);\n const hasCandidates = item.candidates.length > 0;\n const { shipped, queued } = graduationCounts(graduated);\n\n return (\n <div\n className={highlighted ? 'roadmap-item-highlighted' : undefined}\n style={{ display: 'flex', flexDirection: 'column', gap: space[1] }}\n >\n <Card size=\"small\" texture=\"canvas\" className=\"plan-row-card\">\n <div style={{ display: 'flex', flexDirection: 'column', gap: space[1] }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: space[2] }}>\n {/* Raw <button>: icon-only toggle, paper-ui Button doesn't offer this compact chrome. */}\n <button\n type=\"button\"\n aria-expanded={expanded}\n aria-label={expanded ? 'Collapse item' : 'Expand item'}\n onClick={() => setExpanded((v) => !v)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n opacity: 0.5,\n padding: 0,\n transform: expanded ? 'rotate(90deg)' : undefined,\n }}\n >\n <ChevronRightIcon />\n </button>\n <span style={{ fontWeight: 600, flex: 1 }}>{item.name}</span>\n <Button type=\"button\" variant=\"ghost\" size=\"small\" onClick={onPromote}>\n Promote to idea\n </Button>\n </div>\n <span\n className={expanded ? undefined : 'roadmap-item-desc'}\n style={{ fontSize: fontSize.sm, opacity: 0.7 }}\n >\n {item.description}\n </span>\n <div style={{ display: 'flex', alignItems: 'center', gap: space[1] }}>\n {(queued > 0 || shipped > 0) && (\n <button\n type=\"button\"\n onClick={onViewGraduated}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[1],\n background: 'none',\n border: 'none',\n padding: 0,\n cursor: 'pointer',\n }}\n >\n {queued > 0 && (\n <Stamp\n size=\"small\"\n fillColor={STATUS_STAMP.planned.fill}\n textColor={STATUS_STAMP.planned.text}\n >\n {queued} in queue\n </Stamp>\n )}\n {shipped > 0 && (\n <Stamp\n size=\"small\"\n fillColor={STATUS_STAMP.done.fill}\n textColor={STATUS_STAMP.done.text}\n >\n {shipped} shipped\n </Stamp>\n )}\n </button>\n )}\n {hasCandidates && (\n <Stamp size=\"small\" fillColor=\"rgba(0, 0, 0, 0.06)\" textColor=\"rgba(0, 0, 0, 0.55)\">\n {item.candidates.length} candidate{item.candidates.length === 1 ? '' : 's'}\n </Stamp>\n )}\n </div>\n </div>\n </Card>\n {expanded && (\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: space[1],\n paddingLeft: space[6],\n }}\n >\n {item.candidates.map((candidateName) => (\n <CandidateRow\n key={candidateName}\n name={candidateName}\n onPromote={() => onPromoteCandidate(candidateName)}\n />\n ))}\n {graduated.map((plan) => (\n <GraduatedRow key={plan.title} plan={plan} onOpen={() => onOpenGraduated(plan.title)} />\n ))}\n <AddCandidateForm onAdd={onAddCandidate} />\n </div>\n )}\n </div>\n );\n};\n\nconst GoalBanner = ({ goal }: { goal: string }) => {\n const [expanded, setExpanded] = useState(false);\n const [firstParagraph, ...restParagraphs] = goal.split(/\\n{2,}/);\n const hasMore = restParagraphs.length > 0;\n\n return (\n <div\n style={{\n marginBottom: space[6],\n paddingBottom: space[4],\n borderBottom: '1px solid rgba(0, 0, 0, 0.08)',\n }}\n >\n <span\n style={{\n fontFamily: fontFamily.handwritten,\n fontSize: fontSize.xs,\n fontWeight: 600,\n opacity: 0.55,\n }}\n >\n The goal\n </span>\n <div\n style={{\n fontFamily: fontFamily.serif,\n fontSize: fontSize.lg,\n lineHeight: 1.4,\n marginTop: space[2],\n }}\n >\n <div className={expanded ? undefined : 'roadmap-goal-line-clamp'}>\n <Markdown>{firstParagraph}</Markdown>\n </div>\n {expanded && hasMore && <Markdown>{restParagraphs.join('\\n\\n')}</Markdown>}\n </div>\n {hasMore && (\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n style={{\n background: 'none',\n border: 'none',\n padding: 0,\n marginTop: space[2],\n cursor: 'pointer',\n fontSize: fontSize['2xs'],\n opacity: 0.65,\n textDecoration: 'underline',\n }}\n >\n {expanded ? 'Show less' : 'Show more'}\n </button>\n )}\n </div>\n );\n};\n\nconst HorizonPulse = ({\n items,\n graduatedByItem,\n}: { items: RoadmapItem[]; graduatedByItem: (item: RoadmapItem) => PlanEntry[] }) => {\n const graduated = items.filter((item) => graduatedByItem(item).length > 0).length;\n const charted = items.length - graduated;\n return (\n <div style={horizonPulseStyle}>\n {graduated} graduated · {charted} charted\n </div>\n );\n};\n\nexport const RoadmapPage = () => {\n const [roadmap, setRoadmap] = useState<Roadmap | null>(null);\n const [loading, setLoading] = useState(true);\n const [loadFailed, setLoadFailed] = useState(false);\n const [promoting, setPromoting] = useState<{\n horizonTitle: string;\n item: RoadmapItem;\n candidateName?: string;\n } | null>(null);\n const plans = useAppStore((s) => s.plans);\n const navigate = useNavigate();\n const { item: highlightedItem } = useSearch({ from: '/roadmap' });\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n fetchRoadmap()\n .then(setRoadmap)\n .catch(() => setLoadFailed(true))\n .finally(() => setLoading(false));\n }, []);\n\n useEffect(() => {\n if (!highlightedItem || loading) return;\n const row = containerRef.current?.querySelector('.roadmap-item-highlighted');\n row?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }, [highlightedItem, loading]);\n\n if (loading) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p style={{ opacity: 0.5 }}>Loading…</p>\n </div>\n );\n }\n\n if (loadFailed) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p style={{ opacity: 0.5 }}>\n Couldn't load the roadmap — the server may need a restart to pick up new routes.\n </p>\n </div>\n );\n }\n\n if (!roadmap || roadmap.horizons.length === 0) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p style={{ opacity: 0.5 }}>No `ROADMAP.md` found at the project root.</p>\n </div>\n );\n }\n\n const graduatedByItem = (item: RoadmapItem) =>\n plans?.entries.filter((p) => p.subject === item.name) ?? [];\n\n const handleAddItem = async (horizonTitle: string, name: string, description: string) => {\n await addRoadmapItem(horizonTitle, name, description);\n setRoadmap(await fetchRoadmap());\n };\n\n const handleAddCandidate = async (horizonTitle: string, itemName: string, name: string) => {\n await addRoadmapCandidate(horizonTitle, itemName, name);\n setRoadmap(await fetchRoadmap());\n };\n\n return (\n <div ref={containerRef}>\n <GoalBanner goal={roadmap.goal} />\n <div className=\"roadmap-horizons-grid\">\n {roadmap.horizons.map((horizon) => (\n <div\n key={horizon.title}\n style={{ display: 'flex', flexDirection: 'column', gap: space[1] }}\n >\n <div style={{ display: 'flex', alignItems: 'baseline', gap: space[2] }}>\n <div style={horizonHeaderStyle}>{horizon.title}</div>\n <HorizonPulse items={horizon.items} graduatedByItem={graduatedByItem} />\n </div>\n {horizon.items.map((item) => (\n <RoadmapItemRow\n key={item.name}\n item={item}\n graduated={graduatedByItem(item)}\n highlighted={item.name === highlightedItem}\n onPromote={() => setPromoting({ horizonTitle: horizon.title, item })}\n onPromoteCandidate={(candidateName) =>\n setPromoting({ horizonTitle: horizon.title, item, candidateName })\n }\n onAddCandidate={(name) => handleAddCandidate(horizon.title, item.name, name)}\n onViewGraduated={() => navigate({ to: '/', search: { subject: item.name } })}\n onOpenGraduated={(title) =>\n navigate({ to: '/plans/$planId', params: { planId: encodeURIComponent(title) } })\n }\n />\n ))}\n <AddItemForm\n onAdd={(name, description) => handleAddItem(horizon.title, name, description)}\n />\n </div>\n ))}\n </div>\n <PromoteRoadmapItemModal\n horizonTitle={promoting?.horizonTitle ?? null}\n item={promoting?.item ?? null}\n candidateName={promoting?.candidateName}\n onClose={() => setPromoting(null)}\n onPromoted={() => fetchRoadmap().then(setRoadmap)}\n />\n </div>\n );\n};\n"],"names":["NO_SUBJECT","PromoteRoadmapItemModal","horizonTitle","item","candidateName","onClose","onPromoted","promoteRoadmapItem","useAppStore","s","launchIdeaExtend","subjects","useProjectSubjects","subject","setSubject","useState","loading","setLoading","error","setError","toast","useToast","useEffect","handlePromote","id","idea","e","buildRoadmapPromotePrompt","err","oneLineErrorSummary","jsx","Modal","jsxs","space","Select","color","fontSize","Button","graduationCounts","graduated","p","horizonHeaderStyle","fontFamily","horizonPulseStyle","ChevronRightIcon","size","CandidateRow","name","onPromote","Card","AddCandidateForm","onAdd","setName","saving","setSaving","handleAdd","Input","AddItemForm","open","setOpen","description","setDescription","GraduatedRow","plan","onOpen","Stamp","STATUS_STAMP","STATUS_LABEL","RoadmapItemRow","highlighted","onPromoteCandidate","onAddCandidate","onViewGraduated","onOpenGraduated","expanded","setExpanded","hasCandidates","shipped","queued","v","GoalBanner","goal","firstParagraph","restParagraphs","hasMore","Markdown","HorizonPulse","items","graduatedByItem","charted","RoadmapPage","roadmap","setRoadmap","loadFailed","setLoadFailed","promoting","setPromoting","plans","navigate","useNavigate","highlightedItem","useSearch","containerRef","useRef","fetchRoadmap","row","_a","PageTitle","handleAddItem","addRoadmapItem","handleAddCandidate","itemName","addRoadmapCandidate","horizon","title"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as u,g as E,i as G,k as W,j as e,s as n,m as _,p as M,Z as L,O as Y,b as S,n as b,q as C,A as N,t as J,X as T,K as Q,v as ee,w as K,P as te,x as se,c as ae,D as I,y as ie,z as B,Y as P,B as ne,a as le,o as U}from"./main-BNLbBO0E.js";import{S as $}from"./sidebar-section-DVSoUVEe.js";function oe(t){if(t==="git")return{label:"Git",unlocks:"Commits, phase logging, branch creation",fix:o=>o.startsWith("Not inside")?"git init":'git config user.name "Your Name" && git config user.email you@example.com'};if(t==="gh")return{label:"GitHub CLI",unlocks:"PR badges, review flow, fix-review",fix:o=>o.includes("not found")?"Install: https://cli.github.com":o.includes("no origin remote")?"git remote add origin <url>":o.includes("not reachable")?"gh repo view":"gh auth login"};const s=t.slice(6);return{label:`${N[s]} CLI`,unlocks:`Launching ${N[s]} for phase runs, drafts, and reviews`,fix:()=>`Install the ${N[s]} CLI and add it to PATH`}}const re={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"}},de=({result:t,isLast:s,onRecheck:o,rechecking:p})=>{const h=oe(t.id),r=re[t.status],m=t.status!=="ok"?h.fix(t.detail):null;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:h.label}),e.jsx(Y,{size:"small",fillColor:r.fill,textColor:r.text,children:r.label}),e.jsx(L,{size:"small",variant:"secondary",onClick:()=>o(t.id),disabled:p,children:p?"Checking…":"Recheck"})]}),e.jsxs("p",{style:{opacity:.65,fontSize:S.sm,margin:`${n[1]} 0 0`},children:["Unlocks: ",h.unlocks]}),e.jsx("p",{style:{opacity:.5,fontSize:S.sm,margin:`${n[1]} 0 0`},children:t.detail}),m&&e.jsx("code",{style:{display:"block",marginTop:n[2],padding:n[2],background:"rgba(0,0,0,0.06)",borderRadius:4,fontSize:S.sm},children:m})]}),!s&&e.jsx(b,{})]})},ce=()=>{const[t,s]=u.useState(null),[o,p]=u.useState(!1),[h,r]=u.useState(null),[m,x]=u.useState(!1),{toast:d}=E(),j=u.useCallback(a=>{if(a===null){p(!0);return}p(!1),s(a)},[]);u.useEffect(()=>{G().then(j),W().then(a=>x((a==null?void 0:a.setupDismissed)??!1))},[j]);const c=async a=>{r(a),j(await G()),r(null)},v=async()=>{const a=!m,{ok:g}=await C({setupDismissed:a});g?(x(a),d({title:"Saved",variant:"success"})):d({title:"Failed to save",variant:"error"})},w=(t==null?void 0:t.every(a=>a.status==="ok"))??!0;return e.jsxs("div",{children:[e.jsx("div",{style:{marginBottom:n[6]},children:e.jsx("h2",{style:{margin:0},children:"Setup"})}),t===null&&!o&&e.jsx("p",{children:"Loading…"}),o&&e.jsx("div",{style:{marginBottom:n[4]},children:e.jsx(_,{variant:"warning",children:"Failed to load capabilities. Try refreshing."})}),t&&e.jsxs(e.Fragment,{children:[!w&&e.jsx("div",{style:{marginBottom:n[4]},children:e.jsx(_,{variant:"warning",children:"Some capabilities are incomplete — features that depend on them stay disabled until fixed. Run the fix command in your terminal, then recheck."})}),e.jsx(M,{size:"small",children:t.map((a,g)=>e.jsx(de,{result:a,isLast:g===t.length-1,onRecheck:c,rechecking:h===a.id},a.id))}),e.jsx("div",{style:{marginTop:n[4]},children:e.jsx(L,{variant:"secondary",size:"small",onClick:v,children:m?"Show Setup on open again":"Don't show Setup on open"})})]})]})},ue=({name:t,isLast:s,onRename:o,onRemove:p})=>{const[h,r]=u.useState(t),{toast:m}=E(),x=async()=>{const d=h.trim();if(!d||d===t){r(t);return}await o(t,d)||(r(t),m({title:"Failed to rename",variant:"error"}))};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(T,{size:"small",value:h,onChange:d=>r(d.target.value),onBlur:x,style:{flex:1}}),e.jsx(ee,{icon:e.jsx("span",{children:"×"}),variant:"ghost",size:"small",label:`Remove ${t}`,onClick:()=>p(t)})]}),!s&&e.jsx(b,{})]})},pe=()=>{const{subjects:t,loading:s,addSubject:o,renameSubject:p,removeSubject:h}=J(),[r,m]=u.useState(""),{toast:x}=E(),d=async()=>{const c=r.trim();if(!c)return;await o(c)?m(""):x({title:"Failed to add subject",variant:"error"})},j=async c=>{await h(c)||x({title:"Failed to remove subject",variant:"error"})};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:'Group ideas by subject. Removing one falls its ideas back to "No subject" — file contents are untouched.'})]}),s&&e.jsx("p",{children:"Loading…"}),!s&&e.jsxs(M,{size:"small",children:[t.length===0&&e.jsx("p",{style:{opacity:.45,margin:0,paddingBottom:n[2]},children:"No subjects yet."}),t.map((c,v)=>e.jsx(ue,{name:c,isLast:v===t.length-1,onRename:p,onRemove:j},c)),t.length>0&&e.jsx(b,{}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingTop:n[3]},children:[e.jsx(T,{size:"small",placeholder:"New subject",value:r,onChange:c=>m(c.target.value),onKeyDown:c=>{c.key==="Enter"&&d()},style:{flex:1}}),e.jsxs(L,{variant:"secondary",size:"small",onClick:d,disabled:!r.trim(),children:[e.jsx(Q,{size:14})," Add"]})]})]})]})},H=["phase","planDraft","ideaExtend","commitSuggest"],he={phase:"Phase run",planDraft:"Plan draft",ideaExtend:"Idea extend",commitSuggest:"Commit suggest"},Z=110,X=140,O=160,q=110,me=()=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingBottom:n[1]},children:[e.jsx("span",{style:{width:Z,flexShrink:0,fontSize:S.sm,opacity:.45},children:"Task"}),e.jsx("span",{style:{width:X,flexShrink:0,fontSize:S.sm,opacity:.45},children:"Agent"}),e.jsx("span",{style:{width:O,flexShrink:0,fontSize:S.sm,opacity:.45},children:"Model"}),e.jsx("span",{style:{width:q,flexShrink:0,fontSize:S.sm,opacity:.45},children:"Effort"})]}),ge=({taskKey:t,agentConfig:s,isLast:o,onSave:p})=>{const h=B[s.agent]??B["claude-code"],r=h.model,m=h.effort,[x,d]=u.useState(s.model??"");u.useEffect(()=>{d(s.model??"")},[s.model]);const j=a=>{var z;const g=a,k=B[g],A={agent:g};s.model&&(k.model===null||(z=k.model)!=null&&z.includes(s.model))&&(A.model=s.model),s.effort&&Array.isArray(k.effort)&&(A.effort=s.effort),p(t,A)},c=a=>{p(t,{...s,model:a||void 0})},v=()=>{p(t,{...s,model:x||void 0})},w=a=>{p(t,{...s,effort:a||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:Z,flexShrink:0,fontSize:S.sm,opacity:.65},children:he[t]}),e.jsx(P,{size:"small",width:X,value:s.agent,onChange:j,options:ne.map(a=>({value:a,label:N[a]}))}),Array.isArray(r)?e.jsx(P,{size:"small",width:O,value:s.model??"",onChange:c,options:[{value:"",label:"Default"},...r.map(a=>({value:a,label:a}))]}):r===null?e.jsx(T,{size:"small",style:{width:O},value:x,placeholder:"Default model",onChange:a=>d(a.target.value),onBlur:v}):null,e.jsx("div",{style:{visibility:Array.isArray(m)?"visible":"hidden"},children:e.jsx(P,{size:"small",width:q,value:s.effort??"",onChange:w,options:[{value:"",label:"Default"},...(Array.isArray(m)?m:[]).map(a=>({value:a,label:a}))]})})]}),!o&&e.jsx(b,{})]})},xe=()=>{const t=u.useRef(null),[s,o]=u.useState(void 0),{iconDataUri:p,loading:h}=se(),[r,m]=u.useState(null),x=r??p,[d,j]=u.useState(!1),[c,v]=u.useState(""),[w,a]=u.useState(""),{toast:g}=E();u.useEffect(()=>{W().then(i=>{o(i),(i==null?void 0:i.port)!==void 0&&v(String(i.port)),(i==null?void 0:i.projectName)!==void 0&&a(i.projectName)})},[]);const k=async(i,y)=>{const l=s==null?void 0:s.defaultAgents,f={phase:(l==null?void 0:l.phase)??I.phase,planDraft:(l==null?void 0:l.planDraft)??I.planDraft,ideaExtend:(l==null?void 0:l.ideaExtend)??I.ideaExtend,commitSuggest:(l==null?void 0:l.commitSuggest)??I.commitSuggest,[i]:y},{ok:D,error:F}=await C({defaultAgents:f});D?(o(R=>R&&{...R,defaultAgents:f}),g({title:"Saved",variant:"success"})):g({title:"Failed to save",description:F,variant:"error"})},A=async()=>{const i=Number(c);if(!s||!Number.isInteger(i)||i<=0||i===s.port)return;const{ok:y,error:l}=await C({port:i});y?(o(f=>f&&{...f,port:i}),g({title:"Saved",variant:"success"})):g({title:"Failed to save",description:l,variant:"error"})},z=async()=>{const i=w.trim();if(!s||!i||i===s.projectName)return;const{ok:y,error:l}=await C({projectName:i});y?(o(f=>f&&{...f,projectName:i}),a(i),g({title:"Saved",variant:"success"})):g({title:"Failed to save",description:l,variant:"error"})},V=async i=>{var f;const y=(f=i.target.files)==null?void 0:f[0];if(!y)return;j(!0);const l=new FileReader;l.onloadend=async()=>{const D=l.result,F=await ie(D);j(!1),F?(m(D),g({title:"Saved",variant:"success"})):g({title:"Failed to save",variant:"error"})},l.readAsDataURL(y)};return e.jsxs("div",{children:[e.jsx("div",{style:{marginBottom:n[6]},children:e.jsx("h2",{style:{margin:0},children:"Project Info"})}),s===void 0&&e.jsx("p",{children:"Loading…"}),s===null&&e.jsxs(_,{variant:"warning",children:["No papercamp/config.json found — run ",e.jsx("code",{children:"paper-camp init"})," in this directory first."]}),s&&e.jsxs(M,{size:"small",children:[e.jsxs("div",{style:{display:"flex",alignItems:"flex-end",gap:n[3],paddingBottom:n[3]},children:[e.jsx(T,{value:w,onChange:i=>a(i.target.value),onBlur:z,label:"Project Name"}),e.jsxs(Y,{size:"small",fillColor:"rgba(143, 185, 150, 0.25)",textColor:ae.accentGreenDark,children:["v",s.version]})]}),e.jsx(b,{}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingBottom:n[3],paddingTop:n[3]},children:[x&&e.jsx("img",{src:x,alt:"Project icon",style:{width:40,height:40,objectFit:"contain",flexShrink:0,borderRadius:4}}),e.jsxs("div",{children:[e.jsx("input",{ref:t,type:"file",accept:".svg,.png,.jpg,.jpeg,.gif,.webp",onChange:V,style:{display:"none"}}),e.jsx(L,{variant:"secondary",size:"small",onClick:()=>{var i;return(i=t.current)==null?void 0:i.click()},disabled:d,children:d?"Uploading…":"Choose File"}),h&&e.jsx("p",{className:"text-sm",style:{opacity:.5,margin:`${n[1]} 0 0`},children:"Loading…"}),!h&&!x&&!d&&e.jsx("p",{className:"text-sm",style:{opacity:.45,margin:`${n[1]} 0 0`},children:"No icon set."})]})]}),e.jsx(b,{}),e.jsx("div",{style:{display:"flex",alignItems:"flex-end",gap:n[3],paddingBottom:n[3],paddingTop:n[3]},children:e.jsx(T,{type:"number",value:c,onChange:i=>v(i.target.value),onBlur:A,label:"Port",helperText:"Default for `paper-camp dev`. Does not affect the running server."})}),e.jsx(b,{}),e.jsx(me,{}),H.map((i,y)=>{var l;return e.jsx(ge,{taskKey:i,agentConfig:((l=s.defaultAgents)==null?void 0:l[i])??I[i],isLast:y===H.length-1,onSave:k},i)})]}),e.jsxs("p",{style:{opacity:.45,fontSize:S.sm,marginTop:n[4]},children:[e.jsx("strong",{children:"Initialized:"})," ",s?new Date(s.initializedAt).toLocaleString():"—"]})]})},ve=()=>{const t=K();return e.jsxs("div",{children:[e.jsx(te,{children:"Settings"}),t==="subjects"?e.jsx(pe,{}):t==="setup"?e.jsx(ce,{}):e.jsx(xe,{})]})},ye=()=>{const t=K(),s=le();return e.jsxs(e.Fragment,{children:[e.jsxs($,{label:"General",children:[e.jsx(U,{size:"small",active:t===null,onClick:()=>s({to:"/settings"}),children:"Project Info"}),e.jsx(U,{size:"small",active:t==="setup",onClick:()=>s({to:"/settings/$section",params:{section:"setup"}}),children:"Setup"})]}),e.jsx($,{label:"Ideas",children:e.jsx(U,{size:"small",active:t==="subjects",onClick:()=>s({to:"/settings/$section",params:{section:"subjects"}}),children:"Subjects"})})]})};export{ve as SettingsPage,ye as SettingsSidebar};
|
|
2
|
-
//# sourceMappingURL=index-DyLHu3dg.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-DyLHu3dg.js","sources":["../../../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 { fetchCapabilities, fetchConfig, saveConfig } from '@/app/services/system';\nimport { fontSize, space } from '@/app/styles/tokens';\nimport {\n AGENT_LABELS,\n type AgentId,\n type CapabilityResult,\n type CapabilityStatus,\n} from '@/types/index';\nimport { Alert, Button, Card, Divider, Stamp, useToast } from '@dendelion/paper-ui';\nimport { useCallback, useEffect, useState } from 'react';\n\ninterface CapabilityMeta {\n label: string;\n unlocks: string;\n fix: (detail: string) => string;\n}\n\nfunction capabilityMeta(id: string): CapabilityMeta {\n if (id === 'git') {\n return {\n label: 'Git',\n unlocks: 'Commits, phase logging, branch creation',\n fix: (detail) =>\n detail.startsWith('Not inside')\n ? 'git init'\n : 'git config user.name \"Your Name\" && git config user.email you@example.com',\n };\n }\n if (id === 'gh') {\n return {\n label: 'GitHub CLI',\n unlocks: 'PR badges, review flow, fix-review',\n fix: (detail) => {\n if (detail.includes('not found')) return 'Install: https://cli.github.com';\n if (detail.includes('no origin remote')) return 'git remote add origin <url>';\n if (detail.includes('not reachable')) return 'gh repo view';\n return 'gh auth login';\n },\n };\n }\n const agentId = id.slice('agent:'.length) as AgentId;\n return {\n label: `${AGENT_LABELS[agentId]} CLI`,\n unlocks: `Launching ${AGENT_LABELS[agentId]} for phase runs, drafts, and reviews`,\n fix: () => `Install the ${AGENT_LABELS[agentId]} CLI and add it to PATH`,\n };\n}\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 CapabilityRow = ({\n result,\n isLast,\n onRecheck,\n rechecking,\n}: {\n result: CapabilityResult;\n isLast: boolean;\n onRecheck: (id: string) => void;\n rechecking: boolean;\n}) => {\n const meta = capabilityMeta(result.id);\n const stamp = STATUS_STAMP[result.status];\n const fix = result.status !== 'ok' ? meta.fix(result.detail) : null;\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 }}>{meta.label}</span>\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(result.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: {meta.unlocks}\n </p>\n <p style={{ opacity: 0.5, fontSize: fontSize.sm, margin: `${space[1]} 0 0` }}>\n {result.detail}\n </p>\n {fix && (\n <code\n style={{\n display: 'block',\n marginTop: space[2],\n padding: space[2],\n background: 'rgba(0,0,0,0.06)',\n borderRadius: 4,\n fontSize: fontSize.sm,\n }}\n >\n {fix}\n </code>\n )}\n </div>\n {!isLast && <Divider />}\n </>\n );\n};\n\nexport const SetupSection = () => {\n const [capabilities, setCapabilities] = useState<CapabilityResult[] | null>(null);\n const [loadFailed, setLoadFailed] = useState(false);\n const [reloadingId, setReloadingId] = useState<string | null>(null);\n const [setupDismissed, setSetupDismissed] = useState(false);\n const { toast } = useToast();\n\n const applyCapabilities = useCallback((result: CapabilityResult[] | null) => {\n if (result === null) {\n setLoadFailed(true);\n return;\n }\n setLoadFailed(false);\n setCapabilities(result);\n }, []);\n\n useEffect(() => {\n fetchCapabilities().then(applyCapabilities);\n fetchConfig().then((c) => setSetupDismissed(c?.setupDismissed ?? false));\n }, [applyCapabilities]);\n\n const handleRecheck = async (id: string) => {\n setReloadingId(id);\n applyCapabilities(await fetchCapabilities());\n setReloadingId(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 = capabilities?.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 {capabilities === null && !loadFailed && <p>Loading…</p>}\n {loadFailed && (\n <div style={{ marginBottom: space[4] }}>\n <Alert variant=\"warning\">Failed to load capabilities. Try refreshing.</Alert>\n </div>\n )}\n {capabilities && (\n <>\n {!allOk && (\n <div style={{ marginBottom: space[4] }}>\n <Alert variant=\"warning\">\n Some capabilities are incomplete — features that depend on them stay disabled until\n fixed. Run the fix command in your terminal, then recheck.\n </Alert>\n </div>\n )}\n <Card size=\"small\">\n {capabilities.map((c, idx) => (\n <CapabilityRow\n key={c.id}\n result={c}\n isLast={idx === capabilities.length - 1}\n onRecheck={handleRecheck}\n rechecking={reloadingId === 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 { useProjectSubjects } from '@/app/hooks';\nimport { space } from '@/app/styles/tokens';\nimport { Button, Card, Divider, IconButton, Input, PlusIcon, useToast } from '@dendelion/paper-ui';\nimport { useState } from 'react';\n\nconst SubjectRow = ({\n name,\n isLast,\n onRename,\n onRemove,\n}: {\n name: string;\n isLast: boolean;\n onRename: (from: string, to: string) => Promise<boolean>;\n onRemove: (name: string) => Promise<void>;\n}) => {\n const [value, setValue] = useState(name);\n const { toast } = useToast();\n\n const handleBlur = async () => {\n const trimmed = value.trim();\n if (!trimmed || trimmed === name) {\n setValue(name);\n return;\n }\n const ok = await onRename(name, trimmed);\n if (!ok) {\n setValue(name);\n toast({ title: 'Failed to rename', variant: 'error' });\n }\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 <Input\n size=\"small\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onBlur={handleBlur}\n style={{ flex: 1 }}\n />\n <IconButton\n icon={<span>×</span>}\n variant=\"ghost\"\n size=\"small\"\n label={`Remove ${name}`}\n onClick={() => onRemove(name)}\n />\n </div>\n {!isLast && <Divider />}\n </>\n );\n};\n\nexport const SubjectsSection = () => {\n const { subjects, loading, addSubject, renameSubject, removeSubject } = useProjectSubjects();\n const [newSubject, setNewSubject] = useState('');\n const { toast } = useToast();\n\n const handleAdd = async () => {\n const trimmed = newSubject.trim();\n if (!trimmed) return;\n const ok = await addSubject(trimmed);\n if (ok) setNewSubject('');\n else toast({ title: 'Failed to add subject', variant: 'error' });\n };\n\n const handleRemove = async (name: string) => {\n const ok = await removeSubject(name);\n if (!ok) toast({ title: 'Failed to remove subject', variant: 'error' });\n };\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 Group ideas by subject. Removing one falls its ideas back to \"No subject\" — file contents\n are untouched.\n </p>\n </div>\n {loading && <p>Loading…</p>}\n {!loading && (\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 <SubjectRow\n key={name}\n name={name}\n isLast={idx === subjects.length - 1}\n onRename={renameSubject}\n onRemove={handleRemove}\n />\n ))}\n {subjects.length > 0 && <Divider />}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[3],\n paddingTop: space[3],\n }}\n >\n <Input\n size=\"small\"\n placeholder=\"New subject\"\n value={newSubject}\n onChange={(e) => setNewSubject(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') handleAdd();\n }}\n style={{ flex: 1 }}\n />\n <Button\n variant=\"secondary\"\n size=\"small\"\n onClick={handleAdd}\n disabled={!newSubject.trim()}\n >\n <PlusIcon size={14} /> Add\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 { 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 ) : (\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 </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":["capabilityMeta","id","detail","agentId","AGENT_LABELS","STATUS_STAMP","CapabilityRow","result","isLast","onRecheck","rechecking","meta","stamp","fix","jsxs","Fragment","space","jsx","Stamp","Button","fontSize","Divider","SetupSection","capabilities","setCapabilities","useState","loadFailed","setLoadFailed","reloadingId","setReloadingId","setupDismissed","setSetupDismissed","toast","useToast","applyCapabilities","useCallback","useEffect","fetchCapabilities","fetchConfig","c","handleRecheck","handleDismissToggle","next","ok","saveConfig","allOk","Alert","Card","idx","SubjectRow","name","onRename","onRemove","value","setValue","handleBlur","trimmed","Input","e","IconButton","SubjectsSection","subjects","loading","addSubject","renameSubject","removeSubject","useProjectSubjects","newSubject","setNewSubject","handleAdd","handleRemove","PlusIcon","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","m","GeneralSection","fileRef","useRef","config","setConfig","fetchedIconDataUri","identityLoading","useProjectIdentity","uploadedIconDataUri","setUploadedIconDataUri","iconDataUri","uploading","setUploading","portInput","setPortInput","nameInput","setNameInput","handleSaveAgentConfig","key","newEntry","current","updated","DEFAULT_AGENTS","error","prev","handleSavePort","port","handleSaveName","projectName","handleFile","file","reader","dataUri","uploadIcon","color","SettingsPage","section","useActiveSettingsSection","PageTitle","SettingsSidebar","navigate","useNavigate","SidebarSection","ListItem"],"mappings":"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"}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{u as m,C as w,r as l,j as e,P as v,s as f,p as x,b as g,A as S,f as j,O as L,c as y,E as D}from"./main-BNLbBO0E.js";const N={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","fix-review":"Fix review"},p=s=>String(s).padStart(2,"0"),A=s=>{const t=new Date(s);return`${t.getFullYear()}-${p(t.getMonth()+1)}-${p(t.getDate())}`},T=s=>new Date(s).toLocaleDateString(void 0,{weekday:"long",year:"numeric",month:"long",day:"numeric"}),k=s=>{const t=new Date(s);return`${p(t.getHours())}:${p(t.getMinutes())}:${p(t.getSeconds())}`},c={fontSize:g.sm,fontWeight:600,opacity:.6,whiteSpace:"nowrap",overflow:"hidden"},E=({id:s})=>{const[t,o]=l.useState(null);return l.useEffect(()=>{o(null),D(s).then(r=>o(r.lines)).catch(()=>o([]))},[s]),t===null?e.jsx("p",{style:{opacity:.5,margin:0},children:"Loading…"}):t.length===0?e.jsx("p",{style:{opacity:.5,margin:0},children:"No output recorded."}):e.jsx("pre",{style:{fontFamily:j.mono,fontSize:g.xs,margin:0,maxHeight:320,overflowY:"auto",whiteSpace:"pre-wrap"},children:t.join(`
|
|
2
|
-
`)})},b=({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"})}),R=({entry:s,highlighted:t})=>{const[o,r]=l.useState(t);l.useEffect(()=>{t&&r(!0)},[t]);const d=()=>r(i=>!i);return e.jsxs("div",{className:t?"task-row-highlighted":void 0,style:{display:"flex",flexDirection:"column",gap:f[1],borderRadius:10},children:[e.jsx("div",{role:"button",tabIndex:0,onClick:d,onKeyDown:i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),d())},style:{cursor:"pointer",borderRadius:10},children:e.jsx(x,{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":o,style:{display:"inline-flex",alignItems:"center",opacity:.5},children:e.jsx(b,{})}),e.jsx("span",{style:{fontWeight:600,whiteSpace:"nowrap",overflow:"hidden"},children:N[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:S[s.agentId]}),e.jsxs("span",{className:"task-rows-cell-time",style:{fontFamily:j.mono,fontSize:g.xs,opacity:.55,whiteSpace:"nowrap"},children:[k(s.startedAt),"–",k(s.endedAt)]}),e.jsx("div",{style:{display:"flex",alignItems:"center"},children:e.jsx(L,{size:"small",fillColor:s.outcome==="done"?"rgba(143, 185, 150, 0.25)":"rgba(201, 139, 139, 0.25)",textColor:s.outcome==="done"?y.accentGreenDark:y.accentRoseDark,children:s.outcome})})]})})}),o&&e.jsx(x,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsx(E,{id:s.id})})]})},C=()=>{const s=m(a=>a.taskLog),t=m(a=>a.taskLogLoading),o=m(a=>a.loadTaskLog),{taskId:r}=w({from:"/tasks"}),d=l.useRef(null);l.useEffect(()=>{o()},[o]),l.useEffect(()=>{var n;if(!r)return;const a=(n=d.current)==null?void 0:n.querySelector(".task-row-highlighted");a==null||a.scrollIntoView({behavior:"smooth",block:"center"})},[r]);const i=[...s].sort((a,n)=>n.endedAt.localeCompare(a.endedAt)),u=[];for(const a of i){const n=A(a.endedAt),h=u.at(-1);(h==null?void 0:h.key)===n?h.entries.push(a):u.push({key:n,entries:[a]})}return e.jsxs("div",{ref:d,children:[e.jsx(v,{children:"Tasks"}),t&&e.jsx("p",{style:{opacity:.5},children:"Loading…"}),!t&&i.length===0&&e.jsx("p",{style:{opacity:.5},children:"No tasks have run yet."}),!t&&i.length>0&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:f[1]},children:[e.jsx(x,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsxs("div",{className:"task-rows-grid",children:[e.jsx("span",{}),e.jsx("span",{style:c,children:"Task"}),e.jsx("span",{style:c,children:"Plan"}),e.jsx("span",{style:c,children:"Agent"}),e.jsx("span",{className:"task-rows-cell-time",style:c,children:"Time"}),e.jsx("span",{style:c,children:"Outcome"})]})}),u.map(a=>e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:f[1]},children:[e.jsx(x,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsx("span",{style:{...c,opacity:.75},children:T(a.entries[0].endedAt)})}),a.entries.map(n=>e.jsx(R,{entry:n,highlighted:n.id===r},n.id))]},a.key))]})]})};export{C as TasksPage};
|
|
3
|
-
//# sourceMappingURL=index-DzMK8ayh.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-DzMK8ayh.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 { 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 'fix-review': 'Fix 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\n useEffect(() => {\n setLines(null);\n fetchTaskLogLines(id)\n .then((data) => setLines(data.lines))\n .catch(() => setLines([]));\n }, [id]);\n\n if (lines === null) return <p style={{ opacity: 0.5, margin: 0 }}>Loading…</p>;\n if (lines.length === 0) return <p style={{ opacity: 0.5, margin: 0 }}>No output recorded.</p>;\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","useEffect","fetchTaskLogLines","data","jsx","fontFamily","ChevronRightIcon","size","TaskRow","entry","highlighted","expanded","setExpanded","toggle","v","jsxs","space","e","Card","AGENT_LABELS","Stamp","color","TasksPage","taskLog","useAppStore","s","taskLogLoading","loadTaskLog","taskId","useSearch","containerRef","useRef","row","_a","sorted","b","groups","key","group","PageTitle"],"mappings":"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"}
|