mirascope 2.0.0-alpha.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.
Files changed (46) hide show
  1. package/README.md +397 -0
  2. package/dist/bun.cjs +447 -0
  3. package/dist/bun.cjs.map +1 -0
  4. package/dist/bun.d.cts +53 -0
  5. package/dist/bun.d.ts +53 -0
  6. package/dist/bun.js +94 -0
  7. package/dist/bun.js.map +1 -0
  8. package/dist/chunk-2R5IW35Y.js +116 -0
  9. package/dist/chunk-2R5IW35Y.js.map +1 -0
  10. package/dist/chunk-A6ZCB7BU.js +6826 -0
  11. package/dist/chunk-A6ZCB7BU.js.map +1 -0
  12. package/dist/chunk-NSBPE2FW.js +15 -0
  13. package/dist/chunk-NSBPE2FW.js.map +1 -0
  14. package/dist/chunk-RMNCGJYW.js +49 -0
  15. package/dist/chunk-RMNCGJYW.js.map +1 -0
  16. package/dist/chunk-U4MFJ4DP.js +358 -0
  17. package/dist/chunk-U4MFJ4DP.js.map +1 -0
  18. package/dist/index.cjs +7705 -0
  19. package/dist/index.cjs.map +1 -0
  20. package/dist/index.d.cts +4859 -0
  21. package/dist/index.d.ts +4859 -0
  22. package/dist/index.js +324 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/model-T6IQ7UUA.js +4 -0
  25. package/dist/model-T6IQ7UUA.js.map +1 -0
  26. package/dist/tool-schema-Dh-RLHhC.d.cts +45 -0
  27. package/dist/tool-schema-Dh-RLHhC.d.ts +45 -0
  28. package/dist/transform/index.cjs +525 -0
  29. package/dist/transform/index.cjs.map +1 -0
  30. package/dist/transform/index.d.cts +89 -0
  31. package/dist/transform/index.d.ts +89 -0
  32. package/dist/transform/index.js +6 -0
  33. package/dist/transform/index.js.map +1 -0
  34. package/dist/transform/plugins/esbuild.cjs +472 -0
  35. package/dist/transform/plugins/esbuild.cjs.map +1 -0
  36. package/dist/transform/plugins/esbuild.d.cts +46 -0
  37. package/dist/transform/plugins/esbuild.d.ts +46 -0
  38. package/dist/transform/plugins/esbuild.js +5 -0
  39. package/dist/transform/plugins/esbuild.js.map +1 -0
  40. package/dist/transform/plugins/vite.cjs +405 -0
  41. package/dist/transform/plugins/vite.cjs.map +1 -0
  42. package/dist/transform/plugins/vite.d.cts +50 -0
  43. package/dist/transform/plugins/vite.d.ts +50 -0
  44. package/dist/transform/plugins/vite.js +5 -0
  45. package/dist/transform/plugins/vite.js.map +1 -0
  46. package/package.json +127 -0
package/README.md ADDED
@@ -0,0 +1,397 @@
1
+ # Mirascope TypeScript (Alpha)
2
+
3
+ The TypeScript implementation of Mirascope: a type-safe, ergonomic library for building LLM-powered applications. Like its Python counterpart, Mirascope TypeScript provides a "Goldilocks API" - more control than agent frameworks, more ergonomic than raw provider APIs.
4
+
5
+ > [!IMPORTANT]
6
+ > **Alpha Status**: This is an early release. APIs may change.
7
+ > We welcome feedback and contributions!
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ # Using bun
13
+ bun add mirascope@alpha
14
+
15
+ # Using npm
16
+ npm install mirascope@alpha
17
+ ```
18
+
19
+ ## Quickstart
20
+
21
+ ```typescript
22
+ import { llm } from "mirascope";
23
+
24
+ // Simple call
25
+ const model = llm.model("anthropic/claude-haiku-4-5")
26
+ const response = await model.call("What's the best way to learn TypeScript?");
27
+ console.log(response.text());
28
+
29
+ // Streaming
30
+ const stream = await model.stream("Tell me a joke");
31
+ for await (const text of stream.textStream()) {
32
+ process.stdout.write(text);
33
+ }
34
+ ```
35
+
36
+ ## Defining Calls
37
+
38
+ Use `defineCall` to create reusable, type-safe call functions:
39
+
40
+ ```typescript
41
+ import { llm } from "mirascope";
42
+
43
+ const recommendBook = llm.defineCall<{ genre: string }>({
44
+ model: "anthropic/claude-haiku-4-5",
45
+ maxTokens: 1024,
46
+ template: ({ genre }) => `Please recommend a book in ${genre}.`,
47
+ });
48
+
49
+ const response = await recommendBook({ genre: "fantasy" });
50
+ console.log(response.text());
51
+
52
+ // Streaming
53
+ const stream = await recommendBook.stream({ genre: "sci-fi" });
54
+ for await (const text of stream.textStream()) {
55
+ process.stdout.write(text);
56
+ }
57
+ ```
58
+
59
+ ## Structured Output
60
+
61
+ > [!NOTE]
62
+ > TypeScript interface patterns (non-Zod) require a compile-time transform. See [Transform Plugin](#transform-plugin) for setup instructions.
63
+
64
+ ### With Zod Schema
65
+
66
+ ```typescript
67
+ import { llm } from "mirascope";
68
+ import { z } from "zod";
69
+
70
+ const BookSchema = z.object({
71
+ title: z.string().describe("The book title"),
72
+ author: z.string().describe("The author's name"),
73
+ year: z.number().int().describe("Publication year"),
74
+ });
75
+ type Book = z.infer<typeof BookSchema>;
76
+
77
+ const recommendBook = llm.defineCall<{ genre: string }>({
78
+ model: "anthropic/claude-haiku-4-5",
79
+ format: BookSchema,
80
+ template: ({ genre }) => `Recommend a ${genre} book.`,
81
+ });
82
+
83
+ const response = await recommendBook({ genre: "mystery" });
84
+ const book: Book = response.parse();
85
+ console.log(`${book.title} by ${book.author} (${book.year})`);
86
+ ```
87
+
88
+ ### With TypeScript Interface
89
+
90
+ ```typescript
91
+ import { llm } from "mirascope";
92
+
93
+ /**
94
+ * A book recommendation.
95
+ */
96
+ type Book = {
97
+ /** The book title */
98
+ title: string;
99
+ /** The author's name */
100
+ author: string;
101
+ /** Publication year */
102
+ year: number;
103
+ };
104
+
105
+ const recommendBook = llm.defineCall<{ genre: string }, Book>({
106
+ model: "anthropic/claude-haiku-4-5",
107
+ template: ({ genre }) => `Recommend a ${genre} book.`,
108
+ });
109
+
110
+ const response = await recommendBook({ genre: "mystery" });
111
+ const book: Book = response.parse();
112
+ console.log(`${book.title} by ${book.author} (${book.year})`);
113
+ ```
114
+
115
+ ## Tools
116
+
117
+ > [!NOTE]
118
+ > TypeScript interface patterns (non-Zod) require a compile-time transform. See [Transform Plugin](#transform-plugin) for setup instructions.
119
+
120
+ ### With Zod Schema
121
+
122
+ ```typescript
123
+ import { llm } from "mirascope";
124
+ import { z } from "zod";
125
+
126
+ const getWeather = llm.defineTool({
127
+ name: "get_weather",
128
+ description: "Get the current weather for a location",
129
+ validator: z.object({
130
+ city: z.string().describe("The city name"),
131
+ units: z.enum(["celsius", "fahrenheit"]).default("celsius"),
132
+ }),
133
+ tool: ({ city, units }) => {
134
+ return { city, temperature: 22, units };
135
+ },
136
+ });
137
+
138
+ const assistant = llm.defineCall<{ query: string }>({
139
+ model: "openai/gpt-4o-mini",
140
+ tools: [getWeather],
141
+ template: ({ query }) => query,
142
+ });
143
+
144
+ let response = await assistant({ query: "What's the weather in Tokyo?" });
145
+
146
+ // Execute tools and resume until no more tool calls
147
+ while (response.toolCalls.length > 0) {
148
+ const toolOutputs = await response.executeTools();
149
+ response = await response.resume(toolOutputs);
150
+ }
151
+
152
+ console.log(response.text());
153
+ ```
154
+
155
+ ### With TypeScript Interface
156
+
157
+ ```typescript
158
+ import { llm } from "mirascope";
159
+
160
+ /**
161
+ * Arguments for the weather tool.
162
+ */
163
+ type WeatherArgs = {
164
+ /** The city name */
165
+ city: string;
166
+ /** Temperature units */
167
+ units: "celsius" | "fahrenheit";
168
+ };
169
+
170
+ const getWeather = llm.defineTool<WeatherArgs>({
171
+ name: "get_weather",
172
+ description: "Get the current weather for a location",
173
+ tool: ({ city, units }) => {
174
+ return { city, temperature: 22, units };
175
+ },
176
+ });
177
+
178
+ const assistant = llm.defineCall<{ query: string }>({
179
+ model: "openai/gpt-4o-mini",
180
+ tools: [getWeather],
181
+ template: ({ query }) => query,
182
+ });
183
+
184
+ let response = await assistant({ query: "What's the weather in Tokyo?" });
185
+
186
+ while (response.toolCalls.length > 0) {
187
+ const toolOutputs = await response.executeTools();
188
+ response = await response.resume(toolOutputs);
189
+ }
190
+
191
+ console.log(response.text());
192
+ ```
193
+
194
+ ## Context
195
+
196
+ Share dependencies (like databases, APIs, etc.) with your tools using context:
197
+
198
+ ```typescript
199
+ import { llm, type Context } from "mirascope";
200
+ import { z } from "zod";
201
+
202
+ interface AppDeps {
203
+ db: { getUser: (id: string) => { name: string } };
204
+ }
205
+
206
+ const getUserInfo = llm.defineContextTool({
207
+ name: "get_user",
208
+ description: "Look up user information",
209
+ validator: z.object({
210
+ userId: z.string().describe("The user ID to look up"),
211
+ }),
212
+ tool: (ctx: Context<AppDeps>, { userId }) => {
213
+ return ctx.deps.db.getUser(userId);
214
+ },
215
+ });
216
+
217
+ const assistant = llm.defineCall<{ ctx: Context<AppDeps>; query: string }>()({
218
+ model: "openai/gpt-4o-mini",
219
+ tools: [getUserInfo],
220
+ template: ({ query }) => query,
221
+ });
222
+
223
+ const ctx = llm.createContext<AppDeps>({ db: myDatabase });
224
+ let response = await assistant(ctx, { query: "Tell me about user 123" });
225
+
226
+ while (response.toolCalls.length > 0) {
227
+ const toolOutputs = await response.executeTools(ctx);
228
+ response = await response.resume(ctx, toolOutputs);
229
+ }
230
+ ```
231
+
232
+ ## Provider Configuration
233
+
234
+ ### Custom API Keys
235
+
236
+ ```typescript
237
+ import { llm } from "mirascope";
238
+
239
+ // Use a different API key
240
+ llm.registerProvider("openai", { apiKey: "sk-my-key" });
241
+
242
+ // Or a custom endpoint
243
+ llm.registerProvider("anthropic", { baseURL: "https://my-proxy.example.com" });
244
+ ```
245
+
246
+ ### OpenAI-Compatible Providers
247
+
248
+ Route any OpenAI-compatible provider through the OpenAI adapter:
249
+
250
+ ```typescript
251
+ import { llm } from "mirascope";
252
+
253
+ // Route grok/ models through xAI's OpenAI-compatible endpoint
254
+ llm.registerProvider("openai", {
255
+ scope: "grok/",
256
+ baseURL: "https://api.x.ai/v1",
257
+ apiKey: process.env.XAI_API_KEY,
258
+ });
259
+
260
+ const response = await llm.model("grok/grok-4-latest").call("Hello!");
261
+ ```
262
+
263
+ ## Transform Plugin
264
+
265
+ The transform plugin extracts type information from TypeScript interfaces at compile time, enabling the native TypeScript patterns (without Zod) for tools and structured output. This is **optional** - you can use Zod schemas without any build configuration.
266
+
267
+ ### Vite
268
+
269
+ ```typescript
270
+ // vite.config.ts
271
+ import { defineConfig } from "vite";
272
+ import { mirascope } from "mirascope/vite";
273
+
274
+ export default defineConfig({
275
+ plugins: [mirascope()],
276
+ });
277
+ ```
278
+
279
+ ### esbuild
280
+
281
+ ```typescript
282
+ import * as esbuild from "esbuild";
283
+ import { mirascope } from "mirascope/esbuild";
284
+
285
+ await esbuild.build({
286
+ entryPoints: ["src/index.ts"],
287
+ bundle: true,
288
+ outfile: "dist/bundle.js",
289
+ plugins: [mirascope()],
290
+ });
291
+ ```
292
+
293
+ ### Bun
294
+
295
+ Bun supports a preload script that applies the transform at runtime:
296
+
297
+ ```typescript
298
+ // preload.ts
299
+ import { mirascope } from "mirascope/bun";
300
+ mirascope();
301
+ ```
302
+
303
+ ```toml
304
+ # bunfig.toml
305
+ preload = ["./preload.ts"]
306
+ ```
307
+
308
+ Now `bun run your-script.ts` will automatically apply the transform.
309
+
310
+ Alternatively, for production builds, use esbuild:
311
+
312
+ ```typescript
313
+ // build.ts
314
+ import { mirascope } from "mirascope/esbuild";
315
+
316
+ await Bun.build({
317
+ entrypoints: ["src/index.ts"],
318
+ outdir: "dist",
319
+ plugins: [mirascope()],
320
+ });
321
+ ```
322
+
323
+ ## Error Handling
324
+
325
+ ```typescript
326
+ import { llm } from "mirascope";
327
+
328
+ try {
329
+ const response = await llm.model("openai/gpt-4o").call("Hello");
330
+ } catch (e) {
331
+ if (e instanceof llm.AuthenticationError) {
332
+ console.log("Invalid API key");
333
+ } else if (e instanceof llm.RateLimitError) {
334
+ console.log("Rate limited - try again later");
335
+ } else if (e instanceof llm.MirascopeError) {
336
+ console.log("LLM error:", e.message);
337
+ }
338
+ }
339
+ ```
340
+
341
+ ## Supported Providers
342
+
343
+ - **Anthropic**: `anthropic/claude-sonnet-4-5`, `anthropic/claude-haiku-4-5`, etc.
344
+ - **OpenAI**: `openai/gpt-4o`, `openai/gpt-4o-mini`, etc.
345
+ - **Google**: `google/gemini-2.0-flash`, `google/gemini-2.5-pro`, etc.
346
+ - **Ollama**: `ollama/llama3.2`, etc. (local models)
347
+ - **Together**: `together/meta-llama/...`, etc.
348
+ - Any OpenAI-compatible provider via `registerProvider`
349
+
350
+ ## Development Setup
351
+
352
+ 1. **Clone and install**:
353
+ ```bash
354
+ cd typescript
355
+ bun install
356
+ ```
357
+
358
+ 2. **Environment variables** (for e2e tests):
359
+ ```bash
360
+ cp .env.example .env
361
+ # Add your API keys
362
+ ```
363
+
364
+ 3. **Commands**:
365
+ ```bash
366
+ bun run typecheck # Type checking
367
+ bun run lint # Linting + formatting
368
+ bun run test # Run tests
369
+ bun run test:coverage # Tests with coverage (requires 100%)
370
+ ```
371
+
372
+ ## Examples
373
+
374
+ See the [`examples/`](./examples) directory for more examples:
375
+
376
+ - `calls/` - Basic and advanced call patterns
377
+ - `tools/` - Tool definition and execution
378
+ - `format/` - Structured output with Zod
379
+ - `streaming/` - Streaming responses
380
+ - `context/` - Sharing dependencies with context
381
+ - `chaining/` - Chaining and parallel calls
382
+ - `reliability/` - Retry and fallback patterns
383
+
384
+ Run an example:
385
+ ```bash
386
+ bun run example examples/calls/basic.ts
387
+ ```
388
+
389
+ ## Contributing
390
+
391
+ We welcome contributions! Please ensure:
392
+
393
+ 1. `bun run typecheck` passes
394
+ 2. `bun run lint` passes
395
+ 3. `bun run test:coverage` shows 100% coverage
396
+
397
+ For more info, see [the contributing page in our docs](https://mirascope.com/docs/contributing).