nao-core 0.0.12__py3-none-any.whl → 0.0.15__py3-none-any.whl

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.
Files changed (33) hide show
  1. nao_core/__init__.py +1 -1
  2. nao_core/bin/db.sqlite +0 -0
  3. nao_core/bin/fastapi/main.py +102 -0
  4. nao_core/bin/public/assets/_chatId-z5gRlor1.js +1 -0
  5. nao_core/bin/public/assets/chat-messages-DUR3D342.js +1 -0
  6. nao_core/bin/public/assets/index-BDlcD_HE.js +1 -0
  7. nao_core/bin/public/assets/index-Bc7icYyJ.css +1 -0
  8. nao_core/bin/public/assets/index-CGg3ZQH6.js +49 -0
  9. nao_core/bin/public/assets/{login-CGCfd7iQ.js → login-D87n9R5V.js} +1 -1
  10. nao_core/bin/public/assets/signinForm-9PY1Lvqj.js +1 -0
  11. nao_core/bin/public/assets/{signup-BGjbIX9B.js → signup-B7NC1g08.js} +1 -1
  12. nao_core/bin/public/favicon.ico +0 -0
  13. nao_core/bin/public/index.html +3 -3
  14. nao_core/commands/chat.py +67 -25
  15. nao_core/commands/debug.py +0 -4
  16. nao_core/commands/init.py +3 -3
  17. nao_core/commands/sync.py +273 -44
  18. nao_core/config/__init__.py +13 -0
  19. nao_core/{config.py → config/base.py} +4 -66
  20. nao_core/config/databases/__init__.py +29 -0
  21. nao_core/config/databases/base.py +72 -0
  22. nao_core/config/databases/bigquery.py +42 -0
  23. nao_core/config/llm/__init__.py +16 -0
  24. {nao_core-0.0.12.dist-info → nao_core-0.0.15.dist-info}/METADATA +3 -1
  25. nao_core-0.0.15.dist-info/RECORD +39 -0
  26. nao_core/bin/public/assets/index-BUcR0FCx.css +0 -1
  27. nao_core/bin/public/assets/index-DDQ8i103.js +0 -14
  28. nao_core/bin/public/assets/index-nOBqrovO.js +0 -36
  29. nao_core/bin/public/assets/signinForm-BGrBZeLW.js +0 -1
  30. nao_core-0.0.12.dist-info/RECORD +0 -31
  31. {nao_core-0.0.12.dist-info → nao_core-0.0.15.dist-info}/WHEEL +0 -0
  32. {nao_core-0.0.12.dist-info → nao_core-0.0.15.dist-info}/entry_points.txt +0 -0
  33. {nao_core-0.0.12.dist-info → nao_core-0.0.15.dist-info}/licenses/LICENSE +0 -0
@@ -1 +1 @@
1
- import{u,r as o,j as c,a as d}from"./index-DDQ8i103.js";import{S as g}from"./signinForm-BGrBZeLW.js";function w(){const r=u(),[e,s]=o.useState({email:"",password:""}),[n,t]=o.useState(""),i=async a=>{a.preventDefault(),t(""),await d.email({email:e.email,password:e.password},{onSuccess:()=>{r({to:"/"})},onError:p=>{t(p.error.message)}})},m=a=>{s({...e,[a.target.name]:a.target.value})},l=[{id:"email",name:"email",type:"email",label:"Email",placeholder:"Enter your email"},{id:"password",name:"password",type:"password",label:"Password",placeholder:"Enter your password"}];return c.jsx(g,{title:"Sign In",fields:l,formData:e,onSubmit:i,onChange:m,submitButtonText:"Sign In",footerText:"Don't have an account?",footerLinkText:"Sign up",footerLinkTo:"/signup",error:n})}export{w as component};
1
+ import{u,r as o,j as c}from"./index-CGg3ZQH6.js";import{S as d,a as g}from"./signinForm-9PY1Lvqj.js";function w(){const r=u(),[e,s]=o.useState({email:"",password:""}),[n,t]=o.useState(""),i=async a=>{a.preventDefault(),t(""),await g.email({email:e.email,password:e.password},{onSuccess:()=>{r({to:"/"})},onError:p=>{t(p.error.message)}})},m=a=>{s({...e,[a.target.name]:a.target.value})},l=[{id:"email",name:"email",type:"email",label:"Email",placeholder:"Enter your email"},{id:"password",name:"password",type:"password",label:"Password",placeholder:"Enter your password"}];return c.jsx(d,{title:"Sign In",fields:l,formData:e,onSubmit:i,onChange:m,submitButtonText:"Sign In",footerText:"Don't have an account?",footerLinkText:"Sign up",footerLinkTo:"/signup",error:n})}export{w as component};
@@ -0,0 +1 @@
1
+ import{c as ve,r as H,j as g,a as ae,b as Te,t as Pe,B as le,L as Le}from"./index-CGg3ZQH6.js";const Ie=[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]],Ne=ve("eye-off",Ie);const Ae=[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]],Ue=ve("eye",Ae);function Ce({className:e,type:t,...n}){const[r,s]=H.useState(!1),l=t==="password",o=l&&r?"text":t;return l?g.jsxs("div",{className:"relative",children:[g.jsx("input",{type:o,"data-slot":"input",className:ae("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm","focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]","aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive","pr-10",e),...n}),g.jsx("button",{type:"button",onClick:()=>s(!r),className:"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",tabIndex:-1,children:r?g.jsx(Ne,{size:16}):g.jsx(Ue,{size:16})})]}):g.jsx("input",{type:t,"data-slot":"input",className:ae("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm","focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]","aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",e),...n})}var je={},ue={};const J=Object.create(null),q=e=>je||globalThis.Deno?.env.toObject()||globalThis.__env__||(e?J:globalThis),E=new Proxy(J,{get(e,t){return q()[t]??J[t]},has(e,t){return t in q()||t in J},set(e,t,n){const r=q(!0);return r[t]=n,!0},deleteProperty(e,t){if(!t)return!1;const n=q(!0);return delete n[t],!0},ownKeys(){const e=q(!0);return Object.keys(e)}});function m(e,t){return typeof process<"u"&&ue?ue[e]??t:typeof Deno<"u"?Deno.env.get(e)??t:typeof Bun<"u"?Bun.env[e]??t:t}const F=1,y=4,I=8,S=24,ce={eterm:y,cons25:y,console:y,cygwin:y,dtterm:y,gnome:y,hurd:y,jfbterm:y,konsole:y,kterm:y,mlterm:y,mosh:S,putty:y,st:y,"rxvt-unicode-24bit":S,terminator:S,"xterm-kitty":S},Me=new Map(Object.entries({APPVEYOR:I,BUILDKITE:I,CIRCLECI:S,DRONE:I,GITEA_ACTIONS:S,GITHUB_ACTIONS:S,GITLAB_CI:I,TRAVIS:I})),ke=[/ansi/,/color/,/linux/,/direct/,/^con[0-9]*x[0-9]/,/^rxvt/,/^screen/,/^xterm/,/^vt100/,/^vt220/];function Be(){if(m("FORCE_COLOR")!==void 0)switch(m("FORCE_COLOR")){case"":case"1":case"true":return y;case"2":return I;case"3":return S;default:return F}if(m("NODE_DISABLE_COLORS")!==void 0&&m("NODE_DISABLE_COLORS")!==""||m("NO_COLOR")!==void 0&&m("NO_COLOR")!==""||m("TERM")==="dumb")return F;if(m("TMUX"))return S;if("TF_BUILD"in E&&"AGENT_NAME"in E)return y;if("CI"in E){for(const{0:e,1:t}of Me)if(e in E)return t;return m("CI_NAME")==="codeship"?I:F}if("TEAMCITY_VERSION"in E)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.exec(m("TEAMCITY_VERSION"))!==null?y:F;switch(m("TERM_PROGRAM")){case"iTerm.app":return!m("TERM_PROGRAM_VERSION")||/^[0-2]\./.exec(m("TERM_PROGRAM_VERSION"))!==null?I:S;case"HyperTerm":case"MacTerm":return S;case"Apple_Terminal":return I}if(m("COLORTERM")==="truecolor"||m("COLORTERM")==="24bit")return S;if(m("TERM")){if(/truecolor/.exec(m("TERM"))!==null)return S;if(/^xterm-256/.exec(m("TERM"))!==null)return I;const e=m("TERM").toLowerCase();if(ce[e])return ce[e];if(ke.some(t=>t.exec(e)!==null))return y}return m("COLORTERM")?y:F}const N={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",fg:{red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m"}},re=["debug","info","success","warn","error"];function qe(e,t){return re.indexOf(t)>=re.indexOf(e)}const Fe={info:N.fg.blue,success:N.fg.green,warn:N.fg.yellow,error:N.fg.red,debug:N.fg.magenta},De=(e,t,n)=>{const r=new Date().toISOString();return n?`${N.dim}${r}${N.reset} ${Fe[e]}${e.toUpperCase()}${N.reset} ${N.bright}[Better Auth]:${N.reset} ${t}`:`${r} ${e.toUpperCase()} [Better Auth]: ${t}`},$e=e=>{const t="error",n=Be()!==1,r=(s,l,o=[])=>{if(!qe(t,s))return;const d=De(s,l,n);{s==="error"?console.error(d,...o):s==="warn"?console.warn(d,...o):console.log(d,...o);return}};return{...Object.fromEntries(re.map(s=>[s,(...[l,...o])=>r(s,l,o)])),get level(){return t}}};$e();function Ve(e){return e.charAt(0).toUpperCase()+e.slice(1)}var Y=class extends Error{constructor(e,t){super(e),this.name="BetterAuthError",this.message=e,this.cause=t,this.stack=""}};function Ge(e){try{return(new URL(e).pathname.replace(/\/+$/,"")||"/")!=="/"}catch{throw new Y(`Invalid base URL: ${e}. Please provide a valid base URL.`)}}function We(e){try{const t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Y(`Invalid base URL: ${e}. URL must include 'http://' or 'https://'`)}catch(t){throw t instanceof Y?t:new Y(`Invalid base URL: ${e}. Please provide a valid base URL.`,String(t))}}function X(e,t="/api/auth"){if(We(e),Ge(e))return e;const n=e.replace(/\/+$/,"");return!t||t==="/"?n:(t=t.startsWith("/")?t:`/${t}`,`${n}${t}`)}function He(e,t,n,r,s){if(e)return X(e,t);{const l=E.BETTER_AUTH_URL||E.NEXT_PUBLIC_BETTER_AUTH_URL||E.PUBLIC_BETTER_AUTH_URL||E.NUXT_PUBLIC_BETTER_AUTH_URL||E.NUXT_PUBLIC_AUTH_URL||(E.BASE_URL!=="/"?E.BASE_URL:void 0);if(l)return X(l,t)}if(typeof window<"u"&&window.location)return X(window.location.origin,t)}const Je={id:"redirect",name:"Redirect",hooks:{onSuccess(e){if(e.data?.url&&e.data?.redirect&&typeof window<"u"&&window.location&&window.location)try{window.location.href=e.data.url}catch{}}}},Ye={proto:/"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/,constructor:/"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/,protoShort:/"__proto__"\s*:/,constructorShort:/"constructor"\s*:/},ze=/^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/,fe={true:!0,false:!1,null:null,undefined:void 0,nan:NaN,infinity:Number.POSITIVE_INFINITY,"-infinity":Number.NEGATIVE_INFINITY},Qe=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,7}))?(?:Z|([+-])(\d{2}):(\d{2}))$/;function Xe(e){return e instanceof Date&&!isNaN(e.getTime())}function Ze(e){const t=Qe.exec(e);if(!t)return null;const[,n,r,s,l,o,d,i,u,a,f]=t;let h=new Date(Date.UTC(parseInt(n,10),parseInt(r,10)-1,parseInt(s,10),parseInt(l,10),parseInt(o,10),parseInt(d,10),i?parseInt(i.padEnd(3,"0"),10):0));if(u){const v=(parseInt(a,10)*60+parseInt(f,10))*(u==="+"?-1:1);h.setUTCMinutes(h.getUTCMinutes()+v)}return Xe(h)?h:null}function Ke(e,t={}){const{strict:n=!1,warnings:r=!1,reviver:s,parseDates:l=!0}=t;if(typeof e!="string")return e;const o=e.trim();if(o.length>0&&o[0]==='"'&&o.endsWith('"')&&!o.slice(1,-1).includes('"'))return o.slice(1,-1);const d=o.toLowerCase();if(d.length<=9&&d in fe)return fe[d];if(!ze.test(o)){if(n)throw new SyntaxError("[better-json] Invalid JSON");return e}if(Object.entries(Ye).some(([i,u])=>{const a=u.test(o);return a&&r&&console.warn(`[better-json] Detected potential prototype pollution attempt using ${i} pattern`),a})&&n)throw new Error("[better-json] Potential prototype pollution attempt detected");try{return JSON.parse(o,(u,a)=>{if(u==="__proto__"||u==="constructor"&&a&&typeof a=="object"&&"prototype"in a){r&&console.warn(`[better-json] Dropping "${u}" key to prevent prototype pollution`);return}if(l&&typeof a=="string"){const f=Ze(a);if(f)return f}return s?s(u,a):a})}catch(i){if(n)throw i;return e}}function et(e,t={strict:!0}){return Ke(e,t)}let T=[],k=0;const V=4,be=e=>{let t=[],n={get(){return n.lc||n.listen(()=>{})(),n.value},lc:0,listen(r){return n.lc=t.push(r),()=>{for(let l=k+V;l<T.length;)T[l]===r?T.splice(l,V):l+=V;let s=t.indexOf(r);~s&&(t.splice(s,1),--n.lc||n.off())}},notify(r,s){let l=!T.length;for(let o of t)T.push(o,n.value,r,s);if(l){for(k=0;k<T.length;k+=V)T[k](T[k+1],T[k+2],T[k+3]);T.length=0}},off(){},set(r){let s=n.value;s!==r&&(n.value=r,n.notify(s))},subscribe(r){let s=n.listen(r);return r(n.value),s},value:e};return n},tt=5,G=6,W=10;let nt=(e,t,n,r)=>(e.events=e.events||{},e.events[n+W]||(e.events[n+W]=r(s=>{e.events[n].reduceRight((l,o)=>(o(l),l),{shared:{},...s})})),e.events[n]=e.events[n]||[],e.events[n].push(t),()=>{let s=e.events[n],l=s.indexOf(t);s.splice(l,1),s.length||(delete e.events[n],e.events[n+W](),delete e.events[n+W])}),rt=1e3,we=(e,t)=>nt(e,r=>{let s=t(r);s&&e.events[G].push(s)},tt,r=>{let s=e.listen;e.listen=(...o)=>(!e.lc&&!e.active&&(e.active=!0,r()),s(...o));let l=e.off;return e.events[G]=[],e.off=()=>{l(),setTimeout(()=>{if(e.active&&!e.lc){e.active=!1;for(let o of e.events[G])o();e.events[G]=[]}},rt)},()=>{e.listen=s,e.off=l}});function st(e,t,n){let r=new Set(t).add(void 0);return e.listen((s,l,o)=>{r.has(o)&&n(s,l,o)})}const it=()=>typeof window>"u",ot=(e,t,n,r)=>{const s=be({data:null,error:null,isPending:!0,isRefetching:!1,refetch:d=>l(d)}),l=async d=>new Promise(i=>{const u=typeof r=="function"?r({data:s.get().data,error:s.get().error,isPending:s.get().isPending}):r;n(t,{...u,query:{...u?.query,...d?.query},async onSuccess(a){s.set({data:a.data,error:null,isPending:!1,isRefetching:!1,refetch:s.value.refetch}),await u?.onSuccess?.(a)},async onError(a){const{request:f}=a,h=typeof f.retry=="number"?f.retry:f.retry?.attempts,v=f.retryAttempt||0;h&&v<h||(s.set({error:a.error,data:null,isPending:!1,isRefetching:!1,refetch:s.value.refetch}),await u?.onError?.(a))},async onRequest(a){const f=s.get();s.set({isPending:f.data===null,data:f.data,error:null,isRefetching:!0,refetch:s.value.refetch}),await u?.onRequest?.(a)}}).catch(a=>{s.set({error:a,data:null,isPending:!1,isRefetching:!1,refetch:s.value.refetch})}).finally(()=>{i(void 0)})});e=Array.isArray(e)?e:[e];let o=!1;for(const d of e)d.subscribe(async()=>{it()||(o?await l():we(s,()=>{const i=setTimeout(async()=>{o||(await l(),o=!0)},0);return()=>{s.off(),d.off(),clearTimeout(i)}}))});return s},Z=Symbol.for("better-auth:broadcast-channel"),at=()=>Math.floor(Date.now()/1e3);var lt=class{listeners=new Set;name;constructor(e="better-auth.message"){this.name=e}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}post(e){if(!(typeof window>"u"))try{localStorage.setItem(this.name,JSON.stringify({...e,timestamp:at()}))}catch{}}setup(){if(typeof window>"u"||typeof window.addEventListener>"u")return()=>{};const e=t=>{if(t.key!==this.name)return;const n=JSON.parse(t.newValue??"{}");n?.event!=="session"||!n?.data||this.listeners.forEach(r=>r(n))};return window.addEventListener("storage",e),()=>{window.removeEventListener("storage",e)}}};function K(e="better-auth.message"){return globalThis[Z]||(globalThis[Z]=new lt(e)),globalThis[Z]}const ee=Symbol.for("better-auth:focus-manager");var ut=class{listeners=new Set;subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}setFocused(e){this.listeners.forEach(t=>t(e))}setup(){if(typeof window>"u"||typeof document>"u"||typeof window.addEventListener>"u")return()=>{};const e=()=>{document.visibilityState==="visible"&&this.setFocused(!0)};return document.addEventListener("visibilitychange",e,!1),()=>{document.removeEventListener("visibilitychange",e,!1)}}};function de(){return globalThis[ee]||(globalThis[ee]=new ut),globalThis[ee]}const te=Symbol.for("better-auth:online-manager");var ct=class{listeners=new Set;isOnline=typeof navigator<"u"?navigator.onLine:!0;subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}setOnline(e){this.isOnline=e,this.listeners.forEach(t=>t(e))}setup(){if(typeof window>"u"||typeof window.addEventListener>"u")return()=>{};const e=()=>this.setOnline(!0),t=()=>this.setOnline(!1);return window.addEventListener("online",e,!1),window.addEventListener("offline",t,!1),()=>{window.removeEventListener("online",e,!1),window.removeEventListener("offline",t,!1)}}};function ne(){return globalThis[te]||(globalThis[te]=new ct),globalThis[te]}const B=()=>Math.floor(Date.now()/1e3),ft=5;function dt(e){const{sessionAtom:t,sessionSignal:n,$fetch:r,options:s={}}=e,l=s.sessionOptions?.refetchInterval??0,o=s.sessionOptions?.refetchOnWindowFocus??!0,d=s.sessionOptions?.refetchWhenOffline??!1,i={lastSync:0,lastSessionRequest:0,cachedSession:void 0},u=()=>d||ne().isOnline,a=b=>{if(!u())return;if(b?.event==="storage"){i.lastSync=B(),n.set(!n.get());return}const R=t.get();if(b?.event==="poll"){i.lastSessionRequest=B(),r("/get-session").then(c=>{c.error?t.set({...R,data:null,error:c.error}):t.set({...R,data:c.data,error:null}),i.lastSync=B(),n.set(!n.get())}).catch(()=>{});return}if(b?.event==="visibilitychange"){if(B()-i.lastSessionRequest<ft)return;i.lastSessionRequest=B()}(R?.data===null||R?.data===void 0||b?.event==="visibilitychange")&&(i.lastSync=B(),n.set(!n.get()))},f=b=>{K().post({event:"session",data:{trigger:b},clientId:Math.random().toString(36).substring(7)})},h=()=>{l&&l>0&&(i.pollInterval=setInterval(()=>{t.get()?.data&&a({event:"poll"})},l*1e3))},v=()=>{i.unsubscribeBroadcast=K().subscribe(()=>{a({event:"storage"})})},_=()=>{o&&(i.unsubscribeFocus=de().subscribe(()=>{a({event:"visibilitychange"})}))},j=()=>{i.unsubscribeOnline=ne().subscribe(b=>{b&&a({event:"visibilitychange"})})};return{init:()=>{h(),v(),_(),j(),K().setup(),de().setup(),ne().setup()},cleanup:()=>{i.pollInterval&&(clearInterval(i.pollInterval),i.pollInterval=void 0),i.unsubscribeBroadcast&&(i.unsubscribeBroadcast(),i.unsubscribeBroadcast=void 0),i.unsubscribeFocus&&(i.unsubscribeFocus(),i.unsubscribeFocus=void 0),i.unsubscribeOnline&&(i.unsubscribeOnline(),i.unsubscribeOnline=void 0),i.lastSync=0,i.lastSessionRequest=0,i.cachedSession=void 0},triggerRefetch:a,broadcastSessionUpdate:f}}function ht(e,t){const n=be(!1),r=ot(n,"/get-session",e,{method:"GET"});return we(r,()=>{const s=dt({sessionAtom:r,sessionSignal:n,$fetch:e,options:t});return s.init(),()=>{s.cleanup()}}),{session:r,$sessionSignal:n}}var pt=Object.defineProperty,gt=Object.defineProperties,mt=Object.getOwnPropertyDescriptors,he=Object.getOwnPropertySymbols,yt=Object.prototype.hasOwnProperty,vt=Object.prototype.propertyIsEnumerable,pe=(e,t,n)=>t in e?pt(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,P=(e,t)=>{for(var n in t||(t={}))yt.call(t,n)&&pe(e,n,t[n]);if(he)for(var n of he(t))vt.call(t,n)&&pe(e,n,t[n]);return e},L=(e,t)=>gt(e,mt(t)),bt=class extends Error{constructor(e,t,n){super(t||e.toString(),{cause:n}),this.status=e,this.statusText=t,this.error=n,Error.captureStackTrace(this,this.constructor)}},wt=async(e,t)=>{var n,r,s,l,o,d;let i=t||{};const u={onRequest:[t?.onRequest],onResponse:[t?.onResponse],onSuccess:[t?.onSuccess],onError:[t?.onError],onRetry:[t?.onRetry]};if(!t||!t?.plugins)return{url:e,options:i,hooks:u};for(const a of t?.plugins||[]){if(a.init){const f=await((n=a.init)==null?void 0:n.call(a,e.toString(),t));i=f.options||i,e=f.url}u.onRequest.push((r=a.hooks)==null?void 0:r.onRequest),u.onResponse.push((s=a.hooks)==null?void 0:s.onResponse),u.onSuccess.push((l=a.hooks)==null?void 0:l.onSuccess),u.onError.push((o=a.hooks)==null?void 0:o.onError),u.onRetry.push((d=a.hooks)==null?void 0:d.onRetry)}return{url:e,options:i,hooks:u}},ge=class{constructor(e){this.options=e}shouldAttemptRetry(e,t){return this.options.shouldRetry?Promise.resolve(e<this.options.attempts&&this.options.shouldRetry(t)):Promise.resolve(e<this.options.attempts)}getDelay(){return this.options.delay}},Ot=class{constructor(e){this.options=e}shouldAttemptRetry(e,t){return this.options.shouldRetry?Promise.resolve(e<this.options.attempts&&this.options.shouldRetry(t)):Promise.resolve(e<this.options.attempts)}getDelay(e){return Math.min(this.options.maxDelay,this.options.baseDelay*2**e)}};function Rt(e){if(typeof e=="number")return new ge({type:"linear",attempts:e,delay:1e3});switch(e.type){case"linear":return new ge(e);case"exponential":return new Ot(e);default:throw new Error("Invalid retry strategy")}}var _t=async e=>{const t={},n=async r=>typeof r=="function"?await r():r;if(e?.auth){if(e.auth.type==="Bearer"){const r=await n(e.auth.token);if(!r)return t;t.authorization=`Bearer ${r}`}else if(e.auth.type==="Basic"){const[r,s]=await Promise.all([n(e.auth.username),n(e.auth.password)]);if(!r||!s)return t;t.authorization=`Basic ${btoa(`${r}:${s}`)}`}else if(e.auth.type==="Custom"){const[r,s]=await Promise.all([n(e.auth.prefix),n(e.auth.value)]);if(!s)return t;t.authorization=`${r??""} ${s}`}}return t},St=/^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i;function xt(e){const t=e.headers.get("content-type"),n=new Set(["image/svg","application/xml","application/xhtml","application/html"]);if(!t)return"json";const r=t.split(";").shift()||"";return St.test(r)?"json":n.has(r)||r.startsWith("text/")?"text":"blob"}function Et(e){try{return JSON.parse(e),!0}catch{return!1}}function se(e){if(e===void 0)return!1;const t=typeof e;return t==="string"||t==="number"||t==="boolean"||t===null?!0:t!=="object"?!1:Array.isArray(e)?!0:e.buffer?!1:e.constructor&&e.constructor.name==="Object"||typeof e.toJSON=="function"}function me(e){try{return JSON.parse(e)}catch{return e}}function ye(e){return typeof e=="function"}function Tt(e){if(e?.customFetchImpl)return e.customFetchImpl;if(typeof globalThis<"u"&&ye(globalThis.fetch))return globalThis.fetch;if(typeof window<"u"&&ye(window.fetch))return window.fetch;throw new Error("No fetch implementation found")}async function Pt(e){const t=new Headers(e?.headers),n=await _t(e);for(const[r,s]of Object.entries(n||{}))t.set(r,s);if(!t.has("content-type")){const r=Lt(e?.body);r&&t.set("content-type",r)}return t}function Lt(e){return se(e)?"application/json":null}function It(e){if(!e?.body)return null;const t=new Headers(e?.headers);if(se(e.body)&&!t.has("content-type")){for(const[n,r]of Object.entries(e?.body))r instanceof Date&&(e.body[n]=r.toISOString());return JSON.stringify(e.body)}return t.has("content-type")&&t.get("content-type")==="application/x-www-form-urlencoded"&&se(e.body)?new URLSearchParams(e.body).toString():e.body}function Nt(e,t){var n;if(t?.method)return t.method.toUpperCase();if(e.startsWith("@")){const r=(n=e.split("@")[1])==null?void 0:n.split("/")[0];return Re.includes(r)?r.toUpperCase():t?.body?"POST":"GET"}return t?.body?"POST":"GET"}function At(e,t){let n;return!e?.signal&&e?.timeout&&(n=setTimeout(()=>t?.abort(),e?.timeout)),{abortTimeout:n,clearTimeout:()=>{n&&clearTimeout(n)}}}var Ut=class Oe extends Error{constructor(t,n){super(n||JSON.stringify(t,null,2)),this.issues=t,Object.setPrototypeOf(this,Oe.prototype)}};async function z(e,t){const n=await e["~standard"].validate(t);if(n.issues)throw new Ut(n.issues);return n.value}var Re=["get","post","put","patch","delete"],Ct=e=>({id:"apply-schema",name:"Apply Schema",version:"1.0.0",async init(t,n){var r,s,l,o;const d=((s=(r=e.plugins)==null?void 0:r.find(i=>{var u;return(u=i.schema)!=null&&u.config?t.startsWith(i.schema.config.baseURL||"")||t.startsWith(i.schema.config.prefix||""):!1}))==null?void 0:s.schema)||e.schema;if(d){let i=t;(l=d.config)!=null&&l.prefix&&i.startsWith(d.config.prefix)&&(i=i.replace(d.config.prefix,""),d.config.baseURL&&(t=t.replace(d.config.prefix,d.config.baseURL))),(o=d.config)!=null&&o.baseURL&&i.startsWith(d.config.baseURL)&&(i=i.replace(d.config.baseURL,""));const u=d.schema[i];if(u){let a=L(P({},n),{method:u.method,output:u.output});return n?.disableValidation||(a=L(P({},a),{body:u.input?await z(u.input,n?.body):n?.body,params:u.params?await z(u.params,n?.params):n?.params,query:u.query?await z(u.query,n?.query):n?.query})),{url:t,options:a}}}return{url:t,options:n}}}),jt=e=>{async function t(n,r){const s=L(P(P({},e),r),{plugins:[...e?.plugins||[],Ct(e||{}),...r?.plugins||[]]});if(e?.catchAllError)try{return await ie(n,s)}catch(l){return{data:null,error:{status:500,statusText:"Fetch Error",message:"Fetch related error. Captured by catchAllError option. See error property for more details.",error:l}}}return await ie(n,s)}return t};function Mt(e,t){const{baseURL:n,params:r,query:s}=t||{query:{},params:{},baseURL:""};let l=e.startsWith("http")?e.split("/").slice(0,3).join("/"):n||"";if(e.startsWith("@")){const f=e.toString().split("@")[1].split("/")[0];Re.includes(f)&&(e=e.replace(`@${f}/`,"/"))}l.endsWith("/")||(l+="/");let[o,d]=e.replace(l,"").split("?");const i=new URLSearchParams(d);for(const[f,h]of Object.entries(s||{})){if(h==null)continue;let v;if(typeof h=="string")v=h;else if(Array.isArray(h)){for(const _ of h)i.append(f,_);continue}else v=JSON.stringify(h);i.set(f,v)}if(r)if(Array.isArray(r)){const f=o.split("/").filter(h=>h.startsWith(":"));for(const[h,v]of f.entries()){const _=r[h];o=o.replace(v,_)}}else for(const[f,h]of Object.entries(r))o=o.replace(`:${f}`,String(h));o=o.split("/").map(encodeURIComponent).join("/"),o.startsWith("/")&&(o=o.slice(1));let u=i.toString();return u=u.length>0?`?${u}`.replace(/\+/g,"%20"):"",l.startsWith("http")?new URL(`${o}${u}`,l):`${l}${o}${u}`}var ie=async(e,t)=>{var n,r,s,l,o,d,i,u;const{hooks:a,url:f,options:h}=await wt(e,t),v=Tt(h),_=new AbortController,j=(n=h.signal)!=null?n:_.signal,O=Mt(f,h),M=It(h),b=await Pt(h),R=Nt(f,h);let c=L(P({},h),{url:O,headers:b,body:M,method:R,signal:j});for(const x of a.onRequest)if(x){const w=await x(c);typeof w=="object"&&w!==null&&(c=w)}("pipeTo"in c&&typeof c.pipeTo=="function"||typeof((r=t?.body)==null?void 0:r.pipe)=="function")&&("duplex"in c||(c.duplex="half"));const{clearTimeout:A}=At(h,_);let p=await v(c.url,c);A();const D={response:p,request:c};for(const x of a.onResponse)if(x){const w=await x(L(P({},D),{response:(s=t?.hookOptions)!=null&&s.cloneResponse?p.clone():p}));w instanceof Response?p=w:typeof w=="object"&&w!==null&&(p=w.response)}if(p.ok){if(!(c.method!=="HEAD"))return{data:"",error:null};const w=xt(p),U={data:null,response:p,request:c};if(w==="json"||w==="text"){const C=await p.text(),Ee=(l=c.jsonParser)!=null?l:me;U.data=await Ee(C)}else U.data=await p[w]();c?.output&&c.output&&!c.disableValidation&&(U.data=await z(c.output,U.data));for(const C of a.onSuccess)C&&await C(L(P({},U),{response:(o=t?.hookOptions)!=null&&o.cloneResponse?p.clone():p}));return t?.throw?U.data:{data:U.data,error:null}}const Se=(d=t?.jsonParser)!=null?d:me,$=await p.text(),oe=Et($),Q=oe?await Se($):null,xe={response:p,responseText:$,request:c,error:L(P({},Q),{status:p.status,statusText:p.statusText})};for(const x of a.onError)x&&await x(L(P({},xe),{response:(i=t?.hookOptions)!=null&&i.cloneResponse?p.clone():p}));if(t?.retry){const x=Rt(t.retry),w=(u=t.retryAttempt)!=null?u:0;if(await x.shouldAttemptRetry(w,p)){for(const C of a.onRetry)C&&await C(D);const U=x.getDelay(w);return await new Promise(C=>setTimeout(C,U)),await ie(e,L(P({},t),{retryAttempt:w+1}))}}if(t?.throw)throw new bt(p.status,p.statusText,oe?Q:$);return{data:null,error:L(P({},Q),{status:p.status,statusText:p.statusText})}};const kt=(e,t)=>{const n="credentials"in Request.prototype,r=He(e?.baseURL,e?.basePath)??"/api/auth",s=e?.plugins?.flatMap(c=>c.fetchPlugins).filter(c=>c!==void 0)||[],l={id:"lifecycle-hooks",name:"lifecycle-hooks",hooks:{onSuccess:e?.fetchOptions?.onSuccess,onError:e?.fetchOptions?.onError,onRequest:e?.fetchOptions?.onRequest,onResponse:e?.fetchOptions?.onResponse}},{onSuccess:o,onError:d,onRequest:i,onResponse:u,...a}=e?.fetchOptions||{},f=jt({baseURL:r,...n?{credentials:"include"}:{},method:"GET",jsonParser(c){return c?et(c,{strict:!1}):null},customFetchImpl:fetch,...a,plugins:[l,...a.plugins||[],...e?.disableDefaultFetchPlugins?[]:[Je],...s]}),{$sessionSignal:h,session:v}=ht(f,e),_=e?.plugins||[];let j={},O={$sessionSignal:h,session:v},M={"/sign-out":"POST","/revoke-sessions":"POST","/revoke-other-sessions":"POST","/delete-user":"POST"};const b=[{signal:"$sessionSignal",matcher(c){return c==="/sign-out"||c==="/update-user"||c==="/sign-up/email"||c==="/sign-in/email"||c==="/delete-user"||c==="/verify-email"||c==="/revoke-sessions"||c==="/revoke-session"||c==="/change-email"}}];for(const c of _)c.getAtoms&&Object.assign(O,c.getAtoms?.(f)),c.pathMethods&&Object.assign(M,c.pathMethods),c.atomListeners&&b.push(...c.atomListeners);const R={notify:c=>{O[c].set(!O[c].get())},listen:(c,A)=>{O[c].subscribe(A)},atoms:O};for(const c of _)c.getActions&&Object.assign(j,c.getActions?.(f,R,e));return{get baseURL(){return r},pluginsActions:j,pluginsAtoms:O,pluginPathMethods:M,atomListeners:b,$fetch:f,$store:R}};function Bt(e){return typeof e=="object"&&e!==null&&"get"in e&&typeof e.get=="function"&&"lc"in e&&typeof e.lc=="number"}function qt(e,t,n){const r=t[e],{fetchOptions:s,query:l,...o}=n||{};return r||(s?.method?s.method:o&&Object.keys(o).length>0?"POST":"GET")}function Ft(e,t,n,r,s){function l(o=[]){return new Proxy(function(){},{get(d,i){if(typeof i!="string"||i==="then"||i==="catch"||i==="finally")return;const u=[...o,i];let a=e;for(const f of u)if(a&&typeof a=="object"&&f in a)a=a[f];else{a=void 0;break}return typeof a=="function"||Bt(a)?a:l(u)},apply:async(d,i,u)=>{const a="/"+o.map(b=>b.replace(/[A-Z]/g,R=>`-${R.toLowerCase()}`)).join("/"),f=u[0]||{},h=u[1]||{},{query:v,fetchOptions:_,...j}=f,O={...h,..._},M=qt(a,n,f);return await t(a,{...O,body:M==="GET"?void 0:{...j,...O?.body||{}},query:v||O?.query,method:M,async onSuccess(b){if(await O?.onSuccess?.(b),!s||O.disableSignal)return;const R=s.filter(A=>A.matcher(a));if(!R.length)return;const c=new Set;for(const A of R){const p=r[A.signal];if(!p)return;if(c.has(A.signal))continue;c.add(A.signal);const D=p.get();setTimeout(()=>{p.set(!D)},10)}}})}})}return l()}function Dt(e,t={}){let n=H.useRef(e.get());const{keys:r,deps:s=[e,r]}=t;let l=H.useCallback(d=>{const i=u=>{n.current!==u&&(n.current=u,d())};return i(e.value),r?.length?st(e,r,i):e.listen(i)},s),o=()=>n.current;return H.useSyncExternalStore(l,o,o)}function $t(e){return`use${Ve(e)}`}function Vt(e){const{pluginPathMethods:t,pluginsActions:n,pluginsAtoms:r,$fetch:s,$store:l,atomListeners:o}=kt(e);let d={};for(const[i,u]of Object.entries(r))d[$t(i)]=()=>Dt(u);return Ft({...n,...d,$fetch:s,$store:l},s,t,r,o)}const _e=Vt({}),{useSession:Ht,signIn:Jt,signUp:Yt,signOut:zt}=_e,Gt=async()=>{await _e.signIn.social({provider:"google"})};function Qt({title:e,fields:t,formData:n,onSubmit:r,onChange:s,submitButtonText:l,footerText:o,footerLinkText:d,footerLinkTo:i,error:u}){const a=Te(Pe.hasGoogleSetup.queryOptions());return g.jsxs("div",{className:"container mx-auto w-full max-w-2xl p-12",children:[g.jsx("h1",{className:"text-4xl font-bold mb-8 text-center",children:e}),u&&g.jsx("p",{className:"text-red-500 text-center mb-4 text-2xl",children:u}),g.jsxs("form",{onSubmit:r,className:"space-y-6",children:[t.map(f=>g.jsxs("div",{className:"space-y-3",children:[g.jsx("label",{htmlFor:f.id,className:"text-base font-medium",children:f.label}),g.jsx(Ce,{id:f.id,name:f.name,type:f.type,placeholder:f.placeholder,value:n[f.name],onChange:s,required:!0,className:"h-12 text-base"})]},f.id)),g.jsx(le,{type:"submit",className:"w-full h-12 text-base",children:l})]}),a.data&&g.jsxs("div",{className:"mt-8",children:[g.jsxs("div",{className:"relative",children:[g.jsx("div",{className:"absolute inset-0 flex items-center",children:g.jsx("div",{className:"w-full border-t border-gray-300"})}),g.jsx("div",{className:"relative flex justify-center text-sm",children:g.jsx("span",{className:"px-2 bg-background text-muted-foreground",children:"Or continue with"})})]}),g.jsx("div",{className:"flex justify-center items-center gap-4 p-4",children:g.jsx(le,{type:"button",variant:"outline",onClick:Gt,children:g.jsx("img",{src:"/google-icon.svg",alt:"Google",className:"w-5 h-5"})})})]}),g.jsxs("p",{className:"text-center text-sm text-muted-foreground mt-8",children:[o," ",g.jsx(Le,{to:i,className:"text-primary hover:underline font-medium",children:d})]})]})}export{Qt as S,Jt as a,Yt as s};
@@ -1 +1 @@
1
- import{u as c,r as n,j as g,s as d}from"./index-DDQ8i103.js";import{S as u}from"./signinForm-BGrBZeLW.js";function x(){const o=c(),[e,s]=n.useState({name:"",email:"",password:""}),[r,t]=n.useState(""),i=async a=>{a.preventDefault(),t(""),await d.email({name:e.name,email:e.email,password:e.password},{onSuccess:()=>{o({to:"/"})},onError:p=>{t(p.error.message)}})},m=a=>{s({...e,[a.target.name]:a.target.value})},l=[{id:"name",name:"name",type:"text",label:"Name"},{id:"email",name:"email",type:"email",label:"Email",placeholder:"test@gmail.com"},{id:"password",name:"password",type:"password",label:"Password"}];return g.jsx(u,{title:"Sign Up",fields:l,formData:e,onSubmit:i,onChange:m,submitButtonText:"Sign Up",footerText:"Already have an account?",footerLinkText:"Sign in",footerLinkTo:"/login",error:r})}export{x as component};
1
+ import{u as c,r as n,j as g}from"./index-CGg3ZQH6.js";import{S as d,s as u}from"./signinForm-9PY1Lvqj.js";function x(){const o=c(),[e,s]=n.useState({name:"",email:"",password:""}),[r,t]=n.useState(""),i=async a=>{a.preventDefault(),t(""),await u.email({name:e.name,email:e.email,password:e.password},{onSuccess:()=>{o({to:"/"})},onError:p=>{t(p.error.message)}})},m=a=>{s({...e,[a.target.name]:a.target.value})},l=[{id:"name",name:"name",type:"text",label:"Name"},{id:"email",name:"email",type:"email",label:"Email",placeholder:"test@gmail.com"},{id:"password",name:"password",type:"password",label:"Password"}];return g.jsx(d,{title:"Sign Up",fields:l,formData:e,onSubmit:i,onChange:m,submitButtonText:"Sign Up",footerText:"Already have an account?",footerLinkText:"Sign in",footerLinkTo:"/login",error:r})}export{x as component};
Binary file
@@ -8,9 +8,9 @@
8
8
  <meta name="description" content="Web site created using create-tsrouter-app" />
9
9
  <link rel="apple-touch-icon" href="/logo192.png" />
10
10
  <link rel="manifest" href="/manifest.json" />
11
- <title>Create TanStack App - frontend</title>
12
- <script type="module" crossorigin src="/assets/index-DDQ8i103.js"></script>
13
- <link rel="stylesheet" crossorigin href="/assets/index-BUcR0FCx.css">
11
+ <title>nao Chat with your data</title>
12
+ <script type="module" crossorigin src="/assets/index-CGg3ZQH6.js"></script>
13
+ <link rel="stylesheet" crossorigin href="/assets/index-Bc7icYyJ.css">
14
14
  </head>
15
15
  <body>
16
16
  <div id="app"></div>
nao_core/commands/chat.py CHANGED
@@ -13,6 +13,7 @@ console = Console()
13
13
 
14
14
  # Default port for the nao chat server
15
15
  SERVER_PORT = 5005
16
+ FASTAPI_PORT = 8005
16
17
 
17
18
 
18
19
  def get_server_binary_path() -> Path:
@@ -30,6 +31,19 @@ def get_server_binary_path() -> Path:
30
31
  return binary_path
31
32
 
32
33
 
34
+ def get_fastapi_main_path() -> Path:
35
+ """Get the path to the FastAPI main.py file."""
36
+ cli_dir = Path(__file__).parent.parent
37
+ bin_dir = cli_dir / "bin"
38
+ fastapi_path = bin_dir / "fastapi" / "main.py"
39
+
40
+ if not fastapi_path.exists():
41
+ console.print(f"[bold red]✗[/bold red] FastAPI main.py not found at {fastapi_path}")
42
+ sys.exit(1)
43
+
44
+ return fastapi_path
45
+
46
+
33
47
  def wait_for_server(port: int, timeout: int = 30) -> bool:
34
48
  """Wait for the server to be ready."""
35
49
  import socket
@@ -67,8 +81,21 @@ def chat():
67
81
  else:
68
82
  console.print("[dim]No nao_config.yaml found in current directory[/dim]")
69
83
 
70
- # Start the server process
71
- process = None
84
+ # Start the server processes
85
+ chat_process = None
86
+ fastapi_process = None
87
+
88
+ def shutdown_servers():
89
+ """Gracefully shut down both server processes."""
90
+ for name, proc in [("Chat server", chat_process), ("FastAPI server", fastapi_process)]:
91
+ if proc:
92
+ proc.terminate()
93
+ try:
94
+ proc.wait(timeout=5)
95
+ except subprocess.TimeoutExpired:
96
+ proc.kill()
97
+ proc.wait()
98
+
72
99
  try:
73
100
  # Set up environment - inherit from parent but ensure we're in the bin dir
74
101
  # so the server can find the public folder
@@ -80,7 +107,31 @@ def chat():
80
107
  env[env_var_name] = config.llm.api_key
81
108
  console.print(f"[bold green]✓[/bold green] Set {env_var_name} from config")
82
109
 
83
- process = subprocess.Popen(
110
+ env["NAO_PROJECT_FOLDER"] = str(Path.cwd())
111
+ env["FASTAPI_URL"] = f"http://localhost:{FASTAPI_PORT}"
112
+
113
+ # Start the FastAPI server first
114
+ fastapi_path = get_fastapi_main_path()
115
+ console.print(f"[dim]FastAPI server: {fastapi_path}[/dim]")
116
+
117
+ fastapi_process = subprocess.Popen(
118
+ [sys.executable, str(fastapi_path)],
119
+ cwd=str(fastapi_path.parent),
120
+ env=env,
121
+ stdout=subprocess.DEVNULL,
122
+ stderr=subprocess.DEVNULL,
123
+ )
124
+
125
+ console.print("[bold green]✓[/bold green] FastAPI server starting...")
126
+
127
+ # Wait for FastAPI server to be ready
128
+ if wait_for_server(FASTAPI_PORT):
129
+ console.print(f"[bold green]✓[/bold green] FastAPI server ready at http://localhost:{FASTAPI_PORT}")
130
+ else:
131
+ console.print("[bold yellow]⚠[/bold yellow] FastAPI server is taking longer than expected to start...")
132
+
133
+ # Start the chat server
134
+ chat_process = subprocess.Popen(
84
135
  [str(binary_path)],
85
136
  cwd=str(bin_dir),
86
137
  env=env,
@@ -89,44 +140,35 @@ def chat():
89
140
  text=True,
90
141
  )
91
142
 
92
- console.print("[bold green]✓[/bold green] Server starting...")
143
+ console.print("[bold green]✓[/bold green] Chat server starting...")
93
144
 
94
- # Wait for the server to be ready
145
+ # Wait for the chat server to be ready
95
146
  if wait_for_server(SERVER_PORT):
96
147
  url = f"http://localhost:{SERVER_PORT}"
97
- console.print(f"[bold green]✓[/bold green] Server ready at {url}")
148
+ console.print(f"[bold green]✓[/bold green] Chat server ready at {url}")
98
149
  console.print("\n[bold]Opening browser...[/bold]")
99
150
  webbrowser.open(url)
100
- console.print("\n[dim]Press Ctrl+C to stop the server[/dim]\n")
151
+ console.print("\n[dim]Press Ctrl+C to stop the servers[/dim]\n")
101
152
  else:
102
- console.print("[bold yellow]⚠[/bold yellow] Server is taking longer than expected to start...")
153
+ console.print("[bold yellow]⚠[/bold yellow] Chat server is taking longer than expected to start...")
103
154
  console.print(f"[dim]Check http://localhost:{SERVER_PORT} manually[/dim]")
104
155
 
105
- # Stream server output to console
106
- if process.stdout:
107
- for line in process.stdout:
156
+ # Stream chat server output to console
157
+ if chat_process.stdout:
158
+ for line in chat_process.stdout:
108
159
  # Filter out some of the verbose logging if needed
109
160
  console.print(f"[dim]{line.rstrip()}[/dim]")
110
161
 
111
162
  # Wait for process to complete
112
- process.wait()
163
+ chat_process.wait()
113
164
 
114
165
  except KeyboardInterrupt:
115
166
  console.print("\n[bold yellow]Shutting down...[/bold yellow]")
116
- if process:
117
- # Send SIGTERM for graceful shutdown
118
- process.terminate()
119
- try:
120
- process.wait(timeout=5)
121
- except subprocess.TimeoutExpired:
122
- # Force kill if it doesn't respond
123
- process.kill()
124
- process.wait()
125
- console.print("[bold green]✓[/bold green] Server stopped")
167
+ shutdown_servers()
168
+ console.print("[bold green]✓[/bold green] Servers stopped")
126
169
  sys.exit(0)
127
170
 
128
171
  except Exception as e:
129
- console.print(f"[bold red]✗[/bold red] Failed to start server: {e}")
130
- if process:
131
- process.kill()
172
+ console.print(f"[bold red]✗[/bold red] Failed to start servers: {e}")
173
+ shutdown_servers()
132
174
  sys.exit(1)
@@ -14,7 +14,6 @@ def test_database_connection(db_config) -> tuple[bool, str]:
14
14
  Returns:
15
15
  Tuple of (success, message)
16
16
  """
17
- conn = None
18
17
  try:
19
18
  conn = db_config.connect()
20
19
  # Run a simple query to verify the connection works
@@ -30,9 +29,6 @@ def test_database_connection(db_config) -> tuple[bool, str]:
30
29
  return True, f"Connected successfully ({dataset_count} datasets found)"
31
30
  except Exception as e:
32
31
  return False, str(e)
33
- finally:
34
- if conn:
35
- conn.close()
36
32
 
37
33
 
38
34
  def test_llm_connection(llm_config) -> tuple[bool, str]:
nao_core/commands/init.py CHANGED
@@ -5,7 +5,7 @@ from cyclopts import Parameter
5
5
  from rich.console import Console
6
6
  from rich.prompt import Confirm, Prompt
7
7
 
8
- from nao_core.config import BigQueryConfig, DatabaseConfig, DatabaseType, LLMConfig, LLMProvider, NaoConfig
8
+ from nao_core.config import AnyDatabaseConfig, BigQueryConfig, DatabaseType, LLMConfig, LLMProvider, NaoConfig
9
9
 
10
10
  console = Console()
11
11
 
@@ -80,9 +80,9 @@ def setup_bigquery() -> BigQueryConfig:
80
80
  )
81
81
 
82
82
 
83
- def setup_databases() -> list[DatabaseConfig]:
83
+ def setup_databases() -> list[AnyDatabaseConfig]:
84
84
  """Setup database configurations."""
85
- databases: list[DatabaseConfig] = []
85
+ databases: list[AnyDatabaseConfig] = []
86
86
 
87
87
  should_setup = Confirm.ask("\n[bold]Set up database connections?[/bold]", default=True)
88
88