@jterrazz/intelligence 4.0.3 → 4.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 +89 -89
- package/dist/index.cjs +6 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1455 -0
- package/dist/index.d.ts +1095 -22
- package/dist/index.js +4 -63
- package/dist/index.js.map +1 -1
- package/dist/parse-text.cjs +57 -0
- package/dist/parse-text.cjs.map +1 -0
- package/dist/parse-text.d.cts +18 -0
- package/dist/parse-text.d.ts +18 -0
- package/dist/parse-text.js +52 -0
- package/dist/parse-text.js.map +1 -0
- package/dist/text.cjs +3 -0
- package/dist/text.d.cts +2 -0
- package/dist/text.d.ts +2 -0
- package/dist/text.js +2 -0
- package/package.json +59 -42
package/README.md
CHANGED
|
@@ -15,26 +15,26 @@ npm install @jterrazz/intelligence ai zod
|
|
|
15
15
|
Combines `generateText` + `parseObject` + error classification into a single function that returns a discriminated union result.
|
|
16
16
|
|
|
17
17
|
```typescript
|
|
18
|
-
import { generateStructured, withObservability } from
|
|
19
|
-
import { z } from
|
|
18
|
+
import { generateStructured, withObservability } from '@jterrazz/intelligence';
|
|
19
|
+
import { z } from 'zod';
|
|
20
20
|
|
|
21
21
|
const schema = z.object({
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
sentiment: z.string(),
|
|
23
|
+
score: z.number(),
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
const result = await generateStructured({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
model,
|
|
28
|
+
prompt: 'Analyze this article...',
|
|
29
|
+
schema,
|
|
30
|
+
providerOptions: withObservability({ traceId: 'trace-123' }),
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
if (result.success) {
|
|
34
|
-
|
|
34
|
+
console.log(result.data.sentiment, result.data.score);
|
|
35
35
|
} else {
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
// Typed error with code: TIMEOUT | RATE_LIMITED | PARSING_FAILED | etc.
|
|
37
|
+
console.error(result.error.code, result.error.message);
|
|
38
38
|
}
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -44,23 +44,23 @@ Discriminated union result type for explicit error handling.
|
|
|
44
44
|
|
|
45
45
|
```typescript
|
|
46
46
|
import {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
} from
|
|
47
|
+
generationSuccess,
|
|
48
|
+
generationFailure,
|
|
49
|
+
isSuccess,
|
|
50
|
+
isFailure,
|
|
51
|
+
unwrap,
|
|
52
|
+
unwrapOr,
|
|
53
|
+
classifyError,
|
|
54
|
+
type GenerationResult,
|
|
55
|
+
} from '@jterrazz/intelligence';
|
|
56
56
|
|
|
57
57
|
// Create results
|
|
58
|
-
const success = generationSuccess({ data:
|
|
59
|
-
const failure = generationFailure(
|
|
58
|
+
const success = generationSuccess({ data: 'value' });
|
|
59
|
+
const failure = generationFailure('TIMEOUT', 'Request timed out');
|
|
60
60
|
|
|
61
61
|
// Type guards
|
|
62
62
|
if (isSuccess(result)) {
|
|
63
|
-
|
|
63
|
+
console.log(result.data);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
// Unwrap with default
|
|
@@ -68,9 +68,9 @@ const value = unwrapOr(result, defaultValue);
|
|
|
68
68
|
|
|
69
69
|
// Classify errors automatically
|
|
70
70
|
try {
|
|
71
|
-
|
|
71
|
+
await someOperation();
|
|
72
72
|
} catch (error) {
|
|
73
|
-
|
|
73
|
+
const code = classifyError(error); // TIMEOUT, RATE_LIMITED, PARSING_FAILED, etc.
|
|
74
74
|
}
|
|
75
75
|
```
|
|
76
76
|
|
|
@@ -81,26 +81,26 @@ Composable middlewares that wrap AI SDK models. Stack them together for logging,
|
|
|
81
81
|
### Composing Middlewares
|
|
82
82
|
|
|
83
83
|
```typescript
|
|
84
|
-
import { wrapLanguageModel } from
|
|
84
|
+
import { wrapLanguageModel } from 'ai';
|
|
85
85
|
import {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
} from
|
|
86
|
+
createLoggingMiddleware,
|
|
87
|
+
createObservabilityMiddleware,
|
|
88
|
+
LangfuseAdapter,
|
|
89
|
+
OpenRouterMetadataAdapter,
|
|
90
|
+
} from '@jterrazz/intelligence';
|
|
91
91
|
|
|
92
92
|
const model = wrapLanguageModel({
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
+
],
|
|
104
104
|
});
|
|
105
105
|
```
|
|
106
106
|
|
|
@@ -109,22 +109,22 @@ const model = wrapLanguageModel({
|
|
|
109
109
|
Logs AI SDK requests with timing, usage, and optional content.
|
|
110
110
|
|
|
111
111
|
```typescript
|
|
112
|
-
import { wrapLanguageModel, generateText } from
|
|
113
|
-
import { createLoggingMiddleware } from
|
|
112
|
+
import { wrapLanguageModel, generateText } from 'ai';
|
|
113
|
+
import { createLoggingMiddleware } from '@jterrazz/intelligence';
|
|
114
114
|
|
|
115
115
|
const model = wrapLanguageModel({
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
125
|
});
|
|
126
126
|
|
|
127
|
-
await generateText({ model, prompt:
|
|
127
|
+
await generateText({ model, prompt: 'Hello!' });
|
|
128
128
|
// Logs: ai.generate.start, ai.generate.complete (with durationMs, usage, etc.)
|
|
129
129
|
```
|
|
130
130
|
|
|
@@ -133,32 +133,32 @@ await generateText({ model, prompt: "Hello!" });
|
|
|
133
133
|
Sends generation data to observability platforms (Langfuse, etc.).
|
|
134
134
|
|
|
135
135
|
```typescript
|
|
136
|
-
import { wrapLanguageModel, generateText } from
|
|
136
|
+
import { wrapLanguageModel, generateText } from 'ai';
|
|
137
137
|
import {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
} from
|
|
138
|
+
createObservabilityMiddleware,
|
|
139
|
+
withObservability,
|
|
140
|
+
LangfuseAdapter,
|
|
141
|
+
} from '@jterrazz/intelligence';
|
|
142
142
|
|
|
143
143
|
const observability = new LangfuseAdapter({
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
secretKey: process.env.LANGFUSE_SECRET_KEY,
|
|
145
|
+
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
|
|
146
146
|
});
|
|
147
147
|
|
|
148
148
|
const model = wrapLanguageModel({
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
model: provider.model('anthropic/claude-sonnet-4-20250514'),
|
|
150
|
+
middleware: createObservabilityMiddleware({ observability }),
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
// Use withObservability() helper for type-safe metadata
|
|
154
154
|
await generateText({
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
155
|
+
model,
|
|
156
|
+
prompt: 'Analyze this...',
|
|
157
|
+
providerOptions: withObservability({
|
|
158
|
+
traceId: 'trace-123',
|
|
159
|
+
name: 'analyzer',
|
|
160
|
+
metadata: { userId: 'user-1' },
|
|
161
|
+
}),
|
|
162
162
|
});
|
|
163
163
|
```
|
|
164
164
|
|
|
@@ -192,12 +192,12 @@ class AnthropicMetadataAdapter implements ProviderMetadataPort {
|
|
|
192
192
|
Extracts and validates JSON from messy AI outputs (markdown blocks, malformed syntax).
|
|
193
193
|
|
|
194
194
|
````typescript
|
|
195
|
-
import { parseObject } from
|
|
196
|
-
import { z } from
|
|
195
|
+
import { parseObject } from '@jterrazz/intelligence';
|
|
196
|
+
import { z } from 'zod';
|
|
197
197
|
|
|
198
198
|
const schema = z.object({
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
title: z.string(),
|
|
200
|
+
tags: z.array(z.string()),
|
|
201
201
|
});
|
|
202
202
|
|
|
203
203
|
const text = '```json\n{"title": "Hello", "tags": ["ai"]}\n```';
|
|
@@ -210,16 +210,16 @@ const result = parseObject(text, schema);
|
|
|
210
210
|
Creates system prompt instructions for models without native structured output.
|
|
211
211
|
|
|
212
212
|
```typescript
|
|
213
|
-
import { generateText } from
|
|
214
|
-
import { createSchemaPrompt, parseObject } from
|
|
215
|
-
import { z } from
|
|
213
|
+
import { generateText } from 'ai';
|
|
214
|
+
import { createSchemaPrompt, parseObject } from '@jterrazz/intelligence';
|
|
215
|
+
import { z } from 'zod';
|
|
216
216
|
|
|
217
217
|
const schema = z.object({ summary: z.string(), score: z.number() });
|
|
218
218
|
|
|
219
219
|
const { text } = await generateText({
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
model,
|
|
221
|
+
prompt: 'Analyze this article...',
|
|
222
|
+
system: createSchemaPrompt(schema),
|
|
223
223
|
});
|
|
224
224
|
|
|
225
225
|
const result = parseObject(text, schema);
|
|
@@ -230,7 +230,7 @@ const result = parseObject(text, schema);
|
|
|
230
230
|
Removes invisible characters, normalizes typography, cleans AI artifacts.
|
|
231
231
|
|
|
232
232
|
```typescript
|
|
233
|
-
import { parseText } from
|
|
233
|
+
import { parseText } from '@jterrazz/intelligence';
|
|
234
234
|
|
|
235
235
|
const clean = parseText(messyAiOutput);
|
|
236
236
|
// Removes: BOM, zero-width chars, citation markers
|
|
@@ -242,22 +242,22 @@ const clean = parseText(messyAiOutput);
|
|
|
242
242
|
### `createOpenRouterProvider` - OpenRouter for AI SDK
|
|
243
243
|
|
|
244
244
|
```typescript
|
|
245
|
-
import { generateText } from
|
|
246
|
-
import { createOpenRouterProvider } from
|
|
245
|
+
import { generateText } from 'ai';
|
|
246
|
+
import { createOpenRouterProvider } from '@jterrazz/intelligence';
|
|
247
247
|
|
|
248
248
|
const provider = createOpenRouterProvider({
|
|
249
|
-
|
|
249
|
+
apiKey: process.env.OPENROUTER_API_KEY,
|
|
250
250
|
});
|
|
251
251
|
|
|
252
252
|
const { text } = await generateText({
|
|
253
|
-
|
|
254
|
-
|
|
253
|
+
model: provider.model('anthropic/claude-sonnet-4-20250514'),
|
|
254
|
+
prompt: 'Hello!',
|
|
255
255
|
});
|
|
256
256
|
|
|
257
257
|
// With reasoning models
|
|
258
|
-
const reasoningModel = provider.model(
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
const reasoningModel = provider.model('anthropic/claude-sonnet-4-20250514', {
|
|
259
|
+
maxTokens: 16000,
|
|
260
|
+
reasoning: { effort: 'high' },
|
|
261
261
|
});
|
|
262
262
|
```
|
|
263
263
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_parse_text = require("./parse-text.cjs");
|
|
1
3
|
let langfuse = require("langfuse");
|
|
2
4
|
let ai = require("ai");
|
|
3
5
|
let jsonrepair = require("jsonrepair");
|
|
4
6
|
let zod_v4 = require("zod/v4");
|
|
5
7
|
let _openrouter_ai_sdk_provider = require("@openrouter/ai-sdk-provider");
|
|
6
8
|
let _ai_sdk_openai = require("@ai-sdk/openai");
|
|
7
|
-
|
|
8
9
|
//#region src/logging/logging.middleware.ts
|
|
9
10
|
/**
|
|
10
11
|
* Creates middleware that logs AI SDK requests and responses.
|
|
@@ -78,7 +79,6 @@ function createLoggingMiddleware(options) {
|
|
|
78
79
|
}
|
|
79
80
|
};
|
|
80
81
|
}
|
|
81
|
-
|
|
82
82
|
//#endregion
|
|
83
83
|
//#region src/observability/observability.middleware.ts
|
|
84
84
|
/**
|
|
@@ -150,7 +150,6 @@ function createObservabilityMiddleware(options) {
|
|
|
150
150
|
}
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
|
-
|
|
154
153
|
//#endregion
|
|
155
154
|
//#region src/observability/langfuse.adapter.ts
|
|
156
155
|
/**
|
|
@@ -208,7 +207,6 @@ var LangfuseAdapter = class {
|
|
|
208
207
|
});
|
|
209
208
|
}
|
|
210
209
|
};
|
|
211
|
-
|
|
212
210
|
//#endregion
|
|
213
211
|
//#region src/observability/noop.adapter.ts
|
|
214
212
|
/**
|
|
@@ -221,7 +219,6 @@ var NoopObservabilityAdapter = class {
|
|
|
221
219
|
async shutdown() {}
|
|
222
220
|
trace(_params) {}
|
|
223
221
|
};
|
|
224
|
-
|
|
225
222
|
//#endregion
|
|
226
223
|
//#region src/result/result.ts
|
|
227
224
|
/**
|
|
@@ -284,7 +281,6 @@ function unwrap(result) {
|
|
|
284
281
|
function unwrapOr(result, defaultValue) {
|
|
285
282
|
return result.success ? result.data : defaultValue;
|
|
286
283
|
}
|
|
287
|
-
|
|
288
284
|
//#endregion
|
|
289
285
|
//#region src/parsing/parse-object.ts
|
|
290
286
|
const MARKDOWN_CODE_BLOCK_RE = /```(?:json)?\r?\n([^`]*?)\r?\n```/g;
|
|
@@ -294,6 +290,8 @@ const MARKDOWN_CODE_BLOCK_RE = /```(?:json)?\r?\n([^`]*?)\r?\n```/g;
|
|
|
294
290
|
*/
|
|
295
291
|
var ParseObjectError = class extends Error {
|
|
296
292
|
name = "ParseObjectError";
|
|
293
|
+
cause;
|
|
294
|
+
text;
|
|
297
295
|
constructor(message, cause, text) {
|
|
298
296
|
super(message);
|
|
299
297
|
this.cause = cause;
|
|
@@ -435,7 +433,6 @@ function parseObject(text, schema) {
|
|
|
435
433
|
throw error;
|
|
436
434
|
}
|
|
437
435
|
}
|
|
438
|
-
|
|
439
436
|
//#endregion
|
|
440
437
|
//#region src/generation/generate-structured.ts
|
|
441
438
|
/**
|
|
@@ -465,7 +462,6 @@ async function generateStructured(options) {
|
|
|
465
462
|
return generationFailure(classifyError(error), error instanceof Error ? error.message : "Unknown error", error);
|
|
466
463
|
}
|
|
467
464
|
}
|
|
468
|
-
|
|
469
465
|
//#endregion
|
|
470
466
|
//#region src/parsing/create-schema-prompt.ts
|
|
471
467
|
/**
|
|
@@ -521,57 +517,6 @@ ${schemaJson}
|
|
|
521
517
|
Your response must be parseable JSON that validates against this schema. Do not include any text outside the JSON.
|
|
522
518
|
</OUTPUT_FORMAT>`;
|
|
523
519
|
}
|
|
524
|
-
|
|
525
|
-
//#endregion
|
|
526
|
-
//#region src/parsing/parse-text.ts
|
|
527
|
-
const INVISIBLE_CHARS_RE = /[\u00AD\u180E\u200B-\u200C\u200E-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u2069\uFEFF]/g;
|
|
528
|
-
const ASCII_CTRL_RE = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g;
|
|
529
|
-
const SPACE_LIKE_RE = /[\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000]/g;
|
|
530
|
-
const MULTIPLE_SPACES_RE = / {2,}/g;
|
|
531
|
-
const CR_RE = /\r\n?/g;
|
|
532
|
-
const CITATION_RE = / *\(oaicite:\d+\)\{index=\d+\}/g;
|
|
533
|
-
const EM_DASH_SEPARATOR_RE = /\s*[—–―‒]\s*/g;
|
|
534
|
-
const TYPOGRAPHY_REPLACEMENTS = [
|
|
535
|
-
{
|
|
536
|
-
pattern: /[\u2018\u2019\u201A]/g,
|
|
537
|
-
replacement: "'"
|
|
538
|
-
},
|
|
539
|
-
{
|
|
540
|
-
pattern: /[\u201C\u201D\u201E]/g,
|
|
541
|
-
replacement: "\""
|
|
542
|
-
},
|
|
543
|
-
{
|
|
544
|
-
pattern: /\u2026/g,
|
|
545
|
-
replacement: "..."
|
|
546
|
-
},
|
|
547
|
-
{
|
|
548
|
-
pattern: /[\u2022\u25AA-\u25AB\u25B8-\u25B9\u25CF]/g,
|
|
549
|
-
replacement: "-"
|
|
550
|
-
}
|
|
551
|
-
];
|
|
552
|
-
/**
|
|
553
|
-
* Parses and sanitizes text by removing AI artifacts and normalizing typography.
|
|
554
|
-
*
|
|
555
|
-
* @param text - The text to parse
|
|
556
|
-
* @param options - Parsing options
|
|
557
|
-
* @returns The cleaned text
|
|
558
|
-
*/
|
|
559
|
-
function parseText(text, options = {}) {
|
|
560
|
-
const { normalizeEmDashesToCommas = true, collapseSpaces = true } = options;
|
|
561
|
-
if (!text) return "";
|
|
562
|
-
let result = text;
|
|
563
|
-
result = result.replace(CR_RE, "\n");
|
|
564
|
-
result = result.replace(CITATION_RE, "");
|
|
565
|
-
result = result.normalize("NFKC");
|
|
566
|
-
result = result.replace(INVISIBLE_CHARS_RE, "");
|
|
567
|
-
result = result.replace(ASCII_CTRL_RE, "");
|
|
568
|
-
if (normalizeEmDashesToCommas) result = result.replace(EM_DASH_SEPARATOR_RE, ", ");
|
|
569
|
-
result = result.replace(SPACE_LIKE_RE, " ");
|
|
570
|
-
for (const { pattern, replacement } of TYPOGRAPHY_REPLACEMENTS) result = result.replace(pattern, replacement);
|
|
571
|
-
if (collapseSpaces) result = result.replace(MULTIPLE_SPACES_RE, " ").trim();
|
|
572
|
-
return result;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
520
|
//#endregion
|
|
576
521
|
//#region src/provider/openrouter.provider.ts
|
|
577
522
|
/**
|
|
@@ -594,7 +539,6 @@ function createOpenRouterProvider(config) {
|
|
|
594
539
|
});
|
|
595
540
|
} };
|
|
596
541
|
}
|
|
597
|
-
|
|
598
542
|
//#endregion
|
|
599
543
|
//#region src/provider/openrouter-metadata.adapter.ts
|
|
600
544
|
/**
|
|
@@ -617,7 +561,6 @@ var OpenRouterMetadataAdapter = class {
|
|
|
617
561
|
};
|
|
618
562
|
}
|
|
619
563
|
};
|
|
620
|
-
|
|
621
564
|
//#endregion
|
|
622
565
|
//#region src/provider/openai-compatible.provider.ts
|
|
623
566
|
/**
|
|
@@ -633,7 +576,6 @@ function createOpenAICompatibleProvider(config) {
|
|
|
633
576
|
return openai(config.modelMapping?.[name] ?? name);
|
|
634
577
|
} };
|
|
635
578
|
}
|
|
636
|
-
|
|
637
579
|
//#endregion
|
|
638
580
|
//#region src/provider/openai-compatible-metadata.adapter.ts
|
|
639
581
|
/**
|
|
@@ -652,7 +594,6 @@ var OpenAICompatibleMetadataAdapter = class {
|
|
|
652
594
|
} };
|
|
653
595
|
}
|
|
654
596
|
};
|
|
655
|
-
|
|
656
597
|
//#endregion
|
|
657
598
|
exports.LangfuseAdapter = LangfuseAdapter;
|
|
658
599
|
exports.NoopObservabilityAdapter = NoopObservabilityAdapter;
|
|
@@ -671,8 +612,9 @@ exports.generationSuccess = generationSuccess;
|
|
|
671
612
|
exports.isFailure = isFailure;
|
|
672
613
|
exports.isSuccess = isSuccess;
|
|
673
614
|
exports.parseObject = parseObject;
|
|
674
|
-
exports.parseText = parseText;
|
|
615
|
+
exports.parseText = require_parse_text.parseText;
|
|
675
616
|
exports.unwrap = unwrap;
|
|
676
617
|
exports.unwrapOr = unwrapOr;
|
|
677
618
|
exports.withObservability = withObservability;
|
|
619
|
+
|
|
678
620
|
//# sourceMappingURL=index.cjs.map
|