From 782e715abd61ef5d16da3f20f4e33d6216bc8605 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:23:35 +0530 Subject: [PATCH 01/30] feat: add get-system-prompt utility that incorporates auto-generated docs --- lib/get-system-prompt.ts | 112 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 lib/get-system-prompt.ts diff --git a/lib/get-system-prompt.ts b/lib/get-system-prompt.ts new file mode 100644 index 0000000..ed53501 --- /dev/null +++ b/lib/get-system-prompt.ts @@ -0,0 +1,112 @@ +import * as fs from "fs" +import * as path from "path" + +/** + * Fetches the auto-generated tscircuit docs from the registry or local cache. + * These docs are generated from the tscircuit source and provide up-to-date + * component/prop references for the AI model. + */ +async function fetchAutoGeneratedDocs(): Promise { + // Try to load from local assets first (cached copy) + const localDocsPath = path.join( + process.cwd(), + "assets", + "tscircuit-docs.md" + ) + if (fs.existsSync(localDocsPath)) { + return fs.readFileSync(localDocsPath, "utf-8") + } + + // Fall back to fetching from the tscircuit docs endpoint + try { + const response = await fetch( + "https://registry-api.tscircuit.com/autorouting/docs/auto-generated" + ) + if (response.ok) { + return await response.text() + } + } catch (e) { + // ignore fetch errors, fall through to empty string + } + + return "" +} + +/** + * Builds the system prompt used for AI-based circuit generation benchmarks. + * Incorporates auto-generated tscircuit component documentation so the model + * has accurate, up-to-date API references. + */ +export async function getSystemPrompt(): Promise { + const autoGeneratedDocs = await fetchAutoGeneratedDocs() + + const docsSection = autoGeneratedDocs + ? `\n\n## tscircuit Component Reference (Auto-Generated)\n\n${autoGeneratedDocs}` + : "" + + return `You are an expert at generating tscircuit code. tscircuit is a TypeScript library for designing electronic circuits using React-like syntax. + +## Core Concepts + +- Use JSX/TSX syntax to describe circuits +- Components represent electronic parts (resistors, capacitors, LEDs, etc.) +- Connections are made using the \`net\` prop or by sharing net names +- Layouts are specified using props like \`pcbX\`, \`pcbY\`, \`schX\`, \`schY\` + +## Key Rules + +1. Always import from "tscircuit": \`import { resistor, capacitor, led, ... } from "tscircuit"\` +2. Use the \`\` component as the root element +3. Specify footprints using the \`footprint\` prop (e.g., \`footprint="0402"\`) +4. Connect components using shared net names (strings) on their pin props +5. Use \`\` components for explicit routing when needed +6. All measurements are in millimeters unless otherwise specified + +## Example Circuit + +\`\`\`tsx +import { resistor, led, battery } from "tscircuit" + +export default () => ( + + + + + +) +\`\`\` +${docsSection} + +## Instructions + +- Generate complete, valid tscircuit code that compiles without errors +- Include all necessary imports +- Use realistic component values and footprints +- Place components at reasonable PCB positions to avoid overlaps +- Always wrap everything in a default export function returning a \`\` element +- Do not use placeholder values — provide real electrical values +` +} From dec6b9d6bf23a53b275f3b1dad13022bb04a909b Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:23:47 +0530 Subject: [PATCH 02/30] feat: add script to fetch and cache auto-generated tscircuit docs --- scripts/update-docs.ts | 63 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 scripts/update-docs.ts diff --git a/scripts/update-docs.ts b/scripts/update-docs.ts new file mode 100644 index 0000000..5f7032d --- /dev/null +++ b/scripts/update-docs.ts @@ -0,0 +1,63 @@ +/** + * Script to fetch and cache the auto-generated tscircuit documentation. + * Run this periodically to keep the docs up-to-date. + * + * Usage: npx tsx scripts/update-docs.ts + */ + +import * as fs from "fs" +import * as path from "path" + +const DOCS_OUTPUT_PATH = path.join(process.cwd(), "assets", "tscircuit-docs.md") + +const DOCS_SOURCES = [ + // tscircuit registry auto-generated docs + "https://registry-api.tscircuit.com/autorouting/docs/auto-generated", + // fallback: GitHub raw content + "https://raw.githubusercontent.com/tscircuit/tscircuit/main/docs/AUTO_GENERATED.md", +] + +async function fetchDocs(): Promise { + for (const url of DOCS_SOURCES) { + try { + console.log(`Trying to fetch docs from: ${url}`) + const response = await fetch(url) + if (response.ok) { + const text = await response.text() + if (text.trim().length > 0) { + console.log(`✓ Successfully fetched docs from: ${url}`) + return text + } + } else { + console.warn(`✗ Failed to fetch from ${url}: HTTP ${response.status}`) + } + } catch (e) { + console.warn(`✗ Error fetching from ${url}:`, e) + } + } + return null +} + +async function main() { + const docs = await fetchDocs() + + if (!docs) { + console.error("Failed to fetch docs from any source.") + process.exit(1) + } + + // Ensure the assets directory exists + const assetsDir = path.dirname(DOCS_OUTPUT_PATH) + if (!fs.existsSync(assetsDir)) { + fs.mkdirSync(assetsDir, { recursive: true }) + } + + fs.writeFileSync(DOCS_OUTPUT_PATH, docs, "utf-8") + console.log(`✓ Docs written to: ${DOCS_OUTPUT_PATH}`) + console.log(` Size: ${(docs.length / 1024).toFixed(1)} KB`) +} + +main().catch((e) => { + console.error(e) + process.exit(1) +}) From 01768281b3281636737a587a502dca41c0b8a017 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:24:01 +0530 Subject: [PATCH 03/30] feat: add getSystemPromptWithDocs that merges base prompt with auto-generated docs --- lib/get-system-prompt-with-docs.ts | 58 ++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 lib/get-system-prompt-with-docs.ts diff --git a/lib/get-system-prompt-with-docs.ts b/lib/get-system-prompt-with-docs.ts new file mode 100644 index 0000000..7562bf0 --- /dev/null +++ b/lib/get-system-prompt-with-docs.ts @@ -0,0 +1,58 @@ +import * as fs from "fs" +import * as path from "path" + +const DOCS_CACHE_PATH = path.join( + process.cwd(), + "assets", + "tscircuit-docs.md" +) + +/** + * Reads the auto-generated tscircuit docs from the local cache file. + * The cache is populated by running `npx tsx scripts/update-docs.ts`. + */ +function readCachedDocs(): string { + if (fs.existsSync(DOCS_CACHE_PATH)) { + return fs.readFileSync(DOCS_CACHE_PATH, "utf-8") + } + return "" +} + +/** + * Returns the base system prompt text (without docs) as a plain string. + * This is the static portion that instructs the model on tscircuit basics. + */ +export function getBaseSystemPrompt(): string { + return `You are an expert at generating tscircuit code. tscircuit is a TypeScript library for designing electronic circuits using a React-like JSX/TSX syntax. + +## Rules +- Always import components from "tscircuit" +- Use a \`\` element as the root +- Specify component footprints using the \`footprint\` prop +- Connect pins using shared net name strings +- All coordinates and dimensions are in millimeters +- Export the circuit as a default function +- Do not use placeholder values; use real electrical values and footprints` +} + +/** + * Returns the full system prompt including auto-generated component docs. + * The docs section is appended after the base prompt. + */ +export function getSystemPromptWithDocs(): string { + const base = getBaseSystemPrompt() + const docs = readCachedDocs() + + if (!docs) { + return base + } + + return `${base} + +## tscircuit Component Reference (Auto-Generated Docs) + +The following documentation is auto-generated from the tscircuit source and provides +accurate, up-to-date API references for all available components and their props. + +${docs}` +} From 2e1addeb9d06d5eb8d89b30e19c179ee0deac45f Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:24:08 +0530 Subject: [PATCH 04/30] feat: expose systemPrompt with docs for use in eval files --- evals/eval-with-docs.eval.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 evals/eval-with-docs.eval.ts diff --git a/evals/eval-with-docs.eval.ts b/evals/eval-with-docs.eval.ts new file mode 100644 index 0000000..ea21f60 --- /dev/null +++ b/evals/eval-with-docs.eval.ts @@ -0,0 +1,18 @@ +import { getSystemPromptWithDocs } from "../lib/get-system-prompt-with-docs" + +/** + * Re-exports the system prompt with auto-generated docs for use in evals. + * Import `systemPrompt` from this module wherever you need the full prompt. + * + * Example usage in an eval file: + * + * ```ts + * import { systemPrompt } from "../evals/eval-with-docs.eval" + * + * const result = await aiModel.complete({ + * system: systemPrompt, + * prompt: "Create a simple LED circuit with a current-limiting resistor", + * }) + * ``` + */ +export const systemPrompt = getSystemPromptWithDocs() From 2bf336d71d6446971f4f23ffd5974b761dbae8a1 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:24:25 +0530 Subject: [PATCH 05/30] feat: update system-prompt to include auto-generated tscircuit docs --- lib/system-prompt.ts | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 lib/system-prompt.ts diff --git a/lib/system-prompt.ts b/lib/system-prompt.ts new file mode 100644 index 0000000..766913e --- /dev/null +++ b/lib/system-prompt.ts @@ -0,0 +1,64 @@ +import * as fs from "fs" +import * as path from "path" + +/** + * Reads the auto-generated tscircuit documentation from the local assets folder. + * These docs are generated from the official tscircuit source and cover all + * available components, their props, and usage examples. + * + * To refresh the docs, run: + * npx tsx scripts/update-docs.ts + */ +function getAutoGeneratedDocs(): string { + const docsPath = path.join(process.cwd(), "assets", "tscircuit-docs.md") + if (fs.existsSync(docsPath)) { + return fs.readFileSync(docsPath, "utf-8") + } + return "" +} + +/** + * The main system prompt used in all tscircuit prompt benchmarks. + * + * Includes: + * 1. Core instructions for generating valid tscircuit code + * 2. Auto-generated component documentation for accurate API references + */ +export function getSystemPrompt(): string { + const autoGeneratedDocs = getAutoGeneratedDocs() + + const docsBlock = autoGeneratedDocs + ? `\n\n\n${autoGeneratedDocs}\n` + : "" + + return `You are an expert electronics engineer and tscircuit developer. +tscircuit is an open-source TypeScript library that lets you design PCBs and schematics +using React/JSX syntax. + +## Coding Rules + +1. Import all components from \`"tscircuit"\` +2. The root element must always be \`\` +3. Specify footprints via the \`footprint\` prop (e.g. \`footprint="0402"\`, \`footprint="soic8"\`) +4. Connect component pins by giving them the same net name string +5. Use \`pcbX\` / \`pcbY\` (mm) to position components on the PCB +6. Use \`schX\` / \`schY\` to position components on the schematic +7. Export the circuit as a default function returning JSX +8. Use real component values — no placeholders +9. Avoid component overlaps by spacing parts at least 2 mm apart + +## Example + +\`\`\`tsx +import { resistor, led, battery } from "tscircuit" + +export default () => ( + + + + + +) +\`\`\` +${docsBlock}` +} From f8b3dc110955ef2a7023a065b13a4b24d101de82 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:24:29 +0530 Subject: [PATCH 06/30] chore: ensure assets directory is tracked by git --- assets/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/.gitkeep diff --git a/assets/.gitkeep b/assets/.gitkeep new file mode 100644 index 0000000..e69de29 From e063baf23f032d54db334aa8c2a5862e6efb963d Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:47:09 +0530 Subject: [PATCH 07/30] refactor: extract shared BASE_SYSTEM_PROMPT to eliminate duplication across helpers --- lib/base-system-prompt.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 lib/base-system-prompt.ts diff --git a/lib/base-system-prompt.ts b/lib/base-system-prompt.ts new file mode 100644 index 0000000..68c48bf --- /dev/null +++ b/lib/base-system-prompt.ts @@ -0,0 +1,27 @@ +/** + * Single shared base system prompt used across all tscircuit prompt benchmark helpers. + * Each variant (sync, async, with-docs) imports this and only customizes + * the docs-loading / wrapping strategy on top of it. + */ +export const BASE_SYSTEM_PROMPT = `You are an expert electronics engineer and tscircuit developer. Your job is to create tscircuit components. + +Rules: +- Export a default function component called MyCircuit +- Use only tscircuit/core components: , , , , , , , , , , , , , , , +- Do not import anything – all tscircuit components are globally available +- All dimensions are in mm +- Use schX/schY for schematic positioning and pcbX/pcbY for PCB positioning +- Connect components with using the fromPort/toPort props or with using the net prop +- Always specify footprint for chips (e.g. footprint="soic8" or footprint="0402") + +Example component: +\`\`\`tsx +export default () => ( + + + + + +) +\`\`\` +` From 66678c293529f9fcee64b065dfdf7064409e5041 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:47:19 +0530 Subject: [PATCH 08/30] fix: use node: specifier for built-in imports; clarify docstring; use shared BASE_SYSTEM_PROMPT --- lib/system-prompt.ts | 84 +++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 55 deletions(-) diff --git a/lib/system-prompt.ts b/lib/system-prompt.ts index 766913e..e6a7a4f 100644 --- a/lib/system-prompt.ts +++ b/lib/system-prompt.ts @@ -1,64 +1,38 @@ -import * as fs from "fs" -import * as path from "path" +import fs from "node:fs" +import path from "node:path" +import { BASE_SYSTEM_PROMPT } from "./base-system-prompt" + +const DOCS_PATH = path.join(import.meta.dirname ?? __dirname, "../assets/tscircuit-docs.md") /** - * Reads the auto-generated tscircuit documentation from the local assets folder. - * These docs are generated from the official tscircuit source and cover all - * available components, their props, and usage examples. + * Returns the base system prompt, optionally appending cached tscircuit docs + * wrapped in a `` block. + * + * Note: benchmarks that use `createLocalCircuitPrompt()` build their own prompt + * inline. This helper is provided for eval scripts that want a pre-built prompt + * with or without the cached docs appended. * - * To refresh the docs, run: - * npx tsx scripts/update-docs.ts + * @param includeDocs - When true, the contents of `assets/tscircuit-docs.md` + * are appended (if the file exists). */ -function getAutoGeneratedDocs(): string { - const docsPath = path.join(process.cwd(), "assets", "tscircuit-docs.md") - if (fs.existsSync(docsPath)) { - return fs.readFileSync(docsPath, "utf-8") +export function getSystemPrompt(includeDocs = false): string { + if (!includeDocs) { + return BASE_SYSTEM_PROMPT + } + + let docs = "" + try { + docs = fs.readFileSync(DOCS_PATH, "utf-8") + } catch { + // Cache file not present – return base prompt only + return BASE_SYSTEM_PROMPT } - return "" + + return `${BASE_SYSTEM_PROMPT}\n\n${docs}\n` } /** - * The main system prompt used in all tscircuit prompt benchmarks. - * - * Includes: - * 1. Core instructions for generating valid tscircuit code - * 2. Auto-generated component documentation for accurate API references + * The base system prompt without any docs appended. + * Provided as a convenience export for cases where a static string is needed. */ -export function getSystemPrompt(): string { - const autoGeneratedDocs = getAutoGeneratedDocs() - - const docsBlock = autoGeneratedDocs - ? `\n\n\n${autoGeneratedDocs}\n` - : "" - - return `You are an expert electronics engineer and tscircuit developer. -tscircuit is an open-source TypeScript library that lets you design PCBs and schematics -using React/JSX syntax. - -## Coding Rules - -1. Import all components from \`"tscircuit"\` -2. The root element must always be \`\` -3. Specify footprints via the \`footprint\` prop (e.g. \`footprint="0402"\`, \`footprint="soic8"\`) -4. Connect component pins by giving them the same net name string -5. Use \`pcbX\` / \`pcbY\` (mm) to position components on the PCB -6. Use \`schX\` / \`schY\` to position components on the schematic -7. Export the circuit as a default function returning JSX -8. Use real component values — no placeholders -9. Avoid component overlaps by spacing parts at least 2 mm apart - -## Example - -\`\`\`tsx -import { resistor, led, battery } from "tscircuit" - -export default () => ( - - - - - -) -\`\`\` -${docsBlock}` -} +export const systemPrompt = BASE_SYSTEM_PROMPT From 88aaca7163750ec7cf1e8cb9a1586a2217bbc7fb Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:47:28 +0530 Subject: [PATCH 09/30] fix: use node: specifier, shared BASE_SYSTEM_PROMPT, consistent wrapper --- lib/get-system-prompt.ts | 138 ++++++++++----------------------------- 1 file changed, 36 insertions(+), 102 deletions(-) diff --git a/lib/get-system-prompt.ts b/lib/get-system-prompt.ts index ed53501..d41a90f 100644 --- a/lib/get-system-prompt.ts +++ b/lib/get-system-prompt.ts @@ -1,112 +1,46 @@ -import * as fs from "fs" -import * as path from "path" +import fs from "node:fs" +import path from "node:path" +import { BASE_SYSTEM_PROMPT } from "./base-system-prompt" -/** - * Fetches the auto-generated tscircuit docs from the registry or local cache. - * These docs are generated from the tscircuit source and provide up-to-date - * component/prop references for the AI model. - */ -async function fetchAutoGeneratedDocs(): Promise { - // Try to load from local assets first (cached copy) - const localDocsPath = path.join( - process.cwd(), - "assets", - "tscircuit-docs.md" - ) - if (fs.existsSync(localDocsPath)) { - return fs.readFileSync(localDocsPath, "utf-8") - } - - // Fall back to fetching from the tscircuit docs endpoint - try { - const response = await fetch( - "https://registry-api.tscircuit.com/autorouting/docs/auto-generated" - ) - if (response.ok) { - return await response.text() - } - } catch (e) { - // ignore fetch errors, fall through to empty string - } - - return "" -} +const DOCS_PATH = path.join(import.meta.dirname ?? __dirname, "../assets/tscircuit-docs.md") +const REGISTRY_DOCS_URL = + "https://raw.githubusercontent.com/tscircuit/tscircuit/main/docs/tscircuit-docs.md" /** - * Builds the system prompt used for AI-based circuit generation benchmarks. - * Incorporates auto-generated tscircuit component documentation so the model - * has accurate, up-to-date API references. + * Async system prompt builder. + * + * 1. Tries to read the pre-cached `assets/tscircuit-docs.md`. + * 2. Falls back to fetching from the registry/GitHub when the cache is absent. + * 3. Returns the base prompt alone when neither source is available. + * + * Docs are wrapped in a `` block so models can easily + * identify the reference material. */ export async function getSystemPrompt(): Promise { - const autoGeneratedDocs = await fetchAutoGeneratedDocs() - - const docsSection = autoGeneratedDocs - ? `\n\n## tscircuit Component Reference (Auto-Generated)\n\n${autoGeneratedDocs}` - : "" - - return `You are an expert at generating tscircuit code. tscircuit is a TypeScript library for designing electronic circuits using React-like syntax. + let docs: string | null = null -## Core Concepts - -- Use JSX/TSX syntax to describe circuits -- Components represent electronic parts (resistors, capacitors, LEDs, etc.) -- Connections are made using the \`net\` prop or by sharing net names -- Layouts are specified using props like \`pcbX\`, \`pcbY\`, \`schX\`, \`schY\` - -## Key Rules - -1. Always import from "tscircuit": \`import { resistor, capacitor, led, ... } from "tscircuit"\` -2. Use the \`\` component as the root element -3. Specify footprints using the \`footprint\` prop (e.g., \`footprint="0402"\`) -4. Connect components using shared net names (strings) on their pin props -5. Use \`\` components for explicit routing when needed -6. All measurements are in millimeters unless otherwise specified - -## Example Circuit - -\`\`\`tsx -import { resistor, led, battery } from "tscircuit" + // 1. Try cache first + try { + docs = fs.readFileSync(DOCS_PATH, "utf-8") + } catch { + // Cache miss – fall through to network fetch + } -export default () => ( - - - - - -) -\`\`\` -${docsSection} + // 2. Fetch from registry if cache is unavailable + if (!docs) { + try { + const res = await fetch(REGISTRY_DOCS_URL) + if (res.ok) { + docs = await res.text() + } + } catch { + // Network unavailable – fall through + } + } -## Instructions + if (!docs) { + return BASE_SYSTEM_PROMPT + } -- Generate complete, valid tscircuit code that compiles without errors -- Include all necessary imports -- Use realistic component values and footprints -- Place components at reasonable PCB positions to avoid overlaps -- Always wrap everything in a default export function returning a \`\` element -- Do not use placeholder values — provide real electrical values -` + return `${BASE_SYSTEM_PROMPT}\n\n${docs}\n` } From bf7bd8ff7ddc8e80429db93d0518f382d7c94474 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:47:36 +0530 Subject: [PATCH 10/30] fix: use node: specifier, shared BASE_SYSTEM_PROMPT, consistent wrapper across all helpers --- lib/get-system-prompt-with-docs.ts | 64 +++++++++--------------------- 1 file changed, 19 insertions(+), 45 deletions(-) diff --git a/lib/get-system-prompt-with-docs.ts b/lib/get-system-prompt-with-docs.ts index 7562bf0..62f303f 100644 --- a/lib/get-system-prompt-with-docs.ts +++ b/lib/get-system-prompt-with-docs.ts @@ -1,58 +1,32 @@ -import * as fs from "fs" -import * as path from "path" +import fs from "node:fs" +import path from "node:path" +import { BASE_SYSTEM_PROMPT } from "./base-system-prompt" -const DOCS_CACHE_PATH = path.join( - process.cwd(), - "assets", - "tscircuit-docs.md" -) +const DOCS_PATH = path.join(import.meta.dirname ?? __dirname, "../assets/tscircuit-docs.md") /** - * Reads the auto-generated tscircuit docs from the local cache file. - * The cache is populated by running `npx tsx scripts/update-docs.ts`. - */ -function readCachedDocs(): string { - if (fs.existsSync(DOCS_CACHE_PATH)) { - return fs.readFileSync(DOCS_CACHE_PATH, "utf-8") - } - return "" -} - -/** - * Returns the base system prompt text (without docs) as a plain string. - * This is the static portion that instructs the model on tscircuit basics. + * Returns the base system prompt without any docs appended. + * Useful when you want to compare eval quality with/without the docs reference. */ export function getBaseSystemPrompt(): string { - return `You are an expert at generating tscircuit code. tscircuit is a TypeScript library for designing electronic circuits using a React-like JSX/TSX syntax. - -## Rules -- Always import components from "tscircuit" -- Use a \`\` element as the root -- Specify component footprints using the \`footprint\` prop -- Connect pins using shared net name strings -- All coordinates and dimensions are in millimeters -- Export the circuit as a default function -- Do not use placeholder values; use real electrical values and footprints` + return BASE_SYSTEM_PROMPT } /** - * Returns the full system prompt including auto-generated component docs. - * The docs section is appended after the base prompt. + * Returns the base system prompt with the cached tscircuit docs appended inside + * a `` block. + * + * If `assets/tscircuit-docs.md` does not exist, falls back to the base prompt. + * Run `npx tsx scripts/update-docs.ts` to populate the cache. */ export function getSystemPromptWithDocs(): string { - const base = getBaseSystemPrompt() - const docs = readCachedDocs() - - if (!docs) { - return base + let docs = "" + try { + docs = fs.readFileSync(DOCS_PATH, "utf-8") + } catch { + // Cache file not present – return base prompt only + return BASE_SYSTEM_PROMPT } - return `${base} - -## tscircuit Component Reference (Auto-Generated Docs) - -The following documentation is auto-generated from the tscircuit source and provides -accurate, up-to-date API references for all available components and their props. - -${docs}` + return `${BASE_SYSTEM_PROMPT}\n\n${docs}\n` } From 85c9baa2c950c5edc25871d420a2665139531637 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:47:43 +0530 Subject: [PATCH 11/30] fix: use node: specifier with default imports for fs and path (align with repo convention) --- scripts/update-docs.ts | 72 +++++++++++------------------------------- 1 file changed, 19 insertions(+), 53 deletions(-) diff --git a/scripts/update-docs.ts b/scripts/update-docs.ts index 5f7032d..53e3910 100644 --- a/scripts/update-docs.ts +++ b/scripts/update-docs.ts @@ -1,63 +1,29 @@ -/** - * Script to fetch and cache the auto-generated tscircuit documentation. - * Run this periodically to keep the docs up-to-date. - * - * Usage: npx tsx scripts/update-docs.ts - */ - -import * as fs from "fs" -import * as path from "path" - -const DOCS_OUTPUT_PATH = path.join(process.cwd(), "assets", "tscircuit-docs.md") - -const DOCS_SOURCES = [ - // tscircuit registry auto-generated docs - "https://registry-api.tscircuit.com/autorouting/docs/auto-generated", - // fallback: GitHub raw content - "https://raw.githubusercontent.com/tscircuit/tscircuit/main/docs/AUTO_GENERATED.md", -] - -async function fetchDocs(): Promise { - for (const url of DOCS_SOURCES) { - try { - console.log(`Trying to fetch docs from: ${url}`) - const response = await fetch(url) - if (response.ok) { - const text = await response.text() - if (text.trim().length > 0) { - console.log(`✓ Successfully fetched docs from: ${url}`) - return text - } - } else { - console.warn(`✗ Failed to fetch from ${url}: HTTP ${response.status}`) - } - } catch (e) { - console.warn(`✗ Error fetching from ${url}:`, e) - } - } - return null -} +import fs from "node:fs" +import path from "node:path" + +const REGISTRY_DOCS_URL = + "https://raw.githubusercontent.com/tscircuit/tscircuit/main/docs/tscircuit-docs.md" + +const ASSETS_DIR = path.join(import.meta.dirname ?? __dirname, "../assets") +const DOCS_PATH = path.join(ASSETS_DIR, "tscircuit-docs.md") async function main() { - const docs = await fetchDocs() + console.log(`Fetching docs from ${REGISTRY_DOCS_URL} …`) - if (!docs) { - console.error("Failed to fetch docs from any source.") - process.exit(1) + const res = await fetch(REGISTRY_DOCS_URL) + if (!res.ok) { + throw new Error(`Failed to fetch docs: ${res.status} ${res.statusText}`) } - // Ensure the assets directory exists - const assetsDir = path.dirname(DOCS_OUTPUT_PATH) - if (!fs.existsSync(assetsDir)) { - fs.mkdirSync(assetsDir, { recursive: true }) - } + const content = await res.text() + + fs.mkdirSync(ASSETS_DIR, { recursive: true }) + fs.writeFileSync(DOCS_PATH, content, "utf-8") - fs.writeFileSync(DOCS_OUTPUT_PATH, docs, "utf-8") - console.log(`✓ Docs written to: ${DOCS_OUTPUT_PATH}`) - console.log(` Size: ${(docs.length / 1024).toFixed(1)} KB`) + console.log(`✅ Docs written to ${DOCS_PATH} (${content.length} bytes)`) } -main().catch((e) => { - console.error(e) +main().catch((err) => { + console.error(err) process.exit(1) }) From 6f6aa54a559b1378cf39e1c604701e523a7a7031 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 01:47:48 +0530 Subject: [PATCH 12/30] fix: use getSystemPromptWithDocs() so eval output is wrapped in block as intended --- evals/eval-with-docs.eval.ts | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/evals/eval-with-docs.eval.ts b/evals/eval-with-docs.eval.ts index ea21f60..b100730 100644 --- a/evals/eval-with-docs.eval.ts +++ b/evals/eval-with-docs.eval.ts @@ -1,18 +1,9 @@ -import { getSystemPromptWithDocs } from "../lib/get-system-prompt-with-docs" - /** - * Re-exports the system prompt with auto-generated docs for use in evals. - * Import `systemPrompt` from this module wherever you need the full prompt. - * - * Example usage in an eval file: + * Eval entry-point that uses the system prompt augmented with the cached + * tscircuit docs wrapped in a `` block. * - * ```ts - * import { systemPrompt } from "../evals/eval-with-docs.eval" - * - * const result = await aiModel.complete({ - * system: systemPrompt, - * prompt: "Create a simple LED circuit with a current-limiting resistor", - * }) - * ``` + * Run `npx tsx scripts/update-docs.ts` first to populate `assets/tscircuit-docs.md`. */ +import { getSystemPromptWithDocs } from "../lib/get-system-prompt-with-docs" + export const systemPrompt = getSystemPromptWithDocs() From bb6210a9a0ceb7f7ca81aa6af7b4b146fda8a5f7 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:31:52 +0530 Subject: [PATCH 13/30] feat: add getSystemPrompt with auto-generated docs integration --- lib/get-system-prompt.ts | 92 +++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 39 deletions(-) diff --git a/lib/get-system-prompt.ts b/lib/get-system-prompt.ts index d41a90f..ff65839 100644 --- a/lib/get-system-prompt.ts +++ b/lib/get-system-prompt.ts @@ -1,46 +1,60 @@ -import fs from "node:fs" -import path from "node:path" -import { BASE_SYSTEM_PROMPT } from "./base-system-prompt" - -const DOCS_PATH = path.join(import.meta.dirname ?? __dirname, "../assets/tscircuit-docs.md") -const REGISTRY_DOCS_URL = - "https://raw.githubusercontent.com/tscircuit/tscircuit/main/docs/tscircuit-docs.md" - -/** - * Async system prompt builder. - * - * 1. Tries to read the pre-cached `assets/tscircuit-docs.md`. - * 2. Falls back to fetching from the registry/GitHub when the cache is absent. - * 3. Returns the base prompt alone when neither source is available. - * - * Docs are wrapped in a `` block so models can easily - * identify the reference material. - */ -export async function getSystemPrompt(): Promise { - let docs: string | null = null +import { getAvailableComponents } from "./get-available-components" - // 1. Try cache first - try { - docs = fs.readFileSync(DOCS_PATH, "utf-8") - } catch { - // Cache miss – fall through to network fetch - } +const TSCIRCUIT_DOCS_URL = + "https://raw.githubusercontent.com/tscircuit/docs/main/ai/overview.md" + +let cachedDocs: string | null = null - // 2. Fetch from registry if cache is unavailable - if (!docs) { - try { - const res = await fetch(REGISTRY_DOCS_URL) - if (res.ok) { - docs = await res.text() - } - } catch { - // Network unavailable – fall through +async function fetchAutoGeneratedDocs(): Promise { + if (cachedDocs) return cachedDocs + try { + const response = await fetch(TSCIRCUIT_DOCS_URL) + if (response.ok) { + cachedDocs = await response.text() + return cachedDocs } + } catch (e) { + // fall through to empty string if fetch fails } + return "" +} - if (!docs) { - return BASE_SYSTEM_PROMPT - } +export async function getSystemPrompt(): Promise { + const autoGeneratedDocs = await fetchAutoGeneratedDocs() + + const basePrompt = `You are an expert tscircuit developer. tscircuit is a TypeScript library for designing electronic circuits using React-like syntax. + +## Auto-Generated tscircuit Documentation +${autoGeneratedDocs} + +## Key Principles +- Use tscircuit components to create circuit schematics and PCB layouts +- Components are written as JSX/TSX with React-like syntax +- Always import from "tscircuit" package +- Common components: , , , , , , +- Use the \`name\` prop to label each component uniquely +- Connections are made via the \`connections\` prop or by sharing net names +- Footprints define the physical PCB layout + +## Example Circuit +\`\`\`tsx +import { Circuit, Resistor, Led } from "tscircuit" + +export default () => ( + + + + +) +\`\`\` + +When writing circuits: +1. Always export a default function component +2. Wrap everything in a element with width and height +3. Give every component a unique \`name\` prop +4. Specify \`footprint\` for PCB components +5. Use resistance/capacitance values with units (e.g. "10kohm", "100nF") +` - return `${BASE_SYSTEM_PROMPT}\n\n${docs}\n` + return basePrompt } From 7896fea9d3700ff029599884406eb87a5728ce72 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:32:06 +0530 Subject: [PATCH 14/30] feat: use @tscircuit/snippets-ai-docs in system prompt --- lib/get-system-prompt.ts | 87 +++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/lib/get-system-prompt.ts b/lib/get-system-prompt.ts index ff65839..dd5a047 100644 --- a/lib/get-system-prompt.ts +++ b/lib/get-system-prompt.ts @@ -1,60 +1,63 @@ -import { getAvailableComponents } from "./get-available-components" +import snippetsIndex from "@tscircuit/snippets-ai-docs" -const TSCIRCUIT_DOCS_URL = - "https://raw.githubusercontent.com/tscircuit/docs/main/ai/overview.md" +export function getSystemPrompt(opts?: { includeAllDocs?: boolean }): string { + const { includeAllDocs = false } = opts ?? {} -let cachedDocs: string | null = null + // Collect auto-generated docs from @tscircuit/snippets-ai-docs + let autoGeneratedDocs = "" -async function fetchAutoGeneratedDocs(): Promise { - if (cachedDocs) return cachedDocs - try { - const response = await fetch(TSCIRCUIT_DOCS_URL) - if (response.ok) { - cachedDocs = await response.text() - return cachedDocs + if (includeAllDocs) { + // Include all available documentation + for (const [key, content] of Object.entries(snippetsIndex)) { + autoGeneratedDocs += `\n\n### ${key}\n${content}` + } + } else { + // Include core/essential docs by default + const coreKeys = [ + "overview", + "basic-syntax", + "components", + "footprints", + "connections", + "netlist", + ] + for (const key of coreKeys) { + if (key in snippetsIndex) { + autoGeneratedDocs += `\n\n### ${key}\n${(snippetsIndex as Record)[key]}` + } + } + // Fall back to all docs if none of the core keys exist + if (!autoGeneratedDocs.trim()) { + for (const [key, content] of Object.entries(snippetsIndex)) { + autoGeneratedDocs += `\n\n### ${key}\n${content}` + } } - } catch (e) { - // fall through to empty string if fetch fails } - return "" -} -export async function getSystemPrompt(): Promise { - const autoGeneratedDocs = await fetchAutoGeneratedDocs() + return `You are an expert tscircuit developer. tscircuit is a TypeScript/React library for building electronic circuits. - const basePrompt = `You are an expert tscircuit developer. tscircuit is a TypeScript library for designing electronic circuits using React-like syntax. - -## Auto-Generated tscircuit Documentation +## tscircuit Documentation (Auto-Generated) ${autoGeneratedDocs} -## Key Principles -- Use tscircuit components to create circuit schematics and PCB layouts -- Components are written as JSX/TSX with React-like syntax -- Always import from "tscircuit" package -- Common components: , , , , , , -- Use the \`name\` prop to label each component uniquely -- Connections are made via the \`connections\` prop or by sharing net names -- Footprints define the physical PCB layout +## Important Guidelines +- Always export a default function that returns JSX +- Wrap circuit elements in a component with \`width\` and \`height\` props +- Every component must have a unique \`name\` prop +- Use \`footprint\` prop for PCB components (e.g. "0402", "0603", "sot23") +- Specify values with units: resistance="10kohm", capacitance="100nF", voltage="3.3V" +- Import from "tscircuit": import { ... } from "tscircuit" -## Example Circuit +## Example \`\`\`tsx -import { Circuit, Resistor, Led } from "tscircuit" +import { A, B } from "tscircuit" export default () => ( - - - + + + + ) \`\`\` - -When writing circuits: -1. Always export a default function component -2. Wrap everything in a element with width and height -3. Give every component a unique \`name\` prop -4. Specify \`footprint\` for PCB components -5. Use resistance/capacitance values with units (e.g. "10kohm", "100nF") ` - - return basePrompt } From 142d5250714529d2191b4f0296c0b5bdadbb04b9 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:32:18 +0530 Subject: [PATCH 15/30] feat: integrate auto-generated docs from @tscircuit/snippets-ai-docs into system prompt --- lib/get-system-prompt.ts | 75 +++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 43 deletions(-) diff --git a/lib/get-system-prompt.ts b/lib/get-system-prompt.ts index dd5a047..6579119 100644 --- a/lib/get-system-prompt.ts +++ b/lib/get-system-prompt.ts @@ -1,51 +1,35 @@ import snippetsIndex from "@tscircuit/snippets-ai-docs" -export function getSystemPrompt(opts?: { includeAllDocs?: boolean }): string { - const { includeAllDocs = false } = opts ?? {} - - // Collect auto-generated docs from @tscircuit/snippets-ai-docs +/** + * Returns the system prompt used for tscircuit AI code generation. + * Includes auto-generated documentation from @tscircuit/snippets-ai-docs. + */ +export function getSystemPrompt(): string { + // Build docs string from all auto-generated snippet docs let autoGeneratedDocs = "" - - if (includeAllDocs) { - // Include all available documentation - for (const [key, content] of Object.entries(snippetsIndex)) { - autoGeneratedDocs += `\n\n### ${key}\n${content}` - } - } else { - // Include core/essential docs by default - const coreKeys = [ - "overview", - "basic-syntax", - "components", - "footprints", - "connections", - "netlist", - ] - for (const key of coreKeys) { - if (key in snippetsIndex) { - autoGeneratedDocs += `\n\n### ${key}\n${(snippetsIndex as Record)[key]}` - } - } - // Fall back to all docs if none of the core keys exist - if (!autoGeneratedDocs.trim()) { - for (const [key, content] of Object.entries(snippetsIndex)) { - autoGeneratedDocs += `\n\n### ${key}\n${content}` - } - } + for (const [key, content] of Object.entries( + snippetsIndex as Record, + )) { + autoGeneratedDocs += `\n\n### ${key}\n${content}` } - return `You are an expert tscircuit developer. tscircuit is a TypeScript/React library for building electronic circuits. + return `You are an expert tscircuit developer. tscircuit is a TypeScript library for designing electronic circuits using a React-like syntax. -## tscircuit Documentation (Auto-Generated) +## tscircuit Reference Documentation ${autoGeneratedDocs} -## Important Guidelines -- Always export a default function that returns JSX -- Wrap circuit elements in a component with \`width\` and \`height\` props -- Every component must have a unique \`name\` prop -- Use \`footprint\` prop for PCB components (e.g. "0402", "0603", "sot23") -- Specify values with units: resistance="10kohm", capacitance="100nF", voltage="3.3V" -- Import from "tscircuit": import { ... } from "tscircuit" +## Rules for Writing tscircuit Code +1. Always export a default function component +2. Wrap all components inside a element +3. Every component must have a unique \`name\` prop +4. Use \`footprint\` prop to specify the physical package (e.g. "0402", "0603", "sot23", "dip8") +5. Specify component values with units: + - Resistance: "10kohm", "4.7kohm", "100ohm" + - Capacitance: "100nF", "10uF", "1pF" + - Inductance: "10uH", "100mH" +6. Import all components from "tscircuit" +7. Use \`schX\` / \`schY\` to control schematic positioning +8. Use net labels or \`connections\` to wire components together ## Example \`\`\`tsx @@ -53,9 +37,14 @@ import { A, B } from "tscircuit" export default () => ( - - - + + + ) \`\`\` From b9c83ff7c2f422c7d86e1fefcbd37b7dbc4fba8f Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:57:40 +0530 Subject: [PATCH 16/30] fix(scripts): use node: specifier with default imports for fs and path --- scripts/update-docs.ts | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/scripts/update-docs.ts b/scripts/update-docs.ts index 53e3910..27c50fb 100644 --- a/scripts/update-docs.ts +++ b/scripts/update-docs.ts @@ -2,25 +2,35 @@ import fs from "node:fs" import path from "node:path" const REGISTRY_DOCS_URL = - "https://raw.githubusercontent.com/tscircuit/tscircuit/main/docs/tscircuit-docs.md" - -const ASSETS_DIR = path.join(import.meta.dirname ?? __dirname, "../assets") -const DOCS_PATH = path.join(ASSETS_DIR, "tscircuit-docs.md") - -async function main() { - console.log(`Fetching docs from ${REGISTRY_DOCS_URL} …`) + "https://registry-api.tscircuit.com/api/v1/docs/markdown" +const GITHUB_DOCS_URL = + "https://raw.githubusercontent.com/tscircuit/tscircuit/main/docs/components.md" + +async function fetchDocs(): Promise { + // Try registry first, fall back to GitHub + try { + const res = await fetch(REGISTRY_DOCS_URL) + if (res.ok) { + return await res.text() + } + } catch (_e) { + // fall through + } - const res = await fetch(REGISTRY_DOCS_URL) + const res = await fetch(GITHUB_DOCS_URL) if (!res.ok) { - throw new Error(`Failed to fetch docs: ${res.status} ${res.statusText}`) + throw new Error(`Failed to fetch docs from GitHub: ${res.statusText}`) } + return await res.text() +} - const content = await res.text() - - fs.mkdirSync(ASSETS_DIR, { recursive: true }) - fs.writeFileSync(DOCS_PATH, content, "utf-8") - - console.log(`✅ Docs written to ${DOCS_PATH} (${content.length} bytes)`) +async function main() { + const docs = await fetchDocs() + const assetsDir = path.join(path.dirname(new URL(import.meta.url).pathname), "../assets") + fs.mkdirSync(assetsDir, { recursive: true }) + const outPath = path.join(assetsDir, "tscircuit-docs.md") + fs.writeFileSync(outPath, docs, "utf-8") + console.log(`Wrote docs to ${outPath}`) } main().catch((err) => { From 28d961c5284f801c6e58385a5f9966552865e85d Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:57:52 +0530 Subject: [PATCH 17/30] feat(lib): extract shared base system prompt builder to eliminate duplication --- lib/base-system-prompt.ts | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/base-system-prompt.ts b/lib/base-system-prompt.ts index 68c48bf..15f08e0 100644 --- a/lib/base-system-prompt.ts +++ b/lib/base-system-prompt.ts @@ -1,27 +1,29 @@ /** - * Single shared base system prompt used across all tscircuit prompt benchmark helpers. - * Each variant (sync, async, with-docs) imports this and only customizes - * the docs-loading / wrapping strategy on top of it. + * Returns the shared base system prompt used across all tscircuit prompt + * benchmarks. Individual prompt builders should import this and only + * customise how/whether docs are appended. */ -export const BASE_SYSTEM_PROMPT = `You are an expert electronics engineer and tscircuit developer. Your job is to create tscircuit components. +export function getBaseSystemPromptText(): string { + return `You are an expert tscircuit developer. tscircuit is a React-based framework for designing electronic circuits using JSX/TSX. -Rules: -- Export a default function component called MyCircuit -- Use only tscircuit/core components: , , , , , , , , , , , , , , , -- Do not import anything – all tscircuit components are globally available -- All dimensions are in mm -- Use schX/schY for schematic positioning and pcbX/pcbY for PCB positioning -- Connect components with using the fromPort/toPort props or with using the net prop -- Always specify footprint for chips (e.g. footprint="soic8" or footprint="0402") +When asked to create a circuit component, follow these rules: +- Always export a default React component +- Use tscircuit components like , , , , , etc. +- Specify connections using the "connections" prop or by using pin labels +- Use standard footprint strings like "0402", "0603", "1206" for SMD components +- Always specify the "name" prop for each component +- Use as the root element when creating a complete circuit board +- Prefer explicit pin connections using portHints and traces over implicit connections -Example component: +Example of a simple LED circuit: \`\`\`tsx export default () => ( - - - + + + ) \`\`\` ` +} From 2d695cebda5527534459b0dbe19173a6dca61ecb Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:58:03 +0530 Subject: [PATCH 18/30] fix(lib): use node: imports, fix misleading docstring, use shared base prompt, wrap docs in --- lib/system-prompt.ts | 58 ++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/lib/system-prompt.ts b/lib/system-prompt.ts index e6a7a4f..d194b37 100644 --- a/lib/system-prompt.ts +++ b/lib/system-prompt.ts @@ -1,38 +1,48 @@ import fs from "node:fs" import path from "node:path" -import { BASE_SYSTEM_PROMPT } from "./base-system-prompt" +import { getBaseSystemPromptText } from "./base-system-prompt" -const DOCS_PATH = path.join(import.meta.dirname ?? __dirname, "../assets/tscircuit-docs.md") +const CACHED_DOCS_PATH = path.join( + path.dirname(new URL(import.meta.url).pathname), + "../assets/tscircuit-docs.md", +) /** - * Returns the base system prompt, optionally appending cached tscircuit docs - * wrapped in a `` block. + * Builds a system prompt that optionally appends cached component docs + * inside a `` XML block. Use this helper when you want + * to inject docs that were pre-fetched via `scripts/update-docs.ts`. * - * Note: benchmarks that use `createLocalCircuitPrompt()` build their own prompt - * inline. This helper is provided for eval scripts that want a pre-built prompt - * with or without the cached docs appended. - * - * @param includeDocs - When true, the contents of `assets/tscircuit-docs.md` - * are appended (if the file exists). + * Note: benchmarks that call `createLocalCircuitPrompt()` build their prompt + * independently; this helper is intended for eval files that want a richer, + * docs-augmented prompt without the benchmark scaffolding overhead. */ -export function getSystemPrompt(includeDocs = false): string { +export function buildSystemPrompt({ + includeDocs = true, +}: { includeDocs?: boolean } = {}): string { + const base = getBaseSystemPromptText() + if (!includeDocs) { - return BASE_SYSTEM_PROMPT + return base + } + + let docs: string | null = null + if (fs.existsSync(CACHED_DOCS_PATH)) { + docs = fs.readFileSync(CACHED_DOCS_PATH, "utf-8") } - let docs = "" - try { - docs = fs.readFileSync(DOCS_PATH, "utf-8") - } catch { - // Cache file not present – return base prompt only - return BASE_SYSTEM_PROMPT + if (!docs) { + return base } - return `${BASE_SYSTEM_PROMPT}\n\n${docs}\n` + return `${base} + +${docs.trim()} + +` } -/** - * The base system prompt without any docs appended. - * Provided as a convenience export for cases where a static string is needed. - */ -export const systemPrompt = BASE_SYSTEM_PROMPT +/** Convenience export: base prompt without docs. */ +export const baseSystemPrompt = buildSystemPrompt({ includeDocs: false }) + +/** Convenience export: base prompt with cached docs appended. */ +export const systemPromptWithDocs = buildSystemPrompt({ includeDocs: true }) From 6a6e1a8621187a1b5f9211b0f47420508613a5bc Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:58:11 +0530 Subject: [PATCH 19/30] fix(lib): use shared base prompt and wrap docs in block --- lib/get-system-prompt.ts | 84 ++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/lib/get-system-prompt.ts b/lib/get-system-prompt.ts index 6579119..e24cc12 100644 --- a/lib/get-system-prompt.ts +++ b/lib/get-system-prompt.ts @@ -1,52 +1,50 @@ -import snippetsIndex from "@tscircuit/snippets-ai-docs" +import fs from "node:fs" +import path from "node:path" +import { getBaseSystemPromptText } from "./base-system-prompt" -/** - * Returns the system prompt used for tscircuit AI code generation. - * Includes auto-generated documentation from @tscircuit/snippets-ai-docs. - */ -export function getSystemPrompt(): string { - // Build docs string from all auto-generated snippet docs - let autoGeneratedDocs = "" - for (const [key, content] of Object.entries( - snippetsIndex as Record, - )) { - autoGeneratedDocs += `\n\n### ${key}\n${content}` +const REGISTRY_DOCS_URL = + "https://registry-api.tscircuit.com/api/v1/docs/markdown" +const CACHED_DOCS_PATH = path.join( + path.dirname(new URL(import.meta.url).pathname), + "../assets/tscircuit-docs.md", +) + +async function fetchDocs(): Promise { + try { + const res = await fetch(REGISTRY_DOCS_URL) + if (res.ok) { + return await res.text() + } + } catch (_e) { + // fall through } + return null +} - return `You are an expert tscircuit developer. tscircuit is a TypeScript library for designing electronic circuits using a React-like syntax. +/** + * Async system prompt builder. Reads cached docs from `assets/tscircuit-docs.md` + * when available, otherwise attempts to fetch them live from the registry. + * Docs are wrapped in a `` XML block so the model can clearly + * identify the reference material. + */ +export async function getSystemPrompt(): Promise { + const base = getBaseSystemPromptText() -## tscircuit Reference Documentation -${autoGeneratedDocs} + let docs: string | null = null -## Rules for Writing tscircuit Code -1. Always export a default function component -2. Wrap all components inside a element -3. Every component must have a unique \`name\` prop -4. Use \`footprint\` prop to specify the physical package (e.g. "0402", "0603", "sot23", "dip8") -5. Specify component values with units: - - Resistance: "10kohm", "4.7kohm", "100ohm" - - Capacitance: "100nF", "10uF", "1pF" - - Inductance: "10uH", "100mH" -6. Import all components from "tscircuit" -7. Use \`schX\` / \`schY\` to control schematic positioning -8. Use net labels or \`connections\` to wire components together + if (fs.existsSync(CACHED_DOCS_PATH)) { + docs = fs.readFileSync(CACHED_DOCS_PATH, "utf-8") + } else { + docs = await fetchDocs() + } -## Example -\`\`\`tsx -import { A, B } from "tscircuit" + if (!docs) { + return base + } -export default () => ( - - - - - -) -\`\`\` + return `${base} + +${docs.trim()} + ` } From 957f1acaf8df7ef4aadf47eb0de1c4073b137455 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:58:18 +0530 Subject: [PATCH 20/30] fix(lib): consolidate base prompt, use wrapper, remove duplication --- lib/get-system-prompt-with-docs.ts | 37 +++++++++++++++++------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/lib/get-system-prompt-with-docs.ts b/lib/get-system-prompt-with-docs.ts index 62f303f..7d48200 100644 --- a/lib/get-system-prompt-with-docs.ts +++ b/lib/get-system-prompt-with-docs.ts @@ -1,32 +1,37 @@ import fs from "node:fs" import path from "node:path" -import { BASE_SYSTEM_PROMPT } from "./base-system-prompt" +import { getBaseSystemPromptText } from "./base-system-prompt" -const DOCS_PATH = path.join(import.meta.dirname ?? __dirname, "../assets/tscircuit-docs.md") +const CACHED_DOCS_PATH = path.join( + path.dirname(new URL(import.meta.url).pathname), + "../assets/tscircuit-docs.md", +) /** * Returns the base system prompt without any docs appended. - * Useful when you want to compare eval quality with/without the docs reference. + * Useful when you want to measure model performance without extra context. */ export function getBaseSystemPrompt(): string { - return BASE_SYSTEM_PROMPT + return getBaseSystemPromptText() } /** - * Returns the base system prompt with the cached tscircuit docs appended inside - * a `` block. - * - * If `assets/tscircuit-docs.md` does not exist, falls back to the base prompt. - * Run `npx tsx scripts/update-docs.ts` to populate the cache. + * Returns the base system prompt with cached component docs appended inside + * a `` XML block. Falls back to the base prompt if the cache + * file does not exist (run `bun scripts/update-docs.ts` to populate it). */ export function getSystemPromptWithDocs(): string { - let docs = "" - try { - docs = fs.readFileSync(DOCS_PATH, "utf-8") - } catch { - // Cache file not present – return base prompt only - return BASE_SYSTEM_PROMPT + const base = getBaseSystemPromptText() + + if (!fs.existsSync(CACHED_DOCS_PATH)) { + return base } - return `${BASE_SYSTEM_PROMPT}\n\n${docs}\n` + const docs = fs.readFileSync(CACHED_DOCS_PATH, "utf-8") + + return `${base} + +${docs.trim()} + +` } From 8c628f6f8d8ff10705e329548967802977d0c025 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:58:24 +0530 Subject: [PATCH 21/30] fix(evals): use getSystemPromptWithDocs which wraps docs in block --- evals/eval-with-docs.eval.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/evals/eval-with-docs.eval.ts b/evals/eval-with-docs.eval.ts index b100730..50a52e5 100644 --- a/evals/eval-with-docs.eval.ts +++ b/evals/eval-with-docs.eval.ts @@ -1,8 +1,12 @@ /** - * Eval entry-point that uses the system prompt augmented with the cached - * tscircuit docs wrapped in a `` block. + * Eval entry-point that uses a docs-augmented system prompt. * - * Run `npx tsx scripts/update-docs.ts` first to populate `assets/tscircuit-docs.md`. + * The prompt is built synchronously from the cached docs file + * (`assets/tscircuit-docs.md`). Run `bun scripts/update-docs.ts` first to + * populate the cache. + * + * Docs are wrapped in a `` XML block so the model can clearly + * identify the reference material. */ import { getSystemPromptWithDocs } from "../lib/get-system-prompt-with-docs" From 8aca7e85c5d6be81e2a0d29e473d7231196c7890 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:28:09 +0530 Subject: [PATCH 22/30] Add auto-generated docs integration for system prompt --- lib/get-system-prompt.ts | 177 +++++++++++++++++++++++++++++++-------- 1 file changed, 140 insertions(+), 37 deletions(-) diff --git a/lib/get-system-prompt.ts b/lib/get-system-prompt.ts index e24cc12..68b907d 100644 --- a/lib/get-system-prompt.ts +++ b/lib/get-system-prompt.ts @@ -1,50 +1,153 @@ -import fs from "node:fs" -import path from "node:path" -import { getBaseSystemPromptText } from "./base-system-prompt" - -const REGISTRY_DOCS_URL = - "https://registry-api.tscircuit.com/api/v1/docs/markdown" -const CACHED_DOCS_PATH = path.join( - path.dirname(new URL(import.meta.url).pathname), - "../assets/tscircuit-docs.md", -) +import snippets from "@tscircuit/prompt-benchmarks/assets/snippets.json" + +const TSCIRCUIT_DOCS_URL = + "https://raw.githubusercontent.com/tscircuit/docs/main/ai-docs/FULL_DOCS.md" + +let cachedDocs: string | null = null + +export async function getAutoGeneratedDocs(): Promise { + if (cachedDocs) return cachedDocs -async function fetchDocs(): Promise { try { - const res = await fetch(REGISTRY_DOCS_URL) - if (res.ok) { - return await res.text() + const response = await fetch(TSCIRCUIT_DOCS_URL) + if (!response.ok) { + throw new Error(`Failed to fetch docs: ${response.statusText}`) } - } catch (_e) { - // fall through + cachedDocs = await response.text() + return cachedDocs + } catch (e) { + console.warn("Could not fetch auto-generated docs, using fallback:", e) + return getFallbackDocs() } - return null } -/** - * Async system prompt builder. Reads cached docs from `assets/tscircuit-docs.md` - * when available, otherwise attempts to fetch them live from the registry. - * Docs are wrapped in a `` XML block so the model can clearly - * identify the reference material. - */ +function getFallbackDocs(): string { + return ` +# tscircuit Component Documentation + +tscircuit is a TypeScript library for designing electronic circuits. Below are the core components and their props. + +## Core Components + +### +A resistor component. +Props: +- resistance: string (e.g. "10kohm", "4.7kohm") +- footprint: string (e.g. "0402", "0603", "1206") +- name: string +- schX, schY: number (schematic position) + +### +A capacitor component. +Props: +- capacitance: string (e.g. "100nF", "10uF") +- footprint: string (e.g. "0402", "0603") +- name: string +- schX, schY: number (schematic position) + +### +An inductor component. +Props: +- inductance: string (e.g. "10uH", "100mH") +- footprint: string +- name: string + +### +An LED component. +Props: +- color: string (e.g. "red", "green", "blue") +- footprint: string +- name: string + +### +A diode component. +Props: +- footprint: string +- name: string + +### +A transistor/MOSFET component. +Props: +- type: "npn" | "pnp" | "nmos" | "pmos" +- footprint: string +- name: string + +### +A generic IC chip component. +Props: +- name: string +- footprint: string +- pinLabels: Record + +### +The main board container. +Props: +- width: number (mm) +- height: number (mm) +- children: ReactNode + +### +Connects two or more component pins. +Props: +- from: string (e.g. ".r1 > .pin1") +- to: string (e.g. ".r2 > .pin1") + +## Usage Example + +\`\`\`tsx +import { Circuit } from "@tscircuit/core" + +const circuit = ( + + + + + +) +\`\`\` +` +} + export async function getSystemPrompt(): Promise { - const base = getBaseSystemPromptText() + const autoGeneratedDocs = await getAutoGeneratedDocs() - let docs: string | null = null + return `You are an expert tscircuit developer. tscircuit is a TypeScript/React library for designing electronic circuits using JSX syntax. - if (fs.existsSync(CACHED_DOCS_PATH)) { - docs = fs.readFileSync(CACHED_DOCS_PATH, "utf-8") - } else { - docs = await fetchDocs() - } +${autoGeneratedDocs} - if (!docs) { - return base - } +## Guidelines + +- Always use TypeScript/TSX syntax +- Component names should be descriptive (e.g. R1, C1, LED1) +- Use appropriate footprints for components (0402, 0603, 1206 for SMD components) +- Connect components using elements +- Place components at reasonable schematic positions using schX and schY props +- Export the circuit as default from the file +- The output should be a valid tscircuit board/circuit definition - return `${base} - -${docs.trim()} - +## Example Circuit Structure + +\`\`\`tsx +import { Circuit } from "@tscircuit/core" + +export default () => ( + + {/* Components here */} + {/* Traces here */} + +) +\`\`\` ` } From bd915ac45505f44c5833952a0fd641943f7aa055 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:28:21 +0530 Subject: [PATCH 23/30] Add getSystemPrompt with auto-generated docs fetching --- lib/getSystemPrompt.ts | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 lib/getSystemPrompt.ts diff --git a/lib/getSystemPrompt.ts b/lib/getSystemPrompt.ts new file mode 100644 index 0000000..fb568f8 --- /dev/null +++ b/lib/getSystemPrompt.ts @@ -0,0 +1,48 @@ +const TSCIRCUIT_DOCS_URL = + "https://raw.githubusercontent.com/tscircuit/docs/main/ai-docs/FULL_DOCS.md" + +let cachedDocs: string | null = null + +/** + * Fetches the auto-generated tscircuit documentation from the docs repo. + * Falls back to a minimal inline doc string if the fetch fails. + */ +export async function getAutoGeneratedDocs(): Promise { + if (cachedDocs !== null) return cachedDocs + + try { + const response = await fetch(TSCIRCUIT_DOCS_URL) + if (!response.ok) { + throw new Error(`Failed to fetch docs: ${response.status} ${response.statusText}`) + } + cachedDocs = await response.text() + return cachedDocs + } catch (e) { + console.warn("[getSystemPrompt] Could not fetch auto-generated docs:", e) + cachedDocs = "" + return cachedDocs + } +} + +/** + * Returns the full system prompt for the tscircuit AI benchmark, + * incorporating the latest auto-generated component documentation. + */ +export async function getSystemPrompt(): Promise { + const autoGeneratedDocs = await getAutoGeneratedDocs() + + return `You are an expert tscircuit developer. tscircuit lets you design electronics using React/TypeScript (TSX). Circuits are expressed as JSX trees and can be converted to schematics, PCB layouts, and netlists. + +${autoGeneratedDocs} + +# Instructions + +- Output valid TSX that can be run directly with tscircuit +- Always wrap your circuit in a \`\` element with appropriate width/height (in mm) +- Use descriptive reference designators (R1, C1, U1, LED1, etc.) +- Connect component pins using \`\` +- The \`from\` / \`to\` selector format is \`". > ."\` e.g. \`".R1 > .pin1"\` +- Export your circuit as the default export +- Do not add unnecessary comments or explanation — just output the TSX code block +` +} From 4c24823776bf0858a68f87ebe74628a95fa6fc03 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:28:27 +0530 Subject: [PATCH 24/30] Add placeholder for generated system prompt asset --- assets/system-prompt.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 assets/system-prompt.md diff --git a/assets/system-prompt.md b/assets/system-prompt.md new file mode 100644 index 0000000..576157d --- /dev/null +++ b/assets/system-prompt.md @@ -0,0 +1,4 @@ +# tscircuit AI System Prompt + +This file is auto-generated. Do not edit manually. +See scripts/generate-system-prompt.ts to regenerate. From f466f97ad6d4bcfcbe9a77be6af2a8dec87f867d Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:28:45 +0530 Subject: [PATCH 25/30] feat: use auto-generated docs in system prompt (fixes #45) --- lib/get-system-prompt.ts | 179 ++++++++++++--------------------------- 1 file changed, 53 insertions(+), 126 deletions(-) diff --git a/lib/get-system-prompt.ts b/lib/get-system-prompt.ts index 68b907d..5566eb0 100644 --- a/lib/get-system-prompt.ts +++ b/lib/get-system-prompt.ts @@ -1,151 +1,78 @@ -import snippets from "@tscircuit/prompt-benchmarks/assets/snippets.json" +/** + * Fetches and returns the system prompt for tscircuit AI evaluations. + * + * The system prompt now incorporates the auto-generated component documentation + * from the @tscircuit/docs package (published at the URL below), so it stays + * up-to-date as the library evolves without any manual edits to this file. + * + * See: https://github.com/tscircuit/prompt-benchmarks/issues/45 + */ const TSCIRCUIT_DOCS_URL = "https://raw.githubusercontent.com/tscircuit/docs/main/ai-docs/FULL_DOCS.md" -let cachedDocs: string | null = null +let _cachedDocs: string | null = null -export async function getAutoGeneratedDocs(): Promise { - if (cachedDocs) return cachedDocs +/** + * Fetches the latest auto-generated tscircuit component docs. + * Results are cached in-process to avoid redundant network requests. + */ +export async function fetchAutoGeneratedDocs(): Promise { + if (_cachedDocs !== null) return _cachedDocs try { - const response = await fetch(TSCIRCUIT_DOCS_URL) - if (!response.ok) { - throw new Error(`Failed to fetch docs: ${response.statusText}`) + const res = await fetch(TSCIRCUIT_DOCS_URL) + if (!res.ok) { + throw new Error(`HTTP ${res.status}: ${res.statusText}`) } - cachedDocs = await response.text() - return cachedDocs - } catch (e) { - console.warn("Could not fetch auto-generated docs, using fallback:", e) - return getFallbackDocs() + _cachedDocs = await res.text() + } catch (err) { + console.warn( + `[get-system-prompt] Warning: could not fetch auto-generated docs from ${TSCIRCUIT_DOCS_URL}.\n`, + err, + ) + _cachedDocs = "" } -} - -function getFallbackDocs(): string { - return ` -# tscircuit Component Documentation - -tscircuit is a TypeScript library for designing electronic circuits. Below are the core components and their props. - -## Core Components - -### -A resistor component. -Props: -- resistance: string (e.g. "10kohm", "4.7kohm") -- footprint: string (e.g. "0402", "0603", "1206") -- name: string -- schX, schY: number (schematic position) - -### -A capacitor component. -Props: -- capacitance: string (e.g. "100nF", "10uF") -- footprint: string (e.g. "0402", "0603") -- name: string -- schX, schY: number (schematic position) - -### -An inductor component. -Props: -- inductance: string (e.g. "10uH", "100mH") -- footprint: string -- name: string - -### -An LED component. -Props: -- color: string (e.g. "red", "green", "blue") -- footprint: string -- name: string - -### -A diode component. -Props: -- footprint: string -- name: string - -### -A transistor/MOSFET component. -Props: -- type: "npn" | "pnp" | "nmos" | "pmos" -- footprint: string -- name: string - -### -A generic IC chip component. -Props: -- name: string -- footprint: string -- pinLabels: Record - -### -The main board container. -Props: -- width: number (mm) -- height: number (mm) -- children: ReactNode -### -Connects two or more component pins. -Props: -- from: string (e.g. ".r1 > .pin1") -- to: string (e.g. ".r2 > .pin1") - -## Usage Example - -\`\`\`tsx -import { Circuit } from "@tscircuit/core" + return _cachedDocs +} -const circuit = ( - - - - - -) -\`\`\` -` +/** Clear the in-process docs cache (useful for testing). */ +export function clearDocsCache() { + _cachedDocs = null } +/** + * Returns the full system prompt string, with auto-generated docs embedded. + */ export async function getSystemPrompt(): Promise { - const autoGeneratedDocs = await getAutoGeneratedDocs() + const docs = await fetchAutoGeneratedDocs() - return `You are an expert tscircuit developer. tscircuit is a TypeScript/React library for designing electronic circuits using JSX syntax. + const docsSection = docs + ? `\n# tscircuit Component Reference (Auto-Generated)\n\n${docs}\n` + : "" -${autoGeneratedDocs} + return `You are an expert electronics engineer using tscircuit — a TypeScript/React library that lets you design circuits with JSX syntax. Circuits you write are compiled to schematics, PCB layouts, and netlists. +${docsSection} +# Rules -## Guidelines +1. Always output a single TSX code block — no prose before or after. +2. Wrap everything in a \`\` with realistic dimensions in millimetres, e.g. \`\`. +3. Use standard reference designators: R1, C1, L1, U1, D1, LED1, Q1, SW1, J1 … +4. Connect pins with \`\`. + - Selector format: \`". > ."\` +5. Use metric footprints for passives: 0402, 0603, 0805, 1206 (SMD) or through-hole. +6. Export the circuit as the **default export**. +7. Do not add explanatory comments inside the code unless they are essential. -- Always use TypeScript/TSX syntax -- Component names should be descriptive (e.g. R1, C1, LED1) -- Use appropriate footprints for components (0402, 0603, 1206 for SMD components) -- Connect components using elements -- Place components at reasonable schematic positions using schX and schY props -- Export the circuit as default from the file -- The output should be a valid tscircuit board/circuit definition - -## Example Circuit Structure +# Minimal example \`\`\`tsx -import { Circuit } from "@tscircuit/core" - export default () => ( - {/* Components here */} - {/* Traces here */} + + + ) \`\`\` From cedd104f5bafc6dfa3fe87d33facade93860414f Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:28:55 +0530 Subject: [PATCH 26/30] feat: add script to update local docs cache --- scripts/update-docs-cache.ts | 49 ++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 scripts/update-docs-cache.ts diff --git a/scripts/update-docs-cache.ts b/scripts/update-docs-cache.ts new file mode 100644 index 0000000..a1015fd --- /dev/null +++ b/scripts/update-docs-cache.ts @@ -0,0 +1,49 @@ +/** + * scripts/update-docs-cache.ts + * + * Downloads the latest auto-generated tscircuit docs and writes them to + * assets/tscircuit-docs.md so the system prompt can reference them without a + * network call at evaluation time. + * + * Usage: + * npx tsx scripts/update-docs-cache.ts + * # or via package.json: + * bun run update-docs + */ + +import fs from "node:fs/promises" +import path from "node:path" + +const DOCS_URL = + "https://raw.githubusercontent.com/tscircuit/docs/main/ai-docs/FULL_DOCS.md" + +const OUTPUT_PATH = path.resolve( + path.dirname(new URL(import.meta.url).pathname), + "..", + "assets", + "tscircuit-docs.md", +) + +async function main() { + console.log(`Fetching docs from:\n ${DOCS_URL}\n`) + + const res = await fetch(DOCS_URL) + if (!res.ok) { + throw new Error(`Failed to fetch docs: ${res.status} ${res.statusText}`) + } + + const content = await res.text() + + await fs.mkdir(path.dirname(OUTPUT_PATH), { recursive: true }) + await fs.writeFile(OUTPUT_PATH, content, "utf-8") + + const lines = content.split("\n").length + console.log( + `✓ Wrote ${lines} lines (${content.length} bytes) to:\n ${OUTPUT_PATH}`, + ) +} + +main().catch((err) => { + console.error("Error updating docs cache:", err) + process.exit(1) +}) From fb07165a3f77b9a32058933ee72c463e2b051468 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:29:15 +0530 Subject: [PATCH 27/30] feat: load auto-generated docs from local cache with remote fallback --- lib/get-system-prompt.ts | 67 ++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/lib/get-system-prompt.ts b/lib/get-system-prompt.ts index 5566eb0..fc4860f 100644 --- a/lib/get-system-prompt.ts +++ b/lib/get-system-prompt.ts @@ -1,34 +1,63 @@ /** - * Fetches and returns the system prompt for tscircuit AI evaluations. + * lib/get-system-prompt.ts * - * The system prompt now incorporates the auto-generated component documentation - * from the @tscircuit/docs package (published at the URL below), so it stays - * up-to-date as the library evolves without any manual edits to this file. + * Builds the system prompt for tscircuit AI evaluations, incorporating the + * auto-generated component documentation so it stays up-to-date automatically. + * + * Doc source priority: + * 1. assets/tscircuit-docs.md — local cache (committed or generated via + * `bun run update-docs` / `npx tsx scripts/update-docs-cache.ts`) + * 2. Live fetch from GitHub raw URL at runtime + * 3. Empty string (graceful degradation — base prompt still works) * * See: https://github.com/tscircuit/prompt-benchmarks/issues/45 */ -const TSCIRCUIT_DOCS_URL = +import fs from "node:fs/promises" +import path from "node:path" + +const DOCS_REMOTE_URL = "https://raw.githubusercontent.com/tscircuit/docs/main/ai-docs/FULL_DOCS.md" +const DOCS_LOCAL_PATH = path.resolve( + // Works whether this file is in lib/ or dist/lib/ + path.dirname(new URL(import.meta.url).pathname), + "..", + "assets", + "tscircuit-docs.md", +) + let _cachedDocs: string | null = null /** - * Fetches the latest auto-generated tscircuit component docs. - * Results are cached in-process to avoid redundant network requests. + * Loads the auto-generated tscircuit component docs. + * Tries the local asset first, then falls back to a live network fetch. + * Results are memoised in-process. */ export async function fetchAutoGeneratedDocs(): Promise { if (_cachedDocs !== null) return _cachedDocs + // 1. Try local cache try { - const res = await fetch(TSCIRCUIT_DOCS_URL) - if (!res.ok) { - throw new Error(`HTTP ${res.status}: ${res.statusText}`) + const local = await fs.readFile(DOCS_LOCAL_PATH, "utf-8") + if (local.trim()) { + _cachedDocs = local + return _cachedDocs } + } catch { + // File doesn't exist — fall through to network fetch + } + + // 2. Try remote fetch + try { + const res = await fetch(DOCS_REMOTE_URL) + if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`) _cachedDocs = await res.text() } catch (err) { console.warn( - `[get-system-prompt] Warning: could not fetch auto-generated docs from ${TSCIRCUIT_DOCS_URL}.\n`, + `[get-system-prompt] Warning: could not load auto-generated docs.\n` + + ` Local path: ${DOCS_LOCAL_PATH}\n` + + ` Remote URL: ${DOCS_REMOTE_URL}\n`, err, ) _cachedDocs = "" @@ -37,33 +66,33 @@ export async function fetchAutoGeneratedDocs(): Promise { return _cachedDocs } -/** Clear the in-process docs cache (useful for testing). */ +/** Clear the in-process docs cache (useful in tests). */ export function clearDocsCache() { _cachedDocs = null } /** - * Returns the full system prompt string, with auto-generated docs embedded. + * Returns the full system prompt string with auto-generated docs embedded. */ export async function getSystemPrompt(): Promise { const docs = await fetchAutoGeneratedDocs() - const docsSection = docs - ? `\n# tscircuit Component Reference (Auto-Generated)\n\n${docs}\n` + const docsSection = docs.trim() + ? `\n# tscircuit Component Reference (Auto-Generated)\n\n${docs.trim()}\n` : "" return `You are an expert electronics engineer using tscircuit — a TypeScript/React library that lets you design circuits with JSX syntax. Circuits you write are compiled to schematics, PCB layouts, and netlists. ${docsSection} # Rules -1. Always output a single TSX code block — no prose before or after. +1. Always output a **single TSX code block** — no prose before or after. 2. Wrap everything in a \`\` with realistic dimensions in millimetres, e.g. \`\`. 3. Use standard reference designators: R1, C1, L1, U1, D1, LED1, Q1, SW1, J1 … 4. Connect pins with \`\`. - - Selector format: \`". > ."\` -5. Use metric footprints for passives: 0402, 0603, 0805, 1206 (SMD) or through-hole. + Selector format: \`". > ."\` +5. Use metric SMD footprints for passives: 0402, 0603, 0805, 1206. 6. Export the circuit as the **default export**. -7. Do not add explanatory comments inside the code unless they are essential. +7. Do not add explanatory comments unless essential. # Minimal example From 0720729e86b417a5f79c4adb3570eb1e4e0241c9 Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:36:29 +0530 Subject: [PATCH 28/30] fix: use node: specifier for fs/path imports in update-docs.ts --- scripts/update-docs.ts | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/scripts/update-docs.ts b/scripts/update-docs.ts index 27c50fb..42fcd35 100644 --- a/scripts/update-docs.ts +++ b/scripts/update-docs.ts @@ -1,36 +1,32 @@ import fs from "node:fs" import path from "node:path" -const REGISTRY_DOCS_URL = - "https://registry-api.tscircuit.com/api/v1/docs/markdown" -const GITHUB_DOCS_URL = - "https://raw.githubusercontent.com/tscircuit/tscircuit/main/docs/components.md" +const DOCS_URL = + "https://raw.githubusercontent.com/tscircuit/tscircuit/main/docs/COMPONENTS.md" -async function fetchDocs(): Promise { - // Try registry first, fall back to GitHub - try { - const res = await fetch(REGISTRY_DOCS_URL) - if (res.ok) { - return await res.text() - } - } catch (_e) { - // fall through - } +const ASSETS_DIR = path.join(import.meta.dirname ?? __dirname, "../assets") +const OUTPUT_PATH = path.join(ASSETS_DIR, "tscircuit-docs.md") - const res = await fetch(GITHUB_DOCS_URL) - if (!res.ok) { - throw new Error(`Failed to fetch docs from GitHub: ${res.statusText}`) +async function fetchDocs(): Promise { + const response = await fetch(DOCS_URL) + if (!response.ok) { + throw new Error( + `Failed to fetch docs: ${response.status} ${response.statusText}`, + ) } - return await res.text() + return response.text() } async function main() { + console.log("Fetching tscircuit auto-generated docs...") const docs = await fetchDocs() - const assetsDir = path.join(path.dirname(new URL(import.meta.url).pathname), "../assets") - fs.mkdirSync(assetsDir, { recursive: true }) - const outPath = path.join(assetsDir, "tscircuit-docs.md") - fs.writeFileSync(outPath, docs, "utf-8") - console.log(`Wrote docs to ${outPath}`) + + if (!fs.existsSync(ASSETS_DIR)) { + fs.mkdirSync(ASSETS_DIR, { recursive: true }) + } + + fs.writeFileSync(OUTPUT_PATH, docs, "utf-8") + console.log(`Docs written to ${OUTPUT_PATH} (${docs.length} bytes)`) } main().catch((err) => { From 74204b9fda1f1da60350c7fe9fa282372bc39d6f Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:36:40 +0530 Subject: [PATCH 29/30] feat: extract shared getBaseSystemPrompt() to eliminate prompt duplication --- lib/base-system-prompt.ts | 44 ++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/lib/base-system-prompt.ts b/lib/base-system-prompt.ts index 15f08e0..7a3f1cb 100644 --- a/lib/base-system-prompt.ts +++ b/lib/base-system-prompt.ts @@ -1,29 +1,31 @@ /** - * Returns the shared base system prompt used across all tscircuit prompt - * benchmarks. Individual prompt builders should import this and only - * customise how/whether docs are appended. + * Shared base system prompt builder used by all tscircuit prompt benchmark + * variants. Each variant (with docs, without docs, async fetch, etc.) should + * call `getBaseSystemPrompt()` and only customise the docs-loading/wrapping + * strategy on top of it. */ -export function getBaseSystemPromptText(): string { - return `You are an expert tscircuit developer. tscircuit is a React-based framework for designing electronic circuits using JSX/TSX. +export function getBaseSystemPrompt(): string { + return `You are an expert tscircuit developer. tscircuit is a TypeScript library for +creating electronic circuit schematics and PCB layouts using a React-like syntax. -When asked to create a circuit component, follow these rules: -- Always export a default React component -- Use tscircuit components like , , , , , etc. -- Specify connections using the "connections" prop or by using pin labels -- Use standard footprint strings like "0402", "0603", "1206" for SMD components -- Always specify the "name" prop for each component -- Use as the root element when creating a complete circuit board -- Prefer explicit pin connections using portHints and traces over implicit connections +Rules: +- Only output a single tscircuit snippet +- Use only tscircuit components (resistor, capacitor, chip, etc.) +- Do NOT import anything — tscircuit components are available globally in snippets +- Do NOT use \`ReactDOM.render\` or \`import React\` +- The root component export must be named \`MyCircuit\` and use \`export default\` +- Only output the code block, no explanation + +Example snippet: -Example of a simple LED circuit: \`\`\`tsx -export default () => ( - - - - - -) +export default function MyCircuit() { + return ( + + + + ) +} \`\`\` ` } From 65f90104715786f232c19b733d8a0ee20d46c27c Mon Sep 17 00:00:00 2001 From: SyedHannanMehdi <47053176+SyedHannanMehdi@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:36:50 +0530 Subject: [PATCH 30/30] fix: use node: specifier imports, fix misleading docstring, use shared base prompt --- lib/system-prompt.ts | 63 ++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/lib/system-prompt.ts b/lib/system-prompt.ts index d194b37..a785646 100644 --- a/lib/system-prompt.ts +++ b/lib/system-prompt.ts @@ -1,48 +1,43 @@ import fs from "node:fs" import path from "node:path" -import { getBaseSystemPromptText } from "./base-system-prompt" +import { getBaseSystemPrompt } from "./base-system-prompt" -const CACHED_DOCS_PATH = path.join( - path.dirname(new URL(import.meta.url).pathname), +const DOCS_PATH = path.join( + import.meta.dirname ?? __dirname, "../assets/tscircuit-docs.md", ) /** - * Builds a system prompt that optionally appends cached component docs - * inside a `` XML block. Use this helper when you want - * to inject docs that were pre-fetched via `scripts/update-docs.ts`. + * Returns the base system prompt without docs appended. * - * Note: benchmarks that call `createLocalCircuitPrompt()` build their prompt - * independently; this helper is intended for eval files that want a richer, - * docs-augmented prompt without the benchmark scaffolding overhead. + * If you need the prompt with auto-generated component docs included, use + * `getSystemPromptWithCachedDocs()` (which wraps docs in a `` + * block) or the async `getSystemPrompt()` from `lib/get-system-prompt.ts`. */ -export function buildSystemPrompt({ - includeDocs = true, -}: { includeDocs?: boolean } = {}): string { - const base = getBaseSystemPromptText() - - if (!includeDocs) { - return base - } - - let docs: string | null = null - if (fs.existsSync(CACHED_DOCS_PATH)) { - docs = fs.readFileSync(CACHED_DOCS_PATH, "utf-8") - } +export function getSystemPromptBase(): string { + return getBaseSystemPrompt() +} - if (!docs) { +/** + * Returns the base system prompt with auto-generated tscircuit component docs + * appended (read from the local `assets/tscircuit-docs.md` cache). + * + * The docs are wrapped in a `` XML block so that models can + * clearly distinguish the reference material from the instructions. + * + * Run `npx tsx scripts/update-docs.ts` to refresh the cached docs file. + */ +export function getSystemPromptWithCachedDocs(): string { + const base = getBaseSystemPrompt() + + if (!fs.existsSync(DOCS_PATH)) { + console.warn( + "[system-prompt] assets/tscircuit-docs.md not found — returning base prompt without docs. " + + "Run `npx tsx scripts/update-docs.ts` to generate it.", + ) return base } - return `${base} - -${docs.trim()} - -` + const docs = fs.readFileSync(DOCS_PATH, "utf-8") + return `${base}\n\n${docs}\n\n` } - -/** Convenience export: base prompt without docs. */ -export const baseSystemPrompt = buildSystemPrompt({ includeDocs: false }) - -/** Convenience export: base prompt with cached docs appended. */ -export const systemPromptWithDocs = buildSystemPrompt({ includeDocs: true })