@isoldex/sentinel 0.1.0 → 2.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.
- package/README.md +368 -62
- package/dist/__tests__/action-engine.test.d.ts +2 -0
- package/dist/__tests__/action-engine.test.d.ts.map +1 -0
- package/dist/__tests__/action-engine.test.js +144 -0
- package/dist/__tests__/action-engine.test.js.map +1 -0
- package/dist/__tests__/state-parser.test.d.ts +2 -0
- package/dist/__tests__/state-parser.test.d.ts.map +1 -0
- package/dist/__tests__/state-parser.test.js +176 -0
- package/dist/__tests__/state-parser.test.js.map +1 -0
- package/dist/__tests__/verifier.test.d.ts +2 -0
- package/dist/__tests__/verifier.test.d.ts.map +1 -0
- package/dist/__tests__/verifier.test.js +68 -0
- package/dist/__tests__/verifier.test.js.map +1 -0
- package/dist/__tests__/workflow-recorder.test.d.ts +2 -0
- package/dist/__tests__/workflow-recorder.test.d.ts.map +1 -0
- package/dist/__tests__/workflow-recorder.test.js +71 -0
- package/dist/__tests__/workflow-recorder.test.js.map +1 -0
- package/dist/agent/agent-loop.d.ts +36 -0
- package/dist/agent/agent-loop.d.ts.map +1 -0
- package/dist/agent/agent-loop.js +127 -0
- package/dist/agent/agent-loop.js.map +1 -0
- package/dist/agent/memory.d.ts +24 -0
- package/dist/agent/memory.d.ts.map +1 -0
- package/dist/agent/memory.js +34 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/planner.d.ts +18 -0
- package/dist/agent/planner.d.ts.map +1 -0
- package/dist/agent/planner.js +68 -0
- package/dist/agent/planner.js.map +1 -0
- package/dist/api/act.d.ts +4 -2
- package/dist/api/act.d.ts.map +1 -1
- package/dist/api/act.js +174 -30
- package/dist/api/act.js.map +1 -1
- package/dist/api/extract.d.ts +2 -3
- package/dist/api/extract.d.ts.map +1 -1
- package/dist/api/extract.js +0 -1
- package/dist/api/extract.js.map +1 -1
- package/dist/api/observe.d.ts +2 -2
- package/dist/api/observe.d.ts.map +1 -1
- package/dist/api/observe.js +0 -1
- package/dist/api/observe.js.map +1 -1
- package/dist/core/driver.d.ts +21 -1
- package/dist/core/driver.d.ts.map +1 -1
- package/dist/core/driver.js +109 -19
- package/dist/core/driver.js.map +1 -1
- package/dist/core/state-parser.d.ts +1 -0
- package/dist/core/state-parser.d.ts.map +1 -1
- package/dist/core/state-parser.js +60 -0
- package/dist/core/state-parser.js.map +1 -1
- package/dist/core/vision-grounding.d.ts +36 -0
- package/dist/core/vision-grounding.d.ts.map +1 -0
- package/dist/core/vision-grounding.js +118 -0
- package/dist/core/vision-grounding.js.map +1 -0
- package/dist/index.d.ts +111 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +168 -4
- package/dist/index.js.map +1 -1
- package/dist/recorder/workflow-recorder.d.ts +30 -0
- package/dist/recorder/workflow-recorder.d.ts.map +1 -0
- package/dist/recorder/workflow-recorder.js +83 -0
- package/dist/recorder/workflow-recorder.js.map +1 -0
- package/dist/reliability/verifier.d.ts +2 -2
- package/dist/reliability/verifier.d.ts.map +1 -1
- package/dist/reliability/verifier.js +0 -1
- package/dist/reliability/verifier.js.map +1 -1
- package/dist/types/errors.d.ts +45 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +69 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/utils/gemini.d.ts +3 -6
- package/dist/utils/gemini.d.ts.map +1 -1
- package/dist/utils/gemini.js +9 -94
- package/dist/utils/gemini.js.map +1 -1
- package/dist/utils/llm-provider.d.ts +28 -0
- package/dist/utils/llm-provider.d.ts.map +1 -0
- package/dist/utils/llm-provider.js +2 -0
- package/dist/utils/llm-provider.js.map +1 -0
- package/dist/utils/providers/claude-provider.d.ts +17 -0
- package/dist/utils/providers/claude-provider.d.ts.map +1 -0
- package/dist/utils/providers/claude-provider.js +49 -0
- package/dist/utils/providers/claude-provider.js.map +1 -0
- package/dist/utils/providers/gemini-provider.d.ts +14 -0
- package/dist/utils/providers/gemini-provider.d.ts.map +1 -0
- package/dist/utils/providers/gemini-provider.js +95 -0
- package/dist/utils/providers/gemini-provider.js.map +1 -0
- package/dist/utils/providers/ollama-provider.d.ts +18 -0
- package/dist/utils/providers/ollama-provider.d.ts.map +1 -0
- package/dist/utils/providers/ollama-provider.js +62 -0
- package/dist/utils/providers/ollama-provider.js.map +1 -0
- package/dist/utils/providers/openai-provider.d.ts +18 -0
- package/dist/utils/providers/openai-provider.d.ts.map +1 -0
- package/dist/utils/providers/openai-provider.js +51 -0
- package/dist/utils/providers/openai-provider.js.map +1 -0
- package/dist/utils/token-tracker.d.ts +25 -0
- package/dist/utils/token-tracker.d.ts.map +1 -0
- package/dist/utils/token-tracker.js +45 -0
- package/dist/utils/token-tracker.js.map +1 -0
- package/dist/whatsapp-test.js +58 -17
- package/dist/whatsapp-test.js.map +1 -1
- package/package.json +10 -4
package/dist/utils/gemini.js
CHANGED
|
@@ -1,103 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
let lastError;
|
|
7
|
-
for (let attempt = 0; attempt < retries; attempt++) {
|
|
8
|
-
try {
|
|
9
|
-
return await fn();
|
|
10
|
-
}
|
|
11
|
-
catch (err) {
|
|
12
|
-
lastError = err;
|
|
13
|
-
const isRetryable = err?.status === 429 ||
|
|
14
|
-
err?.status === 503 ||
|
|
15
|
-
err?.message?.includes('fetch failed') ||
|
|
16
|
-
err?.message?.includes('ECONNRESET') ||
|
|
17
|
-
err?.message?.includes('rate limit');
|
|
18
|
-
if (!isRetryable || attempt === retries - 1)
|
|
19
|
-
throw err;
|
|
20
|
-
const delay = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
21
|
-
console.warn(`[Gemini] Retryable error (attempt ${attempt + 1}/${retries}). Retrying in ${delay}ms... Error: ${err?.message}`);
|
|
22
|
-
await new Promise(resolve => setTimeout(resolve, delay));
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
throw lastError;
|
|
26
|
-
}
|
|
27
|
-
function isZodSchema(schema) {
|
|
28
|
-
return (typeof schema === 'object' &&
|
|
29
|
-
schema !== null &&
|
|
30
|
-
'_def' in schema &&
|
|
31
|
-
typeof schema.parse === 'function');
|
|
32
|
-
}
|
|
33
|
-
function cleanSchemaForGemini(schema) {
|
|
34
|
-
if (Array.isArray(schema)) {
|
|
35
|
-
return schema.map(cleanSchemaForGemini);
|
|
36
|
-
}
|
|
37
|
-
else if (schema !== null && typeof schema === 'object') {
|
|
38
|
-
const cleaned = {};
|
|
39
|
-
for (const [key, value] of Object.entries(schema)) {
|
|
40
|
-
if (key === '$schema' || key === 'additionalProperties') {
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
cleaned[key] = cleanSchemaForGemini(value);
|
|
44
|
-
}
|
|
45
|
-
return cleaned;
|
|
46
|
-
}
|
|
47
|
-
return schema;
|
|
48
|
-
}
|
|
49
|
-
function resolveJsonSchema(schema) {
|
|
50
|
-
if (isZodSchema(schema)) {
|
|
51
|
-
// Zod v4 has a built-in toJSONSchema() method
|
|
52
|
-
const jsonSchema = z.toJSONSchema(schema);
|
|
53
|
-
return cleanSchemaForGemini(jsonSchema);
|
|
54
|
-
}
|
|
55
|
-
return cleanSchemaForGemini(schema);
|
|
56
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* GeminiService – thin wrapper kept for backward compatibility.
|
|
3
|
+
* Internally delegates to GeminiProvider.
|
|
4
|
+
*/
|
|
5
|
+
import { GeminiProvider } from './providers/gemini-provider.js';
|
|
57
6
|
export class GeminiService {
|
|
58
|
-
|
|
59
|
-
structuredModel;
|
|
60
|
-
textModel;
|
|
7
|
+
provider;
|
|
61
8
|
constructor(apiKey) {
|
|
62
|
-
this.
|
|
63
|
-
const modelName = process.env.GEMINI_VERSION;
|
|
64
|
-
if (!modelName)
|
|
65
|
-
throw new Error("GEMINI_VERSION must be set in .env");
|
|
66
|
-
this.structuredModel = this.genAI.getGenerativeModel({ model: modelName });
|
|
67
|
-
this.textModel = this.genAI.getGenerativeModel({ model: modelName });
|
|
9
|
+
this.provider = new GeminiProvider({ apiKey });
|
|
68
10
|
}
|
|
69
11
|
async generateStructuredData(prompt, schema) {
|
|
70
|
-
|
|
71
|
-
return withRetry(async () => {
|
|
72
|
-
const result = await this.structuredModel.generateContent({
|
|
73
|
-
contents: [{ role: "user", parts: [{ text: prompt }] }],
|
|
74
|
-
generationConfig: {
|
|
75
|
-
responseMimeType: "application/json",
|
|
76
|
-
responseSchema: jsonSchema,
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
const text = result.response.text();
|
|
80
|
-
const parsed = JSON.parse(text);
|
|
81
|
-
// If Zod schema: validate output → get runtime type safety
|
|
82
|
-
if (isZodSchema(schema)) {
|
|
83
|
-
return schema.parse(parsed);
|
|
84
|
-
}
|
|
85
|
-
return parsed;
|
|
86
|
-
});
|
|
12
|
+
return this.provider.generateStructuredData(prompt, schema);
|
|
87
13
|
}
|
|
88
14
|
async generateText(prompt, systemInstruction) {
|
|
89
|
-
return
|
|
90
|
-
const params = { model: process.env.GEMINI_VERSION || "gemini-1.5-flash" };
|
|
91
|
-
console.log(params);
|
|
92
|
-
if (systemInstruction) {
|
|
93
|
-
params.systemInstruction = { role: "system", parts: [{ text: systemInstruction }] };
|
|
94
|
-
}
|
|
95
|
-
const model = systemInstruction
|
|
96
|
-
? this.genAI.getGenerativeModel(params)
|
|
97
|
-
: this.textModel;
|
|
98
|
-
const result = await model.generateContent(prompt);
|
|
99
|
-
return result.response.text();
|
|
100
|
-
});
|
|
15
|
+
return this.provider.generateText(prompt, systemInstruction);
|
|
101
16
|
}
|
|
102
17
|
}
|
|
103
18
|
//# sourceMappingURL=gemini.js.map
|
package/dist/utils/gemini.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/utils/gemini.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/utils/gemini.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAKhE,MAAM,OAAO,aAAa;IAChB,QAAQ,CAAiB;IAEjC,YAAY,MAAc;QACxB,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAI,MAAc,EAAE,MAAsB;QACpE,OAAO,IAAI,CAAC,QAAQ,CAAC,sBAAsB,CAAI,MAAM,EAAE,MAAM,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc,EAAE,iBAA0B;QAC3D,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC/D,CAAC;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** Accepts either a Zod schema or a raw JSON Schema object */
|
|
3
|
+
export type SchemaInput<T> = z.ZodType | Record<string, any>;
|
|
4
|
+
/**
|
|
5
|
+
* Unified interface for all LLM providers.
|
|
6
|
+
* Implement this to add support for any LLM backend.
|
|
7
|
+
*/
|
|
8
|
+
export interface LLMProvider {
|
|
9
|
+
/**
|
|
10
|
+
* Generate structured JSON data conforming to the given schema.
|
|
11
|
+
*/
|
|
12
|
+
generateStructuredData<T>(prompt: string, schema: SchemaInput<T>): Promise<T>;
|
|
13
|
+
/**
|
|
14
|
+
* Generate a plain text response.
|
|
15
|
+
*/
|
|
16
|
+
generateText(prompt: string, systemInstruction?: string): Promise<string>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Token usage tracking returned by providers that support it.
|
|
20
|
+
*/
|
|
21
|
+
export interface TokenUsage {
|
|
22
|
+
inputTokens: number;
|
|
23
|
+
outputTokens: number;
|
|
24
|
+
totalTokens: number;
|
|
25
|
+
/** Estimated cost in USD, if calculable */
|
|
26
|
+
estimatedCostUsd?: number;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=llm-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-provider.d.ts","sourceRoot":"","sources":["../../src/utils/llm-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8DAA8D;AAC9D,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE9E;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3E;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-provider.js","sourceRoot":"","sources":["../../src/utils/llm-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { LLMProvider, SchemaInput } from '../llm-provider.js';
|
|
2
|
+
export interface ClaudeProviderOptions {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
model?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Anthropic Claude provider (claude-3-5-sonnet, claude-3-haiku, etc.)
|
|
8
|
+
* Requires: npm install @anthropic-ai/sdk
|
|
9
|
+
*/
|
|
10
|
+
export declare class ClaudeProvider implements LLMProvider {
|
|
11
|
+
private client;
|
|
12
|
+
private model;
|
|
13
|
+
constructor(options: ClaudeProviderOptions);
|
|
14
|
+
generateStructuredData<T>(prompt: string, schema: SchemaInput<T>): Promise<T>;
|
|
15
|
+
generateText(prompt: string, systemInstruction?: string): Promise<string>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=claude-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-provider.d.ts","sourceRoot":"","sources":["../../../src/utils/providers/claude-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,KAAK,CAAS;gBAEV,OAAO,EAAE,qBAAqB;IAYpC,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAqB7E,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAWhF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic Claude provider (claude-3-5-sonnet, claude-3-haiku, etc.)
|
|
3
|
+
* Requires: npm install @anthropic-ai/sdk
|
|
4
|
+
*/
|
|
5
|
+
export class ClaudeProvider {
|
|
6
|
+
client;
|
|
7
|
+
model;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
try {
|
|
10
|
+
const Anthropic = require('@anthropic-ai/sdk');
|
|
11
|
+
this.client = new Anthropic.default({ apiKey: options.apiKey });
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
throw new Error('[ClaudeProvider] "@anthropic-ai/sdk" package not found. Install it with: npm install @anthropic-ai/sdk');
|
|
15
|
+
}
|
|
16
|
+
this.model = options.model ?? 'claude-3-5-sonnet-20241022';
|
|
17
|
+
}
|
|
18
|
+
async generateStructuredData(prompt, schema) {
|
|
19
|
+
// Claude uses tool_use for structured output
|
|
20
|
+
const response = await this.client.messages.create({
|
|
21
|
+
model: this.model,
|
|
22
|
+
max_tokens: 4096,
|
|
23
|
+
tools: [
|
|
24
|
+
{
|
|
25
|
+
name: 'structured_output',
|
|
26
|
+
description: 'Return structured data matching the schema',
|
|
27
|
+
input_schema: schema,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
tool_choice: { type: 'tool', name: 'structured_output' },
|
|
31
|
+
messages: [{ role: 'user', content: prompt }],
|
|
32
|
+
});
|
|
33
|
+
const toolUse = response.content.find((c) => c.type === 'tool_use');
|
|
34
|
+
if (!toolUse)
|
|
35
|
+
throw new Error('[ClaudeProvider] No tool_use block in response');
|
|
36
|
+
return toolUse.input;
|
|
37
|
+
}
|
|
38
|
+
async generateText(prompt, systemInstruction) {
|
|
39
|
+
const response = await this.client.messages.create({
|
|
40
|
+
model: this.model,
|
|
41
|
+
max_tokens: 4096,
|
|
42
|
+
...(systemInstruction ? { system: systemInstruction } : {}),
|
|
43
|
+
messages: [{ role: 'user', content: prompt }],
|
|
44
|
+
});
|
|
45
|
+
const textBlock = response.content.find((c) => c.type === 'text');
|
|
46
|
+
return textBlock?.text ?? '';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=claude-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-provider.js","sourceRoot":"","sources":["../../../src/utils/providers/claude-provider.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,MAAM,OAAO,cAAc;IACjB,MAAM,CAAM;IACZ,KAAK,CAAS;IAEtB,YAAY,OAA8B;QACxC,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;YAC/C,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAClE,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CACb,wGAAwG,CACzG,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,4BAA4B,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAI,MAAc,EAAE,MAAsB;QACpE,6CAA6C;QAC7C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YACjD,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,UAAU,EAAE,IAAI;YAChB,KAAK,EAAE;gBACL;oBACE,IAAI,EAAE,mBAAmB;oBACzB,WAAW,EAAE,4CAA4C;oBACzD,YAAY,EAAE,MAAM;iBACrB;aACF;YACD,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE;YACxD,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;SAC9C,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QACzE,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAChF,OAAO,OAAO,CAAC,KAAU,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc,EAAE,iBAA0B;QAC3D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YACjD,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,UAAU,EAAE,IAAI;YAChB,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;SAC9C,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QACvE,OAAO,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC;IAC/B,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LLMProvider, SchemaInput } from '../llm-provider.js';
|
|
2
|
+
export interface GeminiProviderOptions {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
model?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class GeminiProvider implements LLMProvider {
|
|
7
|
+
private genAI;
|
|
8
|
+
private structuredModel;
|
|
9
|
+
private textModel;
|
|
10
|
+
constructor(options: GeminiProviderOptions);
|
|
11
|
+
generateStructuredData<T>(prompt: string, schema: SchemaInput<T>): Promise<T>;
|
|
12
|
+
generateText(prompt: string, systemInstruction?: string): Promise<string>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=gemini-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-provider.d.ts","sourceRoot":"","sources":["../../../src/utils/providers/gemini-provider.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAyDnE,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,SAAS,CAAM;gBAEX,OAAO,EAAE,qBAAqB;IAQpC,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAiB7E,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAWhF"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { GoogleGenerativeAI } from '@google/generative-ai';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
const MAX_RETRIES = 3;
|
|
4
|
+
const BASE_DELAY_MS = 1000;
|
|
5
|
+
async function withRetry(fn, retries = MAX_RETRIES) {
|
|
6
|
+
let lastError;
|
|
7
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
8
|
+
try {
|
|
9
|
+
return await fn();
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
lastError = err;
|
|
13
|
+
const isRetryable = err?.status === 429 ||
|
|
14
|
+
err?.status === 503 ||
|
|
15
|
+
err?.message?.includes('fetch failed') ||
|
|
16
|
+
err?.message?.includes('ECONNRESET') ||
|
|
17
|
+
err?.message?.includes('rate limit');
|
|
18
|
+
if (!isRetryable || attempt === retries - 1)
|
|
19
|
+
throw err;
|
|
20
|
+
const delay = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
21
|
+
console.warn(`[Gemini] Retryable error (attempt ${attempt + 1}/${retries}). Retrying in ${delay}ms...`);
|
|
22
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
throw lastError;
|
|
26
|
+
}
|
|
27
|
+
function isZodSchema(schema) {
|
|
28
|
+
return (typeof schema === 'object' &&
|
|
29
|
+
schema !== null &&
|
|
30
|
+
'_def' in schema &&
|
|
31
|
+
typeof schema.parse === 'function');
|
|
32
|
+
}
|
|
33
|
+
function cleanSchemaForGemini(schema) {
|
|
34
|
+
if (Array.isArray(schema))
|
|
35
|
+
return schema.map(cleanSchemaForGemini);
|
|
36
|
+
if (schema !== null && typeof schema === 'object') {
|
|
37
|
+
const cleaned = {};
|
|
38
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
39
|
+
if (key === '$schema' || key === 'additionalProperties')
|
|
40
|
+
continue;
|
|
41
|
+
cleaned[key] = cleanSchemaForGemini(value);
|
|
42
|
+
}
|
|
43
|
+
return cleaned;
|
|
44
|
+
}
|
|
45
|
+
return schema;
|
|
46
|
+
}
|
|
47
|
+
function resolveJsonSchema(schema) {
|
|
48
|
+
if (isZodSchema(schema)) {
|
|
49
|
+
const jsonSchema = z.toJSONSchema(schema);
|
|
50
|
+
return cleanSchemaForGemini(jsonSchema);
|
|
51
|
+
}
|
|
52
|
+
return cleanSchemaForGemini(schema);
|
|
53
|
+
}
|
|
54
|
+
export class GeminiProvider {
|
|
55
|
+
genAI;
|
|
56
|
+
structuredModel;
|
|
57
|
+
textModel;
|
|
58
|
+
constructor(options) {
|
|
59
|
+
this.genAI = new GoogleGenerativeAI(options.apiKey);
|
|
60
|
+
const modelName = options.model ?? process.env.GEMINI_VERSION;
|
|
61
|
+
if (!modelName)
|
|
62
|
+
throw new Error('Gemini model name must be provided or GEMINI_VERSION must be set in .env');
|
|
63
|
+
this.structuredModel = this.genAI.getGenerativeModel({ model: modelName });
|
|
64
|
+
this.textModel = this.genAI.getGenerativeModel({ model: modelName });
|
|
65
|
+
}
|
|
66
|
+
async generateStructuredData(prompt, schema) {
|
|
67
|
+
const jsonSchema = resolveJsonSchema(schema);
|
|
68
|
+
return withRetry(async () => {
|
|
69
|
+
const result = await this.structuredModel.generateContent({
|
|
70
|
+
contents: [{ role: 'user', parts: [{ text: prompt }] }],
|
|
71
|
+
generationConfig: {
|
|
72
|
+
responseMimeType: 'application/json',
|
|
73
|
+
responseSchema: jsonSchema,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
const text = result.response.text();
|
|
77
|
+
const parsed = JSON.parse(text);
|
|
78
|
+
if (isZodSchema(schema))
|
|
79
|
+
return schema.parse(parsed);
|
|
80
|
+
return parsed;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
async generateText(prompt, systemInstruction) {
|
|
84
|
+
return withRetry(async () => {
|
|
85
|
+
const params = { model: process.env.GEMINI_VERSION || 'gemini-1.5-flash' };
|
|
86
|
+
if (systemInstruction) {
|
|
87
|
+
params.systemInstruction = { role: 'system', parts: [{ text: systemInstruction }] };
|
|
88
|
+
}
|
|
89
|
+
const model = systemInstruction ? this.genAI.getGenerativeModel(params) : this.textModel;
|
|
90
|
+
const result = await model.generateContent(prompt);
|
|
91
|
+
return result.response.text();
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=gemini-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-provider.js","sourceRoot":"","sources":["../../../src/utils/providers/gemini-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LLMProvider, SchemaInput } from '../llm-provider.js';
|
|
2
|
+
export interface OllamaProviderOptions {
|
|
3
|
+
model: string;
|
|
4
|
+
baseURL?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Ollama provider for local LLMs (llama3, mistral, qwen2.5, etc.)
|
|
8
|
+
* Requires a running Ollama instance: https://ollama.com
|
|
9
|
+
* No additional npm packages needed – uses the native fetch API.
|
|
10
|
+
*/
|
|
11
|
+
export declare class OllamaProvider implements LLMProvider {
|
|
12
|
+
private model;
|
|
13
|
+
private baseURL;
|
|
14
|
+
constructor(options: OllamaProviderOptions);
|
|
15
|
+
generateStructuredData<T>(prompt: string, schema: SchemaInput<T>): Promise<T>;
|
|
16
|
+
generateText(prompt: string, systemInstruction?: string): Promise<string>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=ollama-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama-provider.d.ts","sourceRoot":"","sources":["../../../src/utils/providers/ollama-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,qBAAqB;IAKpC,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA+B7E,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAwBhF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama provider for local LLMs (llama3, mistral, qwen2.5, etc.)
|
|
3
|
+
* Requires a running Ollama instance: https://ollama.com
|
|
4
|
+
* No additional npm packages needed – uses the native fetch API.
|
|
5
|
+
*/
|
|
6
|
+
export class OllamaProvider {
|
|
7
|
+
model;
|
|
8
|
+
baseURL;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.model = options.model;
|
|
11
|
+
this.baseURL = options.baseURL ?? 'http://localhost:11434';
|
|
12
|
+
}
|
|
13
|
+
async generateStructuredData(prompt, schema) {
|
|
14
|
+
const systemPrompt = `You are a JSON API. Always respond with valid JSON that matches this schema: ${JSON.stringify(schema)}. No markdown, no explanation, only raw JSON.`;
|
|
15
|
+
const response = await fetch(`${this.baseURL}/api/chat`, {
|
|
16
|
+
method: 'POST',
|
|
17
|
+
headers: { 'Content-Type': 'application/json' },
|
|
18
|
+
body: JSON.stringify({
|
|
19
|
+
model: this.model,
|
|
20
|
+
stream: false,
|
|
21
|
+
format: 'json',
|
|
22
|
+
messages: [
|
|
23
|
+
{ role: 'system', content: systemPrompt },
|
|
24
|
+
{ role: 'user', content: prompt },
|
|
25
|
+
],
|
|
26
|
+
}),
|
|
27
|
+
});
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
throw new Error(`[OllamaProvider] HTTP ${response.status}: ${await response.text()}`);
|
|
30
|
+
}
|
|
31
|
+
const data = await response.json();
|
|
32
|
+
const content = data?.message?.content ?? '{}';
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(content);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
throw new Error(`[OllamaProvider] Failed to parse JSON response: ${content}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async generateText(prompt, systemInstruction) {
|
|
41
|
+
const messages = [];
|
|
42
|
+
if (systemInstruction) {
|
|
43
|
+
messages.push({ role: 'system', content: systemInstruction });
|
|
44
|
+
}
|
|
45
|
+
messages.push({ role: 'user', content: prompt });
|
|
46
|
+
const response = await fetch(`${this.baseURL}/api/chat`, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: { 'Content-Type': 'application/json' },
|
|
49
|
+
body: JSON.stringify({
|
|
50
|
+
model: this.model,
|
|
51
|
+
stream: false,
|
|
52
|
+
messages,
|
|
53
|
+
}),
|
|
54
|
+
});
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
throw new Error(`[OllamaProvider] HTTP ${response.status}: ${await response.text()}`);
|
|
57
|
+
}
|
|
58
|
+
const data = await response.json();
|
|
59
|
+
return data?.message?.content ?? '';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=ollama-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama-provider.js","sourceRoot":"","sources":["../../../src/utils/providers/ollama-provider.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,MAAM,OAAO,cAAc;IACjB,KAAK,CAAS;IACd,OAAO,CAAS;IAExB,YAAY,OAA8B;QACxC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,wBAAwB,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAI,MAAc,EAAE,MAAsB;QACpE,MAAM,YAAY,GAAG,gFAAgF,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,+CAA+C,CAAC;QAE3K,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,WAAW,EAAE;YACvD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE;oBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;oBACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;iBAClC;aACF,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,CAAC,MAAM,KAAK,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAS,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC;QAE/C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAM,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,mDAAmD,OAAO,EAAE,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc,EAAE,iBAA0B;QAC3D,MAAM,QAAQ,GAAU,EAAE,CAAC;QAC3B,IAAI,iBAAiB,EAAE,CAAC;YACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAChE,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAEjD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,WAAW,EAAE;YACvD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,KAAK;gBACb,QAAQ;aACT,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,CAAC,MAAM,KAAK,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAS,CAAC;QAC1C,OAAO,IAAI,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;IACtC,CAAC;CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LLMProvider, SchemaInput } from '../llm-provider.js';
|
|
2
|
+
export interface OpenAIProviderOptions {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
model?: string;
|
|
5
|
+
baseURL?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* OpenAI provider (GPT-4o, GPT-4o-mini, etc.)
|
|
9
|
+
* Requires: npm install openai
|
|
10
|
+
*/
|
|
11
|
+
export declare class OpenAIProvider implements LLMProvider {
|
|
12
|
+
private client;
|
|
13
|
+
private model;
|
|
14
|
+
constructor(options: OpenAIProviderOptions);
|
|
15
|
+
generateStructuredData<T>(prompt: string, schema: SchemaInput<T>): Promise<T>;
|
|
16
|
+
generateText(prompt: string, systemInstruction?: string): Promise<string>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=openai-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-provider.d.ts","sourceRoot":"","sources":["../../../src/utils/providers/openai-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,KAAK,CAAS;gBAEV,OAAO,EAAE,qBAAqB;IAgBpC,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAiB7E,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAahF"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI provider (GPT-4o, GPT-4o-mini, etc.)
|
|
3
|
+
* Requires: npm install openai
|
|
4
|
+
*/
|
|
5
|
+
export class OpenAIProvider {
|
|
6
|
+
client;
|
|
7
|
+
model;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
try {
|
|
10
|
+
// Dynamic import to keep openai as optional peer dependency
|
|
11
|
+
const { OpenAI } = require('openai');
|
|
12
|
+
this.client = new OpenAI({
|
|
13
|
+
apiKey: options.apiKey,
|
|
14
|
+
...(options.baseURL ? { baseURL: options.baseURL } : {}),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new Error('[OpenAIProvider] "openai" package not found. Install it with: npm install openai');
|
|
19
|
+
}
|
|
20
|
+
this.model = options.model ?? 'gpt-4o';
|
|
21
|
+
}
|
|
22
|
+
async generateStructuredData(prompt, schema) {
|
|
23
|
+
const response = await this.client.chat.completions.create({
|
|
24
|
+
model: this.model,
|
|
25
|
+
messages: [{ role: 'user', content: prompt }],
|
|
26
|
+
response_format: {
|
|
27
|
+
type: 'json_schema',
|
|
28
|
+
json_schema: {
|
|
29
|
+
name: 'response',
|
|
30
|
+
strict: true,
|
|
31
|
+
schema: schema,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
const content = response.choices[0]?.message?.content ?? '{}';
|
|
36
|
+
return JSON.parse(content);
|
|
37
|
+
}
|
|
38
|
+
async generateText(prompt, systemInstruction) {
|
|
39
|
+
const messages = [];
|
|
40
|
+
if (systemInstruction) {
|
|
41
|
+
messages.push({ role: 'system', content: systemInstruction });
|
|
42
|
+
}
|
|
43
|
+
messages.push({ role: 'user', content: prompt });
|
|
44
|
+
const response = await this.client.chat.completions.create({
|
|
45
|
+
model: this.model,
|
|
46
|
+
messages,
|
|
47
|
+
});
|
|
48
|
+
return response.choices[0]?.message?.content ?? '';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=openai-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-provider.js","sourceRoot":"","sources":["../../../src/utils/providers/openai-provider.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,MAAM,OAAO,cAAc;IACjB,MAAM,CAAM;IACZ,KAAK,CAAS;IAEtB,YAAY,OAA8B;QACxC,IAAI,CAAC;YACH,4DAA4D;YAC5D,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC;gBACvB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACzD,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CACb,kFAAkF,CACnF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAI,MAAc,EAAE,MAAsB;QACpE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YACzD,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;YAC7C,eAAe,EAAE;gBACf,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE;oBACX,IAAI,EAAE,UAAU;oBAChB,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,MAAM;iBACf;aACF;SACF,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC;QAC9D,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAM,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc,EAAE,iBAA0B;QAC3D,MAAM,QAAQ,GAAU,EAAE,CAAC;QAC3B,IAAI,iBAAiB,EAAE,CAAC;YACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAChE,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAEjD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YACzD,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ;SACT,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;IACrD,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface TokenUsageEntry {
|
|
2
|
+
operation: string;
|
|
3
|
+
inputTokens: number;
|
|
4
|
+
outputTokens: number;
|
|
5
|
+
timestamp: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Tracks token usage and estimates costs across all LLM calls.
|
|
9
|
+
*/
|
|
10
|
+
export declare class TokenTracker {
|
|
11
|
+
private entries;
|
|
12
|
+
private model;
|
|
13
|
+
constructor(model?: string);
|
|
14
|
+
track(operation: string, inputTokens: number, outputTokens: number): void;
|
|
15
|
+
getUsage(): {
|
|
16
|
+
totalInputTokens: number;
|
|
17
|
+
totalOutputTokens: number;
|
|
18
|
+
totalTokens: number;
|
|
19
|
+
estimatedCostUsd: number;
|
|
20
|
+
entries: TokenUsageEntry[];
|
|
21
|
+
};
|
|
22
|
+
reset(): void;
|
|
23
|
+
exportAsJSON(): string;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=token-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-tracker.d.ts","sourceRoot":"","sources":["../../src/utils/token-tracker.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAaD;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,SAAqB;IAItC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAIzE,QAAQ,IAAI;QACV,gBAAgB,EAAE,MAAM,CAAC;QACzB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,WAAW,EAAE,MAAM,CAAC;QACpB,gBAAgB,EAAE,MAAM,CAAC;QACzB,OAAO,EAAE,eAAe,EAAE,CAAC;KAC5B;IAmBD,KAAK,IAAI,IAAI;IAIb,YAAY,IAAI,MAAM;CAGvB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Approximate cost per 1M tokens (USD) – update as pricing changes
|
|
2
|
+
const COST_PER_1M = {
|
|
3
|
+
'gemini-2.0-flash': { input: 0.075, output: 0.30 },
|
|
4
|
+
'gemini-1.5-flash': { input: 0.075, output: 0.30 },
|
|
5
|
+
'gemini-1.5-pro': { input: 3.50, output: 10.50 },
|
|
6
|
+
'gpt-4o': { input: 2.50, output: 10.00 },
|
|
7
|
+
'gpt-4o-mini': { input: 0.15, output: 0.60 },
|
|
8
|
+
'claude-3-5-sonnet': { input: 3.00, output: 15.00 },
|
|
9
|
+
'claude-3-haiku': { input: 0.25, output: 1.25 },
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Tracks token usage and estimates costs across all LLM calls.
|
|
13
|
+
*/
|
|
14
|
+
export class TokenTracker {
|
|
15
|
+
entries = [];
|
|
16
|
+
model;
|
|
17
|
+
constructor(model = 'gemini-1.5-flash') {
|
|
18
|
+
this.model = model;
|
|
19
|
+
}
|
|
20
|
+
track(operation, inputTokens, outputTokens) {
|
|
21
|
+
this.entries.push({ operation, inputTokens, outputTokens, timestamp: Date.now() });
|
|
22
|
+
}
|
|
23
|
+
getUsage() {
|
|
24
|
+
const totalInputTokens = this.entries.reduce((s, e) => s + e.inputTokens, 0);
|
|
25
|
+
const totalOutputTokens = this.entries.reduce((s, e) => s + e.outputTokens, 0);
|
|
26
|
+
const totalTokens = totalInputTokens + totalOutputTokens;
|
|
27
|
+
const pricing = COST_PER_1M[this.model] ?? { input: 0, output: 0 };
|
|
28
|
+
const estimatedCostUsd = (totalInputTokens / 1_000_000) * pricing.input +
|
|
29
|
+
(totalOutputTokens / 1_000_000) * pricing.output;
|
|
30
|
+
return {
|
|
31
|
+
totalInputTokens,
|
|
32
|
+
totalOutputTokens,
|
|
33
|
+
totalTokens,
|
|
34
|
+
estimatedCostUsd: Math.round(estimatedCostUsd * 100000) / 100000,
|
|
35
|
+
entries: [...this.entries],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
reset() {
|
|
39
|
+
this.entries = [];
|
|
40
|
+
}
|
|
41
|
+
exportAsJSON() {
|
|
42
|
+
return JSON.stringify(this.getUsage(), null, 2);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=token-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-tracker.js","sourceRoot":"","sources":["../../src/utils/token-tracker.ts"],"names":[],"mappings":"AAOA,mEAAmE;AACnE,MAAM,WAAW,GAAsD;IACrE,kBAAkB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE;IAClD,kBAAkB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE;IAClD,gBAAgB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IAChD,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IACxC,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IAC5C,mBAAmB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IACnD,gBAAgB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;CAChD,CAAC;AAEF;;GAEG;AACH,MAAM,OAAO,YAAY;IACf,OAAO,GAAsB,EAAE,CAAC;IAChC,KAAK,CAAS;IAEtB,YAAY,KAAK,GAAG,kBAAkB;QACpC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,SAAiB,EAAE,WAAmB,EAAE,YAAoB;QAChE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,QAAQ;QAON,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAC7E,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC/E,MAAM,WAAW,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;QAEzD,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACnE,MAAM,gBAAgB,GACpB,CAAC,gBAAgB,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,KAAK;YAC9C,CAAC,iBAAiB,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;QAEnD,OAAO;YACL,gBAAgB;YAChB,iBAAiB;YACjB,WAAW;YACX,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,gBAAgB,GAAG,MAAM,CAAC,GAAG,MAAM;YAChE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;SAC3B,CAAC;IACJ,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;CACF"}
|