clawmini 0.0.2 → 0.0.3
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/.github/workflows/ci.yml +59 -0
- package/README.md +4 -2
- package/dist/adapter-discord/index.d.mts.map +1 -1
- package/dist/adapter-discord/index.mjs +13 -4
- package/dist/adapter-discord/index.mjs.map +1 -1
- package/dist/cli/index.mjs +7 -6
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lite.mjs +16 -10
- package/dist/cli/lite.mjs.map +1 -1
- package/dist/daemon/index.mjs +590 -401
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/{fetch-BjZVyU3Z.mjs → fetch-Cn1XNyiO.mjs} +1 -1
- package/dist/{fetch-BjZVyU3Z.mjs.map → fetch-Cn1XNyiO.mjs.map} +1 -1
- package/dist/lite-oSYSvaOr.mjs +164 -0
- package/dist/lite-oSYSvaOr.mjs.map +1 -0
- package/dist/web/_app/immutable/chunks/{CAZeqksE.js → 8YNcRyEk.js} +1 -1
- package/dist/web/_app/immutable/chunks/{B3YcEpQV.js → DQoygso7.js} +1 -1
- package/dist/web/_app/immutable/entry/{app.ZuicLpkH.js → app.DO5eYwVz.js} +2 -2
- package/dist/web/_app/immutable/entry/start.D48mVn1m.js +1 -0
- package/dist/web/_app/immutable/nodes/{0.BB1CjKco.js → 0.B-0CcADM.js} +1 -1
- package/dist/web/_app/immutable/nodes/{1.CdSgEHu9.js → 1.FixKgvRO.js} +1 -1
- package/{web/.svelte-kit/output/client/_app/immutable/nodes/3.CKp7Wkn8.js → dist/web/_app/immutable/nodes/3.ncP0xLO6.js} +1 -1
- package/dist/web/_app/immutable/nodes/{4.FyeoMY-Y.js → 4.CQYJEgv8.js} +1 -1
- package/dist/web/_app/immutable/nodes/{5.D6mVN7l7.js → 5.BpJUN6QH.js} +1 -1
- package/dist/web/_app/version.json +1 -1
- package/dist/web/index.html +6 -6
- package/dist/{workspace-BC1ahx4R.mjs → workspace-DjoNjhW0.mjs} +12 -42
- package/dist/workspace-DjoNjhW0.mjs.map +1 -0
- package/docs/15_lite_fetch_pending/development_log.md +31 -0
- package/docs/15_lite_fetch_pending/notes.md +48 -0
- package/docs/15_lite_fetch_pending/prd.md +39 -0
- package/docs/15_lite_fetch_pending/questions.md +3 -0
- package/docs/15_lite_fetch_pending/tickets.md +42 -0
- package/docs/CHECKS.md +2 -2
- package/eslint.config.js +12 -0
- package/package.json +3 -2
- package/src/adapter-discord/client.ts +1 -1
- package/src/adapter-discord/index.ts +22 -5
- package/src/cli/client.ts +8 -3
- package/src/cli/e2e/adapter-discord.test.ts +2 -2
- package/src/cli/e2e/daemon.test.ts +2 -1
- package/src/cli/e2e/export-lite-func.test.ts +41 -13
- package/src/cli/e2e/fallbacks.test.ts +4 -0
- package/src/cli/lite.ts +24 -6
- package/src/daemon/api/agent-router.ts +191 -0
- package/src/daemon/{router.test.ts → api/index.test.ts} +101 -34
- package/src/daemon/api/index.ts +4 -0
- package/src/daemon/{router-policy-request.test.ts → api/policy-request.test.ts} +27 -13
- package/src/daemon/api/router-utils.ts +159 -0
- package/src/daemon/api/trpc.ts +30 -0
- package/src/daemon/api/user-router.ts +221 -0
- package/src/daemon/index.ts +3 -3
- package/src/daemon/message-interruption.test.ts +17 -10
- package/src/daemon/message-typing.test.ts +1 -1
- package/src/daemon/message.ts +260 -239
- package/src/daemon/observation.test.ts +1 -1
- package/src/daemon/queue.test.ts +28 -0
- package/src/daemon/queue.ts +30 -15
- package/src/daemon/request-store.test.ts +4 -4
- package/src/daemon/request-store.ts +3 -1
- package/src/shared/workspace.ts +4 -5
- package/templates/debug/settings.json +5 -0
- package/templates/environments/macos/env.json +1 -1
- package/templates/environments/macos-proxy/env.json +1 -1
- package/templates/gemini-claw/.gemini/hooks/insert-pending.sh +9 -0
- package/templates/gemini-claw/.gemini/settings.json +14 -1
- package/templates/gemini-claw/.gemini/system.md +2 -0
- package/web/.svelte-kit/generated/server/internal.js +1 -1
- package/web/.svelte-kit/output/client/.vite/manifest.json +26 -26
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{CAZeqksE.js → 8YNcRyEk.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{B3YcEpQV.js → DQoygso7.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/entry/{app.ZuicLpkH.js → app.DO5eYwVz.js} +2 -2
- package/web/.svelte-kit/output/client/_app/immutable/entry/start.D48mVn1m.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{0.BB1CjKco.js → 0.B-0CcADM.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{1.CdSgEHu9.js → 1.FixKgvRO.js} +1 -1
- package/{dist/web/_app/immutable/nodes/3.CKp7Wkn8.js → web/.svelte-kit/output/client/_app/immutable/nodes/3.ncP0xLO6.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{4.FyeoMY-Y.js → 4.CQYJEgv8.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{5.D6mVN7l7.js → 5.BpJUN6QH.js} +1 -1
- package/web/.svelte-kit/output/client/_app/version.json +1 -1
- package/web/.svelte-kit/output/server/chunks/internal.js +1 -1
- package/web/.svelte-kit/output/server/manifest-full.js +1 -1
- package/web/.svelte-kit/output/server/manifest.js +1 -1
- package/web/.svelte-kit/output/server/nodes/0.js +1 -1
- package/web/.svelte-kit/output/server/nodes/1.js +1 -1
- package/web/.svelte-kit/output/server/nodes/3.js +1 -1
- package/web/.svelte-kit/output/server/nodes/4.js +1 -1
- package/web/.svelte-kit/output/server/nodes/5.js +1 -1
- package/dist/chats-BcbxvPlj.mjs +0 -29
- package/dist/chats-BcbxvPlj.mjs.map +0 -1
- package/dist/chats-CpRQrNHj.mjs +0 -91
- package/dist/chats-CpRQrNHj.mjs.map +0 -1
- package/dist/fs-B5wW0oaH.mjs +0 -14
- package/dist/fs-B5wW0oaH.mjs.map +0 -1
- package/dist/lite-DBUuHsX0.mjs +0 -80
- package/dist/lite-DBUuHsX0.mjs.map +0 -1
- package/dist/policy-utils-BvfOK6Ih.mjs +0 -114
- package/dist/policy-utils-BvfOK6Ih.mjs.map +0 -1
- package/dist/rolldown-runtime-95iHPtFO.mjs +0 -18
- package/dist/web/_app/immutable/entry/start.DuQwh4Nz.js +0 -1
- package/dist/workspace-BC1ahx4R.mjs.map +0 -1
- package/src/daemon/router.ts +0 -510
- package/web/.svelte-kit/output/client/_app/immutable/entry/start.DuQwh4Nz.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as U,a as d,f as p}from"../chunks/Dc-UOHw9.js";import{a as Ve}from"../chunks/B8yYFADm.js";import{f as z,p as Me,a as Le,F as He,I as P,l as we,n as F,w as e,D as f,aR as Se,G as ke,s as S,c,r as v,t as M,C as Q}from"../chunks/CpaGRn9L.js";import{d as Ge,e as Ee,s as O,a as ie}from"../chunks/DG5RZBw-.js";import{l as de,s as le,p as se,b as Ne,r as Ae,i as L}from"../chunks/C3k55nDF.js";import{I as ce,s as ve,a as Ke,d as qe,c as Qe,e as Te,B as Ue,h as j}from"../chunks/BmUXQ3wy.js";import{i as ne}from"../chunks/B3YcEpQV.js";import{a as oe}from"../chunks/B5abRDXp.js";import"../chunks/Bi0jeV7Q.js";function We(k,r){const m=de(r,["children","$$slots","$$events","$$legacy"]);const n=[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16"}]];ce(k,le({name:"circle-alert"},()=>m,{get iconNode(){return n},children:(y,i)=>{var u=U(),l=z(u);ve(l,r,"default",{}),d(y,u)},$$slots:{default:!0}}))}function Xe(k,r){const m=de(r,["children","$$slots","$$events","$$legacy"]);const n=[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 6v6l4 2"}]];ce(k,le({name:"clock"},()=>m,{get iconNode(){return n},children:(y,i)=>{var u=U(),l=z(u);ve(l,r,"default",{}),d(y,u)},$$slots:{default:!0}}))}function Ye(k,r){const m=de(r,["children","$$slots","$$events","$$legacy"]);const n=[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"}],["path",{d:"m21.854 2.147-10.94 10.939"}]];ce(k,le({name:"send"},()=>m,{get iconNode(){return n},children:(y,i)=>{var u=U(),l=z(u);ve(l,r,"default",{}),d(y,u)},$$slots:{default:!0}}))}const Ze=async({params:k,fetch:r,depends:m})=>{const{id:n}=k;m(`app:chat:${n}`);try{const y=await r(`/api/chats/${n}`);if(y.ok){const i=await y.json();return{id:n,messages:i}}}catch(y){console.error(y)}return{id:n,messages:[]}},Ot=Object.freeze(Object.defineProperty({__proto__:null,load:Ze},Symbol.toStringTag,{value:"Module"}));var et=p("<textarea></textarea>");function tt(k,r){Me(r,!0);let m=se(r,"ref",15,null),n=se(r,"value",15),y=se(r,"data-slot",3,"textarea"),i=Ae(r,["$$slots","$$events","$$legacy","ref","value","class","data-slot"]);var u=et();He(u),Ke(u,l=>({"data-slot":y(),class:l,...i}),[()=>Qe("border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",r.class)]),Ne(u,l=>m(l),()=>m()),qe(u,n),d(k,u),Le()}var at=p('<div class="absolute top-4 left-1/2 -translate-x-1/2 bg-yellow-500/10 text-yellow-600 dark:text-yellow-400 text-xs px-3 py-1 rounded-full border border-yellow-500/20 backdrop-blur-sm shadow-sm z-10 flex items-center gap-2"><span class="inline-block w-3 h-3 rounded-full border-2 border-current border-t-transparent animate-spin"></span> Reconnecting...</div>'),rt=p('<div class="flex-1 flex items-center justify-center text-muted-foreground text-sm">No messages yet. Send a message to start the conversation!</div>'),it=p('<div class="px-4 py-2 rounded-2xl bg-primary text-primary-foreground text-sm" data-testid="user-message"> </div>'),st=p('<span class="text-destructive font-bold"> </span>'),nt=p('<div class="whitespace-pre-wrap"> </div>'),ot=p('<div class="whitespace-pre-wrap font-mono text-xs mt-2"> </div>'),dt=p('<div class="whitespace-pre-wrap italic opacity-50 text-xs mt-2">No output</div>'),lt=p('<div class="whitespace-pre-wrap font-mono text-xs mt-2 text-destructive border border-destructive/20 bg-destructive/5 p-2 rounded"> </div>'),ct=p('<div class="font-mono text-xs text-muted-foreground mb-2 flex items-center gap-2"><span> </span> <!></div> <!> <!>',1),vt=p('<div class="whitespace-pre-wrap"> </div>'),ut=p('<div data-testid="log-message"><!></div>'),ft=p('<div><div><!></div> <div class="text-[10px] text-muted-foreground px-2"> </div></div>'),pt=p('<span class="inline-block w-2 h-2 rounded-full border border-current border-t-transparent animate-spin"></span> Sending...',1),mt=p("<!> Offline / Pending",1),xt=p("<!> Failed",1),gt=p('<div class="flex items-center gap-2 mt-1 mr-2 bg-card border rounded-md p-1 shadow-sm text-xs"><button class="px-2 py-1 hover:bg-muted rounded text-primary transition-colors focus:outline-none">Retry manual send</button> <div class="w-px h-3 bg-border"></div> <button class="px-2 py-1 hover:bg-muted rounded text-destructive transition-colors focus:outline-none">Delete message</button></div>'),_t=p('<div><button class="flex items-baseline gap-2 max-w-[80%] flex-row-reverse text-left focus:outline-none"><div data-testid="pending-message"> </div></button> <div><!></div> <!></div>'),ht=p('<!> <span class="sr-only">Send</span>',1),bt=p('<div class="flex flex-col flex-1 h-full overflow-hidden relative"><!> <div class="flex-1 overflow-y-auto p-4"><div class="w-full max-w-4xl mx-auto space-y-6 flex flex-col min-h-full"><!> <!> <!></div></div> <div class="p-4 bg-background/80 backdrop-blur-sm border-t shrink-0"><form class="flex items-center gap-2 max-w-4xl mx-auto"><!> <!></form></div></div>');function zt(k,r){Me(r,!0);let m=P(""),n=P(we([])),y=ke(()=>e(n).filter(t=>t.role==="user"||oe.verbosityLevel==="verbose"?!0:oe.verbosityLevel==="debug"?!t.level||t.level==="default"||t.level==="debug":!t.level||t.level==="default")),i=P(we([])),u=P(void 0),l=null,J=P(!0),W=P(!1),K,R=P(null);async function ue(t){const a=e(i).findIndex(s=>s.id===t);if(a!==-1){e(i)[a].status="sending",D(r.data.id,e(i));try{if(!(await fetch(`/api/chats/${r.data.id}/messages`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:e(i)[a].content})})).ok)throw new Error("Failed to send");await ne(`app:chat:${r.data.id}`)}catch(s){console.error("Failed to retry message:",s);const o=e(i).findIndex(x=>x.id===t);o!==-1&&(e(i)[o].status="failed",D(r.data.id,e(i)))}}}function Oe(t){f(i,e(i).filter(a=>a.id!==t),!0),D(r.data.id,e(i))}F(()=>{const t=()=>{e(i).forEach(a=>{(a.status==="pending"||a.status==="failed")&&ue(a.id)})};return window.addEventListener("online",t),()=>{window.removeEventListener("online",t)}});function ze(t){const a=t.target;f(J,Math.abs(a.scrollHeight-a.scrollTop-a.clientHeight)<10)}function X(){e(u)&&(e(u).scrollTop=e(u).scrollHeight)}F(()=>{f(n,r.data.messages,!0);try{const t=localStorage.getItem(`pending_messages_${r.data.id}`);t?f(i,JSON.parse(t),!0):f(i,[],!0)}catch{f(i,[],!0)}f(J,!0),Y(r.data.id)});function D(t,a){localStorage.setItem(`pending_messages_${t}`,JSON.stringify(a))}F(()=>{(e(n).length>0||e(i).length>0)&&e(u)&&e(J)&&Se().then(X)}),F(()=>{e(m),e(J)&&Se().then(X)}),F(()=>{const t=()=>{e(J)&&X()};return window.addEventListener("resize",t),window.visualViewport?.addEventListener("resize",t),()=>{window.removeEventListener("resize",t),window.visualViewport?.removeEventListener("resize",t)}});async function fe(){const t=e(n).length>0?e(n)[e(n).length-1].id:null;if(t)try{const a=await fetch(`/api/chats/${r.data.id}?since=${t}`);if(a.ok){const s=await a.json();for(const o of s)e(n).find(x=>x.id===o.id)||f(n,[...e(n),o],!0)}}catch(a){console.error("Failed to fetch delta messages:",a)}else await ne(`app:chat:${r.data.id}`)}F(()=>{const t=()=>{document.visibilityState==="visible"&&(fe(),(!l||l.readyState===EventSource.CLOSED)&&Y(r.data.id))};return document.addEventListener("visibilitychange",t),()=>{document.removeEventListener("visibilitychange",t)}});function Y(t){l&&(l.close(),clearTimeout(K)),l=new EventSource(`/api/chats/${t}/stream`),l.onopen=()=>{f(W,!1)},l.onerror=()=>{(l?.readyState===EventSource.CLOSED||l?.readyState===EventSource.CONNECTING)&&(f(W,!0),l.close(),clearTimeout(K),K=setTimeout(async()=>{await fe(),Y(t)},3e3))},l.onmessage=a=>{try{const s=JSON.parse(a.data);if(!e(n).find(o=>o.id===s.id)&&(f(n,[...e(n),s],!0),s.role==="user")){const o=e(i).findIndex(x=>x.content===s.content);o!==-1&&(f(i,e(i).filter((x,V)=>V!==o),!0),D(t,e(i)))}}catch(s){console.error("Failed to parse SSE message",s)}}}Ve(()=>{l&&l.close(),clearTimeout(K)});async function pe(t){if(t.preventDefault(),!e(m).trim())return;const a=e(m);f(m,"");const s={id:`pending-${Date.now()}-${Math.random()}`,content:a,timestamp:new Date().toISOString(),status:navigator.onLine?"sending":"pending"};if(f(i,[...e(i),s],!0),D(r.data.id,e(i)),!!navigator.onLine)try{if(!(await fetch(`/api/chats/${r.data.id}/messages`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:a})})).ok)throw new Error("Failed to send");await ne(`app:chat:${r.data.id}`)}catch(o){console.error("Failed to send message:",o),f(i,e(i).map(x=>x.id===s.id?{...x,status:"failed"}:x),!0),D(r.data.id,e(i))}}function $e(t){return new Date(t).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}var Z=bt(),me=c(Z);{var Ce=t=>{var a=at();d(t,a)};L(me,t=>{e(W)&&t(Ce)})}var B=S(me,2),xe=c(B),ge=c(xe);{var Pe=t=>{var a=rt();d(t,a)};L(ge,t=>{e(n).length===0&&t(Pe)})}var _e=S(ge,2);Te(_e,17,()=>e(y),t=>t.id,(t,a)=>{var s=ft(),o=c(s),x=c(o);{var V=E=>{var T=it(),H=c(T,!0);v(T),M(()=>O(H,e(a).content)),d(E,T)},I=E=>{var T=ut(),H=c(T);{var ae=g=>{var w=ct(),$=z(w),N=c($),G=c(N);v(N);var A=S(N,2);{var re=_=>{var h=st(),C=c(h);v(h),M(()=>O(C,`Exit: ${e(a).exitCode??""}`)),d(_,h)};L(A,_=>{e(a).exitCode!==0&&_(re)})}v($);var ye=S($,2);{var Fe=_=>{var h=nt(),C=c(h,!0);v(h),M(()=>O(C,e(a).content)),d(_,h)},je=_=>{var h=ot(),C=c(h,!0);v(h),M(()=>O(C,e(a).stdout)),d(_,h)},Je=_=>{var h=dt();d(_,h)};L(ye,_=>{e(a).content?_(Fe):e(a).stdout?_(je,1):_(Je,-1)})}var Re=S(ye,2);{var Be=_=>{var h=lt(),C=c(h,!0);v(h),M(()=>O(C,e(a).stderr)),d(_,h)};L(Re,_=>{e(a).stderr&&_(Be)})}M(()=>O(G,`$ ${e(a).command??""}`)),d(g,w)},b=g=>{var w=U(),$=z(w);{var N=G=>{var A=vt(),re=c(A,!0);v(A),M(()=>O(re,e(a).content)),d(G,A)};L($,G=>{e(a).content&&G(N)})}d(g,w)};L(H,g=>{oe.verbosityLevel==="verbose"?g(ae):g(b,-1)})}v(T),M(()=>j(T,1,`px-4 py-3 rounded-2xl bg-card border text-card-foreground text-sm shadow-sm ${e(a).level==="verbose"?"border-primary/50 bg-primary/5 shadow-md":""}`)),d(E,T)};L(x,E=>{e(a).role==="user"?E(V):E(I,-1)})}v(o);var q=S(o,2),te=c(q,!0);v(q),v(s),M(E=>{j(s,1,`flex flex-col gap-1 ${e(a).role==="user"?"items-end":"items-start"}`),j(o,1,`flex items-baseline gap-2 max-w-[80%] ${e(a).role==="user"?"flex-row-reverse":"flex-row"}`),O(te,E)},[()=>$e(e(a).timestamp)]),d(t,s)});var De=S(_e,2);Te(De,17,()=>e(i),t=>t.id,(t,a)=>{var s=_t(),o=c(s),x=c(o),V=c(x,!0);v(x),v(o);var I=S(o,2),q=c(I);{var te=b=>{var g=pt();Q(),d(b,g)},E=b=>{var g=mt(),w=z(g);Xe(w,{class:"w-3 h-3"}),Q(),d(b,g)},T=b=>{var g=xt(),w=z(g);We(w,{class:"w-3 h-3"}),Q(),d(b,g)};L(q,b=>{e(a).status==="sending"?b(te):e(a).status==="pending"?b(E,1):e(a).status==="failed"&&b(T,2)})}v(I);var H=S(I,2);{var ae=b=>{var g=gt(),w=c(g),$=S(w,4);v(g),ie("click",w,N=>{N.stopPropagation(),f(R,null),ue(e(a).id)}),ie("click",$,N=>{N.stopPropagation(),f(R,null),Oe(e(a).id)}),d(b,g)};L(H,b=>{e(R)===e(a).id&&e(a).status!=="sending"&&b(ae)})}v(s),M(()=>{j(s,1,`flex flex-col gap-1 items-end ${e(a).status==="sending"?"opacity-50":""} transition-opacity`),j(x,1,`px-4 py-2 rounded-2xl ${e(a).status==="failed"?"bg-destructive/90 text-destructive-foreground":"bg-primary text-primary-foreground"} text-sm`),O(V,e(a).content),j(I,1,`text-[10px] px-2 flex items-center gap-1 ${e(a).status==="failed"?"text-destructive font-medium":"text-muted-foreground"}`)}),ie("click",o,()=>{e(a).status!=="sending"&&f(R,e(R)===e(a).id?null:e(a).id,!0)}),d(t,s)}),v(xe),v(B),Ne(B,t=>f(u,t),()=>e(u));var he=S(B,2),ee=c(he),be=c(ee);tt(be,{placeholder:"Type your message...",class:"flex-1 min-h-[0px] resize-none overflow-hidden h-auto",onkeydown:t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),pe(t))},"data-testid":"message-input",get value(){return e(m)},set value(t){f(m,t,!0)}});var Ie=S(be,2);{let t=ke(()=>!e(m).trim());Ue(Ie,{type:"submit",get disabled(){return e(t)},size:"icon","data-testid":"send-button",children:(a,s)=>{var o=ht(),x=z(o);Ye(x,{class:"w-4 h-4"}),Q(2),d(a,o)},$$slots:{default:!0}})}v(ee),v(he),v(Z),Ee("scroll",B,ze),Ee("submit",ee,pe),d(k,Z),Le()}Ge(["click"]);export{zt as component,Ot as universal};
|
|
1
|
+
import{c as U,a as d,f as p}from"../chunks/Dc-UOHw9.js";import{a as Ve}from"../chunks/B8yYFADm.js";import{f as z,p as Me,a as Le,F as He,I as P,l as we,n as F,w as e,D as f,aR as Se,G as ke,s as S,c,r as v,t as M,C as Q}from"../chunks/CpaGRn9L.js";import{d as Ge,e as Ee,s as O,a as ie}from"../chunks/DG5RZBw-.js";import{l as de,s as le,p as se,b as Ne,r as Ae,i as L}from"../chunks/C3k55nDF.js";import{I as ce,s as ve,a as Ke,d as qe,c as Qe,e as Te,B as Ue,h as j}from"../chunks/BmUXQ3wy.js";import{i as ne}from"../chunks/DQoygso7.js";import{a as oe}from"../chunks/B5abRDXp.js";import"../chunks/Bi0jeV7Q.js";function We(k,r){const m=de(r,["children","$$slots","$$events","$$legacy"]);const n=[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16"}]];ce(k,le({name:"circle-alert"},()=>m,{get iconNode(){return n},children:(y,i)=>{var u=U(),l=z(u);ve(l,r,"default",{}),d(y,u)},$$slots:{default:!0}}))}function Xe(k,r){const m=de(r,["children","$$slots","$$events","$$legacy"]);const n=[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 6v6l4 2"}]];ce(k,le({name:"clock"},()=>m,{get iconNode(){return n},children:(y,i)=>{var u=U(),l=z(u);ve(l,r,"default",{}),d(y,u)},$$slots:{default:!0}}))}function Ye(k,r){const m=de(r,["children","$$slots","$$events","$$legacy"]);const n=[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"}],["path",{d:"m21.854 2.147-10.94 10.939"}]];ce(k,le({name:"send"},()=>m,{get iconNode(){return n},children:(y,i)=>{var u=U(),l=z(u);ve(l,r,"default",{}),d(y,u)},$$slots:{default:!0}}))}const Ze=async({params:k,fetch:r,depends:m})=>{const{id:n}=k;m(`app:chat:${n}`);try{const y=await r(`/api/chats/${n}`);if(y.ok){const i=await y.json();return{id:n,messages:i}}}catch(y){console.error(y)}return{id:n,messages:[]}},Ot=Object.freeze(Object.defineProperty({__proto__:null,load:Ze},Symbol.toStringTag,{value:"Module"}));var et=p("<textarea></textarea>");function tt(k,r){Me(r,!0);let m=se(r,"ref",15,null),n=se(r,"value",15),y=se(r,"data-slot",3,"textarea"),i=Ae(r,["$$slots","$$events","$$legacy","ref","value","class","data-slot"]);var u=et();He(u),Ke(u,l=>({"data-slot":y(),class:l,...i}),[()=>Qe("border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",r.class)]),Ne(u,l=>m(l),()=>m()),qe(u,n),d(k,u),Le()}var at=p('<div class="absolute top-4 left-1/2 -translate-x-1/2 bg-yellow-500/10 text-yellow-600 dark:text-yellow-400 text-xs px-3 py-1 rounded-full border border-yellow-500/20 backdrop-blur-sm shadow-sm z-10 flex items-center gap-2"><span class="inline-block w-3 h-3 rounded-full border-2 border-current border-t-transparent animate-spin"></span> Reconnecting...</div>'),rt=p('<div class="flex-1 flex items-center justify-center text-muted-foreground text-sm">No messages yet. Send a message to start the conversation!</div>'),it=p('<div class="px-4 py-2 rounded-2xl bg-primary text-primary-foreground text-sm" data-testid="user-message"> </div>'),st=p('<span class="text-destructive font-bold"> </span>'),nt=p('<div class="whitespace-pre-wrap"> </div>'),ot=p('<div class="whitespace-pre-wrap font-mono text-xs mt-2"> </div>'),dt=p('<div class="whitespace-pre-wrap italic opacity-50 text-xs mt-2">No output</div>'),lt=p('<div class="whitespace-pre-wrap font-mono text-xs mt-2 text-destructive border border-destructive/20 bg-destructive/5 p-2 rounded"> </div>'),ct=p('<div class="font-mono text-xs text-muted-foreground mb-2 flex items-center gap-2"><span> </span> <!></div> <!> <!>',1),vt=p('<div class="whitespace-pre-wrap"> </div>'),ut=p('<div data-testid="log-message"><!></div>'),ft=p('<div><div><!></div> <div class="text-[10px] text-muted-foreground px-2"> </div></div>'),pt=p('<span class="inline-block w-2 h-2 rounded-full border border-current border-t-transparent animate-spin"></span> Sending...',1),mt=p("<!> Offline / Pending",1),xt=p("<!> Failed",1),gt=p('<div class="flex items-center gap-2 mt-1 mr-2 bg-card border rounded-md p-1 shadow-sm text-xs"><button class="px-2 py-1 hover:bg-muted rounded text-primary transition-colors focus:outline-none">Retry manual send</button> <div class="w-px h-3 bg-border"></div> <button class="px-2 py-1 hover:bg-muted rounded text-destructive transition-colors focus:outline-none">Delete message</button></div>'),_t=p('<div><button class="flex items-baseline gap-2 max-w-[80%] flex-row-reverse text-left focus:outline-none"><div data-testid="pending-message"> </div></button> <div><!></div> <!></div>'),ht=p('<!> <span class="sr-only">Send</span>',1),bt=p('<div class="flex flex-col flex-1 h-full overflow-hidden relative"><!> <div class="flex-1 overflow-y-auto p-4"><div class="w-full max-w-4xl mx-auto space-y-6 flex flex-col min-h-full"><!> <!> <!></div></div> <div class="p-4 bg-background/80 backdrop-blur-sm border-t shrink-0"><form class="flex items-center gap-2 max-w-4xl mx-auto"><!> <!></form></div></div>');function zt(k,r){Me(r,!0);let m=P(""),n=P(we([])),y=ke(()=>e(n).filter(t=>t.role==="user"||oe.verbosityLevel==="verbose"?!0:oe.verbosityLevel==="debug"?!t.level||t.level==="default"||t.level==="debug":!t.level||t.level==="default")),i=P(we([])),u=P(void 0),l=null,J=P(!0),W=P(!1),K,R=P(null);async function ue(t){const a=e(i).findIndex(s=>s.id===t);if(a!==-1){e(i)[a].status="sending",D(r.data.id,e(i));try{if(!(await fetch(`/api/chats/${r.data.id}/messages`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:e(i)[a].content})})).ok)throw new Error("Failed to send");await ne(`app:chat:${r.data.id}`)}catch(s){console.error("Failed to retry message:",s);const o=e(i).findIndex(x=>x.id===t);o!==-1&&(e(i)[o].status="failed",D(r.data.id,e(i)))}}}function Oe(t){f(i,e(i).filter(a=>a.id!==t),!0),D(r.data.id,e(i))}F(()=>{const t=()=>{e(i).forEach(a=>{(a.status==="pending"||a.status==="failed")&&ue(a.id)})};return window.addEventListener("online",t),()=>{window.removeEventListener("online",t)}});function ze(t){const a=t.target;f(J,Math.abs(a.scrollHeight-a.scrollTop-a.clientHeight)<10)}function X(){e(u)&&(e(u).scrollTop=e(u).scrollHeight)}F(()=>{f(n,r.data.messages,!0);try{const t=localStorage.getItem(`pending_messages_${r.data.id}`);t?f(i,JSON.parse(t),!0):f(i,[],!0)}catch{f(i,[],!0)}f(J,!0),Y(r.data.id)});function D(t,a){localStorage.setItem(`pending_messages_${t}`,JSON.stringify(a))}F(()=>{(e(n).length>0||e(i).length>0)&&e(u)&&e(J)&&Se().then(X)}),F(()=>{e(m),e(J)&&Se().then(X)}),F(()=>{const t=()=>{e(J)&&X()};return window.addEventListener("resize",t),window.visualViewport?.addEventListener("resize",t),()=>{window.removeEventListener("resize",t),window.visualViewport?.removeEventListener("resize",t)}});async function fe(){const t=e(n).length>0?e(n)[e(n).length-1].id:null;if(t)try{const a=await fetch(`/api/chats/${r.data.id}?since=${t}`);if(a.ok){const s=await a.json();for(const o of s)e(n).find(x=>x.id===o.id)||f(n,[...e(n),o],!0)}}catch(a){console.error("Failed to fetch delta messages:",a)}else await ne(`app:chat:${r.data.id}`)}F(()=>{const t=()=>{document.visibilityState==="visible"&&(fe(),(!l||l.readyState===EventSource.CLOSED)&&Y(r.data.id))};return document.addEventListener("visibilitychange",t),()=>{document.removeEventListener("visibilitychange",t)}});function Y(t){l&&(l.close(),clearTimeout(K)),l=new EventSource(`/api/chats/${t}/stream`),l.onopen=()=>{f(W,!1)},l.onerror=()=>{(l?.readyState===EventSource.CLOSED||l?.readyState===EventSource.CONNECTING)&&(f(W,!0),l.close(),clearTimeout(K),K=setTimeout(async()=>{await fe(),Y(t)},3e3))},l.onmessage=a=>{try{const s=JSON.parse(a.data);if(!e(n).find(o=>o.id===s.id)&&(f(n,[...e(n),s],!0),s.role==="user")){const o=e(i).findIndex(x=>x.content===s.content);o!==-1&&(f(i,e(i).filter((x,V)=>V!==o),!0),D(t,e(i)))}}catch(s){console.error("Failed to parse SSE message",s)}}}Ve(()=>{l&&l.close(),clearTimeout(K)});async function pe(t){if(t.preventDefault(),!e(m).trim())return;const a=e(m);f(m,"");const s={id:`pending-${Date.now()}-${Math.random()}`,content:a,timestamp:new Date().toISOString(),status:navigator.onLine?"sending":"pending"};if(f(i,[...e(i),s],!0),D(r.data.id,e(i)),!!navigator.onLine)try{if(!(await fetch(`/api/chats/${r.data.id}/messages`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:a})})).ok)throw new Error("Failed to send");await ne(`app:chat:${r.data.id}`)}catch(o){console.error("Failed to send message:",o),f(i,e(i).map(x=>x.id===s.id?{...x,status:"failed"}:x),!0),D(r.data.id,e(i))}}function $e(t){return new Date(t).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}var Z=bt(),me=c(Z);{var Ce=t=>{var a=at();d(t,a)};L(me,t=>{e(W)&&t(Ce)})}var B=S(me,2),xe=c(B),ge=c(xe);{var Pe=t=>{var a=rt();d(t,a)};L(ge,t=>{e(n).length===0&&t(Pe)})}var _e=S(ge,2);Te(_e,17,()=>e(y),t=>t.id,(t,a)=>{var s=ft(),o=c(s),x=c(o);{var V=E=>{var T=it(),H=c(T,!0);v(T),M(()=>O(H,e(a).content)),d(E,T)},I=E=>{var T=ut(),H=c(T);{var ae=g=>{var w=ct(),$=z(w),N=c($),G=c(N);v(N);var A=S(N,2);{var re=_=>{var h=st(),C=c(h);v(h),M(()=>O(C,`Exit: ${e(a).exitCode??""}`)),d(_,h)};L(A,_=>{e(a).exitCode!==0&&_(re)})}v($);var ye=S($,2);{var Fe=_=>{var h=nt(),C=c(h,!0);v(h),M(()=>O(C,e(a).content)),d(_,h)},je=_=>{var h=ot(),C=c(h,!0);v(h),M(()=>O(C,e(a).stdout)),d(_,h)},Je=_=>{var h=dt();d(_,h)};L(ye,_=>{e(a).content?_(Fe):e(a).stdout?_(je,1):_(Je,-1)})}var Re=S(ye,2);{var Be=_=>{var h=lt(),C=c(h,!0);v(h),M(()=>O(C,e(a).stderr)),d(_,h)};L(Re,_=>{e(a).stderr&&_(Be)})}M(()=>O(G,`$ ${e(a).command??""}`)),d(g,w)},b=g=>{var w=U(),$=z(w);{var N=G=>{var A=vt(),re=c(A,!0);v(A),M(()=>O(re,e(a).content)),d(G,A)};L($,G=>{e(a).content&&G(N)})}d(g,w)};L(H,g=>{oe.verbosityLevel==="verbose"?g(ae):g(b,-1)})}v(T),M(()=>j(T,1,`px-4 py-3 rounded-2xl bg-card border text-card-foreground text-sm shadow-sm ${e(a).level==="verbose"?"border-primary/50 bg-primary/5 shadow-md":""}`)),d(E,T)};L(x,E=>{e(a).role==="user"?E(V):E(I,-1)})}v(o);var q=S(o,2),te=c(q,!0);v(q),v(s),M(E=>{j(s,1,`flex flex-col gap-1 ${e(a).role==="user"?"items-end":"items-start"}`),j(o,1,`flex items-baseline gap-2 max-w-[80%] ${e(a).role==="user"?"flex-row-reverse":"flex-row"}`),O(te,E)},[()=>$e(e(a).timestamp)]),d(t,s)});var De=S(_e,2);Te(De,17,()=>e(i),t=>t.id,(t,a)=>{var s=_t(),o=c(s),x=c(o),V=c(x,!0);v(x),v(o);var I=S(o,2),q=c(I);{var te=b=>{var g=pt();Q(),d(b,g)},E=b=>{var g=mt(),w=z(g);Xe(w,{class:"w-3 h-3"}),Q(),d(b,g)},T=b=>{var g=xt(),w=z(g);We(w,{class:"w-3 h-3"}),Q(),d(b,g)};L(q,b=>{e(a).status==="sending"?b(te):e(a).status==="pending"?b(E,1):e(a).status==="failed"&&b(T,2)})}v(I);var H=S(I,2);{var ae=b=>{var g=gt(),w=c(g),$=S(w,4);v(g),ie("click",w,N=>{N.stopPropagation(),f(R,null),ue(e(a).id)}),ie("click",$,N=>{N.stopPropagation(),f(R,null),Oe(e(a).id)}),d(b,g)};L(H,b=>{e(R)===e(a).id&&e(a).status!=="sending"&&b(ae)})}v(s),M(()=>{j(s,1,`flex flex-col gap-1 items-end ${e(a).status==="sending"?"opacity-50":""} transition-opacity`),j(x,1,`px-4 py-2 rounded-2xl ${e(a).status==="failed"?"bg-destructive/90 text-destructive-foreground":"bg-primary text-primary-foreground"} text-sm`),O(V,e(a).content),j(I,1,`text-[10px] px-2 flex items-center gap-1 ${e(a).status==="failed"?"text-destructive font-medium":"text-muted-foreground"}`)}),ie("click",o,()=>{e(a).status!=="sending"&&f(R,e(R)===e(a).id?null:e(a).id,!0)}),d(t,s)}),v(xe),v(B),Ne(B,t=>f(u,t),()=>e(u));var he=S(B,2),ee=c(he),be=c(ee);tt(be,{placeholder:"Type your message...",class:"flex-1 min-h-[0px] resize-none overflow-hidden h-auto",onkeydown:t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),pe(t))},"data-testid":"message-input",get value(){return e(m)},set value(t){f(m,t,!0)}});var Ie=S(be,2);{let t=ke(()=>!e(m).trim());Ue(Ie,{type:"submit",get disabled(){return e(t)},size:"icon","data-testid":"send-button",children:(a,s)=>{var o=ht(),x=z(o);Ye(x,{class:"w-4 h-4"}),Q(2),d(a,o)},$$slots:{default:!0}})}v(ee),v(he),v(Z),Ee("scroll",B,ze),Ee("submit",ee,pe),d(k,Z),Le()}Ge(["click"]);export{zt as component,Ot as universal};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as W,a as l,f as w,t as D}from"../chunks/Dc-UOHw9.js";import{f as z,p as be,t as j,a as _e,c as r,D as v,w as e,I as J,s as o,r as a,C as N,G as xe}from"../chunks/CpaGRn9L.js";import{s as M,e as ye}from"../chunks/DG5RZBw-.js";import{l as oe,s as se,i as T}from"../chunks/C3k55nDF.js";import{I as de,s as ie,B as H,f as we,g as $e,e as Se}from"../chunks/BmUXQ3wy.js";import{i as re}from"../chunks/
|
|
1
|
+
import{c as W,a as l,f as w,t as D}from"../chunks/Dc-UOHw9.js";import{f as z,p as be,t as j,a as _e,c as r,D as v,w as e,I as J,s as o,r as a,C as N,G as xe}from"../chunks/CpaGRn9L.js";import{s as M,e as ye}from"../chunks/DG5RZBw-.js";import{l as oe,s as se,i as T}from"../chunks/C3k55nDF.js";import{I as de,s as ie,B as H,f as we,g as $e,e as Se}from"../chunks/BmUXQ3wy.js";import{i as re}from"../chunks/DQoygso7.js";import{P as ke,I as U}from"../chunks/ZkLyk0mE.js";import"../chunks/Bi0jeV7Q.js";function je($,c){const b=oe(c,["children","$$slots","$$events","$$legacy"]);const u=[["path",{d:"m12 19-7-7 7-7"}],["path",{d:"M19 12H5"}]];de($,se({name:"arrow-left"},()=>b,{get iconNode(){return u},children:(h,m)=>{var p=W(),g=z(p);ie(g,c,"default",{}),l(h,p)},$$slots:{default:!0}}))}function Je($,c){const b=oe(c,["children","$$slots","$$events","$$legacy"]);const u=[["path",{d:"M10 11v6"}],["path",{d:"M14 11v6"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"}],["path",{d:"M3 6h18"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"}]];de($,se({name:"trash-2"},()=>b,{get iconNode(){return u},children:(h,m)=>{var p=W(),g=z(p);ie(g,c,"default",{}),l(h,p)},$$slots:{default:!0}}))}const Me=async({params:$,fetch:c,depends:b})=>{const{id:u}=$;b(`app:chat:${u}:cron`);let h=[];try{const m=await c(`/api/chats/${u}/cron`);m.ok&&(h=await m.json())}catch(m){console.error("Failed to load cron jobs:",m)}return{id:u,cronJobs:h}},Le=Object.freeze(Object.defineProperty({__proto__:null,load:Me},Symbol.toStringTag,{value:"Module"}));var Te=w("<!> Add Job",1),Ee=w('<div class="p-3 bg-destructive/10 text-destructive text-sm rounded-md border border-destructive/20"> </div>'),Ie=w(`<form class="p-4 border rounded-lg space-y-4 bg-card text-card-foreground shadow-sm"><div class="grid grid-cols-2 gap-4"><div class="space-y-2"><label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="jobId">Job ID</label> <!></div> <div class="space-y-2"><label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="jobType">Schedule Type</label> <select id="jobType" class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"><option>Cron Expression</option><option>Every (e.g. '1h', '30m')</option><option>At (ISO Date/Time)</option></select></div> <div class="space-y-2 col-span-2"><label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="jobSchedule">Schedule Expression</label> <!></div> <div class="space-y-2 col-span-2"><label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="jobMessage">Message / Command</label> <!></div></div> <div class="flex justify-end gap-2 pt-2"><!> <!></div></form>`),Pe=w('<div class="p-8 text-center text-muted-foreground border rounded-lg border-dashed">No cron jobs configured for this chat.</div>'),Ce=w('<!> <span class="sr-only">Delete</span>',1),De=w('<div class="flex items-center justify-between p-4 border rounded-lg bg-card text-card-foreground shadow-sm"><div class="space-y-1.5 overflow-hidden"><div class="font-medium flex items-center gap-2"><span class="truncate"> </span> <span class="shrink-0 px-2 py-0.5 text-[10px] uppercase font-bold tracking-wider rounded-full bg-secondary text-secondary-foreground"><!> <!> <!></span></div> <div class="text-sm text-muted-foreground font-mono bg-muted/50 p-1.5 rounded-md truncate"> </div></div> <!></div>'),Ne=w('<div class="grid gap-4"></div>'),ze=w('<div class="flex-1 overflow-y-auto p-6 h-full bg-background text-foreground"><div class="max-w-4xl mx-auto space-y-8"><div class="flex items-center gap-4"><a class="p-2 -ml-2 rounded-full hover:bg-muted text-muted-foreground hover:text-foreground transition-colors" title="Back to Chat"><!></a> <h1 class="text-2xl font-bold tracking-tight">Chat Settings</h1></div> <section class="space-y-4"><div class="flex items-center justify-between"><h2 class="text-xl font-semibold">Cron Jobs</h2> <!></div> <!> <!> <!></section></div></div>');function Ze($,c){be(c,!0);let b=xe(()=>c.data.cronJobs),u=J(!1),h=J(""),m=J(""),p=J(""),g=J("cron"),A=J(!1),O=J("");async function ne(s){if(confirm("Are you sure you want to delete this job?"))try{if(!(await fetch(`/api/chats/${c.data.id}/cron/${s}`,{method:"DELETE"})).ok)throw new Error("Failed to delete job");await re(`app:chat:${c.data.id}:cron`)}catch(t){alert(t instanceof Error?t.message:String(t))}}async function le(s){s.preventDefault(),v(A,!0),v(O,"");try{const t={id:e(h),message:e(m),schedule:{}};e(g)==="cron"?t.schedule.cron=e(p):e(g)==="every"?t.schedule.every=e(p):e(g)==="at"&&(t.schedule.at=e(p));const n=await fetch(`/api/chats/${c.data.id}/cron`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok){const d=await n.json();throw new Error(d.error||"Failed to add job")}v(u,!1),v(h,""),v(m,""),v(p,""),v(g,"cron"),await re(`app:chat:${c.data.id}:cron`)}catch(t){v(O,t instanceof Error?t.message:String(t),!0)}finally{v(A,!1)}}var V=ze(),X=r(V),G=r(X),L=r(G),ce=r(L);je(ce,{class:"w-5 h-5"}),a(L),N(2),a(G);var Y=o(G,2),Z=r(Y),ve=o(r(Z),2);H(ve,{variant:"outline",size:"sm",onclick:()=>v(u,!e(u)),children:(s,t)=>{var n=Te(),d=z(n);ke(d,{class:"w-4 h-4 mr-2"}),N(),l(s,n)},$$slots:{default:!0}}),a(Z);var ee=o(Z,2);{var ue=s=>{var t=Ee(),n=r(t,!0);a(t),j(()=>M(n,e(O))),l(s,t)};T(ee,s=>{e(O)&&s(ue)})}var te=o(ee,2);{var fe=s=>{var t=Ie(),n=r(t),d=r(n),_=o(r(d),2);U(_,{id:"jobId",placeholder:"e.g. daily-standup",required:!0,get value(){return e(h)},set value(f){v(h,f,!0)}}),a(d);var x=o(d,2),S=o(r(x),2),k=r(S);k.value=k.__value="cron";var I=o(k);I.value=I.__value="every";var P=o(I);P.value=P.__value="at",a(S),a(x);var E=o(x,2),K=o(r(E),2);U(K,{id:"jobSchedule",placeholder:"e.g. * * * * *, 1h, or 2024-01-01T12:00:00Z",required:!0,get value(){return e(p)},set value(f){v(p,f,!0)}}),a(E);var C=o(E,2),Q=o(r(C),2);U(Q,{id:"jobMessage",placeholder:"Command to run...",required:!0,get value(){return e(m)},set value(f){v(m,f,!0)}}),a(C),a(n);var q=o(n,2),B=r(q);H(B,{type:"button",variant:"ghost",onclick:()=>v(u,!1),children:(f,R)=>{N();var i=D("Cancel");l(f,i)},$$slots:{default:!0}});var F=o(B,2);H(F,{type:"submit",get disabled(){return e(A)},children:(f,R)=>{N();var i=D();j(()=>M(i,e(A)?"Saving...":"Save Job")),l(f,i)},$$slots:{default:!0}}),a(q),a(t),ye("submit",t,le),$e(S,()=>e(g),f=>v(g,f)),l(s,t)};T(te,s=>{e(u)&&s(fe)})}var pe=o(te,2);{var he=s=>{var t=W(),n=z(t);{var d=_=>{var x=Pe();l(_,x)};T(n,_=>{e(u)||_(d)})}l(s,t)},me=s=>{var t=Ne();Se(t,21,()=>e(b),n=>n.id,(n,d)=>{var _=De(),x=r(_),S=r(x),k=r(S),I=r(k,!0);a(k);var P=o(k,2),E=r(P);{var K=i=>{var y=D();j(()=>M(y,`cron: ${e(d).schedule.cron??""}`)),l(i,y)};T(E,i=>{e(d).schedule.cron&&i(K)})}var C=o(E,2);{var Q=i=>{var y=D();j(()=>M(y,`every: ${e(d).schedule.every??""}`)),l(i,y)};T(C,i=>{e(d).schedule.every&&i(Q)})}var q=o(C,2);{var B=i=>{var y=D();j(()=>M(y,`at: ${e(d).schedule.at??""}`)),l(i,y)};T(q,i=>{e(d).schedule.at&&i(B)})}a(P),a(S);var F=o(S,2),f=r(F);a(F),a(x);var R=o(x,2);H(R,{variant:"ghost",size:"icon",class:"shrink-0 text-destructive hover:bg-destructive/10 hover:text-destructive",onclick:()=>ne(e(d).id),children:(i,y)=>{var ae=Ce(),ge=z(ae);Je(ge,{class:"w-4 h-4"}),N(2),l(i,ae)},$$slots:{default:!0}}),a(_),j(()=>{M(I,e(d).id),M(f,`$ ${e(d).message??""}`)}),l(n,_)}),a(t),l(s,t)};T(pe,s=>{!e(b)||e(b).length===0?s(he):s(me,-1)})}a(Y),a(X),a(V),j(()=>we(L,"href",`/chats/${c.data.id??""}`)),l($,V),_e()}export{Ze as component,Le as universal};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"
|
|
1
|
+
{"version":"1773350407558"}
|
|
@@ -101,7 +101,7 @@ const options = {
|
|
|
101
101
|
<div class="error">
|
|
102
102
|
<span class="status">` + status + '</span>\n <div class="message">\n <h1>' + message + "</h1>\n </div>\n </div>\n </body>\n</html>\n"
|
|
103
103
|
},
|
|
104
|
-
version_hash: "
|
|
104
|
+
version_hash: "8qk5h6"
|
|
105
105
|
};
|
|
106
106
|
async function get_hooks() {
|
|
107
107
|
let handle;
|
|
@@ -10,7 +10,7 @@ return {
|
|
|
10
10
|
assets: new Set(["robots.txt"]),
|
|
11
11
|
mimeTypes: {".txt":"text/plain"},
|
|
12
12
|
_: {
|
|
13
|
-
client: {start:"_app/immutable/entry/start.
|
|
13
|
+
client: {start:"_app/immutable/entry/start.D48mVn1m.js",app:"_app/immutable/entry/app.DO5eYwVz.js",imports:["_app/immutable/entry/start.D48mVn1m.js","_app/immutable/chunks/DQoygso7.js","_app/immutable/chunks/CpaGRn9L.js","_app/immutable/chunks/B8yYFADm.js","_app/immutable/entry/app.DO5eYwVz.js","_app/immutable/chunks/CpaGRn9L.js","_app/immutable/chunks/DG5RZBw-.js","_app/immutable/chunks/Dc-UOHw9.js","_app/immutable/chunks/B8yYFADm.js","_app/immutable/chunks/C3k55nDF.js","_app/immutable/chunks/CyNaE55B.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
|
|
14
14
|
nodes: [
|
|
15
15
|
__memo(() => import('./nodes/0.js')),
|
|
16
16
|
__memo(() => import('./nodes/1.js')),
|
|
@@ -10,7 +10,7 @@ return {
|
|
|
10
10
|
assets: new Set(["robots.txt"]),
|
|
11
11
|
mimeTypes: {".txt":"text/plain"},
|
|
12
12
|
_: {
|
|
13
|
-
client: {start:"_app/immutable/entry/start.
|
|
13
|
+
client: {start:"_app/immutable/entry/start.D48mVn1m.js",app:"_app/immutable/entry/app.DO5eYwVz.js",imports:["_app/immutable/entry/start.D48mVn1m.js","_app/immutable/chunks/DQoygso7.js","_app/immutable/chunks/CpaGRn9L.js","_app/immutable/chunks/B8yYFADm.js","_app/immutable/entry/app.DO5eYwVz.js","_app/immutable/chunks/CpaGRn9L.js","_app/immutable/chunks/DG5RZBw-.js","_app/immutable/chunks/Dc-UOHw9.js","_app/immutable/chunks/B8yYFADm.js","_app/immutable/chunks/C3k55nDF.js","_app/immutable/chunks/CyNaE55B.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
|
|
14
14
|
nodes: [
|
|
15
15
|
__memo(() => import('./nodes/0.js')),
|
|
16
16
|
__memo(() => import('./nodes/1.js')),
|
|
@@ -8,6 +8,6 @@ export const universal = {
|
|
|
8
8
|
"load": null
|
|
9
9
|
};
|
|
10
10
|
export const universal_id = "src/routes/+layout.ts";
|
|
11
|
-
export const imports = ["_app/immutable/nodes/0.
|
|
11
|
+
export const imports = ["_app/immutable/nodes/0.B-0CcADM.js","_app/immutable/chunks/Dc-UOHw9.js","_app/immutable/chunks/CpaGRn9L.js","_app/immutable/chunks/DG5RZBw-.js","_app/immutable/chunks/BmUXQ3wy.js","_app/immutable/chunks/C3k55nDF.js","_app/immutable/chunks/Bi0jeV7Q.js","_app/immutable/chunks/DcrmIfTj.js","_app/immutable/chunks/CyNaE55B.js","_app/immutable/chunks/BPy8HLo7.js","_app/immutable/chunks/B8yYFADm.js","_app/immutable/chunks/8YNcRyEk.js","_app/immutable/chunks/DQoygso7.js","_app/immutable/chunks/ZkLyk0mE.js","_app/immutable/chunks/B5abRDXp.js"];
|
|
12
12
|
export const stylesheets = ["_app/immutable/assets/0.GI4C4dpV.css"];
|
|
13
13
|
export const fonts = [];
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
export const index = 1;
|
|
4
4
|
let component_cache;
|
|
5
5
|
export const component = async () => component_cache ??= (await import('../entries/fallbacks/error.svelte.js')).default;
|
|
6
|
-
export const imports = ["_app/immutable/nodes/1.
|
|
6
|
+
export const imports = ["_app/immutable/nodes/1.FixKgvRO.js","_app/immutable/chunks/Dc-UOHw9.js","_app/immutable/chunks/CpaGRn9L.js","_app/immutable/chunks/Bi0jeV7Q.js","_app/immutable/chunks/DG5RZBw-.js","_app/immutable/chunks/DcrmIfTj.js","_app/immutable/chunks/8YNcRyEk.js","_app/immutable/chunks/DQoygso7.js","_app/immutable/chunks/B8yYFADm.js"];
|
|
7
7
|
export const stylesheets = [];
|
|
8
8
|
export const fonts = [];
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
export const index = 3;
|
|
4
4
|
let component_cache;
|
|
5
5
|
export const component = async () => component_cache ??= (await import('../entries/pages/agents/_page.svelte.js')).default;
|
|
6
|
-
export const imports = ["_app/immutable/nodes/3.
|
|
6
|
+
export const imports = ["_app/immutable/nodes/3.ncP0xLO6.js","_app/immutable/chunks/Dc-UOHw9.js","_app/immutable/chunks/CpaGRn9L.js","_app/immutable/chunks/DG5RZBw-.js","_app/immutable/chunks/C3k55nDF.js","_app/immutable/chunks/BmUXQ3wy.js","_app/immutable/chunks/Bi0jeV7Q.js","_app/immutable/chunks/DcrmIfTj.js","_app/immutable/chunks/CyNaE55B.js","_app/immutable/chunks/DQoygso7.js","_app/immutable/chunks/B8yYFADm.js","_app/immutable/chunks/ZkLyk0mE.js","_app/immutable/chunks/BPy8HLo7.js"];
|
|
7
7
|
export const stylesheets = [];
|
|
8
8
|
export const fonts = [];
|
|
@@ -8,6 +8,6 @@ export const universal = {
|
|
|
8
8
|
"load": null
|
|
9
9
|
};
|
|
10
10
|
export const universal_id = "src/routes/chats/[id]/+page.ts";
|
|
11
|
-
export const imports = ["_app/immutable/nodes/4.
|
|
11
|
+
export const imports = ["_app/immutable/nodes/4.CQYJEgv8.js","_app/immutable/chunks/Dc-UOHw9.js","_app/immutable/chunks/CpaGRn9L.js","_app/immutable/chunks/B8yYFADm.js","_app/immutable/chunks/DG5RZBw-.js","_app/immutable/chunks/C3k55nDF.js","_app/immutable/chunks/BmUXQ3wy.js","_app/immutable/chunks/Bi0jeV7Q.js","_app/immutable/chunks/DcrmIfTj.js","_app/immutable/chunks/DQoygso7.js","_app/immutable/chunks/B5abRDXp.js"];
|
|
12
12
|
export const stylesheets = [];
|
|
13
13
|
export const fonts = [];
|
|
@@ -8,6 +8,6 @@ export const universal = {
|
|
|
8
8
|
"load": null
|
|
9
9
|
};
|
|
10
10
|
export const universal_id = "src/routes/chats/[id]/settings/+page.ts";
|
|
11
|
-
export const imports = ["_app/immutable/nodes/5.
|
|
11
|
+
export const imports = ["_app/immutable/nodes/5.BpJUN6QH.js","_app/immutable/chunks/Dc-UOHw9.js","_app/immutable/chunks/CpaGRn9L.js","_app/immutable/chunks/DG5RZBw-.js","_app/immutable/chunks/C3k55nDF.js","_app/immutable/chunks/BmUXQ3wy.js","_app/immutable/chunks/Bi0jeV7Q.js","_app/immutable/chunks/DcrmIfTj.js","_app/immutable/chunks/DQoygso7.js","_app/immutable/chunks/B8yYFADm.js","_app/immutable/chunks/ZkLyk0mE.js"];
|
|
12
12
|
export const stylesheets = [];
|
|
13
13
|
export const fonts = [];
|
package/dist/chats-BcbxvPlj.mjs
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-95iHPtFO.mjs";
|
|
2
|
-
import { n as appendMessage$1 } from "./chats-CpRQrNHj.mjs";
|
|
3
|
-
import { EventEmitter } from "node:events";
|
|
4
|
-
|
|
5
|
-
//#region src/daemon/events.ts
|
|
6
|
-
const daemonEvents = new EventEmitter();
|
|
7
|
-
const DAEMON_EVENT_MESSAGE_APPENDED = "message-appended";
|
|
8
|
-
const DAEMON_EVENT_TYPING = "typing";
|
|
9
|
-
function emitMessageAppended(chatId, message) {
|
|
10
|
-
daemonEvents.emit(DAEMON_EVENT_MESSAGE_APPENDED, {
|
|
11
|
-
chatId,
|
|
12
|
-
message
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
function emitTyping(chatId) {
|
|
16
|
-
daemonEvents.emit(DAEMON_EVENT_TYPING, { chatId });
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
//#endregion
|
|
20
|
-
//#region src/daemon/chats.ts
|
|
21
|
-
var chats_exports = /* @__PURE__ */ __exportAll({ appendMessage: () => appendMessage });
|
|
22
|
-
async function appendMessage(id, message, startDir = process.cwd()) {
|
|
23
|
-
await appendMessage$1(id, message, startDir);
|
|
24
|
-
emitMessageAppended(id, message);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
//#endregion
|
|
28
|
-
export { daemonEvents as a, DAEMON_EVENT_TYPING as i, chats_exports as n, emitTyping as o, DAEMON_EVENT_MESSAGE_APPENDED as r, appendMessage as t };
|
|
29
|
-
//# sourceMappingURL=chats-BcbxvPlj.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chats-BcbxvPlj.mjs","names":["shared.appendMessage"],"sources":["../src/daemon/events.ts","../src/daemon/chats.ts"],"sourcesContent":["import { EventEmitter } from 'node:events';\nimport type { ChatMessage } from '../shared/chats.js';\n\nexport const daemonEvents = new EventEmitter();\n\nexport const DAEMON_EVENT_MESSAGE_APPENDED = 'message-appended';\nexport const DAEMON_EVENT_TYPING = 'typing';\n\nexport function emitMessageAppended(chatId: string, message: ChatMessage) {\n daemonEvents.emit(DAEMON_EVENT_MESSAGE_APPENDED, { chatId, message });\n}\n\nexport function emitTyping(chatId: string) {\n daemonEvents.emit(DAEMON_EVENT_TYPING, { chatId });\n}\n","import * as shared from '../shared/chats.js';\nimport { emitMessageAppended } from './events.js';\n\nexport async function appendMessage(\n id: string,\n message: shared.ChatMessage,\n startDir = process.cwd()\n): Promise<void> {\n await shared.appendMessage(id, message, startDir);\n emitMessageAppended(id, message);\n}\n\nexport {\n type ChatMessage,\n type UserMessage,\n type CommandLogMessage,\n getChatsDir,\n isValidChatId,\n createChat,\n listChats,\n deleteChat,\n getMessages,\n getDefaultChatId,\n setDefaultChatId,\n DEFAULT_CHAT_ID,\n} from '../shared/chats.js';\n"],"mappings":";;;;;AAGA,MAAa,eAAe,IAAI,cAAc;AAE9C,MAAa,gCAAgC;AAC7C,MAAa,sBAAsB;AAEnC,SAAgB,oBAAoB,QAAgB,SAAsB;AACxE,cAAa,KAAK,+BAA+B;EAAE;EAAQ;EAAS,CAAC;;AAGvE,SAAgB,WAAW,QAAgB;AACzC,cAAa,KAAK,qBAAqB,EAAE,QAAQ,CAAC;;;;;;ACVpD,eAAsB,cACpB,IACA,SACA,WAAW,QAAQ,KAAK,EACT;AACf,OAAMA,gBAAqB,IAAI,SAAS,SAAS;AACjD,qBAAoB,IAAI,QAAQ"}
|
package/dist/chats-CpRQrNHj.mjs
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { c as getSettingsPath, o as getClawminiDir } from "./workspace-BC1ahx4R.mjs";
|
|
2
|
-
import { n as pathIsInsideDir } from "./fs-B5wW0oaH.mjs";
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import fs$1 from "node:fs/promises";
|
|
6
|
-
|
|
7
|
-
//#region src/shared/chats.ts
|
|
8
|
-
const DEFAULT_CHAT_ID = "default";
|
|
9
|
-
async function getChatsDir(startDir = process.cwd()) {
|
|
10
|
-
const dir = path.join(getClawminiDir(startDir), "chats");
|
|
11
|
-
if (!existsSync(dir)) await fs$1.mkdir(dir, { recursive: true });
|
|
12
|
-
return dir;
|
|
13
|
-
}
|
|
14
|
-
function isValidChatId(chatId) {
|
|
15
|
-
if (!chatId || chatId.length === 0) return false;
|
|
16
|
-
return /^[a-zA-Z0-9_-]+$/.test(chatId);
|
|
17
|
-
}
|
|
18
|
-
function assertValidChatId(id) {
|
|
19
|
-
if (!isValidChatId(id)) throw new Error(`Invalid chat ID: ${id}`);
|
|
20
|
-
}
|
|
21
|
-
async function createChat(id, startDir = process.cwd()) {
|
|
22
|
-
assertValidChatId(id);
|
|
23
|
-
const chatsDir = await getChatsDir(startDir);
|
|
24
|
-
const chatDir = path.join(chatsDir, id);
|
|
25
|
-
if (!existsSync(chatDir)) await fs$1.mkdir(chatDir, { recursive: true });
|
|
26
|
-
const chatFile = path.join(chatDir, "chat.jsonl");
|
|
27
|
-
if (!existsSync(chatFile)) await fs$1.writeFile(chatFile, "");
|
|
28
|
-
}
|
|
29
|
-
async function listChats(startDir = process.cwd()) {
|
|
30
|
-
const chatsDir = await getChatsDir(startDir);
|
|
31
|
-
try {
|
|
32
|
-
return (await fs$1.readdir(chatsDir, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
33
|
-
} catch {
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
async function deleteChat(id, startDir = process.cwd()) {
|
|
38
|
-
assertValidChatId(id);
|
|
39
|
-
const chatsDir = await getChatsDir(startDir);
|
|
40
|
-
const chatDir = path.join(chatsDir, id);
|
|
41
|
-
if (!pathIsInsideDir(chatDir, chatsDir)) throw new Error(`Security Error: Cannot delete chat directory outside of ${chatsDir}`);
|
|
42
|
-
if (existsSync(chatDir)) await fs$1.rm(chatDir, {
|
|
43
|
-
recursive: true,
|
|
44
|
-
force: true
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
async function appendMessage(id, message, startDir = process.cwd()) {
|
|
48
|
-
assertValidChatId(id);
|
|
49
|
-
const chatsDir = await getChatsDir(startDir);
|
|
50
|
-
const chatDir = path.join(chatsDir, id);
|
|
51
|
-
if (!existsSync(chatDir)) await createChat(id, startDir);
|
|
52
|
-
const chatFile = path.join(chatDir, "chat.jsonl");
|
|
53
|
-
await fs$1.appendFile(chatFile, JSON.stringify(message) + "\n");
|
|
54
|
-
}
|
|
55
|
-
async function getMessages(id, limit, startDir = process.cwd()) {
|
|
56
|
-
assertValidChatId(id);
|
|
57
|
-
const chatsDir = await getChatsDir(startDir);
|
|
58
|
-
const chatFile = path.join(chatsDir, id, "chat.jsonl");
|
|
59
|
-
if (!existsSync(chatFile)) throw new Error(`Chat directory or file for '${id}' not found.`);
|
|
60
|
-
const messages = (await fs$1.readFile(chatFile, "utf8")).split("\n").filter((line) => line.trim() !== "").map((line) => JSON.parse(line));
|
|
61
|
-
if (limit !== void 0 && limit > 0) return messages.slice(-limit);
|
|
62
|
-
return messages;
|
|
63
|
-
}
|
|
64
|
-
async function getDefaultChatId(startDir = process.cwd()) {
|
|
65
|
-
const settingsPath = getSettingsPath(startDir);
|
|
66
|
-
if (!existsSync(settingsPath)) return DEFAULT_CHAT_ID;
|
|
67
|
-
try {
|
|
68
|
-
const content = await fs$1.readFile(settingsPath, "utf8");
|
|
69
|
-
return JSON.parse(content).chats?.defaultId || DEFAULT_CHAT_ID;
|
|
70
|
-
} catch {
|
|
71
|
-
return DEFAULT_CHAT_ID;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
async function setDefaultChatId(id, startDir = process.cwd()) {
|
|
75
|
-
assertValidChatId(id);
|
|
76
|
-
const settingsPath = getSettingsPath(startDir);
|
|
77
|
-
let settings = {};
|
|
78
|
-
if (existsSync(settingsPath)) try {
|
|
79
|
-
const content = await fs$1.readFile(settingsPath, "utf8");
|
|
80
|
-
settings = JSON.parse(content);
|
|
81
|
-
} catch {}
|
|
82
|
-
if (!settings.chats) settings.chats = {};
|
|
83
|
-
settings.chats.defaultId = id;
|
|
84
|
-
const clawminiDir = getClawminiDir(startDir);
|
|
85
|
-
if (!existsSync(clawminiDir)) await fs$1.mkdir(clawminiDir, { recursive: true });
|
|
86
|
-
await fs$1.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
//#endregion
|
|
90
|
-
export { getChatsDir as a, isValidChatId as c, deleteChat as i, listChats as l, appendMessage as n, getDefaultChatId as o, createChat as r, getMessages as s, DEFAULT_CHAT_ID as t, setDefaultChatId as u };
|
|
91
|
-
//# sourceMappingURL=chats-CpRQrNHj.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chats-CpRQrNHj.mjs","names":["fs"],"sources":["../src/shared/chats.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { getClawminiDir, getSettingsPath } from './workspace.js';\nimport { pathIsInsideDir } from './utils/fs.js';\n\nexport const DEFAULT_CHAT_ID = 'default';\n\nexport interface UserMessage {\n id: string;\n role: 'user';\n content: string;\n timestamp: string;\n}\n\nexport interface CommandLogMessage {\n id: string;\n messageId: string;\n role: 'log';\n source?: 'router';\n content: string;\n stderr: string;\n timestamp: string;\n command: string;\n cwd: string;\n exitCode: number;\n stdout?: string;\n files?: string[];\n level?: 'default' | 'debug' | 'verbose';\n}\n\nexport type ChatMessage = UserMessage | CommandLogMessage;\n\nexport async function getChatsDir(startDir = process.cwd()): Promise<string> {\n const dir = path.join(getClawminiDir(startDir), 'chats');\n if (!existsSync(dir)) {\n await fs.mkdir(dir, { recursive: true });\n }\n return dir;\n}\n\nexport function isValidChatId(chatId: string): boolean {\n if (!chatId || chatId.length === 0) return false;\n return /^[a-zA-Z0-9_-]+$/.test(chatId);\n}\n\nfunction assertValidChatId(id: string): void {\n if (!isValidChatId(id)) {\n throw new Error(`Invalid chat ID: ${id}`);\n }\n}\n\nexport async function createChat(id: string, startDir = process.cwd()): Promise<void> {\n assertValidChatId(id);\n const chatsDir = await getChatsDir(startDir);\n const chatDir = path.join(chatsDir, id);\n if (!existsSync(chatDir)) {\n await fs.mkdir(chatDir, { recursive: true });\n }\n const chatFile = path.join(chatDir, 'chat.jsonl');\n if (!existsSync(chatFile)) {\n await fs.writeFile(chatFile, '');\n }\n}\n\nexport async function listChats(startDir = process.cwd()): Promise<string[]> {\n const chatsDir = await getChatsDir(startDir);\n try {\n const entries = await fs.readdir(chatsDir, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nexport async function deleteChat(id: string, startDir = process.cwd()): Promise<void> {\n assertValidChatId(id);\n const chatsDir = await getChatsDir(startDir);\n const chatDir = path.join(chatsDir, id);\n\n if (!pathIsInsideDir(chatDir, chatsDir)) {\n throw new Error(`Security Error: Cannot delete chat directory outside of ${chatsDir}`);\n }\n\n if (existsSync(chatDir)) {\n await fs.rm(chatDir, { recursive: true, force: true });\n }\n}\n\nexport async function appendMessage(\n id: string,\n message: ChatMessage,\n startDir = process.cwd()\n): Promise<void> {\n assertValidChatId(id);\n const chatsDir = await getChatsDir(startDir);\n const chatDir = path.join(chatsDir, id);\n if (!existsSync(chatDir)) {\n await createChat(id, startDir);\n }\n const chatFile = path.join(chatDir, 'chat.jsonl');\n await fs.appendFile(chatFile, JSON.stringify(message) + '\\n');\n}\n\nexport async function getMessages(\n id: string,\n limit?: number,\n startDir = process.cwd()\n): Promise<ChatMessage[]> {\n assertValidChatId(id);\n const chatsDir = await getChatsDir(startDir);\n const chatFile = path.join(chatsDir, id, 'chat.jsonl');\n if (!existsSync(chatFile)) {\n throw new Error(`Chat directory or file for '${id}' not found.`);\n }\n const content = await fs.readFile(chatFile, 'utf8');\n const lines = content.split('\\n').filter((line) => line.trim() !== '');\n const messages = lines.map((line) => JSON.parse(line) as ChatMessage);\n\n if (limit !== undefined && limit > 0) {\n return messages.slice(-limit);\n }\n return messages;\n}\n\nexport async function getDefaultChatId(startDir = process.cwd()): Promise<string> {\n const settingsPath = getSettingsPath(startDir);\n if (!existsSync(settingsPath)) return DEFAULT_CHAT_ID;\n\n try {\n const content = await fs.readFile(settingsPath, 'utf8');\n const settings = JSON.parse(content);\n return settings.chats?.defaultId || DEFAULT_CHAT_ID;\n } catch {\n return DEFAULT_CHAT_ID;\n }\n}\n\nexport async function setDefaultChatId(id: string, startDir = process.cwd()): Promise<void> {\n assertValidChatId(id);\n const settingsPath = getSettingsPath(startDir);\n let settings: { chats?: { defaultId?: string; [key: string]: unknown }; [key: string]: unknown } =\n {};\n if (existsSync(settingsPath)) {\n try {\n const content = await fs.readFile(settingsPath, 'utf8');\n settings = JSON.parse(content);\n } catch {\n // Ignore invalid JSON\n }\n }\n\n if (!settings.chats) {\n settings.chats = {};\n }\n settings.chats.defaultId = id;\n\n const clawminiDir = getClawminiDir(startDir);\n if (!existsSync(clawminiDir)) {\n await fs.mkdir(clawminiDir, { recursive: true });\n }\n\n await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));\n}\n"],"mappings":"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"}
|
package/dist/fs-B5wW0oaH.mjs
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-95iHPtFO.mjs";
|
|
2
|
-
import { sep } from "node:path";
|
|
3
|
-
|
|
4
|
-
//#region src/shared/utils/fs.ts
|
|
5
|
-
var fs_exports = /* @__PURE__ */ __exportAll({ pathIsInsideDir: () => pathIsInsideDir });
|
|
6
|
-
function pathIsInsideDir(path, dir, { allowSameDir = false } = {}) {
|
|
7
|
-
const dirWithSep = dir.endsWith(sep) ? dir : dir + sep;
|
|
8
|
-
if (allowSameDir && path === dir) return true;
|
|
9
|
-
return path.startsWith(dirWithSep) && path !== dir;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
//#endregion
|
|
13
|
-
export { pathIsInsideDir as n, fs_exports as t };
|
|
14
|
-
//# sourceMappingURL=fs-B5wW0oaH.mjs.map
|
package/dist/fs-B5wW0oaH.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fs-B5wW0oaH.mjs","names":[],"sources":["../src/shared/utils/fs.ts"],"sourcesContent":["import { sep } from 'node:path';\n\nexport function pathIsInsideDir(\n path: string,\n dir: string,\n { allowSameDir = false }: { allowSameDir?: boolean } = {}\n): boolean {\n const dirWithSep = dir.endsWith(sep) ? dir : dir + sep;\n if (allowSameDir && path === dir) {\n return true;\n }\n return path.startsWith(dirWithSep) && path !== dir;\n}\n"],"mappings":";;;;;AAEA,SAAgB,gBACd,MACA,KACA,EAAE,eAAe,UAAsC,EAAE,EAChD;CACT,MAAM,aAAa,IAAI,SAAS,IAAI,GAAG,MAAM,MAAM;AACnD,KAAI,gBAAgB,SAAS,IAC3B,QAAO;AAET,QAAO,KAAK,WAAW,WAAW,IAAI,SAAS"}
|
package/dist/lite-DBUuHsX0.mjs
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { _ as readSettings, h as readEnvironment, u as getWorkspaceRoot } from "./workspace-BC1ahx4R.mjs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import fs from "node:fs/promises";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
|
|
6
|
-
//#region src/shared/lite.ts
|
|
7
|
-
async function getLiteScriptContent() {
|
|
8
|
-
let liteScriptContent;
|
|
9
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
-
let liteScriptPath = path.resolve(__dirname, "cli/lite.mjs");
|
|
11
|
-
try {
|
|
12
|
-
await fs.access(liteScriptPath);
|
|
13
|
-
} catch {
|
|
14
|
-
try {
|
|
15
|
-
liteScriptPath = path.resolve(__dirname, "lite.mjs");
|
|
16
|
-
await fs.access(liteScriptPath);
|
|
17
|
-
} catch {
|
|
18
|
-
try {
|
|
19
|
-
liteScriptPath = path.resolve(__dirname, "../cli/lite.mjs");
|
|
20
|
-
await fs.access(liteScriptPath);
|
|
21
|
-
} catch {
|
|
22
|
-
liteScriptPath = path.resolve(__dirname, "../../dist/cli/lite.mjs");
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
liteScriptContent = await fs.readFile(liteScriptPath, "utf8");
|
|
27
|
-
if (!liteScriptContent.startsWith("#!")) liteScriptContent = "#!/usr/bin/env node\n" + liteScriptContent;
|
|
28
|
-
return liteScriptContent;
|
|
29
|
-
}
|
|
30
|
-
async function writeLiteScript(outPath) {
|
|
31
|
-
const content = await getLiteScriptContent();
|
|
32
|
-
let finalPath = outPath;
|
|
33
|
-
const isDir = finalPath.endsWith(path.sep) || !(path.extname(finalPath) === ".js" || path.extname(finalPath) === ".mjs" || path.basename(finalPath) === "clawmini-lite");
|
|
34
|
-
try {
|
|
35
|
-
if ((await fs.stat(finalPath)).isDirectory()) finalPath = path.join(finalPath, "clawmini-lite.js");
|
|
36
|
-
} catch {
|
|
37
|
-
if (isDir && !path.extname(finalPath) && !finalPath.endsWith("clawmini-lite") && !finalPath.endsWith("clawmini-lite.js")) {
|
|
38
|
-
await fs.mkdir(finalPath, { recursive: true });
|
|
39
|
-
finalPath = path.join(finalPath, "clawmini-lite.js");
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const dir = path.dirname(finalPath);
|
|
43
|
-
await fs.mkdir(dir, { recursive: true });
|
|
44
|
-
await fs.writeFile(finalPath, content, { mode: 493 });
|
|
45
|
-
return finalPath;
|
|
46
|
-
}
|
|
47
|
-
async function exportLiteToEnvironment(envName, envConfig, affectedDir) {
|
|
48
|
-
if (!envConfig?.exportLiteTo) return false;
|
|
49
|
-
const finalExportPath = path.resolve(affectedDir, envConfig.exportLiteTo);
|
|
50
|
-
if (!finalExportPath.startsWith(affectedDir + path.sep) && finalExportPath !== affectedDir && !finalExportPath.startsWith(affectedDir + "/")) {
|
|
51
|
-
console.warn(`Skipping export for environment '${envName}': exportLiteTo path '${envConfig.exportLiteTo}' escapes the environment target directory '${affectedDir}'`);
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
const writtenPath = await writeLiteScript(finalExportPath);
|
|
56
|
-
console.log(`Successfully exported clawmini-lite to ${writtenPath} (Environment: ${envName})`);
|
|
57
|
-
return true;
|
|
58
|
-
} catch (err) {
|
|
59
|
-
console.error(`Failed to export clawmini-lite to ${finalExportPath} (Environment: ${envName}): ${err instanceof Error ? err.message : String(err)}`);
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
async function exportLiteToAllEnvironments(startDir = process.cwd()) {
|
|
64
|
-
let exportedToEnvironments = false;
|
|
65
|
-
try {
|
|
66
|
-
const workspaceRoot = getWorkspaceRoot(startDir);
|
|
67
|
-
const settings = await readSettings(workspaceRoot);
|
|
68
|
-
if (settings?.environments) for (const [envPath, envName] of Object.entries(settings.environments)) {
|
|
69
|
-
const envConfig = await readEnvironment(envName, workspaceRoot);
|
|
70
|
-
if (envConfig) {
|
|
71
|
-
if (await exportLiteToEnvironment(envName, envConfig, path.resolve(workspaceRoot, envPath))) exportedToEnvironments = true;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
} catch {}
|
|
75
|
-
return exportedToEnvironments;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
//#endregion
|
|
79
|
-
export { writeLiteScript as i, exportLiteToEnvironment as n, getLiteScriptContent as r, exportLiteToAllEnvironments as t };
|
|
80
|
-
//# sourceMappingURL=lite-DBUuHsX0.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lite-DBUuHsX0.mjs","names":[],"sources":["../src/shared/lite.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { readSettings, readEnvironment, getWorkspaceRoot } from './workspace.js';\nimport type { Environment } from './config.js';\n\nexport async function getLiteScriptContent(): Promise<string> {\n let liteScriptContent: string;\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n let liteScriptPath = path.resolve(__dirname, 'cli/lite.mjs'); // if bundled in a shared chunk at dist/\n\n try {\n await fs.access(liteScriptPath);\n } catch {\n try {\n // If bundled in dist/cli or dist/daemon and lite is next to it\n liteScriptPath = path.resolve(__dirname, 'lite.mjs');\n await fs.access(liteScriptPath);\n } catch {\n try {\n // If bundled in dist/daemon, it might be in ../cli/lite.mjs\n liteScriptPath = path.resolve(__dirname, '../cli/lite.mjs');\n await fs.access(liteScriptPath);\n } catch {\n // Fallback for development/testing when running from src/shared\n liteScriptPath = path.resolve(__dirname, '../../dist/cli/lite.mjs');\n }\n }\n }\n\n liteScriptContent = await fs.readFile(liteScriptPath, 'utf8');\n\n // Ensure it has the hashbang (if tsdown stripped it or if missing)\n if (!liteScriptContent.startsWith('#!')) {\n liteScriptContent = '#!/usr/bin/env node\\n' + liteScriptContent;\n }\n return liteScriptContent;\n}\n\nexport async function writeLiteScript(outPath: string): Promise<string> {\n const content = await getLiteScriptContent();\n\n let finalPath = outPath;\n const isDir =\n finalPath.endsWith(path.sep) ||\n !(\n path.extname(finalPath) === '.js' ||\n path.extname(finalPath) === '.mjs' ||\n path.basename(finalPath) === 'clawmini-lite'\n );\n\n try {\n const stat = await fs.stat(finalPath);\n if (stat.isDirectory()) {\n finalPath = path.join(finalPath, 'clawmini-lite.js');\n }\n } catch {\n if (\n isDir &&\n !path.extname(finalPath) &&\n !finalPath.endsWith('clawmini-lite') &&\n !finalPath.endsWith('clawmini-lite.js')\n ) {\n await fs.mkdir(finalPath, { recursive: true });\n finalPath = path.join(finalPath, 'clawmini-lite.js');\n }\n }\n\n const dir = path.dirname(finalPath);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(finalPath, content, { mode: 0o755 });\n return finalPath;\n}\n\nexport async function exportLiteToEnvironment(\n envName: string,\n envConfig: Environment,\n affectedDir: string\n): Promise<boolean> {\n if (!envConfig?.exportLiteTo) return false;\n\n const finalExportPath = path.resolve(affectedDir, envConfig.exportLiteTo);\n\n if (\n !finalExportPath.startsWith(affectedDir + path.sep) &&\n finalExportPath !== affectedDir &&\n !finalExportPath.startsWith(affectedDir + '/')\n ) {\n console.warn(\n `Skipping export for environment '${envName}': exportLiteTo path '${envConfig.exportLiteTo}' escapes the environment target directory '${affectedDir}'`\n );\n return false;\n }\n\n try {\n const writtenPath = await writeLiteScript(finalExportPath);\n console.log(`Successfully exported clawmini-lite to ${writtenPath} (Environment: ${envName})`);\n return true;\n } catch (err) {\n console.error(\n `Failed to export clawmini-lite to ${finalExportPath} (Environment: ${envName}): ${err instanceof Error ? err.message : String(err)}`\n );\n return false;\n }\n}\n\nexport async function exportLiteToAllEnvironments(startDir = process.cwd()): Promise<boolean> {\n let exportedToEnvironments = false;\n try {\n const workspaceRoot = getWorkspaceRoot(startDir);\n const settings = await readSettings(workspaceRoot);\n if (settings?.environments) {\n for (const [envPath, envName] of Object.entries(settings.environments)) {\n const envConfig = await readEnvironment(envName, workspaceRoot);\n if (envConfig) {\n const affectedDir = path.resolve(workspaceRoot, envPath);\n const exported = await exportLiteToEnvironment(envName, envConfig, affectedDir);\n if (exported) {\n exportedToEnvironments = true;\n }\n }\n }\n }\n } catch {\n // Ignore settings read errors\n }\n return exportedToEnvironments;\n}\n"],"mappings":";;;;;;AAMA,eAAsB,uBAAwC;CAC5D,IAAI;CACJ,MAAM,YAAY,KAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;CAE9D,IAAI,iBAAiB,KAAK,QAAQ,WAAW,eAAe;AAE5D,KAAI;AACF,QAAM,GAAG,OAAO,eAAe;SACzB;AACN,MAAI;AAEF,oBAAiB,KAAK,QAAQ,WAAW,WAAW;AACpD,SAAM,GAAG,OAAO,eAAe;UACzB;AACN,OAAI;AAEF,qBAAiB,KAAK,QAAQ,WAAW,kBAAkB;AAC3D,UAAM,GAAG,OAAO,eAAe;WACzB;AAEN,qBAAiB,KAAK,QAAQ,WAAW,0BAA0B;;;;AAKzE,qBAAoB,MAAM,GAAG,SAAS,gBAAgB,OAAO;AAG7D,KAAI,CAAC,kBAAkB,WAAW,KAAK,CACrC,qBAAoB,0BAA0B;AAEhD,QAAO;;AAGT,eAAsB,gBAAgB,SAAkC;CACtE,MAAM,UAAU,MAAM,sBAAsB;CAE5C,IAAI,YAAY;CAChB,MAAM,QACJ,UAAU,SAAS,KAAK,IAAI,IAC5B,EACE,KAAK,QAAQ,UAAU,KAAK,SAC5B,KAAK,QAAQ,UAAU,KAAK,UAC5B,KAAK,SAAS,UAAU,KAAK;AAGjC,KAAI;AAEF,OADa,MAAM,GAAG,KAAK,UAAU,EAC5B,aAAa,CACpB,aAAY,KAAK,KAAK,WAAW,mBAAmB;SAEhD;AACN,MACE,SACA,CAAC,KAAK,QAAQ,UAAU,IACxB,CAAC,UAAU,SAAS,gBAAgB,IACpC,CAAC,UAAU,SAAS,mBAAmB,EACvC;AACA,SAAM,GAAG,MAAM,WAAW,EAAE,WAAW,MAAM,CAAC;AAC9C,eAAY,KAAK,KAAK,WAAW,mBAAmB;;;CAIxD,MAAM,MAAM,KAAK,QAAQ,UAAU;AACnC,OAAM,GAAG,MAAM,KAAK,EAAE,WAAW,MAAM,CAAC;AACxC,OAAM,GAAG,UAAU,WAAW,SAAS,EAAE,MAAM,KAAO,CAAC;AACvD,QAAO;;AAGT,eAAsB,wBACpB,SACA,WACA,aACkB;AAClB,KAAI,CAAC,WAAW,aAAc,QAAO;CAErC,MAAM,kBAAkB,KAAK,QAAQ,aAAa,UAAU,aAAa;AAEzE,KACE,CAAC,gBAAgB,WAAW,cAAc,KAAK,IAAI,IACnD,oBAAoB,eACpB,CAAC,gBAAgB,WAAW,cAAc,IAAI,EAC9C;AACA,UAAQ,KACN,oCAAoC,QAAQ,wBAAwB,UAAU,aAAa,8CAA8C,YAAY,GACtJ;AACD,SAAO;;AAGT,KAAI;EACF,MAAM,cAAc,MAAM,gBAAgB,gBAAgB;AAC1D,UAAQ,IAAI,0CAA0C,YAAY,iBAAiB,QAAQ,GAAG;AAC9F,SAAO;UACA,KAAK;AACZ,UAAQ,MACN,qCAAqC,gBAAgB,iBAAiB,QAAQ,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACpI;AACD,SAAO;;;AAIX,eAAsB,4BAA4B,WAAW,QAAQ,KAAK,EAAoB;CAC5F,IAAI,yBAAyB;AAC7B,KAAI;EACF,MAAM,gBAAgB,iBAAiB,SAAS;EAChD,MAAM,WAAW,MAAM,aAAa,cAAc;AAClD,MAAI,UAAU,aACZ,MAAK,MAAM,CAAC,SAAS,YAAY,OAAO,QAAQ,SAAS,aAAa,EAAE;GACtE,MAAM,YAAY,MAAM,gBAAgB,SAAS,cAAc;AAC/D,OAAI,WAGF;QADiB,MAAM,wBAAwB,SAAS,WADpC,KAAK,QAAQ,eAAe,QAAQ,CACuB,CAE7E,0BAAyB;;;SAK3B;AAGR,QAAO"}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-95iHPtFO.mjs";
|
|
2
|
-
import { n as pathIsInsideDir } from "./fs-B5wW0oaH.mjs";
|
|
3
|
-
import { constants } from "node:fs";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { spawn } from "node:child_process";
|
|
6
|
-
import fs$1 from "node:fs/promises";
|
|
7
|
-
import { randomBytes } from "node:crypto";
|
|
8
|
-
|
|
9
|
-
//#region src/daemon/policy-utils.ts
|
|
10
|
-
var policy_utils_exports = /* @__PURE__ */ __exportAll({
|
|
11
|
-
MAX_SNAPSHOT_SIZE: () => MAX_SNAPSHOT_SIZE,
|
|
12
|
-
createSnapshot: () => createSnapshot,
|
|
13
|
-
executeSafe: () => executeSafe,
|
|
14
|
-
generateRequestPreview: () => generateRequestPreview,
|
|
15
|
-
interpolateArgs: () => interpolateArgs
|
|
16
|
-
});
|
|
17
|
-
const MAX_SNAPSHOT_SIZE = 5 * 1024 * 1024;
|
|
18
|
-
async function createSnapshot(requestedPath, agentDir, snapshotDir) {
|
|
19
|
-
let realAgentDir;
|
|
20
|
-
try {
|
|
21
|
-
realAgentDir = await fs$1.realpath(agentDir);
|
|
22
|
-
} catch (err) {
|
|
23
|
-
throw new Error(`Agent directory not found or cannot be resolved: ${agentDir}`, { cause: err });
|
|
24
|
-
}
|
|
25
|
-
const resolvedRequestedPath = path.resolve(realAgentDir, requestedPath);
|
|
26
|
-
if (!pathIsInsideDir(resolvedRequestedPath, realAgentDir, { allowSameDir: true })) throw new Error(`Security Error: Path resolves outside the allowed agent directory: ${resolvedRequestedPath}`);
|
|
27
|
-
let stat;
|
|
28
|
-
try {
|
|
29
|
-
stat = await fs$1.lstat(resolvedRequestedPath);
|
|
30
|
-
} catch (err) {
|
|
31
|
-
throw new Error(`File not found or cannot be accessed: ${requestedPath}`, { cause: err });
|
|
32
|
-
}
|
|
33
|
-
if (stat.isSymbolicLink()) throw new Error(`Security Error: Symlinks are not allowed: ${requestedPath}`);
|
|
34
|
-
if (!stat.isFile()) throw new Error(`Requested path is not a file: ${requestedPath}`);
|
|
35
|
-
if (stat.size > MAX_SNAPSHOT_SIZE) throw new Error(`File exceeds maximum snapshot size of 5MB: ${requestedPath}`);
|
|
36
|
-
const ext = path.extname(resolvedRequestedPath);
|
|
37
|
-
const base = path.basename(resolvedRequestedPath, ext);
|
|
38
|
-
await fs$1.mkdir(snapshotDir, { recursive: true });
|
|
39
|
-
let snapshotPath;
|
|
40
|
-
while (true) {
|
|
41
|
-
const snapshotFileName = `${base}_${randomBytes(8).toString("hex")}${ext}`;
|
|
42
|
-
snapshotPath = path.join(snapshotDir, snapshotFileName);
|
|
43
|
-
try {
|
|
44
|
-
await fs$1.copyFile(resolvedRequestedPath, snapshotPath, constants.COPYFILE_EXCL);
|
|
45
|
-
break;
|
|
46
|
-
} catch (err) {
|
|
47
|
-
if (err instanceof Error && "code" in err && err.code === "EEXIST") continue;
|
|
48
|
-
throw err;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return snapshotPath;
|
|
52
|
-
}
|
|
53
|
-
function interpolateArgs(args, snapshots) {
|
|
54
|
-
return args.map((arg) => {
|
|
55
|
-
let interpolated = arg;
|
|
56
|
-
for (const [key, snapshotPath] of Object.entries(snapshots)) {
|
|
57
|
-
const variable = `{{${key}}}`;
|
|
58
|
-
interpolated = interpolated.replaceAll(variable, snapshotPath);
|
|
59
|
-
}
|
|
60
|
-
return interpolated;
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
function executeSafe(command, args, options) {
|
|
64
|
-
return new Promise((resolve) => {
|
|
65
|
-
const p = spawn(command, args, {
|
|
66
|
-
shell: false,
|
|
67
|
-
cwd: options?.cwd,
|
|
68
|
-
env: options?.env
|
|
69
|
-
});
|
|
70
|
-
let stdout = "";
|
|
71
|
-
let stderr = "";
|
|
72
|
-
if (p.stdout) p.stdout.on("data", (data) => {
|
|
73
|
-
stdout += data.toString();
|
|
74
|
-
});
|
|
75
|
-
if (p.stderr) p.stderr.on("data", (data) => {
|
|
76
|
-
stderr += data.toString();
|
|
77
|
-
});
|
|
78
|
-
p.on("close", (code) => {
|
|
79
|
-
resolve({
|
|
80
|
-
stdout,
|
|
81
|
-
stderr,
|
|
82
|
-
exitCode: code ?? 1
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
p.on("error", (err) => {
|
|
86
|
-
resolve({
|
|
87
|
-
stdout: "",
|
|
88
|
-
stderr: err.toString(),
|
|
89
|
-
exitCode: 1
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
async function generateRequestPreview(request) {
|
|
95
|
-
let previewContent = `Sandbox Policy Request: ${request.commandName}\n`;
|
|
96
|
-
previewContent += `ID: ${request.id}\n`;
|
|
97
|
-
if (request.args.length > 0) previewContent += `Args: ${request.args.join(" ")}\n`;
|
|
98
|
-
for (const [name, snapPath] of Object.entries(request.fileMappings)) {
|
|
99
|
-
previewContent += `File [${name}]:\n`;
|
|
100
|
-
try {
|
|
101
|
-
let content = await fs$1.readFile(snapPath, "utf8");
|
|
102
|
-
if (content.length > 500) content = content.substring(0, 500) + "\n... (truncated)\n";
|
|
103
|
-
previewContent += content;
|
|
104
|
-
} catch (e) {
|
|
105
|
-
previewContent += `<Error reading file: ${e.message}>\n`;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
previewContent += `\nUse /approve ${request.id} or /reject ${request.id} [reason]`;
|
|
109
|
-
return previewContent;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
//#endregion
|
|
113
|
-
export { policy_utils_exports as i, executeSafe as n, interpolateArgs as r, createSnapshot as t };
|
|
114
|
-
//# sourceMappingURL=policy-utils-BvfOK6Ih.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"policy-utils-BvfOK6Ih.mjs","names":["fs"],"sources":["../src/daemon/policy-utils.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport { constants } from 'node:fs';\nimport path from 'node:path';\nimport { randomBytes } from 'node:crypto';\nimport { spawn } from 'node:child_process';\nimport { pathIsInsideDir } from '../shared/utils/fs.js';\nimport type { PolicyRequest } from '../shared/policies.js';\n\nexport const MAX_SNAPSHOT_SIZE = 5 * 1024 * 1024;\n\nexport async function createSnapshot(\n requestedPath: string,\n agentDir: string,\n snapshotDir: string\n): Promise<string> {\n let realAgentDir: string;\n try {\n realAgentDir = await fs.realpath(agentDir);\n } catch (err) {\n throw new Error(`Agent directory not found or cannot be resolved: ${agentDir}`, { cause: err });\n }\n\n const resolvedRequestedPath = path.resolve(realAgentDir, requestedPath);\n\n // Verify it is inside the allowed agent directory\n if (!pathIsInsideDir(resolvedRequestedPath, realAgentDir, { allowSameDir: true })) {\n throw new Error(\n `Security Error: Path resolves outside the allowed agent directory: ${resolvedRequestedPath}`\n );\n }\n\n // Lstat prevents TOCTOU attacks by not following symlinks\n let stat;\n try {\n stat = await fs.lstat(resolvedRequestedPath);\n } catch (err) {\n throw new Error(`File not found or cannot be accessed: ${requestedPath}`, { cause: err });\n }\n\n if (stat.isSymbolicLink()) {\n throw new Error(`Security Error: Symlinks are not allowed: ${requestedPath}`);\n }\n\n if (!stat.isFile()) {\n throw new Error(`Requested path is not a file: ${requestedPath}`);\n }\n if (stat.size > MAX_SNAPSHOT_SIZE) {\n throw new Error(`File exceeds maximum snapshot size of 5MB: ${requestedPath}`);\n }\n\n // Generate unique filename for the snapshot\n const ext = path.extname(resolvedRequestedPath);\n const base = path.basename(resolvedRequestedPath, ext);\n\n await fs.mkdir(snapshotDir, { recursive: true });\n\n let snapshotPath: string;\n while (true) {\n const uniqueId = randomBytes(8).toString('hex');\n const snapshotFileName = `${base}_${uniqueId}${ext}`;\n snapshotPath = path.join(snapshotDir, snapshotFileName);\n\n try {\n await fs.copyFile(resolvedRequestedPath, snapshotPath, constants.COPYFILE_EXCL);\n break;\n } catch (err: unknown) {\n if (\n err instanceof Error &&\n 'code' in err &&\n (err as Error & { code?: string }).code === 'EEXIST'\n ) {\n continue;\n }\n throw err;\n }\n }\n\n return snapshotPath;\n}\n\nexport function interpolateArgs(args: string[], snapshots: Record<string, string>): string[] {\n return args.map((arg) => {\n let interpolated = arg;\n for (const [key, snapshotPath] of Object.entries(snapshots)) {\n const variable = `{{${key}}}`;\n interpolated = interpolated.replaceAll(variable, snapshotPath);\n }\n return interpolated;\n });\n}\n\nexport function executeSafe(\n command: string,\n args: string[],\n options?: { cwd?: string; env?: NodeJS.ProcessEnv }\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n return new Promise((resolve) => {\n // Safe execution: shell is strictly false to prevent command injection\n const p = spawn(command, args, {\n shell: false,\n cwd: options?.cwd,\n env: options?.env,\n });\n\n let stdout = '';\n let stderr = '';\n\n if (p.stdout) {\n p.stdout.on('data', (data) => {\n stdout += data.toString();\n });\n }\n\n if (p.stderr) {\n p.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n }\n\n p.on('close', (code) => {\n resolve({ stdout, stderr, exitCode: code ?? 1 });\n });\n\n p.on('error', (err) => {\n resolve({ stdout: '', stderr: err.toString(), exitCode: 1 });\n });\n });\n}\n\nexport async function generateRequestPreview(request: PolicyRequest): Promise<string> {\n let previewContent = `Sandbox Policy Request: ${request.commandName}\\n`;\n previewContent += `ID: ${request.id}\\n`;\n if (request.args.length > 0) {\n previewContent += `Args: ${request.args.join(' ')}\\n`;\n }\n\n for (const [name, snapPath] of Object.entries(request.fileMappings)) {\n previewContent += `File [${name}]:\\n`;\n try {\n let content = await fs.readFile(snapPath, 'utf8');\n if (content.length > 500) {\n content = content.substring(0, 500) + '\\n... (truncated)\\n';\n }\n previewContent += content;\n } catch (e: unknown) {\n previewContent += `<Error reading file: ${(e as Error).message}>\\n`;\n }\n }\n\n previewContent += `\\nUse /approve ${request.id} or /reject ${request.id} [reason]`;\n return previewContent;\n}\n"],"mappings":"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"}
|