From b298d766ae9d03739978db7ce712ebb61bc6a490 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Thu, 22 Aug 2024 19:27:38 +0000 Subject: [PATCH 1/5] refining blog ideation --- .vscode/settings.json | 1 + docs/genaisrc/genaiscript.d.ts | 5 + docs/src/content/docs/blog/.gitattributes | 1 + docs/src/content/docs/blog/genaiscript.d.ts | 1939 +++++++++++++++++ docs/src/content/docs/blog/tsconfig.json | 21 + .../content/docs/reference/cli/commands.md | 7 +- genaisrc/blog-generator.genai.mjs | 104 +- genaisrc/genaiscript.d.ts | 5 + packages/cli/src/cli.ts | 1 + packages/cli/src/scripts.ts | 13 +- packages/core/src/chat.ts | 14 +- packages/core/src/constants.ts | 2 +- packages/core/src/fence.ts | 9 + packages/core/src/genaisrc/genaiscript.d.ts | 5 + packages/core/src/promptrunner.ts | 1 + packages/core/src/types/prompt_template.d.ts | 5 + packages/sample/genaisrc/genaiscript.d.ts | 5 + .../sample/genaisrc/node/genaiscript.d.ts | 5 + .../sample/genaisrc/python/genaiscript.d.ts | 5 + .../sample/genaisrc/style/genaiscript.d.ts | 5 + packages/sample/src/aici/genaiscript.d.ts | 5 + packages/sample/src/errors/genaiscript.d.ts | 5 + packages/sample/src/makecode/genaiscript.d.ts | 5 + packages/sample/src/tla/genaiscript.d.ts | 5 + packages/sample/src/vision/genaiscript.d.ts | 5 + slides/genaisrc/genaiscript.d.ts | 5 + 26 files changed, 2157 insertions(+), 26 deletions(-) create mode 100644 docs/src/content/docs/blog/.gitattributes create mode 100644 docs/src/content/docs/blog/genaiscript.d.ts create mode 100644 docs/src/content/docs/blog/tsconfig.json diff --git a/.vscode/settings.json b/.vscode/settings.json index afcbbb62ec..5c1d120661 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -34,6 +34,7 @@ "sysr", "treesitter", "typecheck", + "unfence", "vsix", "xpai" ], diff --git a/docs/genaisrc/genaiscript.d.ts b/docs/genaisrc/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/docs/genaisrc/genaiscript.d.ts +++ b/docs/genaisrc/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/docs/src/content/docs/blog/.gitattributes b/docs/src/content/docs/blog/.gitattributes new file mode 100644 index 0000000000..b89350c92b --- /dev/null +++ b/docs/src/content/docs/blog/.gitattributes @@ -0,0 +1 @@ +genaiscript.d.ts -diff merge=ours linguist-generated \ No newline at end of file diff --git a/docs/src/content/docs/blog/genaiscript.d.ts b/docs/src/content/docs/blog/genaiscript.d.ts new file mode 100644 index 0000000000..0888e74b85 --- /dev/null +++ b/docs/src/content/docs/blog/genaiscript.d.ts @@ -0,0 +1,1939 @@ +type OptionsOrString = (string & {}) | TOptions + +interface PromptGenerationConsole { + log(...data: any[]): void + warn(...data: any[]): void + debug(...data: any[]): void + error(...data: any[]): void +} + +type DiagnosticSeverity = "error" | "warning" | "info" + +interface Diagnostic { + filename: string + range: CharRange + severity: DiagnosticSeverity + message: string + /** + * error or warning code + */ + code?: string +} + +type Awaitable = T | PromiseLike + +interface SerializedError { + name?: string + message?: string + stack?: string + cause?: unknown + code?: string + line?: number + column?: number +} + +interface PromptDefinition { + /** + * Based on file name. + */ + id: string + + /** + * Something like "Summarize children", show in UI. + */ + title?: string + + /** + * Longer description of the prompt. Shows in UI grayed-out. + */ + description?: string +} + +interface PromptLike extends PromptDefinition { + /** + * File where the prompt comes from (if any). + */ + filename?: string + + /** + * The text of the prompt JS source code. + */ + jsSource: string + + /** + * The actual text of the prompt template. + * Only used for system prompts. + */ + text?: string +} + +type SystemPromptId = OptionsOrString<"system" | "system.annotations" | "system.changelog" | "system.diagrams" | "system.diff" | "system.explanations" | "system.files" | "system.files_schema" | "system.fs_find_files" | "system.fs_read_file" | "system.math" | "system.python" | "system.python_code_interpreter" | "system.retrieval_fuzz_search" | "system.retrieval_vector_search" | "system.retrieval_web_search" | "system.schema" | "system.tasks" | "system.technical" | "system.tools" | "system.typescript" | "system.zero_shot_cot"> + +type SystemToolId = OptionsOrString<"fs_find_files" | "fs_read_file" | "math_eval" | "python_code_interpreter" | "retrieval_fuzz_search" | "retrieval_vector_search" | "retrieval_web_search"> + +type FileMergeHandler = ( + filename: string, + label: string, + before: string, + generated: string +) => Awaitable + +interface PromptOutputProcessorResult { + /** + * Updated text + */ + text?: string + /** + * Generated files from the output + */ + files?: Record + + /** + * User defined errors + */ + annotations?: Diagnostic[] +} + +type PromptOutputProcessorHandler = ( + output: GenerationOutput +) => + | PromptOutputProcessorResult + | Promise + | undefined + | Promise + | void + | Promise + +type PromptTemplateResponseType = "json_object" | "json_schema" | undefined + +interface ModelConnectionOptions { + /** + * Which LLM model to use. + * + * @default gpt-4 + * @example gpt-4 gpt-4-32k gpt-3.5-turbo ollama:phi3 ollama:llama3 ollama:mixtral aici:mixtral + */ + model?: + | "openai:gpt-4" + | "openai:gpt-4-32k" + | "openai:gpt-3.5-turbo" + | "ollama:phi3" + | "ollama:llama3" + | "ollama:mixtral" + | string +} + +interface ModelOptions extends ModelConnectionOptions { + /** + * Temperature to use. Higher temperature means more hallucination/creativity. + * Range 0.0-2.0. + * + * @default 0.2 + */ + temperature?: number + + /** + * Specifies the type of output. Default is plain text. + * - `json_object` enables JSON mode + * - `json_schema` enables structured outputs + * Use `responseSchema` to specify an output schema. + */ + responseType?: PromptTemplateResponseType + + /** + * JSON object schema for the output. Enables the `JSON` output mode by default. + */ + responseSchema?: PromptParametersSchema | JSONSchemaObject + + /** + * “Top_p” or nucleus sampling is a setting that decides how many possible words to consider. + * A high “top_p” value means the model looks at more possible words, even the less likely ones, + * which makes the generated text more diverse. + */ + topP?: number + + /** + * When to stop producing output. + * + */ + maxTokens?: number + + /** + * Maximum number of tool calls to make. + */ + maxToolCalls?: number + + /** + * Maximum number of data repairs to attempt. + */ + maxDataRepairs?: number + + /** + * A deterministic integer seed to use for the model. + */ + seed?: number + + /** + * If true, the prompt will be cached. If false, the LLM chat is never cached. + * Leave empty to use the default behavior. + */ + cache?: boolean + + /** + * Custom cache name. If not set, the default cache is used. + */ + cacheName?: string +} + +interface EmbeddingsModelConnectionOptions { + /** + * LLM model to use for embeddings. + */ + embeddingsModel?: OptionsOrString< + "openai:text-embedding-3-small", + "openai:text-embedding-3-large", + "openai:text-embedding-ada-002", + "github:text-embedding-3-small", + "github:text-embedding-3-large", + "ollama:nomic-embed-text" + > +} + +interface EmbeddingsModelOptions extends EmbeddingsModelConnectionOptions {} + +interface ScriptRuntimeOptions { + /** + * List of system script ids used by the prompt. + */ +/** +* System prompt identifiers ([reference](https://microsoft.github.io/genaiscript/reference/scripts/system/)) +* - `system`: Base system prompt +* - `system.annotations`: Emits annotations compatible with GitHub Actions +* - `system.changelog`: Generate changelog formatter edits +* - `system.diagrams`: Generate diagrams +* - `system.diff`: Generates concise file diffs. +* - `system.explanations`: Explain your answers +* - `system.files`: File generation +* - `system.files_schema`: Apply JSON schemas to generated data. +* - `system.fs_find_files`: File find files +* - `system.fs_read_file`: File Read File +* - `system.math`: Math expression evaluator +* - `system.python`: Expert at generating and understanding Python code. +* - `system.python_code_interpreter`: Python Dockerized code execution for data analysis +* - `system.retrieval_fuzz_search`: Full Text Fuzzy Search +* - `system.retrieval_vector_search`: Embeddings Vector Search +* - `system.retrieval_web_search`: Web Search +* - `system.schema`: JSON Schema support +* - `system.tasks`: Generates tasks +* - `system.technical`: Technical Writer +* - `system.tools`: Tools support +* - `system.typescript`: Export TypeScript Developer +* - `system.zero_shot_cot`: Zero-shot Chain Of Though +**/ + system?: SystemPromptId[] + + /** + * List of tools used by the prompt. + */ + tools?: SystemToolId | SystemToolId[] + + /** + * Secrets required by the prompt + */ + secrets?: string[] + + /** + * Default value for emitting line numbers in fenced code blocks. + */ + lineNumbers?: boolean +} + +type PromptParameterType = + | string + | number + | boolean + | object + | JSONSchemaNumber + | JSONSchemaString + | JSONSchemaBoolean +type PromptParametersSchema = Record< + string, + PromptParameterType | PromptParameterType[] +> +type PromptParameters = Record + +type PromptAssertion = { + // How heavily to weigh the assertion. Defaults to 1.0 + weight?: number + /** + * The transformation to apply to the output before checking the assertion. + */ + transform?: string +} & ( + | { + // type of assertion + type: + | "icontains" + | "not-icontains" + | "equals" + | "not-equals" + | "starts-with" + | "not-starts-with" + // The expected value + value: string + } + | { + // type of assertion + type: + | "contains-all" + | "not-contains-all" + | "contains-any" + | "not-contains-any" + | "icontains-all" + | "not-icontains-all" + // The expected values + value: string[] + } + | { + // type of assertion + type: "levenshtein" | "not-levenshtein" + // The expected value + value: string + // The threshold value + threshold?: number + } + | { + type: "javascript" + /** + * JavaScript expression to evaluate. + */ + value: string + /** + * Optional threshold if the javascript expression returns a number + */ + threshold?: number + } +) + +interface PromptTest { + /** + * Short name of the test + */ + name?: string + /** + * Description of the test. + */ + description?: string + /** + * List of files to apply the test to. + */ + files?: string | string[] + /** + * Extra set of variables for this scenario + */ + vars?: Record + /** + * LLM output matches a given rubric, using a Language Model to grade output. + */ + rubrics?: string | string[] + /** + * LLM output adheres to the given facts, using Factuality method from OpenAI evaluation. + */ + facts?: string | string[] + /** + * List of keywords that should be contained in the LLM output. + */ + keywords?: string | string[] + /** + * List of keywords that should not be contained in the LLM output. + */ + forbidden?: string | string[] + /** + * Additional deterministic assertions. + */ + asserts?: PromptAssertion | PromptAssertion[] +} + +interface PromptScript + extends PromptLike, + ModelOptions, + EmbeddingsModelOptions, + ScriptRuntimeOptions { + /** + * Groups template in UI + */ + group?: string + + /** + * Additional template parameters that will populate `env.vars` + */ + parameters?: PromptParametersSchema + + /** + * A file path or list of file paths or globs. + * The content of these files will be by the files selected in the UI by the user or the cli arguments. + */ + files?: string | string[] + + /** + * Extra variable values that can be used to configure system prompts. + */ + vars?: Record + + /** + * Tests to validate this script. + */ + tests?: PromptTest | PromptTest[] + + /** + * Don't show it to the user in lists. Template `system.*` are automatically unlisted. + */ + unlisted?: boolean + + /** + * Set if this is a system prompt. + */ + isSystem?: boolean +} + +/** + * Represent a file linked from a `.gpsec.md` document. + */ +interface WorkspaceFile { + /** + * Name of the file, relative to project root. + */ + filename: string + + /** + * Content of the file. + */ + content?: string +} + +interface WorkspaceFileWithScore extends WorkspaceFile { + /** + * Score allocated by search algorithm + */ + score?: number +} + +interface ToolDefinition { + /** + * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain + * underscores and dashes, with a maximum length of 64. + */ + name: string + + /** + * A description of what the function does, used by the model to choose when and + * how to call the function. + */ + description?: string + + /** + * The parameters the functions accepts, described as a JSON Schema object. See the + * [guide](https://platform.openai.com/docs/guides/text-generation/function-calling) + * for examples, and the + * [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for + * documentation about the format. + * + * Omitting `parameters` defines a function with an empty parameter list. + */ + parameters?: JSONSchema +} + +interface ToolCallTrace { + log(message: string): void + item(message: string): void + tip(message: string): void + fence(message: string, contentType?: string): void +} + +/** + * Position (line, character) in a file. Both are 0-based. + */ +type CharPosition = [number, number] + +/** + * Describes a run of text. + */ +type CharRange = [CharPosition, CharPosition] + +/** + * 0-based line numbers. + */ +type LineRange = [number, number] + +interface FileEdit { + type: string + filename: string + label?: string + validated?: boolean +} + +interface ReplaceEdit extends FileEdit { + type: "replace" + range: CharRange | LineRange + text: string +} + +interface InsertEdit extends FileEdit { + type: "insert" + pos: CharPosition | number + text: string +} + +interface DeleteEdit extends FileEdit { + type: "delete" + range: CharRange | LineRange +} + +interface CreateFileEdit extends FileEdit { + type: "createfile" + overwrite?: boolean + ignoreIfExists?: boolean + text: string +} + +type Edits = InsertEdit | ReplaceEdit | DeleteEdit | CreateFileEdit + +interface ToolCallContent { + type?: "content" + content: string + edits?: Edits[] +} + +type ToolCallOutput = string | ToolCallContent | ShellOutput | WorkspaceFile + +interface WorkspaceFileCache { + /** + * Gets the value associated with the key, or undefined if there is none. + * @param key + */ + get(key: K): Promise + /** + * Sets the value associated with the key. + * @param key + * @param value + */ + set(key: K, value: V): Promise + + /** + * List the values in the cache. + */ + values(): Promise +} + +interface WorkspaceFileSystem { + /** + * Searches for files using the glob pattern and returns a list of files. + * Ignore `.env` files and apply `.gitignore` if present. + * @param glob + */ + findFiles( + glob: string, + options?: { + /** + * Set to false to skip read text content. True by default + */ + readText?: boolean + } + ): Promise + + /** + * Performs a grep search over the files in the workspace + * @param query + * @param globs + */ + grep( + query: string | RegExp, + globs: string | string[] + ): Promise<{ files: WorkspaceFile[] }> + + /** + * Reads the content of a file as text + * @param path + */ + readText(path: string | Awaitable): Promise + + /** + * Reads the content of a file and parses to JSON, using the JSON5 parser. + * @param path + */ + readJSON(path: string | Awaitable): Promise + + /** + * Reads the content of a file and parses to XML, using the XML parser. + */ + readXML(path: string | Awaitable): Promise + + /** + * Writes a file as text to the file system + * @param path + * @param content + */ + writeText(path: string, content: string): Promise + + /** + * Opens a key-value cache for the given cache name. + * The cache is persisted accross runs of the script. Entries are dropped when the cache grows too large. + * @param cacheName + */ + cache( + cacheName: string + ): Promise> +} + +interface ToolCallContext { + trace: ToolCallTrace +} + +interface ToolCallback { + definition: ToolDefinition + fn: ( + args: { context: ToolCallContext } & Record + ) => ToolCallOutput | Promise +} + +type ChatParticipantHandler = ( + context: ChatTurnGenerationContext, + messages: ChatCompletionMessageParam[] +) => Awaitable + +interface ChatParticipantOptions { + label?: string +} + +interface ChatParticipant { + generator: ChatParticipantHandler + options: ChatParticipantOptions +} + +/** + * A set of text extracted from the context of the prompt execution + */ +interface ExpansionVariables { + /** + * Directory where the prompt is executed + */ + dir: string + + /** + * List of linked files parsed in context + */ + files: WorkspaceFile[] + + /** + * current prompt template + */ + template: PromptDefinition + + /** + * User defined variables + */ + vars?: Record + + /** + * List of secrets used by the prompt, must be registered in `genaiscript`. + */ + secrets?: Record + + /** + * Root prompt generation context + */ + generator: ChatGenerationContext +} + +type MakeOptional = Partial> & Omit + +type PromptArgs = Omit + +type PromptSystemArgs = Omit< + PromptArgs, + | "model" + | "embeddingsModel" + | "temperature" + | "topP" + | "maxTokens" + | "seed" + | "tests" + | "responseType" + | "responseSchema" + | "files" +> + +type StringLike = string | WorkspaceFile | WorkspaceFile[] + +interface FenceOptions { + /** + * Language of the fenced code block. Defaults to "markdown". + */ + language?: + | "markdown" + | "json" + | "yaml" + | "javascript" + | "typescript" + | "python" + | "shell" + | "toml" + | string + + /** + * Prepend each line with a line numbers. Helps with generating diffs. + */ + lineNumbers?: boolean + + /** + * JSON schema identifier + */ + schema?: string +} + +interface ContextExpansionOptions { + priority?: number + /** + * Specifies an maximum of estimated tokesn for this entry; after which it will be truncated. + */ + maxTokens?: number +} + +interface DefOptions extends FenceOptions, ContextExpansionOptions, DataFilter { + /** + * Filename filter based on file suffix. Case insensitive. + */ + endsWith?: string + + /** + * Filename filter using glob syntax. + */ + glob?: string + + /** + * By default, throws an error if the value in def is empty. + */ + ignoreEmpty?: boolean +} + +interface DefImagesOptions { + detail?: "high" | "low" +} + +interface ChatTaskOptions { + command: string + cwd?: string + env?: Record + args?: string[] +} + +type JSONSchemaTypeName = + | "string" + | "number" + | "integer" + | "boolean" + | "object" + | "array" + | "null" + +type JSONSchemaType = + | JSONSchemaString + | JSONSchemaNumber + | JSONSchemaBoolean + | JSONSchemaObject + | JSONSchemaArray + | null + +interface JSONSchemaString { + type: "string" + description?: string + default?: string +} + +interface JSONSchemaNumber { + type: "number" | "integer" + description?: string + default?: number + minimum?: number + exclusiveMinimum?: number + maximum?: number + exclusiveMaximum?: number +} + +interface JSONSchemaBoolean { + type: "boolean" + description?: string + default?: boolean +} + +interface JSONSchemaObject { + $schema?: string + type: "object" + description?: string + properties?: { + [key: string]: JSONSchemaType + } + required?: string[] + additionalProperties?: boolean +} + +interface JSONSchemaArray { + $schema?: string + type: "array" + description?: string + items?: JSONSchemaType +} + +type JSONSchema = JSONSchemaObject | JSONSchemaArray + +interface JSONSchemaValidation { + schema?: JSONSchema + valid: boolean + error?: string +} + +interface DataFrame { + schema?: string + data: unknown + validation?: JSONSchemaValidation +} + +interface RunPromptResult { + text: string + annotations?: Diagnostic[] + fences?: Fenced[] + frames?: DataFrame[] + json?: any + error?: SerializedError + genVars?: Record + schemas?: Record + finishReason: + | "stop" + | "length" + | "tool_calls" + | "content_filter" + | "cancel" + | "fail" +} + +/** + * Path manipulation functions. + */ +interface Path { + /** + * Returns the last portion of a path. Similar to the Unix basename command. + * @param path + */ + dirname(path: string): string + + /** + * Returns the extension of the path, from the last '.' to end of string in the last portion of the path. + * @param path + */ + extname(path: string): string + + /** + * Returns the last portion of a path, similar to the Unix basename command. + */ + basename(path: string, suffix?: string): string + + /** + * The path.join() method joins all given path segments together using the platform-specific separator as a delimiter, then normalizes the resulting path. + * @param paths + */ + join(...paths: string[]): string + + /** + * The path.normalize() method normalizes the given path, resolving '..' and '.' segments. + */ + normalize(...paths: string[]): string + + /** + * The path.relative() method returns the relative path from from to to based on the current working directory. If from and to each resolve to the same path (after calling path.resolve() on each), a zero-length string is returned. + */ + relative(from: string, to: string): string + + /** + * The path.resolve() method resolves a sequence of paths or path segments into an absolute path. + * @param pathSegments + */ + resolve(...pathSegments: string[]): string + + /** + * Determines whether the path is an absolute path. + * @param path + */ + isAbsolute(path: string): boolean +} + +interface Fenced { + label: string + language?: string + content: string + args?: { schema?: string } & Record + + validation?: JSONSchemaValidation +} + +interface XMLParseOptions { + allowBooleanAttributes?: boolean + ignoreAttributes?: boolean + ignoreDeclaration?: boolean + ignorePiTags?: boolean + parseAttributeValue?: boolean + removeNSPrefix?: boolean + unpairedTags?: string[] +} + +interface ParsePDFOptions { + filter?: (pageIndex: number, text?: string) => boolean +} + +interface HTMLToTextOptions { + /** + * After how many chars a line break should follow in `p` elements. + * + * Set to `null` or `false` to disable word-wrapping. + */ + wordwrap?: number | false | null | undefined +} + +interface ParseXLSXOptions { + // specific worksheet name + sheet?: string + // Use specified range (A1-style bounded range string) + range?: string +} + +interface WorkbookSheet { + name: string + rows: object[] +} + +interface ParseZipOptions { + glob?: string +} + +type TokenEncoder = (text: string) => number[] + +interface Parsers { + /** + * Parses text as a JSON5 payload + */ + JSON5( + content: string | WorkspaceFile, + options?: { defaultValue?: any } + ): any | undefined + + /** + * Parses text or file as a JSONL payload. Empty lines are ignore, and JSON5 is used for parsing. + * @param content + */ + JSONL(content: string | WorkspaceFile): any[] | undefined + + /** + * Parses text as a YAML paylaod + */ + YAML( + content: string | WorkspaceFile, + options?: { defaultValue?: any } + ): any | undefined + + /** + * Parses text as TOML payload + * @param text text as TOML payload + */ + TOML( + content: string | WorkspaceFile, + options?: { defaultValue?: any } + ): any | undefined + + /** + * Parses the front matter of a markdown file + * @param content + * @param defaultValue + */ + frontmatter( + content: string | WorkspaceFile, + options?: { defaultValue?: any; format: "yaml" | "json" | "toml" } + ): any | undefined + + /** + * Parses a file or URL as PDF + * @param content + */ + PDF( + content: string | WorkspaceFile, + options?: ParsePDFOptions + ): Promise<{ file: WorkspaceFile; pages: string[] } | undefined> + + /** + * Parses a .docx file + * @param content + */ + DOCX( + content: string | WorkspaceFile + ): Promise<{ file: WorkspaceFile } | undefined> + + /** + * Parses a CSV file or text + * @param content + */ + CSV( + content: string | WorkspaceFile, + options?: { delimiter?: string; headers?: string[] } + ): object[] | undefined + + /** + * Parses a XLSX file and a given worksheet + * @param content + */ + XLSX( + content: WorkspaceFile, + options?: ParseXLSXOptions + ): Promise + + /** + * Parses a .env file + * @param content + */ + dotEnv(content: string | WorkspaceFile): Record + + /** + * Parses a .ini file + * @param content + */ + INI( + content: string | WorkspaceFile, + options?: { defaultValue?: any } + ): any | undefined + + /** + * Parses a .xml file + * @param content + */ + XML( + content: string | WorkspaceFile, + options?: { defaultValue?: any } & XMLParseOptions + ): any | undefined + + /** + * Convert HTML to text + * @param content html string or file + * @param options + */ + HTMLToText( + content: string | WorkspaceFile, + options?: HTMLToTextOptions + ): string + + /** + * Extracts the contents of a zip archive file + * @param file + * @param options + */ + unzip( + file: WorkspaceFile, + options?: ParseZipOptions + ): Promise + + /** + * Estimates the number of tokens in the content. + * @param content content to tokenize + */ + tokens(content: string | WorkspaceFile): number + + /** + * Parses fenced code sections in a markdown text + */ + fences(content: string | WorkspaceFile): Fenced[] + + /** + * Parses various format of annotations (error, warning, ...) + * @param content + */ + annotations(content: string | WorkspaceFile): Diagnostic[] + + /** + * Executes a tree-sitter query on a code file + * @param file + * @param query tree sitter query; if missing, returns the entire tree + */ + code(file: WorkspaceFile, query?: string): Promise + + /** + * Parses and evaluates a math expression + * @param expression math expression compatible with mathjs + */ + math(expression: string): Promise + + /** + * Using the JSON schema, validates the content + * @param schema JSON schema instance + * @param content object to validate + */ + validateJSON(schema: JSONSchema, content: any): JSONSchemaValidation +} + +interface AICIGenOptions { + /** + * Make sure the generated text is one of the options. + */ + options?: string[] + /** + * Make sure the generated text matches given regular expression. + */ + regex?: string | RegExp + /** + * Make sure the generated text matches given yacc-like grammar. + */ + yacc?: string + /** + * Make sure the generated text is a substring of the given string. + */ + substring?: string + /** + * Used together with `substring` - treat the substring as ending the substring + * (typically '"' or similar). + */ + substringEnd?: string + /** + * Store result of the generation (as bytes) into a shared variable. + */ + storeVar?: string + /** + * Stop generation when the string is generated (the result includes the string and any following bytes (from the same token)). + */ + stopAt?: string + /** + * Stop generation when the given number of tokens have been generated. + */ + maxTokens?: number +} + +interface AICINode { + type: "aici" + name: "gen" +} + +interface AICIGenNode extends AICINode { + name: "gen" + options: AICIGenOptions +} + +interface AICI { + /** + * Generate a string that matches given constraints. + * If the tokens do not map cleanly into strings, it will contain Unicode replacement characters. + */ + gen(options: AICIGenOptions): AICIGenNode +} + +interface YAML { + /** + * Converts an object to its YAML representation + * @param obj + */ + stringify(obj: any): string + /** + * Parses a YAML string to object + */ + parse(text: string): any +} + +interface XML { + /** + * Parses an XML payload to an object + * @param text + */ + parse(text: string): any +} + +interface JSONL { + /** + * Parses a JSONL string to an array of objects + * @param text + */ + parse(text: string): any[] + /** + * Converts objects to JSONL format + * @param objs + */ + stringify(objs: any[]): string +} + +interface INI { + /** + * Parses a .ini file + * @param text + */ + parse(text: string): any + + /** + * Converts an object to.ini string + * @param value + */ + stringify(value: any): string +} + +interface CSV { + /** + * Parses a CSV string to an array of objects + * @param text + * @param options + */ + parse( + text: string, + options?: { + delimiter?: string + headers?: string[] + } + ): object[] + + /** + * Converts an array of object that represents a data table to a markdown table + * @param csv + * @param options + */ + markdownify(csv: object[], options?: { headers?: string[] }): string +} + +interface HighlightOptions { + maxLength?: number +} + +interface WebSearchResult { + webPages: WorkspaceFile[] +} + +interface VectorSearchOptions extends EmbeddingsModelOptions { + /** + * Maximum number of embeddings to use + */ + topK?: number + /** + * Minimum similarity score + */ + minScore?: number +} + +interface FuzzSearchOptions { + /** + * Controls whether to perform prefix search. It can be a simple boolean, or a + * function. + * + * If a boolean is passed, prefix search is performed if true. + * + * If a function is passed, it is called upon search with a search term, the + * positional index of that search term in the tokenized search query, and the + * tokenized search query. + */ + prefix?: boolean + /** + * Controls whether to perform fuzzy search. It can be a simple boolean, or a + * number, or a function. + * + * If a boolean is given, fuzzy search with a default fuzziness parameter is + * performed if true. + * + * If a number higher or equal to 1 is given, fuzzy search is performed, with + * a maximum edit distance (Levenshtein) equal to the number. + * + * If a number between 0 and 1 is given, fuzzy search is performed within a + * maximum edit distance corresponding to that fraction of the term length, + * approximated to the nearest integer. For example, 0.2 would mean an edit + * distance of 20% of the term length, so 1 character in a 5-characters term. + * The calculated fuzziness value is limited by the `maxFuzzy` option, to + * prevent slowdown for very long queries. + */ + fuzzy?: boolean | number + /** + * Controls the maximum fuzziness when using a fractional fuzzy value. This is + * set to 6 by default. Very high edit distances usually don't produce + * meaningful results, but can excessively impact search performance. + */ + maxFuzzy?: number + /** + * Maximum number of results to return + */ + topK?: number +} + +interface Retrieval { + /** + * Executers a Bing web search. Requires to configure the BING_SEARCH_API_KEY secret. + * @param query + */ + webSearch(query: string): Promise + + /** + * Search using similarity distance on embeddings + */ + vectorSearch( + query: string, + files: (string | WorkspaceFile) | (string | WorkspaceFile)[], + options?: VectorSearchOptions + ): Promise + + /** + * Performs a fuzzy search over the files + * @param query keywords to search + * @param files list of files + * @param options fuzzing configuration + */ + fuzzSearch( + query: string, + files: WorkspaceFile | WorkspaceFile[], + options?: FuzzSearchOptions + ): Promise +} + +type FetchTextOptions = Omit + +interface DataFilter { + /** + * The keys to select from the object. + * If a key is prefixed with -, it will be removed from the object. + */ + headers?: string[] + /** + * Selects the first N elements from the data + */ + sliceHead?: number + /** + * Selects the last N elements from the data + */ + sliceTail?: number + /** + * Selects the a random sample of N items in the collection. + */ + sliceSample?: number + + /** + * Removes items with duplicate values for the specified keys. + */ + distinct?: string[] +} + +interface DefDataOptions + extends Omit, + DataFilter { + /** + * Output format in the prompt. Defaults to markdownified CSV + */ + format?: "json" | "yaml" | "csv" +} + +interface DefSchemaOptions { + /** + * Output format in the prompt. + */ + format?: "typescript" | "json" | "yaml" +} + +type ChatFunctionHandler = ( + args: { context: ToolCallContext } & Record +) => ToolCallOutput | Promise + +interface WriteTextOptions extends ContextExpansionOptions { + /** + * Append text to the assistant response + */ + assistant?: boolean +} + +type PromptGenerator = (ctx: ChatGenerationContext) => Awaitable + +interface PromptGeneratorOptions extends ModelOptions { + /** + * Label for trace + */ + label?: string + + /** + * List of system prompts if any + */ + system?: SystemPromptId[] +} + +interface FileOutputOptions { + /** + * Schema identifier to validate the generated file + */ + schema?: string +} + +interface FileOutput { + pattern: string + description: string + options?: FileOutputOptions +} + +interface ChatTurnGenerationContext { + writeText(body: Awaitable, options?: WriteTextOptions): void + $(strings: TemplateStringsArray, ...args: any[]): void + fence(body: StringLike, options?: FenceOptions): void + def(name: string, body: StringLike, options?: DefOptions): string + defData( + name: string, + data: object[] | object, + options?: DefDataOptions + ): string + console: PromptGenerationConsole +} + +interface FileUpdate { + before: string + after: string + validation?: JSONSchemaValidation +} + +interface ChatGenerationContext extends ChatTurnGenerationContext { + defSchema( + name: string, + schema: JSONSchema, + options?: DefSchemaOptions + ): string + defImages(files: StringLike, options?: DefImagesOptions): void + defTool( + name: string, + description: string, + parameters: PromptParametersSchema | JSONSchema, + fn: ChatFunctionHandler + ): void + defChatParticipant( + participant: ChatParticipantHandler, + options?: ChatParticipantOptions + ): void + defFileOutput( + pattern: string, + description: string, + options?: FileOutputOptions + ): void +} + +interface GenerationOutput { + /** + * LLM output. + */ + text: string + + /** + * Parsed fence sections + */ + fences: Fenced[] + + /** + * Parsed data sections + */ + frames: DataFrame[] + + /** + * A map of file updates + */ + fileEdits: Record + + /** + * Generated variables, typically from AICI.gen + */ + genVars: Record + + /** + * Generated annotations + */ + annotations: Diagnostic[] + + /** + * Schema definition used in the generation + */ + schemas: Record + + /** + * Output as JSON if parsable + */ + json?: any +} + +type Point = { + row: number + column: number +} + +interface SyntaxNode { + id: number + typeId: number + grammarId: number + type: string + grammarType: string + isNamed: boolean + isMissing: boolean + isExtra: boolean + hasChanges: boolean + hasError: boolean + isError: boolean + text: string + parseState: number + nextParseState: number + startPosition: Point + endPosition: Point + startIndex: number + endIndex: number + parent: SyntaxNode | null + children: Array + namedChildren: Array + childCount: number + namedChildCount: number + firstChild: SyntaxNode | null + firstNamedChild: SyntaxNode | null + lastChild: SyntaxNode | null + lastNamedChild: SyntaxNode | null + nextSibling: SyntaxNode | null + nextNamedSibling: SyntaxNode | null + previousSibling: SyntaxNode | null + previousNamedSibling: SyntaxNode | null + descendantCount: number + + equals(other: SyntaxNode): boolean + toString(): string + child(index: number): SyntaxNode | null + namedChild(index: number): SyntaxNode | null + childForFieldName(fieldName: string): SyntaxNode | null + childForFieldId(fieldId: number): SyntaxNode | null + fieldNameForChild(childIndex: number): string | null + childrenForFieldName( + fieldName: string, + cursor: TreeCursor + ): Array + childrenForFieldId(fieldId: number, cursor: TreeCursor): Array + firstChildForIndex(index: number): SyntaxNode | null + firstNamedChildForIndex(index: number): SyntaxNode | null + + descendantForIndex(index: number): SyntaxNode + descendantForIndex(startIndex: number, endIndex: number): SyntaxNode + namedDescendantForIndex(index: number): SyntaxNode + namedDescendantForIndex(startIndex: number, endIndex: number): SyntaxNode + descendantForPosition(position: Point): SyntaxNode + descendantForPosition(startPosition: Point, endPosition: Point): SyntaxNode + namedDescendantForPosition(position: Point): SyntaxNode + namedDescendantForPosition( + startPosition: Point, + endPosition: Point + ): SyntaxNode + descendantsOfType( + types: String | Array, + startPosition?: Point, + endPosition?: Point + ): Array + + walk(): TreeCursor +} + +interface TreeCursor { + nodeType: string + nodeTypeId: number + nodeStateId: number + nodeText: string + nodeId: number + nodeIsNamed: boolean + nodeIsMissing: boolean + startPosition: Point + endPosition: Point + startIndex: number + endIndex: number + readonly currentNode: SyntaxNode + readonly currentFieldName: string + readonly currentFieldId: number + readonly currentDepth: number + readonly currentDescendantIndex: number + + reset(node: SyntaxNode): void + resetTo(cursor: TreeCursor): void + gotoParent(): boolean + gotoFirstChild(): boolean + gotoLastChild(): boolean + gotoFirstChildForIndex(goalIndex: number): boolean + gotoFirstChildForPosition(goalPosition: Point): boolean + gotoNextSibling(): boolean + gotoPreviousSibling(): boolean + gotoDescendant(goalDescendantIndex: number): void +} + +interface QueryCapture { + name: string + node: SyntaxNode +} + +interface ShellOptions { + cwd?: string + stdin?: string + /** + * Process timeout in milliseconds, default is 60s + */ + timeout?: number + /** + * trace label + */ + label?: string +} + +interface ShellOutput { + stdout?: string + stderr?: string + output?: string + exitCode: number + failed: boolean +} + +interface ShellHost { + exec( + command: string, + args: string[], + options?: ShellOptions + ): Promise +} + +interface ContainerOptions { + /** + * Container image names. + * @example python:alpine python:slim python + * @see https://hub.docker.com/_/python/ + */ + image?: string + + /** + * Enable networking in container (disabled by default) + */ + networkEnabled?: boolean + + /** + * Environment variables in container. A null/undefined variable is removed from the environment. + */ + env?: Record + + /** + * Assign the specified name to the container. Must match [a-zA-Z0-9_-]+ + */ + name?: string + + /** + * Disable automatic purge of container and volume directory + */ + disablePurge?: boolean +} + +interface PromptHost extends ShellHost { + container(options?: ContainerOptions): Promise +} + +interface ContainerHost extends ShellHost { + /** + * Container unique identifier in provider + */ + id: string + + /** + * Disable automatic purge of container and volume directory + */ + disablePurge: boolean + + /** + * Path to the volume mounted in the host + */ + hostPath: string + + /** + * Path to the volume mounted in the container + */ + containerPath: string + + /** + * Writes a file as text to the container file system + * @param path + * @param content + */ + writeText(path: string, content: string): Promise + + /** + * Reads a file as text from the container mounted volume + * @param path + */ + readText(path: string): Promise + + /** + * Copies a set of files into the container + * @param fromHost glob matching files + * @param toContainer directory in the container + */ + copyTo(fromHost: string | string[], toContainer: string): Promise + + /** + * Stops and cleans out the container + */ + stop(): Promise + + /** + * Force disconnect network + */ + disconnect(): Promise +} + +interface PromptContext extends ChatGenerationContext { + script(options: PromptArgs): void + system(options: PromptSystemArgs): void + defFileMerge(fn: FileMergeHandler): void + defOutputProcessor(fn: PromptOutputProcessorHandler): void + runPrompt( + generator: string | PromptGenerator, + options?: PromptGeneratorOptions + ): Promise + fetchText( + urlOrFile: string | WorkspaceFile, + options?: FetchTextOptions + ): Promise<{ + ok: boolean + status: number + text?: string + file?: WorkspaceFile + }> + cancel(reason?: string): void + env: ExpansionVariables + path: Path + parsers: Parsers + retrieval: Retrieval + /** + * @deprecated Use `workspace` instead + */ + fs: WorkspaceFileSystem + workspace: WorkspaceFileSystem + YAML: YAML + XML: XML + JSONL: JSONL + CSV: CSV + INI: INI + AICI: AICI + host: PromptHost +} + + + +// keep in sync with PromptContext! + +/** + * Console functions + */ +declare var console: PromptGenerationConsole + +/** + * Setup prompt title and other parameters. + * Exactly one call should be present on top of .genai.js file. + */ +declare function script(options: PromptArgs): void + +/** + * Equivalent of script() for system prompts. + */ +declare function system(options: PromptSystemArgs): void + +/** + * Append given string to the prompt. It automatically appends "\n". + * Typically best to use `` $`...` ``-templates instead. + */ +declare function writeText( + body: Awaitable, + options?: WriteTextOptions +): void + +/** + * Append given string to the prompt. It automatically appends "\n". + * `` $`foo` `` is the same as `text("foo")`. + */ +declare function $(strings: TemplateStringsArray, ...args: any[]): string + +/** + * Appends given (often multi-line) string to the prompt, surrounded in fences. + * Similar to `text(env.fence); text(body); text(env.fence)` + * + * @param body string to be fenced + */ +declare function fence(body: StringLike, options?: FenceOptions): void + +/** + * Defines `name` to be the (often multi-line) string `body`. + * Similar to `text(name + ":"); fence(body, language)` + * + * @param name name of defined entity, eg. "NOTE" or "This is text before NOTE" + * @param body string to be fenced/defined + * @returns variable name + */ +declare function def( + name: string, + body: StringLike, + options?: DefOptions +): string + +/** + * Declares a file that is expected to be generated by the LLM + * @param pattern file name or glob-like path + * @param options expectations about the generated file content + */ +declare function defFileOutput( + pattern: string, + description: string, + options?: FileOutputOptions +): void + +/** + * Declares a tool that can be called from the prompt. + * @param name The name of the tool to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. + * @param description A description of what the function does, used by the model to choose when and how to call the function. + * @param parameters The parameters the tool accepts, described as a JSON Schema object. + * @param fn callback invoked when the LLM requests to run this function + */ +declare function defTool( + name: string, + description: string, + parameters: PromptParametersSchema | JSONSchema, + fn: ChatFunctionHandler +): void + +/** + * Registers a callback to be called when a file is being merged + * @param fn + */ +declare function defFileMerge(fn: FileMergeHandler): void + +/** + * Variables coming from the fragment on which the prompt is operating. + */ +declare var env: ExpansionVariables + +/** + * Path manipulation functions. + */ +declare var path: Path + +/** + * A set of parsers for well-known file formats + */ +declare var parsers: Parsers + +/** + * Retrieval Augmented Generation services + */ +declare var retrieval: Retrieval + +/** + * Access to the workspace file system. + */ +declare var workspace: WorkspaceFileSystem + +/** + * YAML parsing and stringifying functions. + */ +declare var YAML: YAML + +/** + * INI parsing and stringifying. + */ +declare var INI: INI + +/** + * CSV parsing and stringifying. + */ +declare var CSV: CSV + +/** + * XML parsing and stringifying. + */ +declare var XML: XML + +/** + * JSONL parsing and stringifying. + */ +declare var JSONL: JSONL + +/** + * AICI operations + */ +declare var AICI: AICI + +/** + * Access to current LLM chat session information + */ +declare var host: PromptHost + +/** + * Fetches a given URL and returns the response. + * @param url + */ +declare function fetchText( + url: string | WorkspaceFile, + options?: FetchTextOptions +): Promise<{ ok: boolean; status: number; text?: string; file?: WorkspaceFile }> + +/** + * Declares a JSON schema variable. + * @param name name of the variable + * @param schema JSON schema instance + * @returns variable name + */ +declare function defSchema( + name: string, + schema: JSONSchema, + options?: DefSchemaOptions +): string + +/** + * Adds images to the prompt + * @param files + * @param options + */ +declare function defImages(files: StringLike, options?: DefImagesOptions): void + +/** + * Renders a table or object in the prompt + * @param name + * @param data + * @param options + * @returns variable name + */ +declare function defData( + name: string, + data: object[] | object, + options?: DefDataOptions +): string + +/** + * Cancels the current prompt generation/execution with the given reason. + * @param reason + */ +declare function cancel(reason?: string): void + +/** + * Expands and executes prompt + * @param generator + */ +declare function runPrompt( + generator: string | PromptGenerator, + options?: PromptGeneratorOptions +): Promise + +/** + * Registers a callback to process the LLM output + * @param fn + */ +declare function defOutputProcessor(fn: PromptOutputProcessorHandler): void + +/** + * Registers a chat participant + * @param participant + */ +declare function defChatParticipant( + participant: ChatParticipantHandler, + options?: ChatParticipantOptions +): void + +/** + * @deprecated Use `defOutputProcessor` instead. + */ +declare function defOutput(fn: PromptOutputProcessorHandler): void diff --git a/docs/src/content/docs/blog/tsconfig.json b/docs/src/content/docs/blog/tsconfig.json new file mode 100644 index 0000000000..510eefe8f9 --- /dev/null +++ b/docs/src/content/docs/blog/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "lib": [ + "ES2022" + ], + "target": "ES2023", + "module": "NodeNext", + "moduleDetection": "force", + "moduleResolution": "nodenext", + "checkJs": true, + "allowJs": true, + "skipLibCheck": true, + "noEmit": true, + "allowImportingTsExtensions": true + }, + "include": [ + "*.mjs", + "*.mts", + "./genaiscript.d.ts" + ] +} \ No newline at end of file diff --git a/docs/src/content/docs/reference/cli/commands.md b/docs/src/content/docs/reference/cli/commands.md index 90c97eb812..ac6e7022c1 100644 --- a/docs/src/content/docs/reference/cli/commands.md +++ b/docs/src/content/docs/reference/cli/commands.md @@ -120,7 +120,7 @@ Commands: list List all available scripts in workspace create Create a new script fix fix all definition files - compile Compile all script in workspace + compile Compile all script in workspace model [options] [script] List model connection information for scripts help [command] display help for command ``` @@ -164,10 +164,13 @@ Options: ### `scripts compile` ``` -Usage: genaiscript scripts compile [options] +Usage: genaiscript scripts compile [options] Compile all script in workspace +Arguments: + folders Pattern to match files + Options: -h, --help display help for command ``` diff --git a/genaisrc/blog-generator.genai.mjs b/genaisrc/blog-generator.genai.mjs index 02d9df1c94..3a7eb2f02d 100644 --- a/genaisrc/blog-generator.genai.mjs +++ b/genaisrc/blog-generator.genai.mjs @@ -1,6 +1,7 @@ script({ description: "Generate a blog post for Dev.to from the documentation", model: "openai:gpt-4o", + system: [], tools: ["fs"], parameters: { theme: { @@ -38,7 +39,7 @@ Use these files to help you generate a topic for the blog post. ` }, { - model: "openai:gpt-4o", + label: "generate theme", temperature: 1, system: [ "system.tools", @@ -51,6 +52,73 @@ Use these files to help you generate a topic for the blog post. topic = res.text } +// generate a working code snippet from topic +let snippet +{ + const { text, fences, error } = await runPrompt( + (_) => { + _.defTool( + "genaiscript_typecheck", + "Validates the syntax and type checks a GenAIScript source code", + { + source: { + type: "string", + description: "The GenAIScript javascript source code", + }, + }, + async ({ source }) => { + // write file to a scratch folder + console.log(`checking source code`) + await workspace.writeText( + "temp/blog-post/script.genai.mjs", + source + ) + return await host.exec("node", [ + "packages/cli/built/genaiscript.cjs", + "scripts", + "compile", + "temp/blog-post", + ]) + } + ) + + _.def("TOPIC", topic) + _.$`You are a JavaScript developer expert on GenAIScript (https://microsoft.github.io/genaiscript). + + # Task + + - Generate a GenAISCript source code that implements the idea described in TOPIC. + - Validate syntax and checking with genaiscript_typecheck. + - Respond with the JavaScript source code. Do NOT fence code in markdown. + + # Information + + Use these files to help you generate a topic for the blog post. + + - the code will be executed in node.js by the GenAIScript CLI + - the genaiscript type definition: genaiscript/genaiscript.d.ts. Assume that all globals are ambient. Do not import or require genaiscript module. + - the genaiscript samples: packages/sample/src/*.genai.* + - the documentation: docs/src/content/docs/**/*.md* + - the online documentation: https://microsoft.github.io/genaiscript/ + ` + }, + { + label: "generate script", + system: [ + "system.tools", + "system.fs_find_files", + "system.fs_read_file", + ], + temperature: 0.5, + } + ) + if (error) throw error + snippet = + fences.find( + ({ language }) => language === "js" || language === "javascript" + )?.content ?? text +} + // generate a blog post const today = new Date() const yyyy = today.getFullYear() @@ -58,25 +126,25 @@ const mm = String(today.getMonth() + 1).padStart(2, "0") const dd = String(today.getDate()).padStart(2, "0") const formattedDate = `${yyyy}-${mm}-${dd}` def("TOPIC", topic) +def("SNIPPET", snippet) $` # Task -Generate a blog post for the web site https://dev.to on the topic of using GenAIScript script -to solve the task described in TOPIC. +Generate a blog post that explains how to write the code in SNIPPET. The main purpose is to create a genaiscript prompt generation script. +Respond with the markdown content of the blog post. # Writing style and instructions - generate the blog post content, nothing else -- save the generated markdown to a new file under the docs/src/content/docs/blog folder. THIS IS IMPORTANT - use a clear and engaging tone -- illustrate with code examples +- explain each line of code separately, link to the documentation if possible - title should be click-bait, use quotes (") around title - do NOT generate cover_image - the script will be execute by GenAIScript CLI -- the TypeScript API is defined in the file genaisrc/genaiscript.d.ts +- the TypeScript API is defined in the file genaisrc/genaiscript.d.ts. Assume that all globals are ambient. Do not import or require genaiscript module. - generate a single file for the blog post, do NOT generate other files - examples of GenAIScript code are in folder packages/sample/src/**/*.genai.*js - do NOT explain how to install GenAIScript or the GenAIScript CLI @@ -97,17 +165,19 @@ You can extract information from the following files: - the online documentation: https://microsoft.github.io/genaiscript/ ` - -defFileOutput("docs/src/content/docs/blog/*.md", "The generated blog post") defOutputProcessor((output) => { - if (!Object.keys(output.fileEdits || {}).length) { - const fence = output.fences.find((f) => f.language === "markdown") - if (fence) { - const files = { - [`docs/src/content/docs/blog/unnamed-${formattedDate}.md`]: - fence.content, - } - return { files } - } + let md = output.text + if (/\`\`\`markdown\n/.test(md)) { + md = md.replace(/\`\`\`markdown\n/g, "").replace(/\`\`\`\n?$/g, "") + } + const fm = parsers.frontmatter(md) + const fn = + `docs/src/content/docs/blog/${fm.title.replace(/[^a-z0-9]+/gi, "-")}.md`.toLocaleLowerCase() + const sn = fn.replace(/\.md$/, ".genai.mjs") + return { + files: { + [fn]: md, + [sn]: snippet, + }, } }) diff --git a/genaisrc/genaiscript.d.ts b/genaisrc/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/genaisrc/genaiscript.d.ts +++ b/genaisrc/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 02768ea805..a12f067e4f 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -205,6 +205,7 @@ export async function cli() { scripts .command("compile") .description("Compile all script in workspace") + .argument("", "Pattern to match files") .action(compileScript) scripts .command("model") diff --git a/packages/cli/src/scripts.ts b/packages/cli/src/scripts.ts index 0d50d2b6bd..234e05155e 100644 --- a/packages/cli/src/scripts.ts +++ b/packages/cli/src/scripts.ts @@ -24,7 +24,7 @@ export async function createScript(name: string) { const t = coreCreateScript(name) const pr = await copyPrompt(t, { fork: false, name }) console.log(`created script at ${pr}`) - await compileScript() + await compileScript([]) } export async function fixScripts() { @@ -32,10 +32,17 @@ export async function fixScripts() { await fixPromptDefinitions(project) } -export async function compileScript() { +export async function compileScript(folders: string[]) { const project = await buildProject() await fixPromptDefinitions(project) - for (const folder of project.folders()) { + const scriptFolders = project.folders() + const foldersToCompile = ( + folders?.length ? folders : project.folders().map((f) => f.dirname) + ) + .map((f) => scriptFolders.find((sf) => sf.dirname === f)) + .filter((f) => f) + + for (const folder of foldersToCompile) { const { dirname, js, ts } = folder logVerbose(`compiling ${dirname}`) if (js) { diff --git a/packages/core/src/chat.ts b/packages/core/src/chat.ts index 50e1bafab3..88a8279158 100644 --- a/packages/core/src/chat.ts +++ b/packages/core/src/chat.ts @@ -9,7 +9,7 @@ import { checkCancelled, } from "./cancellation" import { assert, logError, logVerbose } from "./util" -import { extractFenced, findFirstDataFence } from "./fence" +import { extractFenced, findFirstDataFence, unfence } from "./fence" import { toStrictJSONSchema, validateFencesWithSchema, @@ -330,13 +330,21 @@ Repair the DATA_FORMAT_ISSUES. THIS IS IMPORTANT.` return true } -function assistantText(messages: ChatCompletionMessageParam[]) { +function assistantText( + messages: ChatCompletionMessageParam[], + responseType?: PromptTemplateResponseType +) { let text = "" for (let i = messages.length - 1; i >= 0; i--) { const msg = messages[i] if (msg.role !== "assistant") break text = msg.content + text } + + if (responseType === undefined) { + text = unfence(text, "(markdown|md)") + } + return text } @@ -352,7 +360,7 @@ function structurifyChatSession( ): RunPromptResult { const { trace, responseType, responseSchema } = options const { resp, err } = others || {} - const text = assistantText(messages) + const text = assistantText(messages, responseType) const annotations = parseAnnotations(text) const finishReason = isCancelError(err) ? "cancel" diff --git a/packages/core/src/constants.ts b/packages/core/src/constants.ts index a005c1f3ad..64d260651c 100644 --- a/packages/core/src/constants.ts +++ b/packages/core/src/constants.ts @@ -4,7 +4,7 @@ export const RECONNECT = "reconnect" export const OPEN = "open" export const MAX_CACHED_TEMPERATURE = 0.5 export const MAX_CACHED_TOP_P = 0.5 -export const MAX_TOOL_CALLS = 100 +export const MAX_TOOL_CALLS = 10000 // https://learn.microsoft.com/en-us/azure/ai-services/openai/reference // https://github.com/Azure/azure-rest-api-specs/blob/main/specification/cognitiveservices/data-plane/AzureOpenAI/inference/stable/2024-02-01/inference.yaml diff --git a/packages/core/src/fence.ts b/packages/core/src/fence.ts index 834d557efb..4b18820175 100644 --- a/packages/core/src/fence.ts +++ b/packages/core/src/fence.ts @@ -212,3 +212,12 @@ ${validation.error.split("\n").join("\n> ")}` ) .join("\n") } + +export function unfence(text: string, language: string) { + const startRx = new RegExp(`^\`\`\`${language}\n`) + const endRx = /\n```[\n\s]*$/ + if (startRx.test(text) && endRx.test(text)) { + return text.replace(startRx, "").replace(endRx, "") + } + return text +} diff --git a/packages/core/src/genaisrc/genaiscript.d.ts b/packages/core/src/genaisrc/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/packages/core/src/genaisrc/genaiscript.d.ts +++ b/packages/core/src/genaisrc/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/packages/core/src/promptrunner.ts b/packages/core/src/promptrunner.ts index 5baba5ff7f..97ca5e3ddc 100644 --- a/packages/core/src/promptrunner.ts +++ b/packages/core/src/promptrunner.ts @@ -323,6 +323,7 @@ export async function runTemplate( trace.detailsFenced(`📁 file ${fn}`, content) const fileEdit = await getFileEdit(fn) fileEdit.after = content + fileEdit.validation = { valid: true } } if (oannotations) annotations = oannotations.slice(0) } diff --git a/packages/core/src/types/prompt_template.d.ts b/packages/core/src/types/prompt_template.d.ts index d819529f1f..2f6f490f85 100644 --- a/packages/core/src/types/prompt_template.d.ts +++ b/packages/core/src/types/prompt_template.d.ts @@ -291,6 +291,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -629,6 +633,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/packages/sample/genaisrc/genaiscript.d.ts b/packages/sample/genaisrc/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/packages/sample/genaisrc/genaiscript.d.ts +++ b/packages/sample/genaisrc/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/packages/sample/genaisrc/node/genaiscript.d.ts b/packages/sample/genaisrc/node/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/packages/sample/genaisrc/node/genaiscript.d.ts +++ b/packages/sample/genaisrc/node/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/packages/sample/genaisrc/python/genaiscript.d.ts b/packages/sample/genaisrc/python/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/packages/sample/genaisrc/python/genaiscript.d.ts +++ b/packages/sample/genaisrc/python/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/packages/sample/genaisrc/style/genaiscript.d.ts b/packages/sample/genaisrc/style/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/packages/sample/genaisrc/style/genaiscript.d.ts +++ b/packages/sample/genaisrc/style/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/packages/sample/src/aici/genaiscript.d.ts b/packages/sample/src/aici/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/packages/sample/src/aici/genaiscript.d.ts +++ b/packages/sample/src/aici/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/packages/sample/src/errors/genaiscript.d.ts b/packages/sample/src/errors/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/packages/sample/src/errors/genaiscript.d.ts +++ b/packages/sample/src/errors/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/packages/sample/src/makecode/genaiscript.d.ts b/packages/sample/src/makecode/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/packages/sample/src/makecode/genaiscript.d.ts +++ b/packages/sample/src/makecode/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/packages/sample/src/tla/genaiscript.d.ts b/packages/sample/src/tla/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/packages/sample/src/tla/genaiscript.d.ts +++ b/packages/sample/src/tla/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/packages/sample/src/vision/genaiscript.d.ts b/packages/sample/src/vision/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/packages/sample/src/vision/genaiscript.d.ts +++ b/packages/sample/src/vision/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" diff --git a/slides/genaisrc/genaiscript.d.ts b/slides/genaisrc/genaiscript.d.ts index 34615cbec0..e2521a78d5 100644 --- a/slides/genaisrc/genaiscript.d.ts +++ b/slides/genaisrc/genaiscript.d.ts @@ -316,6 +316,10 @@ type PromptAssertion = { ) interface PromptTest { + /** + * Short name of the test + */ + name?: string /** * Description of the test. */ @@ -654,6 +658,7 @@ type PromptSystemArgs = Omit< | "maxTokens" | "seed" | "tests" + | "responseLanguage" | "responseType" | "responseSchema" | "files" From 9f1e6935204fe4e0084e0edf2c4e5f500d8295ed Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Thu, 22 Aug 2024 19:29:36 +0000 Subject: [PATCH 2/5] refine more blog entry --- genaisrc/blog-generator.genai.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genaisrc/blog-generator.genai.mjs b/genaisrc/blog-generator.genai.mjs index 3a7eb2f02d..9cf2024370 100644 --- a/genaisrc/blog-generator.genai.mjs +++ b/genaisrc/blog-generator.genai.mjs @@ -89,7 +89,7 @@ let snippet - Generate a GenAISCript source code that implements the idea described in TOPIC. - Validate syntax and checking with genaiscript_typecheck. - - Respond with the JavaScript source code. Do NOT fence code in markdown. + - Respond ONLY with the JavaScript source code. Do NOT fence code in markdown. Do not add text around code. # Information From 97baf537c4ce4c4fcd945bbc55f533c8678ee51c Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Thu, 22 Aug 2024 19:38:33 +0000 Subject: [PATCH 3/5] compile optional --- docs/src/content/docs/reference/cli/commands.md | 4 ++-- packages/cli/src/cli.ts | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/src/content/docs/reference/cli/commands.md b/docs/src/content/docs/reference/cli/commands.md index ac6e7022c1..4fa8291173 100644 --- a/docs/src/content/docs/reference/cli/commands.md +++ b/docs/src/content/docs/reference/cli/commands.md @@ -120,7 +120,7 @@ Commands: list List all available scripts in workspace create Create a new script fix fix all definition files - compile Compile all script in workspace + compile [folders...] Compile all script in workspace model [options] [script] List model connection information for scripts help [command] display help for command ``` @@ -164,7 +164,7 @@ Options: ### `scripts compile` ``` -Usage: genaiscript scripts compile [options] +Usage: genaiscript scripts compile [options] [folders...] Compile all script in workspace diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index a12f067e4f..1f0a68d1cc 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -148,7 +148,10 @@ export async function cli() { "--vars ", "variables, as name=value, stored in env.vars" ) - .option("-rr, --run-retry ", "number of retries for the entire run") + .option( + "-rr, --run-retry ", + "number of retries for the entire run" + ) .action(runScriptWithExitCode) const test = program.command("test") @@ -205,7 +208,7 @@ export async function cli() { scripts .command("compile") .description("Compile all script in workspace") - .argument("", "Pattern to match files") + .argument("[folders...]", "Pattern to match files") .action(compileScript) scripts .command("model") From e0982f2b7f1a784ed3929a3a9dcc8ae06c6108af Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Thu, 22 Aug 2024 21:05:05 +0000 Subject: [PATCH 4/5] removing extra files --- docs/src/content/docs/blog/.gitattributes | 1 - docs/src/content/docs/blog/genaiscript.d.ts | 1939 ------------------- docs/src/content/docs/blog/tsconfig.json | 21 - 3 files changed, 1961 deletions(-) delete mode 100644 docs/src/content/docs/blog/.gitattributes delete mode 100644 docs/src/content/docs/blog/genaiscript.d.ts delete mode 100644 docs/src/content/docs/blog/tsconfig.json diff --git a/docs/src/content/docs/blog/.gitattributes b/docs/src/content/docs/blog/.gitattributes deleted file mode 100644 index b89350c92b..0000000000 --- a/docs/src/content/docs/blog/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -genaiscript.d.ts -diff merge=ours linguist-generated \ No newline at end of file diff --git a/docs/src/content/docs/blog/genaiscript.d.ts b/docs/src/content/docs/blog/genaiscript.d.ts deleted file mode 100644 index 0888e74b85..0000000000 --- a/docs/src/content/docs/blog/genaiscript.d.ts +++ /dev/null @@ -1,1939 +0,0 @@ -type OptionsOrString = (string & {}) | TOptions - -interface PromptGenerationConsole { - log(...data: any[]): void - warn(...data: any[]): void - debug(...data: any[]): void - error(...data: any[]): void -} - -type DiagnosticSeverity = "error" | "warning" | "info" - -interface Diagnostic { - filename: string - range: CharRange - severity: DiagnosticSeverity - message: string - /** - * error or warning code - */ - code?: string -} - -type Awaitable = T | PromiseLike - -interface SerializedError { - name?: string - message?: string - stack?: string - cause?: unknown - code?: string - line?: number - column?: number -} - -interface PromptDefinition { - /** - * Based on file name. - */ - id: string - - /** - * Something like "Summarize children", show in UI. - */ - title?: string - - /** - * Longer description of the prompt. Shows in UI grayed-out. - */ - description?: string -} - -interface PromptLike extends PromptDefinition { - /** - * File where the prompt comes from (if any). - */ - filename?: string - - /** - * The text of the prompt JS source code. - */ - jsSource: string - - /** - * The actual text of the prompt template. - * Only used for system prompts. - */ - text?: string -} - -type SystemPromptId = OptionsOrString<"system" | "system.annotations" | "system.changelog" | "system.diagrams" | "system.diff" | "system.explanations" | "system.files" | "system.files_schema" | "system.fs_find_files" | "system.fs_read_file" | "system.math" | "system.python" | "system.python_code_interpreter" | "system.retrieval_fuzz_search" | "system.retrieval_vector_search" | "system.retrieval_web_search" | "system.schema" | "system.tasks" | "system.technical" | "system.tools" | "system.typescript" | "system.zero_shot_cot"> - -type SystemToolId = OptionsOrString<"fs_find_files" | "fs_read_file" | "math_eval" | "python_code_interpreter" | "retrieval_fuzz_search" | "retrieval_vector_search" | "retrieval_web_search"> - -type FileMergeHandler = ( - filename: string, - label: string, - before: string, - generated: string -) => Awaitable - -interface PromptOutputProcessorResult { - /** - * Updated text - */ - text?: string - /** - * Generated files from the output - */ - files?: Record - - /** - * User defined errors - */ - annotations?: Diagnostic[] -} - -type PromptOutputProcessorHandler = ( - output: GenerationOutput -) => - | PromptOutputProcessorResult - | Promise - | undefined - | Promise - | void - | Promise - -type PromptTemplateResponseType = "json_object" | "json_schema" | undefined - -interface ModelConnectionOptions { - /** - * Which LLM model to use. - * - * @default gpt-4 - * @example gpt-4 gpt-4-32k gpt-3.5-turbo ollama:phi3 ollama:llama3 ollama:mixtral aici:mixtral - */ - model?: - | "openai:gpt-4" - | "openai:gpt-4-32k" - | "openai:gpt-3.5-turbo" - | "ollama:phi3" - | "ollama:llama3" - | "ollama:mixtral" - | string -} - -interface ModelOptions extends ModelConnectionOptions { - /** - * Temperature to use. Higher temperature means more hallucination/creativity. - * Range 0.0-2.0. - * - * @default 0.2 - */ - temperature?: number - - /** - * Specifies the type of output. Default is plain text. - * - `json_object` enables JSON mode - * - `json_schema` enables structured outputs - * Use `responseSchema` to specify an output schema. - */ - responseType?: PromptTemplateResponseType - - /** - * JSON object schema for the output. Enables the `JSON` output mode by default. - */ - responseSchema?: PromptParametersSchema | JSONSchemaObject - - /** - * “Top_p” or nucleus sampling is a setting that decides how many possible words to consider. - * A high “top_p” value means the model looks at more possible words, even the less likely ones, - * which makes the generated text more diverse. - */ - topP?: number - - /** - * When to stop producing output. - * - */ - maxTokens?: number - - /** - * Maximum number of tool calls to make. - */ - maxToolCalls?: number - - /** - * Maximum number of data repairs to attempt. - */ - maxDataRepairs?: number - - /** - * A deterministic integer seed to use for the model. - */ - seed?: number - - /** - * If true, the prompt will be cached. If false, the LLM chat is never cached. - * Leave empty to use the default behavior. - */ - cache?: boolean - - /** - * Custom cache name. If not set, the default cache is used. - */ - cacheName?: string -} - -interface EmbeddingsModelConnectionOptions { - /** - * LLM model to use for embeddings. - */ - embeddingsModel?: OptionsOrString< - "openai:text-embedding-3-small", - "openai:text-embedding-3-large", - "openai:text-embedding-ada-002", - "github:text-embedding-3-small", - "github:text-embedding-3-large", - "ollama:nomic-embed-text" - > -} - -interface EmbeddingsModelOptions extends EmbeddingsModelConnectionOptions {} - -interface ScriptRuntimeOptions { - /** - * List of system script ids used by the prompt. - */ -/** -* System prompt identifiers ([reference](https://microsoft.github.io/genaiscript/reference/scripts/system/)) -* - `system`: Base system prompt -* - `system.annotations`: Emits annotations compatible with GitHub Actions -* - `system.changelog`: Generate changelog formatter edits -* - `system.diagrams`: Generate diagrams -* - `system.diff`: Generates concise file diffs. -* - `system.explanations`: Explain your answers -* - `system.files`: File generation -* - `system.files_schema`: Apply JSON schemas to generated data. -* - `system.fs_find_files`: File find files -* - `system.fs_read_file`: File Read File -* - `system.math`: Math expression evaluator -* - `system.python`: Expert at generating and understanding Python code. -* - `system.python_code_interpreter`: Python Dockerized code execution for data analysis -* - `system.retrieval_fuzz_search`: Full Text Fuzzy Search -* - `system.retrieval_vector_search`: Embeddings Vector Search -* - `system.retrieval_web_search`: Web Search -* - `system.schema`: JSON Schema support -* - `system.tasks`: Generates tasks -* - `system.technical`: Technical Writer -* - `system.tools`: Tools support -* - `system.typescript`: Export TypeScript Developer -* - `system.zero_shot_cot`: Zero-shot Chain Of Though -**/ - system?: SystemPromptId[] - - /** - * List of tools used by the prompt. - */ - tools?: SystemToolId | SystemToolId[] - - /** - * Secrets required by the prompt - */ - secrets?: string[] - - /** - * Default value for emitting line numbers in fenced code blocks. - */ - lineNumbers?: boolean -} - -type PromptParameterType = - | string - | number - | boolean - | object - | JSONSchemaNumber - | JSONSchemaString - | JSONSchemaBoolean -type PromptParametersSchema = Record< - string, - PromptParameterType | PromptParameterType[] -> -type PromptParameters = Record - -type PromptAssertion = { - // How heavily to weigh the assertion. Defaults to 1.0 - weight?: number - /** - * The transformation to apply to the output before checking the assertion. - */ - transform?: string -} & ( - | { - // type of assertion - type: - | "icontains" - | "not-icontains" - | "equals" - | "not-equals" - | "starts-with" - | "not-starts-with" - // The expected value - value: string - } - | { - // type of assertion - type: - | "contains-all" - | "not-contains-all" - | "contains-any" - | "not-contains-any" - | "icontains-all" - | "not-icontains-all" - // The expected values - value: string[] - } - | { - // type of assertion - type: "levenshtein" | "not-levenshtein" - // The expected value - value: string - // The threshold value - threshold?: number - } - | { - type: "javascript" - /** - * JavaScript expression to evaluate. - */ - value: string - /** - * Optional threshold if the javascript expression returns a number - */ - threshold?: number - } -) - -interface PromptTest { - /** - * Short name of the test - */ - name?: string - /** - * Description of the test. - */ - description?: string - /** - * List of files to apply the test to. - */ - files?: string | string[] - /** - * Extra set of variables for this scenario - */ - vars?: Record - /** - * LLM output matches a given rubric, using a Language Model to grade output. - */ - rubrics?: string | string[] - /** - * LLM output adheres to the given facts, using Factuality method from OpenAI evaluation. - */ - facts?: string | string[] - /** - * List of keywords that should be contained in the LLM output. - */ - keywords?: string | string[] - /** - * List of keywords that should not be contained in the LLM output. - */ - forbidden?: string | string[] - /** - * Additional deterministic assertions. - */ - asserts?: PromptAssertion | PromptAssertion[] -} - -interface PromptScript - extends PromptLike, - ModelOptions, - EmbeddingsModelOptions, - ScriptRuntimeOptions { - /** - * Groups template in UI - */ - group?: string - - /** - * Additional template parameters that will populate `env.vars` - */ - parameters?: PromptParametersSchema - - /** - * A file path or list of file paths or globs. - * The content of these files will be by the files selected in the UI by the user or the cli arguments. - */ - files?: string | string[] - - /** - * Extra variable values that can be used to configure system prompts. - */ - vars?: Record - - /** - * Tests to validate this script. - */ - tests?: PromptTest | PromptTest[] - - /** - * Don't show it to the user in lists. Template `system.*` are automatically unlisted. - */ - unlisted?: boolean - - /** - * Set if this is a system prompt. - */ - isSystem?: boolean -} - -/** - * Represent a file linked from a `.gpsec.md` document. - */ -interface WorkspaceFile { - /** - * Name of the file, relative to project root. - */ - filename: string - - /** - * Content of the file. - */ - content?: string -} - -interface WorkspaceFileWithScore extends WorkspaceFile { - /** - * Score allocated by search algorithm - */ - score?: number -} - -interface ToolDefinition { - /** - * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain - * underscores and dashes, with a maximum length of 64. - */ - name: string - - /** - * A description of what the function does, used by the model to choose when and - * how to call the function. - */ - description?: string - - /** - * The parameters the functions accepts, described as a JSON Schema object. See the - * [guide](https://platform.openai.com/docs/guides/text-generation/function-calling) - * for examples, and the - * [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for - * documentation about the format. - * - * Omitting `parameters` defines a function with an empty parameter list. - */ - parameters?: JSONSchema -} - -interface ToolCallTrace { - log(message: string): void - item(message: string): void - tip(message: string): void - fence(message: string, contentType?: string): void -} - -/** - * Position (line, character) in a file. Both are 0-based. - */ -type CharPosition = [number, number] - -/** - * Describes a run of text. - */ -type CharRange = [CharPosition, CharPosition] - -/** - * 0-based line numbers. - */ -type LineRange = [number, number] - -interface FileEdit { - type: string - filename: string - label?: string - validated?: boolean -} - -interface ReplaceEdit extends FileEdit { - type: "replace" - range: CharRange | LineRange - text: string -} - -interface InsertEdit extends FileEdit { - type: "insert" - pos: CharPosition | number - text: string -} - -interface DeleteEdit extends FileEdit { - type: "delete" - range: CharRange | LineRange -} - -interface CreateFileEdit extends FileEdit { - type: "createfile" - overwrite?: boolean - ignoreIfExists?: boolean - text: string -} - -type Edits = InsertEdit | ReplaceEdit | DeleteEdit | CreateFileEdit - -interface ToolCallContent { - type?: "content" - content: string - edits?: Edits[] -} - -type ToolCallOutput = string | ToolCallContent | ShellOutput | WorkspaceFile - -interface WorkspaceFileCache { - /** - * Gets the value associated with the key, or undefined if there is none. - * @param key - */ - get(key: K): Promise - /** - * Sets the value associated with the key. - * @param key - * @param value - */ - set(key: K, value: V): Promise - - /** - * List the values in the cache. - */ - values(): Promise -} - -interface WorkspaceFileSystem { - /** - * Searches for files using the glob pattern and returns a list of files. - * Ignore `.env` files and apply `.gitignore` if present. - * @param glob - */ - findFiles( - glob: string, - options?: { - /** - * Set to false to skip read text content. True by default - */ - readText?: boolean - } - ): Promise - - /** - * Performs a grep search over the files in the workspace - * @param query - * @param globs - */ - grep( - query: string | RegExp, - globs: string | string[] - ): Promise<{ files: WorkspaceFile[] }> - - /** - * Reads the content of a file as text - * @param path - */ - readText(path: string | Awaitable): Promise - - /** - * Reads the content of a file and parses to JSON, using the JSON5 parser. - * @param path - */ - readJSON(path: string | Awaitable): Promise - - /** - * Reads the content of a file and parses to XML, using the XML parser. - */ - readXML(path: string | Awaitable): Promise - - /** - * Writes a file as text to the file system - * @param path - * @param content - */ - writeText(path: string, content: string): Promise - - /** - * Opens a key-value cache for the given cache name. - * The cache is persisted accross runs of the script. Entries are dropped when the cache grows too large. - * @param cacheName - */ - cache( - cacheName: string - ): Promise> -} - -interface ToolCallContext { - trace: ToolCallTrace -} - -interface ToolCallback { - definition: ToolDefinition - fn: ( - args: { context: ToolCallContext } & Record - ) => ToolCallOutput | Promise -} - -type ChatParticipantHandler = ( - context: ChatTurnGenerationContext, - messages: ChatCompletionMessageParam[] -) => Awaitable - -interface ChatParticipantOptions { - label?: string -} - -interface ChatParticipant { - generator: ChatParticipantHandler - options: ChatParticipantOptions -} - -/** - * A set of text extracted from the context of the prompt execution - */ -interface ExpansionVariables { - /** - * Directory where the prompt is executed - */ - dir: string - - /** - * List of linked files parsed in context - */ - files: WorkspaceFile[] - - /** - * current prompt template - */ - template: PromptDefinition - - /** - * User defined variables - */ - vars?: Record - - /** - * List of secrets used by the prompt, must be registered in `genaiscript`. - */ - secrets?: Record - - /** - * Root prompt generation context - */ - generator: ChatGenerationContext -} - -type MakeOptional = Partial> & Omit - -type PromptArgs = Omit - -type PromptSystemArgs = Omit< - PromptArgs, - | "model" - | "embeddingsModel" - | "temperature" - | "topP" - | "maxTokens" - | "seed" - | "tests" - | "responseType" - | "responseSchema" - | "files" -> - -type StringLike = string | WorkspaceFile | WorkspaceFile[] - -interface FenceOptions { - /** - * Language of the fenced code block. Defaults to "markdown". - */ - language?: - | "markdown" - | "json" - | "yaml" - | "javascript" - | "typescript" - | "python" - | "shell" - | "toml" - | string - - /** - * Prepend each line with a line numbers. Helps with generating diffs. - */ - lineNumbers?: boolean - - /** - * JSON schema identifier - */ - schema?: string -} - -interface ContextExpansionOptions { - priority?: number - /** - * Specifies an maximum of estimated tokesn for this entry; after which it will be truncated. - */ - maxTokens?: number -} - -interface DefOptions extends FenceOptions, ContextExpansionOptions, DataFilter { - /** - * Filename filter based on file suffix. Case insensitive. - */ - endsWith?: string - - /** - * Filename filter using glob syntax. - */ - glob?: string - - /** - * By default, throws an error if the value in def is empty. - */ - ignoreEmpty?: boolean -} - -interface DefImagesOptions { - detail?: "high" | "low" -} - -interface ChatTaskOptions { - command: string - cwd?: string - env?: Record - args?: string[] -} - -type JSONSchemaTypeName = - | "string" - | "number" - | "integer" - | "boolean" - | "object" - | "array" - | "null" - -type JSONSchemaType = - | JSONSchemaString - | JSONSchemaNumber - | JSONSchemaBoolean - | JSONSchemaObject - | JSONSchemaArray - | null - -interface JSONSchemaString { - type: "string" - description?: string - default?: string -} - -interface JSONSchemaNumber { - type: "number" | "integer" - description?: string - default?: number - minimum?: number - exclusiveMinimum?: number - maximum?: number - exclusiveMaximum?: number -} - -interface JSONSchemaBoolean { - type: "boolean" - description?: string - default?: boolean -} - -interface JSONSchemaObject { - $schema?: string - type: "object" - description?: string - properties?: { - [key: string]: JSONSchemaType - } - required?: string[] - additionalProperties?: boolean -} - -interface JSONSchemaArray { - $schema?: string - type: "array" - description?: string - items?: JSONSchemaType -} - -type JSONSchema = JSONSchemaObject | JSONSchemaArray - -interface JSONSchemaValidation { - schema?: JSONSchema - valid: boolean - error?: string -} - -interface DataFrame { - schema?: string - data: unknown - validation?: JSONSchemaValidation -} - -interface RunPromptResult { - text: string - annotations?: Diagnostic[] - fences?: Fenced[] - frames?: DataFrame[] - json?: any - error?: SerializedError - genVars?: Record - schemas?: Record - finishReason: - | "stop" - | "length" - | "tool_calls" - | "content_filter" - | "cancel" - | "fail" -} - -/** - * Path manipulation functions. - */ -interface Path { - /** - * Returns the last portion of a path. Similar to the Unix basename command. - * @param path - */ - dirname(path: string): string - - /** - * Returns the extension of the path, from the last '.' to end of string in the last portion of the path. - * @param path - */ - extname(path: string): string - - /** - * Returns the last portion of a path, similar to the Unix basename command. - */ - basename(path: string, suffix?: string): string - - /** - * The path.join() method joins all given path segments together using the platform-specific separator as a delimiter, then normalizes the resulting path. - * @param paths - */ - join(...paths: string[]): string - - /** - * The path.normalize() method normalizes the given path, resolving '..' and '.' segments. - */ - normalize(...paths: string[]): string - - /** - * The path.relative() method returns the relative path from from to to based on the current working directory. If from and to each resolve to the same path (after calling path.resolve() on each), a zero-length string is returned. - */ - relative(from: string, to: string): string - - /** - * The path.resolve() method resolves a sequence of paths or path segments into an absolute path. - * @param pathSegments - */ - resolve(...pathSegments: string[]): string - - /** - * Determines whether the path is an absolute path. - * @param path - */ - isAbsolute(path: string): boolean -} - -interface Fenced { - label: string - language?: string - content: string - args?: { schema?: string } & Record - - validation?: JSONSchemaValidation -} - -interface XMLParseOptions { - allowBooleanAttributes?: boolean - ignoreAttributes?: boolean - ignoreDeclaration?: boolean - ignorePiTags?: boolean - parseAttributeValue?: boolean - removeNSPrefix?: boolean - unpairedTags?: string[] -} - -interface ParsePDFOptions { - filter?: (pageIndex: number, text?: string) => boolean -} - -interface HTMLToTextOptions { - /** - * After how many chars a line break should follow in `p` elements. - * - * Set to `null` or `false` to disable word-wrapping. - */ - wordwrap?: number | false | null | undefined -} - -interface ParseXLSXOptions { - // specific worksheet name - sheet?: string - // Use specified range (A1-style bounded range string) - range?: string -} - -interface WorkbookSheet { - name: string - rows: object[] -} - -interface ParseZipOptions { - glob?: string -} - -type TokenEncoder = (text: string) => number[] - -interface Parsers { - /** - * Parses text as a JSON5 payload - */ - JSON5( - content: string | WorkspaceFile, - options?: { defaultValue?: any } - ): any | undefined - - /** - * Parses text or file as a JSONL payload. Empty lines are ignore, and JSON5 is used for parsing. - * @param content - */ - JSONL(content: string | WorkspaceFile): any[] | undefined - - /** - * Parses text as a YAML paylaod - */ - YAML( - content: string | WorkspaceFile, - options?: { defaultValue?: any } - ): any | undefined - - /** - * Parses text as TOML payload - * @param text text as TOML payload - */ - TOML( - content: string | WorkspaceFile, - options?: { defaultValue?: any } - ): any | undefined - - /** - * Parses the front matter of a markdown file - * @param content - * @param defaultValue - */ - frontmatter( - content: string | WorkspaceFile, - options?: { defaultValue?: any; format: "yaml" | "json" | "toml" } - ): any | undefined - - /** - * Parses a file or URL as PDF - * @param content - */ - PDF( - content: string | WorkspaceFile, - options?: ParsePDFOptions - ): Promise<{ file: WorkspaceFile; pages: string[] } | undefined> - - /** - * Parses a .docx file - * @param content - */ - DOCX( - content: string | WorkspaceFile - ): Promise<{ file: WorkspaceFile } | undefined> - - /** - * Parses a CSV file or text - * @param content - */ - CSV( - content: string | WorkspaceFile, - options?: { delimiter?: string; headers?: string[] } - ): object[] | undefined - - /** - * Parses a XLSX file and a given worksheet - * @param content - */ - XLSX( - content: WorkspaceFile, - options?: ParseXLSXOptions - ): Promise - - /** - * Parses a .env file - * @param content - */ - dotEnv(content: string | WorkspaceFile): Record - - /** - * Parses a .ini file - * @param content - */ - INI( - content: string | WorkspaceFile, - options?: { defaultValue?: any } - ): any | undefined - - /** - * Parses a .xml file - * @param content - */ - XML( - content: string | WorkspaceFile, - options?: { defaultValue?: any } & XMLParseOptions - ): any | undefined - - /** - * Convert HTML to text - * @param content html string or file - * @param options - */ - HTMLToText( - content: string | WorkspaceFile, - options?: HTMLToTextOptions - ): string - - /** - * Extracts the contents of a zip archive file - * @param file - * @param options - */ - unzip( - file: WorkspaceFile, - options?: ParseZipOptions - ): Promise - - /** - * Estimates the number of tokens in the content. - * @param content content to tokenize - */ - tokens(content: string | WorkspaceFile): number - - /** - * Parses fenced code sections in a markdown text - */ - fences(content: string | WorkspaceFile): Fenced[] - - /** - * Parses various format of annotations (error, warning, ...) - * @param content - */ - annotations(content: string | WorkspaceFile): Diagnostic[] - - /** - * Executes a tree-sitter query on a code file - * @param file - * @param query tree sitter query; if missing, returns the entire tree - */ - code(file: WorkspaceFile, query?: string): Promise - - /** - * Parses and evaluates a math expression - * @param expression math expression compatible with mathjs - */ - math(expression: string): Promise - - /** - * Using the JSON schema, validates the content - * @param schema JSON schema instance - * @param content object to validate - */ - validateJSON(schema: JSONSchema, content: any): JSONSchemaValidation -} - -interface AICIGenOptions { - /** - * Make sure the generated text is one of the options. - */ - options?: string[] - /** - * Make sure the generated text matches given regular expression. - */ - regex?: string | RegExp - /** - * Make sure the generated text matches given yacc-like grammar. - */ - yacc?: string - /** - * Make sure the generated text is a substring of the given string. - */ - substring?: string - /** - * Used together with `substring` - treat the substring as ending the substring - * (typically '"' or similar). - */ - substringEnd?: string - /** - * Store result of the generation (as bytes) into a shared variable. - */ - storeVar?: string - /** - * Stop generation when the string is generated (the result includes the string and any following bytes (from the same token)). - */ - stopAt?: string - /** - * Stop generation when the given number of tokens have been generated. - */ - maxTokens?: number -} - -interface AICINode { - type: "aici" - name: "gen" -} - -interface AICIGenNode extends AICINode { - name: "gen" - options: AICIGenOptions -} - -interface AICI { - /** - * Generate a string that matches given constraints. - * If the tokens do not map cleanly into strings, it will contain Unicode replacement characters. - */ - gen(options: AICIGenOptions): AICIGenNode -} - -interface YAML { - /** - * Converts an object to its YAML representation - * @param obj - */ - stringify(obj: any): string - /** - * Parses a YAML string to object - */ - parse(text: string): any -} - -interface XML { - /** - * Parses an XML payload to an object - * @param text - */ - parse(text: string): any -} - -interface JSONL { - /** - * Parses a JSONL string to an array of objects - * @param text - */ - parse(text: string): any[] - /** - * Converts objects to JSONL format - * @param objs - */ - stringify(objs: any[]): string -} - -interface INI { - /** - * Parses a .ini file - * @param text - */ - parse(text: string): any - - /** - * Converts an object to.ini string - * @param value - */ - stringify(value: any): string -} - -interface CSV { - /** - * Parses a CSV string to an array of objects - * @param text - * @param options - */ - parse( - text: string, - options?: { - delimiter?: string - headers?: string[] - } - ): object[] - - /** - * Converts an array of object that represents a data table to a markdown table - * @param csv - * @param options - */ - markdownify(csv: object[], options?: { headers?: string[] }): string -} - -interface HighlightOptions { - maxLength?: number -} - -interface WebSearchResult { - webPages: WorkspaceFile[] -} - -interface VectorSearchOptions extends EmbeddingsModelOptions { - /** - * Maximum number of embeddings to use - */ - topK?: number - /** - * Minimum similarity score - */ - minScore?: number -} - -interface FuzzSearchOptions { - /** - * Controls whether to perform prefix search. It can be a simple boolean, or a - * function. - * - * If a boolean is passed, prefix search is performed if true. - * - * If a function is passed, it is called upon search with a search term, the - * positional index of that search term in the tokenized search query, and the - * tokenized search query. - */ - prefix?: boolean - /** - * Controls whether to perform fuzzy search. It can be a simple boolean, or a - * number, or a function. - * - * If a boolean is given, fuzzy search with a default fuzziness parameter is - * performed if true. - * - * If a number higher or equal to 1 is given, fuzzy search is performed, with - * a maximum edit distance (Levenshtein) equal to the number. - * - * If a number between 0 and 1 is given, fuzzy search is performed within a - * maximum edit distance corresponding to that fraction of the term length, - * approximated to the nearest integer. For example, 0.2 would mean an edit - * distance of 20% of the term length, so 1 character in a 5-characters term. - * The calculated fuzziness value is limited by the `maxFuzzy` option, to - * prevent slowdown for very long queries. - */ - fuzzy?: boolean | number - /** - * Controls the maximum fuzziness when using a fractional fuzzy value. This is - * set to 6 by default. Very high edit distances usually don't produce - * meaningful results, but can excessively impact search performance. - */ - maxFuzzy?: number - /** - * Maximum number of results to return - */ - topK?: number -} - -interface Retrieval { - /** - * Executers a Bing web search. Requires to configure the BING_SEARCH_API_KEY secret. - * @param query - */ - webSearch(query: string): Promise - - /** - * Search using similarity distance on embeddings - */ - vectorSearch( - query: string, - files: (string | WorkspaceFile) | (string | WorkspaceFile)[], - options?: VectorSearchOptions - ): Promise - - /** - * Performs a fuzzy search over the files - * @param query keywords to search - * @param files list of files - * @param options fuzzing configuration - */ - fuzzSearch( - query: string, - files: WorkspaceFile | WorkspaceFile[], - options?: FuzzSearchOptions - ): Promise -} - -type FetchTextOptions = Omit - -interface DataFilter { - /** - * The keys to select from the object. - * If a key is prefixed with -, it will be removed from the object. - */ - headers?: string[] - /** - * Selects the first N elements from the data - */ - sliceHead?: number - /** - * Selects the last N elements from the data - */ - sliceTail?: number - /** - * Selects the a random sample of N items in the collection. - */ - sliceSample?: number - - /** - * Removes items with duplicate values for the specified keys. - */ - distinct?: string[] -} - -interface DefDataOptions - extends Omit, - DataFilter { - /** - * Output format in the prompt. Defaults to markdownified CSV - */ - format?: "json" | "yaml" | "csv" -} - -interface DefSchemaOptions { - /** - * Output format in the prompt. - */ - format?: "typescript" | "json" | "yaml" -} - -type ChatFunctionHandler = ( - args: { context: ToolCallContext } & Record -) => ToolCallOutput | Promise - -interface WriteTextOptions extends ContextExpansionOptions { - /** - * Append text to the assistant response - */ - assistant?: boolean -} - -type PromptGenerator = (ctx: ChatGenerationContext) => Awaitable - -interface PromptGeneratorOptions extends ModelOptions { - /** - * Label for trace - */ - label?: string - - /** - * List of system prompts if any - */ - system?: SystemPromptId[] -} - -interface FileOutputOptions { - /** - * Schema identifier to validate the generated file - */ - schema?: string -} - -interface FileOutput { - pattern: string - description: string - options?: FileOutputOptions -} - -interface ChatTurnGenerationContext { - writeText(body: Awaitable, options?: WriteTextOptions): void - $(strings: TemplateStringsArray, ...args: any[]): void - fence(body: StringLike, options?: FenceOptions): void - def(name: string, body: StringLike, options?: DefOptions): string - defData( - name: string, - data: object[] | object, - options?: DefDataOptions - ): string - console: PromptGenerationConsole -} - -interface FileUpdate { - before: string - after: string - validation?: JSONSchemaValidation -} - -interface ChatGenerationContext extends ChatTurnGenerationContext { - defSchema( - name: string, - schema: JSONSchema, - options?: DefSchemaOptions - ): string - defImages(files: StringLike, options?: DefImagesOptions): void - defTool( - name: string, - description: string, - parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler - ): void - defChatParticipant( - participant: ChatParticipantHandler, - options?: ChatParticipantOptions - ): void - defFileOutput( - pattern: string, - description: string, - options?: FileOutputOptions - ): void -} - -interface GenerationOutput { - /** - * LLM output. - */ - text: string - - /** - * Parsed fence sections - */ - fences: Fenced[] - - /** - * Parsed data sections - */ - frames: DataFrame[] - - /** - * A map of file updates - */ - fileEdits: Record - - /** - * Generated variables, typically from AICI.gen - */ - genVars: Record - - /** - * Generated annotations - */ - annotations: Diagnostic[] - - /** - * Schema definition used in the generation - */ - schemas: Record - - /** - * Output as JSON if parsable - */ - json?: any -} - -type Point = { - row: number - column: number -} - -interface SyntaxNode { - id: number - typeId: number - grammarId: number - type: string - grammarType: string - isNamed: boolean - isMissing: boolean - isExtra: boolean - hasChanges: boolean - hasError: boolean - isError: boolean - text: string - parseState: number - nextParseState: number - startPosition: Point - endPosition: Point - startIndex: number - endIndex: number - parent: SyntaxNode | null - children: Array - namedChildren: Array - childCount: number - namedChildCount: number - firstChild: SyntaxNode | null - firstNamedChild: SyntaxNode | null - lastChild: SyntaxNode | null - lastNamedChild: SyntaxNode | null - nextSibling: SyntaxNode | null - nextNamedSibling: SyntaxNode | null - previousSibling: SyntaxNode | null - previousNamedSibling: SyntaxNode | null - descendantCount: number - - equals(other: SyntaxNode): boolean - toString(): string - child(index: number): SyntaxNode | null - namedChild(index: number): SyntaxNode | null - childForFieldName(fieldName: string): SyntaxNode | null - childForFieldId(fieldId: number): SyntaxNode | null - fieldNameForChild(childIndex: number): string | null - childrenForFieldName( - fieldName: string, - cursor: TreeCursor - ): Array - childrenForFieldId(fieldId: number, cursor: TreeCursor): Array - firstChildForIndex(index: number): SyntaxNode | null - firstNamedChildForIndex(index: number): SyntaxNode | null - - descendantForIndex(index: number): SyntaxNode - descendantForIndex(startIndex: number, endIndex: number): SyntaxNode - namedDescendantForIndex(index: number): SyntaxNode - namedDescendantForIndex(startIndex: number, endIndex: number): SyntaxNode - descendantForPosition(position: Point): SyntaxNode - descendantForPosition(startPosition: Point, endPosition: Point): SyntaxNode - namedDescendantForPosition(position: Point): SyntaxNode - namedDescendantForPosition( - startPosition: Point, - endPosition: Point - ): SyntaxNode - descendantsOfType( - types: String | Array, - startPosition?: Point, - endPosition?: Point - ): Array - - walk(): TreeCursor -} - -interface TreeCursor { - nodeType: string - nodeTypeId: number - nodeStateId: number - nodeText: string - nodeId: number - nodeIsNamed: boolean - nodeIsMissing: boolean - startPosition: Point - endPosition: Point - startIndex: number - endIndex: number - readonly currentNode: SyntaxNode - readonly currentFieldName: string - readonly currentFieldId: number - readonly currentDepth: number - readonly currentDescendantIndex: number - - reset(node: SyntaxNode): void - resetTo(cursor: TreeCursor): void - gotoParent(): boolean - gotoFirstChild(): boolean - gotoLastChild(): boolean - gotoFirstChildForIndex(goalIndex: number): boolean - gotoFirstChildForPosition(goalPosition: Point): boolean - gotoNextSibling(): boolean - gotoPreviousSibling(): boolean - gotoDescendant(goalDescendantIndex: number): void -} - -interface QueryCapture { - name: string - node: SyntaxNode -} - -interface ShellOptions { - cwd?: string - stdin?: string - /** - * Process timeout in milliseconds, default is 60s - */ - timeout?: number - /** - * trace label - */ - label?: string -} - -interface ShellOutput { - stdout?: string - stderr?: string - output?: string - exitCode: number - failed: boolean -} - -interface ShellHost { - exec( - command: string, - args: string[], - options?: ShellOptions - ): Promise -} - -interface ContainerOptions { - /** - * Container image names. - * @example python:alpine python:slim python - * @see https://hub.docker.com/_/python/ - */ - image?: string - - /** - * Enable networking in container (disabled by default) - */ - networkEnabled?: boolean - - /** - * Environment variables in container. A null/undefined variable is removed from the environment. - */ - env?: Record - - /** - * Assign the specified name to the container. Must match [a-zA-Z0-9_-]+ - */ - name?: string - - /** - * Disable automatic purge of container and volume directory - */ - disablePurge?: boolean -} - -interface PromptHost extends ShellHost { - container(options?: ContainerOptions): Promise -} - -interface ContainerHost extends ShellHost { - /** - * Container unique identifier in provider - */ - id: string - - /** - * Disable automatic purge of container and volume directory - */ - disablePurge: boolean - - /** - * Path to the volume mounted in the host - */ - hostPath: string - - /** - * Path to the volume mounted in the container - */ - containerPath: string - - /** - * Writes a file as text to the container file system - * @param path - * @param content - */ - writeText(path: string, content: string): Promise - - /** - * Reads a file as text from the container mounted volume - * @param path - */ - readText(path: string): Promise - - /** - * Copies a set of files into the container - * @param fromHost glob matching files - * @param toContainer directory in the container - */ - copyTo(fromHost: string | string[], toContainer: string): Promise - - /** - * Stops and cleans out the container - */ - stop(): Promise - - /** - * Force disconnect network - */ - disconnect(): Promise -} - -interface PromptContext extends ChatGenerationContext { - script(options: PromptArgs): void - system(options: PromptSystemArgs): void - defFileMerge(fn: FileMergeHandler): void - defOutputProcessor(fn: PromptOutputProcessorHandler): void - runPrompt( - generator: string | PromptGenerator, - options?: PromptGeneratorOptions - ): Promise - fetchText( - urlOrFile: string | WorkspaceFile, - options?: FetchTextOptions - ): Promise<{ - ok: boolean - status: number - text?: string - file?: WorkspaceFile - }> - cancel(reason?: string): void - env: ExpansionVariables - path: Path - parsers: Parsers - retrieval: Retrieval - /** - * @deprecated Use `workspace` instead - */ - fs: WorkspaceFileSystem - workspace: WorkspaceFileSystem - YAML: YAML - XML: XML - JSONL: JSONL - CSV: CSV - INI: INI - AICI: AICI - host: PromptHost -} - - - -// keep in sync with PromptContext! - -/** - * Console functions - */ -declare var console: PromptGenerationConsole - -/** - * Setup prompt title and other parameters. - * Exactly one call should be present on top of .genai.js file. - */ -declare function script(options: PromptArgs): void - -/** - * Equivalent of script() for system prompts. - */ -declare function system(options: PromptSystemArgs): void - -/** - * Append given string to the prompt. It automatically appends "\n". - * Typically best to use `` $`...` ``-templates instead. - */ -declare function writeText( - body: Awaitable, - options?: WriteTextOptions -): void - -/** - * Append given string to the prompt. It automatically appends "\n". - * `` $`foo` `` is the same as `text("foo")`. - */ -declare function $(strings: TemplateStringsArray, ...args: any[]): string - -/** - * Appends given (often multi-line) string to the prompt, surrounded in fences. - * Similar to `text(env.fence); text(body); text(env.fence)` - * - * @param body string to be fenced - */ -declare function fence(body: StringLike, options?: FenceOptions): void - -/** - * Defines `name` to be the (often multi-line) string `body`. - * Similar to `text(name + ":"); fence(body, language)` - * - * @param name name of defined entity, eg. "NOTE" or "This is text before NOTE" - * @param body string to be fenced/defined - * @returns variable name - */ -declare function def( - name: string, - body: StringLike, - options?: DefOptions -): string - -/** - * Declares a file that is expected to be generated by the LLM - * @param pattern file name or glob-like path - * @param options expectations about the generated file content - */ -declare function defFileOutput( - pattern: string, - description: string, - options?: FileOutputOptions -): void - -/** - * Declares a tool that can be called from the prompt. - * @param name The name of the tool to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. - * @param description A description of what the function does, used by the model to choose when and how to call the function. - * @param parameters The parameters the tool accepts, described as a JSON Schema object. - * @param fn callback invoked when the LLM requests to run this function - */ -declare function defTool( - name: string, - description: string, - parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler -): void - -/** - * Registers a callback to be called when a file is being merged - * @param fn - */ -declare function defFileMerge(fn: FileMergeHandler): void - -/** - * Variables coming from the fragment on which the prompt is operating. - */ -declare var env: ExpansionVariables - -/** - * Path manipulation functions. - */ -declare var path: Path - -/** - * A set of parsers for well-known file formats - */ -declare var parsers: Parsers - -/** - * Retrieval Augmented Generation services - */ -declare var retrieval: Retrieval - -/** - * Access to the workspace file system. - */ -declare var workspace: WorkspaceFileSystem - -/** - * YAML parsing and stringifying functions. - */ -declare var YAML: YAML - -/** - * INI parsing and stringifying. - */ -declare var INI: INI - -/** - * CSV parsing and stringifying. - */ -declare var CSV: CSV - -/** - * XML parsing and stringifying. - */ -declare var XML: XML - -/** - * JSONL parsing and stringifying. - */ -declare var JSONL: JSONL - -/** - * AICI operations - */ -declare var AICI: AICI - -/** - * Access to current LLM chat session information - */ -declare var host: PromptHost - -/** - * Fetches a given URL and returns the response. - * @param url - */ -declare function fetchText( - url: string | WorkspaceFile, - options?: FetchTextOptions -): Promise<{ ok: boolean; status: number; text?: string; file?: WorkspaceFile }> - -/** - * Declares a JSON schema variable. - * @param name name of the variable - * @param schema JSON schema instance - * @returns variable name - */ -declare function defSchema( - name: string, - schema: JSONSchema, - options?: DefSchemaOptions -): string - -/** - * Adds images to the prompt - * @param files - * @param options - */ -declare function defImages(files: StringLike, options?: DefImagesOptions): void - -/** - * Renders a table or object in the prompt - * @param name - * @param data - * @param options - * @returns variable name - */ -declare function defData( - name: string, - data: object[] | object, - options?: DefDataOptions -): string - -/** - * Cancels the current prompt generation/execution with the given reason. - * @param reason - */ -declare function cancel(reason?: string): void - -/** - * Expands and executes prompt - * @param generator - */ -declare function runPrompt( - generator: string | PromptGenerator, - options?: PromptGeneratorOptions -): Promise - -/** - * Registers a callback to process the LLM output - * @param fn - */ -declare function defOutputProcessor(fn: PromptOutputProcessorHandler): void - -/** - * Registers a chat participant - * @param participant - */ -declare function defChatParticipant( - participant: ChatParticipantHandler, - options?: ChatParticipantOptions -): void - -/** - * @deprecated Use `defOutputProcessor` instead. - */ -declare function defOutput(fn: PromptOutputProcessorHandler): void diff --git a/docs/src/content/docs/blog/tsconfig.json b/docs/src/content/docs/blog/tsconfig.json deleted file mode 100644 index 510eefe8f9..0000000000 --- a/docs/src/content/docs/blog/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "lib": [ - "ES2022" - ], - "target": "ES2023", - "module": "NodeNext", - "moduleDetection": "force", - "moduleResolution": "nodenext", - "checkJs": true, - "allowJs": true, - "skipLibCheck": true, - "noEmit": true, - "allowImportingTsExtensions": true - }, - "include": [ - "*.mjs", - "*.mts", - "./genaiscript.d.ts" - ] -} \ No newline at end of file From 1ce76f115605cd6cd17420d69e4bf2d1ac7c8b5b Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Thu, 22 Aug 2024 21:12:07 +0000 Subject: [PATCH 5/5] don't generate snippets in docs folder --- genaisrc/blog-generator.genai.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/genaisrc/blog-generator.genai.mjs b/genaisrc/blog-generator.genai.mjs index 9cf2024370..e0b3817f0d 100644 --- a/genaisrc/blog-generator.genai.mjs +++ b/genaisrc/blog-generator.genai.mjs @@ -173,7 +173,8 @@ defOutputProcessor((output) => { const fm = parsers.frontmatter(md) const fn = `docs/src/content/docs/blog/${fm.title.replace(/[^a-z0-9]+/gi, "-")}.md`.toLocaleLowerCase() - const sn = fn.replace(/\.md$/, ".genai.mjs") + const sn = + `packages/sample/genaisrc/blog/${fm.title.replace(/[^a-z0-9]+/gi, "-")}.genai.mjs`.toLocaleLowerCase() return { files: { [fn]: md,