@future-explorer/lib 1.0.10 → 1.0.12

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 CHANGED
@@ -87,10 +87,9 @@ const SentimentSchema = z.object({
87
87
  });
88
88
 
89
89
  // Generate structured response
90
- const result = await client.generateStructuredResponse({
91
- schema: SentimentSchema,
92
- userPrompt: 'I absolutely love this product!',
93
- systemMessage: 'You are a sentiment analysis expert.',
90
+ const result = await client.generateStructuredResponse(SentimentSchema, {
91
+ prompt: 'I absolutely love this product!',
92
+ system: 'You are a sentiment analysis expert.',
94
93
  });
95
94
 
96
95
  console.log(result.sentiment); // 'positive'
@@ -108,9 +107,52 @@ console.log(result.summary); // '...'
108
107
 
109
108
  ### Methods
110
109
 
111
- - `generateStructuredResponse<T>(params: GenerateObjectParams<T>)`: Generates a structured response matching the Zod schema. Accepts `schema`, `userPrompt`, `systemMessage`, plus any additional `generateObject()` options
110
+ - `generateStructuredResponse<T>(schema, params, usageTracker?)`: Generates a structured response matching the Zod schema. Accepts `prompt`, `system`, plus any additional options. Optionally pass an `AiUsageTracker` to record usage.
112
111
  - `getModel()`: Returns the underlying LanguageModel instance
113
112
 
113
+ ## AiUsageTracker
114
+
115
+ Tracks and accumulates AI usage costs across multiple `generateStructuredResponse()` calls. Useful for calculating the total cost of processing a single input that requires multiple AI calls.
116
+
117
+ ### Basic Usage
118
+
119
+ ```typescript
120
+ import { UnifiedAiClient, AiUsageTracker, Provider } from '@future-explorer/lib';
121
+ import { z } from 'zod';
122
+
123
+ const client = new UnifiedAiClient(Provider.XAI);
124
+ const tracker = new AiUsageTracker();
125
+
126
+ const Schema = z.object({ summary: z.string() });
127
+
128
+ // Each call automatically records usage in the tracker
129
+ await client.generateStructuredResponse(Schema, { prompt: 'First call...' }, tracker);
130
+ await client.generateStructuredResponse(Schema, { prompt: 'Second call...' }, tracker);
131
+
132
+ // Get accumulated results
133
+ console.log(tracker.getSummary());
134
+ // AI Usage: 2 call(s), $0.001234 estimated
135
+ // Tokens - input: 500, output: 200, reasoning: 0, total: 700
136
+ // [xai/grok-4-1-fast-reasoning] in=250 out=100 $0.000617 3200ms
137
+ // [xai/grok-4-1-fast-reasoning] in=250 out=100 $0.000617 2800ms
138
+
139
+ console.log(tracker.getTotalCost()); // 0.001234
140
+ console.log(tracker.getTotalTokens()); // { input: 500, output: 200, reasoning: 0, total: 700 }
141
+ console.log(tracker.getCalls()); // AiCallUsage[]
142
+ ```
143
+
144
+ ### Supported Models
145
+
146
+ Built-in pricing for cost estimation (easily extensible):
147
+
148
+ | Provider | Models |
149
+ | -------- | ------ |
150
+ | xAI | grok-4-1-fast, grok-4-fast, grok-4, grok-3, grok-3-mini, grok-2 |
151
+ | OpenAI | gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, gpt-4o, gpt-4o-mini, o3, o3-mini, o4-mini |
152
+ | Gemini | gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, gemini-2.0-flash |
153
+
154
+ Model IDs are matched by substring, so `grok-4-1-fast-reasoning` matches the `grok-4-1-fast` pricing entry.
155
+
114
156
  ## Development
115
157
 
116
158
  ### Build
@@ -163,6 +205,20 @@ npm publish
163
205
 
164
206
  ## Changelog
165
207
 
208
+ ### 1.0.12
209
+
210
+ - Added `AiUsageTracker` for tracking AI usage costs across multiple calls
211
+ - `generateStructuredResponse()` now accepts optional `usageTracker` parameter
212
+
213
+ ### 1.0.11
214
+
215
+ - Moved `schema` out of `GenerateObjectParams` into a separate parameter
216
+ - Renamed `userPrompt`/`systemMessage` to `prompt`/`system`
217
+
218
+ ### 1.0.10
219
+
220
+ - Refactored `generateStructuredResponse()` to accept a single `GenerateObjectParams<T>` object
221
+
166
222
  ### 1.0.7
167
223
 
168
224
  - Updated peer dependency to zod 4.2.x
@@ -1,5 +1,6 @@
1
1
  export * from './grok';
2
2
  export * from './shared';
3
+ export * from './unified/ai-usage-tracker';
3
4
  export * from './unified/unified-ai-client';
4
5
  export * from './unified/unified-ai-client.model';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/clients/ai/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/clients/ai/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC"}
@@ -16,5 +16,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./grok"), exports);
18
18
  __exportStar(require("./shared"), exports);
19
+ __exportStar(require("./unified/ai-usage-tracker"), exports);
19
20
  __exportStar(require("./unified/unified-ai-client"), exports);
20
21
  __exportStar(require("./unified/unified-ai-client.model"), exports);
@@ -0,0 +1,34 @@
1
+ import { LanguageModelUsage } from 'ai';
2
+ export interface AiCallUsage {
3
+ provider: string;
4
+ model: string;
5
+ inputTokens: number;
6
+ outputTokens: number;
7
+ totalTokens: number;
8
+ reasoningTokens?: number;
9
+ cachedInputTokens?: number;
10
+ estimatedCost: number;
11
+ durationMs: number;
12
+ }
13
+ export interface ModelPricing {
14
+ inputPer1MTokens: number;
15
+ outputPer1MTokens: number;
16
+ reasoningPer1MTokens?: number;
17
+ cachedInputPer1MTokens?: number;
18
+ }
19
+ export declare class AiUsageTracker {
20
+ private calls;
21
+ addCall(call: AiCallUsage): void;
22
+ getCalls(): AiCallUsage[];
23
+ getTotalCost(): number;
24
+ getTotalTokens(): {
25
+ input: number;
26
+ output: number;
27
+ reasoning: number;
28
+ total: number;
29
+ };
30
+ getSummary(): string;
31
+ static findPricing(model: string): ModelPricing | undefined;
32
+ static estimateCost(model: string, usage: LanguageModelUsage): number;
33
+ }
34
+ //# sourceMappingURL=ai-usage-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-usage-tracker.d.ts","sourceRoot":"","sources":["../../../../src/clients/ai/unified/ai-usage-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,IAAI,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AA0BD,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAqB;IAElC,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAIhC,QAAQ,IAAI,WAAW,EAAE;IAIzB,YAAY,IAAI,MAAM;IAItB,cAAc,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAYrF,UAAU,IAAI,MAAM;IAepB,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAe3D,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,MAAM;CAsBtE"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AiUsageTracker = void 0;
4
+ const MODEL_PRICING = {
5
+ // xAI / Grok
6
+ 'grok-4-1-fast': { inputPer1MTokens: 0.2, outputPer1MTokens: 0.5, reasoningPer1MTokens: 0.5, cachedInputPer1MTokens: 0.05 },
7
+ 'grok-4-fast': { inputPer1MTokens: 0.2, outputPer1MTokens: 0.5, reasoningPer1MTokens: 0.5, cachedInputPer1MTokens: 0.05 },
8
+ 'grok-4': { inputPer1MTokens: 3, outputPer1MTokens: 15, cachedInputPer1MTokens: 0.75 },
9
+ 'grok-3-mini': { inputPer1MTokens: 0.3, outputPer1MTokens: 0.5, reasoningPer1MTokens: 0.5, cachedInputPer1MTokens: 0.075 },
10
+ 'grok-3': { inputPer1MTokens: 3, outputPer1MTokens: 15, cachedInputPer1MTokens: 0.75 },
11
+ 'grok-2': { inputPer1MTokens: 2, outputPer1MTokens: 10 },
12
+ // OpenAI
13
+ 'gpt-4.1': { inputPer1MTokens: 2, outputPer1MTokens: 8, cachedInputPer1MTokens: 0.5 },
14
+ 'gpt-4.1-mini': { inputPer1MTokens: 0.4, outputPer1MTokens: 1.6, cachedInputPer1MTokens: 0.1 },
15
+ 'gpt-4.1-nano': { inputPer1MTokens: 0.1, outputPer1MTokens: 0.4, cachedInputPer1MTokens: 0.025 },
16
+ 'gpt-4o': { inputPer1MTokens: 2.5, outputPer1MTokens: 10, cachedInputPer1MTokens: 1.25 },
17
+ 'gpt-4o-mini': { inputPer1MTokens: 0.15, outputPer1MTokens: 0.6, cachedInputPer1MTokens: 0.075 },
18
+ 'o3': { inputPer1MTokens: 2, outputPer1MTokens: 8, reasoningPer1MTokens: 8, cachedInputPer1MTokens: 0.5 },
19
+ 'o3-mini': { inputPer1MTokens: 1.1, outputPer1MTokens: 4.4, reasoningPer1MTokens: 4.4, cachedInputPer1MTokens: 0.275 },
20
+ 'o4-mini': { inputPer1MTokens: 1.1, outputPer1MTokens: 4.4, reasoningPer1MTokens: 4.4, cachedInputPer1MTokens: 0.275 },
21
+ // Google Gemini
22
+ 'gemini-2.5-pro': { inputPer1MTokens: 1.25, outputPer1MTokens: 10, reasoningPer1MTokens: 10 },
23
+ 'gemini-2.5-flash': { inputPer1MTokens: 0.15, outputPer1MTokens: 0.6, reasoningPer1MTokens: 0.6 },
24
+ 'gemini-2.5-flash-lite': { inputPer1MTokens: 0.1, outputPer1MTokens: 0.4 },
25
+ 'gemini-2.0-flash': { inputPer1MTokens: 0.1, outputPer1MTokens: 0.4 },
26
+ };
27
+ class AiUsageTracker {
28
+ calls = [];
29
+ addCall(call) {
30
+ this.calls.push(call);
31
+ }
32
+ getCalls() {
33
+ return this.calls;
34
+ }
35
+ getTotalCost() {
36
+ return this.calls.reduce((sum, c) => sum + c.estimatedCost, 0);
37
+ }
38
+ getTotalTokens() {
39
+ return this.calls.reduce((acc, c) => ({
40
+ input: acc.input + c.inputTokens,
41
+ output: acc.output + c.outputTokens,
42
+ reasoning: acc.reasoning + (c.reasoningTokens ?? 0),
43
+ total: acc.total + c.totalTokens,
44
+ }), { input: 0, output: 0, reasoning: 0, total: 0 });
45
+ }
46
+ getSummary() {
47
+ const tokens = this.getTotalTokens();
48
+ const cost = this.getTotalCost();
49
+ const lines = [
50
+ `AI Usage: ${this.calls.length} call(s), $${cost.toFixed(6)} estimated`,
51
+ ` Tokens — input: ${tokens.input}, output: ${tokens.output}, reasoning: ${tokens.reasoning}, total: ${tokens.total}`,
52
+ ];
53
+ for (const c of this.calls) {
54
+ lines.push(` [${c.provider}/${c.model}] in=${c.inputTokens} out=${c.outputTokens}${c.reasoningTokens ? ` reasoning=${c.reasoningTokens}` : ''} $${c.estimatedCost.toFixed(6)} ${c.durationMs}ms`);
55
+ }
56
+ return lines.join('\n');
57
+ }
58
+ static findPricing(model) {
59
+ // Exact match first
60
+ if (MODEL_PRICING[model])
61
+ return MODEL_PRICING[model];
62
+ // Substring match — find the longest key that matches
63
+ let bestMatch;
64
+ for (const key of Object.keys(MODEL_PRICING)) {
65
+ if (model.includes(key)) {
66
+ if (!bestMatch || key.length > bestMatch.length) {
67
+ bestMatch = key;
68
+ }
69
+ }
70
+ }
71
+ return bestMatch ? MODEL_PRICING[bestMatch] : undefined;
72
+ }
73
+ static estimateCost(model, usage) {
74
+ const pricing = AiUsageTracker.findPricing(model);
75
+ if (!pricing)
76
+ return 0;
77
+ const inputTokens = usage.inputTokens ?? 0;
78
+ const outputTokens = usage.outputTokens ?? 0;
79
+ const reasoningTokens = usage.reasoningTokens ?? 0;
80
+ const cachedInputTokens = usage.cachedInputTokens ?? 0;
81
+ const billableInputTokens = inputTokens - cachedInputTokens;
82
+ let cost = 0;
83
+ cost += (billableInputTokens / 1_000_000) * pricing.inputPer1MTokens;
84
+ cost += (outputTokens / 1_000_000) * pricing.outputPer1MTokens;
85
+ if (pricing.cachedInputPer1MTokens) {
86
+ cost += (cachedInputTokens / 1_000_000) * pricing.cachedInputPer1MTokens;
87
+ }
88
+ if (pricing.reasoningPer1MTokens) {
89
+ cost += (reasoningTokens / 1_000_000) * pricing.reasoningPer1MTokens;
90
+ }
91
+ return cost;
92
+ }
93
+ }
94
+ exports.AiUsageTracker = AiUsageTracker;
@@ -1,3 +1,4 @@
1
+ export * from './ai-usage-tracker';
1
2
  export * from './unified-ai-client';
2
3
  export * from './unified-ai-client.model';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/clients/ai/unified/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/clients/ai/unified/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC"}
@@ -14,5 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./ai-usage-tracker"), exports);
17
18
  __exportStar(require("./unified-ai-client"), exports);
18
19
  __exportStar(require("./unified-ai-client.model"), exports);
@@ -1,4 +1,6 @@
1
1
  import { LanguageModel } from 'ai';
2
+ import { ZodSchema } from 'zod';
3
+ import { AiUsageTracker } from './ai-usage-tracker';
2
4
  import { GenerateObjectParams, Provider } from './unified-ai-client.model';
3
5
  /**
4
6
  * Unified AI Client that supports multiple AI providers (OpenAI, XAI, Gemini)
@@ -6,14 +8,17 @@ import { GenerateObjectParams, Provider } from './unified-ai-client.model';
6
8
  */
7
9
  export declare class UnifiedAiClient {
8
10
  private model;
11
+ private provider;
9
12
  constructor(provider: Provider);
10
13
  /**
11
14
  * Generates a structured response from the AI model based on a Zod schema.
12
15
  *
13
16
  * @template T - The type inferred from the Zod schema
14
17
  *
15
- * @param params - Configuration object for the structured response generation.
16
- * See {@link GenerateObjectParams} for all available options.
18
+ * @param schema - Zod schema defining the expected response structure.
19
+ * The AI model will be constrained to return data matching this schema.
20
+ * @param params - Configuration object with prompt, system message, and any additional options.
21
+ * See {@link GenerateObjectParams} for all available options.
17
22
  *
18
23
  * @returns Promise resolving to the validated object matching the schema type T
19
24
  *
@@ -29,16 +34,15 @@ export declare class UnifiedAiClient {
29
34
  * });
30
35
  *
31
36
  * // Generate structured response
32
- * const result = await service.generateStructuredResponse({
33
- * schema: SentimentSchema,
34
- * userPrompt: 'I absolutely love this product!',
35
- * systemMessage: 'You are a sentiment analysis expert. Be precise with confidence scores.',
37
+ * const result = await service.generateStructuredResponse(SentimentSchema, {
38
+ * prompt: 'I absolutely love this product!',
39
+ * system: 'You are a sentiment analysis expert. Be precise with confidence scores.',
36
40
  * });
37
41
  *
38
42
  * console.log(result.sentiment); // 'positive'
39
43
  * console.log(result.confidence); // 0.95
40
44
  */
41
- generateStructuredResponse<T>(params: GenerateObjectParams<T>): Promise<T>;
45
+ generateStructuredResponse<T>(schema: ZodSchema<T>, params: GenerateObjectParams<T>, usageTracker?: AiUsageTracker): Promise<T>;
42
46
  /**
43
47
  * Retrieves the underlying LanguageModel instance.
44
48
  * @returns The LanguageModel instance used by the UnifiedAiClient.
@@ -1 +1 @@
1
- {"version":3,"file":"unified-ai-client.d.ts","sourceRoot":"","sources":["../../../../src/clients/ai/unified/unified-ai-client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,aAAa,EAAE,MAAM,IAAI,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE3E;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAgB;gBAEjB,QAAQ,EAAE,QAAQ;IAI9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACG,0BAA0B,CAAC,CAAC,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAchF;;;OAGG;IACH,QAAQ,IAAI,aAAa;IAIzB,OAAO,CAAC,WAAW;CAYpB"}
1
+ {"version":3,"file":"unified-ai-client.d.ts","sourceRoot":"","sources":["../../../../src/clients/ai/unified/unified-ai-client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,aAAa,EAAE,MAAM,IAAI,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAe,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE3E;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAgB;IAE7B,OAAO,CAAC,QAAQ,CAAW;gBAEf,QAAQ,EAAE,QAAQ;IAK9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACG,0BAA0B,CAAC,CAAC,EAChC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EACpB,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAC/B,YAAY,CAAC,EAAE,cAAc,GAC5B,OAAO,CAAC,CAAC,CAAC;IAuCb;;;OAGG;IACH,QAAQ,IAAI,aAAa;IAIzB,OAAO,CAAC,WAAW;CAYpB"}
@@ -5,6 +5,7 @@ const google_1 = require("@ai-sdk/google");
5
5
  const openai_1 = require("@ai-sdk/openai");
6
6
  const xai_1 = require("@ai-sdk/xai");
7
7
  const ai_1 = require("ai");
8
+ const ai_usage_tracker_1 = require("./ai-usage-tracker");
8
9
  const unified_ai_client_model_1 = require("./unified-ai-client.model");
9
10
  /**
10
11
  * Unified AI Client that supports multiple AI providers (OpenAI, XAI, Gemini)
@@ -12,7 +13,9 @@ const unified_ai_client_model_1 = require("./unified-ai-client.model");
12
13
  */
13
14
  class UnifiedAiClient {
14
15
  model;
16
+ provider;
15
17
  constructor(provider) {
18
+ this.provider = provider;
16
19
  this.model = this.createModel(provider);
17
20
  }
18
21
  /**
@@ -20,8 +23,10 @@ class UnifiedAiClient {
20
23
  *
21
24
  * @template T - The type inferred from the Zod schema
22
25
  *
23
- * @param params - Configuration object for the structured response generation.
24
- * See {@link GenerateObjectParams} for all available options.
26
+ * @param schema - Zod schema defining the expected response structure.
27
+ * The AI model will be constrained to return data matching this schema.
28
+ * @param params - Configuration object with prompt, system message, and any additional options.
29
+ * See {@link GenerateObjectParams} for all available options.
25
30
  *
26
31
  * @returns Promise resolving to the validated object matching the schema type T
27
32
  *
@@ -37,24 +42,42 @@ class UnifiedAiClient {
37
42
  * });
38
43
  *
39
44
  * // Generate structured response
40
- * const result = await service.generateStructuredResponse({
41
- * schema: SentimentSchema,
42
- * userPrompt: 'I absolutely love this product!',
43
- * systemMessage: 'You are a sentiment analysis expert. Be precise with confidence scores.',
45
+ * const result = await service.generateStructuredResponse(SentimentSchema, {
46
+ * prompt: 'I absolutely love this product!',
47
+ * system: 'You are a sentiment analysis expert. Be precise with confidence scores.',
44
48
  * });
45
49
  *
46
50
  * console.log(result.sentiment); // 'positive'
47
51
  * console.log(result.confidence); // 0.95
48
52
  */
49
- async generateStructuredResponse(params) {
50
- const { schema, userPrompt, systemMessage, ...rest } = params;
53
+ async generateStructuredResponse(schema, params, usageTracker) {
54
+ const { prompt, system, ...rest } = params;
55
+ const startTime = Date.now();
51
56
  const result = await (0, ai_1.generateObject)({
52
57
  ...rest,
53
58
  model: this.model,
54
59
  schema: schema, // Option 2: Use jsonSchema instead of Zod directly: schema: jsonSchema<T>(zodToJsonSchema(schema) as any),
55
- prompt: userPrompt,
56
- system: systemMessage,
60
+ prompt: prompt,
61
+ system: system,
57
62
  });
63
+ const durationMs = Date.now() - startTime;
64
+ const usage = result.usage;
65
+ const model = result.response.modelId;
66
+ const aiCallUsage = {
67
+ provider: this.provider,
68
+ model,
69
+ inputTokens: usage.inputTokens ?? 0,
70
+ outputTokens: usage.outputTokens ?? 0,
71
+ totalTokens: usage.totalTokens ?? 0,
72
+ reasoningTokens: usage.reasoningTokens ?? undefined,
73
+ cachedInputTokens: usage.cachedInputTokens ?? undefined,
74
+ estimatedCost: ai_usage_tracker_1.AiUsageTracker.estimateCost(model, usage),
75
+ durationMs,
76
+ };
77
+ console.log(`[AI Call Usage] ${aiCallUsage.provider}/${aiCallUsage.model} in=${aiCallUsage.inputTokens} out=${aiCallUsage.outputTokens}${aiCallUsage.reasoningTokens ? ` reasoning=${aiCallUsage.reasoningTokens}` : ''} $${aiCallUsage.estimatedCost.toFixed(6)} ${aiCallUsage.durationMs}ms`);
78
+ if (usageTracker) {
79
+ usageTracker.addCall(aiCallUsage);
80
+ }
58
81
  return result.object;
59
82
  }
60
83
  /**
@@ -1,21 +1,19 @@
1
- import { generateObject } from 'ai';
2
- import { ZodSchema } from 'zod';
3
1
  /**
4
2
  * Options for generating a structured response from the AI model.
5
3
  *
6
- * @template T - The type inferred from the Zod schema
4
+ * Includes the core params (`prompt`, `system`) plus any additional options
5
+ * (e.g. `mode`, `schemaName`, `schemaDescription`, `maxTokens`, `temperature`, etc.).
6
+ * Extra properties are passed through as-is.
7
7
  *
8
- * Includes the core params (schema, userPrompt, systemMessage) plus
9
- * any additional options supported by the underlying `generateObject()` call
10
- * (e.g. mode, schemaName, schemaDescription, maxTokens, temperature, etc.).
8
+ * Note: The Zod `schema` is passed as a separate argument to `generateStructuredResponse()`.
11
9
  */
12
- export interface GenerateObjectParams<T> extends Omit<Parameters<typeof generateObject>[0], 'model' | 'schema' | 'prompt' | 'system' | 'messages'> {
13
- /** Zod schema defining the expected response structure. */
14
- schema: ZodSchema<T>;
10
+ export interface GenerateObjectParams<T> {
15
11
  /** User input/message to send to the AI model (role: user). */
16
- userPrompt: string;
12
+ prompt: string;
17
13
  /** Optional system instructions that define the AI's behavior, persona, and task context (role: system). */
18
- systemMessage?: string;
14
+ system?: string;
15
+ /** Any additional options are passed through to the underlying AI call. */
16
+ [key: string]: unknown;
19
17
  }
20
18
  /**
21
19
  * Enum representing supported AI providers.
@@ -1 +1 @@
1
- {"version":3,"file":"unified-ai-client.model.d.ts","sourceRoot":"","sources":["../../../../src/clients/ai/unified/unified-ai-client.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAEhC;;;;;;;;GAQG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,CACrC,SAAQ,IAAI,CACV,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC,EACpC,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CACtD;IACD,2DAA2D;IAC3D,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACrB,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,4GAA4G;IAC5G,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,oBAAY,QAAQ;IAClB;;OAEG;IACH,MAAM,WAAW;IACjB;;OAEG;IACH,GAAG,QAAQ;IACX;;OAEG;IACH,MAAM,WAAW;CAClB"}
1
+ {"version":3,"file":"unified-ai-client.model.d.ts","sourceRoot":"","sources":["../../../../src/clients/ai/unified/unified-ai-client.model.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,4GAA4G;IAC5G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,oBAAY,QAAQ;IAClB;;OAEG;IACH,MAAM,WAAW;IACjB;;OAEG;IACH,GAAG,QAAQ;IACX;;OAEG;IACH,MAAM,WAAW;CAClB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@future-explorer/lib",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "Shared utilities and clients for Future Explorer projects",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -52,14 +52,17 @@
52
52
  "zod": "^4.2.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@types/node": "^24.5.2",
55
+ "@types/node": "^24.10.12",
56
56
  "@typescript-eslint/eslint-plugin": "^8.0.0",
57
57
  "@typescript-eslint/parser": "^8.0.0",
58
+ "dotenv": "^17.2.4",
58
59
  "eslint": "^9.20.1",
59
60
  "eslint-config-prettier": "^10.0.1",
60
61
  "eslint-plugin-prettier": "^5.2.3",
61
62
  "prettier": "^3.5.1",
62
63
  "rimraf": "^6.0.1",
63
- "typescript": "^5.6.3"
64
+ "ts-node": "^10.9.2",
65
+ "typescript": "^5.6.3",
66
+ "zod": "^4.3.6"
64
67
  }
65
68
  }