mirror of
https://github.com/supabase/supabase.git
synced 2026-09-06 09:59:03 +08:00
## Summary - Adds `list_notebooks` (cursor-paginated) and `get_notebook` AI tools in `lib/ai/tools/notebook-tools.ts`, modeled directly on `report-tools.ts`: server-side `getContent`/`getNotebook` with the `authorization` header forwarded, zod-validated input. - `get_notebook` resolves every cell and exposes `unchecked_sql` as a plain `sql` field for the agent to read — display only, per the `safe-sql-execution` skill; nothing here executes SQL. - Registers both tools in `lib/ai/tools/index.ts` (same platform branch as reports) and in `lib/ai/tool-filter.ts`'s `toolSetValidationSchema` + `TOOL_CATEGORY_MAP` (`SCHEMA` tier). - Adds an optional `headers` param to `content-infinite-query.ts`'s `getContent`, mirroring the sibling `content-query.ts`, so the cursor-paginated fetch can carry the `Authorization` header from a server context. - New tools are behind the Explorer feature flag. Stacked on #48907 (1.4 — notebook query and mutation hooks), per the Notebooks implementation plan (stack 2.1). Resolves FE-4081 Resolves FE-4080 ## Test plan - [x] `pnpm exec tsc --noEmit` — no new errors - [x] `pnpm exec vitest run lib/ai/tools/notebook-tools.test.ts lib/ai/tools/index.test.ts lib/ai/tools/report-tools.test.ts data/content/notebooks` — 36/36 passing - [x] `pnpm --filter studio run lint` — no new warnings - [x] `pnpm exec prettier --check` on changed files — clean <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added AI tools to list project notebooks with pagination. * Added AI support for retrieving notebook markdown and resolved SQL cell content. * Notebook tools now respect project and authorization context. * Notebook features are available only when Explorer access is enabled. * Content requests can forward custom request headers. * **Tests** * Added coverage for notebook tools, Explorer access, feature flags, authorization, pagination, and error handling. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
import { getClient, PollingMode, User } from '@configcat/sdk/node'
|
|
|
|
let serverClient: ReturnType<typeof getClient>
|
|
|
|
export type TrustedUserEmail = string & { readonly __trustedUserEmailBrand: never }
|
|
|
|
// Promotes an email to TrustedUserEmail. Only call this with an email whose origin is already
|
|
// verified — e.g. `claims.email` from a JWT that apiAuthenticate has confirmed — never with a
|
|
// raw request body/query param.
|
|
export function trustedUserEmail(email: string | undefined): TrustedUserEmail | undefined {
|
|
return email as TrustedUserEmail | undefined
|
|
}
|
|
|
|
const STAFF_EMAIL_DOMAINS = ['supabase.com', 'supabase.io']
|
|
|
|
function isStaffEmail(email: string): boolean {
|
|
const domain = email.slice(email.lastIndexOf('@') + 1).toLowerCase()
|
|
return STAFF_EMAIL_DOMAINS.includes(domain)
|
|
}
|
|
|
|
function buildUser(userEmail?: TrustedUserEmail, customAttributes?: Record<string, string>) {
|
|
const _customAttributes = {
|
|
...customAttributes,
|
|
is_staff: (!!userEmail && isStaffEmail(userEmail)).toString(),
|
|
}
|
|
|
|
return new User(userEmail ?? 'anonymous', undefined, undefined, _customAttributes)
|
|
}
|
|
|
|
function getServerClient() {
|
|
if (serverClient) return serverClient
|
|
|
|
const proxyUrl = process.env.NEXT_PUBLIC_CONFIGCAT_PROXY_URL
|
|
const sdkKey = process.env.NEXT_PUBLIC_CONFIGCAT_SDK_KEY
|
|
|
|
if (!proxyUrl && !sdkKey) {
|
|
console.log('Skipping server ConfigCat set up as env vars are not present')
|
|
return undefined
|
|
}
|
|
|
|
try {
|
|
if (proxyUrl) {
|
|
serverClient = getClient('configcat-proxy/frontend-v2', PollingMode.LazyLoad, {
|
|
baseUrl: proxyUrl,
|
|
})
|
|
return serverClient
|
|
}
|
|
|
|
if (sdkKey) {
|
|
serverClient = getClient(sdkKey, PollingMode.LazyLoad)
|
|
return serverClient
|
|
}
|
|
|
|
return undefined
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : String(error)
|
|
console.error(`Failed to get server ConfigCat client: ${message}`)
|
|
return undefined
|
|
}
|
|
}
|
|
|
|
export async function getServerFlags(
|
|
userEmail?: TrustedUserEmail,
|
|
customAttributes?: Record<string, string>
|
|
) {
|
|
const client = getServerClient()
|
|
|
|
if (!client) {
|
|
return []
|
|
}
|
|
|
|
return client.getAllValuesAsync(buildUser(userEmail, customAttributes))
|
|
}
|