From 0963fed692b27f3eb80c4c4b3345540c8d8a0719 Mon Sep 17 00:00:00 2001 From: Finesssee <90105158+Finesssee@users.noreply.github.com> Date: Thu, 21 May 2026 05:16:18 +0700 Subject: [PATCH 1/2] Include generated docs in local circuit prompt --- .../create-local-circuit-prompt.ts | 31 +++++++++++ tests/create-local-circuit-prompt.test.ts | 52 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 tests/create-local-circuit-prompt.test.ts diff --git a/lib/prompt-templates/create-local-circuit-prompt.ts b/lib/prompt-templates/create-local-circuit-prompt.ts index a93f11f..6e2a35b 100644 --- a/lib/prompt-templates/create-local-circuit-prompt.ts +++ b/lib/prompt-templates/create-local-circuit-prompt.ts @@ -19,6 +19,22 @@ async function fetchFileContent(url: string): Promise { } } +async function fetchOptionalFileContent(url: string): Promise { + try { + const response = await fetch(url) + if (!response.ok) { + console.warn( + `Skipping optional prompt context from ${url}: ${response.status} ${response.statusText}`, + ) + return "" + } + return await response.text() + } catch (error) { + console.warn(`Skipping optional prompt context from ${url}:`, error) + return "" + } +} + export const createLocalCircuitPrompt = async () => { const footprintNamesByType = getFootprintNamesByType() const footprintSizes = getFootprintSizes() @@ -38,6 +54,10 @@ export const createLocalCircuitPrompt = async () => { "https://raw.githubusercontent.com/tscircuit/props/main/generated/COMPONENT_TYPES.md", )) || "" + const generatedDocs = ( + await fetchOptionalFileContent("https://docs.tscircuit.com/ai.txt") + ).trim() + const cleanedPropsDoc = propsDoc .split("\n") .filter((line) => !line.startsWith("#")) @@ -118,6 +138,17 @@ keep in mind that num_pins can be replaced with a number directly infront of the ${cleanedPropsDoc} +${ + generatedDocs + ? `### Auto-generated tscircuit docs + +The following docs are generated from the current tscircuit documentation site: + +${generatedDocs} +` + : "" +} + - Here is a list of unsupported components: 1- powersource diff --git a/tests/create-local-circuit-prompt.test.ts b/tests/create-local-circuit-prompt.test.ts new file mode 100644 index 0000000..b1b2b0a --- /dev/null +++ b/tests/create-local-circuit-prompt.test.ts @@ -0,0 +1,52 @@ +import { afterEach, describe, expect, test } from "bun:test" +import { createLocalCircuitPrompt } from "lib/prompt-templates/create-local-circuit-prompt" + +const originalFetch = globalThis.fetch + +afterEach(() => { + globalThis.fetch = originalFetch +}) + +const mockFetch = (handler: (url: string) => Response | Promise) => { + globalThis.fetch = ((input: RequestInfo | URL) => { + const url = input.toString() + return Promise.resolve(handler(url)) + }) as typeof fetch +} + +describe("createLocalCircuitPrompt", () => { + test("includes generated tscircuit docs when ai.txt is available", async () => { + mockFetch((url) => { + if (url === "https://docs.tscircuit.com/ai.txt") { + return new Response("Generated docs: prefer pinLabels", { + status: 200, + }) + } + + return new Response("# Components\n\n\n", { status: 200 }) + }) + + const prompt = await createLocalCircuitPrompt() + + expect(prompt).toContain("### Auto-generated tscircuit docs") + expect(prompt).toContain("Generated docs: prefer pinLabels") + }) + + test("still creates a prompt when generated docs cannot be fetched", async () => { + mockFetch((url) => { + if (url === "https://docs.tscircuit.com/ai.txt") { + return new Response("not found", { + status: 404, + statusText: "Not Found", + }) + } + + return new Response("# Components\n\n\n", { status: 200 }) + }) + + const prompt = await createLocalCircuitPrompt() + + expect(prompt).toContain("## tscircuit API overview") + expect(prompt).not.toContain("### Auto-generated tscircuit docs") + }) +}) From 9903b6bb09b068bbac8d7d518b87b41f2f0fceca Mon Sep 17 00:00:00 2001 From: Finesssee <90105158+Finesssee@users.noreply.github.com> Date: Thu, 21 May 2026 05:18:39 +0700 Subject: [PATCH 2/2] Skip live OpenAI tests without API key --- tests/tscircuitCoder.test.ts | 75 +++++++++++---------- tests/utils/generate-random-prompts.test.ts | 4 +- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/tests/tscircuitCoder.test.ts b/tests/tscircuitCoder.test.ts index d66c022..02d26c9 100644 --- a/tests/tscircuitCoder.test.ts +++ b/tests/tscircuitCoder.test.ts @@ -2,38 +2,43 @@ 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 - }) - - await tscircuitCoder.submitPrompt({ - prompt: "create bridge rectifier circuit", - }) - - await tscircuitCoder.submitPrompt({ - prompt: "add a transistor component", - }) - - let codeWithTransistor = getPrimarySourceCodeFromVfs(tscircuitCoder.vfs) - expect(codeWithTransistor).toInclude("transistor") - - await tscircuitCoder.submitPrompt({ - prompt: "add a tssop20 chip", - }) - - 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) -}) +const testWithOpenAiKey = process.env.OPENAI_API_KEY ? test : test.skip + +testWithOpenAiKey( + "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: "add a transistor component", + }) + + let codeWithTransistor = getPrimarySourceCodeFromVfs(tscircuitCoder.vfs) + expect(codeWithTransistor).toInclude("transistor") + + await tscircuitCoder.submitPrompt({ + prompt: "add a tssop20 chip", + }) + + 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) + }, +) diff --git a/tests/utils/generate-random-prompts.test.ts b/tests/utils/generate-random-prompts.test.ts index 41a061c..559386f 100644 --- a/tests/utils/generate-random-prompts.test.ts +++ b/tests/utils/generate-random-prompts.test.ts @@ -1,8 +1,10 @@ import { describe, it, expect } from "bun:test" import { generateRandomPrompts } from "../../lib/utils/generate-random-prompts" +const itWithOpenAiKey = process.env.OPENAI_API_KEY ? it : it.skip + describe("generateRandomPrompts", () => { - it("should return an array of prompts", async () => { + itWithOpenAiKey("should return an array of prompts", async () => { const prompts = await generateRandomPrompts(3) expect(Array.isArray(prompts)).toBe(true)