@askdb/studio 0.2.0-beta.41 → 0.2.0-beta.43
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/README.md +1 -1
- package/dist/client/assets/{index-CGC5sKu1.js → index-DX7u2yPd.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/introspection.d.ts.map +1 -1
- package/dist/introspection.js +1 -0
- package/dist/introspection.js.map +1 -1
- package/dist/prisma-install.d.ts +1 -1
- package/dist/prisma-install.js +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +40 -35
- package/dist/server.js.map +1 -1
- package/dist/setup.d.ts +6 -12
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +83 -288
- package/dist/setup.js.map +1 -1
- package/package.json +13 -13
- package/dist/package-manager.d.ts +0 -44
- package/dist/package-manager.d.ts.map +0 -1
- package/dist/package-manager.js +0 -86
- package/dist/package-manager.js.map +0 -1
package/README.md
CHANGED
|
@@ -61,6 +61,6 @@ Configuration, in `askdb.config.*` (bind any value to an environment variable of
|
|
|
61
61
|
| `studio.listen.port` | Bind port. Defaults to `5556`. `--port` overrides it. |
|
|
62
62
|
| `dev.mockSql` | Deterministic generated SQL for tests or offline demos. |
|
|
63
63
|
|
|
64
|
-
Security: every `/api/*` request must carry the per-launch session token that Studio injects into the page it serves (`x-askdb-studio-token` header), come with an allowed `Host` (`localhost`, `127.0.0.1`, `[::1]`, or the bound host), and, for writes, be same-origin JSON. Programmatic callers of `createStudioServer()` can read the token from `server.sessionToken`. Binding to a non-loopback host exposes query execution and schema writes to anyone on that network who can load the page. Only do that on a trusted network. See [Studio → Security model](https://askdb.tools/studio/#security-model).
|
|
64
|
+
Security: every `/api/*` request must carry the per-launch session token that Studio injects into the page it serves (`x-askdb-studio-token` header), come with an allowed `Host` (`localhost`, `127.0.0.1`, `[::1]`, or the bound host), and, for writes, be same-origin JSON. Programmatic callers of `createStudioServer()` can read the token from `server.sessionToken`. Binding to a non-loopback host exposes query execution and schema writes to anyone on that network who can load the page. Only do that on a trusted network. See [Studio → Security model](https://askdb.tools/reference/studio/#security-model).
|
|
65
65
|
|
|
66
66
|
Studio uses the active `rag.store` branch from `askdb.config.*`, and embeds with `rag.embedder`: `mock`, a local lexical embedder that needs no key, or `ai`, the `ai.embedding` model, built from that section's connection only (see the [configuration reference](https://askdb.tools/reference/config/#aiembedding)). For `pgvector`, make sure `rag.storeConfig.pgvector.databaseUrl` resolves; there's no need to create the table. The first index build creates it, and the `vector` extension, at the width the embedding model returns (or `ai.embedding.dimensions`). A table that already exists at another width is refused, with a message saying how to resolve it. If Studio's database role can't create extensions, create `vector` first.
|
|
@@ -97,4 +97,4 @@ const { sql${l&&i===`sql-params`?`, tenantParams`:``} } = await ask({
|
|
|
97
97
|
`).map((e,t)=>t===0?e:n+e).join(`
|
|
98
98
|
`)}var Mg=`h-9 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring`,Ng={border:0,padding:0,margin:0};function Pg(e){return`${e}-${globalThis.crypto?.randomUUID?.()??`${Date.now()}-${Math.random().toString(36).slice(2)}`}`}function Fg(){let{workspace:e}=vr(),{ragAvailable:t}=jr(),{askQuestion:n,setAskQuestion:r,askMode:i,setAskMode:a,askMessage:o,askResult:s,askTenantEnabled:c,setAskTenantEnabled:l,askTenantAccessKind:u,setAskTenantAccessKind:d,askTenantRoot:f,setAskTenantRoot:p,askTenantIdsText:m,setAskTenantIdsText:h,askTenantMultiRootRows:g,setAskTenantMultiRootRows:_,askTenantGlobalReason:v,setAskTenantGlobalReason:y,askTenantContext:b,setAskTenantContext:x,askTenantContextAttributes:S,setAskTenantContextAttributes:C,generatedTenantScopeJson:w,tenantScopeValidationError:T,askTenantSqlMode:E,setAskTenantSqlMode:D,executeResult:O,executeMessage:k,executeStatus:A,historyEntries:j,busy:N,handleAsk:ee,handleExecute:te,loadHistoryEntry:P,handleDeleteHistory:ne,handleInstallExecuteDriver:re}=Vr(),ie=(0,M.useCallback)(e=>{(e.metaKey||e.ctrlKey)&&e.key===`Enter`&&!N.has(`ask`)&&(e.preventDefault(),ee())},[N,ee]);if((0,M.useEffect)(()=>(document.addEventListener(`keydown`,ie),()=>document.removeEventListener(`keydown`,ie)),[ie]),!e)return null;let ae=!!e.tenantPolicy,oe=e.tenantPolicy?.roots??[],se=oe[0]?.id??``;return(0,R.jsxs)(`main`,{className:`main-pane`,children:[(0,R.jsx)(`div`,{className:`main-hd`,children:(0,R.jsxs)(`div`,{className:`main-title`,children:[(0,R.jsxs)(`h1`,{children:[(0,R.jsx)(ea,{size:18,style:{display:`inline`,marginRight:8}}),`Query Playground`]}),(0,R.jsx)(`div`,{className:`main-sub`,children:`Generate SQL from natural language and execute it against your database`})]})}),(0,R.jsx)(`div`,{className:`main-body`,style:{overflow:`hidden`,padding:0},children:(0,R.jsxs)(`div`,{style:{display:`grid`,gridTemplateColumns:`2fr 3fr`,height:`100%`},children:[(0,R.jsxs)(`div`,{style:{borderRight:`1px solid var(--border)`,display:`flex`,flexDirection:`column`,overflow:`auto`},children:[(0,R.jsx)(`div`,{style:{padding:`var(--pad-y) var(--pad-x)`},children:(0,R.jsxs)(`div`,{style:{display:`grid`,gap:12},children:[(0,R.jsx)($,{label:`Natural language question`,children:(0,R.jsx)(Hh,{value:n,onChange:e=>r(e.target.value),placeholder:`How many users placed orders last month?`,rows:4})}),(0,R.jsxs)(`div`,{style:{display:`grid`,gap:6},children:[(0,R.jsx)(`span`,{className:`muted`,style:{fontSize:11,fontWeight:600,textTransform:`uppercase`,letterSpacing:`0.04em`},children:`Retrieval mode`}),(0,R.jsxs)(`fieldset`,{className:`toggle-seg`,style:Ng,children:[(0,R.jsx)(`legend`,{className:`sr-only`,children:`Retrieval mode`}),(0,R.jsx)(`button`,{className:i===`full`?`active`:``,onClick:()=>a(`full`),children:`Full schema`}),(0,R.jsxs)(`button`,{className:i===`rag`?`active`:``,disabled:!t,title:t?void 0:`Build the RAG index first to query with retrieval.`,onClick:()=>a(`rag`),children:[!t&&(0,R.jsx)(Ki,{size:12,style:{display:`inline`,marginRight:4}}),`RAG`]})]})]}),ae&&(0,R.jsxs)(`div`,{style:{display:`grid`,gap:10},children:[(0,R.jsxs)(`label`,{style:{display:`flex`,alignItems:`center`,gap:8},children:[(0,R.jsx)(`input`,{type:`checkbox`,checked:c,onChange:e=>l(e.target.checked)}),(0,R.jsxs)(`span`,{className:`muted`,style:{fontSize:11,fontWeight:600},children:[(0,R.jsx)(ha,{size:12,style:{display:`inline`,marginRight:4}}),`Tenant scope`]})]}),c&&(0,R.jsxs)(`div`,{style:{display:`grid`,gap:10},children:[(0,R.jsxs)(`div`,{style:{display:`grid`,gap:6},children:[(0,R.jsx)(`span`,{className:`muted`,style:{fontSize:11,fontWeight:600,textTransform:`uppercase`,letterSpacing:`0.04em`},children:`Access kind`}),(0,R.jsxs)(`fieldset`,{className:`toggle-seg`,style:Ng,children:[(0,R.jsx)(`legend`,{className:`sr-only`,children:`Tenant scope access kind`}),(0,R.jsx)(`button`,{className:u===`ids`?`active`:``,onClick:()=>d(`ids`),children:`IDs`}),(0,R.jsx)(`button`,{className:u===`multi_root`?`active`:``,onClick:()=>d(`multi_root`),children:`Multi-root`}),(0,R.jsx)(`button`,{className:u===`global`?`active`:``,onClick:()=>d(`global`),children:`Super / global`})]})]}),(u===`ids`||u===`subtree`)&&(0,R.jsxs)(`div`,{style:{display:`grid`,gap:8},children:[(0,R.jsx)($,{label:`Tenant root`,children:(0,R.jsx)(`select`,{className:Mg,value:f,onChange:e=>p(e.target.value),children:oe.map(e=>(0,R.jsxs)(`option`,{value:e.id,children:[e.label,` (`,e.id,`)`]},e.id))})}),(0,R.jsx)($,{label:u===`ids`?`Tenant IDs`:`Subtree root IDs`,description:`Comma-separated IDs from your app's auth context.`,children:(0,R.jsx)(Vm,{value:m,onChange:e=>h(e.target.value),placeholder:u===`ids`?`org-1, org-2`:`region-1`})})]}),u===`multi_root`&&(0,R.jsxs)(`div`,{style:{display:`grid`,gap:8},children:[g.map((e,t)=>(0,R.jsxs)(`div`,{style:{display:`grid`,gridTemplateColumns:`minmax(0, 1fr) minmax(0, 1fr) auto`,gap:8,alignItems:`end`},children:[(0,R.jsx)($,{label:`Tenant root`,className:`min-w-0`,children:(0,R.jsx)(`select`,{className:Mg,value:e.tenantRoot,onChange:n=>{let r=[...g];r[t]={...e,tenantRoot:n.target.value},_(r)},children:oe.map(e=>(0,R.jsxs)(`option`,{value:e.id,children:[e.label,` (`,e.id,`)`]},e.id))})}),(0,R.jsx)($,{label:`IDs`,className:`min-w-0`,children:(0,R.jsx)(Vm,{value:e.idsText,onChange:n=>{let r=[...g];r[t]={...e,idsText:n.target.value},_(r)},placeholder:`org-1, org-2`})}),(0,R.jsx)(`button`,{className:`btn ghost sm`,disabled:g.length===1,onClick:()=>_(g.filter((e,n)=>n!==t)),title:`Remove scope row`,children:(0,R.jsx)(Ca,{size:14})})]},e.id)),(0,R.jsx)(`div`,{children:(0,R.jsxs)(`button`,{className:`btn ghost sm`,onClick:()=>_([...g,{id:Pg(`multi-root`),tenantRoot:se,idsText:``}]),children:[(0,R.jsx)(na,{size:14}),`Add root`]})})]}),u===`global`&&(0,R.jsx)($,{label:`Super / global reason`,description:`Required for audit context.`,children:(0,R.jsx)(Vm,{value:v,onChange:e=>y(e.target.value),placeholder:`superuser access for support investigation`})}),(0,R.jsxs)(`details`,{children:[(0,R.jsx)(`summary`,{className:`muted`,style:{cursor:`pointer`,fontSize:11,fontWeight:600,textTransform:`uppercase`,letterSpacing:`0.04em`},children:`Advisory context`}),(0,R.jsxs)(`div`,{style:{display:`grid`,gap:8,marginTop:8},children:[(0,R.jsxs)(`div`,{style:{display:`grid`,gridTemplateColumns:`1fr 1fr`,gap:8},children:[(0,R.jsx)($,{label:`Role`,children:(0,R.jsx)(Vm,{value:b.role,onChange:e=>x({...b,role:e.target.value}),placeholder:`regional_manager`})}),(0,R.jsx)($,{label:`Label`,children:(0,R.jsx)(Vm,{value:b.label,onChange:e=>x({...b,label:e.target.value}),placeholder:`Jane Smith, Northeast`})}),(0,R.jsx)($,{label:`Department`,children:(0,R.jsx)(Vm,{value:b.department,onChange:e=>x({...b,department:e.target.value}),placeholder:`operations`})}),(0,R.jsx)($,{label:`Region`,children:(0,R.jsx)(Vm,{value:b.region,onChange:e=>x({...b,region:e.target.value}),placeholder:`northeast`})})]}),(0,R.jsx)($,{label:`Description`,children:(0,R.jsx)(Hh,{value:b.description,onChange:e=>x({...b,description:e.target.value}),placeholder:`Business context for this user's scope.`,rows:2})}),S.map((e,t)=>(0,R.jsxs)(`div`,{style:{display:`grid`,gridTemplateColumns:`minmax(0, 1fr) minmax(0, 1fr) auto`,gap:8,alignItems:`end`},children:[(0,R.jsx)($,{label:`Attribute key`,className:`min-w-0`,children:(0,R.jsx)(Vm,{value:e.key,onChange:n=>{let r=[...S];r[t]={...e,key:n.target.value},C(r)},placeholder:`team`})}),(0,R.jsx)($,{label:`Attribute value`,className:`min-w-0`,children:(0,R.jsx)(Vm,{value:e.value,onChange:n=>{let r=[...S];r[t]={...e,value:n.target.value},C(r)},placeholder:`field-sales`})}),(0,R.jsx)(`button`,{className:`btn ghost sm`,onClick:()=>C(S.filter((e,n)=>n!==t)),title:`Remove attribute`,children:(0,R.jsx)(Ca,{size:14})})]},e.id)),(0,R.jsx)(`div`,{children:(0,R.jsxs)(`button`,{className:`btn ghost sm`,onClick:()=>C([...S,{id:Pg(`context-attribute`),key:``,value:``}]),children:[(0,R.jsx)(na,{size:14}),`Add attribute`]})})]})]}),(0,R.jsxs)(`div`,{style:{display:`grid`,gap:6},children:[(0,R.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,justifyContent:`space-between`,gap:8},children:[(0,R.jsx)(`span`,{className:`muted`,style:{fontSize:11,fontWeight:600,textTransform:`uppercase`,letterSpacing:`0.04em`},children:`tenantScope JSON preview`}),w&&(0,R.jsx)(Tg,{value:w})]}),(0,R.jsx)(`pre`,{className:`mono`,style:{minHeight:116,margin:0,overflow:`auto`,whiteSpace:`pre-wrap`,border:`1px solid var(--border)`,borderRadius:6,padding:10,fontSize:11,background:`var(--surface-2)`},children:w||T||`Complete the tenant scope fields to preview the JSON passed to ask().`}),T&&(0,R.jsx)(`span`,{style:{color:`var(--red-600)`,fontSize:12},children:T})]}),(0,R.jsxs)(`div`,{style:{display:`grid`,gap:6},children:[(0,R.jsx)(`span`,{className:`muted`,style:{fontSize:11,fontWeight:600,textTransform:`uppercase`,letterSpacing:`0.04em`},children:`SQL output mode`}),(0,R.jsxs)(`fieldset`,{className:`toggle-seg`,style:Ng,children:[(0,R.jsx)(`legend`,{className:`sr-only`,children:`SQL output mode`}),(0,R.jsx)(`button`,{className:E===`sql-only`?`active`:``,onClick:()=>D(`sql-only`),children:`Inline literals`}),(0,R.jsx)(`button`,{className:E===`sql-params`?`active`:``,onClick:()=>D(`sql-params`),children:`$N parameters`})]})]})]})]}),(0,R.jsxs)(`button`,{className:`btn primary`,disabled:N.has(`ask`),onClick:()=>void ee(),title:`Generate SQL (⌘↵)`,children:[N.has(`ask`)?(0,R.jsx)(Wi,{size:14,className:`animate-spin`}):(0,R.jsx)(_a,{size:14}),`Generate SQL`,(0,R.jsx)(`kbd`,{className:`kbd`,style:{marginLeft:4,opacity:.7},children:`⌘↵`})]}),o&&(0,R.jsx)(Ah,{status:o})]})}),j.length>0&&(0,R.jsxs)(`div`,{style:{borderTop:`1px solid var(--border)`,flex:1,overflow:`auto`},children:[(0,R.jsx)(`div`,{style:{padding:`8px var(--pad-x)`},children:(0,R.jsxs)(`span`,{className:`muted`,style:{fontSize:11,fontWeight:600,textTransform:`uppercase`,letterSpacing:`0.04em`},children:[`History (`,j.length,`)`]})}),(0,R.jsx)(`div`,{children:j.slice(0,20).map(e=>(0,R.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,justifyContent:`space-between`,gap:8,padding:`6px var(--pad-x)`,cursor:`pointer`,fontSize:12,borderBottom:`1px solid var(--border)`},onClick:()=>P(e),children:[(0,R.jsx)(`span`,{style:{overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`,flex:1},children:e.question}),(0,R.jsx)(`span`,{className:`chip ${e.mode===`rag`?`red`:``}`,style:{flexShrink:0},children:e.mode}),(0,R.jsx)(`button`,{className:`btn ghost sm`,onClick:t=>{t.stopPropagation(),ne(e.id)},title:`Delete`,style:{flexShrink:0,padding:2},children:`×`})]},e.id))})]})]}),(0,R.jsx)(`div`,{style:{overflow:`auto`},children:s?(0,R.jsxs)(`div`,{style:{display:`grid`,gap:0},children:[(0,R.jsxs)(`section`,{style:{padding:`var(--pad-y) var(--pad-x)`,borderBottom:`1px solid var(--border)`},children:[(0,R.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,justifyContent:`space-between`,marginBottom:8},children:[(0,R.jsx)(`h3`,{style:{fontSize:13,fontWeight:600},children:`Generated SQL`}),s.sql&&(0,R.jsx)(Tg,{value:s.sql})]}),s.sql?(0,R.jsx)(`pre`,{className:`sql-block`,children:s.sql}):(0,R.jsx)(vg,{text:`No SQL generated.`})]}),s.explain!==null&&s.explain!==void 0&&(0,R.jsx)(`section`,{style:{padding:`var(--pad-y) var(--pad-x)`,borderBottom:`1px solid var(--border)`},children:(0,R.jsx)(zg,{explain:s.explain})}),s.tenant?.enabled&&(0,R.jsxs)(`section`,{style:{padding:`var(--pad-y) var(--pad-x)`,borderBottom:`1px solid var(--border)`},children:[(0,R.jsx)(`h3`,{style:{fontSize:13,fontWeight:600,marginBottom:8},children:`Tenant Params`}),s.tenant.params.length>0?(0,R.jsxs)(`div`,{style:{padding:8,border:`1px solid var(--border)`,borderRadius:`var(--radius)`,fontSize:12},children:[(0,R.jsx)(`span`,{style:{fontWeight:600},children:`Positional params:`}),` `,(0,R.jsx)(`code`,{children:JSON.stringify(s.tenant.params)})]}):(0,R.jsx)(vg,{text:`No tenant params.`})]}),(0,R.jsxs)(`div`,{style:{padding:`var(--pad-y) var(--pad-x)`,borderBottom:`1px solid var(--border)`,display:`flex`,flexDirection:`column`,gap:8},children:[A&&!A.enabled&&(0,R.jsx)(`p`,{className:`muted`,style:{fontSize:12,margin:0},children:A.disabledReason}),A?.enabled&&(0,R.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,gap:8,flexWrap:`wrap`},children:[(0,R.jsx)(`span`,{className:`muted`,style:{fontSize:11,fontWeight:600},children:A.label}),A.configured?(0,R.jsx)(`span`,{className:`chip`,style:{fontSize:11},children:A.connectionKind===`file`?`file configured`:`URL configured`}):(0,R.jsx)(`span`,{className:`chip red`,style:{fontSize:11},children:A.connectionKind===`file`?`no file`:`no URL`}),A.installed?(0,R.jsxs)(`span`,{className:`chip`,style:{fontSize:11},children:[A.packageName,` ready`]}):(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`span`,{className:`chip red`,style:{fontSize:11},children:[A.packageName,` missing`]}),A.canInstallFromStudio&&(0,R.jsxs)(`button`,{className:`btn ghost sm`,disabled:N.has(`install-driver`),onClick:()=>void re(),style:{fontSize:11},children:[N.has(`install-driver`)?(0,R.jsx)(Wi,{size:12,className:`animate-spin`}):null,`Install `,A.packageName]}),!A.canInstallFromStudio&&A.manualInstallReason&&(0,R.jsx)(`span`,{className:`muted`,style:{fontSize:11},children:A.installCommand})]})]}),A?.enabled&&A.disabledReason&&(0,R.jsx)(`p`,{className:`muted`,style:{fontSize:12,margin:0},children:A.disabledReason}),A?.enabled&&(0,R.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,gap:12},children:[(0,R.jsxs)(`button`,{className:`btn primary`,disabled:N.has(`execute`)||!s.sql||!A.configured||!A.installed,onClick:()=>void te(),title:`Runs read-only · ${Math.round(A.timeoutMs/1e3)}s timeout · first ${A.maxRows} rows`,children:[N.has(`execute`)?(0,R.jsx)(Wi,{size:14,className:`animate-spin`}):(0,R.jsx)(ea,{size:14}),`Execute Query`]}),k&&(0,R.jsx)(Ah,{status:k})]})]}),(0,R.jsx)(Ag,{}),O?.ok===!0&&(0,R.jsxs)(`section`,{style:{padding:`var(--pad-y) var(--pad-x)`},children:[(0,R.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,justifyContent:`space-between`,marginBottom:8},children:[(0,R.jsx)(`h3`,{style:{fontSize:13,fontWeight:600},children:`Results`}),O.truncated&&(0,R.jsxs)(`span`,{className:`chip amber`,children:[`Showing first `,O.rowLimit,` rows`]})]}),O.columns&&O.rows?(0,R.jsx)(`div`,{style:{overflowX:`auto`},children:(0,R.jsxs)(`table`,{className:`tbl`,children:[(0,R.jsx)(`thead`,{children:(0,R.jsx)(`tr`,{children:O.columns.map(e=>(0,R.jsx)(`th`,{children:e},e))})}),(0,R.jsx)(`tbody`,{children:O.rows.map((e,t)=>(0,R.jsx)(`tr`,{children:e.map((e,t)=>(0,R.jsx)(`td`,{className:`mono`,style:{fontSize:11},children:e==null?(0,R.jsx)(`span`,{className:`muted`,children:`NULL`}):String(e)},t))},t))})]})}):(0,R.jsx)(vg,{text:`No results.`})]}),s.usage&&(0,R.jsx)(`section`,{style:{padding:`var(--pad-y) var(--pad-x)`,borderTop:`1px solid var(--border)`},children:(0,R.jsx)(Sg,{title:`Token usage`,usage:s.usage})})]}):(0,R.jsx)(`div`,{style:{display:`flex`,alignItems:`center`,justifyContent:`center`,height:`100%`,padding:32},children:(0,R.jsx)(vg,{text:`Ask a question to generate SQL`})})})]})})]})}function Ig(e){return typeof e==`string`?e:JSON.stringify(e,null,2)}function Lg(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.statementKind==`string`&&Array.isArray(t.checksVerified)&&t.checksVerified.every(e=>typeof e==`string`)&&typeof t.remediationNote==`string`}function Rg(e){return e.replace(/_/g,` `)}function zg({explain:e}){let[t,n]=(0,M.useState)(!1);return(0,R.jsxs)(`div`,{children:[(0,R.jsxs)(`button`,{type:`button`,className:`collapsible-btn`,onClick:()=>n(!t),children:[t?(0,R.jsx)(vi,{size:14}):(0,R.jsx)(bi,{size:14}),`Explain`]}),t&&(Lg(e)?(0,R.jsxs)(`div`,{style:{display:`grid`,gap:8,fontSize:12},children:[(0,R.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,gap:6},children:[(0,R.jsx)(`span`,{className:`muted`,style:{fontWeight:600},children:`Statement kind`}),(0,R.jsx)(`span`,{className:`chip`,children:e.statementKind})]}),(0,R.jsxs)(`div`,{style:{display:`grid`,gap:4},children:[(0,R.jsx)(`span`,{className:`muted`,style:{fontWeight:600},children:`Checks verified`}),(0,R.jsx)(`ul`,{style:{listStyle:`none`,margin:0,padding:0,display:`grid`,gap:4},children:e.checksVerified.map(e=>(0,R.jsxs)(`li`,{style:{display:`flex`,alignItems:`center`,gap:6},children:[(0,R.jsx)(gi,{size:13,style:{color:`var(--green-500)`,flexShrink:0}}),Rg(e)]},e))})]}),(0,R.jsx)(`p`,{className:`muted`,style:{margin:0,fontStyle:`italic`},children:e.remediationNote})]}):(0,R.jsx)(`pre`,{className:`plain-block`,children:Ig(e)}))]})}function Bg(){let{workspace:e}=vr(),{ragStatus:t}=jr();return e?(0,R.jsxs)(`main`,{className:`main-pane`,children:[(0,R.jsx)(`div`,{className:`main-hd`,children:(0,R.jsxs)(`div`,{className:`main-title`,children:[(0,R.jsxs)(`h1`,{children:[(0,R.jsx)(pa,{size:18,style:{display:`inline`,marginRight:8}}),`Settings`]}),(0,R.jsx)(`div`,{className:`main-sub`,children:`Workspace configuration and diagnostics`})]})}),(0,R.jsx)(`div`,{className:`main-body`,children:(0,R.jsxs)(`div`,{className:`stack`,style:{padding:`var(--pad-y) var(--pad-x)`},children:[(0,R.jsxs)(`section`,{className:`card`,children:[(0,R.jsx)(`div`,{className:`card-hd`,children:(0,R.jsx)(`h3`,{children:`Workspace`})}),(0,R.jsx)(`div`,{className:`card-bd`,children:(0,R.jsxs)(`dl`,{className:`definition-list`,children:[(0,R.jsx)(`dt`,{children:`Schema ID`}),(0,R.jsx)(`dd`,{children:e.schemaId}),(0,R.jsx)(`dt`,{children:`Schema path`}),(0,R.jsx)(`dd`,{children:e.schemaDir}),(0,R.jsx)(`dt`,{children:`AI provider`}),(0,R.jsx)(`dd`,{children:e.aiProvider}),(0,R.jsx)(`dt`,{children:`Model`}),(0,R.jsx)(`dd`,{children:e.model}),(0,R.jsx)(`dt`,{children:`AI suggestions`}),(0,R.jsx)(`dd`,{children:e.aiConfigured?`Configured`:`Not configured`})]})})]}),(0,R.jsxs)(`section`,{className:`card`,children:[(0,R.jsx)(`div`,{className:`card-hd`,children:(0,R.jsx)(`h3`,{children:`RAG Store`})}),(0,R.jsx)(`div`,{className:`card-bd`,children:t?(0,R.jsxs)(`dl`,{className:`definition-list`,children:[(0,R.jsx)(`dt`,{children:`Embedder`}),(0,R.jsx)(`dd`,{children:t.embedder.kind===`mock`?`mock (local lexical)`:`${t.embedder.provider??`unknown provider`} · ${t.embedder.model??`no model`}`}),(0,R.jsx)(`dt`,{children:`Store`}),(0,R.jsx)(`dd`,{children:t.store.kind}),(0,R.jsx)(`dt`,{children:`Lock file`}),(0,R.jsx)(`dd`,{children:t.files.lock?`present`:`missing`}),t.store.kind===`file`&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`dt`,{children:`Base path`}),(0,R.jsx)(`dd`,{children:t.store.basePath??`n/a`}),(0,R.jsx)(`dt`,{children:`Embeddings JSON`}),(0,R.jsx)(`dd`,{children:t.files.embeddingsJson?`present`:`missing`}),(0,R.jsx)(`dt`,{children:`Embeddings binary`}),(0,R.jsx)(`dd`,{children:t.files.embeddingsBin?`present`:`missing`})]}),t.store.kind===`pgvector`&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`dt`,{children:`Table`}),(0,R.jsx)(`dd`,{children:t.store.table??`askdb_rag_chunks`}),(0,R.jsx)(`dt`,{children:`Index strategy`}),(0,R.jsx)(`dd`,{children:t.store.indexStrategy??`default`})]}),t.store.kind===`memory`&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`dt`,{children:`Persistence`}),(0,R.jsx)(`dd`,{children:`In-process only`})]})]}):(0,R.jsx)(vg,{text:`RAG status is unavailable.`})})]}),(0,R.jsxs)(`section`,{className:`card`,children:[(0,R.jsx)(`div`,{className:`card-hd`,children:(0,R.jsx)(`h3`,{children:`Schema Warnings`})}),(0,R.jsx)(`div`,{className:`card-bd`,children:e.warnings.length>0?(0,R.jsx)(`div`,{style:{display:`grid`,gap:8},children:e.warnings.map((e,t)=>(0,R.jsx)(`pre`,{className:`warning-block`,children:typeof e==`string`?e:JSON.stringify(e,null,2)},t))}):(0,R.jsx)(vg,{text:`No schema warnings.`})})]})]})})]}):null}function Vg({label:e,description:t,value:n,onChange:r,disabled:i}){let[a,o]=(0,M.useState)(!1);return a&&!i?(0,R.jsx)($,{label:e,description:t,children:(0,R.jsx)(Vm,{autoFocus:!0,value:n,onChange:e=>r(e.target.value.toUpperCase()),onBlur:()=>o(!1),onKeyDown:e=>{e.key===`Enter`&&e.currentTarget.blur()}})}):(0,R.jsx)($,{label:e,description:t,children:(0,R.jsxs)(`button`,{type:`button`,className:`env-var-field`,disabled:i,onClick:()=>o(!0),children:[(0,R.jsx)(`span`,{className:`mono env-var-field-value`,children:n}),!i&&(0,R.jsx)(Qi,{size:12,className:`muted`})]})})}var Hg=[{value:`postgres`,label:`PostgreSQL`},{value:`mysql`,label:`MySQL`},{value:`sqlite`,label:`SQLite`},{value:`sqlserver`,label:`SQL Server`},{value:`prisma`,label:`Prisma schema file (no live database)`}],Ug=[{value:`openai`,label:`OpenAI`,keyEnv:`OPENAI_API_KEY`,modelEnv:`OPENAI_MODEL`},{value:`anthropic`,label:`Anthropic`,keyEnv:`ANTHROPIC_API_KEY`,modelEnv:`ANTHROPIC_MODEL`},{value:`google`,label:`Google (Gemini)`,keyEnv:`GOOGLE_GENERATIVE_AI_API_KEY`,modelEnv:`GOOGLE_AI_MODEL`},{value:`azure`,label:`Azure OpenAI`,keyEnv:`AZURE_OPENAI_API_KEY`,modelEnv:`AZURE_OPENAI_DEPLOYMENT`},{value:`foundry`,label:`Azure AI Foundry`,keyEnv:`AZURE_OPENAI_API_KEY`,modelEnv:`AZURE_OPENAI_DEPLOYMENT`},{value:`gateway`,label:`Vercel AI Gateway`,keyEnv:`AI_GATEWAY_API_KEY`,modelEnv:`ASKDB_AI_MODEL`}],Wg=[{value:`file`,label:`File (default, no setup required)`},{value:`memory`,label:`Memory (fast, non-persistent)`},{value:`pgvector`,label:`pgvector (Postgres vector store)`}],Gg=[{value:`postgres`,label:`PostgreSQL`},{value:`mysql`,label:`MySQL`},{value:`sqlite`,label:`SQLite`},{value:`sqlserver`,label:`SQL Server`}],Kg={postgres:`DATABASE_URL`,mysql:`DATABASE_URL`,sqlserver:`DATABASE_URL`,sqlite:``,prisma:``},qg={postgres:`DATABASE_URL`,mysql:`DATABASE_URL`,sqlserver:`DATABASE_URL`,sqlite:``},Jg=`h-9 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring`;function Yg({stepNumber:e,configResult:t,busy:n,database:r,onDatabaseChange:i,needsConnectionEnv:a,connectionEnv:o,onConnectionEnvChange:s,sqliteFile:c,onSqliteFileChange:l,prismaSchema:u,onPrismaSchemaChange:d,aiProvider:f,onAiProviderChange:p,aiKeyEnv:m,onAiKeyEnvChange:h,aiModelEnv:g,onAiModelEnvChange:_,schemaOut:v,onSchemaOutChange:y,ragStore:b,onRagStoreChange:x,pgvectorEnv:S,onPgvectorEnvChange:C,studioExecuteEnabled:w,onStudioExecuteEnabledChange:T,studioExecuteProvider:E,onStudioExecuteProviderChange:D,studioExecuteConnectionEnv:O,onStudioExecuteConnectionEnvChange:k,studioExecuteSqliteFile:A,onStudioExecuteSqliteFileChange:j,onWriteConfig:M}){let N=!!t;return(0,R.jsxs)(`div`,{className:`card`,children:[(0,R.jsxs)(`div`,{className:`card-hd`,children:[(0,R.jsxs)(`h3`,{children:[(0,R.jsx)(Mi,{size:14}),` `,e,` · Database & model provider`]}),t&&(0,R.jsxs)(`span`,{className:`chip green`,children:[(0,R.jsx)(gi,{size:11}),` config written`]})]}),(0,R.jsxs)(`div`,{className:`card-bd`,style:{display:`grid`,gap:12},children:[(0,R.jsx)($,{label:`Database engine`,children:(0,R.jsx)(`select`,{className:Jg,value:r,disabled:N,onChange:e=>i(e.target.value),children:Hg.map(e=>(0,R.jsx)(`option`,{value:e.value,children:e.label},e.value))})}),a&&(0,R.jsx)(Vg,{label:`Connection URL env var name`,description:`The NAME of the environment variable — the actual URL goes in .env, never here.`,value:o,disabled:N,onChange:s}),r===`sqlite`&&(0,R.jsx)($,{label:`SQLite file path`,description:`Relative to the project root.`,children:(0,R.jsx)(Vm,{value:c,disabled:N,onChange:e=>l(e.target.value)})}),r===`prisma`&&(0,R.jsx)($,{label:`Prisma schema path`,description:`Leave empty to auto-discover prisma/schema.prisma.`,children:(0,R.jsx)(Vm,{value:u,disabled:N,onChange:e=>d(e.target.value),placeholder:`./prisma/schema.prisma`})}),(0,R.jsx)($,{label:`AI provider`,children:(0,R.jsx)(`select`,{className:Jg,value:f,disabled:N,onChange:e=>p(e.target.value),children:Ug.map(e=>(0,R.jsx)(`option`,{value:e.value,children:e.label},e.value))})}),(0,R.jsx)(Vg,{label:`API key env var name`,description:`The NAME of the environment variable holding your model API key.`,value:m,disabled:N,onChange:h}),(0,R.jsx)(Vg,{label:`Model env var name (optional)`,description:`The NAME of the environment variable for a model override. Leave empty to use the provider default.`,value:g,disabled:N,onChange:_}),(0,R.jsx)($,{label:`Schema artifact directory`,description:`Where introspection writes the schema artifact.`,children:(0,R.jsx)(Vm,{value:v,disabled:N,onChange:e=>y(e.target.value)})}),(0,R.jsx)($,{label:`RAG store`,description:`Where table/relationship embeddings are indexed for retrieval.`,children:(0,R.jsx)(`select`,{className:Jg,value:b,disabled:N,onChange:e=>x(e.target.value),children:Wg.map(e=>(0,R.jsx)(`option`,{value:e.value,children:e.label},e.value))})}),b===`pgvector`&&(0,R.jsx)(Vg,{label:`pgvector connection URL env var name`,description:`The NAME of the environment variable — the actual URL goes in .env, never here.`,value:S,disabled:N,onChange:C}),(0,R.jsxs)(`label`,{style:{display:`flex`,alignItems:`center`,gap:8},children:[(0,R.jsx)(`input`,{type:`checkbox`,checked:w,disabled:N,onChange:e=>T(e.target.checked)}),(0,R.jsx)(`span`,{style:{fontSize:13},children:`Enable Studio execute (run queries from the browser playground)`})]}),(0,R.jsx)(`p`,{className:`muted`,style:{fontSize:12,margin:0},children:`Off by default. When on, Studio runs generated SELECTs read-only with a timeout and row cap. Point it at a read-only database role.`}),w&&r===`prisma`&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)($,{label:`Studio execute database`,description:`Prisma has no live database of its own — pick one for the browser playground to run queries against.`,children:(0,R.jsx)(`select`,{className:Jg,value:E,disabled:N,onChange:e=>D(e.target.value),children:Gg.map(e=>(0,R.jsx)(`option`,{value:e.value,children:e.label},e.value))})}),E===`sqlite`?(0,R.jsx)($,{label:`SQLite file path`,description:`Relative to the project root.`,children:(0,R.jsx)(Vm,{value:A,disabled:N,onChange:e=>j(e.target.value)})}):(0,R.jsx)(Vg,{label:`Connection URL env var name`,description:`The NAME of the environment variable — the actual URL goes in .env, never here.`,value:O,disabled:N,onChange:k})]}),!t&&(0,R.jsx)(`div`,{children:(0,R.jsxs)(`button`,{type:`button`,className:`btn primary`,disabled:n===`config`,onClick:M,children:[n===`config`?(0,R.jsx)(Wi,{size:14,className:`animate-spin`}):(0,R.jsx)(gi,{size:14}),`Write askdb.config.ts`]})}),t&&(0,R.jsxs)(`div`,{style:{display:`grid`,gap:6},children:[(0,R.jsxs)(`p`,{className:`muted`,style:{fontSize:12.5},children:[`Wrote `,(0,R.jsx)(`code`,{className:`mono`,children:t.configPath}),t.envExamplePath?(0,R.jsxs)(R.Fragment,{children:[` and `,(0,R.jsx)(`code`,{className:`mono`,children:t.envExamplePath})]}):null,t.packageJsonCreated?(0,R.jsxs)(R.Fragment,{children:[` (plus a minimal `,(0,R.jsx)(`code`,{className:`mono`,children:`package.json`}),`)`]}):null,`.`]}),t.installed&&t.installed.length>0&&(0,R.jsxs)(`p`,{className:`muted`,style:{fontSize:12.5},children:[`Installed into your project: `,(0,R.jsx)(`code`,{className:`mono`,children:t.installed.join(` `)}),`.`]}),t.manualInstallCommand&&(0,R.jsxs)(`div`,{style:{display:`grid`,gap:6,border:`1px solid var(--amber-500)`,borderRadius:6,padding:10},children:[(0,R.jsx)(`span`,{style:{fontSize:12.5,fontWeight:600},children:`One manual step: install the dependencies`}),(0,R.jsx)(`p`,{className:`muted`,style:{fontSize:12},children:`The wizard couldn't install packages automatically. Run this in your project, then continue below:`}),(0,R.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,gap:8},children:[(0,R.jsx)(`code`,{className:`mono`,style:{flex:1,fontSize:12,border:`1px solid var(--border)`,borderRadius:6,padding:`6px 8px`,background:`var(--surface-2)`},children:t.manualInstallCommand}),(0,R.jsx)(Tg,{value:t.manualInstallCommand})]})]})]})]})]})}function Xg({stepNumber:e,envVars:t}){let n=t.map(e=>`${e.name}=`).join(`
|
|
99
99
|
`);return(0,R.jsxs)(`div`,{className:`card`,children:[(0,R.jsx)(`div`,{className:`card-hd`,children:(0,R.jsxs)(`h3`,{children:[(0,R.jsx)(Ii,{size:14}),` `,e,` · Add your secrets to .env`]})}),(0,R.jsxs)(`div`,{className:`card-bd`,style:{display:`grid`,gap:10},children:[(0,R.jsxs)(`p`,{className:`muted`,style:{fontSize:12.5,lineHeight:1.6},children:[`Create a `,(0,R.jsx)(`code`,{className:`mono`,children:`.env`}),` file next to `,(0,R.jsx)(`code`,{className:`mono`,children:`askdb.config.ts`}),` and fill in the values. Studio never asks for secret values — they stay on disk, outside this UI.`]}),(0,R.jsxs)(`div`,{style:{display:`flex`,alignItems:`flex-start`,gap:8},children:[(0,R.jsx)(`pre`,{className:`mono`,style:{flex:1,margin:0,border:`1px solid var(--border)`,borderRadius:6,padding:10,fontSize:12,background:`var(--surface-2)`},children:t.map(e=>`${e.name}= # ${e.purpose}`).join(`
|
|
100
|
-
`)}),(0,R.jsx)(Tg,{value:n})]})]})]})}function Zg({stepNumber:e,busy:t,onIntrospect:n}){return(0,R.jsxs)(`div`,{className:`card`,children:[(0,R.jsx)(`div`,{className:`card-hd`,children:(0,R.jsxs)(`h3`,{children:[(0,R.jsx)(_a,{size:14}),` `,e,` · Introspect your database`]})}),(0,R.jsxs)(`div`,{className:`card-bd`,style:{display:`grid`,gap:10},children:[(0,R.jsx)(`p`,{className:`muted`,style:{fontSize:12.5,lineHeight:1.6},children:`Reads your schema structure (tables, columns, relationships — never rows) and writes the schema artifact. When it finishes, Studio opens on the Overview.`}),(0,R.jsx)(`div`,{children:(0,R.jsxs)(`button`,{type:`button`,className:`btn primary`,disabled:t===`introspect`,onClick:n,children:[t===`introspect`?(0,R.jsx)(Wi,{size:14,className:`animate-spin`}):(0,R.jsx)(Mi,{size:14}),`Run introspection`]})})]})]})}function Qg({status:e,onComplete:t}){let n=e.reason===`no-artifact`,[r,i]=(0,M.useState)(`postgres`),[a,o]=(0,M.useState)(`DATABASE_URL`),s=(0,M.useRef)(!1),[c,l]=(0,M.useState)(`./data.db`),[u,d]=(0,M.useState)(``),[f,p]=(0,M.useState)(`openai`),[m,h]=(0,M.useState)(`OPENAI_API_KEY`),g=(0,M.useRef)(!1),[_,v]=(0,M.useState)(`OPENAI_MODEL`),y=(0,M.useRef)(!1),[b,x]=(0,M.useState)(`./askdb`),[S,C]=(0,M.useState)(`file`),[w,T]=(0,M.useState)(`ASKDB_PGVECTOR_URL`),[E,D]=(0,M.useState)(!1),[O,k]=(0,M.useState)(`postgres`),[A,j]=(0,M.useState)(`DATABASE_URL`),N=(0,M.useRef)(!1),[ee,te]=(0,M.useState)(`./data.db`),[P,ne]=(0,M.useState)(null),[re,ie]=(0,M.useState)(null),[ae,oe]=(0,M.useState)(null),se=r
|
|
100
|
+
`)}),(0,R.jsx)(Tg,{value:n})]})]})]})}function Zg({stepNumber:e,busy:t,onIntrospect:n}){return(0,R.jsxs)(`div`,{className:`card`,children:[(0,R.jsx)(`div`,{className:`card-hd`,children:(0,R.jsxs)(`h3`,{children:[(0,R.jsx)(_a,{size:14}),` `,e,` · Introspect your database`]})}),(0,R.jsxs)(`div`,{className:`card-bd`,style:{display:`grid`,gap:10},children:[(0,R.jsx)(`p`,{className:`muted`,style:{fontSize:12.5,lineHeight:1.6},children:`Reads your schema structure (tables, columns, relationships — never rows) and writes the schema artifact. When it finishes, Studio opens on the Overview.`}),(0,R.jsx)(`div`,{children:(0,R.jsxs)(`button`,{type:`button`,className:`btn primary`,disabled:t===`introspect`,onClick:n,children:[t===`introspect`?(0,R.jsx)(Wi,{size:14,className:`animate-spin`}):(0,R.jsx)(Mi,{size:14}),`Run introspection`]})})]})]})}function Qg({status:e,onComplete:t}){let n=e.reason===`no-artifact`,[r,i]=(0,M.useState)(`postgres`),[a,o]=(0,M.useState)(`DATABASE_URL`),s=(0,M.useRef)(!1),[c,l]=(0,M.useState)(`./data.db`),[u,d]=(0,M.useState)(``),[f,p]=(0,M.useState)(`openai`),[m,h]=(0,M.useState)(`OPENAI_API_KEY`),g=(0,M.useRef)(!1),[_,v]=(0,M.useState)(`OPENAI_MODEL`),y=(0,M.useRef)(!1),[b,x]=(0,M.useState)(`./askdb`),[S,C]=(0,M.useState)(`file`),[w,T]=(0,M.useState)(`ASKDB_PGVECTOR_URL`),[E,D]=(0,M.useState)(!1),[O,k]=(0,M.useState)(`postgres`),[A,j]=(0,M.useState)(`DATABASE_URL`),N=(0,M.useRef)(!1),[ee,te]=(0,M.useState)(`./data.db`),[P,ne]=(0,M.useState)(null),[re,ie]=(0,M.useState)(null),[ae,oe]=(0,M.useState)(null),se=Kg[r]!==``,ce=n||P!==null,le=(0,M.useMemo)(()=>{if(P)return P.envVars;let e=new Map,t=t=>{t.name&&!e.has(t.name)&&e.set(t.name,t)};if(t({name:m,purpose:`${f} API key`,requiredForIntrospection:!1}),_&&t({name:_,purpose:`${f} model override`,requiredForIntrospection:!1}),se&&t({name:a,purpose:`${r} connection URL`,requiredForIntrospection:!0}),S===`pgvector`&&t({name:w,purpose:`pgvector connection URL`,requiredForIntrospection:!1}),E){let e=r===`prisma`?O:r;e!==`sqlite`&&t({name:r===`prisma`?A:a,purpose:`${e} connection URL (Studio execute)`,requiredForIntrospection:!1})}return Array.from(e.values())},[P,m,f,_,se,a,r,S,w,E,O,A]),ue=(0,M.useCallback)(e=>{i(e),s.current||o(Kg[e]||`DATABASE_URL`)},[]),de=(0,M.useCallback)(e=>{p(e);let t=Ug.find(t=>t.value===e);g.current||h(t?.keyEnv??`OPENAI_API_KEY`),y.current||v(t?.modelEnv??``)},[]),fe=(0,M.useCallback)(e=>{k(e),N.current||j(qg[e]||`DATABASE_URL`)},[]),pe=(0,M.useCallback)(async()=>{ie(`config`),oe(null);try{let e=r===`prisma`?O:r,t=await or({database:r,aiProvider:f,...se&&a?{connectionEnv:a}:{},...r===`sqlite`&&c?{sqliteFile:c}:{},...r===`prisma`&&u?{prismaSchema:u}:{},...m?{aiKeyEnv:m}:{},..._?{aiModelEnv:_}:{},...b?{schemaOut:b}:{},ragStore:S,...S===`pgvector`&&w?{pgvectorEnv:w}:{},studioExecute:E,...E?{studioExecuteProvider:e,...e===`sqlite`?{studioExecuteSqliteFile:r===`prisma`?ee:c}:{studioExecuteConnectionEnv:r===`prisma`?A:a}}:{}});ne(t)}catch(e){oe(e instanceof Error?e.message:String(e))}finally{ie(null)}},[r,f,se,a,c,u,m,_,b,S,w,E,O,A,ee]),me=(0,M.useCallback)(async()=>{ie(`introspect`),oe(null);try{await sr(),t()}catch(e){oe(e instanceof Error?e.message:String(e))}finally{ie(null)}},[t]),he=n?1:2,F=n?2:3;return(0,R.jsx)(`div`,{className:`app-shell`,style:{display:`flex`,alignItems:`flex-start`,justifyContent:`center`,overflow:`auto`,padding:`48px 16px`},children:(0,R.jsxs)(`div`,{style:{width:`100%`,maxWidth:640,display:`grid`,gap:16},children:[(0,R.jsxs)(`div`,{children:[(0,R.jsxs)(`h1`,{style:{fontSize:20,fontWeight:700,display:`flex`,alignItems:`center`,gap:8},children:[(0,R.jsx)(Ta,{size:18}),` Set up AskDB`]}),(0,R.jsx)(`p`,{className:`muted`,style:{fontSize:13,marginTop:6,lineHeight:1.6},children:n?(0,R.jsxs)(R.Fragment,{children:[`Config found at `,(0,R.jsx)(`code`,{className:`mono`,children:e.configPath}),`, but no schema artifact yet. Run introspection to create it.`]}):(0,R.jsxs)(R.Fragment,{children:[`No `,(0,R.jsx)(`code`,{className:`mono`,children:`askdb.config.ts`}),` found in `,(0,R.jsx)(`code`,{className:`mono`,children:e.projectDir}),`. Answer two questions and Studio writes it for you — your secrets stay in `,(0,R.jsx)(`code`,{className:`mono`,children:`.env`}),`, on your machine.`]})})]}),!n&&(0,R.jsx)(Yg,{stepNumber:1,configResult:P,busy:re,database:r,onDatabaseChange:ue,needsConnectionEnv:se,connectionEnv:a,onConnectionEnvChange:e=>{o(e),s.current=!0},sqliteFile:c,onSqliteFileChange:l,prismaSchema:u,onPrismaSchemaChange:d,aiProvider:f,onAiProviderChange:de,aiKeyEnv:m,onAiKeyEnvChange:e=>{h(e),g.current=!0},aiModelEnv:_,onAiModelEnvChange:e=>{v(e),y.current=!0},schemaOut:b,onSchemaOutChange:x,ragStore:S,onRagStoreChange:C,pgvectorEnv:w,onPgvectorEnvChange:T,studioExecuteEnabled:E,onStudioExecuteEnabledChange:D,studioExecuteProvider:O,onStudioExecuteProviderChange:fe,studioExecuteConnectionEnv:A,onStudioExecuteConnectionEnvChange:e=>{j(e),N.current=!0},studioExecuteSqliteFile:ee,onStudioExecuteSqliteFileChange:te,onWriteConfig:()=>void pe()}),ce&&(0,R.jsx)(Xg,{stepNumber:he,envVars:le}),ce&&(0,R.jsx)(Zg,{stepNumber:F,busy:re,onIntrospect:()=>void me()}),ae&&(0,R.jsx)(`div`,{className:`card`,style:{borderColor:`var(--red-600)`},children:(0,R.jsx)(`div`,{className:`card-bd`,children:(0,R.jsx)(`p`,{style:{color:`var(--red-600)`,fontSize:12.5,whiteSpace:`pre-wrap`},children:ae})})}),(0,R.jsxs)(`p`,{className:`muted tiny`,style:{lineHeight:1.6},children:[`Prefer the terminal? `,(0,R.jsx)(`code`,{className:`mono`,children:`npx askdb init`}),` runs the same setup as a CLI wizard.`]})]})})}function $g(){return(0,R.jsx)(Vn,{children:(0,R.jsx)(xr,{children:(0,R.jsx)(Pr,{children:(0,R.jsx)(e_,{})})})})}function e_(){let{load:e,loadState:t,setupStatus:n,suggestionDialog:r,setSuggestionDialog:i,applySuggestion:a}=vr(),{refreshRagStatus:o,ragAvailable:s}=jr();return(0,M.useEffect)(()=>{e().then(()=>void o())},[e,o]),t.kind===`setup`&&n?(0,R.jsx)(Qg,{status:n,onComplete:()=>void e().then(()=>void o())}):t.kind===`loading`?(0,R.jsx)(`div`,{className:`app-shell`,style:{display:`flex`,alignItems:`center`,justifyContent:`center`},children:(0,R.jsx)(`p`,{style:{color:`var(--ink-400)`,fontSize:13},children:`Loading workspace…`})}):t.kind===`error`?(0,R.jsx)(`div`,{className:`app-shell`,style:{display:`flex`,alignItems:`center`,justifyContent:`center`},children:(0,R.jsxs)(`div`,{style:{textAlign:`center`},children:[(0,R.jsx)(`p`,{style:{color:`var(--red-600)`,fontWeight:600,marginBottom:8},children:`Failed to load workspace`}),(0,R.jsx)(`p`,{style:{color:`var(--ink-400)`,fontSize:13},children:t.message})]})}):(0,R.jsxs)(Hr,{ragAvailable:s,children:[(0,R.jsxs)(ch,{defaultOpen:!0,className:`!min-h-0 h-svh`,style:{"--sidebar-width":`var(--nav-w)`},children:[(0,R.jsx)(Dh,{}),(0,R.jsxs)(dh,{className:`min-h-0 overflow-hidden`,children:[(0,R.jsxs)(`header`,{className:`topbar`,children:[(0,R.jsx)(uh,{className:`-ml-1`}),(0,R.jsx)(Hm,{orientation:`vertical`,className:`mr-2 !h-4`}),(0,R.jsx)(Ch,{})]}),(0,R.jsx)(`div`,{className:`app-content`,children:(0,R.jsxs)(un,{children:[(0,R.jsx)(cn,{path:`/`,element:(0,R.jsx)(on,{to:`/overview`,replace:!0})}),(0,R.jsx)(cn,{path:`/overview`,element:(0,R.jsx)(jh,{})}),(0,R.jsx)(cn,{path:`/tables`,element:(0,R.jsx)(Ih,{}),children:(0,R.jsxs)(cn,{path:`:schema/:name`,element:(0,R.jsx)(Lh,{}),children:[(0,R.jsx)(cn,{index:!0,element:(0,R.jsx)(on,{to:`enrichment`,replace:!0})}),(0,R.jsx)(cn,{path:`enrichment`,element:(0,R.jsx)(Gh,{})}),(0,R.jsx)(cn,{path:`schema`,element:(0,R.jsx)(Jh,{})}),(0,R.jsx)(cn,{path:`sensitivity`,element:(0,R.jsx)(Yh,{})})]})}),(0,R.jsx)(cn,{path:`/concepts`,element:(0,R.jsx)(eg,{})}),(0,R.jsx)(cn,{path:`/tenancy`,element:(0,R.jsx)(og,{})}),(0,R.jsx)(cn,{path:`/rag-index`,element:(0,R.jsx)(Cg,{})}),(0,R.jsx)(cn,{path:`/playground`,element:(0,R.jsx)(Fg,{})}),(0,R.jsx)(cn,{path:`/settings`,element:(0,R.jsx)(Bg,{})})]})})]})]}),r&&(0,R.jsx)(Oh,{dialog:r,onApply:a,onClose:()=>i(null)})]})}var t_=document.getElementById(`root`);if(!t_)throw Error(`Missing #root element.`);(0,Ln.createRoot)(t_).render((0,R.jsx)(M.StrictMode,{children:(0,R.jsx)(Tn,{children:(0,R.jsx)($g,{})})}));
|
package/dist/client/index.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>AskDB Studio</title>
|
|
7
7
|
<link rel="icon" type="image/png" media="(prefers-color-scheme: light)" href="/assets/brand/light-icon.png" />
|
|
8
8
|
<link rel="icon" type="image/png" media="(prefers-color-scheme: dark)" href="/assets/brand/dark-icon.png" />
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-DX7u2yPd.js"></script>
|
|
10
10
|
<link rel="stylesheet" crossorigin href="/assets/index-Bl9jqOjj.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"introspection.d.ts","sourceRoot":"","sources":["../src/introspection.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AA+B3B,MAAM,MAAM,uBAAuB,GAC/B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;;;;GAKG;AACH,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,uBAAuB,CAAC,CAevF;AAaD,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,OAAO,CAAC;CAC9B,GAAG,OAAO,CAAC,sBAAsB,CAAC,
|
|
1
|
+
{"version":3,"file":"introspection.d.ts","sourceRoot":"","sources":["../src/introspection.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AA+B3B,MAAM,MAAM,uBAAuB,GAC/B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;;;;GAKG;AACH,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,uBAAuB,CAAC,CAevF;AAaD,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,OAAO,CAAC;CAC9B,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAqClC"}
|
package/dist/introspection.js
CHANGED
|
@@ -90,6 +90,7 @@ export async function runStudioIntrospection(options) {
|
|
|
90
90
|
outDir: options.outDir,
|
|
91
91
|
schemaId,
|
|
92
92
|
existingArtifactDir: options.hasExistingArtifact ? options.outDir : undefined,
|
|
93
|
+
filters: connectorConfig.filters,
|
|
93
94
|
}, { connector });
|
|
94
95
|
return {
|
|
95
96
|
engine: plan.engine,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"introspection.js","sourceRoot":"","sources":["../src/introspection.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"introspection.js","sourceRoot":"","sources":["../src/introspection.ts"],"names":[],"mappings":"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"}
|
package/dist/prisma-install.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The builds pnpm must approve to install `@askdb/prisma`, an optional peer (#259):
|
|
3
3
|
* `@prisma/engines` has a postinstall script, and pnpm 11 exits 1 on an unapproved one.
|
|
4
|
-
* Read by
|
|
4
|
+
* Read by the introspection plan's missing-package hint. Guided setup installs from the scaffold planner in `@askdb/config/scaffold`, which approves the same build (`setup-engines.test.ts` checks they match). `askdb init`'s copy is `apps/cli/src/prisma-install.ts`.
|
|
5
5
|
*/
|
|
6
6
|
export declare const PRISMA_BUILD_APPROVALS: readonly string[];
|
|
7
7
|
//# sourceMappingURL=prisma-install.d.ts.map
|
package/dist/prisma-install.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The builds pnpm must approve to install `@askdb/prisma`, an optional peer (#259):
|
|
3
3
|
* `@prisma/engines` has a postinstall script, and pnpm 11 exits 1 on an unapproved one.
|
|
4
|
-
* Read by
|
|
4
|
+
* Read by the introspection plan's missing-package hint. Guided setup installs from the scaffold planner in `@askdb/config/scaffold`, which approves the same build (`setup-engines.test.ts` checks they match). `askdb init`'s copy is `apps/cli/src/prisma-install.ts`.
|
|
5
5
|
*/
|
|
6
6
|
export const PRISMA_BUILD_APPROVALS = ["@prisma/engines"];
|
|
7
7
|
//# sourceMappingURL=prisma-install.js.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAgDjG,OAAO,EAQL,mBAAmB,EAUpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAcL,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAYV,WAAW,EAKX,kBAAkB,EAGnB,MAAM,iBAAiB,CAAC;AA0BzB,yEAAyE;AACzE,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAExE;AAMD,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAClC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,CAAC;AAsEF,wBAAgB,qCAAqC,CACnD,OAAO,EAAE,OAAO,mBAAmB,GAAG,SAAS,GAC9C,IAAI,CAEN;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CAuKvE;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,GAAG,kBAAkB,CA+C3E;AAksDD,gDAAgD;AAChD,eAAO,MAAM,mBAAmB,QAAc,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { existsSync, readdirSync, readFileSync, rmSync } from "node:fs";
|
|
3
3
|
import { createServer } from "node:http";
|
|
4
|
-
import { extname, relative, join, resolve,
|
|
4
|
+
import { extname, relative, join, resolve, sep } from "node:path";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { generateText as defaultGenerateText } from "ai";
|
|
8
8
|
import { ASKDB_AI_PROVIDERS, bootstrapAskDbEnv, getAskDbRuntimeConfig, } from "@askdb/config";
|
|
9
|
-
import {
|
|
9
|
+
import { findNearestPackageJsonDir, lockfilePackageManager, packageManagerAddArgs, packageManagerSpawnSpec, } from "@askdb/config/scaffold";
|
|
10
|
+
import { createAiRegistry, resolveReasoningEffortFromSection, } from "@askdb/ai";
|
|
10
11
|
import { ask, DEFAULT_TENANT_SQL_MODE, formatSchemaV2ForNlToSql, formatSensitiveReference, isBuiltInDialectId, loadSchema, saveSchemaFile, schemaHasSensitiveIdentifiers, SensitiveEnrichmentTargetError, SqlValidationError, validateSensitiveReferences, suggestEnrichment, tenantScopeSchema, SchemaParseError, tenantPolicyFrontmatterSchema, } from "@askdb/core";
|
|
12
|
+
import { EmptyIntrospectionError } from "@askdb/introspect";
|
|
11
13
|
import { buildSchemaIndex, chunkContentHash, chunkSchema, aiSdkEmbedderId, createAiSdkEmbedder, createFileStore, createMemoryStore, createPgvectorStore, createRetriever, detectEmbeddingDimensions, loadChunkerSourcesFromDir, PgvectorDimensionMismatchError, } from "@askdb/rag";
|
|
12
14
|
import { buildDefaultTableBody, buildFrontmatter, buildSuggestionContext, buildSuggestionTarget, buildTableDraft, loadWorkspace, replaceH2Section, replaceTableDescription, saveConcepts, saveTable, saveTenantPolicy, } from "@askdb/enrich";
|
|
13
15
|
import { EXECUTE_DRIVER_REGISTRY, executeDialectFor, isDriverInstalled, isStudioExecuteProvider, validateExecuteSql, } from "./execute-registry.js";
|
|
14
|
-
import { lockfilePackageManager, packageManagerAddArgs, packageManagerSpawnSpec, } from "./package-manager.js";
|
|
15
16
|
import { resolveStudioIntrospectionPlan, runStudioIntrospection } from "./introspection.js";
|
|
16
17
|
import { probeSetupState, writeSetupConfig, SetupError } from "./setup.js";
|
|
17
18
|
import { checkApiRequest, checkHost, createStudioSessionToken, injectSessionToken, } from "./request-guard.js";
|
|
@@ -203,11 +204,11 @@ export function serializeWorkspace(workspace) {
|
|
|
203
204
|
const rt = getAskDbRuntimeConfig();
|
|
204
205
|
const aiConfig = (() => {
|
|
205
206
|
try {
|
|
206
|
-
return ai.
|
|
207
|
+
return ai.resolveAiConfigFromSection(rt.ai.language);
|
|
207
208
|
}
|
|
208
209
|
catch {
|
|
209
|
-
// A misconfigured AI
|
|
210
|
-
// listing — surface it as "not configured" in the UI and let the user fix .
|
|
210
|
+
// A misconfigured AI section (e.g. azure without resourceName) shouldn't crash the workspace
|
|
211
|
+
// listing — surface it as "not configured" in the UI and let the user fix askdb.config.
|
|
211
212
|
return undefined;
|
|
212
213
|
}
|
|
213
214
|
})();
|
|
@@ -320,7 +321,7 @@ async function handleSetupIntrospect(state) {
|
|
|
320
321
|
"Install the project dependencies shown in setup step 1, then retry.");
|
|
321
322
|
}
|
|
322
323
|
const outDir = probe.outputDir;
|
|
323
|
-
const run = await
|
|
324
|
+
const run = await introspectForRequest({
|
|
324
325
|
outDir,
|
|
325
326
|
hasExistingArtifact: existsSync(join(outDir, "schema.json")),
|
|
326
327
|
});
|
|
@@ -345,7 +346,7 @@ async function handleResync(state) {
|
|
|
345
346
|
catch {
|
|
346
347
|
// Keep the snapshot the server started with when the config disappeared mid-session.
|
|
347
348
|
}
|
|
348
|
-
const run = await
|
|
349
|
+
const run = await introspectForRequest({
|
|
349
350
|
outDir: state.schemaDir,
|
|
350
351
|
schemaId: workspace.physical.schemaId,
|
|
351
352
|
hasExistingArtifact: true,
|
|
@@ -467,12 +468,12 @@ function saveDraft(state, tableId, draft) {
|
|
|
467
468
|
}
|
|
468
469
|
async function suggestForSource(state, source) {
|
|
469
470
|
const rt = getAskDbRuntimeConfig();
|
|
470
|
-
const aiConfig = ai.
|
|
471
|
+
const aiConfig = ai.resolveAiConfigFromSection(rt.ai.language);
|
|
471
472
|
if (!aiConfig) {
|
|
472
473
|
throw new StudioHttpError(400, ai.keyMissingMessage("AI enrichment suggestions"));
|
|
473
474
|
}
|
|
474
475
|
const model = await ai.createLanguageModel(aiConfig);
|
|
475
|
-
const reasoningEffort =
|
|
476
|
+
const reasoningEffort = resolveReasoningEffortFromSection(rt.ai.language.reasoning, "enrichment");
|
|
476
477
|
const providerOptions = reasoningEffort
|
|
477
478
|
? ai.resolveProviderOptions(aiConfig, { reasoningEffort })
|
|
478
479
|
: undefined;
|
|
@@ -572,7 +573,7 @@ function tenantPolicySchemaForPrompt(schema, omitSensitive) {
|
|
|
572
573
|
}
|
|
573
574
|
async function suggestTenantPolicyDraft(state) {
|
|
574
575
|
const rt = getAskDbRuntimeConfig();
|
|
575
|
-
const model = await ai.
|
|
576
|
+
const model = await ai.createLanguageModelFromSection(rt.ai.language);
|
|
576
577
|
if (!model) {
|
|
577
578
|
throw new StudioHttpError(400, ai.keyMissingMessage("AI tenant policy suggestion"));
|
|
578
579
|
}
|
|
@@ -641,11 +642,11 @@ If the schema has no clear multi-tenant pattern, still make your best guess at w
|
|
|
641
642
|
async function askSampleQuestion(state, options) {
|
|
642
643
|
const rt = getAskDbRuntimeConfig();
|
|
643
644
|
const mockSql = rt.dev.mockSql;
|
|
644
|
-
const aiConfig = mockSql ? undefined : ai.
|
|
645
|
+
const aiConfig = mockSql ? undefined : ai.resolveAiConfigFromSection(rt.ai.language);
|
|
645
646
|
if (!mockSql && !aiConfig) {
|
|
646
647
|
throw new StudioHttpError(400, `${ai.keyMissingMessage("Sample NL-to-SQL generation")} Set dev.mockSql in askdb.config to bypass the live model.`);
|
|
647
648
|
}
|
|
648
|
-
const reasoningEffort = mockSql ? undefined :
|
|
649
|
+
const reasoningEffort = mockSql ? undefined : resolveReasoningEffortFromSection(rt.ai.language.reasoning, "nlToSql");
|
|
649
650
|
const providerOptions = aiConfig && reasoningEffort ? ai.resolveProviderOptions(aiConfig, { reasoningEffort }) : undefined;
|
|
650
651
|
const schema = loadSchema(state.schemaDir);
|
|
651
652
|
const retrievedChunks = [];
|
|
@@ -655,7 +656,7 @@ async function askSampleQuestion(state, options) {
|
|
|
655
656
|
: undefined;
|
|
656
657
|
const model = mockSql
|
|
657
658
|
? undefined
|
|
658
|
-
: (await ai.
|
|
659
|
+
: (await ai.createLanguageModel(aiConfig));
|
|
659
660
|
const schemaProvider = "provider" in schema && typeof schema.provider === "string"
|
|
660
661
|
? schema.provider
|
|
661
662
|
: undefined;
|
|
@@ -990,8 +991,8 @@ function resolveStudioRagEmbedderConfig() {
|
|
|
990
991
|
label: "Mock lexical",
|
|
991
992
|
};
|
|
992
993
|
}
|
|
993
|
-
// The
|
|
994
|
-
const aiConfig = ai.
|
|
994
|
+
// The section holds the embedding connection only, so no other provider's key can reach it (#345).
|
|
995
|
+
const aiConfig = ai.resolveEmbeddingConfigFromSection(embedding);
|
|
995
996
|
// The adapter's canonical name (`foundry` resolves to `azure`) keeps existing index ids stable.
|
|
996
997
|
const provider = aiConfig?.provider ?? embedding.provider;
|
|
997
998
|
const model = embedding.model;
|
|
@@ -1000,7 +1001,7 @@ function resolveStudioRagEmbedderConfig() {
|
|
|
1000
1001
|
kind: "ai-sdk",
|
|
1001
1002
|
provider,
|
|
1002
1003
|
configuredProvider: embedding.provider,
|
|
1003
|
-
connection: embedding.connection,
|
|
1004
|
+
connection: embedding.connection.name,
|
|
1004
1005
|
embedderId: aiSdkEmbedderId({ provider, model, dimensions }),
|
|
1005
1006
|
dimensions,
|
|
1006
1007
|
configured: Boolean(aiConfig),
|
|
@@ -1366,7 +1367,7 @@ async function getExecuteStatus(schemaDir) {
|
|
|
1366
1367
|
const exec = rt.studio.execute;
|
|
1367
1368
|
const { provider, databaseUrl, file } = exec;
|
|
1368
1369
|
const def = EXECUTE_DRIVER_REGISTRY[provider];
|
|
1369
|
-
const projectRoot =
|
|
1370
|
+
const projectRoot = findNearestPackageJsonDir(schemaDir) ?? schemaDir;
|
|
1370
1371
|
const installed = isDriverInstalled(def.packageName, projectRoot);
|
|
1371
1372
|
const connectionKind = provider === "sqlite" ? "file" : "url";
|
|
1372
1373
|
const configured = connectionKind === "file" ? Boolean(file) : Boolean(databaseUrl);
|
|
@@ -1406,7 +1407,7 @@ async function installExecuteDriver(body, schemaDir) {
|
|
|
1406
1407
|
provider = body.provider;
|
|
1407
1408
|
}
|
|
1408
1409
|
const def = EXECUTE_DRIVER_REGISTRY[provider];
|
|
1409
|
-
const detection =
|
|
1410
|
+
const detection = detectExecuteDriverInstaller(schemaDir, def.packageName);
|
|
1410
1411
|
if (detection.manualReason !== null) {
|
|
1411
1412
|
return {
|
|
1412
1413
|
ok: false,
|
|
@@ -1431,9 +1432,14 @@ async function installExecuteDriver(body, schemaDir) {
|
|
|
1431
1432
|
installed,
|
|
1432
1433
|
};
|
|
1433
1434
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1435
|
+
/**
|
|
1436
|
+
* How to install the execute driver: with the manager of the lockfile in the nearest
|
|
1437
|
+
* `package.json` directory above `cwd`. Unlike setup's detection it doesn't walk further
|
|
1438
|
+
* up or guess, so Studio never installs into a parent project or with a manager the
|
|
1439
|
+
* project hasn't chosen.
|
|
1440
|
+
*/
|
|
1441
|
+
function detectExecuteDriverInstaller(cwd, packageName) {
|
|
1442
|
+
const projectRoot = findNearestPackageJsonDir(cwd);
|
|
1437
1443
|
if (!projectRoot) {
|
|
1438
1444
|
return { manualReason: `Could not locate a package.json above ${cwd}. Run the install manually.` };
|
|
1439
1445
|
}
|
|
@@ -1448,18 +1454,6 @@ function detectPackageManager(cwd, packageName) {
|
|
|
1448
1454
|
spawnSpec: packageManagerSpawnSpec(pm, packageManagerAddArgs(pm, [packageName])),
|
|
1449
1455
|
};
|
|
1450
1456
|
}
|
|
1451
|
-
function findProjectRoot(startDir) {
|
|
1452
|
-
let current = resolve(startDir);
|
|
1453
|
-
for (let i = 0; i < 20; i++) {
|
|
1454
|
-
if (existsSync(join(current, "package.json")))
|
|
1455
|
-
return current;
|
|
1456
|
-
const parent = dirname(current);
|
|
1457
|
-
if (parent === current)
|
|
1458
|
-
return null;
|
|
1459
|
-
current = parent;
|
|
1460
|
-
}
|
|
1461
|
-
return null;
|
|
1462
|
-
}
|
|
1463
1457
|
function spawnCommand(spec, cwd) {
|
|
1464
1458
|
return new Promise((resolve) => {
|
|
1465
1459
|
const proc = spawn(spec.command, spec.args, { cwd, shell: spec.shell, stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -1506,7 +1500,7 @@ async function executeQuery(body, schemaDir) {
|
|
|
1506
1500
|
throw error;
|
|
1507
1501
|
}
|
|
1508
1502
|
const warnings = sensitiveExecuteWarnings(sql, schemaDir, executeDialectFor(exec.provider, rt.nlToSql.dialect));
|
|
1509
|
-
const projectRoot =
|
|
1503
|
+
const projectRoot = findNearestPackageJsonDir(schemaDir) ?? schemaDir;
|
|
1510
1504
|
const def = EXECUTE_DRIVER_REGISTRY[exec.provider];
|
|
1511
1505
|
const result = await def.execute({
|
|
1512
1506
|
connectionString: exec.databaseUrl,
|
|
@@ -1859,6 +1853,17 @@ function contentTypeFor(path) {
|
|
|
1859
1853
|
function isRecord(value) {
|
|
1860
1854
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1861
1855
|
}
|
|
1856
|
+
/** `runStudioIntrospection` for an HTTP route: an empty result is the user's to fix (ADR 0037), so it becomes a 422, not a 500. */
|
|
1857
|
+
async function introspectForRequest(options) {
|
|
1858
|
+
try {
|
|
1859
|
+
return await runStudioIntrospection(options);
|
|
1860
|
+
}
|
|
1861
|
+
catch (error) {
|
|
1862
|
+
if (error instanceof EmptyIntrospectionError)
|
|
1863
|
+
throw new StudioHttpError(422, error.message);
|
|
1864
|
+
throw error;
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1862
1867
|
class StudioHttpError extends Error {
|
|
1863
1868
|
status;
|
|
1864
1869
|
constructor(status, message) {
|