Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move prompt files to CLI directory #1172

Merged
merged 12 commits into from
Feb 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
8 changes: 6 additions & 2 deletions docs/src/content/docs/reference/scripts/system.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ defTool(
if (frontmatter) {
const files = []
for (const { filename } of res) {
const file = {
const file: WorkspaceFile & { frontmatter?: string } = {
filename,
}
files.push(file)
Expand Down Expand Up @@ -2108,7 +2108,11 @@ defTool(
if (!matches?.length) return "No files found."
const q = await host.promiseQueue(5)
const files = await q.mapAll(matches, async ({ filename, content }) => {
const file = {
const file: WorkspaceFile & {
title?: string
description?: string
summary?: string
} = {
filename,
}
try {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"retrieval:search": "node packages/cli/built/genaiscript.cjs retrieval search lorem \"packages/sample/src/rag/*\"",
"retrieval:codequery": "node packages/cli/built/genaiscript.cjs code query packages/core/src/progress.ts \"(interface_declaration) @i\"",
"test:tokens": "node packages/cli/built/genaiscript.cjs retrieval tokens packages/sample/src/rag/*",
"test:system": "cd packages/core && node ../cli/built/genaiscript.cjs scripts compile",
"test:system": "cd packages/cli && node ./built/genaiscript.cjs scripts compile",
"test:compile": "node packages/cli/built/genaiscript.cjs scripts compile",
"test:fix": "node packages/cli/built/genaiscript.cjs scripts fix",
"test:infomodel": "node packages/cli/built/genaiscript.cjs scripts model",
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ defTool(
if (frontmatter) {
const files = []
for (const { filename } of res) {
const file = {
const file: WorkspaceFile & { frontmatter?: string } = {
filename,
}
files.push(file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ defTool(
if (!matches?.length) return "No files found."
const q = await host.promiseQueue(5)
const files = await q.mapAll(matches, async ({ filename, content }) => {
const file = {
const file: WorkspaceFile & {
title?: string
description?: string
summary?: string
} = {
filename,
}
try {
Expand Down
3 changes: 2 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"built/markdown.css",
"built/codicon.css",
"built/codicon.ttf",
"built/favicon.svg"
"built/favicon.svg",
"genaisrc/*.genai.mts"
],
"publisher": "Microsoft",
"repository": {
Expand Down
12 changes: 3 additions & 9 deletions packages/core/bundleprompts.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const { readdirSync, readFileSync, writeFileSync } = require("fs")
const { parse } = require("json5")

async function main() {
const dir = "./src/genaisrc"
const dir = "../cli/genaisrc"
const fp = "./src/default_prompts.ts"
const fmp = "../../docs/src/content/docs/reference/scripts/system.mdx"
const fnp = "../../docs/src/components/BuiltinTools.mdx"
Expand All @@ -11,10 +11,10 @@ async function main() {
const promptMap = {}
const prompts = readdirSync(dir)
for (const prompt of prompts) {
if (!/\.genai\.js$/.test(prompt)) continue
if (!/\.genai\.m?ts$/.test(prompt)) continue
const text = readFileSync(`${dir}/${prompt}`, "utf-8")
if (/^system\./.test(prompt)) {
const id = prompt.replace(/\.genai\.m?js$/i, "")
const id = prompt.replace(/\.genai\.m?ts$/i, "")
if (promptMap[id]) throw new Error(`duplicate prompt ${id}`)
promptMap[id] = text
}
Expand Down Expand Up @@ -105,12 +105,6 @@ async function main() {
console.log(`found ${functions.length} tools`)

const text = `// autogenerated - node bundleprompts.mjs
export const defaultPrompts = Object.freeze<Record<string, string>>(${JSON.stringify(
promptMap,
null,
4
)});

export const promptDefinitions = Object.freeze<Record<string, string>>(${JSON.stringify(
promptDefs,
null,
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ export const TRANSCRIPTION_MODEL_ID = "transcription"
export const SPEECH_MODEL_ID = "speech"
export const DEFAULT_FENCE_FORMAT: FenceFormat = "xml"
export const DEFAULT_TEMPERATURE = 0.8
export const BUILTIN_PREFIX = "_builtin/"
export const CACHE_LLMREQUEST_PREFIX = "genaiscript/cache/llm/"
export const CACHE_AIREQUEST_TRACE_PREFIX = "genaiscript/cache/ai/trace/"
export const CACHE_AIREQUEST_TEXT_PREFIX = "genaiscript/cache/ai/text/"
Expand Down
17 changes: 0 additions & 17 deletions packages/core/src/genaisrc/jsconfig.json

This file was deleted.

21 changes: 0 additions & 21 deletions packages/core/src/genaisrc/tsconfig.json

This file was deleted.

52 changes: 37 additions & 15 deletions packages/core/src/parser.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
// Importing utility functions and constants from other files
import { logVerbose, strcmp } from "./util" // String comparison function
import { defaultPrompts } from "./default_prompts" // Default prompt data
import { logVerbose, logWarn, strcmp } from "./util" // String comparison function
import { parsePromptScript } from "./template" // Function to parse scripts
import { readText } from "./fs" // Function to read text from a file
import { BUILTIN_PREFIX } from "./constants" // Constants for MIME types and prefixes
import { GENAI_ANYTS_REGEX } from "./constants" // Constants for MIME types and prefixes
import { Project } from "./server/messages"
import { resolveSystems } from "./systems"
import { resolveScriptParametersSchema } from "./vars"
import { dirname, join, resolve } from "node:path"
import { fileURLToPath } from "node:url"
import { readdir } from "node:fs/promises"
import { uniq } from "es-toolkit"

/**
* Converts a string to a character position represented as [row, column].
Expand All @@ -30,25 +33,44 @@ export async function parseProject(options: { scriptFiles: string[] }) {
const prj: Project = {
scripts: [],
diagnostics: [],
} // Initialize a new project instance

// Clone the default prompts
const deflPr: Record<string, string> = Object.assign({}, defaultPrompts)

}
const genaisrcDir = resolve(
join(
dirname(dirname(__filename ?? fileURLToPath(import.meta.url))),
"genaisrc"
)
) // ignore esbuild warning
const systemPrompts = await (
await readdir(genaisrcDir)
).filter((f) => GENAI_ANYTS_REGEX.test(f))
// Process each script file, parsing its content and updating the project
for (const f of scriptFiles) {
const tmpl = await parsePromptScript(f, await readText(f), prj)
const scripts: Record<string, PromptScript> = {}
for (const fn of systemPrompts) {
const f = join(genaisrcDir, fn)
const tmpl = await parsePromptScript(f, await readText(f))
if (!tmpl) {
logVerbose(`skipping invalid script file: ${f}`)
logWarn(`skipping invalid system script: ${fn}`)
continue
} // Skip if no template is parsed
delete deflPr[tmpl.id] // Remove the parsed template from defaults
prj.scripts.push(tmpl) // Add to project templates
scripts[tmpl.id] = tmpl
}

// Add remaining default prompts to the project
for (const [id, v] of Object.entries(deflPr)) {
prj.scripts.push(await parsePromptScript(BUILTIN_PREFIX + id, v, prj))
for (const f of uniq(scriptFiles).filter(
(f) => resolve(dirname(f)) !== genaisrcDir
)) {
const tmpl = await parsePromptScript(f, await readText(f))
if (!tmpl) {
logWarn(`skipping invalid script ${f}`)
continue
} // Skip if no template is parsed
if (scripts[tmpl.id]) {
logWarn(`duplicate script '${tmpl.id}' (${f})`)
logVerbose(` already defined in ${scripts[tmpl.id].filename}`)
continue
}
prj.scripts.push(tmpl) // Add t
scripts[tmpl.id] = tmpl
}

/**
Expand Down
9 changes: 4 additions & 5 deletions packages/core/src/scripts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,13 @@ export async function fixPromptDefinitions(project: Project) {
const { dirname, ts, js } = folder
{
const fn = host.path.join(dirname, ".gitignore")
const current = await tryReadText(fn)
const content = dedent`# auto-generated
genaiscript.d.ts
const current = (await tryReadText(fn)) || ""
const content = dedent`genaiscript.d.ts
tsconfig.json
jsconfig.json`
if (current !== content) {
if (!current.includes(content)) {
logVerbose(`updating ${fn}`)
await writeText(fn, content)
await writeText(fn, current + "\n#GenAIScript\n" + content)
}
}
for (let [defName, defContent] of Object.entries(promptDefinitions)) {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/systems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export function resolveSystems(
if (responseSchema && !responseType) systems.push("system.output_json")

// Include tools-related systems if specified in the script
if (tools.length) {
if (tools.length || resolvedTools?.length) {
systems.push("system.tools")
// Resolve and add each tool's systems based on its definition in the project
tools.forEach((tool) =>
Expand Down
22 changes: 5 additions & 17 deletions packages/core/src/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
* data types and formats.
*/

import { Project } from "./server/messages"
import { BUILTIN_PREFIX, GENAI_ANY_REGEX, PROMPTY_REGEX } from "./constants"
import { errorMessage } from "./error"
import { GENAI_ANY_REGEX, PROMPTY_REGEX } from "./constants"
import { host } from "./host"
import { JSON5TryParse } from "./json5"
import { humanize } from "inflection"
import { validateSchema } from "./schema"
import { promptyParse, promptyToGenAIScript } from "./prompty"

/**
Expand Down Expand Up @@ -76,20 +73,15 @@ function parsePromptScriptTools(jsSource: string) {
* @param finalizer - Finalizer function to perform additional validation.
* @returns The parsed PromptScript or undefined in case of errors.
*/
async function parsePromptTemplateCore(
filename: string,
content: string,
prj: Project
) {
async function parsePromptTemplateCore(filename: string, content: string) {
const r = {
id: templateIdFromFileName(filename),
title: humanize(
host.path.basename(filename).replace(GENAI_ANY_REGEX, "")
),
jsSource: content,
} as PromptScript
if (!filename.startsWith(BUILTIN_PREFIX))
r.filename = host.path.resolve(filename)
r.filename = host.path.resolve(filename)
const meta = parsePromptScriptMeta(r.jsSource)
Object.assign(r, meta)
return r
Expand All @@ -103,19 +95,15 @@ async function parsePromptTemplateCore(
* @param prj - The Project instance containing diagnostics.
* @returns The parsed PromptScript or undefined in case of errors.
*/
export async function parsePromptScript(
filename: string,
content: string,
prj: Project
) {
export async function parsePromptScript(filename: string, content: string) {
let text: string = undefined
if (PROMPTY_REGEX.test(filename)) {
text = content
const doc = await promptyParse(filename, content)
content = await promptyToGenAIScript(doc)
}

const script = await parsePromptTemplateCore(filename, content, prj)
const script = await parsePromptTemplateCore(filename, content)
if (text) script.text = text
return script
}
17 changes: 0 additions & 17 deletions packages/vscode/src/markdowndocumentprovider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@ import {
TRACE_NODE_PREFIX,
CACHE_LLMREQUEST_PREFIX,
CACHE_AIREQUEST_TRACE_PREFIX,
BUILTIN_PREFIX,
GENAI_ANY_REGEX,
CACHE_AIREQUEST_TEXT_PREFIX,
GENAI_MJS_EXT,
} from "../../core/src/constants"
import { defaultPrompts } from "../../core/src/default_prompts"
import { extractFenced, renderFencedVariables } from "../../core/src/fence"
import { prettifyMarkdown } from "../../core/src/markdown"
import {
Expand Down Expand Up @@ -131,12 +127,6 @@ ${prettifyMarkdown(md)}
.replace(/\.md$/, "")
return this.previewAIRequest(sha, "text")
}
if (uri.path.startsWith(BUILTIN_PREFIX)) {
const id = uri.path
.slice(BUILTIN_PREFIX.length)
.replace(GENAI_ANY_REGEX, "")
return defaultPrompts[id] ?? `No such builtin prompt: ${id}`
}
return ""
}

Expand Down Expand Up @@ -207,13 +197,6 @@ export function infoUri(path: string) {
return vscode.Uri.from({ scheme: SCHEME, path })
}

export function builtinPromptUri(id: string) {
return vscode.Uri.from({
scheme: SCHEME,
path: BUILTIN_PREFIX + id + GENAI_MJS_EXT,
})
}

export function activateMarkdownTextDocumentContentProvider(
state: ExtensionState
) {
Expand Down
5 changes: 1 addition & 4 deletions packages/vscode/src/promptcommands.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as vscode from "vscode"
import { ExtensionState } from "./state"
import { builtinPromptUri } from "./markdowndocumentprovider"
import { templatesToQuickPickItems } from "./fragmentcommands"
import { registerCommand } from "./commands"
import { createScript } from "../../core/src/scripts"
Expand Down Expand Up @@ -67,9 +66,7 @@ export function activatePromptCommands(state: ExtensionState) {
registerCommand(
"genaiscript.prompt.navigate",
async (prompt: PromptScript) => {
const uri = prompt.filename
? host.toUri(prompt.filename)
: builtinPromptUri(prompt.id)
const uri = host.toUri(prompt.filename)
await vscode.window.showTextDocument(uri)
}
)
Expand Down
Loading