clawmini 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter-discord/index.mjs +1 -1
- package/dist/adapter-google-chat/index.mjs +1 -1
- package/dist/cli/index.mjs +2 -2
- package/dist/cli/lite.mjs +5 -3
- package/dist/cli/lite.mjs.map +1 -1
- package/dist/cli/propose-policy.mjs +2 -0
- package/dist/cli/propose-policy.mjs.map +1 -1
- package/dist/daemon/index.mjs +23 -8
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/{lite-BbCFgEjn.mjs → lite-CBxOT1y5.mjs} +2 -2
- package/dist/{lite-BbCFgEjn.mjs.map → lite-CBxOT1y5.mjs.map} +1 -1
- package/{web/.svelte-kit/output/client/_app/immutable/chunks/uD5YsQE1.js → dist/web/_app/immutable/chunks/9nfWZDAH.js} +1 -1
- package/{web/.svelte-kit/output/client/_app/immutable/chunks/ByezTNKv.js → dist/web/_app/immutable/chunks/zsjBVtme.js} +1 -1
- package/dist/web/_app/immutable/entry/{app.Dkba_ZYl.js → app.CDP4hzOl.js} +2 -2
- package/dist/web/_app/immutable/entry/start.k4GcE1y3.js +1 -0
- package/dist/web/_app/immutable/nodes/{0.CFkkEWLe.js → 0.BK2mQuoD.js} +1 -1
- package/dist/web/_app/immutable/nodes/{1.BVylC0w0.js → 1.DsQuFekn.js} +1 -1
- package/dist/web/_app/immutable/nodes/{3.DEhhZBsS.js → 3.BZVFNxO-.js} +1 -1
- package/dist/web/_app/immutable/nodes/{4.C_OhFIXf.js → 4.L2HPGZB4.js} +1 -1
- package/dist/web/_app/immutable/nodes/{5.Bj0bsDBW.js → 5.B4lC9vS4.js} +1 -1
- package/dist/web/_app/version.json +1 -1
- package/dist/web/index.html +6 -6
- package/dist/{workspace-CEdb2nPR.mjs → workspace-BJmJBfKi.mjs} +3 -1
- package/dist/workspace-BJmJBfKi.mjs.map +1 -0
- package/docs/23_custom_token_env/development_log.md +31 -0
- package/docs/23_custom_token_env/notes.md +16 -0
- package/docs/23_custom_token_env/prd.md +42 -0
- package/docs/23_custom_token_env/questions.md +8 -0
- package/docs/23_custom_token_env/tickets.md +54 -0
- package/napkin.md +1 -0
- package/package.json +1 -1
- package/src/adapter-google-chat/client.test.ts +1 -1
- package/src/cli/e2e/daemon.test.ts +103 -0
- package/src/cli/e2e/messages.test.ts +5 -2
- package/src/cli/lite.ts +10 -3
- package/src/daemon/agent/agent-session.ts +20 -4
- package/src/daemon/utils/spawn.ts +2 -1
- package/src/shared/config.ts +2 -0
- package/templates/environments/macos/sandbox.sb +8 -0
- package/templates/environments/macos-proxy/allowlist.txt +4 -0
- package/templates/environments/macos-proxy/proxy.mjs +25 -20
- package/templates/environments/macos-proxy/sandbox.sb +8 -0
- package/templates/gemini/.gemini/settings.json +6 -1
- package/templates/gemini/settings.json +22 -21
- package/templates/gemini-claw/.gemini/settings.json +6 -1
- package/templates/gemini-claw/GEMINI.md +1 -1
- package/templates/gemini-claw/settings.json +26 -25
- package/web/.svelte-kit/generated/server/internal.js +1 -1
- package/web/.svelte-kit/output/client/.vite/manifest.json +26 -26
- package/{dist/web/_app/immutable/chunks/uD5YsQE1.js → web/.svelte-kit/output/client/_app/immutable/chunks/9nfWZDAH.js} +1 -1
- package/{dist/web/_app/immutable/chunks/ByezTNKv.js → web/.svelte-kit/output/client/_app/immutable/chunks/zsjBVtme.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/entry/{app.Dkba_ZYl.js → app.CDP4hzOl.js} +2 -2
- package/web/.svelte-kit/output/client/_app/immutable/entry/start.k4GcE1y3.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{0.CFkkEWLe.js → 0.BK2mQuoD.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{1.BVylC0w0.js → 1.DsQuFekn.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{3.DEhhZBsS.js → 3.BZVFNxO-.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{4.C_OhFIXf.js → 4.L2HPGZB4.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{5.Bj0bsDBW.js → 5.B4lC9vS4.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/web/_app/immutable/entry/start.B_seWfvF.js +0 -1
- package/dist/workspace-CEdb2nPR.mjs.map +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/entry/start.B_seWfvF.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{b as Kt,c as at,a as w,f as L,t as Jt}from"../chunks/BmRlVmv6.js";import{a as Ar}from"../chunks/DhD271EB.js";import{h as Rt,i as Hn,M as ft,t as ue,d as Bn,L as Rr,aO as Lr,k as Gn,S as Ir,aD as Cr,aK as Dr,aE as Or,J as Mr,aP as Nr,aQ as Pr,f as Ce,p as Ft,a as Ut,F as zr,r as y,w as u,G as un,c as S,I as Ne,l as Wn,n as st,D as O,aN as en,s as q,C as qe}from"../chunks/CME08kGM.js";import{s as ke,d as $r,e as qn,a as tn}from"../chunks/DMtIqaiV.js";import{l as mn,s as kn,p as nn,b as or,r as Fr,i as J}from"../chunks/B6YN0Nuq.js";import{I as xn,s as bn,a as Ur,d as Hr,c as Br,e as jn,B as Lt,h as je}from"../chunks/CK9JZLaG.js";import{i as It}from"../chunks/uD5YsQE1.js";import{a as Ze}from"../chunks/DsIToJCP.js";import"../chunks/Ck3rYNON.js";function Gr(s,e,n=!1,r=!1,t=!1,o=!1){var i=s,p="";if(n){var c=s;Rt&&(i=Hn(ft(c)))}ue(()=>{var g=Rr;if(p===(p=e()??"")){Rt&&Bn();return}if(n&&!Rt){g.nodes=null,c.innerHTML=p,p!==""&&Kt(ft(c),c.lastChild);return}if(g.nodes!==null&&(Lr(g.nodes.start,g.nodes.end),g.nodes=null),p!==""){if(Rt){Gn.data;for(var f=Bn(),b=f;f!==null&&(f.nodeType!==Ir||f.data!=="");)b=f,f=Cr(f);if(f===null)throw Dr(),Or;Kt(Gn,b),i=Hn(f);return}var v=r?Nr:t?Pr:void 0,C=Mr(r?"svg":t?"math":"template",v);C.innerHTML=p;var E=r||t?C:C.content;if(Kt(ft(E),E.lastChild),r||t)for(;ft(E);)i.before(ft(E));else i.before(E)}})}function Wr(s,e){const n=mn(e,["children","$$slots","$$events","$$legacy"]);const r=[["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"}]];xn(s,kn({name:"circle-alert"},()=>n,{get iconNode(){return r},children:(t,o)=>{var i=at(),p=Ce(i);bn(p,e,"default",{}),w(t,i)},$$slots:{default:!0}}))}function qr(s,e){const n=mn(e,["children","$$slots","$$events","$$legacy"]);const r=[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 6v6l4 2"}]];xn(s,kn({name:"clock"},()=>n,{get iconNode(){return r},children:(t,o)=>{var i=at(),p=Ce(i);bn(p,e,"default",{}),w(t,i)},$$slots:{default:!0}}))}function jr(s,e){const n=mn(e,["children","$$slots","$$events","$$legacy"]);const r=[["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"}]];xn(s,kn({name:"send"},()=>n,{get iconNode(){return r},children:(t,o)=>{var i=at(),p=Ce(i);bn(p,e,"default",{}),w(t,i)},$$slots:{default:!0}}))}const Zr=async({params:s,fetch:e,depends:n})=>{const{id:r}=s;n(`app:chat:${r}`);try{const t=await e(`/api/chats/${r}`);if(t.ok){const o=await t.json();return{id:r,messages:o}}}catch(t){console.error(t)}return{id:r,messages:[]}},Za=Object.freeze(Object.defineProperty({__proto__:null,load:Zr},Symbol.toStringTag,{value:"Module"}));var Yr=L("<textarea></textarea>");function Xr(s,e){Ft(e,!0);let n=nn(e,"ref",15,null),r=nn(e,"value",15),t=nn(e,"data-slot",3,"textarea"),o=Fr(e,["$$slots","$$events","$$legacy","ref","value","class","data-slot"]);var i=Yr();zr(i),Ur(i,p=>({"data-slot":t(),class:p,...o}),[()=>Br("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",e.class)]),or(i,p=>n(p),()=>n()),Hr(i,r),w(s,i),Ut()}function vn(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var Ve=vn();function lr(s){Ve=s}var Ye={exec:()=>null};function A(s,e=""){let n=typeof s=="string"?s:s.source,r={replace:(t,o)=>{let i=typeof o=="string"?o:o.source;return i=i.replace(pe.caret,"$1"),n=n.replace(t,i),r},getRegex:()=>new RegExp(n,e)};return r}var Vr=(()=>{try{return!!new RegExp("(?<=1)(?<!1)")}catch{return!1}})(),pe={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:s=>new RegExp(`^( {0,3}${s})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}#`),htmlBeginRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}<(?:[a-z].*>|!--)`,"i"),blockquoteBeginRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}>`)},Qr=/^(?:[ \t]*(?:\n|$))+/,Kr=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,Jr=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,yt=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,es=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,_n=/ {0,3}(?:[*+-]|\d{1,9}[.)])/,cr=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,ur=A(cr).replace(/bull/g,_n).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),ts=A(cr).replace(/bull/g,_n).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),wn=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,ns=/^[^\n]+/,Tn=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,rs=A(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",Tn).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),ss=A(/^(bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,_n).getRegex(),Ht="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",yn=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,as=A("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",yn).replace("tag",Ht).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),pr=A(wn).replace("hr",yt).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",Ht).getRegex(),is=A(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",pr).getRegex(),Sn={blockquote:is,code:Kr,def:rs,fences:Jr,heading:es,hr:yt,html:as,lheading:ur,list:ss,newline:Qr,paragraph:pr,table:Ye,text:ns},Zn=A("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",yt).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",Ht).getRegex(),os={...Sn,lheading:ts,table:Zn,paragraph:A(wn).replace("hr",yt).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",Zn).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",Ht).getRegex()},ls={...Sn,html:A(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",yn).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:Ye,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:A(wn).replace("hr",yt).replace("heading",` *#{1,6} *[^
|
|
1
|
+
import{b as Kt,c as at,a as w,f as L,t as Jt}from"../chunks/BmRlVmv6.js";import{a as Ar}from"../chunks/DhD271EB.js";import{h as Rt,i as Hn,M as ft,t as ue,d as Bn,L as Rr,aO as Lr,k as Gn,S as Ir,aD as Cr,aK as Dr,aE as Or,J as Mr,aP as Nr,aQ as Pr,f as Ce,p as Ft,a as Ut,F as zr,r as y,w as u,G as un,c as S,I as Ne,l as Wn,n as st,D as O,aN as en,s as q,C as qe}from"../chunks/CME08kGM.js";import{s as ke,d as $r,e as qn,a as tn}from"../chunks/DMtIqaiV.js";import{l as mn,s as kn,p as nn,b as or,r as Fr,i as J}from"../chunks/B6YN0Nuq.js";import{I as xn,s as bn,a as Ur,d as Hr,c as Br,e as jn,B as Lt,h as je}from"../chunks/CK9JZLaG.js";import{i as It}from"../chunks/9nfWZDAH.js";import{a as Ze}from"../chunks/DsIToJCP.js";import"../chunks/Ck3rYNON.js";function Gr(s,e,n=!1,r=!1,t=!1,o=!1){var i=s,p="";if(n){var c=s;Rt&&(i=Hn(ft(c)))}ue(()=>{var g=Rr;if(p===(p=e()??"")){Rt&&Bn();return}if(n&&!Rt){g.nodes=null,c.innerHTML=p,p!==""&&Kt(ft(c),c.lastChild);return}if(g.nodes!==null&&(Lr(g.nodes.start,g.nodes.end),g.nodes=null),p!==""){if(Rt){Gn.data;for(var f=Bn(),b=f;f!==null&&(f.nodeType!==Ir||f.data!=="");)b=f,f=Cr(f);if(f===null)throw Dr(),Or;Kt(Gn,b),i=Hn(f);return}var v=r?Nr:t?Pr:void 0,C=Mr(r?"svg":t?"math":"template",v);C.innerHTML=p;var E=r||t?C:C.content;if(Kt(ft(E),E.lastChild),r||t)for(;ft(E);)i.before(ft(E));else i.before(E)}})}function Wr(s,e){const n=mn(e,["children","$$slots","$$events","$$legacy"]);const r=[["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"}]];xn(s,kn({name:"circle-alert"},()=>n,{get iconNode(){return r},children:(t,o)=>{var i=at(),p=Ce(i);bn(p,e,"default",{}),w(t,i)},$$slots:{default:!0}}))}function qr(s,e){const n=mn(e,["children","$$slots","$$events","$$legacy"]);const r=[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 6v6l4 2"}]];xn(s,kn({name:"clock"},()=>n,{get iconNode(){return r},children:(t,o)=>{var i=at(),p=Ce(i);bn(p,e,"default",{}),w(t,i)},$$slots:{default:!0}}))}function jr(s,e){const n=mn(e,["children","$$slots","$$events","$$legacy"]);const r=[["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"}]];xn(s,kn({name:"send"},()=>n,{get iconNode(){return r},children:(t,o)=>{var i=at(),p=Ce(i);bn(p,e,"default",{}),w(t,i)},$$slots:{default:!0}}))}const Zr=async({params:s,fetch:e,depends:n})=>{const{id:r}=s;n(`app:chat:${r}`);try{const t=await e(`/api/chats/${r}`);if(t.ok){const o=await t.json();return{id:r,messages:o}}}catch(t){console.error(t)}return{id:r,messages:[]}},Za=Object.freeze(Object.defineProperty({__proto__:null,load:Zr},Symbol.toStringTag,{value:"Module"}));var Yr=L("<textarea></textarea>");function Xr(s,e){Ft(e,!0);let n=nn(e,"ref",15,null),r=nn(e,"value",15),t=nn(e,"data-slot",3,"textarea"),o=Fr(e,["$$slots","$$events","$$legacy","ref","value","class","data-slot"]);var i=Yr();zr(i),Ur(i,p=>({"data-slot":t(),class:p,...o}),[()=>Br("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",e.class)]),or(i,p=>n(p),()=>n()),Hr(i,r),w(s,i),Ut()}function vn(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var Ve=vn();function lr(s){Ve=s}var Ye={exec:()=>null};function A(s,e=""){let n=typeof s=="string"?s:s.source,r={replace:(t,o)=>{let i=typeof o=="string"?o:o.source;return i=i.replace(pe.caret,"$1"),n=n.replace(t,i),r},getRegex:()=>new RegExp(n,e)};return r}var Vr=(()=>{try{return!!new RegExp("(?<=1)(?<!1)")}catch{return!1}})(),pe={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:s=>new RegExp(`^( {0,3}${s})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}#`),htmlBeginRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}<(?:[a-z].*>|!--)`,"i"),blockquoteBeginRegex:s=>new RegExp(`^ {0,${Math.min(3,s-1)}}>`)},Qr=/^(?:[ \t]*(?:\n|$))+/,Kr=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,Jr=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,yt=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,es=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,_n=/ {0,3}(?:[*+-]|\d{1,9}[.)])/,cr=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,ur=A(cr).replace(/bull/g,_n).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),ts=A(cr).replace(/bull/g,_n).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),wn=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,ns=/^[^\n]+/,Tn=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,rs=A(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",Tn).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),ss=A(/^(bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,_n).getRegex(),Ht="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",yn=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,as=A("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",yn).replace("tag",Ht).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),pr=A(wn).replace("hr",yt).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",Ht).getRegex(),is=A(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",pr).getRegex(),Sn={blockquote:is,code:Kr,def:rs,fences:Jr,heading:es,hr:yt,html:as,lheading:ur,list:ss,newline:Qr,paragraph:pr,table:Ye,text:ns},Zn=A("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",yt).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",Ht).getRegex(),os={...Sn,lheading:ts,table:Zn,paragraph:A(wn).replace("hr",yt).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",Zn).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",Ht).getRegex()},ls={...Sn,html:A(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",yn).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:Ye,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:A(wn).replace("hr",yt).replace("heading",` *#{1,6} *[^
|
|
2
2
|
]`).replace("lheading",ur).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},cs=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,us=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,dr=/^( {2,}|\\)\n(?!\s*$)/,ps=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,it=/[\p{P}\p{S}]/u,Bt=/[\s\p{P}\p{S}]/u,En=/[^\s\p{P}\p{S}]/u,ds=A(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,Bt).getRegex(),hr=/(?!~)[\p{P}\p{S}]/u,hs=/(?!~)[\s\p{P}\p{S}]/u,fs=/(?:[^\s\p{P}\p{S}]|~)/u,gs=A(/link|precode-code|html/,"g").replace("link",/\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-",Vr?"(?<!`)()":"(^^|[^`])").replace("code",/(?<b>`+)[^`]+\k<b>(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),fr=/^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/,ms=A(fr,"u").replace(/punct/g,it).getRegex(),ks=A(fr,"u").replace(/punct/g,hr).getRegex(),gr="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",xs=A(gr,"gu").replace(/notPunctSpace/g,En).replace(/punctSpace/g,Bt).replace(/punct/g,it).getRegex(),bs=A(gr,"gu").replace(/notPunctSpace/g,fs).replace(/punctSpace/g,hs).replace(/punct/g,hr).getRegex(),vs=A("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,En).replace(/punctSpace/g,Bt).replace(/punct/g,it).getRegex(),_s=A(/^~~?(?:((?!~)punct)|[^\s~])/,"u").replace(/punct/g,it).getRegex(),ws="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",Ts=A(ws,"gu").replace(/notPunctSpace/g,En).replace(/punctSpace/g,Bt).replace(/punct/g,it).getRegex(),ys=A(/\\(punct)/,"gu").replace(/punct/g,it).getRegex(),Ss=A(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Es=A(yn).replace("(?:-->|$)","-->").getRegex(),As=A("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment",Es).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),Pt=/(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/,Rs=A(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label",Pt).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),mr=A(/^!?\[(label)\]\[(ref)\]/).replace("label",Pt).replace("ref",Tn).getRegex(),kr=A(/^!?\[(ref)\](?:\[\])?/).replace("ref",Tn).getRegex(),Ls=A("reflink|nolink(?!\\()","g").replace("reflink",mr).replace("nolink",kr).getRegex(),Yn=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,An={_backpedal:Ye,anyPunctuation:ys,autolink:Ss,blockSkip:gs,br:dr,code:us,del:Ye,delLDelim:Ye,delRDelim:Ye,emStrongLDelim:ms,emStrongRDelimAst:xs,emStrongRDelimUnd:vs,escape:cs,link:Rs,nolink:kr,punctuation:ds,reflink:mr,reflinkSearch:Ls,tag:As,text:ps,url:Ye},Is={...An,link:A(/^!?\[(label)\]\((.*?)\)/).replace("label",Pt).getRegex(),reflink:A(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",Pt).getRegex()},pn={...An,emStrongRDelimAst:bs,emStrongLDelim:ks,delLDelim:_s,delRDelim:Ts,url:A(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol",Yn).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:A(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol",Yn).getRegex()},Cs={...pn,br:A(dr).replace("{2,}","*").getRegex(),text:A(pn.text).replace("\\b_","\\b_| {2,}\\n").replace(/\{2,\}/g,"*").getRegex()},Ct={normal:Sn,gfm:os,pedantic:ls},gt={normal:An,gfm:pn,breaks:Cs,pedantic:Is},Ds={"&":"&","<":"<",">":">",'"':""","'":"'"},Xn=s=>Ds[s];function Le(s,e){if(e){if(pe.escapeTest.test(s))return s.replace(pe.escapeReplace,Xn)}else if(pe.escapeTestNoEncode.test(s))return s.replace(pe.escapeReplaceNoEncode,Xn);return s}function Vn(s){try{s=encodeURI(s).replace(pe.percentDecode,"%")}catch{return null}return s}function Qn(s,e){let n=s.replace(pe.findPipe,(o,i,p)=>{let c=!1,g=i;for(;--g>=0&&p[g]==="\\";)c=!c;return c?"|":" |"}),r=n.split(pe.splitPipe),t=0;if(r[0].trim()||r.shift(),r.length>0&&!r.at(-1)?.trim()&&r.pop(),e)if(r.length>e)r.splice(e);else for(;r.length<e;)r.push("");for(;t<r.length;t++)r[t]=r[t].trim().replace(pe.slashPipe,"|");return r}function mt(s,e,n){let r=s.length;if(r===0)return"";let t=0;for(;t<r&&s.charAt(r-t-1)===e;)t++;return s.slice(0,r-t)}function Os(s,e){if(s.indexOf(e[1])===-1)return-1;let n=0;for(let r=0;r<s.length;r++)if(s[r]==="\\")r++;else if(s[r]===e[0])n++;else if(s[r]===e[1]&&(n--,n<0))return r;return n>0?-2:-1}function Ms(s,e=0){let n=e,r="";for(let t of s)if(t===" "){let o=4-n%4;r+=" ".repeat(o),n+=o}else r+=t,n++;return r}function Kn(s,e,n,r,t){let o=e.href,i=e.title||null,p=s[1].replace(t.other.outputLinkReplace,"$1");r.state.inLink=!0;let c={type:s[0].charAt(0)==="!"?"image":"link",raw:n,href:o,title:i,text:p,tokens:r.inlineTokens(p)};return r.state.inLink=!1,c}function Ns(s,e,n){let r=s.match(n.other.indentCodeCompensation);if(r===null)return e;let t=r[1];return e.split(`
|
|
3
3
|
`).map(o=>{let i=o.match(n.other.beginningSpace);if(i===null)return o;let[p]=i;return p.length>=t.length?o.slice(t.length):o}).join(`
|
|
4
4
|
`)}var zt=class{options;rules;lexer;constructor(s){this.options=s||Ve}space(s){let e=this.rules.block.newline.exec(s);if(e&&e[0].length>0)return{type:"space",raw:e[0]}}code(s){let e=this.rules.block.code.exec(s);if(e){let n=e[0].replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:e[0],codeBlockStyle:"indented",text:this.options.pedantic?n:mt(n,`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as W,a as l,f as w,t as D}from"../chunks/BmRlVmv6.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/CME08kGM.js";import{s as M,e as ye}from"../chunks/DMtIqaiV.js";import{l as oe,s as se,i as T}from"../chunks/B6YN0Nuq.js";import{I as de,s as ie,B as H,f as we,g as $e,e as Se}from"../chunks/CK9JZLaG.js";import{i as re}from"../chunks/
|
|
1
|
+
import{c as W,a as l,f as w,t as D}from"../chunks/BmRlVmv6.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/CME08kGM.js";import{s as M,e as ye}from"../chunks/DMtIqaiV.js";import{l as oe,s as se,i as T}from"../chunks/B6YN0Nuq.js";import{I as de,s as ie,B as H,f as we,g as $e,e as Se}from"../chunks/CK9JZLaG.js";import{i as re}from"../chunks/9nfWZDAH.js";import{P as ke,I as U}from"../chunks/Drm9vgeP.js";import"../chunks/Ck3rYNON.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":"1774990031225"}
|
package/dist/web/index.html
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1, interactive-widget=resizes-content" />
|
|
6
|
-
<link href="/_app/immutable/entry/start.
|
|
7
|
-
<link href="/_app/immutable/chunks/
|
|
6
|
+
<link href="/_app/immutable/entry/start.k4GcE1y3.js" rel="modulepreload">
|
|
7
|
+
<link href="/_app/immutable/chunks/9nfWZDAH.js" rel="modulepreload">
|
|
8
8
|
<link href="/_app/immutable/chunks/CME08kGM.js" rel="modulepreload">
|
|
9
9
|
<link href="/_app/immutable/chunks/DhD271EB.js" rel="modulepreload">
|
|
10
|
-
<link href="/_app/immutable/entry/app.
|
|
10
|
+
<link href="/_app/immutable/entry/app.CDP4hzOl.js" rel="modulepreload">
|
|
11
11
|
<link href="/_app/immutable/chunks/DMtIqaiV.js" rel="modulepreload">
|
|
12
12
|
<link href="/_app/immutable/chunks/BmRlVmv6.js" rel="modulepreload">
|
|
13
13
|
<link href="/_app/immutable/chunks/B6YN0Nuq.js" rel="modulepreload">
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
<div style="display: contents">
|
|
19
19
|
<script>
|
|
20
20
|
{
|
|
21
|
-
|
|
21
|
+
__sveltekit_miui9j = {
|
|
22
22
|
base: ""
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
const element = document.currentScript.parentElement;
|
|
26
26
|
|
|
27
27
|
Promise.all([
|
|
28
|
-
import("/_app/immutable/entry/start.
|
|
29
|
-
import("/_app/immutable/entry/app.
|
|
28
|
+
import("/_app/immutable/entry/start.k4GcE1y3.js"),
|
|
29
|
+
import("/_app/immutable/entry/app.CDP4hzOl.js")
|
|
30
30
|
]).then(([kit, app]) => {
|
|
31
31
|
kit.start(app, element);
|
|
32
32
|
});
|
|
@@ -24,6 +24,8 @@ const AgentSchema = z.looseObject({
|
|
|
24
24
|
getSessionId: z.string().optional(),
|
|
25
25
|
getMessageContent: z.string().optional()
|
|
26
26
|
}).optional(),
|
|
27
|
+
apiTokenEnvVar: z.string().optional(),
|
|
28
|
+
apiUrlEnvVar: z.string().optional(),
|
|
27
29
|
env: z.record(z.string(), z.union([z.string(), z.boolean()])).optional(),
|
|
28
30
|
subagentEnv: z.record(z.string(), z.union([z.string(), z.boolean()])).optional(),
|
|
29
31
|
directory: z.string().optional(),
|
|
@@ -451,4 +453,4 @@ async function enableEnvironment(name, targetPath = "./", startDir = process.cwd
|
|
|
451
453
|
|
|
452
454
|
//#endregion
|
|
453
455
|
export { writeAgentSessionSettings as C, pathIsInsideDir as D, writeSettings as E, CronJobSchema as O, updateChatSettings as S, writeChatSettings as T, readEnvironment as _, enableEnvironment as a, resolveAgentWorkDir as b, getClawminiDir as c, getSocketPath as d, getWorkspaceRoot as f, readChatSettings as g, readAgentSessionSettings as h, deleteAgent as i, SettingsSchema as k, getEnvironmentPath as l, listAgents as m, copyAgentSkill as n, getActiveEnvironmentInfo as o, isValidAgentId as p, copyAgentSkills as r, getAgent as s, applyTemplateToAgent as t, getSettingsPath as u, readPolicies as v, writeAgentSettings as w, resolveSkillsTemplatePath as x, readSettings as y };
|
|
454
|
-
//# sourceMappingURL=workspace-
|
|
456
|
+
//# sourceMappingURL=workspace-BJmJBfKi.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-BJmJBfKi.mjs","names":["fsPromises"],"sources":["../src/shared/config.ts","../src/shared/utils/fs.ts","../src/shared/workspace.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const FallbackSchema = z.looseObject({\n commands: z\n .looseObject({\n new: z.string().optional(),\n append: z.string().optional(),\n getSessionId: z.string().optional(),\n getMessageContent: z.string().optional(),\n })\n .optional(),\n env: z.record(z.string(), z.union([z.string(), z.boolean()])).optional(),\n retries: z.number().int().min(0).default(1),\n delayMs: z.number().int().min(0).default(1000),\n});\n\nexport const AgentSchema = z.looseObject({\n commands: z\n .looseObject({\n new: z.string().optional(),\n append: z.string().optional(),\n getSessionId: z.string().optional(),\n getMessageContent: z.string().optional(),\n })\n .optional(),\n apiTokenEnvVar: z.string().optional(),\n apiUrlEnvVar: z.string().optional(),\n env: z.record(z.string(), z.union([z.string(), z.boolean()])).optional(),\n subagentEnv: z.record(z.string(), z.union([z.string(), z.boolean()])).optional(),\n directory: z.string().optional(),\n skillsDir: z.string().optional(),\n fallbacks: z.array(FallbackSchema).optional(),\n files: z.string().default('./attachments').optional(),\n});\n\nexport type Agent = z.infer<typeof AgentSchema>;\n\nexport type CronJob = {\n id: string;\n createdAt?: string;\n message: string;\n reply?: string;\n agentId?: string;\n env?: Record<string, string | boolean>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n session?: { type: string; [key: string]: any };\n schedule: { cron: string } | { every: string } | { at: string };\n nextSessionId?: string;\n action?: 'stop' | 'interrupt' | 'continue';\n jobs?: {\n add?: CronJob[];\n remove?: string[];\n };\n};\n\nexport const CronJobSchema = z.lazy(() =>\n z.looseObject({\n id: z.string().min(1),\n createdAt: z.string().optional(),\n message: z.string().default(''),\n reply: z.string().optional(),\n agentId: z.string().optional(),\n env: z.record(z.string(), z.union([z.string(), z.boolean()])).optional(),\n session: z.looseObject({ type: z.string() }).optional(),\n schedule: z.union([\n z.looseObject({ cron: z.string() }),\n z.looseObject({ every: z.string() }),\n z.looseObject({ at: z.string() }),\n ]),\n nextSessionId: z.string().optional(),\n action: z.enum(['stop', 'interrupt', 'continue']).optional(),\n jobs: z\n .looseObject({\n add: z.array(z.lazy(() => CronJobSchema)).optional(),\n remove: z.array(z.string()).optional(),\n })\n .optional(),\n })\n) as z.ZodType<CronJob>;\n\nexport const RouterConfigSchema = z.union([\n z.string(),\n z.looseObject({\n use: z.string(),\n with: z.record(z.string(), z.any()).optional(),\n }),\n]);\n\nexport type RouterConfig = z.infer<typeof RouterConfigSchema>;\n\nexport const SubagentTrackerSchema = z.looseObject({\n id: z.string(),\n agentId: z.string().optional(),\n sessionId: z.string().optional(),\n createdAt: z.string(),\n status: z.enum(['active', 'completed', 'failed']),\n parentId: z.string().optional(),\n});\n\nexport type SubagentTracker = z.infer<typeof SubagentTrackerSchema>;\n\nexport const ChatSettingsSchema = z.looseObject({\n defaultAgent: z.string().optional(),\n sessions: z.record(z.string(), z.string()).optional(),\n routers: z.array(RouterConfigSchema).optional(),\n jobs: z.array(CronJobSchema).optional(),\n subagents: z.record(z.string(), SubagentTrackerSchema).optional(),\n});\n\nexport type ChatSettings = z.infer<typeof ChatSettingsSchema>;\n\nexport const AgentSessionSettingsSchema = z.looseObject({\n env: z.record(z.string(), z.union([z.string(), z.boolean()])).optional(),\n});\n\nexport type AgentSessionSettings = z.infer<typeof AgentSessionSettingsSchema>;\n\nexport const EnvironmentSchema = z.looseObject({\n init: z.string().optional(),\n up: z.string().optional(),\n down: z.string().optional(),\n prefix: z.string().optional(),\n envFormat: z.string().optional(),\n exportLiteTo: z.string().optional(),\n env: z.record(z.string(), z.union([z.string(), z.boolean()])).optional(),\n});\n\nexport type Environment = z.infer<typeof EnvironmentSchema>;\n\nexport const SettingsSchema = z.looseObject({\n chats: z\n .looseObject({\n defaultId: z.string().optional(),\n })\n .optional(),\n defaultAgent: AgentSchema.optional(),\n environments: z.record(z.string(), z.string()).optional(),\n routers: z.array(RouterConfigSchema).optional(),\n files: z.string().default('./attachments').optional(),\n api: z\n .union([\n z.boolean(),\n z.looseObject({\n host: z.string().optional(),\n port: z.number().optional(),\n proxy_host: z.string().optional(),\n }),\n ])\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","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","/* eslint-disable max-lines */\nimport { execSync } from 'node:child_process';\nimport type { PolicyConfig } from './policies.js';\nimport fs from 'node:fs';\nimport fsPromises from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport {\n type Agent,\n AgentSchema,\n type ChatSettings,\n ChatSettingsSchema,\n type AgentSessionSettings,\n AgentSessionSettingsSchema,\n type Environment,\n EnvironmentSchema,\n type Settings,\n SettingsSchema,\n} from './config.js';\nimport { pathIsInsideDir } from './utils/fs.js';\n\nexport function getWorkspaceRoot(startDir = process.cwd()): string {\n let curr = startDir;\n while (curr !== path.parse(curr).root) {\n if (fs.existsSync(path.join(curr, '.clawmini'))) {\n return curr;\n }\n if (fs.existsSync(path.join(curr, 'package.json')) || fs.existsSync(path.join(curr, '.git'))) {\n return curr;\n }\n curr = path.dirname(curr);\n }\n return startDir;\n}\n\nexport function resolveAgentWorkDir(\n agentId: string,\n customDir?: string,\n startDir = process.cwd()\n): string {\n const workspaceRoot = getWorkspaceRoot(startDir);\n let dirPath = workspaceRoot;\n if (customDir) {\n dirPath = path.resolve(workspaceRoot, customDir);\n } else if (agentId !== 'default') {\n dirPath = path.resolve(workspaceRoot, agentId);\n }\n\n if (!pathIsInsideDir(dirPath, workspaceRoot, { allowSameDir: true })) {\n throw new Error('Invalid agent directory: resolves outside the workspace.');\n }\n\n return dirPath;\n}\n\nexport function resolveAgentSkillsDir(\n agentId: string,\n agentData: Agent,\n startDir = process.cwd()\n): string {\n const workDir = resolveAgentWorkDir(agentId, agentData.directory, startDir);\n return path.resolve(workDir, agentData.skillsDir || '.agents/skills');\n}\n\nexport async function ensureAgentWorkDir(\n agentId: string,\n customDir?: string,\n startDir = process.cwd()\n): Promise<string> {\n const dirPath = resolveAgentWorkDir(agentId, customDir, startDir);\n\n if (!fs.existsSync(dirPath)) {\n await fsPromises.mkdir(dirPath, { recursive: true });\n console.log(`Created agent working directory at ${dirPath}`);\n }\n return dirPath;\n}\n\nexport function getClawminiDir(startDir = process.cwd()): string {\n return path.join(getWorkspaceRoot(startDir), '.clawmini');\n}\n\nexport function getSocketPath(startDir = process.cwd()): string {\n return path.join(getClawminiDir(startDir), 'daemon.sock');\n}\n\nexport function getSettingsPath(startDir = process.cwd()): string {\n return path.join(getClawminiDir(startDir), 'settings.json');\n}\n\nexport function getPoliciesPath(startDir = process.cwd()): string {\n return path.join(getClawminiDir(startDir), 'policies.json');\n}\n\nexport function getChatSettingsPath(chatId: string, startDir = process.cwd()): string {\n return path.join(getClawminiDir(startDir), 'chats', chatId, 'settings.json');\n}\n\nexport function isValidAgentId(agentId: string): boolean {\n if (!agentId || agentId.length === 0) return false;\n return /^[a-zA-Z0-9_]+(?:-[a-zA-Z0-9_]+)*$/.test(agentId);\n}\n\nexport function getAgentDir(agentId: string, startDir = process.cwd()): string {\n if (!isValidAgentId(agentId)) {\n throw new Error(`Invalid agent ID: ${agentId}`);\n }\n return path.join(getClawminiDir(startDir), 'agents', agentId);\n}\n\nexport function getAgentSettingsPath(agentId: string, startDir = process.cwd()): string {\n return path.join(getAgentDir(agentId, startDir), 'settings.json');\n}\n\nexport function getAgentSessionSettingsPath(\n agentId: string,\n sessionId: string,\n startDir = process.cwd()\n): string {\n if (!isValidAgentId(agentId)) {\n throw new Error(`Invalid agent ID: ${agentId}`);\n }\n return path.join(\n getClawminiDir(startDir),\n 'agents',\n agentId,\n 'sessions',\n sessionId,\n 'settings.json'\n );\n}\n\nasync function readJsonFile(filePath: string): Promise<Record<string, unknown> | null> {\n try {\n const data = await fsPromises.readFile(filePath, 'utf-8');\n return JSON.parse(data) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nasync function writeJsonFile(filePath: string, data: Record<string, unknown>): Promise<void> {\n const dir = path.dirname(filePath);\n await fsPromises.mkdir(dir, { recursive: true });\n await fsPromises.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8');\n}\n\nexport async function readChatSettings(\n chatId: string,\n startDir = process.cwd()\n): Promise<ChatSettings | null> {\n const data = await readJsonFile(getChatSettingsPath(chatId, startDir));\n if (!data) return null;\n const parsed = ChatSettingsSchema.safeParse(data);\n return parsed.success ? parsed.data : null;\n}\n\nexport async function writeChatSettings(\n chatId: string,\n data: ChatSettings,\n startDir = process.cwd()\n): Promise<void> {\n await writeJsonFile(getChatSettingsPath(chatId, startDir), data as Record<string, unknown>);\n}\n\nexport const chatSettingsLocks = new Map<string, Promise<void>>();\n\nexport async function updateChatSettings(\n chatId: string,\n updater: (settings: ChatSettings) => ChatSettings | Promise<ChatSettings>,\n startDir = process.cwd()\n): Promise<void> {\n const prevLock = chatSettingsLocks.get(chatId) || Promise.resolve();\n let release!: () => void;\n const nextLock = new Promise<void>((resolve) => {\n release = resolve;\n });\n const nextLockPromise = prevLock.catch(() => {}).then(() => nextLock);\n chatSettingsLocks.set(chatId, nextLockPromise);\n\n try {\n await prevLock;\n const settings = (await readChatSettings(chatId, startDir)) || {};\n const updated = await updater(settings);\n await writeChatSettings(chatId, updated, startDir);\n } finally {\n release();\n if (chatSettingsLocks.get(chatId) === nextLockPromise) {\n chatSettingsLocks.delete(chatId);\n }\n }\n}\n\nexport async function readAgentSessionSettings(\n agentId: string,\n sessionId: string,\n startDir = process.cwd()\n): Promise<AgentSessionSettings | null> {\n const data = await readJsonFile(getAgentSessionSettingsPath(agentId, sessionId, startDir));\n if (!data) return null;\n const parsed = AgentSessionSettingsSchema.safeParse(data);\n return parsed.success ? parsed.data : null;\n}\n\nexport async function writeAgentSessionSettings(\n agentId: string,\n sessionId: string,\n data: AgentSessionSettings,\n startDir = process.cwd()\n): Promise<void> {\n await writeJsonFile(\n getAgentSessionSettingsPath(agentId, sessionId, startDir),\n data as Record<string, unknown>\n );\n}\n\nexport async function getAgent(agentId: string, startDir = process.cwd()): Promise<Agent | null> {\n const filePath = getAgentSettingsPath(agentId, startDir);\n let dataStr: string;\n try {\n dataStr = await fsPromises.readFile(filePath, 'utf-8');\n } catch (err: unknown) {\n if (err && typeof err === 'object' && 'code' in err && err.code === 'ENOENT') return null;\n throw err;\n }\n\n let data: unknown;\n try {\n data = JSON.parse(dataStr);\n } catch (parseErr: unknown) {\n const message = parseErr instanceof Error ? parseErr.message : String(parseErr);\n throw new Error(`Invalid JSON in ${filePath}: ${message}`, { cause: parseErr });\n }\n\n const parsed = AgentSchema.safeParse(data);\n if (!parsed.success) {\n throw new Error(`Invalid schema in ${filePath}: ${parsed.error.message}`);\n }\n return parsed.data;\n}\n\nexport async function writeAgentSettings(\n agentId: string,\n data: Agent,\n startDir = process.cwd()\n): Promise<void> {\n await ensureAgentWorkDir(agentId, data.directory, startDir);\n await writeJsonFile(getAgentSettingsPath(agentId, startDir), data as Record<string, unknown>);\n}\n\nexport async function listAgents(startDir = process.cwd()): Promise<string[]> {\n const agentsDir = path.join(getClawminiDir(startDir), 'agents');\n try {\n const entries = await fsPromises.readdir(agentsDir, { withFileTypes: true });\n const agentIds = [];\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const settingsPath = path.join(agentsDir, entry.name, 'settings.json');\n try {\n await fsPromises.access(settingsPath);\n agentIds.push(entry.name);\n } catch {\n // No settings.json, probably just a sessions dir for a non-existent agent or default agent\n }\n }\n }\n return agentIds;\n } catch {\n return [];\n }\n}\n\nexport async function deleteAgent(agentId: string, startDir = process.cwd()): Promise<void> {\n const dir = getAgentDir(agentId, startDir);\n const agentsDir = path.join(getClawminiDir(startDir), 'agents');\n\n if (!pathIsInsideDir(dir, agentsDir)) {\n throw new Error(`Security Error: Cannot delete agent directory outside of ${agentsDir}`);\n }\n\n try {\n await fsPromises.rm(dir, { recursive: true, force: true });\n } catch {\n // Ignore if not found\n }\n}\n\nasync function isDirectory(dirPath: string): Promise<boolean> {\n try {\n const stat = await fsPromises.stat(dirPath);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\nexport async function resolveTemplatePathBase(\n templateName: string,\n startDir = process.cwd()\n): Promise<string> {\n const workspaceRoot = getWorkspaceRoot(startDir);\n const localTemplatePath = path.join(workspaceRoot, '.clawmini', 'templates', templateName);\n\n if (await isDirectory(localTemplatePath)) {\n return localTemplatePath;\n }\n\n // Fallback to built-in templates\n // Find the clawmini package root by looking for package.json\n let currentDir = path.dirname(fileURLToPath(import.meta.url));\n while (\n currentDir !== path.parse(currentDir).root &&\n !fs.existsSync(path.join(currentDir, 'package.json'))\n ) {\n currentDir = path.dirname(currentDir);\n }\n\n const searchPath = path.join(currentDir, 'templates', templateName);\n\n if (await isDirectory(searchPath)) {\n return searchPath;\n }\n\n throw new Error(\n `Template not found: ${templateName} (searched local: ${localTemplatePath}, built-in: ${searchPath})`\n );\n}\n\nexport async function resolveTemplatePath(\n templateName: string,\n startDir = process.cwd()\n): Promise<string> {\n if (templateName === 'environments' || templateName.startsWith('environments/')) {\n throw new Error(`Template not found: ${templateName}`);\n }\n return resolveTemplatePathBase(templateName, startDir);\n}\n\nexport async function resolveEnvironmentTemplatePath(\n templateName: string,\n startDir = process.cwd()\n): Promise<string> {\n return resolveTemplatePathBase(path.join('environments', templateName), startDir);\n}\n\nexport async function resolveSkillsTemplatePath(startDir = process.cwd()): Promise<string> {\n return resolveTemplatePathBase('skills', startDir);\n}\n\nexport async function copyTemplateBase(\n templatePath: string,\n targetDir: string,\n allowMissingDir: boolean = false,\n overwrite: boolean = false\n): Promise<void> {\n // Check if target directory exists and is not empty\n try {\n const entries = await fsPromises.readdir(targetDir);\n if (entries.length > 0 && !overwrite) {\n throw new Error(`Target directory is not empty: ${targetDir}`);\n }\n } catch (err: unknown) {\n if (err && typeof err === 'object' && 'code' in err && err.code === 'ENOENT') {\n if (allowMissingDir) {\n await fsPromises.mkdir(targetDir, { recursive: true });\n } else {\n throw new Error(`Target directory does not exist: ${targetDir}`, { cause: err });\n }\n } else {\n throw err;\n }\n }\n\n // Recursively copy\n await fsPromises.cp(templatePath, targetDir, { recursive: true, force: true });\n}\n\nexport async function copyTemplate(\n templateName: string,\n targetDir: string,\n startDir = process.cwd()\n): Promise<void> {\n const templatePath = await resolveTemplatePath(templateName, startDir);\n await copyTemplateBase(templatePath, targetDir, false);\n}\n\nexport async function resolveTargetAgentSkillsDir(\n agentId: string,\n startDir = process.cwd()\n): Promise<string> {\n const agentDir = getAgentDir(agentId, startDir);\n try {\n const stat = await fsPromises.stat(agentDir);\n if (!stat.isDirectory()) {\n throw new Error(`Agent not found: ${agentId}`);\n }\n } catch (err: unknown) {\n if (err && typeof err === 'object' && 'code' in err && err.code === 'ENOENT') {\n throw new Error(`Agent not found: ${agentId}`, { cause: err });\n }\n throw err;\n }\n\n let agentData: Agent | null = null;\n try {\n agentData = await getAgent(agentId, startDir);\n } catch {\n // Ignore malformed settings.json\n }\n\n if (agentData) {\n return resolveAgentSkillsDir(agentId, agentData, startDir);\n }\n\n const workDir = resolveAgentWorkDir(agentId, undefined, startDir);\n return path.resolve(workDir, '.agents/skills');\n}\n\nexport async function copyEnvironmentTemplate(\n templateName: string,\n targetDir: string,\n startDir = process.cwd()\n): Promise<void> {\n const templatePath = await resolveEnvironmentTemplatePath(templateName, startDir);\n await copyTemplateBase(templatePath, targetDir, true);\n}\n\nexport async function copyAgentSkills(\n agentId: string,\n startDir = process.cwd(),\n overwrite = false\n): Promise<void> {\n const targetDir = await resolveTargetAgentSkillsDir(agentId, startDir);\n const templatePath = await resolveSkillsTemplatePath(startDir);\n await copyTemplateBase(templatePath, targetDir, true, overwrite);\n}\n\nexport async function copyAgentSkill(\n agentId: string,\n skillName: string,\n startDir = process.cwd(),\n overwrite = false\n): Promise<void> {\n const targetDir = await resolveTargetAgentSkillsDir(agentId, startDir);\n const templatePath = await resolveSkillsTemplatePath(startDir);\n const specificSkillPath = path.join(templatePath, skillName);\n\n try {\n const stat = await fsPromises.stat(specificSkillPath);\n if (!stat.isDirectory()) {\n throw new Error(`Skill not found: ${skillName}`);\n }\n } catch (err: unknown) {\n if (err && typeof err === 'object' && 'code' in err && err.code === 'ENOENT') {\n throw new Error(`Skill not found: ${skillName}`, { cause: err });\n }\n throw err;\n }\n\n const skillTargetDir = path.join(targetDir, skillName);\n await copyTemplateBase(specificSkillPath, skillTargetDir, true, overwrite);\n}\n\nexport async function applyTemplateToAgent(\n agentId: string,\n templateName: string,\n overrides: Agent,\n startDir = process.cwd()\n): Promise<void> {\n const agentWorkDir = resolveAgentWorkDir(agentId, overrides.directory, startDir);\n await copyTemplate(templateName, agentWorkDir, startDir);\n\n const settingsPath = path.join(agentWorkDir, 'settings.json');\n try {\n const rawSettings = await fsPromises.readFile(settingsPath, 'utf-8');\n const parsedSettings = JSON.parse(rawSettings);\n const validation = AgentSchema.safeParse(parsedSettings);\n\n if (validation.success) {\n const templateData = validation.data;\n if (templateData.directory) {\n console.warn(\n `Warning: Ignoring 'directory' field from template settings.json. Using default or provided directory.`\n );\n delete templateData.directory;\n }\n\n // Merge: overrides take precedence over templateData\n const mergedEnv = { ...(templateData.env || {}), ...(overrides.env || {}) };\n const mergedData: Agent = { ...templateData, ...overrides };\n if (Object.keys(mergedEnv).length > 0) {\n mergedData.env = mergedEnv;\n }\n\n await writeAgentSettings(agentId, mergedData, startDir);\n }\n } catch {\n // Ignore parsing or file not found errors\n } finally {\n try {\n await fsPromises.rm(settingsPath);\n } catch {\n // Ignore if it doesn't exist\n }\n }\n}\n\nexport async function readSettings(startDir = process.cwd()): Promise<Settings | null> {\n const data = await readJsonFile(getSettingsPath(startDir));\n if (!data) return null;\n const parsed = SettingsSchema.safeParse(data);\n return parsed.success ? parsed.data : null;\n}\n\nexport async function writeSettings(data: Settings, startDir = process.cwd()): Promise<void> {\n await writeJsonFile(getSettingsPath(startDir), data as Record<string, unknown>);\n}\n\nexport async function readPolicies(startDir = process.cwd()): Promise<PolicyConfig | null> {\n const data = await readJsonFile(getPoliciesPath(startDir));\n if (!data) return null;\n // Basic validation, assuming PolicyConfig structure\n if (data.policies && typeof data.policies === 'object') {\n return data as unknown as PolicyConfig;\n }\n return null;\n}\n\nexport function getEnvironmentPath(name: string, startDir = process.cwd()): string {\n return path.join(getClawminiDir(startDir), 'environments', name);\n}\n\nexport async function readEnvironment(\n name: string,\n startDir = process.cwd()\n): Promise<Environment | null> {\n const data = await readJsonFile(path.join(getEnvironmentPath(name, startDir), 'env.json'));\n if (!data) return null;\n const parsed = EnvironmentSchema.safeParse(data);\n return parsed.success ? parsed.data : null;\n}\n\nexport async function getActiveEnvironmentInfo(\n targetPath: string,\n startDir = process.cwd()\n): Promise<{ name: string; targetPath: string } | null> {\n const settings = await readSettings(startDir);\n if (!settings?.environments) return null;\n\n const workspaceRoot = getWorkspaceRoot(startDir);\n const resolvedTarget = path.resolve(workspaceRoot, targetPath);\n\n let bestMatch: { name: string; targetPath: string } | null = null;\n let maxDepth = -1;\n\n for (const [envPath, envName] of Object.entries(settings.environments)) {\n const resolvedEnvPath = path.resolve(workspaceRoot, envPath);\n\n if (pathIsInsideDir(resolvedTarget, resolvedEnvPath, { allowSameDir: true })) {\n const depth = resolvedEnvPath.split(path.sep).length;\n if (depth > maxDepth) {\n maxDepth = depth;\n bestMatch = { name: envName, targetPath: resolvedEnvPath };\n }\n }\n }\n\n return bestMatch;\n}\n\nexport async function getActiveEnvironmentName(\n targetPath: string,\n startDir = process.cwd()\n): Promise<string | null> {\n const info = await getActiveEnvironmentInfo(targetPath, startDir);\n return info ? info.name : null;\n}\n\nexport async function enableEnvironment(\n name: string,\n targetPath: string = './',\n startDir = process.cwd()\n): Promise<void> {\n const targetDir = getEnvironmentPath(name, startDir);\n\n // Copy template to targetDir if it does not already exist\n if (!fs.existsSync(targetDir)) {\n await copyEnvironmentTemplate(name, targetDir, startDir);\n console.log(`Copied environment template '${name}'.`);\n } else {\n console.log(`Environment template '${name}' already exists in workspace.`);\n }\n\n const settings = (await readSettings(startDir)) || { chats: { defaultId: '' } };\n const environments = settings.environments || {};\n\n environments[targetPath] = name;\n settings.environments = environments;\n\n await writeSettings(settings, startDir);\n console.log(`Enabled environment '${name}' for path '${targetPath}'.`);\n\n // Execute init command if present\n const envConfig = await readEnvironment(name, startDir);\n if (envConfig?.init) {\n // Get the target directory for the environment\n const workspaceRoot = getWorkspaceRoot(startDir);\n const affectedDir = path.resolve(workspaceRoot, targetPath);\n console.log(`Executing init command for environment '${name}': ${envConfig.init}`);\n execSync(envConfig.init, { cwd: affectedDir, stdio: 'inherit' });\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Development Log
|
|
2
|
+
|
|
3
|
+
## Initialization
|
|
4
|
+
- Started working on "Step 1: Update Agent Schema".
|
|
5
|
+
- Added `apiTokenEnvVar` and `apiUrlEnvVar` to `AgentSchema` in `src/shared/config.ts`.
|
|
6
|
+
- Ran `npm run format && npm run lint:fix && npm run validate`.
|
|
7
|
+
- Validations failed initially due to zombie processes on the e2e test port, so killed zombie node and daemon processes and retried successfully.
|
|
8
|
+
- Marked Step 1 as completed in `tickets.md`.
|
|
9
|
+
|
|
10
|
+
## Step 2: Update Lite Client Resolution Logic
|
|
11
|
+
- Updated `src/cli/lite.ts` to dynamically resolve authentication environment variables.
|
|
12
|
+
- Read pointer variables `CLAW_LITE_API_VAR` and `CLAW_LITE_URL_VAR` to resolve the `API_TOKEN` and `API_URL` respectively.
|
|
13
|
+
- Updated error handling to log out the expected dynamically resolved variable names instead of the hardcoded names if missing.
|
|
14
|
+
- Ran `npm run format && npm run lint:fix && npm run validate` which succeeded.
|
|
15
|
+
- Marked Step 2 as completed in `tickets.md`.
|
|
16
|
+
|
|
17
|
+
## Step 3: Update Daemon Environment Variable Injection
|
|
18
|
+
- Updated `src/daemon/agent/agent-session.ts` in `buildExecutionContext`.
|
|
19
|
+
- Added logic to check if `currentAgent.apiTokenEnvVar` and `currentAgent.apiUrlEnvVar` are defined.
|
|
20
|
+
- Injected token/URL into custom variables and updated pointer variables `CLAW_LITE_API_VAR` and `CLAW_LITE_URL_VAR`.
|
|
21
|
+
- If custom variables are not defined, gracefully falls back to `CLAW_API_TOKEN` and `CLAW_API_URL` respectively.
|
|
22
|
+
- Ran validations (`npm run format && npm run lint:fix && npm run validate`), all tests passed.
|
|
23
|
+
- Marked Step 3 as completed in `tickets.md`.
|
|
24
|
+
|
|
25
|
+
## Step 4: Add and Update E2E Tests
|
|
26
|
+
- Added a new E2E test in `src/cli/e2e/daemon.test.ts` to verify injection and functioning of custom `apiTokenEnvVar` and `apiUrlEnvVar`.
|
|
27
|
+
- Created an agent with customized pointer variables and used it to send messages.
|
|
28
|
+
- Verified that `lite` dynamically correctly leverages `CLAW_LITE_API_VAR` and `CLAW_LITE_URL_VAR` to securely interact with the Daemon APIs.
|
|
29
|
+
- Reviewed `export-lite-func.test.ts` and `requests.test.ts`, confirming they inherently verify the fallback/default behavior remains completely intact.
|
|
30
|
+
- Ran formatting and final validation checks (`npm run validate`); all 380 E2E tests successfully pass.
|
|
31
|
+
- Marked Step 4 as completed in `tickets.md`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Notes on Custom Token Env
|
|
2
|
+
|
|
3
|
+
## Current Behavior
|
|
4
|
+
- The daemon securely authenticates with the Agent API using a dynamically generated HMAC token (`CLAW_API_TOKEN`).
|
|
5
|
+
- `src/daemon/agent/agent-session.ts` injects `CLAW_API_URL` and `CLAW_API_TOKEN` into the environment of the executed agent process.
|
|
6
|
+
- `src/cli/lite.ts` (which compiles to `clawmini-lite.js`) reads these via `process.env.CLAW_API_URL` and `process.env.CLAW_API_TOKEN`.
|
|
7
|
+
- E2E tests (`src/cli/e2e/`) check for `CLAW_API_TOKEN=` in the environment variables.
|
|
8
|
+
|
|
9
|
+
## Issue
|
|
10
|
+
- Gemini CLI strips out environment variables that include `TOKEN`, `KEY`, `SECRET`, etc., unless they have the `GEMINI_CLI_` prefix.
|
|
11
|
+
- Therefore, when Clawmini runs Gemini CLI as an agent, `CLAW_API_TOKEN` is stripped, and `clawmini-lite.js` (used for fallbacks or tool usage) cannot authenticate.
|
|
12
|
+
|
|
13
|
+
## Solution Direction
|
|
14
|
+
- Allow configuring an alternative env var name to pass the token (e.g., `GEMINI_CLI_CLAW_API_TOKEN`).
|
|
15
|
+
- If this is configured, the daemon must inject the token using this alternative name.
|
|
16
|
+
- We need a way to tell `clawmini-lite.js` which environment variable contains the token, since it won't be `CLAW_API_TOKEN` anymore. This pointer variable itself must not contain the words `TOKEN`, `KEY`, or `SECRET` to avoid being stripped.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Product Requirements Document: Custom Token Environment Variables
|
|
2
|
+
|
|
3
|
+
## 1. Vision
|
|
4
|
+
Enable Clawmini to integrate seamlessly with strict sandboxes and external CLI tools (like Gemini CLI) that aggressively filter or strip environment variables containing sensitive keywords such as `TOKEN`, `KEY`, or `SECRET`. By allowing agents to configure custom names for the API URL and API Token environment variables, Clawmini ensures that injected authentication details reach the target agent process without being discarded by intermediate wrappers.
|
|
5
|
+
|
|
6
|
+
## 2. Product/Market Background
|
|
7
|
+
Clawmini securely authenticates spawned agents with its API using a dynamically generated HMAC token passed via the `CLAW_API_TOKEN` environment variable. The agent uses the lightweight `clawmini-lite.js` script to execute tasks (e.g., fallbacks, tool usage). However, some agents—such as the Gemini CLI—employ strict security measures that strip out environment variables matching sensitive keyword patterns unless explicitly prefixed (e.g., `GEMINI_CLI_`). This behavior breaks Clawmini's authentication flow because `CLAW_API_TOKEN` is stripped before `clawmini-lite.js` runs.
|
|
8
|
+
|
|
9
|
+
## 3. Use Cases
|
|
10
|
+
- **Running Gemini CLI as an Agent:** A user configures Gemini CLI as a Clawmini agent. They define `apiTokenEnvVar: 'GEMINI_CLI_CLAW_API_TOKEN'` in the agent configuration so that the authentication token bypasses Gemini CLI's environment variable filter.
|
|
11
|
+
- **Custom URL Overrides:** A user is running an agent inside an environment where `CLAW_API_URL` conflicts with an existing system variable or is stripped, and they need to map it to a custom variable name like `CUSTOM_API_HOST`.
|
|
12
|
+
|
|
13
|
+
## 4. Requirements
|
|
14
|
+
|
|
15
|
+
### 4.1. Configuration (`src/shared/config.ts`)
|
|
16
|
+
- Update the `AgentSchema` (and corresponding `Agent` type) to include two new optional string properties:
|
|
17
|
+
- `apiTokenEnvVar`: Specifies an alternative environment variable name for the API token.
|
|
18
|
+
- `apiUrlEnvVar`: Specifies an alternative environment variable name for the API URL.
|
|
19
|
+
|
|
20
|
+
### 4.2. Daemon Injection (`src/daemon/agent/agent-session.ts`)
|
|
21
|
+
- When spawning an agent, check if `agent.apiTokenEnvVar` and/or `agent.apiUrlEnvVar` are set.
|
|
22
|
+
- If `apiTokenEnvVar` is defined:
|
|
23
|
+
- Inject the token into the specified custom environment variable (e.g., `GEMINI_CLI_CLAW_API_TOKEN`) instead of `CLAW_API_TOKEN`.
|
|
24
|
+
- Inject a "pointer" environment variable named `CLAW_LITE_API_VAR` whose value is the name of the custom token variable (e.g., `"GEMINI_CLI_CLAW_API_TOKEN"`). This pointer must *not* be stripped by target tools, hence avoiding keywords like `TOKEN`.
|
|
25
|
+
- If `apiUrlEnvVar` is defined:
|
|
26
|
+
- Inject the API URL into the specified custom environment variable instead of `CLAW_API_URL`.
|
|
27
|
+
- Also ensure that `clawmini-lite.js` knows where to look for the URL (e.g., using another pointer variable like `CLAW_LITE_URL_VAR`, or encoding both in a structured way). Given the structure, a matching pointer for the URL `CLAW_LITE_URL_VAR` should be introduced.
|
|
28
|
+
|
|
29
|
+
### 4.3. Lite Client Updates (`src/cli/lite.ts`)
|
|
30
|
+
- `clawmini-lite.js` must be updated to dynamically resolve the environment variable names used for authentication.
|
|
31
|
+
- Read the pointer variables first (`process.env.CLAW_LITE_API_VAR` and `process.env.CLAW_LITE_URL_VAR`).
|
|
32
|
+
- If `CLAW_LITE_API_VAR` is set, read the token from `process.env[process.env.CLAW_LITE_API_VAR]`. Fallback to `process.env.CLAW_API_TOKEN` if the pointer is not set.
|
|
33
|
+
- If `CLAW_LITE_URL_VAR` is set, read the URL from `process.env[process.env.CLAW_LITE_URL_VAR]`. Fallback to `process.env.CLAW_API_URL` if the pointer is not set.
|
|
34
|
+
- Ensure appropriate error handling if the resolved variables are missing or empty.
|
|
35
|
+
|
|
36
|
+
### 4.4. Security Considerations
|
|
37
|
+
- The introduction of custom environment variables does not alter the fundamental HMAC authentication model. The token remains dynamically generated per execution and is only valid for its intended scope.
|
|
38
|
+
- The pointer variables (`CLAW_LITE_API_VAR`, `CLAW_LITE_URL_VAR`) must not contain sensitive strings like `TOKEN` to ensure they bypass downstream filters.
|
|
39
|
+
|
|
40
|
+
### 4.5. Testing
|
|
41
|
+
- **E2E Tests:** Update `src/cli/e2e/daemon.test.ts`, `src/cli/e2e/export-lite-func.test.ts`, and `src/cli/e2e/requests.test.ts` to accommodate or verify the fallback logic.
|
|
42
|
+
- Write a specific test case that configures an agent with `apiTokenEnvVar` and `apiUrlEnvVar`, ensuring the daemon properly injects the custom and pointer variables, and verifying that a mock `clawmini-lite.js` invocation successfully authenticates using the redirected variables.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Questions for Custom Token Env
|
|
2
|
+
|
|
3
|
+
1. Since we need a way to tell `clawmini-lite.js` which environment variable contains the token, what should we name this "pointer" environment variable? It cannot contain `TOKEN`, `KEY`, or `SECRET` (e.g., `CLAW_API_TOKEN_VAR` would be stripped). Would something like `CLAW_LITE_API_VAR` or `CLAW_AUTH_ENV` work?
|
|
4
|
+
- **Answer:** `CLAW_LITE_API_VAR` is a good choice as it avoids sensitive words.
|
|
5
|
+
2. Where should the configuration for the alternative environment variable name live? Should we add an `apiTokenEnvVar` property to the `Agent` schema, the `Environment` schema, or both (with Agent overriding Environment)?
|
|
6
|
+
- **Answer:** The `Agent` schema is the appropriate place. The property name should be `apiTokenEnvVar`.
|
|
7
|
+
3. Does `CLAW_API_URL` pass through Gemini CLI without issues, or do we also need to support renaming the URL environment variable?
|
|
8
|
+
- **Answer:** It generally passes through without issues, but we should also allow the user to override it via an `apiUrlEnvVar` property on the `Agent` schema.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Tickets: Custom Token Environment Variables
|
|
2
|
+
|
|
3
|
+
## Step 1: Update Agent Schema
|
|
4
|
+
**Status**: Completed
|
|
5
|
+
|
|
6
|
+
**Tasks:**
|
|
7
|
+
- Update `src/shared/config.ts`.
|
|
8
|
+
- Add `apiTokenEnvVar` (optional string) to `AgentSchema` and `Agent` type.
|
|
9
|
+
- Add `apiUrlEnvVar` (optional string) to `AgentSchema` and `Agent` type.
|
|
10
|
+
|
|
11
|
+
**Verification:**
|
|
12
|
+
- Run `npm run format` and `npm run lint:fix`.
|
|
13
|
+
- Run `npm run validate` to ensure type checking and tests pass.
|
|
14
|
+
|
|
15
|
+
## Step 2: Update Lite Client Resolution Logic
|
|
16
|
+
**Status**: Completed
|
|
17
|
+
|
|
18
|
+
**Tasks:**
|
|
19
|
+
- Update `src/cli/lite.ts` to dynamically resolve authentication environment variables.
|
|
20
|
+
- Read pointer variables: `process.env.CLAW_LITE_API_VAR` and `process.env.CLAW_LITE_URL_VAR`.
|
|
21
|
+
- Resolve token: If `CLAW_LITE_API_VAR` is set, use `process.env[process.env.CLAW_LITE_API_VAR]`. Otherwise, fallback to `process.env.CLAW_API_TOKEN`.
|
|
22
|
+
- Resolve URL: If `CLAW_LITE_URL_VAR` is set, use `process.env[process.env.CLAW_LITE_URL_VAR]`. Otherwise, fallback to `process.env.CLAW_API_URL`.
|
|
23
|
+
- Ensure appropriate error handling if the resolved variables are missing or empty.
|
|
24
|
+
|
|
25
|
+
**Verification:**
|
|
26
|
+
- Run `npm run format` and `npm run lint:fix`.
|
|
27
|
+
- Run `npm run validate` to ensure code compiles.
|
|
28
|
+
|
|
29
|
+
## Step 3: Update Daemon Environment Variable Injection
|
|
30
|
+
**Status**: Completed
|
|
31
|
+
|
|
32
|
+
**Tasks:**
|
|
33
|
+
- Update `src/daemon/agent/agent-session.ts`.
|
|
34
|
+
- When spawning an agent, check for `agent.apiTokenEnvVar` and `agent.apiUrlEnvVar`.
|
|
35
|
+
- If `apiTokenEnvVar` is defined, inject the token into the custom variable and set `CLAW_LITE_API_VAR` to the custom variable name. Do not inject `CLAW_API_TOKEN`.
|
|
36
|
+
- If `apiUrlEnvVar` is defined, inject the URL into the custom variable and set `CLAW_LITE_URL_VAR` to the custom variable name. Do not inject `CLAW_API_URL`.
|
|
37
|
+
- If they are not defined, inject `CLAW_API_TOKEN` and `CLAW_API_URL` as usual.
|
|
38
|
+
|
|
39
|
+
**Verification:**
|
|
40
|
+
- Run `npm run format` and `npm run lint:fix`.
|
|
41
|
+
- Run `npm run validate` to ensure tests still pass.
|
|
42
|
+
|
|
43
|
+
## Step 4: Add and Update E2E Tests
|
|
44
|
+
**Status**: Completed
|
|
45
|
+
|
|
46
|
+
**Tasks:**
|
|
47
|
+
- Update existing E2E tests (e.g., `src/cli/e2e/daemon.test.ts`, `src/cli/e2e/export-lite-func.test.ts`, `src/cli/e2e/requests.test.ts`) if they explicitly check for the hardcoded `CLAW_API_TOKEN` but shouldn't, or update them to verify default behavior remains intact.
|
|
48
|
+
- Add a new specific test case configuring an agent with both `apiTokenEnvVar` and `apiUrlEnvVar`.
|
|
49
|
+
- Verify that the daemon correctly injects the custom variables and the pointer variables (`CLAW_LITE_API_VAR`, `CLAW_LITE_URL_VAR`).
|
|
50
|
+
- Verify that an invocation of `clawmini-lite` via the CLI or mock successfully authenticates using these redirected variables.
|
|
51
|
+
|
|
52
|
+
**Verification:**
|
|
53
|
+
- Run `npm run format` and `npm run lint:fix`.
|
|
54
|
+
- Run `npm run validate` to verify all new and existing tests pass successfully.
|
package/napkin.md
CHANGED
|
@@ -23,3 +23,4 @@
|
|
|
23
23
|
- **Fixing CI missing optional dependencies (e.g. `@rollup/rollup-linux-x64-gnu`)**: If GitHub Actions on Linux fails during `npm ci` because an optional dependency for Linux x64 is missing from `package-lock.json` (often created on macOS), run `rm -rf package-lock.json node_modules web/node_modules && npm install` to regenerate the lockfile with cross-platform optional dependencies included.
|
|
24
24
|
- **When mocking state modules like state.js**, ensure `vi.mock('./state.js', ...)` is at the top level and includes the correct return shapes so subsequent tests relying on default properties (like `channelChatMap`) don't fail.
|
|
25
25
|
- **When mocking discord.js Messages**, ensure they match the properties required by the code paths (e.g. `channelId`, `attachments`, `reply`).
|
|
26
|
+
- **When you need to append content to files**, NEVER use `cat << EOF >>` inside a `run_shell_command`. This violates critical safety instructions and often fails or is insecure. Always use the native `read_file` combined with `write_file` or the `replace` tool to perform file modifications.
|
package/package.json
CHANGED
|
@@ -530,7 +530,7 @@ describe('Google Chat Adapter Client', () => {
|
|
|
530
530
|
|
|
531
531
|
// Override the list mock for this test
|
|
532
532
|
const { google } = await import('googleapis');
|
|
533
|
-
|
|
533
|
+
|
|
534
534
|
vi.mocked(google.chat({ version: 'v1' }).spaces.messages.list).mockResolvedValueOnce({
|
|
535
535
|
data: { messages: [{ sender: { type: 'BOT' } }] },
|
|
536
536
|
} as any);
|
|
@@ -316,4 +316,107 @@ describe('E2E Daemon and Web Tests', () => {
|
|
|
316
316
|
fs.writeFileSync(settingsPath, originalSettings);
|
|
317
317
|
await runCli(['up']);
|
|
318
318
|
}, 15000);
|
|
319
|
+
|
|
320
|
+
it('should inject custom env vars and pointers when configured, and lite should work', async () => {
|
|
321
|
+
await runCli(['down']);
|
|
322
|
+
const settingsPath = path.resolve(e2eDir, '.clawmini/settings.json');
|
|
323
|
+
let originalSettings = '{}';
|
|
324
|
+
if (fs.existsSync(settingsPath)) {
|
|
325
|
+
originalSettings = fs.readFileSync(settingsPath, 'utf8');
|
|
326
|
+
}
|
|
327
|
+
fs.writeFileSync(
|
|
328
|
+
settingsPath,
|
|
329
|
+
JSON.stringify({
|
|
330
|
+
...JSON.parse(originalSettings),
|
|
331
|
+
api: { host: '127.0.0.1', port: 3006 },
|
|
332
|
+
})
|
|
333
|
+
);
|
|
334
|
+
await runCli(['up']);
|
|
335
|
+
|
|
336
|
+
await runCli(['agents', 'add', 'custom-env-dumper', '--dir', 'custom-env-dumper']);
|
|
337
|
+
const agentSettingsPath = path.resolve(
|
|
338
|
+
e2eDir,
|
|
339
|
+
'.clawmini/agents/custom-env-dumper/settings.json'
|
|
340
|
+
);
|
|
341
|
+
fs.mkdirSync(path.dirname(agentSettingsPath), { recursive: true });
|
|
342
|
+
|
|
343
|
+
// Create the actual agent working directory so spawn doesn't fail with ENOENT
|
|
344
|
+
const agentWorkingDir = path.resolve(e2eDir, 'custom-env-dumper');
|
|
345
|
+
fs.mkdirSync(agentWorkingDir, { recursive: true });
|
|
346
|
+
|
|
347
|
+
const dumperScript = process.platform === 'win32' ? 'set > env.txt' : 'env > env.txt';
|
|
348
|
+
|
|
349
|
+
fs.writeFileSync(
|
|
350
|
+
agentSettingsPath,
|
|
351
|
+
JSON.stringify({
|
|
352
|
+
apiTokenEnvVar: 'MY_CUSTOM_TOKEN',
|
|
353
|
+
apiUrlEnvVar: 'MY_CUSTOM_URL',
|
|
354
|
+
commands: {
|
|
355
|
+
new: dumperScript,
|
|
356
|
+
},
|
|
357
|
+
})
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
await runCli(['chats', 'add', 'custom-env-chat']);
|
|
361
|
+
const { stdout, stderr, code } = await runCli([
|
|
362
|
+
'messages',
|
|
363
|
+
'send',
|
|
364
|
+
'dump custom',
|
|
365
|
+
'--chat',
|
|
366
|
+
'custom-env-chat',
|
|
367
|
+
'--agent',
|
|
368
|
+
'custom-env-dumper',
|
|
369
|
+
]);
|
|
370
|
+
if (code !== 0) {
|
|
371
|
+
console.error('send failed:', stdout, stderr);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
375
|
+
|
|
376
|
+
const chatLogPath = path.resolve(e2eDir, '.clawmini/chats/custom-env-chat/chat.jsonl');
|
|
377
|
+
expect(fs.existsSync(chatLogPath)).toBe(true);
|
|
378
|
+
|
|
379
|
+
const envTxtPath = path.resolve(agentWorkingDir, 'env.txt');
|
|
380
|
+
expect(fs.existsSync(envTxtPath)).toBe(true);
|
|
381
|
+
const envContent = fs.readFileSync(envTxtPath, 'utf8');
|
|
382
|
+
|
|
383
|
+
expect(envContent).toContain('CLAW_LITE_API_VAR=MY_CUSTOM_TOKEN');
|
|
384
|
+
expect(envContent).toContain('CLAW_LITE_URL_VAR=MY_CUSTOM_URL');
|
|
385
|
+
expect(envContent).toContain('MY_CUSTOM_URL=http://127.0.0.1:3006');
|
|
386
|
+
expect(envContent).toContain('MY_CUSTOM_TOKEN=');
|
|
387
|
+
|
|
388
|
+
// Verify lite works with the dynamically configured vars
|
|
389
|
+
const urlMatch = envContent.match(/MY_CUSTOM_URL=(.+)/);
|
|
390
|
+
const tokenMatch = envContent.match(/MY_CUSTOM_TOKEN=(.+)/);
|
|
391
|
+
|
|
392
|
+
expect(urlMatch).toBeTruthy();
|
|
393
|
+
expect(tokenMatch).toBeTruthy();
|
|
394
|
+
|
|
395
|
+
const envUrl = urlMatch![1]!.trim();
|
|
396
|
+
const envToken = tokenMatch![1]!.trim();
|
|
397
|
+
|
|
398
|
+
const litePath = path.resolve(__dirname, '../../../dist/cli/lite.mjs');
|
|
399
|
+
const replyProcess = spawn('node', [litePath, 'reply', 'hello from custom env'], {
|
|
400
|
+
env: {
|
|
401
|
+
...process.env,
|
|
402
|
+
MY_CUSTOM_URL: envUrl,
|
|
403
|
+
MY_CUSTOM_TOKEN: envToken,
|
|
404
|
+
CLAW_LITE_URL_VAR: 'MY_CUSTOM_URL',
|
|
405
|
+
CLAW_LITE_API_VAR: 'MY_CUSTOM_TOKEN',
|
|
406
|
+
},
|
|
407
|
+
cwd: agentWorkingDir,
|
|
408
|
+
});
|
|
409
|
+
let replyStdout = '';
|
|
410
|
+
replyProcess.stdout.on('data', (d) => (replyStdout += d.toString()));
|
|
411
|
+
replyProcess.stderr.on('data', (d) => (replyStdout += d.toString()));
|
|
412
|
+
await new Promise((resolve) => replyProcess.on('close', resolve));
|
|
413
|
+
expect(replyStdout).toContain('Reply message appended');
|
|
414
|
+
|
|
415
|
+
const chatLogContentReply = fs.readFileSync(chatLogPath, 'utf8');
|
|
416
|
+
expect(chatLogContentReply).toContain('hello from custom env');
|
|
417
|
+
|
|
418
|
+
await runCli(['down']);
|
|
419
|
+
fs.writeFileSync(settingsPath, originalSettings);
|
|
420
|
+
await runCli(['up']);
|
|
421
|
+
}, 15000);
|
|
319
422
|
});
|
|
@@ -19,8 +19,11 @@ describe('E2E Messages Tests', () => {
|
|
|
19
19
|
expect(code).toBe(0);
|
|
20
20
|
expect(stdout).toContain('Message sent successfully.');
|
|
21
21
|
|
|
22
|
-
const
|
|
23
|
-
|
|
22
|
+
const chatLog = fs.readFileSync(
|
|
23
|
+
path.resolve(e2eDir, '.clawmini/chats/default/chat.jsonl'),
|
|
24
|
+
'utf8'
|
|
25
|
+
);
|
|
26
|
+
expect(chatLog).toContain('e2e test message');
|
|
24
27
|
});
|
|
25
28
|
|
|
26
29
|
it('should send a message to a specific chat', async () => {
|