@semiont/inference 0.3.4 → 0.3.5

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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Logger, InferenceServiceConfig } from '@semiont/core';
1
+ import { Logger } from '@semiont/core';
2
2
 
3
3
  interface InferenceResponse {
4
4
  text: string;
@@ -32,11 +32,6 @@ interface InferenceClientConfig {
32
32
  baseURL?: string;
33
33
  }
34
34
  declare function createInferenceClient(config: InferenceClientConfig, logger?: Logger): InferenceClient;
35
- declare function getInferenceClient(inferenceConfig: InferenceServiceConfig, logger?: Logger): Promise<InferenceClient>;
36
- /**
37
- * Get the configured model name
38
- */
39
- declare function getInferenceModel(inferenceConfig: InferenceServiceConfig): string;
40
35
 
41
36
  declare class AnthropicInferenceClient implements InferenceClient {
42
37
  private client;
@@ -72,4 +67,4 @@ declare class MockInferenceClient implements InferenceClient {
72
67
  setResponses(responses: string[], stopReasons?: string[]): void;
73
68
  }
74
69
 
75
- export { AnthropicInferenceClient, type InferenceClient, type InferenceClientConfig, type InferenceClientType, type InferenceResponse, MockInferenceClient, OllamaInferenceClient, createInferenceClient, getInferenceClient, getInferenceModel };
70
+ export { AnthropicInferenceClient, type InferenceClient, type InferenceClientConfig, type InferenceClientType, type InferenceResponse, MockInferenceClient, OllamaInferenceClient, createInferenceClient };
package/dist/index.js CHANGED
@@ -156,46 +156,6 @@ function createInferenceClient(config, logger) {
156
156
  throw new Error(`Unsupported inference client type: ${config.type}`);
157
157
  }
158
158
  }
159
- function evaluateEnvVar(value) {
160
- if (!value) return void 0;
161
- return value.replace(/\$\{([^}]+)\}/g, (match, varName) => {
162
- const envValue = process.env[varName];
163
- if (!envValue) {
164
- throw new Error(`Environment variable ${varName} is not set. Referenced in configuration as ${match}`);
165
- }
166
- return envValue;
167
- });
168
- }
169
- async function getInferenceClient(inferenceConfig, logger) {
170
- if (!inferenceConfig.model) {
171
- throw new Error("services.inference.model is required in environment config");
172
- }
173
- const clientConfig = {
174
- type: inferenceConfig.type,
175
- apiKey: evaluateEnvVar(inferenceConfig.apiKey),
176
- model: inferenceConfig.model,
177
- endpoint: inferenceConfig.endpoint,
178
- baseURL: inferenceConfig.baseURL
179
- };
180
- logger?.info("Loading inference client configuration", {
181
- type: clientConfig.type,
182
- model: clientConfig.model,
183
- endpoint: clientConfig.endpoint,
184
- hasApiKey: !!clientConfig.apiKey
185
- });
186
- const client = createInferenceClient(clientConfig, logger);
187
- logger?.info("Inference client initialized", {
188
- type: inferenceConfig.type,
189
- model: inferenceConfig.model
190
- });
191
- return client;
192
- }
193
- function getInferenceModel(inferenceConfig) {
194
- if (!inferenceConfig.model) {
195
- throw new Error("Inference model not configured! Set it in your environment configuration.");
196
- }
197
- return inferenceConfig.model;
198
- }
199
159
 
200
160
  // src/implementations/mock.ts
201
161
  var MockInferenceClient = class {
@@ -235,8 +195,6 @@ export {
235
195
  AnthropicInferenceClient,
236
196
  MockInferenceClient,
237
197
  OllamaInferenceClient,
238
- createInferenceClient,
239
- getInferenceClient,
240
- getInferenceModel
198
+ createInferenceClient
241
199
  };
242
200
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/implementations/anthropic.ts","../src/implementations/ollama.ts","../src/factory.ts","../src/implementations/mock.ts"],"sourcesContent":["// Anthropic Claude implementation of InferenceClient interface\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport type { Logger } from '@semiont/core';\nimport { InferenceClient, InferenceResponse } from '../interface.js';\n\nexport class AnthropicInferenceClient implements InferenceClient {\n private client: Anthropic;\n private model: string;\n private logger?: Logger;\n\n constructor(apiKey: string, model: string, baseURL?: string, logger?: Logger) {\n this.client = new Anthropic({\n apiKey,\n baseURL: baseURL || 'https://api.anthropic.com',\n });\n this.model = model;\n this.logger = logger;\n }\n\n async generateText(prompt: string, maxTokens: number, temperature: number): Promise<string> {\n const response = await this.generateTextWithMetadata(prompt, maxTokens, temperature);\n return response.text;\n }\n\n async generateTextWithMetadata(prompt: string, maxTokens: number, temperature: number): Promise<InferenceResponse> {\n this.logger?.debug('Generating text with inference client', {\n model: this.model,\n promptLength: prompt.length,\n maxTokens,\n temperature\n });\n\n const response = await this.client.messages.create({\n model: this.model,\n max_tokens: maxTokens,\n temperature,\n messages: [\n {\n role: 'user',\n content: prompt\n }\n ]\n });\n\n this.logger?.debug('Inference response received', {\n model: this.model,\n contentBlocks: response.content.length,\n stopReason: response.stop_reason\n });\n\n const textContent = response.content.find(c => c.type === 'text');\n\n if (!textContent || textContent.type !== 'text') {\n this.logger?.error('No text content in inference response', {\n model: this.model,\n contentTypes: response.content.map(c => c.type)\n });\n throw new Error('No text content in inference response');\n }\n\n this.logger?.info('Text generation completed', {\n model: this.model,\n textLength: textContent.text.length,\n stopReason: response.stop_reason\n });\n\n return {\n text: textContent.text,\n stopReason: response.stop_reason || 'unknown'\n };\n }\n}\n","// Ollama implementation of InferenceClient interface\n// Uses native Ollama HTTP API (no SDK dependency)\n\nimport type { Logger } from '@semiont/core';\nimport { InferenceClient, InferenceResponse } from '../interface.js';\n\ninterface OllamaGenerateResponse {\n response: string;\n done: boolean;\n done_reason?: string;\n}\n\nexport class OllamaInferenceClient implements InferenceClient {\n private baseURL: string;\n private model: string;\n private logger?: Logger;\n\n constructor(model: string, baseURL?: string, logger?: Logger) {\n this.baseURL = (baseURL || 'http://localhost:11434').replace(/\\/+$/, '');\n this.model = model;\n this.logger = logger;\n }\n\n async generateText(prompt: string, maxTokens: number, temperature: number): Promise<string> {\n const response = await this.generateTextWithMetadata(prompt, maxTokens, temperature);\n return response.text;\n }\n\n async generateTextWithMetadata(prompt: string, maxTokens: number, temperature: number): Promise<InferenceResponse> {\n this.logger?.debug('Generating text with Ollama', {\n model: this.model,\n promptLength: prompt.length,\n maxTokens,\n temperature\n });\n\n const url = `${this.baseURL}/api/generate`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: this.model,\n prompt,\n stream: false,\n options: {\n num_predict: maxTokens,\n temperature,\n },\n }),\n });\n\n if (!res.ok) {\n const body = await res.text();\n this.logger?.error('Ollama API error', {\n model: this.model,\n status: res.status,\n body,\n });\n throw new Error(`Ollama API error (${res.status}): ${body}`);\n }\n\n const data = await res.json() as OllamaGenerateResponse;\n\n if (!data.response) {\n this.logger?.error('Empty response from Ollama', { model: this.model });\n throw new Error('Empty response from Ollama');\n }\n\n const stopReason = mapStopReason(data.done_reason);\n\n this.logger?.info('Text generation completed', {\n model: this.model,\n textLength: data.response.length,\n stopReason,\n });\n\n return {\n text: data.response,\n stopReason,\n };\n }\n}\n\nfunction mapStopReason(doneReason: string | undefined): string {\n switch (doneReason) {\n case 'stop': return 'end_turn';\n case 'length': return 'max_tokens';\n default: return doneReason || 'unknown';\n }\n}\n","// Factory for creating inference client instances based on configuration\n\nimport type { InferenceServiceConfig, Logger } from '@semiont/core';\nimport { InferenceClient } from './interface.js';\nimport { AnthropicInferenceClient } from './implementations/anthropic.js';\nimport { OllamaInferenceClient } from './implementations/ollama.js';\n\nexport type InferenceClientType = 'anthropic' | 'ollama';\n\nexport interface InferenceClientConfig {\n type: InferenceClientType;\n apiKey?: string;\n model: string;\n endpoint?: string;\n baseURL?: string;\n}\n\nexport function createInferenceClient(config: InferenceClientConfig, logger?: Logger): InferenceClient {\n switch (config.type) {\n case 'anthropic': {\n if (!config.apiKey || config.apiKey.trim() === '') {\n throw new Error('apiKey is required for Anthropic inference client');\n }\n return new AnthropicInferenceClient(\n config.apiKey,\n config.model,\n config.endpoint || config.baseURL,\n logger\n );\n }\n\n case 'ollama': {\n return new OllamaInferenceClient(\n config.model,\n config.endpoint || config.baseURL,\n logger\n );\n }\n\n default:\n throw new Error(`Unsupported inference client type: ${config.type}`);\n }\n}\n\n// Helper function to evaluate environment variable placeholders\nfunction evaluateEnvVar(value: string | undefined): string | undefined {\n if (!value) return undefined;\n\n // Replace ${VAR_NAME} with actual environment variable value\n return value.replace(/\\$\\{([^}]+)\\}/g, (match, varName) => {\n const envValue = process.env[varName];\n if (!envValue) {\n throw new Error(`Environment variable ${varName} is not set. Referenced in configuration as ${match}`);\n }\n return envValue;\n });\n}\n\nexport async function getInferenceClient(inferenceConfig: InferenceServiceConfig, logger?: Logger): Promise<InferenceClient> {\n if (!inferenceConfig.model) {\n throw new Error('services.inference.model is required in environment config');\n }\n\n const clientConfig: InferenceClientConfig = {\n type: inferenceConfig.type as InferenceClientType,\n apiKey: evaluateEnvVar(inferenceConfig.apiKey),\n model: inferenceConfig.model,\n endpoint: inferenceConfig.endpoint,\n baseURL: inferenceConfig.baseURL,\n };\n\n logger?.info('Loading inference client configuration', {\n type: clientConfig.type,\n model: clientConfig.model,\n endpoint: clientConfig.endpoint,\n hasApiKey: !!clientConfig.apiKey\n });\n\n const client = createInferenceClient(clientConfig, logger);\n\n logger?.info('Inference client initialized', {\n type: inferenceConfig.type,\n model: inferenceConfig.model\n });\n return client;\n}\n\n/**\n * Get the configured model name\n */\nexport function getInferenceModel(inferenceConfig: InferenceServiceConfig): string {\n if (!inferenceConfig.model) {\n throw new Error('Inference model not configured! Set it in your environment configuration.');\n }\n return inferenceConfig.model;\n}\n\n","// Mock implementation of InferenceClient for testing\n\nimport { InferenceClient, InferenceResponse } from '../interface.js';\n\nexport class MockInferenceClient implements InferenceClient {\n private responses: string[] = [];\n private responseIndex: number = 0;\n private stopReasons: string[] = [];\n public calls: Array<{ prompt: string; maxTokens: number; temperature: number }> = [];\n\n constructor(responses: string[] = ['Mock response'], stopReasons?: string[]) {\n this.responses = responses;\n this.stopReasons = stopReasons || responses.map(() => 'end_turn');\n }\n\n async generateText(prompt: string, maxTokens: number, temperature: number): Promise<string> {\n const response = await this.generateTextWithMetadata(prompt, maxTokens, temperature);\n return response.text;\n }\n\n async generateTextWithMetadata(prompt: string, maxTokens: number, temperature: number): Promise<InferenceResponse> {\n this.calls.push({ prompt, maxTokens, temperature });\n\n const text = this.responses[this.responseIndex];\n const stopReason = this.stopReasons[this.responseIndex] || 'end_turn';\n\n if (this.responseIndex < this.responses.length - 1) {\n this.responseIndex++;\n }\n\n return { text, stopReason };\n }\n\n // Test helper methods\n reset(): void {\n this.calls = [];\n this.responseIndex = 0;\n }\n\n setResponses(responses: string[], stopReasons?: string[]): void {\n this.responses = responses;\n this.stopReasons = stopReasons || responses.map(() => 'end_turn');\n this.responseIndex = 0;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/implementations/anthropic.ts","../src/implementations/ollama.ts","../src/factory.ts","../src/implementations/mock.ts"],"sourcesContent":["// Anthropic Claude implementation of InferenceClient interface\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport type { Logger } from '@semiont/core';\nimport { InferenceClient, InferenceResponse } from '../interface.js';\n\nexport class AnthropicInferenceClient implements InferenceClient {\n private client: Anthropic;\n private model: string;\n private logger?: Logger;\n\n constructor(apiKey: string, model: string, baseURL?: string, logger?: Logger) {\n this.client = new Anthropic({\n apiKey,\n baseURL: baseURL || 'https://api.anthropic.com',\n });\n this.model = model;\n this.logger = logger;\n }\n\n async generateText(prompt: string, maxTokens: number, temperature: number): Promise<string> {\n const response = await this.generateTextWithMetadata(prompt, maxTokens, temperature);\n return response.text;\n }\n\n async generateTextWithMetadata(prompt: string, maxTokens: number, temperature: number): Promise<InferenceResponse> {\n this.logger?.debug('Generating text with inference client', {\n model: this.model,\n promptLength: prompt.length,\n maxTokens,\n temperature\n });\n\n const response = await this.client.messages.create({\n model: this.model,\n max_tokens: maxTokens,\n temperature,\n messages: [\n {\n role: 'user',\n content: prompt\n }\n ]\n });\n\n this.logger?.debug('Inference response received', {\n model: this.model,\n contentBlocks: response.content.length,\n stopReason: response.stop_reason\n });\n\n const textContent = response.content.find(c => c.type === 'text');\n\n if (!textContent || textContent.type !== 'text') {\n this.logger?.error('No text content in inference response', {\n model: this.model,\n contentTypes: response.content.map(c => c.type)\n });\n throw new Error('No text content in inference response');\n }\n\n this.logger?.info('Text generation completed', {\n model: this.model,\n textLength: textContent.text.length,\n stopReason: response.stop_reason\n });\n\n return {\n text: textContent.text,\n stopReason: response.stop_reason || 'unknown'\n };\n }\n}\n","// Ollama implementation of InferenceClient interface\n// Uses native Ollama HTTP API (no SDK dependency)\n\nimport type { Logger } from '@semiont/core';\nimport { InferenceClient, InferenceResponse } from '../interface.js';\n\ninterface OllamaGenerateResponse {\n response: string;\n done: boolean;\n done_reason?: string;\n}\n\nexport class OllamaInferenceClient implements InferenceClient {\n private baseURL: string;\n private model: string;\n private logger?: Logger;\n\n constructor(model: string, baseURL?: string, logger?: Logger) {\n this.baseURL = (baseURL || 'http://localhost:11434').replace(/\\/+$/, '');\n this.model = model;\n this.logger = logger;\n }\n\n async generateText(prompt: string, maxTokens: number, temperature: number): Promise<string> {\n const response = await this.generateTextWithMetadata(prompt, maxTokens, temperature);\n return response.text;\n }\n\n async generateTextWithMetadata(prompt: string, maxTokens: number, temperature: number): Promise<InferenceResponse> {\n this.logger?.debug('Generating text with Ollama', {\n model: this.model,\n promptLength: prompt.length,\n maxTokens,\n temperature\n });\n\n const url = `${this.baseURL}/api/generate`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: this.model,\n prompt,\n stream: false,\n options: {\n num_predict: maxTokens,\n temperature,\n },\n }),\n });\n\n if (!res.ok) {\n const body = await res.text();\n this.logger?.error('Ollama API error', {\n model: this.model,\n status: res.status,\n body,\n });\n throw new Error(`Ollama API error (${res.status}): ${body}`);\n }\n\n const data = await res.json() as OllamaGenerateResponse;\n\n if (!data.response) {\n this.logger?.error('Empty response from Ollama', { model: this.model });\n throw new Error('Empty response from Ollama');\n }\n\n const stopReason = mapStopReason(data.done_reason);\n\n this.logger?.info('Text generation completed', {\n model: this.model,\n textLength: data.response.length,\n stopReason,\n });\n\n return {\n text: data.response,\n stopReason,\n };\n }\n}\n\nfunction mapStopReason(doneReason: string | undefined): string {\n switch (doneReason) {\n case 'stop': return 'end_turn';\n case 'length': return 'max_tokens';\n default: return doneReason || 'unknown';\n }\n}\n","// Factory for creating inference client instances based on configuration\n\nimport type { Logger } from '@semiont/core';\nimport { InferenceClient } from './interface.js';\nimport { AnthropicInferenceClient } from './implementations/anthropic.js';\nimport { OllamaInferenceClient } from './implementations/ollama.js';\n\nexport type InferenceClientType = 'anthropic' | 'ollama';\n\nexport interface InferenceClientConfig {\n type: InferenceClientType;\n apiKey?: string;\n model: string;\n endpoint?: string;\n baseURL?: string;\n}\n\nexport function createInferenceClient(config: InferenceClientConfig, logger?: Logger): InferenceClient {\n switch (config.type) {\n case 'anthropic': {\n if (!config.apiKey || config.apiKey.trim() === '') {\n throw new Error('apiKey is required for Anthropic inference client');\n }\n return new AnthropicInferenceClient(\n config.apiKey,\n config.model,\n config.endpoint || config.baseURL,\n logger\n );\n }\n\n case 'ollama': {\n return new OllamaInferenceClient(\n config.model,\n config.endpoint || config.baseURL,\n logger\n );\n }\n\n default:\n throw new Error(`Unsupported inference client type: ${config.type}`);\n }\n}\n","// Mock implementation of InferenceClient for testing\n\nimport { InferenceClient, InferenceResponse } from '../interface.js';\n\nexport class MockInferenceClient implements InferenceClient {\n private responses: string[] = [];\n private responseIndex: number = 0;\n private stopReasons: string[] = [];\n public calls: Array<{ prompt: string; maxTokens: number; temperature: number }> = [];\n\n constructor(responses: string[] = ['Mock response'], stopReasons?: string[]) {\n this.responses = responses;\n this.stopReasons = stopReasons || responses.map(() => 'end_turn');\n }\n\n async generateText(prompt: string, maxTokens: number, temperature: number): Promise<string> {\n const response = await this.generateTextWithMetadata(prompt, maxTokens, temperature);\n return response.text;\n }\n\n async generateTextWithMetadata(prompt: string, maxTokens: number, temperature: number): Promise<InferenceResponse> {\n this.calls.push({ prompt, maxTokens, temperature });\n\n const text = this.responses[this.responseIndex];\n const stopReason = this.stopReasons[this.responseIndex] || 'end_turn';\n\n if (this.responseIndex < this.responses.length - 1) {\n this.responseIndex++;\n }\n\n return { text, stopReason };\n }\n\n // Test helper methods\n reset(): void {\n this.calls = [];\n this.responseIndex = 0;\n }\n\n setResponses(responses: string[], stopReasons?: string[]): void {\n this.responses = responses;\n this.stopReasons = stopReasons || responses.map(() => 'end_turn');\n this.responseIndex = 0;\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@semiont/inference",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "type": "module",
5
5
  "description": "AI inference capabilities for entity extraction, text generation, and resource creation",
6
6
  "main": "./dist/index.js",
@@ -26,13 +26,14 @@
26
26
  "dependencies": {
27
27
  "@anthropic-ai/sdk": "^0.63.0",
28
28
  "@semiont/api-client": "*",
29
- "@semiont/core": "*"
29
+ "@semiont/core": "*",
30
+ "@vitest/ui": "4.0.18"
30
31
  },
31
32
  "devDependencies": {
32
- "@vitest/coverage-v8": "^4.1.0",
33
+ "@vitest/coverage-v8": "^4.0.18",
33
34
  "tsup": "^8.0.1",
34
35
  "typescript": "^5.6.3",
35
- "vitest": "^4.1.0"
36
+ "vitest": "^4.0.18"
36
37
  },
37
38
  "publishConfig": {
38
39
  "access": "public"