@buildwithtrace/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # @buildwithtrace/sdk
2
+
3
+ TypeScript SDK for [Trace](https://buildwithtrace.com) — AI-powered PCB & schematic design.
4
+
5
+ ```bash
6
+ npm install @buildwithtrace/sdk
7
+ ```
8
+
9
+ ```ts
10
+ import { Trace } from '@buildwithtrace/sdk';
11
+
12
+ const trace = new Trace({ apiKey: process.env.TRACE_API_KEY });
13
+
14
+ const sym = await trace.generateSymbol('LM7805 5V voltage regulator');
15
+ sym.save('./symbols/'); // writes LM7805.kicad_sym
16
+
17
+ const fp = await trace.generateFootprint('SOIC-8 3.9x4.9mm');
18
+ fp.save('./footprints/'); // writes SOIC-8.kicad_mod
19
+
20
+ const hits = await trace.search('3.3V LDO', { type: 'symbol' });
21
+
22
+ // Read-only Q&A:
23
+ const ans = await trace.ask('What ERC violations exist?', { projectDir: './my-board/' });
24
+
25
+ // Standalone agent (executes file tools locally + posts results):
26
+ const res = await trace.chat('Add a 100nF decoupling cap on U1', {
27
+ mode: 'agent',
28
+ projectDir: './my-board/',
29
+ });
30
+ ```
31
+
32
+ Get an API key: `buildwithtrace auth token` (CLI) or buildwithtrace.com/dashboard/settings → Developer.
33
+
34
+ ## Notes
35
+
36
+ - `chat({ mode: 'agent' | 'plan' })` runs a client-side tool-execution loop for **file tools**
37
+ (`read_file`, `write`, `search_replace`, `list_dir`, `grep`, `delete_trace_file`) with a
38
+ path/extension allowlist + project-dir sandbox. **Engine tools** (ERC/DRC/gerbers/export)
39
+ are not yet ported — those throw `TraceToolExecutionError`; use the `buildwithtrace` CLI for them.
40
+ - `.trace_*` writes succeed, but the matching `.kicad_*` isn't regenerated client-side yet
41
+ (the converter isn't bundled in the Node SDK) — the result says so.
42
+ - BYOK supported via `chat(..., { llmProvider, llmApiKey, llmModelId })`.
@@ -0,0 +1,171 @@
1
+ /**
2
+ * @buildwithtrace/sdk — TypeScript SDK for Trace AI-powered EDA tools.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { Trace } from '@buildwithtrace/sdk';
7
+ *
8
+ * const trace = new Trace({ apiKey: 'your-api-key' });
9
+ *
10
+ * const symbol = await trace.generateSymbol('LM7805 5V voltage regulator');
11
+ * console.log(symbol.name); // "LM7805"
12
+ * console.log(symbol.pinCount); // 3
13
+ * symbol.save('./symbols/'); // writes LM7805.kicad_sym
14
+ *
15
+ * const fp = await trace.generateFootprint('SOIC-8 3.9x4.9mm');
16
+ * fp.save('./footprints/'); // writes SOIC-8.kicad_mod
17
+ *
18
+ * const results = await trace.search('voltage regulator', { type: 'symbol' });
19
+ * const answer = await trace.ask('What ERC violations exist?', { projectDir: './my-board/' });
20
+ * ```
21
+ */
22
+ /** Base error for SDK-surfaced backend failures (e.g. an SSE `error` event). */
23
+ declare class TraceError extends Error {
24
+ constructor(message: string);
25
+ }
26
+ /**
27
+ * Thrown when an agent turn requests a tool the SDK does NOT execute locally.
28
+ *
29
+ * The SDK runs a client-side tool loop for FILE tools (`read_file`, `write`,
30
+ * `search_replace`, `list_dir`, `grep`, `delete_trace_file`). Engine/GUI tools
31
+ * — ERC/DRC, gerber/drill/position export, `take_snapshot`, `run_*`, `autoroute`,
32
+ * etc. — are out of scope and raise this error pointing you at the
33
+ * `buildwithtrace` CLI or the desktop app.
34
+ */
35
+ declare class TraceToolExecutionError extends TraceError {
36
+ constructor(message: string);
37
+ }
38
+ interface TraceConfig {
39
+ apiKey: string;
40
+ baseUrl?: string;
41
+ timeout?: number;
42
+ }
43
+ interface GenerateResult {
44
+ name: string;
45
+ type: 'symbol' | 'footprint';
46
+ description: string;
47
+ pinCount: number;
48
+ padCount: number;
49
+ kicadSym: string | null;
50
+ kicadMod: string | null;
51
+ traceJson: Record<string, unknown> | null;
52
+ warning: string | null;
53
+ steps: Array<Record<string, unknown>>;
54
+ save(directory?: string): string;
55
+ }
56
+ interface SearchResult {
57
+ name: string;
58
+ library: string;
59
+ description: string;
60
+ pinCount: number;
61
+ padCount: number;
62
+ category: string;
63
+ source: string;
64
+ score: number;
65
+ }
66
+ interface TextResult {
67
+ text: string;
68
+ conversationId: string | null;
69
+ usage: Record<string, unknown> | null;
70
+ }
71
+ interface SearchOptions {
72
+ type?: 'symbol' | 'footprint';
73
+ limit?: number;
74
+ }
75
+ interface AskOptions {
76
+ projectDir?: string;
77
+ fileContent?: string;
78
+ appType?: 'eeschema' | 'pcbnew';
79
+ filePath?: string;
80
+ conversationId?: string;
81
+ }
82
+ interface ChatOptions {
83
+ mode?: 'ask' | 'agent' | 'plan';
84
+ appType?: 'eeschema' | 'pcbnew';
85
+ projectDir?: string;
86
+ filePath?: string;
87
+ fileContent?: string;
88
+ conversationId?: string;
89
+ teamId?: string;
90
+ attachments?: Array<Record<string, unknown>>;
91
+ /** BYOK: route this turn to your own provider (you pay the provider directly). */
92
+ llmProvider?: string;
93
+ llmApiKey?: string;
94
+ llmModelId?: string;
95
+ }
96
+ declare class Trace {
97
+ private apiKey;
98
+ private baseUrl;
99
+ private timeout;
100
+ constructor(config: TraceConfig);
101
+ generateSymbol(description: string, options?: {
102
+ datasheetUrl?: string;
103
+ additionalInstructions?: string;
104
+ }): Promise<GenerateResult>;
105
+ generateFootprint(description: string, options?: {
106
+ packageType?: string;
107
+ datasheetUrl?: string;
108
+ }): Promise<GenerateResult>;
109
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
110
+ ask(question: string, options?: AskOptions): Promise<TextResult>;
111
+ review(options?: {
112
+ projectDir?: string;
113
+ focus?: string;
114
+ appType?: 'eeschema' | 'pcbnew';
115
+ fileContent?: string;
116
+ filePath?: string;
117
+ }): Promise<TextResult>;
118
+ /**
119
+ * Stream a chat turn and collect the full response. Exposes the full backend
120
+ * chat contract: pcbnew vs eeschema (`appType`), multi-turn (`conversationId` —
121
+ * read it back off the result), team workspaces (`teamId`), multimodal
122
+ * `attachments`, `filePath` + `fileContent`, and BYOK
123
+ * (`llmProvider`/`llmApiKey`/`llmModelId`).
124
+ *
125
+ * NOTE: mode 'agent'/'plan' produce tool calls that run on the caller's
126
+ * machine. The SDK runs a client-side tool loop for FILE tools (read_file,
127
+ * write, search_replace, list_dir, grep, delete_trace_file), executing them
128
+ * under `projectDir` (defaults to process.cwd()) with the same path +
129
+ * extension allowlist as the CLI/desktop, and POSTing each result back to the
130
+ * backend so multi-step agent runs continue. Engine/GUI tools (ERC/DRC,
131
+ * gerber/export, take_snapshot, run_*, autoroute) are out of scope and throw
132
+ * TraceToolExecutionError — use the `buildwithtrace` CLI for those.
133
+ */
134
+ chat(message: string, options?: ChatOptions): Promise<TextResult>;
135
+ private _post;
136
+ private static _httpError;
137
+ private _get;
138
+ /**
139
+ * Single source of truth for the /chat/stream request body. Mirrors the
140
+ * backend ChatRequest contract so the SDK stays in lockstep with the
141
+ * CLI/desktop instead of sending a stale minimal payload.
142
+ */
143
+ private _buildChatBody;
144
+ /**
145
+ * Stream /chat/stream and drive a client-side tool loop.
146
+ *
147
+ * The backend pauses the SSE stream at each `tool_call` until the client POSTs
148
+ * the result to /tools/result, so we MUST read the body incrementally (not
149
+ * buffer it whole — that would dead-lock waiting for `done`). FILE tools are
150
+ * executed locally under `projectDir`; their result is posted back and the
151
+ * SAME stream keeps yielding events (the backend drives the multi-step loop)
152
+ * until `done`. Engine/GUI tools are out of scope and throw.
153
+ */
154
+ private _streamChat;
155
+ private static _parseSSELine;
156
+ /**
157
+ * Execute one tool call. FILE tools run locally (sandboxed to projectDir) and
158
+ * their result is POSTed to /tools/result so the backend continues the stream.
159
+ * Engine/GUI tools are out of scope and throw TraceToolExecutionError.
160
+ */
161
+ private _handleToolCall;
162
+ /**
163
+ * POST a tool result back to /api/<version>/tools/result (same base URL +
164
+ * version as /chat/stream). Non-fatal on failure — like the CLI, we warn and
165
+ * move on rather than crashing the loop (the backend turn will time out).
166
+ */
167
+ private _postToolResult;
168
+ private _makeGenerateResult;
169
+ }
170
+
171
+ export { type AskOptions, type ChatOptions, type GenerateResult, type SearchOptions, type SearchResult, type TextResult, Trace, type TraceConfig, TraceError, TraceToolExecutionError, Trace as default };
@@ -0,0 +1,171 @@
1
+ /**
2
+ * @buildwithtrace/sdk — TypeScript SDK for Trace AI-powered EDA tools.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { Trace } from '@buildwithtrace/sdk';
7
+ *
8
+ * const trace = new Trace({ apiKey: 'your-api-key' });
9
+ *
10
+ * const symbol = await trace.generateSymbol('LM7805 5V voltage regulator');
11
+ * console.log(symbol.name); // "LM7805"
12
+ * console.log(symbol.pinCount); // 3
13
+ * symbol.save('./symbols/'); // writes LM7805.kicad_sym
14
+ *
15
+ * const fp = await trace.generateFootprint('SOIC-8 3.9x4.9mm');
16
+ * fp.save('./footprints/'); // writes SOIC-8.kicad_mod
17
+ *
18
+ * const results = await trace.search('voltage regulator', { type: 'symbol' });
19
+ * const answer = await trace.ask('What ERC violations exist?', { projectDir: './my-board/' });
20
+ * ```
21
+ */
22
+ /** Base error for SDK-surfaced backend failures (e.g. an SSE `error` event). */
23
+ declare class TraceError extends Error {
24
+ constructor(message: string);
25
+ }
26
+ /**
27
+ * Thrown when an agent turn requests a tool the SDK does NOT execute locally.
28
+ *
29
+ * The SDK runs a client-side tool loop for FILE tools (`read_file`, `write`,
30
+ * `search_replace`, `list_dir`, `grep`, `delete_trace_file`). Engine/GUI tools
31
+ * — ERC/DRC, gerber/drill/position export, `take_snapshot`, `run_*`, `autoroute`,
32
+ * etc. — are out of scope and raise this error pointing you at the
33
+ * `buildwithtrace` CLI or the desktop app.
34
+ */
35
+ declare class TraceToolExecutionError extends TraceError {
36
+ constructor(message: string);
37
+ }
38
+ interface TraceConfig {
39
+ apiKey: string;
40
+ baseUrl?: string;
41
+ timeout?: number;
42
+ }
43
+ interface GenerateResult {
44
+ name: string;
45
+ type: 'symbol' | 'footprint';
46
+ description: string;
47
+ pinCount: number;
48
+ padCount: number;
49
+ kicadSym: string | null;
50
+ kicadMod: string | null;
51
+ traceJson: Record<string, unknown> | null;
52
+ warning: string | null;
53
+ steps: Array<Record<string, unknown>>;
54
+ save(directory?: string): string;
55
+ }
56
+ interface SearchResult {
57
+ name: string;
58
+ library: string;
59
+ description: string;
60
+ pinCount: number;
61
+ padCount: number;
62
+ category: string;
63
+ source: string;
64
+ score: number;
65
+ }
66
+ interface TextResult {
67
+ text: string;
68
+ conversationId: string | null;
69
+ usage: Record<string, unknown> | null;
70
+ }
71
+ interface SearchOptions {
72
+ type?: 'symbol' | 'footprint';
73
+ limit?: number;
74
+ }
75
+ interface AskOptions {
76
+ projectDir?: string;
77
+ fileContent?: string;
78
+ appType?: 'eeschema' | 'pcbnew';
79
+ filePath?: string;
80
+ conversationId?: string;
81
+ }
82
+ interface ChatOptions {
83
+ mode?: 'ask' | 'agent' | 'plan';
84
+ appType?: 'eeschema' | 'pcbnew';
85
+ projectDir?: string;
86
+ filePath?: string;
87
+ fileContent?: string;
88
+ conversationId?: string;
89
+ teamId?: string;
90
+ attachments?: Array<Record<string, unknown>>;
91
+ /** BYOK: route this turn to your own provider (you pay the provider directly). */
92
+ llmProvider?: string;
93
+ llmApiKey?: string;
94
+ llmModelId?: string;
95
+ }
96
+ declare class Trace {
97
+ private apiKey;
98
+ private baseUrl;
99
+ private timeout;
100
+ constructor(config: TraceConfig);
101
+ generateSymbol(description: string, options?: {
102
+ datasheetUrl?: string;
103
+ additionalInstructions?: string;
104
+ }): Promise<GenerateResult>;
105
+ generateFootprint(description: string, options?: {
106
+ packageType?: string;
107
+ datasheetUrl?: string;
108
+ }): Promise<GenerateResult>;
109
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
110
+ ask(question: string, options?: AskOptions): Promise<TextResult>;
111
+ review(options?: {
112
+ projectDir?: string;
113
+ focus?: string;
114
+ appType?: 'eeschema' | 'pcbnew';
115
+ fileContent?: string;
116
+ filePath?: string;
117
+ }): Promise<TextResult>;
118
+ /**
119
+ * Stream a chat turn and collect the full response. Exposes the full backend
120
+ * chat contract: pcbnew vs eeschema (`appType`), multi-turn (`conversationId` —
121
+ * read it back off the result), team workspaces (`teamId`), multimodal
122
+ * `attachments`, `filePath` + `fileContent`, and BYOK
123
+ * (`llmProvider`/`llmApiKey`/`llmModelId`).
124
+ *
125
+ * NOTE: mode 'agent'/'plan' produce tool calls that run on the caller's
126
+ * machine. The SDK runs a client-side tool loop for FILE tools (read_file,
127
+ * write, search_replace, list_dir, grep, delete_trace_file), executing them
128
+ * under `projectDir` (defaults to process.cwd()) with the same path +
129
+ * extension allowlist as the CLI/desktop, and POSTing each result back to the
130
+ * backend so multi-step agent runs continue. Engine/GUI tools (ERC/DRC,
131
+ * gerber/export, take_snapshot, run_*, autoroute) are out of scope and throw
132
+ * TraceToolExecutionError — use the `buildwithtrace` CLI for those.
133
+ */
134
+ chat(message: string, options?: ChatOptions): Promise<TextResult>;
135
+ private _post;
136
+ private static _httpError;
137
+ private _get;
138
+ /**
139
+ * Single source of truth for the /chat/stream request body. Mirrors the
140
+ * backend ChatRequest contract so the SDK stays in lockstep with the
141
+ * CLI/desktop instead of sending a stale minimal payload.
142
+ */
143
+ private _buildChatBody;
144
+ /**
145
+ * Stream /chat/stream and drive a client-side tool loop.
146
+ *
147
+ * The backend pauses the SSE stream at each `tool_call` until the client POSTs
148
+ * the result to /tools/result, so we MUST read the body incrementally (not
149
+ * buffer it whole — that would dead-lock waiting for `done`). FILE tools are
150
+ * executed locally under `projectDir`; their result is posted back and the
151
+ * SAME stream keeps yielding events (the backend drives the multi-step loop)
152
+ * until `done`. Engine/GUI tools are out of scope and throw.
153
+ */
154
+ private _streamChat;
155
+ private static _parseSSELine;
156
+ /**
157
+ * Execute one tool call. FILE tools run locally (sandboxed to projectDir) and
158
+ * their result is POSTed to /tools/result so the backend continues the stream.
159
+ * Engine/GUI tools are out of scope and throw TraceToolExecutionError.
160
+ */
161
+ private _handleToolCall;
162
+ /**
163
+ * POST a tool result back to /api/<version>/tools/result (same base URL +
164
+ * version as /chat/stream). Non-fatal on failure — like the CLI, we warn and
165
+ * move on rather than crashing the loop (the backend turn will time out).
166
+ */
167
+ private _postToolResult;
168
+ private _makeGenerateResult;
169
+ }
170
+
171
+ export { type AskOptions, type ChatOptions, type GenerateResult, type SearchOptions, type SearchResult, type TextResult, Trace, type TraceConfig, TraceError, TraceToolExecutionError, Trace as default };