hazo_llm_api 1.2.13 → 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 +321 -8
- package/config/hazo_llm_api_config.ini +38 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/llm_call_inspector/index.d.ts +6 -0
- package/dist/components/llm_call_inspector/index.d.ts.map +1 -0
- package/dist/components/llm_call_inspector/index.js +5 -0
- package/dist/components/llm_call_inspector/index.js.map +1 -0
- package/dist/components/llm_call_inspector/llm_call_inspector.d.ts +18 -0
- package/dist/components/llm_call_inspector/llm_call_inspector.d.ts.map +1 -0
- package/dist/components/llm_call_inspector/llm_call_inspector.js +103 -0
- package/dist/components/llm_call_inspector/llm_call_inspector.js.map +1 -0
- package/dist/components/llm_cost_dashboard/index.d.ts +6 -0
- package/dist/components/llm_cost_dashboard/index.d.ts.map +1 -0
- package/dist/components/llm_cost_dashboard/index.js +5 -0
- package/dist/components/llm_cost_dashboard/index.js.map +1 -0
- package/dist/components/llm_cost_dashboard/llm_cost_dashboard.d.ts +16 -0
- package/dist/components/llm_cost_dashboard/llm_cost_dashboard.d.ts.map +1 -0
- package/dist/components/llm_cost_dashboard/llm_cost_dashboard.js +154 -0
- package/dist/components/llm_cost_dashboard/llm_cost_dashboard.js.map +1 -0
- package/dist/components/prompt_editor/prompt_editor.d.ts.map +1 -1
- package/dist/components/prompt_editor/prompt_editor.js +3 -2
- package/dist/components/prompt_editor/prompt_editor.js.map +1 -1
- package/dist/components/prompt_editor/ui/alert_dialog.js +1 -1
- package/dist/components/prompt_editor/ui/alert_dialog.js.map +1 -1
- package/dist/components/prompt_editor/ui/button.js +1 -1
- package/dist/components/prompt_editor/ui/button.js.map +1 -1
- package/dist/components/prompt_editor/ui/checkbox.js +1 -1
- package/dist/components/prompt_editor/ui/checkbox.js.map +1 -1
- package/dist/components/prompt_editor/ui/dialog.js +1 -1
- package/dist/components/prompt_editor/ui/dialog.js.map +1 -1
- package/dist/components/prompt_editor/ui/index.d.ts +1 -1
- package/dist/components/prompt_editor/ui/index.d.ts.map +1 -1
- package/dist/components/prompt_editor/ui/index.js +1 -1
- package/dist/components/prompt_editor/ui/index.js.map +1 -1
- package/dist/components/prompt_editor/ui/input.js +1 -1
- package/dist/components/prompt_editor/ui/input.js.map +1 -1
- package/dist/components/prompt_editor/ui/textarea.js +1 -1
- package/dist/components/prompt_editor/ui/textarea.js.map +1 -1
- package/dist/components/prompt_editor/ui/tooltip.js +1 -1
- package/dist/components/prompt_editor/ui/tooltip.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/cascade/cascade_runner.d.ts +50 -0
- package/dist/lib/cascade/cascade_runner.d.ts.map +1 -0
- package/dist/lib/cascade/cascade_runner.js +115 -0
- package/dist/lib/cascade/cascade_runner.js.map +1 -0
- package/dist/lib/cascade/index.d.ts +5 -0
- package/dist/lib/cascade/index.d.ts.map +1 -0
- package/dist/lib/cascade/index.js +4 -0
- package/dist/lib/cascade/index.js.map +1 -0
- package/dist/lib/cascade/types.d.ts +35 -0
- package/dist/lib/cascade/types.d.ts.map +1 -0
- package/dist/lib/cascade/types.js +14 -0
- package/dist/lib/cascade/types.js.map +1 -0
- package/dist/lib/config/index.d.ts +1 -0
- package/dist/lib/config/index.d.ts.map +1 -1
- package/dist/lib/config/index.js +3 -0
- package/dist/lib/config/index.js.map +1 -1
- package/dist/lib/config/llm_api_config.d.ts +42 -0
- package/dist/lib/config/llm_api_config.d.ts.map +1 -0
- package/dist/lib/config/llm_api_config.js +49 -0
- package/dist/lib/config/llm_api_config.js.map +1 -0
- package/dist/lib/cost_cap/cost_cap.d.ts +40 -0
- package/dist/lib/cost_cap/cost_cap.d.ts.map +1 -0
- package/dist/lib/cost_cap/cost_cap.js +150 -0
- package/dist/lib/cost_cap/cost_cap.js.map +1 -0
- package/dist/lib/cost_cap/index.d.ts +3 -0
- package/dist/lib/cost_cap/index.d.ts.map +1 -0
- package/dist/lib/cost_cap/index.js +2 -0
- package/dist/lib/cost_cap/index.js.map +1 -0
- package/dist/lib/database/init_api_log.d.ts +10 -0
- package/dist/lib/database/init_api_log.d.ts.map +1 -0
- package/dist/lib/database/init_api_log.js +91 -0
- package/dist/lib/database/init_api_log.js.map +1 -0
- package/dist/lib/database/init_database.d.ts.map +1 -1
- package/dist/lib/database/init_database.js +2 -1
- package/dist/lib/database/init_database.js.map +1 -1
- package/dist/lib/hazo_connect/direct_db_connect.d.ts +11 -7
- package/dist/lib/hazo_connect/direct_db_connect.d.ts.map +1 -1
- package/dist/lib/hazo_connect/direct_db_connect.js +61 -7
- package/dist/lib/hazo_connect/direct_db_connect.js.map +1 -1
- package/dist/lib/hazo_connect/types.d.ts +35 -3
- package/dist/lib/hazo_connect/types.d.ts.map +1 -1
- package/dist/lib/llm_api/embed_cache.d.ts +15 -0
- package/dist/lib/llm_api/embed_cache.d.ts.map +1 -0
- package/dist/lib/llm_api/embed_cache.js +53 -0
- package/dist/lib/llm_api/embed_cache.js.map +1 -0
- package/dist/lib/llm_api/hazo_llm_document_text.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_document_text.js +56 -14
- package/dist/lib/llm_api/hazo_llm_document_text.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.js +19 -1
- package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_embed.d.ts +10 -0
- package/dist/lib/llm_api/hazo_llm_embed.d.ts.map +1 -0
- package/dist/lib/llm_api/hazo_llm_embed.js +80 -0
- package/dist/lib/llm_api/hazo_llm_embed.js.map +1 -0
- package/dist/lib/llm_api/hazo_llm_image_image.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_image_image.js +56 -14
- package/dist/lib/llm_api/hazo_llm_image_image.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_image_text.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_image_text.js +56 -14
- package/dist/lib/llm_api/hazo_llm_image_text.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_prompt_chain.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_prompt_chain.js +19 -2
- package/dist/lib/llm_api/hazo_llm_prompt_chain.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_text_image.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_text_image.js +56 -14
- package/dist/lib/llm_api/hazo_llm_text_image.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_text_text.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_text_text.js +90 -15
- package/dist/lib/llm_api/hazo_llm_text_text.js.map +1 -1
- package/dist/lib/llm_api/index.d.ts +31 -3
- package/dist/lib/llm_api/index.d.ts.map +1 -1
- package/dist/lib/llm_api/index.js +427 -35
- package/dist/lib/llm_api/index.js.map +1 -1
- package/dist/lib/llm_api/prompt_parts_helper.d.ts +15 -0
- package/dist/lib/llm_api/prompt_parts_helper.d.ts.map +1 -0
- package/dist/lib/llm_api/prompt_parts_helper.js +9 -0
- package/dist/lib/llm_api/prompt_parts_helper.js.map +1 -0
- package/dist/lib/llm_api/provider_helper.d.ts.map +1 -1
- package/dist/lib/llm_api/provider_helper.js +3 -38
- package/dist/lib/llm_api/provider_helper.js.map +1 -1
- package/dist/lib/llm_api/types.d.ts +187 -2
- package/dist/lib/llm_api/types.d.ts.map +1 -1
- package/dist/lib/llm_api/types.js +4 -0
- package/dist/lib/llm_api/types.js.map +1 -1
- package/dist/lib/maintenance/purge_log_job.d.ts +23 -0
- package/dist/lib/maintenance/purge_log_job.d.ts.map +1 -0
- package/dist/lib/maintenance/purge_log_job.js +49 -0
- package/dist/lib/maintenance/purge_log_job.js.map +1 -0
- package/dist/lib/observability/log_context.d.ts +15 -0
- package/dist/lib/observability/log_context.d.ts.map +1 -0
- package/dist/lib/observability/log_context.js +32 -0
- package/dist/lib/observability/log_context.js.map +1 -0
- package/dist/lib/observability/log_writer.d.ts +35 -0
- package/dist/lib/observability/log_writer.d.ts.map +1 -0
- package/dist/lib/observability/log_writer.js +106 -0
- package/dist/lib/observability/log_writer.js.map +1 -0
- package/dist/lib/observability/queries.d.ts +15 -0
- package/dist/lib/observability/queries.d.ts.map +1 -0
- package/dist/lib/observability/queries.js +78 -0
- package/dist/lib/observability/queries.js.map +1 -0
- package/dist/lib/observability/types.d.ts +77 -0
- package/dist/lib/observability/types.d.ts.map +1 -0
- package/dist/lib/observability/types.js +8 -0
- package/dist/lib/observability/types.js.map +1 -0
- package/dist/lib/pricing/pricing.d.ts +49 -0
- package/dist/lib/pricing/pricing.d.ts.map +1 -0
- package/dist/lib/pricing/pricing.js +153 -0
- package/dist/lib/pricing/pricing.js.map +1 -0
- package/dist/lib/pricing/pricing.json +75 -0
- package/dist/lib/pricing/types.d.ts +58 -0
- package/dist/lib/pricing/types.d.ts.map +1 -0
- package/dist/lib/pricing/types.js +8 -0
- package/dist/lib/pricing/types.js.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_client.d.ts +71 -0
- package/dist/lib/providers/anthropic/anthropic_client.d.ts.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_client.js +135 -0
- package/dist/lib/providers/anthropic/anthropic_client.js.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_provider.d.ts +60 -0
- package/dist/lib/providers/anthropic/anthropic_provider.d.ts.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_provider.js +273 -0
- package/dist/lib/providers/anthropic/anthropic_provider.js.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_response_to_usage.d.ts +21 -0
- package/dist/lib/providers/anthropic/anthropic_response_to_usage.d.ts.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_response_to_usage.js +46 -0
- package/dist/lib/providers/anthropic/anthropic_response_to_usage.js.map +1 -0
- package/dist/lib/providers/anthropic/index.d.ts +3 -0
- package/dist/lib/providers/anthropic/index.d.ts.map +1 -0
- package/dist/lib/providers/anthropic/index.js +2 -0
- package/dist/lib/providers/anthropic/index.js.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_client.d.ts +55 -0
- package/dist/lib/providers/deepseek/deepseek_client.d.ts.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_client.js +130 -0
- package/dist/lib/providers/deepseek/deepseek_client.js.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_provider.d.ts +50 -0
- package/dist/lib/providers/deepseek/deepseek_provider.d.ts.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_provider.js +147 -0
- package/dist/lib/providers/deepseek/deepseek_provider.js.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_response_to_usage.d.ts +21 -0
- package/dist/lib/providers/deepseek/deepseek_response_to_usage.d.ts.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_response_to_usage.js +40 -0
- package/dist/lib/providers/deepseek/deepseek_response_to_usage.js.map +1 -0
- package/dist/lib/providers/deepseek/index.d.ts +3 -0
- package/dist/lib/providers/deepseek/index.d.ts.map +1 -0
- package/dist/lib/providers/deepseek/index.js +2 -0
- package/dist/lib/providers/deepseek/index.js.map +1 -0
- package/dist/lib/providers/gemini/gemini_client.d.ts.map +1 -1
- package/dist/lib/providers/gemini/gemini_client.js +2 -1
- package/dist/lib/providers/gemini/gemini_client.js.map +1 -1
- package/dist/lib/providers/gemini/gemini_provider.d.ts.map +1 -1
- package/dist/lib/providers/gemini/gemini_provider.js +43 -6
- package/dist/lib/providers/gemini/gemini_provider.js.map +1 -1
- package/dist/lib/providers/gemini/gemini_response_to_usage.d.ts +37 -0
- package/dist/lib/providers/gemini/gemini_response_to_usage.d.ts.map +1 -0
- package/dist/lib/providers/gemini/gemini_response_to_usage.js +49 -0
- package/dist/lib/providers/gemini/gemini_response_to_usage.js.map +1 -0
- package/dist/lib/providers/index.d.ts +3 -0
- package/dist/lib/providers/index.d.ts.map +1 -1
- package/dist/lib/providers/index.js +3 -0
- package/dist/lib/providers/index.js.map +1 -1
- package/dist/lib/providers/openai/index.d.ts +3 -0
- package/dist/lib/providers/openai/index.d.ts.map +1 -0
- package/dist/lib/providers/openai/index.js +2 -0
- package/dist/lib/providers/openai/index.js.map +1 -0
- package/dist/lib/providers/openai/openai_client.d.ts +99 -0
- package/dist/lib/providers/openai/openai_client.d.ts.map +1 -0
- package/dist/lib/providers/openai/openai_client.js +188 -0
- package/dist/lib/providers/openai/openai_client.js.map +1 -0
- package/dist/lib/providers/openai/openai_provider.d.ts +66 -0
- package/dist/lib/providers/openai/openai_provider.d.ts.map +1 -0
- package/dist/lib/providers/openai/openai_provider.js +297 -0
- package/dist/lib/providers/openai/openai_provider.js.map +1 -0
- package/dist/lib/providers/openai/openai_response_to_usage.d.ts +21 -0
- package/dist/lib/providers/openai/openai_response_to_usage.d.ts.map +1 -0
- package/dist/lib/providers/openai/openai_response_to_usage.js +50 -0
- package/dist/lib/providers/openai/openai_response_to_usage.js.map +1 -0
- package/dist/lib/providers/qwen/qwen_client.d.ts.map +1 -1
- package/dist/lib/providers/qwen/qwen_client.js +10 -9
- package/dist/lib/providers/qwen/qwen_client.js.map +1 -1
- package/dist/lib/providers/qwen/qwen_provider.d.ts.map +1 -1
- package/dist/lib/providers/qwen/qwen_provider.js +58 -8
- package/dist/lib/providers/qwen/qwen_provider.js.map +1 -1
- package/dist/lib/providers/qwen/qwen_response_to_usage.d.ts +36 -0
- package/dist/lib/providers/qwen/qwen_response_to_usage.d.ts.map +1 -0
- package/dist/lib/providers/qwen/qwen_response_to_usage.js +50 -0
- package/dist/lib/providers/qwen/qwen_response_to_usage.js.map +1 -0
- package/dist/lib/providers/types.d.ts +16 -6
- package/dist/lib/providers/types.d.ts.map +1 -1
- package/dist/lib/providers/types.js +1 -0
- package/dist/lib/providers/types.js.map +1 -1
- package/dist/lib/utils.d.ts +13 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +16 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/server.d.ts +16 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +29 -2
- package/dist/server.js.map +1 -1
- package/migrations/db_setup_postgres.sql +68 -0
- package/migrations/db_setup_sqlite.sql +66 -0
- package/migrations/hazo_llm_api_log.sql +72 -0
- package/package.json +24 -6
|
@@ -25,11 +25,20 @@ import { hazo_llm_image_image_text as hazo_llm_image_image_text_internal } from
|
|
|
25
25
|
import { hazo_llm_prompt_chain as hazo_llm_prompt_chain_internal } from './hazo_llm_prompt_chain.js';
|
|
26
26
|
import { hazo_llm_document_text as hazo_llm_document_text_internal } from './hazo_llm_document_text.js';
|
|
27
27
|
import { hazo_llm_dynamic_data_extract as hazo_llm_dynamic_data_extract_internal } from './hazo_llm_dynamic_data_extract.js';
|
|
28
|
+
import { hazo_llm_embed_internal } from './hazo_llm_embed.js';
|
|
29
|
+
import { configure_embed_cache } from './embed_cache.js';
|
|
28
30
|
import { register_provider, set_enabled_llms, set_primary_llm, get_primary_llm, get_provider, } from '../providers/registry.js';
|
|
29
31
|
import { GeminiProvider } from '../providers/gemini/index.js';
|
|
30
32
|
import { QwenProvider } from '../providers/qwen/index.js';
|
|
33
|
+
import { AnthropicProvider } from '../providers/anthropic/index.js';
|
|
34
|
+
import { OpenAIProvider } from '../providers/openai/index.js';
|
|
35
|
+
import { DeepSeekProvider } from '../providers/deepseek/index.js';
|
|
31
36
|
import { SERVICE_TYPES } from '../providers/types.js';
|
|
32
37
|
import { create_request_context, call_before_request_hook, call_after_response_hook, call_on_error_hook, detect_error_code, } from './provider_helper.js';
|
|
38
|
+
import { ensure_api_log_table } from '../database/init_api_log.js';
|
|
39
|
+
import { create_default_after_response_hook } from '../observability/log_writer.js';
|
|
40
|
+
import { load_pricing, set_pricing_overrides } from '../pricing/pricing.js';
|
|
41
|
+
import { createLogger, HazoConfigError, HazoInternalError } from 'hazo_core';
|
|
33
42
|
import * as fs from 'fs';
|
|
34
43
|
import * as path from 'path';
|
|
35
44
|
import * as ini from 'ini';
|
|
@@ -40,27 +49,16 @@ let initialized = false;
|
|
|
40
49
|
let db_auto_initialized = false;
|
|
41
50
|
let current_config = null;
|
|
42
51
|
let stored_hazo_connect = null;
|
|
52
|
+
let stored_cascade_config = null;
|
|
53
|
+
let stored_cost_cap_config = null;
|
|
43
54
|
// =============================================================================
|
|
44
55
|
// Default Logger
|
|
45
56
|
// =============================================================================
|
|
46
57
|
/**
|
|
47
|
-
* Default
|
|
48
|
-
*
|
|
58
|
+
* Default structured logger used when no custom logger is provided.
|
|
59
|
+
* Delegates to hazo_logs when available, auto-injects correlationId and env.
|
|
49
60
|
*/
|
|
50
|
-
export const default_logger =
|
|
51
|
-
error: (message, meta) => {
|
|
52
|
-
console.error(`[HAZO_LLM_API ERROR] ${message}`, meta ? JSON.stringify(meta, null, 2) : '');
|
|
53
|
-
},
|
|
54
|
-
info: (message, meta) => {
|
|
55
|
-
console.log(`[HAZO_LLM_API INFO] ${message}`, meta ? JSON.stringify(meta, null, 2) : '');
|
|
56
|
-
},
|
|
57
|
-
warn: (message, meta) => {
|
|
58
|
-
console.warn(`[HAZO_LLM_API WARN] ${message}`, meta ? JSON.stringify(meta, null, 2) : '');
|
|
59
|
-
},
|
|
60
|
-
debug: (message, meta) => {
|
|
61
|
-
console.debug(`[HAZO_LLM_API DEBUG] ${message}`, meta ? JSON.stringify(meta, null, 2) : '');
|
|
62
|
-
},
|
|
63
|
-
};
|
|
61
|
+
export const default_logger = createLogger('hazo_llm_api');
|
|
64
62
|
/**
|
|
65
63
|
* Stored logger instance - set during initialization
|
|
66
64
|
*/
|
|
@@ -403,7 +401,7 @@ function load_api_key_from_env(provider_name) {
|
|
|
403
401
|
}
|
|
404
402
|
/**
|
|
405
403
|
* Read LLM global config from [llm] section
|
|
406
|
-
* @returns Object with enabled_llms and
|
|
404
|
+
* @returns Object with enabled_llms, primary_llm, sqlite_path, and optional cascade config
|
|
407
405
|
*/
|
|
408
406
|
function get_llm_global_config() {
|
|
409
407
|
const config_path = find_config_file();
|
|
@@ -424,10 +422,37 @@ function get_llm_global_config() {
|
|
|
424
422
|
const enabled_llms = parse_enabled_llms(llm_section.enabled_llms);
|
|
425
423
|
const primary_llm = llm_section.primary_llm || default_primary;
|
|
426
424
|
const sqlite_path = llm_section.sqlite_path || default_sqlite;
|
|
425
|
+
const cascade_section = config.llm_cascade;
|
|
426
|
+
let parsed_cascade;
|
|
427
|
+
if (cascade_section) {
|
|
428
|
+
parsed_cascade = {};
|
|
429
|
+
if (cascade_section.providers) {
|
|
430
|
+
parsed_cascade.providers = String(cascade_section.providers)
|
|
431
|
+
.split(',')
|
|
432
|
+
.map((s) => s.trim())
|
|
433
|
+
.filter(Boolean);
|
|
434
|
+
}
|
|
435
|
+
if (cascade_section.timeout_ms_per_attempt) {
|
|
436
|
+
const ms = parseInt(String(cascade_section.timeout_ms_per_attempt), 10);
|
|
437
|
+
if (!isNaN(ms) && ms > 0) {
|
|
438
|
+
parsed_cascade.timeout_ms_per_attempt = ms;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
if (cascade_section.cascade_on_codes) {
|
|
442
|
+
const codes = String(cascade_section.cascade_on_codes)
|
|
443
|
+
.split(',')
|
|
444
|
+
.map((s) => s.trim())
|
|
445
|
+
.filter(Boolean);
|
|
446
|
+
if (codes.length > 0) {
|
|
447
|
+
parsed_cascade.cascade_on_codes = codes;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
427
451
|
return {
|
|
428
452
|
enabled_llms: enabled_llms.length > 0 ? enabled_llms : default_enabled,
|
|
429
453
|
primary_llm,
|
|
430
454
|
sqlite_path,
|
|
455
|
+
cascade: parsed_cascade,
|
|
431
456
|
};
|
|
432
457
|
}
|
|
433
458
|
catch {
|
|
@@ -435,6 +460,7 @@ function get_llm_global_config() {
|
|
|
435
460
|
enabled_llms: default_enabled,
|
|
436
461
|
primary_llm: default_primary,
|
|
437
462
|
sqlite_path: default_sqlite,
|
|
463
|
+
cascade: undefined,
|
|
438
464
|
};
|
|
439
465
|
}
|
|
440
466
|
}
|
|
@@ -448,7 +474,6 @@ function load_gemini_provider_from_config(logger) {
|
|
|
448
474
|
if (!config_path) {
|
|
449
475
|
logger.warn('Config file not found, cannot load Gemini provider', {
|
|
450
476
|
file: 'index.ts',
|
|
451
|
-
line: 340,
|
|
452
477
|
});
|
|
453
478
|
return null;
|
|
454
479
|
}
|
|
@@ -462,7 +487,6 @@ function load_gemini_provider_from_config(logger) {
|
|
|
462
487
|
if (!api_key) {
|
|
463
488
|
logger.error(`${env_var_name} not found in environment variables`, {
|
|
464
489
|
file: 'index.ts',
|
|
465
|
-
line: 352,
|
|
466
490
|
data: { config_path, env_var_name },
|
|
467
491
|
});
|
|
468
492
|
return null;
|
|
@@ -492,7 +516,6 @@ function load_gemini_provider_from_config(logger) {
|
|
|
492
516
|
const error_message = error instanceof Error ? error.message : String(error);
|
|
493
517
|
logger.error('Failed to load Gemini provider from config', {
|
|
494
518
|
file: 'index.ts',
|
|
495
|
-
line: 378,
|
|
496
519
|
data: { error: error_message, config_path },
|
|
497
520
|
});
|
|
498
521
|
return null;
|
|
@@ -607,7 +630,6 @@ function load_qwen_provider_from_config(logger) {
|
|
|
607
630
|
if (!config_path) {
|
|
608
631
|
logger.warn('Config file not found, cannot load Qwen provider', {
|
|
609
632
|
file: 'index.ts',
|
|
610
|
-
line: 500,
|
|
611
633
|
});
|
|
612
634
|
return null;
|
|
613
635
|
}
|
|
@@ -621,7 +643,6 @@ function load_qwen_provider_from_config(logger) {
|
|
|
621
643
|
if (!api_key) {
|
|
622
644
|
logger.error(`${env_var_name} not found in environment variables`, {
|
|
623
645
|
file: 'index.ts',
|
|
624
|
-
line: 512,
|
|
625
646
|
data: { config_path, env_var_name },
|
|
626
647
|
});
|
|
627
648
|
return null;
|
|
@@ -654,7 +675,211 @@ function load_qwen_provider_from_config(logger) {
|
|
|
654
675
|
const error_message = error instanceof Error ? error.message : String(error);
|
|
655
676
|
logger.error('Failed to load Qwen provider from config', {
|
|
656
677
|
file: 'index.ts',
|
|
657
|
-
|
|
678
|
+
data: { error: error_message, config_path },
|
|
679
|
+
});
|
|
680
|
+
return null;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Load Anthropic provider from config file
|
|
685
|
+
* Reads [llm_anthropic] section + ANTHROPIC_API_KEY env var
|
|
686
|
+
*/
|
|
687
|
+
function load_anthropic_provider_from_config(logger) {
|
|
688
|
+
const config_path = find_config_file();
|
|
689
|
+
if (!config_path) {
|
|
690
|
+
logger.warn('Config file not found, cannot load Anthropic provider', {
|
|
691
|
+
file: 'index.ts',
|
|
692
|
+
});
|
|
693
|
+
return null;
|
|
694
|
+
}
|
|
695
|
+
try {
|
|
696
|
+
const config_content = fs.readFileSync(config_path, 'utf-8');
|
|
697
|
+
const config = ini.parse(config_content);
|
|
698
|
+
const section = config.llm_anthropic || {};
|
|
699
|
+
const env_var_name = section.api_key_env || 'ANTHROPIC_API_KEY';
|
|
700
|
+
const api_key = process.env[env_var_name];
|
|
701
|
+
if (!api_key) {
|
|
702
|
+
logger.error(`${env_var_name} not found in environment variables`, {
|
|
703
|
+
file: 'index.ts',
|
|
704
|
+
data: { config_path, env_var_name },
|
|
705
|
+
});
|
|
706
|
+
return null;
|
|
707
|
+
}
|
|
708
|
+
const capabilities = parse_capabilities(section.capabilities);
|
|
709
|
+
const generation_config = {};
|
|
710
|
+
let has_config = false;
|
|
711
|
+
if (section.text_max_tokens !== undefined) {
|
|
712
|
+
const v = parseInt(section.text_max_tokens, 10);
|
|
713
|
+
if (!isNaN(v)) {
|
|
714
|
+
generation_config.max_tokens = v;
|
|
715
|
+
has_config = true;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
if (section.text_temperature !== undefined) {
|
|
719
|
+
const v = parseFloat(section.text_temperature);
|
|
720
|
+
if (!isNaN(v)) {
|
|
721
|
+
generation_config.temperature = v;
|
|
722
|
+
has_config = true;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
const provider_config = {
|
|
726
|
+
api_key,
|
|
727
|
+
api_url: section.api_url,
|
|
728
|
+
api_version: section.api_version,
|
|
729
|
+
model_text_text: section.model_text_text,
|
|
730
|
+
model_image_text: section.model_image_text,
|
|
731
|
+
model_document_text: section.model_document_text,
|
|
732
|
+
generation_config: has_config ? generation_config : undefined,
|
|
733
|
+
capabilities: capabilities.length > 0 ? capabilities : undefined,
|
|
734
|
+
logger,
|
|
735
|
+
};
|
|
736
|
+
return new AnthropicProvider(provider_config);
|
|
737
|
+
}
|
|
738
|
+
catch (error) {
|
|
739
|
+
const error_message = error instanceof Error ? error.message : String(error);
|
|
740
|
+
logger.error('Failed to load Anthropic provider from config', {
|
|
741
|
+
file: 'index.ts',
|
|
742
|
+
data: { error: error_message, config_path },
|
|
743
|
+
});
|
|
744
|
+
return null;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Load OpenAI provider from config file
|
|
749
|
+
* Reads [llm_openai] section + OPENAI_API_KEY env var
|
|
750
|
+
*/
|
|
751
|
+
function load_openai_provider_from_config(logger) {
|
|
752
|
+
const config_path = find_config_file();
|
|
753
|
+
if (!config_path) {
|
|
754
|
+
logger.warn('Config file not found, cannot load OpenAI provider', {
|
|
755
|
+
file: 'index.ts',
|
|
756
|
+
});
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
try {
|
|
760
|
+
const config_content = fs.readFileSync(config_path, 'utf-8');
|
|
761
|
+
const config = ini.parse(config_content);
|
|
762
|
+
const section = config.llm_openai || {};
|
|
763
|
+
const env_var_name = section.api_key_env || 'OPENAI_API_KEY';
|
|
764
|
+
const api_key = process.env[env_var_name];
|
|
765
|
+
if (!api_key) {
|
|
766
|
+
logger.error(`${env_var_name} not found in environment variables`, {
|
|
767
|
+
file: 'index.ts',
|
|
768
|
+
data: { config_path, env_var_name },
|
|
769
|
+
});
|
|
770
|
+
return null;
|
|
771
|
+
}
|
|
772
|
+
const capabilities = parse_capabilities(section.capabilities);
|
|
773
|
+
const generation_config = {};
|
|
774
|
+
let has_config = false;
|
|
775
|
+
if (section.text_temperature !== undefined) {
|
|
776
|
+
const v = parseFloat(section.text_temperature);
|
|
777
|
+
if (!isNaN(v)) {
|
|
778
|
+
generation_config.temperature = v;
|
|
779
|
+
has_config = true;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
if (section.text_top_p !== undefined) {
|
|
783
|
+
const v = parseFloat(section.text_top_p);
|
|
784
|
+
if (!isNaN(v)) {
|
|
785
|
+
generation_config.top_p = v;
|
|
786
|
+
has_config = true;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
if (section.text_max_tokens !== undefined) {
|
|
790
|
+
const v = parseInt(section.text_max_tokens, 10);
|
|
791
|
+
if (!isNaN(v)) {
|
|
792
|
+
generation_config.max_tokens = v;
|
|
793
|
+
has_config = true;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
const provider_config = {
|
|
797
|
+
api_key,
|
|
798
|
+
api_url: section.api_url,
|
|
799
|
+
api_url_image: section.api_url_image,
|
|
800
|
+
api_url_embed: section.api_url_embed,
|
|
801
|
+
model_text_text: section.model_text_text,
|
|
802
|
+
model_image_text: section.model_image_text,
|
|
803
|
+
model_text_image: section.model_text_image,
|
|
804
|
+
model_embed: section.model_embed,
|
|
805
|
+
generation_config: has_config ? generation_config : undefined,
|
|
806
|
+
capabilities: capabilities.length > 0 ? capabilities : undefined,
|
|
807
|
+
logger,
|
|
808
|
+
};
|
|
809
|
+
return new OpenAIProvider(provider_config);
|
|
810
|
+
}
|
|
811
|
+
catch (error) {
|
|
812
|
+
const error_message = error instanceof Error ? error.message : String(error);
|
|
813
|
+
logger.error('Failed to load OpenAI provider from config', {
|
|
814
|
+
file: 'index.ts',
|
|
815
|
+
data: { error: error_message, config_path },
|
|
816
|
+
});
|
|
817
|
+
return null;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Load DeepSeek provider from config file
|
|
822
|
+
* Reads [llm_deepseek] section + DEEPSEEK_API_KEY env var
|
|
823
|
+
*/
|
|
824
|
+
function load_deepseek_provider_from_config(logger) {
|
|
825
|
+
const config_path = find_config_file();
|
|
826
|
+
if (!config_path) {
|
|
827
|
+
logger.warn('Config file not found, cannot load DeepSeek provider', {
|
|
828
|
+
file: 'index.ts',
|
|
829
|
+
});
|
|
830
|
+
return null;
|
|
831
|
+
}
|
|
832
|
+
try {
|
|
833
|
+
const config_content = fs.readFileSync(config_path, 'utf-8');
|
|
834
|
+
const config = ini.parse(config_content);
|
|
835
|
+
const section = config.llm_deepseek || {};
|
|
836
|
+
const env_var_name = section.api_key_env || 'DEEPSEEK_API_KEY';
|
|
837
|
+
const api_key = process.env[env_var_name];
|
|
838
|
+
if (!api_key) {
|
|
839
|
+
logger.error(`${env_var_name} not found in environment variables`, {
|
|
840
|
+
file: 'index.ts',
|
|
841
|
+
data: { config_path, env_var_name },
|
|
842
|
+
});
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
845
|
+
const capabilities = parse_capabilities(section.capabilities);
|
|
846
|
+
const generation_config = {};
|
|
847
|
+
let has_config = false;
|
|
848
|
+
if (section.text_temperature !== undefined) {
|
|
849
|
+
const v = parseFloat(section.text_temperature);
|
|
850
|
+
if (!isNaN(v)) {
|
|
851
|
+
generation_config.temperature = v;
|
|
852
|
+
has_config = true;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
if (section.text_top_p !== undefined) {
|
|
856
|
+
const v = parseFloat(section.text_top_p);
|
|
857
|
+
if (!isNaN(v)) {
|
|
858
|
+
generation_config.top_p = v;
|
|
859
|
+
has_config = true;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
if (section.text_max_tokens !== undefined) {
|
|
863
|
+
const v = parseInt(section.text_max_tokens, 10);
|
|
864
|
+
if (!isNaN(v)) {
|
|
865
|
+
generation_config.max_tokens = v;
|
|
866
|
+
has_config = true;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
const provider_config = {
|
|
870
|
+
api_key,
|
|
871
|
+
api_url: section.api_url,
|
|
872
|
+
model_text_text: section.model_text_text,
|
|
873
|
+
generation_config: has_config ? generation_config : undefined,
|
|
874
|
+
capabilities: capabilities.length > 0 ? capabilities : undefined,
|
|
875
|
+
logger,
|
|
876
|
+
};
|
|
877
|
+
return new DeepSeekProvider(provider_config);
|
|
878
|
+
}
|
|
879
|
+
catch (error) {
|
|
880
|
+
const error_message = error instanceof Error ? error.message : String(error);
|
|
881
|
+
logger.error('Failed to load DeepSeek provider from config', {
|
|
882
|
+
file: 'index.ts',
|
|
658
883
|
data: { error: error_message, config_path },
|
|
659
884
|
});
|
|
660
885
|
return null;
|
|
@@ -679,7 +904,6 @@ function load_and_register_providers(logger) {
|
|
|
679
904
|
else {
|
|
680
905
|
logger.warn('Gemini provider is enabled in config but failed to load. Check GEMINI_API_KEY in environment variables.', {
|
|
681
906
|
file: 'index.ts',
|
|
682
|
-
line: 716,
|
|
683
907
|
data: { llm_name: llm_name.toLowerCase() },
|
|
684
908
|
});
|
|
685
909
|
}
|
|
@@ -692,12 +916,47 @@ function load_and_register_providers(logger) {
|
|
|
692
916
|
else {
|
|
693
917
|
logger.warn('Qwen provider is enabled in config but failed to load. Check QWEN_API_KEY in environment variables.', {
|
|
694
918
|
file: 'index.ts',
|
|
695
|
-
line: 728,
|
|
696
919
|
data: { llm_name: llm_name.toLowerCase() },
|
|
697
920
|
});
|
|
698
921
|
}
|
|
699
922
|
}
|
|
700
|
-
|
|
923
|
+
else if (llm_name.toLowerCase() === 'anthropic') {
|
|
924
|
+
const provider = load_anthropic_provider_from_config(logger);
|
|
925
|
+
if (provider) {
|
|
926
|
+
register_provider(provider);
|
|
927
|
+
}
|
|
928
|
+
else {
|
|
929
|
+
logger.warn('Anthropic provider is enabled in config but failed to load. Check ANTHROPIC_API_KEY in environment variables.', {
|
|
930
|
+
file: 'index.ts',
|
|
931
|
+
data: { llm_name: llm_name.toLowerCase() },
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
else if (llm_name.toLowerCase() === 'openai') {
|
|
936
|
+
const provider = load_openai_provider_from_config(logger);
|
|
937
|
+
if (provider) {
|
|
938
|
+
register_provider(provider);
|
|
939
|
+
}
|
|
940
|
+
else {
|
|
941
|
+
logger.warn('OpenAI provider is enabled in config but failed to load. Check OPENAI_API_KEY in environment variables.', {
|
|
942
|
+
file: 'index.ts',
|
|
943
|
+
data: { llm_name: llm_name.toLowerCase() },
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
else if (llm_name.toLowerCase() === 'deepseek') {
|
|
948
|
+
const provider = load_deepseek_provider_from_config(logger);
|
|
949
|
+
if (provider) {
|
|
950
|
+
register_provider(provider);
|
|
951
|
+
}
|
|
952
|
+
else {
|
|
953
|
+
logger.warn('DeepSeek provider is enabled in config but failed to load. Check DEEPSEEK_API_KEY in environment variables.', {
|
|
954
|
+
file: 'index.ts',
|
|
955
|
+
data: { llm_name: llm_name.toLowerCase() },
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
// Future: Add other providers here
|
|
701
960
|
}
|
|
702
961
|
}
|
|
703
962
|
// =============================================================================
|
|
@@ -721,7 +980,6 @@ async function auto_initialize_database() {
|
|
|
721
980
|
const error_message = error instanceof Error ? error.message : String(error);
|
|
722
981
|
default_logger.error('Failed to auto-initialize database', {
|
|
723
982
|
file: file_name,
|
|
724
|
-
line: 124,
|
|
725
983
|
data: { error: error_message },
|
|
726
984
|
});
|
|
727
985
|
// Don't throw - allow manual initialization later
|
|
@@ -758,10 +1016,12 @@ export async function initialize_llm_api(config = {}) {
|
|
|
758
1016
|
const logger = config.logger || default_logger;
|
|
759
1017
|
// Store the logger for use by other functions
|
|
760
1018
|
set_logger(logger);
|
|
761
|
-
//
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
1019
|
+
// Reset hooks — will be set correctly after connect is established below
|
|
1020
|
+
set_hooks({});
|
|
1021
|
+
// Reset cascade config — will be set correctly below
|
|
1022
|
+
stored_cascade_config = null;
|
|
1023
|
+
// Reset cost cap config — will be set correctly below
|
|
1024
|
+
stored_cost_cap_config = null;
|
|
765
1025
|
// Get global config from file
|
|
766
1026
|
const global_config = get_llm_global_config();
|
|
767
1027
|
// Use provided sqlite_path or fall back to config file value
|
|
@@ -774,9 +1034,8 @@ export async function initialize_llm_api(config = {}) {
|
|
|
774
1034
|
const error_msg = 'No primary LLM configured. Set primary_llm in [llm] section of config file.';
|
|
775
1035
|
logger.error(error_msg, {
|
|
776
1036
|
file: file_name,
|
|
777
|
-
line: 615,
|
|
778
1037
|
});
|
|
779
|
-
throw new
|
|
1038
|
+
throw new HazoConfigError({ code: 'HAZO_LLM_API_NO_PRIMARY_LLM', pkg: 'hazo_llm_api', message: error_msg });
|
|
780
1039
|
}
|
|
781
1040
|
// Set final config
|
|
782
1041
|
const final_config = {
|
|
@@ -803,13 +1062,72 @@ export async function initialize_llm_api(config = {}) {
|
|
|
803
1062
|
}
|
|
804
1063
|
initialized = true;
|
|
805
1064
|
current_config = final_config;
|
|
1065
|
+
// Apply pricing table and any consumer overrides
|
|
1066
|
+
load_pricing();
|
|
1067
|
+
if (config.pricing_overrides) {
|
|
1068
|
+
set_pricing_overrides(config.pricing_overrides);
|
|
1069
|
+
}
|
|
1070
|
+
// Store resolved cascade config: init-time config takes precedence over INI
|
|
1071
|
+
stored_cascade_config = config.cascade ?? global_config.cascade ?? null;
|
|
1072
|
+
// Store cost cap config from consumer
|
|
1073
|
+
stored_cost_cap_config = config.cost_cap ?? null;
|
|
1074
|
+
// Configure embed cache from config
|
|
1075
|
+
if (config.embed_cache) {
|
|
1076
|
+
configure_embed_cache({
|
|
1077
|
+
max_size: config.embed_cache.max_size,
|
|
1078
|
+
keyv: config.embed_cache.keyv,
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
// Set up the log table + default afterResponse hook unless explicitly disabled
|
|
1082
|
+
const resolved_connect = stored_hazo_connect;
|
|
1083
|
+
const api_log_enabled = config.api_log?.enabled !== false;
|
|
1084
|
+
const consumer_after = config.hooks?.afterResponse;
|
|
1085
|
+
if (api_log_enabled && resolved_connect) {
|
|
1086
|
+
try {
|
|
1087
|
+
await ensure_api_log_table(resolved_connect, logger);
|
|
1088
|
+
// Ensure cost cap index exists for fast session-based SUM queries
|
|
1089
|
+
const { ensure_cost_cap_index } = await import('../cost_cap/cost_cap.js');
|
|
1090
|
+
await ensure_cost_cap_index(resolved_connect, logger);
|
|
1091
|
+
const default_hook = create_default_after_response_hook({
|
|
1092
|
+
connect: resolved_connect,
|
|
1093
|
+
logger,
|
|
1094
|
+
extract_context: config.api_log?.extract_context,
|
|
1095
|
+
});
|
|
1096
|
+
// Chain: default hook first, then consumer hook (if provided)
|
|
1097
|
+
const chained = consumer_after
|
|
1098
|
+
? async (ctx) => {
|
|
1099
|
+
await default_hook(ctx);
|
|
1100
|
+
await consumer_after(ctx);
|
|
1101
|
+
}
|
|
1102
|
+
: default_hook;
|
|
1103
|
+
set_hooks({
|
|
1104
|
+
...get_hooks(), // preserve any other hooks (beforeRequest, onError)
|
|
1105
|
+
...config.hooks, // merge consumer hooks
|
|
1106
|
+
afterResponse: chained,
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
catch (err) {
|
|
1110
|
+
logger.warn('api_log setup failed; calls will not be logged', {
|
|
1111
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1112
|
+
});
|
|
1113
|
+
// Fall through — install consumer hooks only, don't override with failing default
|
|
1114
|
+
if (config.hooks) {
|
|
1115
|
+
set_hooks(config.hooks);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
else {
|
|
1120
|
+
// api_log disabled or no connect: install consumer hooks as-is (or leave empty)
|
|
1121
|
+
if (config.hooks) {
|
|
1122
|
+
set_hooks(config.hooks);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
806
1125
|
// LLM API initialized successfully
|
|
807
1126
|
}
|
|
808
1127
|
catch (error) {
|
|
809
1128
|
const error_message = error instanceof Error ? error.message : String(error);
|
|
810
1129
|
logger.error('Failed to initialize LLM API', {
|
|
811
1130
|
file: file_name,
|
|
812
|
-
line: 653,
|
|
813
1131
|
data: { error: error_message },
|
|
814
1132
|
});
|
|
815
1133
|
throw error;
|
|
@@ -857,7 +1175,7 @@ export async function initialize_llm_api(config = {}) {
|
|
|
857
1175
|
*/
|
|
858
1176
|
function check_initialized() {
|
|
859
1177
|
if (!initialized || !current_config || !stored_hazo_connect) {
|
|
860
|
-
throw new
|
|
1178
|
+
throw new HazoInternalError({ code: 'HAZO_LLM_API_NOT_INITIALIZED', pkg: 'hazo_llm_api', message: 'LLM API not initialized. Call initialize_llm_api first.' });
|
|
861
1179
|
}
|
|
862
1180
|
// Ensure logger and hazo_connect are always present
|
|
863
1181
|
return {
|
|
@@ -1116,6 +1434,36 @@ export async function hazo_llm_dynamic_data_extract(params, llm) {
|
|
|
1116
1434
|
}
|
|
1117
1435
|
}
|
|
1118
1436
|
// =============================================================================
|
|
1437
|
+
// Embed Function
|
|
1438
|
+
// =============================================================================
|
|
1439
|
+
/**
|
|
1440
|
+
* Generate vector embeddings for one or more text inputs.
|
|
1441
|
+
* Caches results in-memory (or via BYO Keyv) and deduplicates repeated texts in batches.
|
|
1442
|
+
*
|
|
1443
|
+
* @param params - Text string or array of strings to embed, plus optional model override
|
|
1444
|
+
* @returns EmbedResponse with vectors, dimensions, model, and cache flags
|
|
1445
|
+
*
|
|
1446
|
+
* @example
|
|
1447
|
+
* ```typescript
|
|
1448
|
+
* import { hazo_llm_embed } from 'hazo_llm_api/server';
|
|
1449
|
+
*
|
|
1450
|
+
* const result = await hazo_llm_embed({ text: 'Hello world' });
|
|
1451
|
+
* if (result.success) {
|
|
1452
|
+
* console.log(result.vectors?.[0]); // number[]
|
|
1453
|
+
* }
|
|
1454
|
+
* ```
|
|
1455
|
+
*/
|
|
1456
|
+
export async function hazo_llm_embed(params, _llm) {
|
|
1457
|
+
try {
|
|
1458
|
+
const config = check_initialized();
|
|
1459
|
+
const logger = config.logger || default_logger;
|
|
1460
|
+
return hazo_llm_embed_internal(params, logger);
|
|
1461
|
+
}
|
|
1462
|
+
catch (error) {
|
|
1463
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
// =============================================================================
|
|
1119
1467
|
// Streaming Functions
|
|
1120
1468
|
// =============================================================================
|
|
1121
1469
|
/**
|
|
@@ -1173,6 +1521,21 @@ export async function* hazo_llm_text_text_stream(params, llm) {
|
|
|
1173
1521
|
};
|
|
1174
1522
|
return;
|
|
1175
1523
|
}
|
|
1524
|
+
// Cost cap pre-call gate
|
|
1525
|
+
const cost_cap_config = get_cost_cap_config();
|
|
1526
|
+
if (cost_cap_config) {
|
|
1527
|
+
const { check_cost_cap_gate } = await import('../cost_cap/cost_cap.js');
|
|
1528
|
+
const cap_block = await check_cost_cap_gate(stored_hazo_connect, cost_cap_config, logger);
|
|
1529
|
+
if (cap_block !== null) {
|
|
1530
|
+
yield {
|
|
1531
|
+
text: '',
|
|
1532
|
+
done: true,
|
|
1533
|
+
error: cap_block.error ?? cap_block.error_info?.message,
|
|
1534
|
+
error_info: cap_block.error_info,
|
|
1535
|
+
};
|
|
1536
|
+
return;
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1176
1539
|
// Call hooks and streaming method
|
|
1177
1540
|
const request_context = create_request_context(SERVICE_TYPES.TEXT_TEXT, provider.get_name(), {
|
|
1178
1541
|
prompt: params.prompt,
|
|
@@ -1267,6 +1630,21 @@ export async function* hazo_llm_image_text_stream(params, llm) {
|
|
|
1267
1630
|
};
|
|
1268
1631
|
return;
|
|
1269
1632
|
}
|
|
1633
|
+
// Cost cap pre-call gate
|
|
1634
|
+
const cost_cap_config = get_cost_cap_config();
|
|
1635
|
+
if (cost_cap_config) {
|
|
1636
|
+
const { check_cost_cap_gate } = await import('../cost_cap/cost_cap.js');
|
|
1637
|
+
const cap_block = await check_cost_cap_gate(stored_hazo_connect, cost_cap_config, logger);
|
|
1638
|
+
if (cap_block !== null) {
|
|
1639
|
+
yield {
|
|
1640
|
+
text: '',
|
|
1641
|
+
done: true,
|
|
1642
|
+
error: cap_block.error ?? cap_block.error_info?.message,
|
|
1643
|
+
error_info: cap_block.error_info,
|
|
1644
|
+
};
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1270
1648
|
// Call hooks and streaming method
|
|
1271
1649
|
const request_context = create_request_context(SERVICE_TYPES.IMAGE_TEXT, provider.get_name(), {
|
|
1272
1650
|
prompt: params.prompt,
|
|
@@ -1329,6 +1707,20 @@ export async function* hazo_llm_image_text_stream(params, llm) {
|
|
|
1329
1707
|
export function is_initialized() {
|
|
1330
1708
|
return initialized;
|
|
1331
1709
|
}
|
|
1710
|
+
/**
|
|
1711
|
+
* Get the current cascade configuration (from init or INI).
|
|
1712
|
+
* Returns null if no cascade config has been set.
|
|
1713
|
+
*/
|
|
1714
|
+
export function get_cascade_config() {
|
|
1715
|
+
return stored_cascade_config;
|
|
1716
|
+
}
|
|
1717
|
+
/**
|
|
1718
|
+
* Get the current cost cap configuration (set during initialize_llm_api).
|
|
1719
|
+
* Returns null if no cost cap config has been set.
|
|
1720
|
+
*/
|
|
1721
|
+
export function get_cost_cap_config() {
|
|
1722
|
+
return stored_cost_cap_config;
|
|
1723
|
+
}
|
|
1332
1724
|
/**
|
|
1333
1725
|
* Get the current configuration (without sensitive logger)
|
|
1334
1726
|
* @returns Current configuration or null if not initialized
|