Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions lib/prompt-templates/create-local-circuit-prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
getFootprintSizes,
fp,
} from "@tscircuit/footprinter"
import { fetchTSCircuitAIDocs } from "../utils/fetch-tscircuit-context"

async function fetchFileContent(url: string): Promise<string> {
try {
Expand Down Expand Up @@ -44,12 +45,17 @@ export const createLocalCircuitPrompt = async () => {
.join("\n")
.replace(/\n\n+/g, "\n\n")

// Fetch comprehensive TSCircuit AI documentation
const tscircuitAIDocs = await fetchTSCircuitAIDocs()

return `
You are an expert in electronic circuit design and tscircuit, and your job is to create a circuit board in tscircuit with the user-provided description.

YOU MUST ABIDE BY THE RULES IN THE RULES SECTION

## tscircuit API overview
## TSCircuit Comprehensive Documentation

${tscircuitAIDocs ? `${tscircuitAIDocs}\n\n` : ""}## tscircuit API overview

Here's an overview of the tscircuit API:

Expand Down Expand Up @@ -330,7 +336,7 @@ export const MyLed = () => (
// ### Importing Components

// You can import a variety of components from the tscircuit registry. tscircuit
// registry components are always prefixed with \`@tsci/\`. Make sure to include
// registry components are always prefixed with `@tsci/`. Make sure to include
// your imports at the top of the codefence.

// If you are not told explicitly that an import exists, do not import it.
31 changes: 31 additions & 0 deletions lib/utils/fetch-tscircuit-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Utility to fetch TSCircuit AI documentation
*/

export async function fetchTSCircuitAIDocs(): Promise<string> {
try {
console.log(
"Fetching TSCircuit AI documentation from docs.tscircuit.com/ai.txt",
)

const response = await fetch("https://docs.tscircuit.com/ai.txt", {
headers: {
"User-Agent": "tscircuit-prompt-benchmarks",
},
})

if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}

const docs = await response.text()
console.log(
`Successfully fetched TSCircuit AI docs (${docs.length} characters)`,
)
return docs
} catch (error) {
console.warn("Failed to fetch TSCircuit AI docs:", error)
console.log("Continuing without TSCircuit AI context")
return ""
}
}
28 changes: 21 additions & 7 deletions lib/utils/get-primary-source-code-from-vfs.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
export function getPrimarySourceCodeFromVfs(
vfs: Record<string, string> | undefined,
): string | undefined {
let code = undefined
if (vfs && Object.keys(vfs).length !== 0) {
const finalResultKey = Object.keys(vfs)[Object.keys(vfs).length - 1]
if (finalResultKey.includes("final")) {
code = vfs[finalResultKey]
}
if (!vfs || Object.keys(vfs).length === 0) {
return undefined
}
return code

const finalKeys = Object.keys(vfs).filter((key) => key.includes("final"))

if (finalKeys.length === 0) {
return undefined
}

const parsePromptId = (key: string): number => {
const match = key.match(/prompt-(\d+)-attempt-final/)
return match ? parseInt(match[1], 10) : 0
}

finalKeys.sort((a, b) => {
const idA = parsePromptId(a)
const idB = parsePromptId(b)
return idB - idA
})

return vfs[finalKeys[0]]
}
61 changes: 32 additions & 29 deletions tests/tscircuitCoder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,41 @@ import { createTscircuitCoder } from "lib/tscircuit-coder/tscircuitCoder"
import { expect, test } from "bun:test"
import { getPrimarySourceCodeFromVfs } from "lib/utils/get-primary-source-code-from-vfs"

test("TscircuitCoder submitPrompt streams and updates vfs", async () => {
const streamedChunks: string[] = []
let vfsUpdated = false
const tscircuitCoder = createTscircuitCoder()
tscircuitCoder.on("streamedChunk", (chunk: string) => {
streamedChunks.push(chunk)
})
tscircuitCoder.on("vfsChanged", () => {
vfsUpdated = true
})
test.skipIf(!process.env.OPENAI_API_KEY)(
"TscircuitCoder submitPrompt streams and updates vfs",
async () => {
const streamedChunks: string[] = []
let vfsUpdated = false
const tscircuitCoder = createTscircuitCoder()
tscircuitCoder.on("streamedChunk", (chunk: string) => {
streamedChunks.push(chunk)
})
tscircuitCoder.on("vfsChanged", () => {
vfsUpdated = true
})

await tscircuitCoder.submitPrompt({
prompt: "create bridge rectifier circuit",
})
await tscircuitCoder.submitPrompt({
prompt: "create bridge rectifier circuit",
})

await tscircuitCoder.submitPrompt({
prompt: "add a transistor component",
})
await tscircuitCoder.submitPrompt({
prompt: "add a transistor component",
})

let codeWithTransistor = getPrimarySourceCodeFromVfs(tscircuitCoder.vfs)
expect(codeWithTransistor).toInclude("transistor")
let codeWithTransistor = getPrimarySourceCodeFromVfs(tscircuitCoder.vfs)
expect(codeWithTransistor).toInclude("transistor")

await tscircuitCoder.submitPrompt({
prompt: "add a tssop20 chip",
})
await tscircuitCoder.submitPrompt({
prompt: "add a tssop20 chip",
})

let codeWithChip = getPrimarySourceCodeFromVfs(tscircuitCoder.vfs)
expect(codeWithChip).toInclude("tssop20")
expect(codeWithChip).toInclude("transistor")
let codeWithChip = getPrimarySourceCodeFromVfs(tscircuitCoder.vfs)
expect(codeWithChip).toInclude("tssop20")
expect(codeWithChip).toInclude("transistor")

expect(streamedChunks.length).toBeGreaterThan(0)
const vfsKeys = Object.keys(tscircuitCoder.vfs)
expect(vfsKeys.length).toBeGreaterThan(0)
expect(vfsUpdated).toBe(true)
})
expect(streamedChunks.length).toBeGreaterThan(0)
const vfsKeys = Object.keys(tscircuitCoder.vfs)
expect(vfsKeys.length).toBeGreaterThan(0)
expect(vfsUpdated).toBe(true)
},
)
13 changes: 8 additions & 5 deletions tests/utils/generate-random-prompts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import { describe, it, expect } from "bun:test"
import { generateRandomPrompts } from "../../lib/utils/generate-random-prompts"

describe("generateRandomPrompts", () => {
it("should return an array of prompts", async () => {
const prompts = await generateRandomPrompts(3)
it.skipIf(!process.env.OPENAI_API_KEY)(
"should return an array of prompts",
async () => {
const prompts = await generateRandomPrompts(3)

expect(Array.isArray(prompts)).toBe(true)
expect(prompts.length).toBe(3)
})
expect(Array.isArray(prompts)).toBe(true)
expect(prompts.length).toBe(3)
},
)
})