Skip to content
Closed
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
26 changes: 25 additions & 1 deletion lib/prompt-templates/create-local-circuit-prompt.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
fp,
getFootprintNamesByType,
getFootprintSizes,
fp,
} from "@tscircuit/footprinter"

async function fetchFileContent(url: string): Promise<string> {
Expand All @@ -19,6 +19,22 @@ async function fetchFileContent(url: string): Promise<string> {
}
}

async function fetchOptionalFileContent(url: string): Promise<string> {
try {
const response = await fetch(url)
if (!response.ok) {
console.warn(
`Skipping optional file: ${response.status} ${response.statusText}`,
)
return ""
}
return await response.text()
} catch (error) {
console.warn("Skipping optional file:", error)
return ""
}
}

export const createLocalCircuitPrompt = async () => {
const footprintNamesByType = getFootprintNamesByType()
const footprintSizes = getFootprintSizes()
Expand All @@ -44,11 +60,19 @@ export const createLocalCircuitPrompt = async () => {
.join("\n")
.replace(/\n\n+/g, "\n\n")

const generatedDocs = await fetchOptionalFileContent(
"https://docs.tscircuit.com/ai.txt",
)

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

## Generated tscircuit documentation

${generatedDocs}

## tscircuit API overview

Here's an overview of the tscircuit API:
Expand Down
61 changes: 61 additions & 0 deletions tests/prompt-templates/create-local-circuit-prompt.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { afterEach, describe, expect, it } from "bun:test"
import { createLocalCircuitPrompt } from "../../lib/prompt-templates/create-local-circuit-prompt"

describe("createLocalCircuitPrompt", () => {
const originalFetch = globalThis.fetch

afterEach(() => {
globalThis.fetch = originalFetch
})

it("includes generated tscircuit docs in the system prompt", async () => {
globalThis.fetch = (async (input: RequestInfo | URL) => {
const url = input.toString()

if (url === "https://docs.tscircuit.com/ai.txt") {
return new Response("Generated docs marker", { status: 200 })
}

if (
url ===
"https://raw.githubusercontent.com/tscircuit/props/main/generated/COMPONENT_TYPES.md"
) {
return new Response("# Components\n\n<resistor />", { status: 200 })
}

throw new Error(`Unexpected URL: ${url}`)
}) as typeof fetch

const prompt = await createLocalCircuitPrompt()

expect(prompt).toContain("## Generated tscircuit documentation")
expect(prompt).toContain("Generated docs marker")
})

it("still creates a prompt when generated docs are unavailable", async () => {
globalThis.fetch = (async (input: RequestInfo | URL) => {
const url = input.toString()

if (url === "https://docs.tscircuit.com/ai.txt") {
return new Response("Unavailable", {
status: 503,
statusText: "Service Unavailable",
})
}

if (
url ===
"https://raw.githubusercontent.com/tscircuit/props/main/generated/COMPONENT_TYPES.md"
) {
return new Response("# Components\n\n<resistor />", { status: 200 })
}

throw new Error(`Unexpected URL: ${url}`)
}) as typeof fetch

const prompt = await createLocalCircuitPrompt()

expect(prompt).toContain("## Generated tscircuit documentation")
expect(prompt).toContain("## tscircuit API overview")
})
})
10 changes: 6 additions & 4 deletions tests/tscircuitCoder.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { createTscircuitCoder } from "lib/tscircuit-coder/tscircuitCoder"
import { expect, test } from "bun:test"
import { createTscircuitCoder } from "lib/tscircuit-coder/tscircuitCoder"
import { getPrimarySourceCodeFromVfs } from "lib/utils/get-primary-source-code-from-vfs"

test("TscircuitCoder submitPrompt streams and updates vfs", async () => {
const openAiTest = process.env.OPENAI_API_KEY ? test : test.skip

openAiTest("TscircuitCoder submitPrompt streams and updates vfs", async () => {
const streamedChunks: string[] = []
let vfsUpdated = false
const tscircuitCoder = createTscircuitCoder()
Expand All @@ -21,14 +23,14 @@ test("TscircuitCoder submitPrompt streams and updates vfs", async () => {
prompt: "add a transistor component",
})

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

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

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

Expand Down
6 changes: 4 additions & 2 deletions tests/utils/generate-random-prompts.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { describe, it, expect } from "bun:test"
import { describe, expect, it } from "bun:test"
import { generateRandomPrompts } from "../../lib/utils/generate-random-prompts"

describe("generateRandomPrompts", () => {
it("should return an array of prompts", async () => {
const openAiIt = process.env.OPENAI_API_KEY ? it : it.skip

openAiIt("should return an array of prompts", async () => {
const prompts = await generateRandomPrompts(3)

expect(Array.isArray(prompts)).toBe(true)
Expand Down
Loading