create-harness-vibe-coding 0.8.18 → 0.8.19
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/CHANGELOG.md +13 -0
- package/README.md +1 -0
- package/package.json +5 -2
- package/src/index.js +383 -267
- package/src/ui/dist/assets/AgentsRoute-CuSKYmFu.js +17 -0
- package/src/ui/dist/assets/AgentsRoute-CuSKYmFu.js.map +1 -0
- package/src/ui/dist/assets/RolesRoute-DOzTYVRm.js +7 -0
- package/src/ui/dist/assets/RolesRoute-DOzTYVRm.js.map +1 -0
- package/src/ui/dist/assets/SettingsRoute-DPU7jSQm.js +12 -0
- package/src/ui/dist/assets/SettingsRoute-DPU7jSQm.js.map +1 -0
- package/src/ui/dist/assets/TaskList-BN4r8s1i.js +50 -0
- package/src/ui/dist/assets/TaskList-BN4r8s1i.js.map +1 -0
- package/src/ui/dist/assets/TerminalDrawer-6GBZ9nXN.css +32 -0
- package/src/ui/dist/assets/TerminalDrawer-Cej4PxsH.js +74 -0
- package/src/ui/dist/assets/TerminalDrawer-Cej4PxsH.js.map +1 -0
- package/src/ui/dist/assets/WorkflowRoute-BnuhLJ6X.css +1 -0
- package/src/ui/dist/assets/WorkflowRoute-C-clKe-j.js +39 -0
- package/src/ui/dist/assets/WorkflowRoute-C-clKe-j.js.map +1 -0
- package/src/ui/dist/assets/index-BOVYWntB.js +117 -0
- package/src/ui/dist/assets/index-BOVYWntB.js.map +1 -0
- package/src/ui/dist/assets/index-DaUObq0H.css +1 -0
- package/src/ui/dist/assets/maximize-2-LNrr_rKr.js +7 -0
- package/src/ui/dist/assets/maximize-2-LNrr_rKr.js.map +1 -0
- package/src/ui/dist/assets/plus-QuTJyoT3.js +7 -0
- package/src/ui/dist/assets/plus-QuTJyoT3.js.map +1 -0
- package/src/ui/dist/assets/proxy-D0vUbds5.js +2 -0
- package/src/ui/dist/assets/proxy-D0vUbds5.js.map +1 -0
- package/src/ui/dist/assets/refresh-cw-JNmExijd.js +7 -0
- package/src/ui/dist/assets/refresh-cw-JNmExijd.js.map +1 -0
- package/src/ui/dist/assets/terminal-BBQvnOAK.js +7 -0
- package/src/ui/dist/assets/terminal-BBQvnOAK.js.map +1 -0
- package/src/ui/dist/assets/useReducedMotion-BqmH0Tf7.js +7 -0
- package/src/ui/dist/assets/useReducedMotion-BqmH0Tf7.js.map +1 -0
- package/src/ui/dist/assets/x-DoIOGAJz.js +7 -0
- package/src/ui/dist/assets/x-DoIOGAJz.js.map +1 -0
- package/src/ui/dist/index.html +18 -0
- package/src/ui/index.html +17 -0
- package/src/ui/package.json +33 -0
- package/src/ui/pnpm-lock.yaml +1582 -0
- package/src/ui/pnpm-workspace.yaml +2 -0
- package/src/ui/src/App.tsx +86 -0
- package/src/ui/src/api.ts +93 -0
- package/src/ui/src/components/AgentsRoute.tsx +503 -0
- package/src/ui/src/components/Footer.tsx +69 -0
- package/src/ui/src/components/Header.tsx +175 -0
- package/src/ui/src/components/LoadingView.tsx +22 -0
- package/src/ui/src/components/RolesRoute.tsx +169 -0
- package/src/ui/src/components/SettingsRoute.tsx +166 -0
- package/src/ui/src/components/TaskList.tsx +388 -0
- package/src/ui/src/components/TerminalDrawer.tsx +611 -0
- package/src/ui/src/components/WorkflowRoute.tsx +670 -0
- package/src/ui/src/hooks/useReducedMotion.ts +17 -0
- package/src/ui/src/hooks/useServerConnection.ts +114 -0
- package/src/ui/src/index.css +281 -0
- package/src/ui/src/main.tsx +11 -0
- package/src/ui/src/types.ts +108 -0
- package/src/ui/tsconfig.json +21 -0
- package/src/ui/vite.config.ts +19 -0
- package/src/wf-ui-server/__tests__/a2a-store.test.mjs +79 -0
- package/src/wf-ui-server/__tests__/peer-capsule.test.mjs +268 -0
- package/src/wf-ui-server/__tests__/pty-adapter.test.mjs +70 -0
- package/src/wf-ui-server/__tests__/runtime-config.test.mjs +43 -0
- package/src/wf-ui-server/__tests__/runtime-detector.test.mjs +90 -0
- package/src/wf-ui-server/__tests__/security.test.mjs +59 -0
- package/src/wf-ui-server/__tests__/server.integration.test.mjs +150 -0
- package/src/wf-ui-server/__tests__/session-registry.test.mjs +238 -0
- package/src/wf-ui-server/__tests__/settings.test.mjs +135 -0
- package/src/wf-ui-server/__tests__/task-parser.test.mjs +200 -0
- package/src/wf-ui-server/__tests__/terminal-store.test.mjs +138 -0
- package/src/wf-ui-server/__tests__/token.test.mjs +48 -0
- package/src/wf-ui-server/__tests__/ws-events.integration.test.mjs +419 -0
- package/src/wf-ui-server/__tests__/ws-terminal.integration.test.mjs +383 -0
- package/src/wf-ui-server/a2a-store.mjs +296 -0
- package/src/wf-ui-server/peer-capsule.mjs +213 -0
- package/src/wf-ui-server/pty-adapter.mjs +155 -0
- package/src/wf-ui-server/runtime-config.mjs +153 -0
- package/src/wf-ui-server/runtime-detector.mjs +374 -0
- package/src/wf-ui-server/security.mjs +67 -0
- package/src/wf-ui-server/server.mjs +849 -0
- package/src/wf-ui-server/session-registry.mjs +204 -0
- package/src/wf-ui-server/settings.mjs +100 -0
- package/src/wf-ui-server/task-parser.mjs +133 -0
- package/src/wf-ui-server/terminal-store.mjs +225 -0
- package/src/wf-ui-server/token.mjs +41 -0
- package/src/wf-ui-server/ws-events.mjs +354 -0
- package/src/wf-ui-server/ws-terminal.mjs +473 -0
- package/templates/common/.claude/commands/wf-help.md +1 -0
- package/templates/common/.claude/commands/wf-task-list.md +2 -0
- package/templates/common/.claude/commands/wf-ui.md +26 -0
- package/templates/common/.claude/commands/wf-update.md +54 -9
- package/templates/common/.claude/rules/ecc/common.md +1 -1
- package/templates/common/.claude/skills/wf-auto/SKILL.md +3 -3
- package/templates/common/.claude/skills/wf-auto-spark/SKILL.md +2 -2
- package/templates/common/.claude/skills/wf-ui/SKILL.md +78 -0
- package/templates/common/.claude/skills/wf-update/SKILL.md +55 -58
- package/templates/common/.harness-version +63 -39
- package/templates/common/.opencode/commands/wf-help.md +1 -0
- package/templates/common/.opencode/commands/wf-task-list.md +2 -0
- package/templates/common/.opencode/commands/wf-ui.md +26 -0
- package/templates/common/.opencode/commands/wf-update.md +54 -9
- package/templates/common/CLAUDE.md +1 -1
- package/templates/common/Harness/MEMORY.md +2 -0
- package/templates/common/Harness/README.md +6 -4
- package/templates/common/Harness/a2a/role-graph.json +79 -0
- package/templates/common/Harness/a2a/runtime-registry.json +5 -0
- package/templates/common/Harness/a2a/skills/terminal-control.json +15 -0
- package/templates/common/Harness/ownership.manifest.json +57 -2
- package/templates/common/Harness/scripts/README.md +134 -0
- package/templates/common/Harness/scripts/a2a-terminal.mjs +191 -0
- package/templates/common/Harness/scripts/context-budget.mjs +1 -1
- package/templates/common/Harness/scripts/sync-host-global.mjs +278 -0
- package/templates/common/Harness/scripts/task-state.mjs +556 -23
- package/templates/common/Harness/scripts/validate-harness.mjs +229 -19
- package/templates/common/Harness/scripts/wf-remove.mjs +8 -3
- package/templates/common/Harness/scripts/wf-update-check.mjs +37 -9
- package/templates/common/Harness/scripts/wf-update-runner.mjs +325 -0
- package/templates/common/Harness/settings.json +35 -0
- package/templates/common/Harness/specs/protocols/TASK_ARCHIVE.md +7 -2
- package/templates/common/Harness/specs/runtime/command-surface.json +14 -0
- package/templates/common/Harness/specs/workflows/WF-AUTO-SPARK.md +8 -8
- package/templates/common/Harness/specs/workflows/WF-AUTO.md +12 -12
- package/templates/common/Harness/tasks/_template/NAMING.md +16 -16
- package/templates/common/Harness/tasks/_template/PLAN.md +17 -60
- package/templates/common/Harness/tasks/_template/PROBLEM.md +18 -0
- package/templates/common/Harness/tasks/_template/PROGRESS.md +9 -14
- package/templates/common/Harness/tasks/_template/REFERENCES.md +26 -0
- package/templates/common/Harness/tasks/_template/ARTIFACTS.md +0 -3
- package/templates/common/Harness/tasks/_template/NOTES.md +0 -3
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import{c as A,r,j as e,L as se,B as me,i as E,a as ie,b as C}from"./index-BOVYWntB.js";import{u as ve,S as ye}from"./useReducedMotion-BqmH0Tf7.js";import{R as be}from"./refresh-cw-JNmExijd.js";import{P as Se}from"./plus-QuTJyoT3.js";import{m as je}from"./proxy-D0vUbds5.js";import{T as ne}from"./terminal-BBQvnOAK.js";/**
|
|
2
|
+
* @license lucide-react v0.400.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const we=A("Check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]]);/**
|
|
7
|
+
* @license lucide-react v0.400.0 - ISC
|
|
8
|
+
*
|
|
9
|
+
* This source code is licensed under the ISC license.
|
|
10
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
+
*/const ke=A("ExternalLink",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);/**
|
|
12
|
+
* @license lucide-react v0.400.0 - ISC
|
|
13
|
+
*
|
|
14
|
+
* This source code is licensed under the ISC license.
|
|
15
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
16
|
+
*/const Ce=A("Settings2",[["path",{d:"M20 7h-9",key:"3s1dr2"}],["path",{d:"M14 17H5",key:"gfn3mx"}],["circle",{cx:"17",cy:"17",r:"3",key:"18b49y"}],["circle",{cx:"7",cy:"7",r:"3",key:"dfmy0x"}]]),I=5,z={border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg)"};function re(s){return s==="running"||s==="available"?"#166534":s==="blocked"||s==="missing"?"#991b1b":s==="starting"?"#d97706":"#6b7280"}function O(s){if(!s)return"";const g=s.split(/[\\/]/).filter(Boolean);return g.length>4?`.../${g.slice(-3).join("/")}`:s}function Le({onSelectSession:s}){var te;const[g,u]=r.useState([]),[c,b]=r.useState([]),[h,oe]=r.useState([]),[B,H]=r.useState(!1),[S,de]=r.useState(!1),[f,R]=r.useState(0),[T,N]=r.useState(""),[F,U]=r.useState(""),[M,V]=r.useState(!1),[le,ce]=r.useState(()=>new Set),q=r.useRef(new Set),[pe,ge]=r.useState(!0),[J,p]=r.useState(null),[m,D]=r.useState(null),[d,_]=r.useState(null),[G,P]=r.useState({}),[W,K]=r.useState("user"),[Z,L]=r.useState(null),ue=ve(),j=r.useMemo(()=>h.find(t=>t.id===T)||null,[h,T]),Q=g,v=Math.max(1,Math.ceil(c.length/I)),fe=c.slice(f*I,f*I+I),w=t=>{ce(i=>{const n=t(i);return q.current=n,n})},y=async(t=!1)=>{try{t&&E("/api/runtimes");const[i,n,a]=await Promise.all([ie(t?"/api/runtimes?refresh=1":"/api/runtimes",{ttlMs:12e3,refresh:t}),C("/api/sessions"),S?ie("/api/sessions?all=1",{ttlMs:t?0:3e3,refresh:t}).catch(()=>[]):Promise.resolve([])]),l=q.current;oe(i),u(n.filter(o=>!l.has(o.sessionId))),b(a.filter(o=>o.status!=="running"&&o.status!=="starting")),w(o=>{if(o.size===0)return o;const $=new Set(n.map(k=>k.sessionId));return new Set([...o].filter(k=>$.has(k)))}),N(o=>{var $;return o&&i.some(k=>k.id===o)?o:(($=i[0])==null?void 0:$.id)||""}),p(null)}catch(i){p((i==null?void 0:i.message)||"Failed to load agent terminals")}finally{ge(!1)}};r.useEffect(()=>{y();const t=setInterval(()=>y(!1),1200),i=n=>{const a=n.detail;if(a!=null&&a.sessionId&&a.state==="stopping"){w(l=>new Set(l).add(a.sessionId)),u(l=>l.filter(o=>o.sessionId!==a.sessionId));return}a!=null&&a.sessionId&&a.state==="saved"&&(w(l=>{const o=new Set(l);return o.delete(a.sessionId),o}),u(l=>l.filter(o=>o.sessionId!==a.sessionId))),y(!0)};return window.addEventListener("harness:sessions-changed",i),()=>{clearInterval(t),window.removeEventListener("harness:sessions-changed",i)}},[S]),r.useEffect(()=>{R(t=>Math.min(t,Math.max(0,v-1)))},[v]);const X=async t=>{D(t),_(null),P({}),L(null);try{const i=await C(`/api/runtimes/${encodeURIComponent(t)}/config`);_(i);const n=i.files.find(a=>a.writable)||i.files[0];K((n==null?void 0:n.scope)||"user"),P({...(n==null?void 0:n.values)||{}})}catch(i){p((i==null?void 0:i.message)||"Failed to load runtime config")}},x=(d==null?void 0:d.files.find(t=>t.scope===W&&t.writable))||(d==null?void 0:d.files.find(t=>t.writable))||null,xe=t=>{const i=(d==null?void 0:d.files.find(n=>n.scope===t))||null;K(t),P({...(i==null?void 0:i.values)||{}}),L(null)},he=async()=>{if(!(!m||!x)){L(null);try{const t=await C(`/api/runtimes/${encodeURIComponent(m)}/config`,{method:"POST",body:JSON.stringify({scope:x.scope,values:G})});L(t.backupPath?`Saved with backup: ${O(t.backupPath)}`:`Saved: ${t.path}`),await X(m)}catch(t){p((t==null?void 0:t.message)||"Failed to save runtime config")}}},Y=async(t=T)=>{if(t){V(!0),p(null);try{const i=await C("/api/sessions",{method:"POST",body:JSON.stringify({runtime:t,model:F.trim(),role:"terminal-agent",objective:"Manual Harness agent terminal",subagentMode:"wf-subagents"})});E("/api/sessions"),H(!1),U(""),await y(),s(i.sessionId)}catch(i){p((i==null?void 0:i.message)||"Session launch failed")}finally{V(!1)}}},ee=async t=>{const i=g;w(n=>new Set(n).add(t)),u(n=>n.filter(a=>a.sessionId!==t));try{await C(`/api/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"}),E("/api/sessions"),E("/api/sessions?all=1"),window.dispatchEvent(new CustomEvent("harness:sessions-changed")),await y()}catch(n){u(i),p((n==null?void 0:n.message)||"Stop failed")}finally{w(n=>{const a=new Set(n);return a.delete(t),a})}};return pe?e.jsx(se,{label:"Loading agent terminals"}):e.jsxs("div",{style:{display:"grid",gap:14},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:10},children:[e.jsxs("h2",{style:{fontSize:12,fontWeight:600,textTransform:"uppercase",letterSpacing:"0.05em",color:"var(--muted)",margin:0,display:"flex",alignItems:"center",gap:5},children:[e.jsx(me,{size:14})," Agent Terminals"]}),e.jsxs("div",{style:{display:"flex",gap:6},children:[e.jsx("button",{onClick:()=>{de(t=>!t),R(0)},title:"Show saved terminal sessions",style:{fontSize:10,color:S?"var(--fg)":"var(--muted)",display:"flex",alignItems:"center",gap:4,border:"1px solid var(--border)",borderRadius:"var(--radius)",padding:"4px 8px",background:S?"var(--surface)":"var(--bg)"},children:"Saved"}),e.jsxs("button",{onClick:()=>y(!0),title:"Scan PATH again",style:{fontSize:10,color:"var(--muted)",display:"flex",alignItems:"center",gap:4,border:"1px solid var(--border)",borderRadius:"var(--radius)",padding:"4px 8px"},children:[e.jsx(be,{size:11})," Scan"]})]})]}),J&&e.jsxs("div",{style:{fontSize:11,color:"#991b1b",padding:"7px 9px",background:"#fef2f2",borderRadius:"var(--radius)"},children:[J,e.jsx("button",{onClick:()=>p(null),style:{marginLeft:8,fontSize:10,color:"#991b1b",textDecoration:"underline"},children:"dismiss"})]}),e.jsxs("section",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(220px, 1fr))",gap:8},children:[e.jsxs("button",{"data-testid":"agent-add-box",onClick:()=>H(t=>!t),style:{...z,minHeight:132,borderStyle:"dashed",display:"grid",placeItems:"center",textAlign:"center",padding:16,color:"var(--fg)",background:B?"var(--surface)":"var(--bg)"},children:[e.jsx("span",{style:{width:34,height:34,borderRadius:"var(--radius)",border:"1px solid var(--border)",display:"grid",placeItems:"center",marginBottom:8},children:e.jsx(Se,{size:18})}),e.jsx("span",{style:{fontSize:13,fontWeight:600},children:"New Agent Terminal"}),e.jsx("span",{style:{fontSize:10,color:"var(--muted)",marginTop:2},children:"Choose a detected terminal platform"})]}),h.map(t=>e.jsxs(je.div,{"data-testid":"detected-runtime-card",initial:ue?void 0:{opacity:0,y:4},animate:{opacity:1,y:0},style:{...z,padding:10,minHeight:132,display:"grid",alignContent:"space-between",gap:8},children:[e.jsxs("div",{style:{minWidth:0},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:7,minWidth:0},children:[e.jsx("span",{style:{width:7,height:7,borderRadius:"50%",background:re(t.status),flexShrink:0}}),e.jsx("span",{style:{fontSize:13,fontWeight:600,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.label}),e.jsx("span",{style:{fontSize:9,color:"var(--muted)",border:"1px solid var(--border)",borderRadius:99,padding:"0 5px",flexShrink:0},children:t.command})]}),e.jsx("div",{title:t.path||"",style:{fontSize:10,color:"var(--muted)",marginTop:5,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:O(t.path)}),e.jsx("div",{style:{fontSize:10,color:"var(--muted)",marginTop:3,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.version||t.capabilities.slice(0,3).join(" / ")})]}),e.jsxs("div",{style:{display:"flex",gap:5},children:[e.jsxs("button",{onClick:()=>Y(t.id),disabled:M,style:{flex:1,fontSize:10,fontWeight:600,color:"#fff",background:"#111",borderRadius:"var(--radius)",padding:"5px 8px",display:"flex",alignItems:"center",justifyContent:"center",gap:4,opacity:M?.5:1},children:[e.jsx(ne,{size:11})," Start"]}),e.jsx("button",{onClick:()=>X(t.id),title:"Configure runtime",style:{width:28,height:27,display:"grid",placeItems:"center",border:"1px solid var(--border)",borderRadius:"var(--radius)",color:"var(--muted)"},children:e.jsx(Ce,{size:12})})]})]},t.id))]}),B&&e.jsx("section",{style:{...z,padding:12,display:"grid",gap:10},children:h.length===0?e.jsx("div",{style:{fontSize:11,color:"var(--muted)",textAlign:"center",padding:16},children:"No detected terminal agents. Run Scan after installing a CLI on PATH."}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{display:"grid",gridTemplateColumns:"minmax(160px, 240px) minmax(120px, 220px) auto",gap:8,alignItems:"end"},children:[e.jsxs("label",{style:{fontSize:10,color:"var(--muted)",display:"grid",gap:3},children:["Platform",e.jsx("select",{value:T,onChange:t=>N(t.target.value),style:{padding:"6px 8px",fontSize:11,border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg)"},children:h.map(t=>e.jsx("option",{value:t.id,children:t.label},t.id))})]}),e.jsxs("label",{style:{fontSize:10,color:"var(--muted)",display:"grid",gap:3},children:["Model Override",e.jsx("input",{value:F,onChange:t=>U(t.target.value),placeholder:"optional",style:{padding:"6px 8px",fontSize:11,border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg)"}})]}),e.jsx("button",{onClick:()=>Y(),disabled:!j||M,style:{height:31,padding:"0 14px",fontSize:11,fontWeight:600,borderRadius:"var(--radius)",background:"#111",color:"#fff",opacity:!j||M?.5:1},children:"Start Terminal"})]}),e.jsx("div",{style:{fontSize:10,color:"var(--muted)"},children:j?`${j.command} from ${O(j.path)}`:"Only detected runtimes are listed."})]})}),m&&e.jsxs("section",{style:{...z,padding:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:10,marginBottom:10},children:[e.jsxs("div",{children:[e.jsxs("div",{style:{fontSize:12,fontWeight:600},children:[((te=h.find(t=>t.id===m))==null?void 0:te.label)||m," Config"]}),e.jsx("div",{style:{fontSize:10,color:"var(--muted)"},children:"Known global/project config files. Authentication files are shown read-only unless a safe model field is known."})]}),e.jsx("button",{onClick:()=>D(null),style:{fontSize:10,color:"var(--muted)",border:"1px solid var(--border)",borderRadius:"var(--radius)",padding:"3px 8px"},children:"Close"})]}),d?d.files.length===0?e.jsx("div",{style:{fontSize:11,color:"var(--muted)"},children:"No editable config path is known for this CLI yet."}):e.jsxs("div",{style:{display:"grid",gridTemplateColumns:"minmax(170px, 260px) minmax(0, 1fr)",gap:12},children:[e.jsx("div",{style:{display:"grid",gap:5},children:d.files.map(t=>e.jsxs("button",{onClick:()=>xe(t.scope),style:{textAlign:"left",border:`1px solid ${W===t.scope?"#111":"var(--border)"}`,borderRadius:"var(--radius)",padding:8,background:W===t.scope?"var(--surface)":"var(--bg)"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:5,fontSize:11,fontWeight:600},children:[t.exists&&e.jsx(we,{size:11,color:"#166534"})," ",t.scope]}),e.jsx("div",{style:{fontSize:10,color:"var(--muted)",marginTop:3,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.path})]},`${t.scope}-${t.path}`))}),e.jsxs("div",{children:[x?e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{fontSize:10,color:"var(--muted)",marginBottom:8},children:[x.format," / ",x.exists?"existing":"will create"," / ",O(x.absolutePath)]}),e.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(140px, 1fr))",gap:8},children:Object.keys(x.fields).map(t=>e.jsxs("label",{style:{fontSize:10,color:"var(--muted)",display:"grid",gap:3},children:[t,e.jsx("input",{value:G[t]||"",onChange:i=>P(n=>({...n,[t]:i.target.value})),style:{padding:"6px 8px",fontSize:11,border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg)"}})]},t))}),e.jsx("button",{onClick:he,style:{marginTop:10,fontSize:11,fontWeight:600,color:"#fff",background:"#111",borderRadius:"var(--radius)",padding:"6px 12px"},children:"Save Config"})]}):e.jsx("div",{style:{fontSize:11,color:"var(--muted)"},children:"This config file is read-only in Harness UI."}),Z&&e.jsx("div",{style:{fontSize:10,color:"#166534",marginTop:8},children:Z})]})]}):e.jsx(se,{label:"Loading runtime config"})]}),e.jsxs("section",{children:[e.jsx("div",{style:{fontSize:10,fontWeight:600,color:"var(--muted)",textTransform:"uppercase",marginBottom:6},children:"Running Terminals"}),Q.length===0?e.jsxs("div",{"data-testid":"agents-empty",style:{padding:28,color:"var(--muted)",textAlign:"center",fontSize:11,border:"1px solid var(--border)",borderRadius:"var(--radius)"},children:[e.jsx(ne,{size:26,style:{marginBottom:8,opacity:.35}}),e.jsx("p",{style:{marginBottom:3,fontWeight:500},children:"No running agent terminal."}),e.jsx("p",{children:"Use the plus box to start a detected CLI."})]}):e.jsx("div",{"data-testid":"agents-list",style:{display:"grid",gap:5},children:Q.map(t=>e.jsx(ae,{session:t,onSelectSession:s,onStop:ee,stopping:le.has(t.sessionId)},t.sessionId))})]}),S&&c.length>0&&e.jsxs("section",{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,marginBottom:6},children:[e.jsxs("div",{style:{fontSize:10,fontWeight:600,color:"var(--muted)",textTransform:"uppercase"},children:["Saved Sessions (",c.length,")"]}),c.length>I&&e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:5,fontSize:10,color:"var(--muted)"},children:[e.jsx("button",{onClick:()=>R(t=>Math.max(0,t-1)),disabled:f===0,style:{border:"1px solid var(--border)",borderRadius:"var(--radius)",padding:"2px 7px",opacity:f===0?.45:1},children:"Prev"}),e.jsxs("span",{children:[f+1," / ",v]}),e.jsx("button",{onClick:()=>R(t=>Math.min(v-1,t+1)),disabled:f>=v-1,style:{border:"1px solid var(--border)",borderRadius:"var(--radius)",padding:"2px 7px",opacity:f>=v-1?.45:1},children:"Next"})]})]}),e.jsx("div",{style:{display:"grid",gap:5},children:fe.map(t=>e.jsx(ae,{session:t,onSelectSession:s,onStop:ee,muted:!0},t.sessionId))})]})]})}function ae({session:s,onSelectSession:g,onStop:u,muted:c=!1,stopping:b=!1}){return e.jsxs("div",{"data-testid":"agent-row",style:{...z,padding:9,opacity:c?.68:1},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,minWidth:0},children:[e.jsx("span",{style:{width:7,height:7,borderRadius:"50%",background:re(s.status),flexShrink:0}}),e.jsx("span",{style:{fontSize:12,fontWeight:600},children:s.runtime}),e.jsx("span",{style:{fontSize:10,color:"var(--muted)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:s.peerId||s.sessionId})]}),e.jsxs("div",{style:{display:"flex",gap:4,flexShrink:0},children:[e.jsxs("button",{onClick:()=>g(s.sessionId),style:{fontSize:10,padding:"3px 8px",border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg)",display:"flex",alignItems:"center",gap:3},children:[e.jsx(ke,{size:9})," Terminal"]}),!c&&e.jsxs("button",{onClick:()=>u(s.sessionId),disabled:b,style:{fontSize:10,padding:"3px 8px",border:"1px solid #991b1b",borderRadius:"var(--radius)",color:"#991b1b",background:"var(--bg)",display:"flex",alignItems:"center",gap:3},children:[e.jsx(ye,{size:9})," ",b?"Stopping":"Stop"]})]})]}),e.jsxs("div",{style:{fontSize:10,color:"var(--muted)",marginTop:4},children:[[b?"stopping":s.status,s.role,s.workflowMode||null,s.ptyProvider||null,s.taskId||null,`${s.wsClientCount??0} viewer(s)`].filter(Boolean).join(" / "),s.model?` / ${s.model}`:"",s.resumeCommand?` / resume: ${s.resumeCommand}`:"",s.blockedReason?` / ${s.blockedReason}`:"",s.blockedHint?` / ${s.blockedHint}`:""]})]})}export{Le as default};
|
|
17
|
+
//# sourceMappingURL=AgentsRoute-CuSKYmFu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentsRoute-CuSKYmFu.js","sources":["../../node_modules/.pnpm/lucide-react@0.400.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/check.js","../../node_modules/.pnpm/lucide-react@0.400.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/external-link.js","../../node_modules/.pnpm/lucide-react@0.400.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/settings-2.js","../../src/components/AgentsRoute.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Check = createLucideIcon(\"Check\", [[\"path\", { d: \"M20 6 9 17l-5-5\", key: \"1gmf2c\" }]]);\n\nexport { Check as default };\n//# sourceMappingURL=check.js.map\n","/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ExternalLink = createLucideIcon(\"ExternalLink\", [\n [\"path\", { d: \"M15 3h6v6\", key: \"1q9fwt\" }],\n [\"path\", { d: \"M10 14 21 3\", key: \"gplh6r\" }],\n [\"path\", { d: \"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\", key: \"a6xqqp\" }]\n]);\n\nexport { ExternalLink as default };\n//# sourceMappingURL=external-link.js.map\n","/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Settings2 = createLucideIcon(\"Settings2\", [\n [\"path\", { d: \"M20 7h-9\", key: \"3s1dr2\" }],\n [\"path\", { d: \"M14 17H5\", key: \"gfn3mx\" }],\n [\"circle\", { cx: \"17\", cy: \"17\", r: \"3\", key: \"18b49y\" }],\n [\"circle\", { cx: \"7\", cy: \"7\", r: \"3\", key: \"dfmy0x\" }]\n]);\n\nexport { Settings2 as default };\n//# sourceMappingURL=settings-2.js.map\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport type { CSSProperties } from 'react';\nimport { Bot, Check, ExternalLink, Plus, RefreshCw, Settings2, Square, Terminal } from 'lucide-react';\nimport { motion } from 'motion/react';\nimport { apiJson, apiJsonCached, invalidateApiCache } from '../api';\nimport { useReducedMotion } from '../hooks/useReducedMotion';\nimport type { RuntimeConfigFile, RuntimeInfo, Session } from '../types';\nimport LoadingView from './LoadingView';\n\ntype Props = { onSelectSession: (sessionId: string) => void };\ntype RuntimeConfig = { runtime: string; files: RuntimeConfigFile[] };\nconst SAVED_PAGE_SIZE = 5;\n\nconst PANEL: CSSProperties = {\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius)',\n background: 'var(--bg)',\n};\n\nfunction statusColor(status: string) {\n if (status === 'running' || status === 'available') return '#166534';\n if (status === 'blocked' || status === 'missing') return '#991b1b';\n if (status === 'starting') return '#d97706';\n return '#6b7280';\n}\n\nfunction compactPath(value: string | null | undefined) {\n if (!value) return '';\n const parts = value.split(/[\\\\/]/).filter(Boolean);\n return parts.length > 4 ? `.../${parts.slice(-3).join('/')}` : value;\n}\n\nexport default function AgentsRoute({ onSelectSession }: Props) {\n const [sessions, setSessions] = useState<Session[]>([]);\n const [savedSessions, setSavedSessions] = useState<Session[]>([]);\n const [runtimes, setRuntimes] = useState<RuntimeInfo[]>([]);\n const [launcherOpen, setLauncherOpen] = useState(false);\n const [showSaved, setShowSaved] = useState(false);\n const [savedPage, setSavedPage] = useState(0);\n const [selectedRuntimeId, setSelectedRuntimeId] = useState('');\n const [launchModel, setLaunchModel] = useState('');\n const [creating, setCreating] = useState(false);\n const [stoppingIds, setStoppingIds] = useState<Set<string>>(() => new Set());\n const stoppingIdsRef = useRef<Set<string>>(new Set());\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [configRuntimeId, setConfigRuntimeId] = useState<string | null>(null);\n const [runtimeConfig, setRuntimeConfig] = useState<RuntimeConfig | null>(null);\n const [configValues, setConfigValues] = useState<Record<string, string>>({});\n const [configScope, setConfigScope] = useState('user');\n const [configSaved, setConfigSaved] = useState<string | null>(null);\n const reducedMotion = useReducedMotion();\n\n const selectedRuntime = useMemo(\n () => runtimes.find(runtime => runtime.id === selectedRuntimeId) || null,\n [runtimes, selectedRuntimeId],\n );\n\n const runningSessions = sessions;\n const savedPageCount = Math.max(1, Math.ceil(savedSessions.length / SAVED_PAGE_SIZE));\n const visibleSavedSessions = savedSessions.slice(\n savedPage * SAVED_PAGE_SIZE,\n savedPage * SAVED_PAGE_SIZE + SAVED_PAGE_SIZE,\n );\n\n const updateStoppingIds = (updater: (current: Set<string>) => Set<string>) => {\n setStoppingIds(current => {\n const next = updater(current);\n stoppingIdsRef.current = next;\n return next;\n });\n };\n\n const loadControlPlane = async (refresh = false) => {\n try {\n if (refresh) invalidateApiCache('/api/runtimes');\n const [runtimeRows, sessionRows, allRows] = await Promise.all([\n apiJsonCached<RuntimeInfo[]>(refresh ? '/api/runtimes?refresh=1' : '/api/runtimes', { ttlMs: 12000, refresh }),\n apiJson<Session[]>('/api/sessions'),\n showSaved\n ? apiJsonCached<Session[]>('/api/sessions?all=1', { ttlMs: refresh ? 0 : 3000, refresh }).catch(() => [])\n : Promise.resolve([]),\n ]);\n const pendingStops = stoppingIdsRef.current;\n setRuntimes(runtimeRows);\n setSessions(sessionRows.filter(session => !pendingStops.has(session.sessionId)));\n setSavedSessions(allRows.filter(session => session.status !== 'running' && session.status !== 'starting'));\n updateStoppingIds(current => {\n if (current.size === 0) return current;\n const liveIds = new Set(sessionRows.map(session => session.sessionId));\n return new Set([...current].filter(id => liveIds.has(id)));\n });\n setSelectedRuntimeId(current => current && runtimeRows.some(row => row.id === current)\n ? current\n : runtimeRows[0]?.id || '');\n setError(null);\n } catch (e: any) {\n setError(e?.message || 'Failed to load agent terminals');\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n loadControlPlane();\n const interval = setInterval(() => loadControlPlane(false), 1200);\n const onSessionsChanged = (event: Event) => {\n const detail = (event as CustomEvent<{ sessionId?: string; state?: string }>).detail;\n if (detail?.sessionId && detail.state === 'stopping') {\n updateStoppingIds(current => new Set(current).add(detail.sessionId!));\n setSessions(current => current.filter(session => session.sessionId !== detail.sessionId));\n return;\n }\n if (detail?.sessionId && detail.state === 'saved') {\n updateStoppingIds(current => {\n const next = new Set(current);\n next.delete(detail.sessionId!);\n return next;\n });\n setSessions(current => current.filter(session => session.sessionId !== detail.sessionId));\n }\n loadControlPlane(true);\n };\n window.addEventListener('harness:sessions-changed', onSessionsChanged);\n return () => {\n clearInterval(interval);\n window.removeEventListener('harness:sessions-changed', onSessionsChanged);\n };\n }, [showSaved]);\n\n useEffect(() => {\n setSavedPage(page => Math.min(page, Math.max(0, savedPageCount - 1)));\n }, [savedPageCount]);\n\n const openConfig = async (runtimeId: string) => {\n setConfigRuntimeId(runtimeId);\n setRuntimeConfig(null);\n setConfigValues({});\n setConfigSaved(null);\n try {\n const data = await apiJson<RuntimeConfig>(`/api/runtimes/${encodeURIComponent(runtimeId)}/config`);\n setRuntimeConfig(data);\n const writable = data.files.find(file => file.writable) || data.files[0];\n setConfigScope(writable?.scope || 'user');\n setConfigValues({ ...(writable?.values || {}) });\n } catch (e: any) {\n setError(e?.message || 'Failed to load runtime config');\n }\n };\n\n const selectedConfigFile = runtimeConfig?.files.find(file => file.scope === configScope && file.writable)\n || runtimeConfig?.files.find(file => file.writable)\n || null;\n\n const switchConfigScope = (scope: string) => {\n const nextFile = runtimeConfig?.files.find(file => file.scope === scope) || null;\n setConfigScope(scope);\n setConfigValues({ ...(nextFile?.values || {}) });\n setConfigSaved(null);\n };\n\n const saveConfig = async () => {\n if (!configRuntimeId || !selectedConfigFile) return;\n setConfigSaved(null);\n try {\n const result = await apiJson<{ path: string; backupPath?: string | null }>(\n `/api/runtimes/${encodeURIComponent(configRuntimeId)}/config`,\n {\n method: 'POST',\n body: JSON.stringify({ scope: selectedConfigFile.scope, values: configValues }),\n },\n );\n setConfigSaved(result.backupPath ? `Saved with backup: ${compactPath(result.backupPath)}` : `Saved: ${result.path}`);\n await openConfig(configRuntimeId);\n } catch (e: any) {\n setError(e?.message || 'Failed to save runtime config');\n }\n };\n\n const createSession = async (runtimeId = selectedRuntimeId) => {\n if (!runtimeId) return;\n setCreating(true);\n setError(null);\n try {\n const session = await apiJson<Session>('/api/sessions', {\n method: 'POST',\n body: JSON.stringify({\n runtime: runtimeId,\n model: launchModel.trim(),\n role: 'terminal-agent',\n objective: 'Manual Harness agent terminal',\n subagentMode: 'wf-subagents',\n }),\n });\n invalidateApiCache('/api/sessions');\n setLauncherOpen(false);\n setLaunchModel('');\n await loadControlPlane();\n onSelectSession(session.sessionId);\n } catch (e: any) {\n setError(e?.message || 'Session launch failed');\n } finally {\n setCreating(false);\n }\n };\n\n const stopSession = async (sessionId: string) => {\n const previous = sessions;\n updateStoppingIds(current => new Set(current).add(sessionId));\n setSessions(current => current.filter(session => session.sessionId !== sessionId));\n try {\n await apiJson(`/api/sessions/${encodeURIComponent(sessionId)}/stop`, { method: 'POST' });\n invalidateApiCache('/api/sessions');\n invalidateApiCache('/api/sessions?all=1');\n window.dispatchEvent(new CustomEvent('harness:sessions-changed'));\n await loadControlPlane();\n } catch (e: any) {\n setSessions(previous);\n setError(e?.message || 'Stop failed');\n } finally {\n updateStoppingIds(current => {\n const next = new Set(current);\n next.delete(sessionId);\n return next;\n });\n }\n };\n\n if (loading) {\n return <LoadingView label=\"Loading agent terminals\" />;\n }\n\n return (\n <div style={{ display: 'grid', gap: 14 }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 }}>\n <h2 style={{ fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--muted)', margin: 0, display: 'flex', alignItems: 'center', gap: 5 }}>\n <Bot size={14} /> Agent Terminals\n </h2>\n <div style={{ display: 'flex', gap: 6 }}>\n <button onClick={() => { setShowSaved(value => !value); setSavedPage(0); }} title=\"Show saved terminal sessions\" style={{ fontSize: 10, color: showSaved ? 'var(--fg)' : 'var(--muted)', display: 'flex', alignItems: 'center', gap: 4, border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: '4px 8px', background: showSaved ? 'var(--surface)' : 'var(--bg)' }}>\n Saved\n </button>\n <button onClick={() => loadControlPlane(true)} title=\"Scan PATH again\" style={{ fontSize: 10, color: 'var(--muted)', display: 'flex', alignItems: 'center', gap: 4, border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: '4px 8px' }}>\n <RefreshCw size={11} /> Scan\n </button>\n </div>\n </div>\n\n {error && (\n <div style={{ fontSize: 11, color: '#991b1b', padding: '7px 9px', background: '#fef2f2', borderRadius: 'var(--radius)' }}>\n {error}\n <button onClick={() => setError(null)} style={{ marginLeft: 8, fontSize: 10, color: '#991b1b', textDecoration: 'underline' }}>dismiss</button>\n </div>\n )}\n\n <section style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 8 }}>\n <button\n data-testid=\"agent-add-box\"\n onClick={() => setLauncherOpen(value => !value)}\n style={{\n ...PANEL,\n minHeight: 132,\n borderStyle: 'dashed',\n display: 'grid',\n placeItems: 'center',\n textAlign: 'center',\n padding: 16,\n color: 'var(--fg)',\n background: launcherOpen ? 'var(--surface)' : 'var(--bg)',\n }}\n >\n <span style={{ width: 34, height: 34, borderRadius: 'var(--radius)', border: '1px solid var(--border)', display: 'grid', placeItems: 'center', marginBottom: 8 }}>\n <Plus size={18} />\n </span>\n <span style={{ fontSize: 13, fontWeight: 600 }}>New Agent Terminal</span>\n <span style={{ fontSize: 10, color: 'var(--muted)', marginTop: 2 }}>Choose a detected terminal platform</span>\n </button>\n\n {runtimes.map(runtime => (\n <motion.div\n key={runtime.id}\n data-testid=\"detected-runtime-card\"\n initial={reducedMotion ? undefined : { opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n style={{ ...PANEL, padding: 10, minHeight: 132, display: 'grid', alignContent: 'space-between', gap: 8 }}\n >\n <div style={{ minWidth: 0 }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 7, minWidth: 0 }}>\n <span style={{ width: 7, height: 7, borderRadius: '50%', background: statusColor(runtime.status), flexShrink: 0 }} />\n <span style={{ fontSize: 13, fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{runtime.label}</span>\n <span style={{ fontSize: 9, color: 'var(--muted)', border: '1px solid var(--border)', borderRadius: 99, padding: '0 5px', flexShrink: 0 }}>{runtime.command}</span>\n </div>\n <div title={runtime.path || ''} style={{ fontSize: 10, color: 'var(--muted)', marginTop: 5, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>\n {compactPath(runtime.path)}\n </div>\n <div style={{ fontSize: 10, color: 'var(--muted)', marginTop: 3, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>\n {runtime.version || runtime.capabilities.slice(0, 3).join(' / ')}\n </div>\n </div>\n <div style={{ display: 'flex', gap: 5 }}>\n <button onClick={() => createSession(runtime.id)} disabled={creating}\n style={{ flex: 1, fontSize: 10, fontWeight: 600, color: '#fff', background: '#111', borderRadius: 'var(--radius)', padding: '5px 8px', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4, opacity: creating ? 0.5 : 1 }}>\n <Terminal size={11} /> Start\n </button>\n <button onClick={() => openConfig(runtime.id)} title=\"Configure runtime\" style={{ width: 28, height: 27, display: 'grid', placeItems: 'center', border: '1px solid var(--border)', borderRadius: 'var(--radius)', color: 'var(--muted)' }}>\n <Settings2 size={12} />\n </button>\n </div>\n </motion.div>\n ))}\n </section>\n\n {launcherOpen && (\n <section style={{ ...PANEL, padding: 12, display: 'grid', gap: 10 }}>\n {runtimes.length === 0 ? (\n <div style={{ fontSize: 11, color: 'var(--muted)', textAlign: 'center', padding: 16 }}>\n No detected terminal agents. Run Scan after installing a CLI on PATH.\n </div>\n ) : (\n <>\n <div style={{ display: 'grid', gridTemplateColumns: 'minmax(160px, 240px) minmax(120px, 220px) auto', gap: 8, alignItems: 'end' }}>\n <label style={{ fontSize: 10, color: 'var(--muted)', display: 'grid', gap: 3 }}>\n Platform\n <select value={selectedRuntimeId} onChange={e => setSelectedRuntimeId(e.target.value)}\n style={{ padding: '6px 8px', fontSize: 11, border: '1px solid var(--border)', borderRadius: 'var(--radius)', background: 'var(--bg)' }}>\n {runtimes.map(runtime => <option key={runtime.id} value={runtime.id}>{runtime.label}</option>)}\n </select>\n </label>\n <label style={{ fontSize: 10, color: 'var(--muted)', display: 'grid', gap: 3 }}>\n Model Override\n <input value={launchModel} onChange={e => setLaunchModel(e.target.value)} placeholder=\"optional\"\n style={{ padding: '6px 8px', fontSize: 11, border: '1px solid var(--border)', borderRadius: 'var(--radius)', background: 'var(--bg)' }} />\n </label>\n <button onClick={() => createSession()} disabled={!selectedRuntime || creating}\n style={{ height: 31, padding: '0 14px', fontSize: 11, fontWeight: 600, borderRadius: 'var(--radius)', background: '#111', color: '#fff', opacity: !selectedRuntime || creating ? 0.5 : 1 }}>\n Start Terminal\n </button>\n </div>\n <div style={{ fontSize: 10, color: 'var(--muted)' }}>\n {selectedRuntime ? `${selectedRuntime.command} from ${compactPath(selectedRuntime.path)}` : 'Only detected runtimes are listed.'}\n </div>\n </>\n )}\n </section>\n )}\n\n {configRuntimeId && (\n <section style={{ ...PANEL, padding: 12 }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, marginBottom: 10 }}>\n <div>\n <div style={{ fontSize: 12, fontWeight: 600 }}>{runtimes.find(r => r.id === configRuntimeId)?.label || configRuntimeId} Config</div>\n <div style={{ fontSize: 10, color: 'var(--muted)' }}>Known global/project config files. Authentication files are shown read-only unless a safe model field is known.</div>\n </div>\n <button onClick={() => setConfigRuntimeId(null)} style={{ fontSize: 10, color: 'var(--muted)', border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: '3px 8px' }}>Close</button>\n </div>\n\n {!runtimeConfig ? (\n <LoadingView label=\"Loading runtime config\" />\n ) : runtimeConfig.files.length === 0 ? (\n <div style={{ fontSize: 11, color: 'var(--muted)' }}>No editable config path is known for this CLI yet.</div>\n ) : (\n <div style={{ display: 'grid', gridTemplateColumns: 'minmax(170px, 260px) minmax(0, 1fr)', gap: 12 }}>\n <div style={{ display: 'grid', gap: 5 }}>\n {runtimeConfig.files.map(file => (\n <button key={`${file.scope}-${file.path}`} onClick={() => switchConfigScope(file.scope)}\n style={{\n textAlign: 'left',\n border: `1px solid ${configScope === file.scope ? '#111' : 'var(--border)'}`,\n borderRadius: 'var(--radius)',\n padding: 8,\n background: configScope === file.scope ? 'var(--surface)' : 'var(--bg)',\n }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 11, fontWeight: 600 }}>\n {file.exists && <Check size={11} color=\"#166534\" />} {file.scope}\n </div>\n <div style={{ fontSize: 10, color: 'var(--muted)', marginTop: 3, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{file.path}</div>\n </button>\n ))}\n </div>\n\n <div>\n {selectedConfigFile ? (\n <>\n <div style={{ fontSize: 10, color: 'var(--muted)', marginBottom: 8 }}>\n {selectedConfigFile.format} / {selectedConfigFile.exists ? 'existing' : 'will create'} / {compactPath(selectedConfigFile.absolutePath)}\n </div>\n <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))', gap: 8 }}>\n {Object.keys(selectedConfigFile.fields).map(alias => (\n <label key={alias} style={{ fontSize: 10, color: 'var(--muted)', display: 'grid', gap: 3 }}>\n {alias}\n <input value={configValues[alias] || ''} onChange={e => setConfigValues(values => ({ ...values, [alias]: e.target.value }))}\n style={{ padding: '6px 8px', fontSize: 11, border: '1px solid var(--border)', borderRadius: 'var(--radius)', background: 'var(--bg)' }} />\n </label>\n ))}\n </div>\n <button onClick={saveConfig} style={{ marginTop: 10, fontSize: 11, fontWeight: 600, color: '#fff', background: '#111', borderRadius: 'var(--radius)', padding: '6px 12px' }}>\n Save Config\n </button>\n </>\n ) : (\n <div style={{ fontSize: 11, color: 'var(--muted)' }}>This config file is read-only in Harness UI.</div>\n )}\n {configSaved && <div style={{ fontSize: 10, color: '#166534', marginTop: 8 }}>{configSaved}</div>}\n </div>\n </div>\n )}\n </section>\n )}\n\n <section>\n <div style={{ fontSize: 10, fontWeight: 600, color: 'var(--muted)', textTransform: 'uppercase', marginBottom: 6 }}>Running Terminals</div>\n {runningSessions.length === 0 ? (\n <div data-testid=\"agents-empty\" style={{ padding: 28, color: 'var(--muted)', textAlign: 'center', fontSize: 11, border: '1px solid var(--border)', borderRadius: 'var(--radius)' }}>\n <Terminal size={26} style={{ marginBottom: 8, opacity: 0.35 }} />\n <p style={{ marginBottom: 3, fontWeight: 500 }}>No running agent terminal.</p>\n <p>Use the plus box to start a detected CLI.</p>\n </div>\n ) : (\n <div data-testid=\"agents-list\" style={{ display: 'grid', gap: 5 }}>\n {runningSessions.map(session => (\n <SessionRow key={session.sessionId} session={session} onSelectSession={onSelectSession} onStop={stopSession} stopping={stoppingIds.has(session.sessionId)} />\n ))}\n </div>\n )}\n </section>\n\n {showSaved && savedSessions.length > 0 && (\n <section>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, marginBottom: 6 }}>\n <div style={{ fontSize: 10, fontWeight: 600, color: 'var(--muted)', textTransform: 'uppercase' }}>\n Saved Sessions ({savedSessions.length})\n </div>\n {savedSessions.length > SAVED_PAGE_SIZE && (\n <div style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 10, color: 'var(--muted)' }}>\n <button onClick={() => setSavedPage(page => Math.max(0, page - 1))} disabled={savedPage === 0}\n style={{ border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: '2px 7px', opacity: savedPage === 0 ? 0.45 : 1 }}>\n Prev\n </button>\n <span>{savedPage + 1} / {savedPageCount}</span>\n <button onClick={() => setSavedPage(page => Math.min(savedPageCount - 1, page + 1))} disabled={savedPage >= savedPageCount - 1}\n style={{ border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: '2px 7px', opacity: savedPage >= savedPageCount - 1 ? 0.45 : 1 }}>\n Next\n </button>\n </div>\n )}\n </div>\n <div style={{ display: 'grid', gap: 5 }}>\n {visibleSavedSessions.map(session => (\n <SessionRow key={session.sessionId} session={session} onSelectSession={onSelectSession} onStop={stopSession} muted />\n ))}\n </div>\n </section>\n )}\n </div>\n );\n}\n\nfunction SessionRow({\n session,\n onSelectSession,\n onStop,\n muted = false,\n stopping = false,\n}: {\n session: Session;\n onSelectSession: (sessionId: string) => void;\n onStop: (sessionId: string) => void;\n muted?: boolean;\n stopping?: boolean;\n}) {\n return (\n <div data-testid=\"agent-row\" style={{ ...PANEL, padding: 9, opacity: muted ? 0.68 : 1 }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>\n <span style={{ width: 7, height: 7, borderRadius: '50%', background: statusColor(session.status), flexShrink: 0 }} />\n <span style={{ fontSize: 12, fontWeight: 600 }}>{session.runtime}</span>\n <span style={{ fontSize: 10, color: 'var(--muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>\n {session.peerId || session.sessionId}\n </span>\n </div>\n <div style={{ display: 'flex', gap: 4, flexShrink: 0 }}>\n <button onClick={() => onSelectSession(session.sessionId)}\n style={{ fontSize: 10, padding: '3px 8px', border: '1px solid var(--border)', borderRadius: 'var(--radius)', background: 'var(--bg)', display: 'flex', alignItems: 'center', gap: 3 }}>\n <ExternalLink size={9} /> Terminal\n </button>\n {!muted && (\n <button onClick={() => onStop(session.sessionId)} disabled={stopping}\n style={{ fontSize: 10, padding: '3px 8px', border: '1px solid #991b1b', borderRadius: 'var(--radius)', color: '#991b1b', background: 'var(--bg)', display: 'flex', alignItems: 'center', gap: 3 }}>\n <Square size={9} /> {stopping ? 'Stopping' : 'Stop'}\n </button>\n )}\n </div>\n </div>\n <div style={{ fontSize: 10, color: 'var(--muted)', marginTop: 4 }}>\n {[stopping ? 'stopping' : session.status, session.role, session.workflowMode || null, session.ptyProvider || null, session.taskId || null, `${session.wsClientCount ?? 0} viewer(s)`].filter(Boolean).join(' / ')}\n {session.model ? ` / ${session.model}` : ''}\n {session.resumeCommand ? ` / resume: ${session.resumeCommand}` : ''}\n {session.blockedReason ? ` / ${session.blockedReason}` : ''}\n {session.blockedHint ? ` / ${session.blockedHint}` : ''}\n </div>\n </div>\n );\n}\n"],"names":["Check","createLucideIcon","ExternalLink","Settings2","SAVED_PAGE_SIZE","PANEL","statusColor","status","compactPath","value","parts","AgentsRoute","onSelectSession","sessions","setSessions","useState","savedSessions","setSavedSessions","runtimes","setRuntimes","launcherOpen","setLauncherOpen","showSaved","setShowSaved","savedPage","setSavedPage","selectedRuntimeId","setSelectedRuntimeId","launchModel","setLaunchModel","creating","setCreating","stoppingIds","setStoppingIds","stoppingIdsRef","useRef","loading","setLoading","error","setError","configRuntimeId","setConfigRuntimeId","runtimeConfig","setRuntimeConfig","configValues","setConfigValues","configScope","setConfigScope","configSaved","setConfigSaved","reducedMotion","useReducedMotion","selectedRuntime","useMemo","runtime","runningSessions","savedPageCount","visibleSavedSessions","updateStoppingIds","updater","current","next","loadControlPlane","refresh","runtimeRows","sessionRows","allRows","apiJsonCached","apiJson","pendingStops","session","liveIds","id","row","_a","e","useEffect","interval","onSessionsChanged","event","detail","page","openConfig","runtimeId","data","writable","file","selectedConfigFile","switchConfigScope","scope","nextFile","saveConfig","result","createSession","invalidateApiCache","stopSession","sessionId","previous","jsx","LoadingView","jsxs","Bot","RefreshCw","Plus","motion","Terminal","Fragment","r","alias","values","SessionRow","onStop","muted","stopping","Square"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{c as b,r as a,j as e,L as S,G as w,i as z,a as I,B as C}from"./index-BOVYWntB.js";import{R}from"./refresh-cw-JNmExijd.js";import{T as k}from"./terminal-BBQvnOAK.js";/**
|
|
2
|
+
* @license lucide-react v0.400.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const W=b("ShieldCheck",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]]);function B(r){return r==="controller"?"#111111":r==="runtime"?"#1e40af":r==="review"||r==="validation"?"#166534":r==="implementer"?"#7c2d12":"#6b7280"}function u({kind:r}){return r==="runtime"?e.jsx(k,{size:14}):r==="validation"||r==="review"?e.jsx(W,{size:14}):e.jsx(C,{size:14})}function E(){const[r,v]=a.useState(null),[o,c]=a.useState("ceo"),[h,y]=a.useState(!0),[n,p]=a.useState(null),f=async()=>{try{const t=await I("/api/roles",{ttlMs:3e4});v(t),c(s=>s&&t.agents.some(i=>i.agentId===s)?s:t.rootAgentId),p(null)}catch(t){p((t==null?void 0:t.message)||"Failed to load roles")}finally{y(!1)}};a.useEffect(()=>{f()},[]);const j=a.useMemo(()=>{const t=new Map;for(const s of(r==null?void 0:r.agents)||[]){const i=t.get(s.level)||[];i.push(s),t.set(s.level,i)}return[...t.entries()].sort(([s],[i])=>s-i)},[r]),l=(r==null?void 0:r.agents.find(t=>t.agentId===o))||null,x=(r==null?void 0:r.edges.filter(t=>t.to===o))||[],m=(r==null?void 0:r.edges.filter(t=>t.from===o))||[];return h?e.jsx(S,{label:"Loading roles"}):r?e.jsxs("div",{style:{display:"grid",gap:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:10},children:[e.jsxs("h2",{style:{fontSize:12,fontWeight:600,textTransform:"uppercase",letterSpacing:"0.05em",color:"var(--muted)",margin:0,display:"flex",alignItems:"center",gap:5},children:[e.jsx(w,{size:14})," Roles"]}),e.jsxs("button",{onClick:()=>{z("/api/roles"),f()},style:{fontSize:10,color:"var(--muted)",display:"flex",alignItems:"center",gap:4,border:"1px solid var(--border)",borderRadius:"var(--radius)",padding:"4px 8px"},children:[e.jsx(R,{size:11})," Refresh"]})]}),n&&e.jsx("div",{style:{fontSize:11,color:"#991b1b"},children:n}),e.jsxs("section",{style:{display:"grid",gridTemplateColumns:"minmax(0, 1fr) minmax(240px, 320px)",gap:12,alignItems:"start"},children:[e.jsx("div",{style:{display:"grid",gap:10},children:j.map(([t,s])=>e.jsxs("div",{style:{display:"grid",gap:6},children:[e.jsx("div",{style:{fontSize:10,color:"var(--muted)",textTransform:"uppercase",fontWeight:700},children:t===0?"Leader":"Role Layer"}),e.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(190px, 1fr))",gap:6},children:s.map(i=>{const g=o===i.agentId,d=B(i.kind);return e.jsxs("button",{onClick:()=>c(i.agentId),style:{border:`1px solid ${g?d:"var(--border)"}`,borderLeft:`3px solid ${d}`,borderRadius:"var(--radius)",padding:9,background:g?"var(--surface)":"var(--bg)",textAlign:"left",minHeight:82,display:"grid",alignContent:"start",gap:4},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,minWidth:0},children:[e.jsx(u,{kind:i.kind}),e.jsx("span",{style:{fontSize:12,fontWeight:700,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:i.role})]}),e.jsx("div",{style:{fontSize:10,color:d},children:i.kind}),e.jsx("div",{style:{fontSize:10,color:"var(--muted)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:(i.skills||[]).slice(0,3).join(" / ")||i.agentId})]},i.agentId)})})]},t))}),e.jsx("aside",{style:{border:"1px solid var(--border)",borderRadius:"var(--radius)",padding:12,background:"var(--bg)"},children:l?e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginBottom:8},children:[e.jsx(u,{kind:l.kind}),e.jsxs("div",{style:{minWidth:0},children:[e.jsx("div",{style:{fontSize:12,fontWeight:700,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:l.role}),e.jsx("div",{style:{fontSize:10,color:"var(--muted)"},children:l.agentId})]})]}),e.jsx("div",{style:{fontSize:10,fontWeight:700,color:"var(--muted)",textTransform:"uppercase",marginBottom:5},children:"Edges"}),e.jsxs("div",{style:{display:"grid",gap:3,fontSize:10,marginBottom:10},children:[[...x.map(t=>`${t.from} -> ${t.relation}`),...m.map(t=>`${t.relation} -> ${t.to}`)].map((t,s)=>e.jsx("div",{style:{color:"var(--muted)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t},`${t}-${s}`)),x.length+m.length===0&&e.jsx("div",{style:{color:"var(--muted)"},children:"no edges"})]}),e.jsx("div",{style:{fontSize:10,fontWeight:700,color:"var(--muted)",textTransform:"uppercase",marginBottom:5},children:"Skills"}),e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:3,marginBottom:10},children:(l.skills||[]).map(t=>e.jsx("span",{style:{fontSize:9,padding:"1px 5px",border:"1px solid var(--border)",borderRadius:99,color:"var(--muted)"},children:t},t))}),e.jsx("div",{style:{fontSize:10,fontWeight:700,color:"var(--muted)",textTransform:"uppercase",marginBottom:5},children:"Permissions"}),e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:3},children:(l.permissions||[]).map(t=>e.jsx("span",{style:{fontSize:9,padding:"1px 5px",border:"1px solid var(--border)",borderRadius:99,color:"var(--muted)"},children:t},t))})]}):e.jsx("div",{style:{color:"var(--muted)",fontSize:11},children:"Select a role."})})]})]}):e.jsx("div",{style:{padding:20,color:"#991b1b",fontSize:11},children:n||"No role graph available."})}export{E as default};
|
|
7
|
+
//# sourceMappingURL=RolesRoute-DOzTYVRm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RolesRoute-DOzTYVRm.js","sources":["../../node_modules/.pnpm/lucide-react@0.400.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/shield-check.js","../../src/components/RolesRoute.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ShieldCheck = createLucideIcon(\"ShieldCheck\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ],\n [\"path\", { d: \"m9 12 2 2 4-4\", key: \"dzmm74\" }]\n]);\n\nexport { ShieldCheck as default };\n//# sourceMappingURL=shield-check.js.map\n","import { useEffect, useMemo, useState } from 'react';\nimport { Bot, GitBranch, RefreshCw, ShieldCheck, Terminal } from 'lucide-react';\nimport { apiJsonCached, invalidateApiCache } from '../api';\nimport LoadingView from './LoadingView';\n\ntype RoleNode = {\n agentId: string;\n role: string;\n level: number;\n kind: string;\n skills?: string[];\n permissions?: string[];\n};\n\ntype RoleEdge = { from: string; to: string; relation: string };\ntype RoleGraph = { rootAgentId: string; agents: RoleNode[]; edges: RoleEdge[] };\n\nfunction kindColor(kind: string) {\n if (kind === 'controller') return '#111111';\n if (kind === 'runtime') return '#1e40af';\n if (kind === 'review' || kind === 'validation') return '#166534';\n if (kind === 'implementer') return '#7c2d12';\n return '#6b7280';\n}\n\nfunction NodeIcon({ kind }: { kind: string }) {\n if (kind === 'runtime') return <Terminal size={14} />;\n if (kind === 'validation' || kind === 'review') return <ShieldCheck size={14} />;\n return <Bot size={14} />;\n}\n\nexport default function RolesRoute() {\n const [graph, setGraph] = useState<RoleGraph | null>(null);\n const [selectedId, setSelectedId] = useState('ceo');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const loadRoles = async () => {\n try {\n const data = await apiJsonCached<RoleGraph>('/api/roles', { ttlMs: 30000 });\n setGraph(data);\n setSelectedId(current => current && data.agents.some(agent => agent.agentId === current) ? current : data.rootAgentId);\n setError(null);\n } catch (e: any) {\n setError(e?.message || 'Failed to load roles');\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n loadRoles();\n }, []);\n\n const lanes = useMemo(() => {\n const grouped = new Map<number, RoleNode[]>();\n for (const node of graph?.agents || []) {\n const lane = grouped.get(node.level) || [];\n lane.push(node);\n grouped.set(node.level, lane);\n }\n return [...grouped.entries()].sort(([a], [b]) => a - b);\n }, [graph]);\n\n const selected = graph?.agents.find(node => node.agentId === selectedId) || null;\n const inbound = graph?.edges.filter(edge => edge.to === selectedId) || [];\n const outbound = graph?.edges.filter(edge => edge.from === selectedId) || [];\n\n if (loading) return <LoadingView label=\"Loading roles\" />;\n if (!graph) return <div style={{ padding: 20, color: '#991b1b', fontSize: 11 }}>{error || 'No role graph available.'}</div>;\n\n return (\n <div style={{ display: 'grid', gap: 12 }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 }}>\n <h2 style={{ fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--muted)', margin: 0, display: 'flex', alignItems: 'center', gap: 5 }}>\n <GitBranch size={14} /> Roles\n </h2>\n <button onClick={() => { invalidateApiCache('/api/roles'); loadRoles(); }} style={{ fontSize: 10, color: 'var(--muted)', display: 'flex', alignItems: 'center', gap: 4, border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: '4px 8px' }}>\n <RefreshCw size={11} /> Refresh\n </button>\n </div>\n\n {error && <div style={{ fontSize: 11, color: '#991b1b' }}>{error}</div>}\n\n <section style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(240px, 320px)', gap: 12, alignItems: 'start' }}>\n <div style={{ display: 'grid', gap: 10 }}>\n {lanes.map(([level, nodes]) => (\n <div key={level} style={{ display: 'grid', gap: 6 }}>\n <div style={{ fontSize: 10, color: 'var(--muted)', textTransform: 'uppercase', fontWeight: 700 }}>\n {level === 0 ? 'Leader' : 'Role Layer'}\n </div>\n <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(190px, 1fr))', gap: 6 }}>\n {nodes.map(node => {\n const active = selectedId === node.agentId;\n const color = kindColor(node.kind);\n return (\n <button\n key={node.agentId}\n onClick={() => setSelectedId(node.agentId)}\n style={{\n border: `1px solid ${active ? color : 'var(--border)'}`,\n borderLeft: `3px solid ${color}`,\n borderRadius: 'var(--radius)',\n padding: 9,\n background: active ? 'var(--surface)' : 'var(--bg)',\n textAlign: 'left',\n minHeight: 82,\n display: 'grid',\n alignContent: 'start',\n gap: 4,\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: 6, minWidth: 0 }}>\n <NodeIcon kind={node.kind} />\n <span style={{ fontSize: 12, fontWeight: 700, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{node.role}</span>\n </div>\n <div style={{ fontSize: 10, color }}>{node.kind}</div>\n <div style={{ fontSize: 10, color: 'var(--muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>\n {(node.skills || []).slice(0, 3).join(' / ') || node.agentId}\n </div>\n </button>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n\n <aside style={{ border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: 12, background: 'var(--bg)' }}>\n {selected ? (\n <>\n <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 8 }}>\n <NodeIcon kind={selected.kind} />\n <div style={{ minWidth: 0 }}>\n <div style={{ fontSize: 12, fontWeight: 700, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{selected.role}</div>\n <div style={{ fontSize: 10, color: 'var(--muted)' }}>{selected.agentId}</div>\n </div>\n </div>\n\n <div style={{ fontSize: 10, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', marginBottom: 5 }}>Edges</div>\n <div style={{ display: 'grid', gap: 3, fontSize: 10, marginBottom: 10 }}>\n {[...inbound.map(edge => `${edge.from} -> ${edge.relation}`), ...outbound.map(edge => `${edge.relation} -> ${edge.to}`)].map((line, index) => (\n <div key={`${line}-${index}`} style={{ color: 'var(--muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{line}</div>\n ))}\n {inbound.length + outbound.length === 0 && <div style={{ color: 'var(--muted)' }}>no edges</div>}\n </div>\n\n <div style={{ fontSize: 10, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', marginBottom: 5 }}>Skills</div>\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 3, marginBottom: 10 }}>\n {(selected.skills || []).map(skill => (\n <span key={skill} style={{ fontSize: 9, padding: '1px 5px', border: '1px solid var(--border)', borderRadius: 99, color: 'var(--muted)' }}>{skill}</span>\n ))}\n </div>\n\n <div style={{ fontSize: 10, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', marginBottom: 5 }}>Permissions</div>\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 3 }}>\n {(selected.permissions || []).map(permission => (\n <span key={permission} style={{ fontSize: 9, padding: '1px 5px', border: '1px solid var(--border)', borderRadius: 99, color: 'var(--muted)' }}>{permission}</span>\n ))}\n </div>\n </>\n ) : (\n <div style={{ color: 'var(--muted)', fontSize: 11 }}>Select a role.</div>\n )}\n </aside>\n </section>\n </div>\n );\n}\n"],"names":["ShieldCheck","createLucideIcon","kindColor","kind","NodeIcon","jsx","Terminal","Bot","RolesRoute","graph","setGraph","useState","selectedId","setSelectedId","loading","setLoading","error","setError","loadRoles","data","apiJsonCached","current","agent","e","useEffect","lanes","useMemo","grouped","node","lane","a","b","selected","inbound","edge","outbound","LoadingView","jsxs","GitBranch","invalidateApiCache","RefreshCw","level","nodes","active","color","Fragment","line","index","skill","permission"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import{c,r as d,j as e,L as f,S as m,a as y,b as S,i as j}from"./index-BOVYWntB.js";/**
|
|
2
|
+
* @license lucide-react v0.400.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const k=c("RotateCcw",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]]);/**
|
|
7
|
+
* @license lucide-react v0.400.0 - ISC
|
|
8
|
+
*
|
|
9
|
+
* This source code is licensed under the ISC license.
|
|
10
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
+
*/const R=c("Save",[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",key:"1c8476"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",key:"1ydtos"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7",key:"t51u73"}]]),n={server:{host:"127.0.0.1",port:0},terminal:{enabled:!1,attachMode:!1,defaultRuntime:"codex"},peers:{allowlist:["claude","cc","codex","opencode","gemini","qwen","deepseek","pi","aider","goose","amp","crush","cline","plandex","openclaw","chatgpt","openai"]},ui:{theme:"auto",language:"en",reducedMotion:!1}};function z(r){return{...n,...r,server:{...n.server,...r.server},terminal:{...n.terminal,...r.terminal},peers:{...n.peers,...r.peers},ui:{...n.ui,...r.ui}}}function w(){const[r,i]=d.useState(n),[g,x]=d.useState(!0),[v,l]=d.useState(!1),[p,o]=d.useState(null),u=async()=>{try{const a=await y("/api/settings",{ttlMs:1e4});i(z(a)),o(null)}catch{o("Failed to load settings")}finally{x(!1)}};d.useEffect(()=>{u()},[]);const h=async()=>{o(null),l(!1);try{await S("/api/settings",{method:"POST",body:JSON.stringify(r)}),j("/api/settings"),l(!0),setTimeout(()=>l(!1),2e3)}catch(a){o((a==null?void 0:a.message)||"Save failed")}},s=(a,t)=>e.jsxs("div",{style:{marginBottom:12},children:[e.jsx("div",{style:{fontSize:10,fontWeight:600,color:"var(--muted)",marginBottom:4,textTransform:"uppercase"},children:a}),t]});return g?e.jsx(f,{label:"Loading settings"}):e.jsxs("div",{style:{maxWidth:560},children:[e.jsxs("h2",{style:{fontSize:12,fontWeight:600,textTransform:"uppercase",letterSpacing:"0.05em",color:"var(--muted)",marginBottom:12,display:"flex",alignItems:"center",gap:4},children:[e.jsx(m,{size:14})," Settings"]}),e.jsxs("div",{style:{padding:14,border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg)"},children:[s("Server Host",e.jsx("input",{type:"text",value:r.server.host,onChange:a=>i(t=>({...t,server:{...t.server,host:a.target.value}})),style:{width:"100%",padding:"4px 8px",fontSize:11,border:"1px solid var(--border)",borderRadius:"var(--radius)"}})),s("Server Port",e.jsx("input",{type:"number",value:r.server.port,onChange:a=>i(t=>({...t,server:{...t.server,port:parseInt(a.target.value)||0}})),style:{width:100,padding:"4px 8px",fontSize:11,border:"1px solid var(--border)",borderRadius:"var(--radius)"}})),s("UI Theme",e.jsxs("select",{value:r.ui.theme,onChange:a=>i(t=>({...t,ui:{...t.ui,theme:a.target.value}})),style:{padding:"4px 8px",fontSize:11,border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg)"},children:[e.jsx("option",{value:"auto",children:"auto"}),e.jsx("option",{value:"light",children:"light"}),e.jsx("option",{value:"dark",children:"dark"})]})),s("Language",e.jsxs("select",{value:r.ui.language,onChange:a=>i(t=>({...t,ui:{...t.ui,language:a.target.value}})),style:{padding:"4px 8px",fontSize:11,border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg)"},children:[e.jsx("option",{value:"en",children:"English"}),e.jsx("option",{value:"zh",children:"Chinese"}),e.jsx("option",{value:"ja",children:"Japanese"})]})),s("Terminal",e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:11},children:[e.jsx("input",{type:"checkbox",checked:r.terminal.enabled,onChange:a=>i(t=>({...t,terminal:{...t.terminal,enabled:a.target.checked}}))}),"Enable PTY terminal"]})),s("Default Task Agent",e.jsx("select",{value:r.terminal.defaultRuntime,onChange:a=>i(t=>({...t,terminal:{...t.terminal,defaultRuntime:a.target.value}})),style:{padding:"4px 8px",fontSize:11,border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg)"},children:r.peers.allowlist.map(a=>e.jsx("option",{value:a,children:a},a))})),s("Reduced Motion",e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:11},children:[e.jsx("input",{type:"checkbox",checked:r.ui.reducedMotion,onChange:a=>i(t=>({...t,ui:{...t.ui,reducedMotion:a.target.checked}}))}),"Disable animations"]})),s("Peer Runtimes",e.jsx("input",{type:"text",value:r.peers.allowlist.join(", "),onChange:a=>i(t=>({...t,peers:{allowlist:a.target.value.split(",").map(b=>b.trim()).filter(Boolean)}})),style:{width:"100%",padding:"4px 8px",fontSize:11,border:"1px solid var(--border)",borderRadius:"var(--radius)"}}))]}),p&&e.jsx("div",{style:{marginTop:8,fontSize:11,color:"#991b1b",padding:"6px 8px",background:"#fef2f2",borderRadius:"var(--radius)"},children:p}),v&&e.jsx("div",{style:{marginTop:8,fontSize:11,color:"#166534",padding:"6px 8px",background:"#dcfce7",borderRadius:"var(--radius)"},children:"Settings saved."}),e.jsxs("div",{style:{display:"flex",gap:8,marginTop:12},children:[e.jsxs("button",{onClick:h,style:{padding:"6px 16px",fontSize:11,fontWeight:500,border:"1px solid #166534",borderRadius:"var(--radius)",background:"#166534",color:"#fff",display:"flex",alignItems:"center",gap:4},children:[e.jsx(R,{size:12})," Save"]}),e.jsxs("button",{onClick:u,style:{padding:"6px 16px",fontSize:11,border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg)",display:"flex",alignItems:"center",gap:4},children:[e.jsx(k,{size:12})," Reload"]})]})]})}export{w as default};
|
|
12
|
+
//# sourceMappingURL=SettingsRoute-DPU7jSQm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsRoute-DPU7jSQm.js","sources":["../../node_modules/.pnpm/lucide-react@0.400.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/rotate-ccw.js","../../node_modules/.pnpm/lucide-react@0.400.0_react@19.2.8/node_modules/lucide-react/dist/esm/icons/save.js","../../src/components/SettingsRoute.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst RotateCcw = createLucideIcon(\"RotateCcw\", [\n [\"path\", { d: \"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\", key: \"1357e3\" }],\n [\"path\", { d: \"M3 3v5h5\", key: \"1xhq8a\" }]\n]);\n\nexport { RotateCcw as default };\n//# sourceMappingURL=rotate-ccw.js.map\n","/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Save = createLucideIcon(\"Save\", [\n [\n \"path\",\n {\n d: \"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z\",\n key: \"1c8476\"\n }\n ],\n [\"path\", { d: \"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7\", key: \"1ydtos\" }],\n [\"path\", { d: \"M7 3v4a1 1 0 0 0 1 1h7\", key: \"t51u73\" }]\n]);\n\nexport { Save as default };\n//# sourceMappingURL=save.js.map\n","import { useEffect, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { RotateCcw, Save, Settings } from 'lucide-react';\nimport { apiJson, apiJsonCached, invalidateApiCache } from '../api';\nimport LoadingView from './LoadingView';\n\ntype SettingsData = {\n server: { host: string; port: number };\n terminal: { enabled: boolean; attachMode: boolean; defaultRuntime: string };\n peers: { allowlist: string[] };\n ui: { theme: string; language: string; reducedMotion: boolean };\n};\n\nconst DEFAULTS: SettingsData = {\n server: { host: '127.0.0.1', port: 0 },\n terminal: { enabled: false, attachMode: false, defaultRuntime: 'codex' },\n peers: {\n allowlist: [\n 'claude',\n 'cc',\n 'codex',\n 'opencode',\n 'gemini',\n 'qwen',\n 'deepseek',\n 'pi',\n 'aider',\n 'goose',\n 'amp',\n 'crush',\n 'cline',\n 'plandex',\n 'openclaw',\n 'chatgpt',\n 'openai',\n ],\n },\n ui: { theme: 'auto', language: 'en', reducedMotion: false },\n};\n\nfunction mergeSettings(value: Partial<SettingsData>): SettingsData {\n return {\n ...DEFAULTS,\n ...value,\n server: { ...DEFAULTS.server, ...value.server },\n terminal: { ...DEFAULTS.terminal, ...value.terminal },\n peers: { ...DEFAULTS.peers, ...value.peers },\n ui: { ...DEFAULTS.ui, ...value.ui },\n };\n}\n\nexport default function SettingsRoute() {\n const [settings, setSettings] = useState<SettingsData>(DEFAULTS);\n const [loading, setLoading] = useState(true);\n const [saved, setSaved] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const loadSettings = async () => {\n try {\n const data = await apiJsonCached<Partial<SettingsData>>('/api/settings', { ttlMs: 10000 });\n setSettings(mergeSettings(data));\n setError(null);\n } catch {\n setError('Failed to load settings');\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n loadSettings();\n }, []);\n\n const save = async () => {\n setError(null);\n setSaved(false);\n try {\n await apiJson('/api/settings', {\n method: 'POST',\n body: JSON.stringify(settings),\n });\n invalidateApiCache('/api/settings');\n setSaved(true);\n setTimeout(() => setSaved(false), 2000);\n } catch (e: any) {\n setError(e?.message || 'Save failed');\n }\n };\n\n const field = (label: string, child: ReactNode) => (\n <div style={{ marginBottom: 12 }}>\n <div style={{ fontSize: 10, fontWeight: 600, color: 'var(--muted)', marginBottom: 4, textTransform: 'uppercase' }}>{label}</div>\n {child}\n </div>\n );\n\n if (loading) return <LoadingView label=\"Loading settings\" />;\n\n return (\n <div style={{ maxWidth: 560 }}>\n <h2 style={{ fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--muted)', marginBottom: 12, display: 'flex', alignItems: 'center', gap: 4 }}>\n <Settings size={14} /> Settings\n </h2>\n\n <div style={{ padding: 14, border: '1px solid var(--border)', borderRadius: 'var(--radius)', background: 'var(--bg)' }}>\n {field('Server Host', <input type=\"text\" value={settings.server.host} onChange={e => setSettings(s => ({ ...s, server: { ...s.server, host: e.target.value } }))} style={{ width: '100%', padding: '4px 8px', fontSize: 11, border: '1px solid var(--border)', borderRadius: 'var(--radius)' }} />)}\n\n {field('Server Port', <input type=\"number\" value={settings.server.port} onChange={e => setSettings(s => ({ ...s, server: { ...s.server, port: parseInt(e.target.value) || 0 } }))} style={{ width: 100, padding: '4px 8px', fontSize: 11, border: '1px solid var(--border)', borderRadius: 'var(--radius)' }} />)}\n\n {field('UI Theme', (\n <select value={settings.ui.theme} onChange={e => setSettings(s => ({ ...s, ui: { ...s.ui, theme: e.target.value } }))} style={{ padding: '4px 8px', fontSize: 11, border: '1px solid var(--border)', borderRadius: 'var(--radius)', background: 'var(--bg)' }}>\n <option value=\"auto\">auto</option>\n <option value=\"light\">light</option>\n <option value=\"dark\">dark</option>\n </select>\n ))}\n\n {field('Language', (\n <select value={settings.ui.language} onChange={e => setSettings(s => ({ ...s, ui: { ...s.ui, language: e.target.value } }))} style={{ padding: '4px 8px', fontSize: 11, border: '1px solid var(--border)', borderRadius: 'var(--radius)', background: 'var(--bg)' }}>\n <option value=\"en\">English</option>\n <option value=\"zh\">Chinese</option>\n <option value=\"ja\">Japanese</option>\n </select>\n ))}\n\n {field('Terminal', (\n <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11 }}>\n <input type=\"checkbox\" checked={settings.terminal.enabled} onChange={e => setSettings(s => ({ ...s, terminal: { ...s.terminal, enabled: e.target.checked } }))} />\n Enable PTY terminal\n </label>\n ))}\n\n {field('Default Task Agent', (\n <select value={settings.terminal.defaultRuntime} onChange={e => setSettings(s => ({ ...s, terminal: { ...s.terminal, defaultRuntime: e.target.value } }))} style={{ padding: '4px 8px', fontSize: 11, border: '1px solid var(--border)', borderRadius: 'var(--radius)', background: 'var(--bg)' }}>\n {settings.peers.allowlist.map(runtime => <option key={runtime} value={runtime}>{runtime}</option>)}\n </select>\n ))}\n\n {field('Reduced Motion', (\n <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11 }}>\n <input type=\"checkbox\" checked={settings.ui.reducedMotion} onChange={e => setSettings(s => ({ ...s, ui: { ...s.ui, reducedMotion: e.target.checked } }))} />\n Disable animations\n </label>\n ))}\n\n {field('Peer Runtimes', (\n <input type=\"text\" value={settings.peers.allowlist.join(', ')}\n onChange={e => setSettings(s => ({ ...s, peers: { allowlist: e.target.value.split(',').map(x => x.trim()).filter(Boolean) } }))}\n style={{ width: '100%', padding: '4px 8px', fontSize: 11, border: '1px solid var(--border)', borderRadius: 'var(--radius)' }} />\n ))}\n </div>\n\n {error && <div style={{ marginTop: 8, fontSize: 11, color: '#991b1b', padding: '6px 8px', background: '#fef2f2', borderRadius: 'var(--radius)' }}>{error}</div>}\n {saved && <div style={{ marginTop: 8, fontSize: 11, color: '#166534', padding: '6px 8px', background: '#dcfce7', borderRadius: 'var(--radius)' }}>Settings saved.</div>}\n\n <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>\n <button onClick={save} style={{ padding: '6px 16px', fontSize: 11, fontWeight: 500, border: '1px solid #166534', borderRadius: 'var(--radius)', background: '#166534', color: '#fff', display: 'flex', alignItems: 'center', gap: 4 }}>\n <Save size={12} /> Save\n </button>\n <button onClick={loadSettings} style={{ padding: '6px 16px', fontSize: 11, border: '1px solid var(--border)', borderRadius: 'var(--radius)', background: 'var(--bg)', display: 'flex', alignItems: 'center', gap: 4 }}>\n <RotateCcw size={12} /> Reload\n </button>\n </div>\n </div>\n );\n}\n"],"names":["RotateCcw","createLucideIcon","Save","DEFAULTS","mergeSettings","value","SettingsRoute","settings","setSettings","useState","loading","setLoading","saved","setSaved","error","setError","loadSettings","data","apiJsonCached","useEffect","save","apiJson","invalidateApiCache","e","field","label","child","jsxs","jsx","LoadingView","Settings","s","runtime","x"],"mappings":"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","x_google_ignoreList":[0,1]}
|