Files
supabase/packages/ai-commands/test/util.ts
Joshen LimandSaxon Fletcher 12d92aed99 Assistant V2 (#30523)
* start

* added panels

* remove stuff

* fixes and refinements

* clean up

* remove old assistant panel

* resizable assistant kinda

* use icon

* Add missing package

* remove canvas

* add suggestions

* updated empty state if no tables exist

* fix table condition

* Implement diffing if using assistant in sql editor

* Reinstate old assistant in SQL editor if feature preview is off

* pane size adjustment

* assistant button corners

* Add SQL snippet content to assistant if opening assistant in sql editor

* Add the necessary checks for opt in and hipaa

* revert adding snippet to assistant when opening assistant in sql editor

* Add cmd i shortcut

* Add admonitions for when disablePrompt is toggled on, and if no api key is set. Add footer note RE rate limitation

* Bump ai package in packages

* some fixes for backwards compability depending on feature preview toggled

* Rename feature preview property for new assistant

* Smol fix

* Prevent SQL snippet from running until message is finished

* only loading last message

* fix z-index

* save chat state to global state

* add debug to failed ai queries

* Add basic contextual invalidation

* Add explain code action to SQL editor

* Add link to abort ongoing queries from SqlSnippet

* Update feature preview content

* Fix

* Fix

* Fix

* Te4st

* Fix tests

* ONly show ai button within a project

* Fix PH tracking

* Beef up a bit more event tracking

* Rough fix to padding when assistant is open

* A bit more telemetry stuff

* Update prompts

* fix rls editing via assistant

* Update generate-v3.ts

prompt to get auth schema too

* Add policy satement to assistant when editing

* Address all comments

* fixc

* Fix SqlSnippet not taking full width on larger viewports

* Adjust max width

---------

Co-authored-by: Saxon Fletcher <saxonafletcher@gmail.com>
2024-11-25 18:50:56 +08:00

92 lines
2.4 KiB
TypeScript

import chalk from 'chalk'
import { fromMarkdown } from 'mdast-util-from-markdown'
import type { Code } from 'mdast-util-from-markdown/lib'
import { format } from 'sql-formatter'
declare global {
interface ReadableStream<R = any> {
[Symbol.asyncIterator](): AsyncIterableIterator<R>
}
}
/**
* Formats Postgres SQL into a consistent format.
*
* @returns The formatted SQL.
*/
export const formatSql = (sql: string) =>
format(sql, { language: 'postgresql', keywordCase: 'lower' })
/**
* Collects an `ArrayBuffer` stream into a single decoded string.
*
* @returns A single string combining all the decoded stream chunks.
*/
export async function collectStream<R extends BufferSource>(stream: ReadableStream<R>) {
const textDecoderStream = new TextDecoderStream()
let content = ''
for await (const chunk of stream.pipeThrough(textDecoderStream)) {
const text = chunk.split('0:')[1]
content += text.slice(1, text.length - 2)
}
return content.replaceAll('\\n', '\n').replaceAll('\\"', '"')
}
/**
* Parses markdown and extracts all SQL code blocks.
*
* @returns An array of string content from each SQL code block.
*/
export function extractMarkdownSql(markdown: string) {
const mdTree = fromMarkdown(markdown)
return mdTree.children
.filter((node): node is Code => node.type === 'code' && node.lang === 'sql')
.map(({ value }) => value)
}
/**
* Prints the provided metadata along with any assertion errors.
* Works both synchronously and asynchronously.
*
* Useful for providing extra context for failed tests.
*/
export function withMetadata<T extends void | Promise<void>>(
metadata: Record<string, string>,
fn: () => T
): T {
/**
* Prepends metadata to an Error's stack trace.
*/
function modifyError(err: unknown) {
if (err instanceof Error && err.stack) {
const formattedMetadata = Object.entries(metadata).map(
([key, value]) => `${chalk.bold.dim(key)}:\n\n${chalk.green.dim(value)}`
)
err.stack = `${formattedMetadata.join('\n\n')}\n\n${err.stack}`
}
return err
}
// Execute the function and handle both
// synchronous or asynchronous scenarios
try {
const maybePromise = fn()
if (maybePromise instanceof Promise) {
return maybePromise.catch((err) => {
// Re-throw the error
throw modifyError(err)
}) as T
}
return maybePromise
} catch (err) {
// Re-throw the error
throw modifyError(err)
}
}