nao-core 0.0.16__py3-none-any.whl → 0.0.17__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 (48) hide show
  1. nao_core/__init__.py +1 -1
  2. nao_core/bin/chats/588bbb8a-dcbc-42dc-b0d8-b6b9ed13e2fb.json +45 -0
  3. nao_core/bin/fastapi/main.py +19 -2
  4. nao_core/bin/migrations-postgres/{0000_supreme_cable.sql → 0000_user_auth_and_chat_tables.sql} +35 -22
  5. nao_core/bin/migrations-postgres/meta/0000_snapshot.json +208 -111
  6. nao_core/bin/migrations-postgres/meta/_journal.json +2 -2
  7. nao_core/bin/migrations-sqlite/{0000_cloudy_squirrel_girl.sql → 0000_user_auth_and_chat_tables.sql} +35 -22
  8. nao_core/bin/migrations-sqlite/meta/0000_snapshot.json +189 -105
  9. nao_core/bin/migrations-sqlite/meta/_journal.json +2 -2
  10. nao_core/bin/nao-chat-server +0 -0
  11. nao_core/bin/public/assets/_chat-layout-Do0mWziW.js +1 -0
  12. nao_core/bin/public/assets/_chat-layout.index-mxrV7qZY.js +1 -0
  13. nao_core/bin/public/assets/agentProvider-cEZoyU1e.js +1 -0
  14. nao_core/bin/public/assets/code-block-F6WJLWQG-oIWcWPcR.js +153 -0
  15. nao_core/bin/public/assets/createLucideIcon-BGNfPWE_.js +1 -0
  16. nao_core/bin/public/assets/index-B-_pu_22.js +59 -0
  17. nao_core/bin/public/assets/index-CWAm1NQa.css +1 -0
  18. nao_core/bin/public/assets/login-CF4uOXFH.js +1 -0
  19. nao_core/bin/public/assets/mermaid-FSSLJTFX-BzFakw7W.js +380 -0
  20. nao_core/bin/public/assets/signinForm-D98dwmLQ.js +1 -0
  21. nao_core/bin/public/assets/signup-CQSmDpcH.js +1 -0
  22. nao_core/bin/public/assets/utils-DzJYey0s.js +1 -0
  23. nao_core/bin/public/index.html +2 -2
  24. nao_core/bin/public/nao-logo-greyscale.svg +25 -0
  25. nao_core/commands/init.py +111 -0
  26. nao_core/commands/sync/__init__.py +59 -0
  27. nao_core/commands/sync/accessors.py +212 -0
  28. nao_core/commands/sync/databases.py +132 -0
  29. nao_core/commands/sync/registry.py +23 -0
  30. nao_core/commands/sync/repositories.py +103 -0
  31. nao_core/config/base.py +2 -0
  32. nao_core/config/repos/__init__.py +3 -0
  33. nao_core/config/repos/base.py +11 -0
  34. {nao_core-0.0.16.dist-info → nao_core-0.0.17.dist-info}/METADATA +1 -1
  35. nao_core-0.0.17.dist-info/RECORD +51 -0
  36. nao_core/bin/public/assets/_chatId-z5gRlor1.js +0 -1
  37. nao_core/bin/public/assets/chat-messages-DUR3D342.js +0 -1
  38. nao_core/bin/public/assets/index-BDlcD_HE.js +0 -1
  39. nao_core/bin/public/assets/index-Bc7icYyJ.css +0 -1
  40. nao_core/bin/public/assets/index-CGg3ZQH6.js +0 -49
  41. nao_core/bin/public/assets/login-D87n9R5V.js +0 -1
  42. nao_core/bin/public/assets/signinForm-9PY1Lvqj.js +0 -1
  43. nao_core/bin/public/assets/signup-B7NC1g08.js +0 -1
  44. nao_core/commands/sync.py +0 -380
  45. nao_core-0.0.16.dist-info/RECORD +0 -39
  46. {nao_core-0.0.16.dist-info → nao_core-0.0.17.dist-info}/WHEEL +0 -0
  47. {nao_core-0.0.16.dist-info → nao_core-0.0.17.dist-info}/entry_points.txt +0 -0
  48. {nao_core-0.0.16.dist-info → nao_core-0.0.17.dist-info}/licenses/LICENSE +0 -0
@@ -1 +0,0 @@
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};
@@ -1 +0,0 @@
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 +0,0 @@
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};
nao_core/commands/sync.py DELETED
@@ -1,380 +0,0 @@
1
- import sys
2
- from abc import ABC, abstractmethod
3
- from pathlib import Path
4
-
5
- from ibis import BaseBackend
6
- from rich.console import Console
7
- from rich.progress import BarColumn, Progress, SpinnerColumn, TaskProgressColumn, TextColumn
8
-
9
- from nao_core.config import AccessorType, NaoConfig
10
-
11
- console = Console()
12
-
13
-
14
- # =============================================================================
15
- # Data Accessors
16
- # =============================================================================
17
-
18
-
19
- class DataAccessor(ABC):
20
- """Base class for data accessors that generate markdown files for tables."""
21
-
22
- @property
23
- @abstractmethod
24
- def filename(self) -> str:
25
- """The filename this accessor writes to (e.g., 'columns.md')."""
26
- ...
27
-
28
- @abstractmethod
29
- def generate(self, conn: BaseBackend, dataset: str, table: str) -> str:
30
- """Generate the markdown content for a table.
31
-
32
- Args:
33
- conn: The Ibis database connection
34
- dataset: The dataset/schema name
35
- table: The table name
36
-
37
- Returns:
38
- Markdown string content
39
- """
40
- ...
41
-
42
- def get_table(self, conn: BaseBackend, dataset: str, table: str):
43
- """Helper to get an Ibis table reference."""
44
- full_table_name = f"{dataset}.{table}"
45
- return conn.table(full_table_name)
46
-
47
-
48
- class ColumnsAccessor(DataAccessor):
49
- """Generates columns.md with column names, types, and nullable info."""
50
-
51
- @property
52
- def filename(self) -> str:
53
- return "columns.md"
54
-
55
- def generate(self, conn: BaseBackend, dataset: str, table: str) -> str:
56
- try:
57
- t = self.get_table(conn, dataset, table)
58
- schema = t.schema()
59
-
60
- lines = [
61
- f"# {table}",
62
- "",
63
- f"**Dataset:** `{dataset}`",
64
- "",
65
- "## Columns",
66
- "",
67
- "| Column | Type | Nullable | Description |",
68
- "|--------|------|----------|-------------|",
69
- ]
70
-
71
- for name, dtype in schema.items():
72
- nullable = "Yes" if dtype.nullable else "No"
73
- description = ""
74
- lines.append(f"| `{name}` | `{dtype}` | {nullable} | {description} |")
75
-
76
- return "\n".join(lines)
77
- except Exception as e:
78
- return f"# {table}\n\nError fetching schema: {e}"
79
-
80
-
81
- class PreviewAccessor(DataAccessor):
82
- """Generates preview.md with the first N rows of data."""
83
-
84
- def __init__(self, num_rows: int = 10):
85
- self.num_rows = num_rows
86
-
87
- @property
88
- def filename(self) -> str:
89
- return "preview.md"
90
-
91
- def generate(self, conn: BaseBackend, dataset: str, table: str) -> str:
92
- try:
93
- t = self.get_table(conn, dataset, table)
94
- schema = t.schema()
95
-
96
- preview_df = t.limit(self.num_rows).execute()
97
-
98
- lines = [
99
- f"# {table} - Preview",
100
- "",
101
- f"**Dataset:** `{dataset}`",
102
- f"**Showing:** First {len(preview_df)} rows",
103
- "",
104
- "## Data Preview",
105
- "",
106
- ]
107
-
108
- columns = list(schema.keys())
109
- header = "| " + " | ".join(f"`{col}`" for col in columns) + " |"
110
- separator = "| " + " | ".join("---" for _ in columns) + " |"
111
- lines.append(header)
112
- lines.append(separator)
113
-
114
- for _, row in preview_df.iterrows():
115
- row_values = []
116
- for col in columns:
117
- val = row[col]
118
- val_str = str(val) if val is not None else ""
119
- if len(val_str) > 50:
120
- val_str = val_str[:47] + "..."
121
- val_str = val_str.replace("|", "\\|").replace("\n", " ")
122
- row_values.append(val_str)
123
- lines.append("| " + " | ".join(row_values) + " |")
124
-
125
- return "\n".join(lines)
126
- except Exception as e:
127
- return f"# {table} - Preview\n\nError fetching preview: {e}"
128
-
129
-
130
- class DescriptionAccessor(DataAccessor):
131
- """Generates description.md with table metadata (row count, column count, etc.)."""
132
-
133
- @property
134
- def filename(self) -> str:
135
- return "description.md"
136
-
137
- def generate(self, conn: BaseBackend, dataset: str, table: str) -> str:
138
- try:
139
- t = self.get_table(conn, dataset, table)
140
- schema = t.schema()
141
-
142
- row_count = t.count().execute()
143
- col_count = len(schema)
144
-
145
- lines = [
146
- f"# {table}",
147
- "",
148
- f"**Dataset:** `{dataset}`",
149
- "",
150
- "## Table Metadata",
151
- "",
152
- "| Property | Value |",
153
- "|----------|-------|",
154
- f"| **Row Count** | {row_count:,} |",
155
- f"| **Column Count** | {col_count} |",
156
- "",
157
- "## Description",
158
- "",
159
- "_No description available._",
160
- "",
161
- ]
162
-
163
- return "\n".join(lines)
164
- except Exception as e:
165
- return f"# {table}\n\nError fetching description: {e}"
166
-
167
-
168
- class ProfilingAccessor(DataAccessor):
169
- """Generates profiling.md with column statistics and data profiling."""
170
-
171
- @property
172
- def filename(self) -> str:
173
- return "profiling.md"
174
-
175
- def generate(self, conn: BaseBackend, dataset: str, table: str) -> str:
176
- try:
177
- t = self.get_table(conn, dataset, table)
178
- schema = t.schema()
179
-
180
- lines = [
181
- f"# {table} - Profiling",
182
- "",
183
- f"**Dataset:** `{dataset}`",
184
- "",
185
- "## Column Statistics",
186
- "",
187
- "| Column | Type | Nulls | Unique | Min | Max |",
188
- "|--------|------|-------|--------|-----|-----|",
189
- ]
190
-
191
- for name, dtype in schema.items():
192
- col = t[name]
193
- dtype_str = str(dtype)
194
-
195
- try:
196
- null_count = t.filter(col.isnull()).count().execute()
197
- unique_count = col.nunique().execute()
198
-
199
- min_val = ""
200
- max_val = ""
201
- if dtype.is_numeric() or dtype.is_temporal():
202
- try:
203
- min_val = str(col.min().execute())
204
- max_val = str(col.max().execute())
205
- if len(min_val) > 20:
206
- min_val = min_val[:17] + "..."
207
- if len(max_val) > 20:
208
- max_val = max_val[:17] + "..."
209
- except Exception:
210
- pass
211
-
212
- lines.append(
213
- f"| `{name}` | `{dtype_str}` | {null_count:,} | {unique_count:,} | {min_val} | {max_val} |"
214
- )
215
- except Exception as col_error:
216
- lines.append(f"| `{name}` | `{dtype_str}` | Error: {col_error} | | | |")
217
-
218
- return "\n".join(lines)
219
- except Exception as e:
220
- return f"# {table} - Profiling\n\nError fetching profiling: {e}"
221
-
222
-
223
- # =============================================================================
224
- # Accessor Registry
225
- # =============================================================================
226
-
227
- ACCESSOR_REGISTRY: dict[AccessorType, DataAccessor] = {
228
- AccessorType.COLUMNS: ColumnsAccessor(),
229
- AccessorType.PREVIEW: PreviewAccessor(num_rows=10),
230
- AccessorType.DESCRIPTION: DescriptionAccessor(),
231
- AccessorType.PROFILING: ProfilingAccessor(),
232
- }
233
-
234
-
235
- def get_accessors(accessor_types: list[AccessorType]) -> list[DataAccessor]:
236
- """Get accessor instances for the given types."""
237
- return [ACCESSOR_REGISTRY[t] for t in accessor_types if t in ACCESSOR_REGISTRY]
238
-
239
-
240
- # =============================================================================
241
- # Sync Functions
242
- # =============================================================================
243
-
244
-
245
- def sync_bigquery(
246
- db_config,
247
- base_path: Path,
248
- progress: Progress,
249
- accessors: list[DataAccessor],
250
- ) -> tuple[int, int]:
251
- """Sync BigQuery database schema to markdown files.
252
-
253
- Args:
254
- db_config: The database configuration
255
- base_path: Base output path
256
- progress: Rich progress instance
257
- accessors: List of data accessors to run
258
-
259
- Returns:
260
- Tuple of (datasets_synced, tables_synced)
261
- """
262
- conn = db_config.connect()
263
- db_path = base_path / "bigquery" / db_config.name
264
-
265
- datasets_synced = 0
266
- tables_synced = 0
267
-
268
- if db_config.dataset_id:
269
- datasets = [db_config.dataset_id]
270
- else:
271
- datasets = conn.list_databases()
272
-
273
- dataset_task = progress.add_task(
274
- f"[dim]{db_config.name}[/dim]",
275
- total=len(datasets),
276
- )
277
-
278
- for dataset in datasets:
279
- try:
280
- all_tables = conn.list_tables(database=dataset)
281
- except Exception:
282
- progress.update(dataset_task, advance=1)
283
- continue
284
-
285
- # Filter tables based on include/exclude patterns
286
- tables = [t for t in all_tables if db_config.matches_pattern(dataset, t)]
287
-
288
- # Skip dataset if no tables match
289
- if not tables:
290
- progress.update(dataset_task, advance=1)
291
- continue
292
-
293
- dataset_path = db_path / dataset
294
- dataset_path.mkdir(parents=True, exist_ok=True)
295
- datasets_synced += 1
296
-
297
- table_task = progress.add_task(
298
- f" [cyan]{dataset}[/cyan]",
299
- total=len(tables),
300
- )
301
-
302
- for table in tables:
303
- table_path = dataset_path / table
304
- table_path.mkdir(parents=True, exist_ok=True)
305
-
306
- for accessor in accessors:
307
- content = accessor.generate(conn, dataset, table)
308
- output_file = table_path / accessor.filename
309
- output_file.write_text(content)
310
-
311
- tables_synced += 1
312
- progress.update(table_task, advance=1)
313
-
314
- progress.update(dataset_task, advance=1)
315
-
316
- return datasets_synced, tables_synced
317
-
318
-
319
- def sync(output_dir: str = "databases"):
320
- """Sync database schemas to local markdown files.
321
-
322
- Creates a folder structure with table metadata:
323
- databases/bigquery/<connection>/<dataset>/<table>/columns.md
324
- databases/bigquery/<connection>/<dataset>/<table>/preview.md
325
- databases/bigquery/<connection>/<dataset>/<table>/description.md
326
- databases/bigquery/<connection>/<dataset>/<table>/profiling.md
327
-
328
- Args:
329
- output_dir: Output directory for the database schemas (default: "databases")
330
- """
331
- console.print("\n[bold cyan]🔄 nao sync[/bold cyan]\n")
332
-
333
- config = NaoConfig.try_load()
334
- if not config:
335
- console.print("[bold red]✗[/bold red] No nao_config.yaml found in current directory")
336
- console.print("[dim]Run 'nao init' to create a configuration file[/dim]")
337
- sys.exit(1)
338
-
339
- console.print(f"[dim]Project:[/dim] {config.project_name}")
340
-
341
- if not config.databases:
342
- console.print("[dim]No databases configured[/dim]")
343
- return
344
-
345
- base_path = Path(output_dir)
346
- total_datasets = 0
347
- total_tables = 0
348
-
349
- console.print()
350
-
351
- with Progress(
352
- SpinnerColumn(style="dim"),
353
- TextColumn("[progress.description]{task.description}"),
354
- BarColumn(bar_width=30, style="dim", complete_style="cyan", finished_style="green"),
355
- TaskProgressColumn(),
356
- console=console,
357
- transient=False,
358
- ) as progress:
359
- for db in config.databases:
360
- # Get accessors from database config
361
- db_accessors = get_accessors(db.accessors)
362
- accessor_names = [a.filename.replace(".md", "") for a in db_accessors]
363
-
364
- try:
365
- if db.type == "bigquery":
366
- console.print(f"[dim]{db.name} accessors:[/dim] {', '.join(accessor_names)}")
367
- datasets, tables = sync_bigquery(db, base_path, progress, db_accessors)
368
- total_datasets += datasets
369
- total_tables += tables
370
- else:
371
- console.print(f"[yellow]⚠ Unsupported database type: {db.type}[/yellow]")
372
- except Exception as e:
373
- console.print(f"[bold red]✗[/bold red] Failed to sync {db.name}: {e}")
374
-
375
- console.print()
376
- console.print(
377
- f"[green]✓[/green] Synced [bold]{total_tables}[/bold] tables across [bold]{total_datasets}[/bold] datasets"
378
- )
379
- console.print(f"[dim] → {base_path.absolute()}[/dim]")
380
- console.print()
@@ -1,39 +0,0 @@
1
- nao_core/__init__.py,sha256=KJyJjkLBBL_KS5Ti_d52Czr4pYqLcMft1lp6skMXgTc,46
2
- nao_core/main.py,sha256=f00vLL4s2B2kCMa8y3lI56LX3TnUppWzYmqM6eOGomA,205
3
- nao_core/bin/db.sqlite,sha256=FwRfxk8J3T_Qrdcw5TbxSnafGDn0yiHCKhwMdULc7C4,110592
4
- nao_core/bin/nao-chat-server,sha256=ktfG-ncBIKaBAO5BNh8xgu4Te-G82Y7yYbpwLJVP05Q,64756464
5
- nao_core/bin/fastapi/main.py,sha256=pEH8iMnqQXvQjxseEkXEsParU7REkiTO4UFB1-dDAPc,3068
6
- nao_core/bin/migrations-postgres/0000_supreme_cable.sql,sha256=BR_BcHRpUr35pbrRDOsFbRm9u4wC-AQ9orGuAc4BJok,3751
7
- nao_core/bin/migrations-postgres/meta/0000_snapshot.json,sha256=lAf2CNFAqTtLw2mjsF2vdKryTb5UbkwSa1K9XmCcdyY,15080
8
- nao_core/bin/migrations-postgres/meta/_journal.json,sha256=zIBPX9lX4UnSgo3fzeoQXh2u3M9ZlyxRDvs8-VzBJbI,207
9
- nao_core/bin/migrations-sqlite/0000_cloudy_squirrel_girl.sql,sha256=i8NqZSv7qTzcVIoLBE0pNcuM4ZCp4WS9iYMUXxzqCT0,3609
10
- nao_core/bin/migrations-sqlite/meta/0000_snapshot.json,sha256=q-O9sjRNmCT3s0-ZyF1gZ60ZaDH24wGjC-VHG-2RdVU,15268
11
- nao_core/bin/migrations-sqlite/meta/_journal.json,sha256=-8raNXK1aCMrt-25YnnIM4GRb9w_JT6AtiDDBQfBgx0,210
12
- nao_core/bin/public/favicon.ico,sha256=s-a2BQ71NeB_Y2uOC_EPF9isG5DavpF9GKwYgxNSOWk,15406
13
- nao_core/bin/public/github-icon.svg,sha256=drFeRxLjsnngoGOh4heU3E5mX_xUsmGgFOc_mnjXKwU,1926
14
- nao_core/bin/public/google-icon.svg,sha256=bTmcoH4gkdoV2Atl2kp-pLFpFZNL85FR_8GAKv9LL5I,1140
15
- nao_core/bin/public/index.html,sha256=BOiBADShUuIisOGAPzzOoWtz6WZGOnPd1she4-nlghk,670
16
- nao_core/bin/public/assets/_chatId-z5gRlor1.js,sha256=SsV80_uJgklDpNGZvHCd3z2L6gbEhaI4jbjCGUn2skU,317
17
- nao_core/bin/public/assets/chat-messages-DUR3D342.js,sha256=TdgOYw6ydRjhIaxnGWoAfOYZXSZALfAObQvm5PUXaOs,10008
18
- nao_core/bin/public/assets/index-BDlcD_HE.js,sha256=2p13XoH_dd-F2EL40raWqWLFQ2M08QsJw54S19PWA5Y,144
19
- nao_core/bin/public/assets/index-Bc7icYyJ.css,sha256=p2xISnm3R1k1yDMu2H4GgMwOlqvqXrI4vxbkMbWfB9k,34874
20
- nao_core/bin/public/assets/index-CGg3ZQH6.js,sha256=bymnyMM_CMLWyWDWmNV6qeBI_g5L5zQhVu_t4hkwo-8,521092
21
- nao_core/bin/public/assets/login-D87n9R5V.js,sha256=ztE0a6I0pP3OS2DgWg8Voe4K5--gvko33VUcRmrl6AQ,793
22
- nao_core/bin/public/assets/signinForm-9PY1Lvqj.js,sha256=T3y4qLH7YeO6YvZwlVs6y-D_kaao3FwHhmjrKZ4b4JY,28761
23
- nao_core/bin/public/assets/signup-B7NC1g08.js,sha256=NQcfePZ3vLhH0VZY4ge1RB6eiIAhcjVYDMs1RxUm1ug,832
24
- nao_core/commands/__init__.py,sha256=rFCuUyA9wM4hS6CxCt2M_5W4VysyQXh6HkA_hyRCxPc,207
25
- nao_core/commands/chat.py,sha256=TiV-0dEFPRmIirHMnPVbKNomNWO67OsaPT1SzA07EIM,5995
26
- nao_core/commands/debug.py,sha256=Hdtb6_2F-a9Nr-aU_exdnPZY0-Lf9dgV1QX6QxPr9P8,4794
27
- nao_core/commands/init.py,sha256=QGKdBn7mKc3yc379DJNOsFh5LW313XS4r7CFsZs-nRY,5184
28
- nao_core/commands/sync.py,sha256=NCWgWoBqYMk6qzobSQTbGqCc8a9pX2VI-CqCNmXsFhQ,12626
29
- nao_core/config/__init__.py,sha256=qzM2sXRKfO5ZCKbIRwUS-Roh5ry0zVEqWJBobVlGbJM,308
30
- nao_core/config/base.py,sha256=O6wf0csZteCk18Mw7hV8sHtUS9KTbR06Ffv3BpHINvc,2715
31
- nao_core/config/databases/__init__.py,sha256=t62wpLCTi9lAf6rzem7iu605ywtK4qo7DuTP-qSr3jc,1027
32
- nao_core/config/databases/base.py,sha256=Y0BN8Zowi0n0GKT2sEJ2iqitPf-P4o1V9gCVhgiSzr8,2219
33
- nao_core/config/databases/bigquery.py,sha256=RA07YMp24kQVPOQStdLCx27e50nUIIoO_U1io1wqtVk,1453
34
- nao_core/config/llm/__init__.py,sha256=wBVFFmOWWUuIM19fNeXkdIWxg9nE_cR3roWFyUvAuIE,343
35
- nao_core-0.0.16.dist-info/METADATA,sha256=udLAonzSH_-v9bTtjzCCwox-_lYIFoGT9oVDSQrhUqc,5206
36
- nao_core-0.0.16.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
37
- nao_core-0.0.16.dist-info/entry_points.txt,sha256=SZakIiNybgS3pl_OEZVLyLSweadeBFoEMBECMoj9czY,42
38
- nao_core-0.0.16.dist-info/licenses/LICENSE,sha256=rn5YtWB6E5hPQI49tCTNSyqlArWGsB6HzA5FfSbRHRs,1066
39
- nao_core-0.0.16.dist-info/RECORD,,