@jterrazz/intelligence 3.0.2 → 4.0.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 (34) hide show
  1. package/README.md +260 -63
  2. package/dist/index.cjs +594 -808
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.ts +352 -5
  5. package/dist/index.js +620 -5
  6. package/dist/index.js.map +1 -1
  7. package/package.json +26 -20
  8. package/dist/middleware/__tests__/logging.middleware.test.d.ts +0 -1
  9. package/dist/middleware/__tests__/logging.middleware.test.js +0 -463
  10. package/dist/middleware/__tests__/logging.middleware.test.js.map +0 -1
  11. package/dist/middleware/logging.middleware.d.ts +0 -29
  12. package/dist/middleware/logging.middleware.js +0 -298
  13. package/dist/middleware/logging.middleware.js.map +0 -1
  14. package/dist/parsing/__tests__/create-schema-prompt.test.d.ts +0 -1
  15. package/dist/parsing/__tests__/create-schema-prompt.test.js +0 -53
  16. package/dist/parsing/__tests__/create-schema-prompt.test.js.map +0 -1
  17. package/dist/parsing/__tests__/parse-object.test.d.ts +0 -1
  18. package/dist/parsing/__tests__/parse-object.test.js +0 -433
  19. package/dist/parsing/__tests__/parse-object.test.js.map +0 -1
  20. package/dist/parsing/__tests__/parse-text.test.d.ts +0 -1
  21. package/dist/parsing/__tests__/parse-text.test.js +0 -167
  22. package/dist/parsing/__tests__/parse-text.test.js.map +0 -1
  23. package/dist/parsing/create-schema-prompt.d.ts +0 -28
  24. package/dist/parsing/create-schema-prompt.js +0 -42
  25. package/dist/parsing/create-schema-prompt.js.map +0 -1
  26. package/dist/parsing/parse-object.d.ts +0 -33
  27. package/dist/parsing/parse-object.js +0 -383
  28. package/dist/parsing/parse-object.js.map +0 -1
  29. package/dist/parsing/parse-text.d.ts +0 -14
  30. package/dist/parsing/parse-text.js +0 -76
  31. package/dist/parsing/parse-text.js.map +0 -1
  32. package/dist/providers/openrouter.provider.d.ts +0 -36
  33. package/dist/providers/openrouter.provider.js +0 -58
  34. package/dist/providers/openrouter.provider.js.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @jterrazz/intelligence
2
2
 
3
- Lightweight utilities for AI SDK apps structured output parsing, text sanitization, and provider helpers.
3
+ Lightweight, composable utilities for AI SDK apps - middleware for logging and observability, structured output parsing, result handling, and provider helpers.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,112 +8,309 @@ Lightweight utilities for AI SDK apps — structured output parsing, text saniti
8
8
  npm install @jterrazz/intelligence ai zod
9
9
  ```
10
10
 
11
- ## Parsing Utilities
11
+ ## Generation
12
12
 
13
- ### `parseObject` Extract structured data from AI responses
13
+ ### `generateStructured` - Type-safe structured generation with error handling
14
14
 
15
- Extracts and validates JSON from messy AI outputs (markdown blocks, embedded JSON, malformed syntax).
15
+ Combines `generateText` + `parseObject` + error classification into a single function that returns a discriminated union result.
16
16
 
17
17
  ```typescript
18
- import { parseObject } from '@jterrazz/intelligence';
19
- import { z } from 'zod';
18
+ import { generateStructured, withObservability } from "@jterrazz/intelligence";
19
+ import { z } from "zod";
20
20
 
21
21
  const schema = z.object({
22
- title: z.string(),
23
- tags: z.array(z.string()),
22
+ sentiment: z.string(),
23
+ score: z.number(),
24
24
  });
25
25
 
26
- // Handles markdown code blocks, embedded JSON, trailing commas, etc.
27
- const text = '```json\n{"title": "Hello", "tags": ["ai", "typescript"]}\n```';
28
- const result = parseObject(text, schema);
29
- // → { title: 'Hello', tags: ['ai', 'typescript'] }
26
+ const result = await generateStructured({
27
+ model,
28
+ prompt: "Analyze this article...",
29
+ schema,
30
+ providerOptions: withObservability({ traceId: "trace-123" }),
31
+ });
32
+
33
+ if (result.success) {
34
+ console.log(result.data.sentiment, result.data.score);
35
+ } else {
36
+ // Typed error with code: TIMEOUT | RATE_LIMITED | PARSING_FAILED | etc.
37
+ console.error(result.error.code, result.error.message);
38
+ }
30
39
  ```
31
40
 
32
- ### `createSchemaPrompt` — Generate schema instructions for prompts
41
+ ## Result Utilities
33
42
 
34
- Creates system prompt instructions for models that don't support native structured outputs.
43
+ Discriminated union result type for explicit error handling.
35
44
 
36
45
  ```typescript
37
- import { generateText } from 'ai';
38
- import { createSchemaPrompt, parseObject } from '@jterrazz/intelligence';
39
- import { z } from 'zod';
46
+ import {
47
+ generationSuccess,
48
+ generationFailure,
49
+ isSuccess,
50
+ isFailure,
51
+ unwrap,
52
+ unwrapOr,
53
+ classifyError,
54
+ type GenerationResult,
55
+ } from "@jterrazz/intelligence";
56
+
57
+ // Create results
58
+ const success = generationSuccess({ data: "value" });
59
+ const failure = generationFailure("TIMEOUT", "Request timed out");
60
+
61
+ // Type guards
62
+ if (isSuccess(result)) {
63
+ console.log(result.data);
64
+ }
65
+
66
+ // Unwrap with default
67
+ const value = unwrapOr(result, defaultValue);
68
+
69
+ // Classify errors automatically
70
+ try {
71
+ await someOperation();
72
+ } catch (error) {
73
+ const code = classifyError(error); // TIMEOUT, RATE_LIMITED, PARSING_FAILED, etc.
74
+ }
75
+ ```
40
76
 
41
- const schema = z.object({ summary: z.string(), score: z.number() });
77
+ ## Middleware
42
78
 
43
- const { text } = await generateText({
44
- model,
45
- prompt: 'Analyze this article...',
46
- system: createSchemaPrompt(schema), // Injects JSON schema instructions
79
+ Composable middlewares that wrap AI SDK models. Stack them together for logging, observability, and more.
80
+
81
+ ### Composing Middlewares
82
+
83
+ ```typescript
84
+ import { wrapLanguageModel } from "ai";
85
+ import {
86
+ createLoggingMiddleware,
87
+ createObservabilityMiddleware,
88
+ LangfuseAdapter,
89
+ OpenRouterMetadataAdapter,
90
+ } from "@jterrazz/intelligence";
91
+
92
+ const model = wrapLanguageModel({
93
+ model: provider.model("anthropic/claude-sonnet-4-20250514"),
94
+ middleware: [
95
+ createLoggingMiddleware({ logger, include: { usage: true } }),
96
+ createObservabilityMiddleware({
97
+ observability: new LangfuseAdapter({
98
+ secretKey: process.env.LANGFUSE_SECRET_KEY,
99
+ publicKey: process.env.LANGFUSE_PUBLIC_KEY,
100
+ }),
101
+ providerMetadata: new OpenRouterMetadataAdapter(),
102
+ }),
103
+ ],
47
104
  });
105
+ ```
48
106
 
49
- const result = parseObject(text, schema);
107
+ ### Logging Middleware
108
+
109
+ Logs AI SDK requests with timing, usage, and optional content.
110
+
111
+ ```typescript
112
+ import { wrapLanguageModel, generateText } from "ai";
113
+ import { createLoggingMiddleware } from "@jterrazz/intelligence";
114
+
115
+ const model = wrapLanguageModel({
116
+ model: provider.model("anthropic/claude-sonnet-4-20250514"),
117
+ middleware: createLoggingMiddleware({
118
+ logger,
119
+ include: {
120
+ params: false, // Log request params
121
+ content: false, // Log response content
122
+ usage: true, // Log token usage (default: true)
123
+ },
124
+ }),
125
+ });
126
+
127
+ await generateText({ model, prompt: "Hello!" });
128
+ // Logs: ai.generate.start, ai.generate.complete (with durationMs, usage, etc.)
50
129
  ```
51
130
 
52
- ### `parseText` — Sanitize AI-generated text
131
+ ### Observability Middleware
53
132
 
54
- Removes invisible characters, normalizes typography, and cleans common AI artifacts.
133
+ Sends generation data to observability platforms (Langfuse, etc.).
55
134
 
56
135
  ```typescript
57
- import { parseText } from '@jterrazz/intelligence';
136
+ import { wrapLanguageModel, generateText } from "ai";
137
+ import {
138
+ createObservabilityMiddleware,
139
+ withObservability,
140
+ LangfuseAdapter,
141
+ } from "@jterrazz/intelligence";
142
+
143
+ const observability = new LangfuseAdapter({
144
+ secretKey: process.env.LANGFUSE_SECRET_KEY,
145
+ publicKey: process.env.LANGFUSE_PUBLIC_KEY,
146
+ });
58
147
 
59
- const clean = parseText(messyAiOutput);
60
- // Removes: BOM, zero-width chars, AI citation markers
61
- // Normalizes: smart quotes → straight, em dashes → ", ", ellipsis → ...
62
- // Collapses multiple spaces and trims
63
-
64
- // Options
65
- parseText(text, {
66
- normalizeEmDashesToCommas: true, // Convert em/en dashes to ", " (default: true)
67
- collapseSpaces: true, // Collapse multiple spaces, trim (default: true)
148
+ const model = wrapLanguageModel({
149
+ model: provider.model("anthropic/claude-sonnet-4-20250514"),
150
+ middleware: createObservabilityMiddleware({ observability }),
151
+ });
152
+
153
+ // Use withObservability() helper for type-safe metadata
154
+ await generateText({
155
+ model,
156
+ prompt: "Analyze this...",
157
+ providerOptions: withObservability({
158
+ traceId: "trace-123",
159
+ name: "analyzer",
160
+ metadata: { userId: "user-1" },
161
+ }),
68
162
  });
69
163
  ```
70
164
 
71
- ## Provider
165
+ ### Custom Adapters
72
166
 
73
- ### `createOpenRouterProvider` OpenRouter for AI SDK
167
+ Implement ports to integrate with any platform:
74
168
 
75
169
  ```typescript
76
- import { generateText } from 'ai';
77
- import { createOpenRouterProvider } from '@jterrazz/intelligence';
170
+ import type { ObservabilityPort, ProviderMetadataPort } from "@jterrazz/intelligence";
171
+
172
+ // Observability adapter (Datadog, etc.)
173
+ class DatadogAdapter implements ObservabilityPort {
174
+ trace(params) { /* ... */ }
175
+ generation(params) { /* ... */ }
176
+ async flush() { /* ... */ }
177
+ async shutdown() { /* ... */ }
178
+ }
179
+
180
+ // Provider metadata adapter (extract usage/cost)
181
+ class AnthropicMetadataAdapter implements ProviderMetadataPort {
182
+ extract(metadata) {
183
+ return { usage: { ... }, cost: { ... } };
184
+ }
185
+ }
186
+ ```
78
187
 
79
- const provider = createOpenRouterProvider({
80
- apiKey: process.env.OPENROUTER_API_KEY,
188
+ ## Parsing Utilities
189
+
190
+ ### `parseObject` - Extract structured data from AI responses
191
+
192
+ Extracts and validates JSON from messy AI outputs (markdown blocks, malformed syntax).
193
+
194
+ ````typescript
195
+ import { parseObject } from "@jterrazz/intelligence";
196
+ import { z } from "zod";
197
+
198
+ const schema = z.object({
199
+ title: z.string(),
200
+ tags: z.array(z.string()),
81
201
  });
82
202
 
203
+ const text = '```json\n{"title": "Hello", "tags": ["ai"]}\n```';
204
+ const result = parseObject(text, schema);
205
+ // { title: "Hello", tags: ["ai"] }
206
+ ````
207
+
208
+ ### `createSchemaPrompt` - Generate schema instructions
209
+
210
+ Creates system prompt instructions for models without native structured output.
211
+
212
+ ```typescript
213
+ import { generateText } from "ai";
214
+ import { createSchemaPrompt, parseObject } from "@jterrazz/intelligence";
215
+ import { z } from "zod";
216
+
217
+ const schema = z.object({ summary: z.string(), score: z.number() });
218
+
83
219
  const { text } = await generateText({
84
- model: provider.model('anthropic/claude-sonnet-4-20250514'),
85
- prompt: 'Hello!',
220
+ model,
221
+ prompt: "Analyze this article...",
222
+ system: createSchemaPrompt(schema),
86
223
  });
224
+
225
+ const result = parseObject(text, schema);
87
226
  ```
88
227
 
89
- With reasoning models:
228
+ ### `parseText` - Sanitize AI-generated text
229
+
230
+ Removes invisible characters, normalizes typography, cleans AI artifacts.
90
231
 
91
232
  ```typescript
92
- const model = provider.model('anthropic/claude-sonnet-4-20250514', {
93
- maxTokens: 16000,
94
- reasoning: { effort: 'high' },
95
- });
233
+ import { parseText } from "@jterrazz/intelligence";
234
+
235
+ const clean = parseText(messyAiOutput);
236
+ // Removes: BOM, zero-width chars, citation markers
237
+ // Normalizes: smart quotes, em dashes, ellipsis
96
238
  ```
97
239
 
98
- ## Middleware
240
+ ## Provider
99
241
 
100
- ### `createLoggingMiddleware` Log AI SDK requests
242
+ ### `createOpenRouterProvider` - OpenRouter for AI SDK
101
243
 
102
244
  ```typescript
103
- import { wrapLanguageModel } from 'ai';
104
- import { createLoggingMiddleware } from '@jterrazz/intelligence';
245
+ import { generateText } from "ai";
246
+ import { createOpenRouterProvider } from "@jterrazz/intelligence";
105
247
 
106
- const model = wrapLanguageModel({
107
- model: provider.model('anthropic/claude-sonnet-4-20250514'),
108
- middleware: createLoggingMiddleware({
109
- logger, // Any logger with debug/error methods
110
- include: {
111
- params: false, // Include request params (default: false)
112
- content: false, // Include response content (default: false)
113
- usage: true, // Include token usage (default: true)
114
- },
115
- }),
248
+ const provider = createOpenRouterProvider({
249
+ apiKey: process.env.OPENROUTER_API_KEY,
250
+ });
251
+
252
+ const { text } = await generateText({
253
+ model: provider.model("anthropic/claude-sonnet-4-20250514"),
254
+ prompt: "Hello!",
255
+ });
256
+
257
+ // With reasoning models
258
+ const reasoningModel = provider.model("anthropic/claude-sonnet-4-20250514", {
259
+ maxTokens: 16000,
260
+ reasoning: { effort: "high" },
116
261
  });
117
262
  ```
118
263
 
119
- Happy coding! 🚀
264
+ ## API Reference
265
+
266
+ ### Generation
267
+
268
+ | Export | Description |
269
+ | ----------------------------- | ------------------------------------------------------ |
270
+ | `generateStructured(options)` | Generate and parse structured data with error handling |
271
+
272
+ ### Result
273
+
274
+ | Export | Description |
275
+ | ------------------------------------------ | -------------------------------------------------------- |
276
+ | `GenerationResult<T>` | Discriminated union result type |
277
+ | `generationSuccess(data)` | Create success result |
278
+ | `generationFailure(code, message, cause?)` | Create failure result |
279
+ | `isSuccess(result)` | Type guard for success |
280
+ | `isFailure(result)` | Type guard for failure |
281
+ | `unwrap(result)` | Extract data or throw |
282
+ | `unwrapOr(result, default)` | Extract data or return default |
283
+ | `classifyError(error)` | Classify error into error code |
284
+ | `GenerationErrorCode` | Error codes: TIMEOUT, RATE_LIMITED, PARSING_FAILED, etc. |
285
+
286
+ ### Middleware
287
+
288
+ | Export | Description |
289
+ | ---------------------------------------- | -------------------------------------------- |
290
+ | `createLoggingMiddleware(options)` | Creates logging middleware |
291
+ | `createObservabilityMiddleware(options)` | Creates observability middleware |
292
+ | `withObservability(meta)` | Helper for type-safe observability metadata |
293
+ | `LangfuseAdapter` | Langfuse implementation of ObservabilityPort |
294
+ | `NoopObservabilityAdapter` | No-op adapter for testing/development |
295
+ | `OpenRouterMetadataAdapter` | Extract usage/cost from OpenRouter |
296
+
297
+ ### Ports
298
+
299
+ | Export | Description |
300
+ | ---------------------- | ------------------------------------------ |
301
+ | `ObservabilityPort` | Interface for observability adapters |
302
+ | `ProviderMetadataPort` | Interface for provider metadata extraction |
303
+
304
+ ### Parsing
305
+
306
+ | Export | Description |
307
+ | ---------------------------- | ---------------------------------------- |
308
+ | `parseObject(text, schema)` | Parse and validate JSON from AI output |
309
+ | `createSchemaPrompt(schema)` | Generate schema instructions for prompts |
310
+ | `parseText(text, options?)` | Sanitize AI-generated text |
311
+
312
+ ### Provider
313
+
314
+ | Export | Description |
315
+ | ---------------------------------- | ------------------------------------- |
316
+ | `createOpenRouterProvider(config)` | Create OpenRouter provider for AI SDK |