Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
782e715
feat: add get-system-prompt utility that incorporates auto-generated …
SyedHannanMehdi Mar 29, 2026
dec6b9d
feat: add script to fetch and cache auto-generated tscircuit docs
SyedHannanMehdi Mar 29, 2026
0176828
feat: add getSystemPromptWithDocs that merges base prompt with auto-g…
SyedHannanMehdi Mar 29, 2026
2e1adde
feat: expose systemPrompt with docs for use in eval files
SyedHannanMehdi Mar 29, 2026
2bf336d
feat: update system-prompt to include auto-generated tscircuit docs
SyedHannanMehdi Mar 29, 2026
f8b3dc1
chore: ensure assets directory is tracked by git
SyedHannanMehdi Mar 29, 2026
e063baf
refactor: extract shared BASE_SYSTEM_PROMPT to eliminate duplication …
SyedHannanMehdi Mar 29, 2026
66678c2
fix: use node: specifier for built-in imports; clarify docstring; use…
SyedHannanMehdi Mar 29, 2026
88aaca7
fix: use node: specifier, shared BASE_SYSTEM_PROMPT, consistent <tsci…
SyedHannanMehdi Mar 29, 2026
bf7bd8f
fix: use node: specifier, shared BASE_SYSTEM_PROMPT, consistent <tsci…
SyedHannanMehdi Mar 29, 2026
85c9baa
fix: use node: specifier with default imports for fs and path (align …
SyedHannanMehdi Mar 29, 2026
6f6aa54
fix: use getSystemPromptWithDocs() so eval output is wrapped in <tsci…
SyedHannanMehdi Mar 29, 2026
bb6210a
feat: add getSystemPrompt with auto-generated docs integration
SyedHannanMehdi Mar 29, 2026
7896fea
feat: use @tscircuit/snippets-ai-docs in system prompt
SyedHannanMehdi Mar 29, 2026
142d525
feat: integrate auto-generated docs from @tscircuit/snippets-ai-docs …
SyedHannanMehdi Mar 29, 2026
b9c83ff
fix(scripts): use node: specifier with default imports for fs and path
SyedHannanMehdi Mar 29, 2026
28d961c
feat(lib): extract shared base system prompt builder to eliminate dup…
SyedHannanMehdi Mar 29, 2026
2d695ce
fix(lib): use node: imports, fix misleading docstring, use shared bas…
SyedHannanMehdi Mar 29, 2026
6a6e1a8
fix(lib): use shared base prompt and wrap docs in <tscircuit_docs> block
SyedHannanMehdi Mar 29, 2026
957f1ac
fix(lib): consolidate base prompt, use <tscircuit_docs> wrapper, remo…
SyedHannanMehdi Mar 29, 2026
8c628f6
fix(evals): use getSystemPromptWithDocs which wraps docs in <tscircui…
SyedHannanMehdi Mar 29, 2026
8aca7e8
Add auto-generated docs integration for system prompt
SyedHannanMehdi Mar 30, 2026
bd915ac
Add getSystemPrompt with auto-generated docs fetching
SyedHannanMehdi Mar 30, 2026
4c24823
Add placeholder for generated system prompt asset
SyedHannanMehdi Mar 30, 2026
f466f97
feat: use auto-generated docs in system prompt (fixes #45)
SyedHannanMehdi Mar 30, 2026
cedd104
feat: add script to update local docs cache
SyedHannanMehdi Mar 30, 2026
fb07165
feat: load auto-generated docs from local cache with remote fallback
SyedHannanMehdi Mar 30, 2026
0720729
fix: use node: specifier for fs/path imports in update-docs.ts
SyedHannanMehdi Mar 30, 2026
74204b9
feat: extract shared getBaseSystemPrompt() to eliminate prompt duplic…
SyedHannanMehdi Mar 30, 2026
65f9010
fix: use node: specifier imports, fix misleading docstring, use share…
SyedHannanMehdi Mar 30, 2026
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
Empty file added assets/.gitkeep
Empty file.
18 changes: 18 additions & 0 deletions evals/eval-with-docs.eval.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { getSystemPromptWithDocs } from "../lib/get-system-prompt-with-docs"

Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description mentions appending cached docs inside a clearly delimited <tscircuit_docs> block, but this eval re-export uses getSystemPromptWithDocs() which appends docs under a markdown heading and does not include the <tscircuit_docs> delimiter. Please align the eval prompt output with the intended wrapper (either change the builder to wrap in <tscircuit_docs> or import the builder that already does so).

Copilot uses AI. Check for mistakes.
/**
* 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()
58 changes: 58 additions & 0 deletions lib/get-system-prompt-with-docs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as fs from "fs"
import * as path from "path"
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repository convention is to import Node built-ins via the node: specifier with default imports (e.g. import fs from "node:fs", import path from "node:path" as in lib/utils/save-prompt.ts:1-2). Please align these imports for consistency.

Suggested change
import * as fs from "fs"
import * as path from "path"
import fs from "node:fs"
import path from "node:path"

Copilot uses AI. Check for mistakes.

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"
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are now multiple hard-coded base prompt variants across lib/system-prompt.ts, lib/get-system-prompt.ts, and this getBaseSystemPrompt() (different rules/examples and different docs wrapper formats). This duplication is likely to drift over time; consider extracting a single shared base prompt builder and having each variant only customize the docs-loading/wrapping strategy.

Copilot uses AI. Check for mistakes.
- Use a \`<board>\` 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}`
}
112 changes: 112 additions & 0 deletions lib/get-system-prompt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import * as fs from "fs"
import * as path from "path"
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repository convention is to import Node built-ins via the node: specifier with default imports (e.g. import fs from "node:fs", import path from "node:path" as in lib/utils/save-prompt.ts:1-2). Please align these imports for consistency and to avoid ESM interop edge-cases.

Suggested change
import * as fs from "fs"
import * as path from "path"
import fs from "node:fs"
import path from "node:path"

Copilot uses AI. Check for mistakes.

/**
* 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<string> {
// 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<string> {
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file exports an async getSystemPrompt(), but lib/system-prompt.ts also exports a sync getSystemPrompt() with different formatting/wrapping. Having two similarly-named public APIs for the same concept is confusing and can lead to importing the wrong one; consider consolidating to one implementation or renaming to reflect behavior (sync vs async / cached vs fetch) and standardizing the docs wrapper format.

Suggested change
* 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<string> {
* Builds the system prompt used for AI-based circuit generation benchmarks,
* including auto-generated tscircuit component documentation so the model
* has accurate, up-to-date API references.
*
* This async variant fetches the latest docs (from local cache or remote)
* and should be used when you need a prompt with embedded documentation.
*/
export async function getSystemPromptWithDocs(): Promise<string> {

Copilot uses AI. Check for mistakes.
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 \`<board>\` 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 \`<trace>\` 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 () => (
<board width="10mm" height="10mm">
<battery
name="B1"
footprint="cr2032"
pcbX={0}
pcbY={0}
positive="VCC"
negative="GND"
/>
<resistor
name="R1"
resistance="330"
footprint="0402"
pcbX={3}
pcbY={0}
pin1="VCC"
pin2="led_anode"
/>
<led
name="LED1"
footprint="0402"
color="red"
pcbX={6}
pcbY={0}
anode="led_anode"
cathode="GND"
/>
</board>
)
\`\`\`
${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 \`<board>\` element
- Do not use placeholder values — provide real electrical values
`
}
64 changes: 64 additions & 0 deletions lib/system-prompt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as fs from "fs"
import * as path from "path"
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repository convention is to import Node built-ins via the node: specifier with default imports (e.g. import fs from "node:fs", import path from "node:path" as in lib/utils/save-prompt.ts:1-2). Using import * as fs from "fs" / import * as path from "path" is inconsistent and can behave differently depending on TS/Bundler settings; please align these imports with the existing pattern.

Suggested change
import * as fs from "fs"
import * as path from "path"
import fs from "node:fs"
import path from "node:path"

Copilot uses AI. Check for mistakes.

/**
* 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
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring states this is "the main system prompt used in all tscircuit prompt benchmarks", but the benchmarks currently build the system prompt via createLocalCircuitPrompt() (see benchmarks/benchmark-local-circuit*.eval.ts) and nothing imports lib/system-prompt.ts. Please either wire this prompt builder into the benchmark flow or reword the comment to avoid misleading future readers.

Copilot uses AI. Check for mistakes.
*/
export function getSystemPrompt(): string {
const autoGeneratedDocs = getAutoGeneratedDocs()

const docsBlock = autoGeneratedDocs
? `\n\n<tscircuit_docs>\n${autoGeneratedDocs}\n</tscircuit_docs>`
: ""

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 \`<board>\`
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 () => (
<board width="20mm" height="10mm">
<battery name="B1" footprint="cr2032" pcbX={0} pcbY={0} positive="VCC" negative="GND" />
<resistor name="R1" resistance="330" footprint="0402" pcbX={5} pcbY={0} pin1="VCC" pin2="net1" />
<led name="D1" footprint="0402" color="red" pcbX={10} pcbY={0} anode="net1" cathode="GND" />
</board>
)
\`\`\`
${docsBlock}`
}
63 changes: 63 additions & 0 deletions scripts/update-docs.ts
Original file line number Diff line number Diff line change
@@ -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"
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repository convention is to import Node built-ins via the node: specifier with default imports (e.g. import fs from "node:fs", import path from "node:path" as in scripts/threshold-test.ts:2-3). Please align these imports for consistency.

Suggested change
import * as fs from "fs"
import * as path from "path"
import fs from "node:fs"
import path from "node:path"

Copilot uses AI. Check for mistakes.

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<string | null> {
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)
})
Loading