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.
Files changed (247) hide show
  1. package/README.md +321 -8
  2. package/config/hazo_llm_api_config.ini +38 -0
  3. package/dist/components/index.d.ts +2 -0
  4. package/dist/components/index.d.ts.map +1 -1
  5. package/dist/components/index.js +2 -0
  6. package/dist/components/index.js.map +1 -1
  7. package/dist/components/llm_call_inspector/index.d.ts +6 -0
  8. package/dist/components/llm_call_inspector/index.d.ts.map +1 -0
  9. package/dist/components/llm_call_inspector/index.js +5 -0
  10. package/dist/components/llm_call_inspector/index.js.map +1 -0
  11. package/dist/components/llm_call_inspector/llm_call_inspector.d.ts +18 -0
  12. package/dist/components/llm_call_inspector/llm_call_inspector.d.ts.map +1 -0
  13. package/dist/components/llm_call_inspector/llm_call_inspector.js +103 -0
  14. package/dist/components/llm_call_inspector/llm_call_inspector.js.map +1 -0
  15. package/dist/components/llm_cost_dashboard/index.d.ts +6 -0
  16. package/dist/components/llm_cost_dashboard/index.d.ts.map +1 -0
  17. package/dist/components/llm_cost_dashboard/index.js +5 -0
  18. package/dist/components/llm_cost_dashboard/index.js.map +1 -0
  19. package/dist/components/llm_cost_dashboard/llm_cost_dashboard.d.ts +16 -0
  20. package/dist/components/llm_cost_dashboard/llm_cost_dashboard.d.ts.map +1 -0
  21. package/dist/components/llm_cost_dashboard/llm_cost_dashboard.js +154 -0
  22. package/dist/components/llm_cost_dashboard/llm_cost_dashboard.js.map +1 -0
  23. package/dist/components/prompt_editor/prompt_editor.d.ts.map +1 -1
  24. package/dist/components/prompt_editor/prompt_editor.js +3 -2
  25. package/dist/components/prompt_editor/prompt_editor.js.map +1 -1
  26. package/dist/components/prompt_editor/ui/alert_dialog.js +1 -1
  27. package/dist/components/prompt_editor/ui/alert_dialog.js.map +1 -1
  28. package/dist/components/prompt_editor/ui/button.js +1 -1
  29. package/dist/components/prompt_editor/ui/button.js.map +1 -1
  30. package/dist/components/prompt_editor/ui/checkbox.js +1 -1
  31. package/dist/components/prompt_editor/ui/checkbox.js.map +1 -1
  32. package/dist/components/prompt_editor/ui/dialog.js +1 -1
  33. package/dist/components/prompt_editor/ui/dialog.js.map +1 -1
  34. package/dist/components/prompt_editor/ui/index.d.ts +1 -1
  35. package/dist/components/prompt_editor/ui/index.d.ts.map +1 -1
  36. package/dist/components/prompt_editor/ui/index.js +1 -1
  37. package/dist/components/prompt_editor/ui/index.js.map +1 -1
  38. package/dist/components/prompt_editor/ui/input.js +1 -1
  39. package/dist/components/prompt_editor/ui/input.js.map +1 -1
  40. package/dist/components/prompt_editor/ui/textarea.js +1 -1
  41. package/dist/components/prompt_editor/ui/textarea.js.map +1 -1
  42. package/dist/components/prompt_editor/ui/tooltip.js +1 -1
  43. package/dist/components/prompt_editor/ui/tooltip.js.map +1 -1
  44. package/dist/index.d.ts +2 -1
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/lib/cascade/cascade_runner.d.ts +50 -0
  47. package/dist/lib/cascade/cascade_runner.d.ts.map +1 -0
  48. package/dist/lib/cascade/cascade_runner.js +115 -0
  49. package/dist/lib/cascade/cascade_runner.js.map +1 -0
  50. package/dist/lib/cascade/index.d.ts +5 -0
  51. package/dist/lib/cascade/index.d.ts.map +1 -0
  52. package/dist/lib/cascade/index.js +4 -0
  53. package/dist/lib/cascade/index.js.map +1 -0
  54. package/dist/lib/cascade/types.d.ts +35 -0
  55. package/dist/lib/cascade/types.d.ts.map +1 -0
  56. package/dist/lib/cascade/types.js +14 -0
  57. package/dist/lib/cascade/types.js.map +1 -0
  58. package/dist/lib/config/index.d.ts +1 -0
  59. package/dist/lib/config/index.d.ts.map +1 -1
  60. package/dist/lib/config/index.js +3 -0
  61. package/dist/lib/config/index.js.map +1 -1
  62. package/dist/lib/config/llm_api_config.d.ts +42 -0
  63. package/dist/lib/config/llm_api_config.d.ts.map +1 -0
  64. package/dist/lib/config/llm_api_config.js +49 -0
  65. package/dist/lib/config/llm_api_config.js.map +1 -0
  66. package/dist/lib/cost_cap/cost_cap.d.ts +40 -0
  67. package/dist/lib/cost_cap/cost_cap.d.ts.map +1 -0
  68. package/dist/lib/cost_cap/cost_cap.js +150 -0
  69. package/dist/lib/cost_cap/cost_cap.js.map +1 -0
  70. package/dist/lib/cost_cap/index.d.ts +3 -0
  71. package/dist/lib/cost_cap/index.d.ts.map +1 -0
  72. package/dist/lib/cost_cap/index.js +2 -0
  73. package/dist/lib/cost_cap/index.js.map +1 -0
  74. package/dist/lib/database/init_api_log.d.ts +10 -0
  75. package/dist/lib/database/init_api_log.d.ts.map +1 -0
  76. package/dist/lib/database/init_api_log.js +91 -0
  77. package/dist/lib/database/init_api_log.js.map +1 -0
  78. package/dist/lib/database/init_database.d.ts.map +1 -1
  79. package/dist/lib/database/init_database.js +2 -1
  80. package/dist/lib/database/init_database.js.map +1 -1
  81. package/dist/lib/hazo_connect/direct_db_connect.d.ts +11 -7
  82. package/dist/lib/hazo_connect/direct_db_connect.d.ts.map +1 -1
  83. package/dist/lib/hazo_connect/direct_db_connect.js +61 -7
  84. package/dist/lib/hazo_connect/direct_db_connect.js.map +1 -1
  85. package/dist/lib/hazo_connect/types.d.ts +35 -3
  86. package/dist/lib/hazo_connect/types.d.ts.map +1 -1
  87. package/dist/lib/llm_api/embed_cache.d.ts +15 -0
  88. package/dist/lib/llm_api/embed_cache.d.ts.map +1 -0
  89. package/dist/lib/llm_api/embed_cache.js +53 -0
  90. package/dist/lib/llm_api/embed_cache.js.map +1 -0
  91. package/dist/lib/llm_api/hazo_llm_document_text.d.ts.map +1 -1
  92. package/dist/lib/llm_api/hazo_llm_document_text.js +56 -14
  93. package/dist/lib/llm_api/hazo_llm_document_text.js.map +1 -1
  94. package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.d.ts.map +1 -1
  95. package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.js +19 -1
  96. package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.js.map +1 -1
  97. package/dist/lib/llm_api/hazo_llm_embed.d.ts +10 -0
  98. package/dist/lib/llm_api/hazo_llm_embed.d.ts.map +1 -0
  99. package/dist/lib/llm_api/hazo_llm_embed.js +80 -0
  100. package/dist/lib/llm_api/hazo_llm_embed.js.map +1 -0
  101. package/dist/lib/llm_api/hazo_llm_image_image.d.ts.map +1 -1
  102. package/dist/lib/llm_api/hazo_llm_image_image.js +56 -14
  103. package/dist/lib/llm_api/hazo_llm_image_image.js.map +1 -1
  104. package/dist/lib/llm_api/hazo_llm_image_text.d.ts.map +1 -1
  105. package/dist/lib/llm_api/hazo_llm_image_text.js +56 -14
  106. package/dist/lib/llm_api/hazo_llm_image_text.js.map +1 -1
  107. package/dist/lib/llm_api/hazo_llm_prompt_chain.d.ts.map +1 -1
  108. package/dist/lib/llm_api/hazo_llm_prompt_chain.js +19 -2
  109. package/dist/lib/llm_api/hazo_llm_prompt_chain.js.map +1 -1
  110. package/dist/lib/llm_api/hazo_llm_text_image.d.ts.map +1 -1
  111. package/dist/lib/llm_api/hazo_llm_text_image.js +56 -14
  112. package/dist/lib/llm_api/hazo_llm_text_image.js.map +1 -1
  113. package/dist/lib/llm_api/hazo_llm_text_text.d.ts.map +1 -1
  114. package/dist/lib/llm_api/hazo_llm_text_text.js +90 -15
  115. package/dist/lib/llm_api/hazo_llm_text_text.js.map +1 -1
  116. package/dist/lib/llm_api/index.d.ts +31 -3
  117. package/dist/lib/llm_api/index.d.ts.map +1 -1
  118. package/dist/lib/llm_api/index.js +427 -35
  119. package/dist/lib/llm_api/index.js.map +1 -1
  120. package/dist/lib/llm_api/prompt_parts_helper.d.ts +15 -0
  121. package/dist/lib/llm_api/prompt_parts_helper.d.ts.map +1 -0
  122. package/dist/lib/llm_api/prompt_parts_helper.js +9 -0
  123. package/dist/lib/llm_api/prompt_parts_helper.js.map +1 -0
  124. package/dist/lib/llm_api/provider_helper.d.ts.map +1 -1
  125. package/dist/lib/llm_api/provider_helper.js +3 -38
  126. package/dist/lib/llm_api/provider_helper.js.map +1 -1
  127. package/dist/lib/llm_api/types.d.ts +187 -2
  128. package/dist/lib/llm_api/types.d.ts.map +1 -1
  129. package/dist/lib/llm_api/types.js +4 -0
  130. package/dist/lib/llm_api/types.js.map +1 -1
  131. package/dist/lib/maintenance/purge_log_job.d.ts +23 -0
  132. package/dist/lib/maintenance/purge_log_job.d.ts.map +1 -0
  133. package/dist/lib/maintenance/purge_log_job.js +49 -0
  134. package/dist/lib/maintenance/purge_log_job.js.map +1 -0
  135. package/dist/lib/observability/log_context.d.ts +15 -0
  136. package/dist/lib/observability/log_context.d.ts.map +1 -0
  137. package/dist/lib/observability/log_context.js +32 -0
  138. package/dist/lib/observability/log_context.js.map +1 -0
  139. package/dist/lib/observability/log_writer.d.ts +35 -0
  140. package/dist/lib/observability/log_writer.d.ts.map +1 -0
  141. package/dist/lib/observability/log_writer.js +106 -0
  142. package/dist/lib/observability/log_writer.js.map +1 -0
  143. package/dist/lib/observability/queries.d.ts +15 -0
  144. package/dist/lib/observability/queries.d.ts.map +1 -0
  145. package/dist/lib/observability/queries.js +78 -0
  146. package/dist/lib/observability/queries.js.map +1 -0
  147. package/dist/lib/observability/types.d.ts +77 -0
  148. package/dist/lib/observability/types.d.ts.map +1 -0
  149. package/dist/lib/observability/types.js +8 -0
  150. package/dist/lib/observability/types.js.map +1 -0
  151. package/dist/lib/pricing/pricing.d.ts +49 -0
  152. package/dist/lib/pricing/pricing.d.ts.map +1 -0
  153. package/dist/lib/pricing/pricing.js +153 -0
  154. package/dist/lib/pricing/pricing.js.map +1 -0
  155. package/dist/lib/pricing/pricing.json +75 -0
  156. package/dist/lib/pricing/types.d.ts +58 -0
  157. package/dist/lib/pricing/types.d.ts.map +1 -0
  158. package/dist/lib/pricing/types.js +8 -0
  159. package/dist/lib/pricing/types.js.map +1 -0
  160. package/dist/lib/providers/anthropic/anthropic_client.d.ts +71 -0
  161. package/dist/lib/providers/anthropic/anthropic_client.d.ts.map +1 -0
  162. package/dist/lib/providers/anthropic/anthropic_client.js +135 -0
  163. package/dist/lib/providers/anthropic/anthropic_client.js.map +1 -0
  164. package/dist/lib/providers/anthropic/anthropic_provider.d.ts +60 -0
  165. package/dist/lib/providers/anthropic/anthropic_provider.d.ts.map +1 -0
  166. package/dist/lib/providers/anthropic/anthropic_provider.js +273 -0
  167. package/dist/lib/providers/anthropic/anthropic_provider.js.map +1 -0
  168. package/dist/lib/providers/anthropic/anthropic_response_to_usage.d.ts +21 -0
  169. package/dist/lib/providers/anthropic/anthropic_response_to_usage.d.ts.map +1 -0
  170. package/dist/lib/providers/anthropic/anthropic_response_to_usage.js +46 -0
  171. package/dist/lib/providers/anthropic/anthropic_response_to_usage.js.map +1 -0
  172. package/dist/lib/providers/anthropic/index.d.ts +3 -0
  173. package/dist/lib/providers/anthropic/index.d.ts.map +1 -0
  174. package/dist/lib/providers/anthropic/index.js +2 -0
  175. package/dist/lib/providers/anthropic/index.js.map +1 -0
  176. package/dist/lib/providers/deepseek/deepseek_client.d.ts +55 -0
  177. package/dist/lib/providers/deepseek/deepseek_client.d.ts.map +1 -0
  178. package/dist/lib/providers/deepseek/deepseek_client.js +130 -0
  179. package/dist/lib/providers/deepseek/deepseek_client.js.map +1 -0
  180. package/dist/lib/providers/deepseek/deepseek_provider.d.ts +50 -0
  181. package/dist/lib/providers/deepseek/deepseek_provider.d.ts.map +1 -0
  182. package/dist/lib/providers/deepseek/deepseek_provider.js +147 -0
  183. package/dist/lib/providers/deepseek/deepseek_provider.js.map +1 -0
  184. package/dist/lib/providers/deepseek/deepseek_response_to_usage.d.ts +21 -0
  185. package/dist/lib/providers/deepseek/deepseek_response_to_usage.d.ts.map +1 -0
  186. package/dist/lib/providers/deepseek/deepseek_response_to_usage.js +40 -0
  187. package/dist/lib/providers/deepseek/deepseek_response_to_usage.js.map +1 -0
  188. package/dist/lib/providers/deepseek/index.d.ts +3 -0
  189. package/dist/lib/providers/deepseek/index.d.ts.map +1 -0
  190. package/dist/lib/providers/deepseek/index.js +2 -0
  191. package/dist/lib/providers/deepseek/index.js.map +1 -0
  192. package/dist/lib/providers/gemini/gemini_client.d.ts.map +1 -1
  193. package/dist/lib/providers/gemini/gemini_client.js +2 -1
  194. package/dist/lib/providers/gemini/gemini_client.js.map +1 -1
  195. package/dist/lib/providers/gemini/gemini_provider.d.ts.map +1 -1
  196. package/dist/lib/providers/gemini/gemini_provider.js +43 -6
  197. package/dist/lib/providers/gemini/gemini_provider.js.map +1 -1
  198. package/dist/lib/providers/gemini/gemini_response_to_usage.d.ts +37 -0
  199. package/dist/lib/providers/gemini/gemini_response_to_usage.d.ts.map +1 -0
  200. package/dist/lib/providers/gemini/gemini_response_to_usage.js +49 -0
  201. package/dist/lib/providers/gemini/gemini_response_to_usage.js.map +1 -0
  202. package/dist/lib/providers/index.d.ts +3 -0
  203. package/dist/lib/providers/index.d.ts.map +1 -1
  204. package/dist/lib/providers/index.js +3 -0
  205. package/dist/lib/providers/index.js.map +1 -1
  206. package/dist/lib/providers/openai/index.d.ts +3 -0
  207. package/dist/lib/providers/openai/index.d.ts.map +1 -0
  208. package/dist/lib/providers/openai/index.js +2 -0
  209. package/dist/lib/providers/openai/index.js.map +1 -0
  210. package/dist/lib/providers/openai/openai_client.d.ts +99 -0
  211. package/dist/lib/providers/openai/openai_client.d.ts.map +1 -0
  212. package/dist/lib/providers/openai/openai_client.js +188 -0
  213. package/dist/lib/providers/openai/openai_client.js.map +1 -0
  214. package/dist/lib/providers/openai/openai_provider.d.ts +66 -0
  215. package/dist/lib/providers/openai/openai_provider.d.ts.map +1 -0
  216. package/dist/lib/providers/openai/openai_provider.js +297 -0
  217. package/dist/lib/providers/openai/openai_provider.js.map +1 -0
  218. package/dist/lib/providers/openai/openai_response_to_usage.d.ts +21 -0
  219. package/dist/lib/providers/openai/openai_response_to_usage.d.ts.map +1 -0
  220. package/dist/lib/providers/openai/openai_response_to_usage.js +50 -0
  221. package/dist/lib/providers/openai/openai_response_to_usage.js.map +1 -0
  222. package/dist/lib/providers/qwen/qwen_client.d.ts.map +1 -1
  223. package/dist/lib/providers/qwen/qwen_client.js +10 -9
  224. package/dist/lib/providers/qwen/qwen_client.js.map +1 -1
  225. package/dist/lib/providers/qwen/qwen_provider.d.ts.map +1 -1
  226. package/dist/lib/providers/qwen/qwen_provider.js +58 -8
  227. package/dist/lib/providers/qwen/qwen_provider.js.map +1 -1
  228. package/dist/lib/providers/qwen/qwen_response_to_usage.d.ts +36 -0
  229. package/dist/lib/providers/qwen/qwen_response_to_usage.d.ts.map +1 -0
  230. package/dist/lib/providers/qwen/qwen_response_to_usage.js +50 -0
  231. package/dist/lib/providers/qwen/qwen_response_to_usage.js.map +1 -0
  232. package/dist/lib/providers/types.d.ts +16 -6
  233. package/dist/lib/providers/types.d.ts.map +1 -1
  234. package/dist/lib/providers/types.js +1 -0
  235. package/dist/lib/providers/types.js.map +1 -1
  236. package/dist/lib/utils.d.ts +13 -0
  237. package/dist/lib/utils.d.ts.map +1 -0
  238. package/dist/lib/utils.js +16 -0
  239. package/dist/lib/utils.js.map +1 -0
  240. package/dist/server.d.ts +16 -2
  241. package/dist/server.d.ts.map +1 -1
  242. package/dist/server.js +29 -2
  243. package/dist/server.js.map +1 -1
  244. package/migrations/db_setup_postgres.sql +68 -0
  245. package/migrations/db_setup_sqlite.sql +66 -0
  246. package/migrations/hazo_llm_api_log.sql +72 -0
  247. package/package.json +24 -6
@@ -0,0 +1,115 @@
1
+ // file_description: Cascade runner — tries LLM providers in order until one succeeds
2
+ import { LLM_ERROR_CODES } from '../llm_api/types.js';
3
+ import { DEFAULT_CASCADE_ON_CODES } from './types.js';
4
+ // =============================================================================
5
+ // resolve_providers
6
+ // =============================================================================
7
+ /**
8
+ * Determine the ordered list of provider names to use.
9
+ * Precedence: per-call providers > init cascade providers > single_llm arg > primary_llm.
10
+ * An empty per_call array is treated as "not set" (falls through).
11
+ */
12
+ export function resolve_providers(opts) {
13
+ const { per_call, init_cascade, single_llm, primary_llm } = opts;
14
+ if (per_call && per_call.length > 0) {
15
+ return per_call;
16
+ }
17
+ if (init_cascade?.providers && init_cascade.providers.length > 0) {
18
+ return init_cascade.providers;
19
+ }
20
+ if (single_llm) {
21
+ return [single_llm];
22
+ }
23
+ return [primary_llm];
24
+ }
25
+ // =============================================================================
26
+ // run_with_cascade
27
+ // =============================================================================
28
+ /**
29
+ * Try each provider in order, returning the first successful response.
30
+ *
31
+ * Rules:
32
+ * - Success on first try → `attempts` is empty (no cascade record).
33
+ * - Cascadable error (RATE_LIMITED, NETWORK_ERROR, TIMEOUT, API_ERROR by default) →
34
+ * record attempt, try next provider.
35
+ * - Non-cascadable error (config errors: PROVIDER_NOT_FOUND, API_KEY_MISSING, etc.) →
36
+ * return immediately without trying more providers.
37
+ * - Timeout → treated as TIMEOUT error code, always cascadable.
38
+ * - All providers exhausted → return last error with all attempts recorded.
39
+ */
40
+ export async function run_with_cascade(opts) {
41
+ const { providers, call_fn, cascade_on_codes = DEFAULT_CASCADE_ON_CODES, timeout_ms_per_attempt, logger, } = opts;
42
+ const attempts = [];
43
+ for (let i = 0; i < providers.length; i++) {
44
+ const provider = providers[i];
45
+ const provider_name = provider.get_name();
46
+ const is_last = i === providers.length - 1;
47
+ const t0 = Date.now();
48
+ let response;
49
+ try {
50
+ if (timeout_ms_per_attempt) {
51
+ response = await Promise.race([
52
+ call_fn(provider),
53
+ make_timeout_promise(timeout_ms_per_attempt, provider_name),
54
+ ]);
55
+ }
56
+ else {
57
+ response = await call_fn(provider);
58
+ }
59
+ }
60
+ catch (err) {
61
+ // Thrown exception: timeout or unhandled provider throw
62
+ const latency_ms = Date.now() - t0;
63
+ const error_code = err instanceof TimeoutError
64
+ ? LLM_ERROR_CODES.TIMEOUT
65
+ : LLM_ERROR_CODES.NETWORK_ERROR;
66
+ const error_msg = err instanceof Error ? err.message : String(err);
67
+ const attempt = { provider: provider_name, success: false, error_code, latency_ms };
68
+ if (!is_last && cascade_on_codes.includes(error_code)) {
69
+ logger.warn(`[cascade] ${provider_name} threw ${error_code} — trying next`, { provider: provider_name, error_code, latency_ms });
70
+ attempts.push(attempt);
71
+ continue;
72
+ }
73
+ return {
74
+ response: {
75
+ success: false,
76
+ error: error_msg,
77
+ error_info: { code: error_code, message: error_msg, retryable: true },
78
+ },
79
+ attempts: [...attempts, attempt],
80
+ };
81
+ }
82
+ const latency_ms = Date.now() - t0;
83
+ if (response.success) {
84
+ return { response, attempts };
85
+ }
86
+ // Failed response
87
+ const error_code = response.error_info?.code ?? LLM_ERROR_CODES.UNKNOWN;
88
+ const is_cascadable = cascade_on_codes.includes(error_code);
89
+ if (!is_last && is_cascadable) {
90
+ logger.warn(`[cascade] ${provider_name} returned ${error_code} — trying next`, { provider: provider_name, error_code, latency_ms });
91
+ attempts.push({ provider: provider_name, success: false, error_code, latency_ms });
92
+ continue;
93
+ }
94
+ // Either last provider or non-cascadable error — return now
95
+ const final_attempts = is_last && attempts.length > 0
96
+ ? [...attempts, { provider: provider_name, success: false, error_code, latency_ms }]
97
+ : attempts;
98
+ return { response, attempts: final_attempts };
99
+ }
100
+ // Unreachable — loop always returns
101
+ return { response: { success: false, error: 'cascade: no providers' }, attempts };
102
+ }
103
+ // =============================================================================
104
+ // Timeout helper
105
+ // =============================================================================
106
+ class TimeoutError extends Error {
107
+ constructor(provider, ms) {
108
+ super(`[cascade] provider "${provider}" timed out after ${ms}ms`);
109
+ this.name = 'TimeoutError';
110
+ }
111
+ }
112
+ function make_timeout_promise(ms, provider) {
113
+ return new Promise((_, reject) => setTimeout(() => reject(new TimeoutError(provider, ms)), ms));
114
+ }
115
+ //# sourceMappingURL=cascade_runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cascade_runner.js","sourceRoot":"","sources":["../../../src/lib/cascade/cascade_runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export type { CascadeConfig } from './types.js';
2
+ export { DEFAULT_CASCADE_ON_CODES } from './types.js';
3
+ export { run_with_cascade, resolve_providers } from './cascade_runner.js';
4
+ export type { CascadeRunOptions, CascadeRunResult, ResolveProvidersOptions } from './cascade_runner.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/cascade/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,4 @@
1
+ // file_description: Cascade module exports
2
+ export { DEFAULT_CASCADE_ON_CODES } from './types.js';
3
+ export { run_with_cascade, resolve_providers } from './cascade_runner.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/cascade/index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAG3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { LLMErrorCode } from '../llm_api/types.js';
2
+ /**
3
+ * Cascade configuration — controls provider failover behavior.
4
+ *
5
+ * Precedence (highest to lowest):
6
+ * 1. per-call `params.providers`
7
+ * 2. `initialize_llm_api({ cascade })` config
8
+ * 3. `[llm_cascade]` ini section
9
+ * 4. no cascade (single primary provider)
10
+ */
11
+ export interface CascadeConfig {
12
+ /**
13
+ * Ordered list of provider names to try. First is attempted first.
14
+ * If empty or unset, no cascade — uses primary provider.
15
+ */
16
+ providers?: string[];
17
+ /**
18
+ * Timeout per individual provider attempt in milliseconds.
19
+ * No timeout if not set.
20
+ */
21
+ timeout_ms_per_attempt?: number;
22
+ /**
23
+ * Error codes that permit cascade to the next provider.
24
+ * Defaults to: RATE_LIMITED, NETWORK_ERROR, TIMEOUT, API_ERROR.
25
+ */
26
+ cascade_on_codes?: LLMErrorCode[];
27
+ }
28
+ /**
29
+ * Default error codes that trigger cascade to the next provider.
30
+ * Only transient / server-side errors are included.
31
+ * Configuration errors (PROVIDER_NOT_FOUND, CAPABILITY_NOT_SUPPORTED, API_KEY_MISSING)
32
+ * are intentionally excluded — they won't succeed on retry.
33
+ */
34
+ export declare const DEFAULT_CASCADE_ON_CODES: LLMErrorCode[];
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/cascade/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,YAAY,EAAE,CAAC;CACnC;AAED;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,YAAY,EAKlD,CAAC"}
@@ -0,0 +1,14 @@
1
+ // file_description: Cascade configuration and runner types for hazo_llm_api
2
+ /**
3
+ * Default error codes that trigger cascade to the next provider.
4
+ * Only transient / server-side errors are included.
5
+ * Configuration errors (PROVIDER_NOT_FOUND, CAPABILITY_NOT_SUPPORTED, API_KEY_MISSING)
6
+ * are intentionally excluded — they won't succeed on retry.
7
+ */
8
+ export const DEFAULT_CASCADE_ON_CODES = [
9
+ 'RATE_LIMITED',
10
+ 'NETWORK_ERROR',
11
+ 'TIMEOUT',
12
+ 'API_ERROR',
13
+ ];
14
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/cascade/types.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAiC5E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAmB;IACtD,cAAc;IACd,eAAe;IACf,SAAS;IACT,WAAW;CACZ,CAAC"}
@@ -5,4 +5,5 @@
5
5
  */
6
6
  export { type BaseGenerationConfig, type ParameterMapping, type GlobalLLMConfig, COMMON_PARAM_MAPPINGS, GEMINI_PARAM_MAPPINGS, QWEN_PARAM_MAPPINGS, find_config_file, read_config_file, parse_generation_config, parse_capabilities, parse_enabled_llms, load_api_key_from_env, get_api_key_env_var_name, get_llm_global_config, } from './config_parser.js';
7
7
  export { type BaseProviderConfig, type ProviderFactory, type ProviderLoadResult, register_provider_factory, get_provider_factory, get_registered_factory_names, load_provider_from_config, load_all_providers, } from './provider_loader.js';
8
+ export { type HazoLLMApiConfig, getHazoLLMApiConfig, } from './llm_api_config.js';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/config/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EAEpB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EAEnB,gBAAgB,EAChB,gBAAgB,EAEhB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAElB,qBAAqB,EACrB,wBAAwB,EAExB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EAEvB,yBAAyB,EACzB,oBAAoB,EACpB,4BAA4B,EAE5B,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/config/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EAEpB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EAEnB,gBAAgB,EAChB,gBAAgB,EAEhB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAElB,qBAAqB,EACrB,wBAAwB,EAExB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EAEvB,yBAAyB,EACzB,oBAAoB,EACpB,4BAA4B,EAE5B,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,gBAAgB,EAErB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC"}
@@ -19,4 +19,7 @@ export {
19
19
  register_provider_factory, get_provider_factory, get_registered_factory_names,
20
20
  // Provider loading
21
21
  load_provider_from_config, load_all_providers, } from './provider_loader.js';
22
+ export {
23
+ // Loader
24
+ getHazoLLMApiConfig, } from './llm_api_config.js';
22
25
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/config/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO;AAKL,qBAAqB;AACrB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB;AACnB,wBAAwB;AACxB,gBAAgB,EAChB,gBAAgB;AAChB,oBAAoB;AACpB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB;AAClB,wBAAwB;AACxB,qBAAqB,EACrB,wBAAwB;AACxB,gBAAgB;AAChB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO;AAKL,uBAAuB;AACvB,yBAAyB,EACzB,oBAAoB,EACpB,4BAA4B;AAC5B,mBAAmB;AACnB,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/config/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO;AAKL,qBAAqB;AACrB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB;AACnB,wBAAwB;AACxB,gBAAgB,EAChB,gBAAgB;AAChB,oBAAoB;AACpB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB;AAClB,wBAAwB;AACxB,qBAAqB,EACrB,wBAAwB;AACxB,gBAAgB;AAChB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO;AAKL,uBAAuB;AACvB,yBAAyB,EACzB,oBAAoB,EACpB,4BAA4B;AAC5B,mBAAmB;AACnB,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO;AAGL,SAAS;AACT,mBAAmB,GACpB,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Zod-validated config loader for hazo_llm_api.
3
+ *
4
+ * Covers the standard/global sections ([llm] and [log.overrides]).
5
+ * Provider-specific sections ([llm_gemini], [llm_qwen], etc.) are still
6
+ * parsed by the existing config_parser.ts / llm_api/index.ts path — this
7
+ * module only adds a validated overlay for the sections hazo_core knows about.
8
+ */
9
+ import { z } from 'zod';
10
+ declare const HazoLLMApiConfigSchema: z.ZodObject<{
11
+ llm: z.ZodPipe<z.ZodOptional<z.ZodObject<{
12
+ enabled_llms: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string[], string | undefined>>;
13
+ primary_llm: z.ZodDefault<z.ZodOptional<z.ZodString>>;
14
+ sqlite_path: z.ZodDefault<z.ZodOptional<z.ZodString>>;
15
+ }, z.core.$strip>>, z.ZodTransform<{
16
+ enabled_llms: string[];
17
+ primary_llm: string;
18
+ sqlite_path: string;
19
+ }, {
20
+ enabled_llms: string[];
21
+ primary_llm: string;
22
+ sqlite_path: string;
23
+ } | undefined>>;
24
+ log: z.ZodPipe<z.ZodOptional<z.ZodObject<{
25
+ overrides: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>;
26
+ }, z.core.$strip>>, z.ZodTransform<{
27
+ overrides: Record<string, string>;
28
+ }, {
29
+ overrides: Record<string, string>;
30
+ } | undefined>>;
31
+ }, z.core.$strip>;
32
+ export type HazoLLMApiConfig = z.infer<typeof HazoLLMApiConfigSchema>;
33
+ /**
34
+ * Load and validate the hazo_llm_api config using hazo_core's loadConfig.
35
+ *
36
+ * Reads `config/hazo_llm_api_config.ini` relative to process.cwd(),
37
+ * applies any `HAZO_LLM_API_<SECTION>_<KEY>` env-var overrides, and
38
+ * validates the result with the Zod schema above.
39
+ */
40
+ export declare function getHazoLLMApiConfig(): HazoLLMApiConfig;
41
+ export {};
42
+ //# sourceMappingURL=llm_api_config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm_api_config.d.ts","sourceRoot":"","sources":["../../../src/lib/config/llm_api_config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,QAAA,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;iBAkB1B,CAAC;AAMH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAMtE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,gBAAgB,CAKtD"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Zod-validated config loader for hazo_llm_api.
3
+ *
4
+ * Covers the standard/global sections ([llm] and [log.overrides]).
5
+ * Provider-specific sections ([llm_gemini], [llm_qwen], etc.) are still
6
+ * parsed by the existing config_parser.ts / llm_api/index.ts path — this
7
+ * module only adds a validated overlay for the sections hazo_core knows about.
8
+ */
9
+ import { z } from 'zod';
10
+ import { loadConfig } from 'hazo_core';
11
+ // ---------------------------------------------------------------------------
12
+ // Schema
13
+ // ---------------------------------------------------------------------------
14
+ const HazoLLMApiConfigSchema = z.object({
15
+ llm: z
16
+ .object({
17
+ enabled_llms: z
18
+ .string()
19
+ .optional()
20
+ .transform((v) => (v ? v.split(',').map((s) => s.trim()) : ['gemini'])),
21
+ primary_llm: z.string().optional().default('gemini'),
22
+ sqlite_path: z.string().optional().default('prompt_library.sqlite'),
23
+ })
24
+ .optional()
25
+ .transform((v) => v ?? { enabled_llms: ['gemini'], primary_llm: 'gemini', sqlite_path: 'prompt_library.sqlite' }),
26
+ log: z
27
+ .object({
28
+ overrides: z.record(z.string(), z.string()).optional().default({}),
29
+ })
30
+ .optional()
31
+ .transform((v) => v ?? { overrides: {} }),
32
+ });
33
+ // ---------------------------------------------------------------------------
34
+ // Loader
35
+ // ---------------------------------------------------------------------------
36
+ /**
37
+ * Load and validate the hazo_llm_api config using hazo_core's loadConfig.
38
+ *
39
+ * Reads `config/hazo_llm_api_config.ini` relative to process.cwd(),
40
+ * applies any `HAZO_LLM_API_<SECTION>_<KEY>` env-var overrides, and
41
+ * validates the result with the Zod schema above.
42
+ */
43
+ export function getHazoLLMApiConfig() {
44
+ return loadConfig({
45
+ pkg: 'hazo_llm_api',
46
+ schema: HazoLLMApiConfigSchema,
47
+ });
48
+ }
49
+ //# sourceMappingURL=llm_api_config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm_api_config.js","sourceRoot":"","sources":["../../../src/lib/config/llm_api_config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,GAAG,EAAE,CAAC;SACH,MAAM,CAAC;QACN,YAAY,EAAE,CAAC;aACZ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;QACpD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC;KACpE,CAAC;SACD,QAAQ,EAAE;SACV,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;IACnH,GAAG,EAAE,CAAC;SACH,MAAM,CAAC;QACN,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;KACnE,CAAC;SACD,QAAQ,EAAE;SACV,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;CAC5C,CAAC,CAAC;AAQH,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,UAAU,CAAmB;QAClC,GAAG,EAAE,cAAc;QACnB,MAAM,EAAE,sBAA+B;KACxC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Cost Cap Gate
3
+ *
4
+ * Pre-call gate that checks the accumulated cost for the current session
5
+ * against a configured cap. Returns a COST_LIMIT_EXCEEDED error response
6
+ * when the cap is reached (block mode) or fires a warn hook and proceeds
7
+ * (warn mode).
8
+ *
9
+ * Requires:
10
+ * - hazo_llm_api_log table to exist (ensure_api_log_table must be called first)
11
+ * - A session_id available via hazo_logs ALS (safe_get_log_context)
12
+ * - cost_cap.enabled = true in LLMApiConfig
13
+ */
14
+ import type { Logger, LLMResponse, CostCapConfig } from '../llm_api/types.js';
15
+ import type { HazoConnect } from '../hazo_connect/types.js';
16
+ /**
17
+ * Ensure the session_id + created_at composite index exists on hazo_llm_api_log.
18
+ * Idempotent — safe to call on every initialization.
19
+ * Errors are swallowed to avoid crashing initialization.
20
+ */
21
+ export declare function ensure_cost_cap_index(connect: HazoConnect, logger: Logger): Promise<void>;
22
+ /**
23
+ * Query the total cost_usd accumulated for a session within the given window.
24
+ *
25
+ * Returns 0 if connect has no raw_sql, if there are no matching rows, or if
26
+ * any DB error occurs (errors are swallowed).
27
+ */
28
+ export declare function query_session_cost(connect: HazoConnect, session_id: string, window_start: string, logger: Logger): Promise<number>;
29
+ /**
30
+ * Pre-call cost cap gate.
31
+ *
32
+ * Returns:
33
+ * - `null` if the gate should not block (cap disabled, no session, current < cap, or warn mode)
34
+ * - `LLMResponse` if the call should be blocked (block mode, cap exceeded)
35
+ *
36
+ * In warn mode the `cost_cap_exceeded` hook is called (errors swallowed) and null is returned
37
+ * so the call proceeds.
38
+ */
39
+ export declare function check_cost_cap_gate(connect: HazoConnect | null, cap_config: CostCapConfig | undefined, logger: Logger): Promise<LLMResponse | null>;
40
+ //# sourceMappingURL=cost_cap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost_cap.d.ts","sourceRoot":"","sources":["../../../src/lib/cost_cap/cost_cap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AA+B5D;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAaf;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,UAAU,EAAE,aAAa,GAAG,SAAS,EACrC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAoE7B"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Cost Cap Gate
3
+ *
4
+ * Pre-call gate that checks the accumulated cost for the current session
5
+ * against a configured cap. Returns a COST_LIMIT_EXCEEDED error response
6
+ * when the cap is reached (block mode) or fires a warn hook and proceeds
7
+ * (warn mode).
8
+ *
9
+ * Requires:
10
+ * - hazo_llm_api_log table to exist (ensure_api_log_table must be called first)
11
+ * - A session_id available via hazo_logs ALS (safe_get_log_context)
12
+ * - cost_cap.enabled = true in LLMApiConfig
13
+ */
14
+ import { build_error_response } from '../llm_api/provider_helper.js';
15
+ import { LLM_ERROR_CODES } from '../llm_api/types.js';
16
+ import { safe_get_log_context } from '../observability/log_context.js';
17
+ // =============================================================================
18
+ // Internal Helpers
19
+ // =============================================================================
20
+ /**
21
+ * Compute the window_start timestamp string for the rolling window.
22
+ *
23
+ * - 'day': rolling 24 hours
24
+ * - 'hour': rolling 1 hour
25
+ * - 'session': epoch (all records for this session regardless of age)
26
+ */
27
+ function get_window_start(window = 'session') {
28
+ if (window === 'day') {
29
+ return new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
30
+ }
31
+ if (window === 'hour') {
32
+ return new Date(Date.now() - 60 * 60 * 1000).toISOString();
33
+ }
34
+ // 'session': use epoch to capture all records for this session
35
+ return '1970-01-01T00:00:00.000Z';
36
+ }
37
+ // =============================================================================
38
+ // Public API
39
+ // =============================================================================
40
+ /**
41
+ * Ensure the session_id + created_at composite index exists on hazo_llm_api_log.
42
+ * Idempotent — safe to call on every initialization.
43
+ * Errors are swallowed to avoid crashing initialization.
44
+ */
45
+ export async function ensure_cost_cap_index(connect, logger) {
46
+ if (!connect.raw_sql) {
47
+ return;
48
+ }
49
+ try {
50
+ await connect.raw_sql('CREATE INDEX IF NOT EXISTS idx_llm_log_session_created ON hazo_llm_api_log(session_id, created_at)');
51
+ }
52
+ catch (err) {
53
+ logger.warn('ensure_cost_cap_index: failed to create index (non-fatal)', {
54
+ error: err instanceof Error ? err.message : String(err),
55
+ });
56
+ }
57
+ }
58
+ /**
59
+ * Query the total cost_usd accumulated for a session within the given window.
60
+ *
61
+ * Returns 0 if connect has no raw_sql, if there are no matching rows, or if
62
+ * any DB error occurs (errors are swallowed).
63
+ */
64
+ export async function query_session_cost(connect, session_id, window_start, logger) {
65
+ if (!connect.raw_sql) {
66
+ return 0;
67
+ }
68
+ try {
69
+ const rows = await connect.raw_sql('SELECT COALESCE(SUM(cost_usd), 0) AS total FROM hazo_llm_api_log WHERE session_id = ? AND created_at >= ?', [session_id, window_start]);
70
+ if (!rows || rows.length === 0) {
71
+ return 0;
72
+ }
73
+ const total = rows[0].total;
74
+ return typeof total === 'number' ? total : Number(total) || 0;
75
+ }
76
+ catch (err) {
77
+ logger.warn('query_session_cost: failed to query cost (non-fatal)', {
78
+ session_id,
79
+ error: err instanceof Error ? err.message : String(err),
80
+ });
81
+ return 0;
82
+ }
83
+ }
84
+ /**
85
+ * Pre-call cost cap gate.
86
+ *
87
+ * Returns:
88
+ * - `null` if the gate should not block (cap disabled, no session, current < cap, or warn mode)
89
+ * - `LLMResponse` if the call should be blocked (block mode, cap exceeded)
90
+ *
91
+ * In warn mode the `cost_cap_exceeded` hook is called (errors swallowed) and null is returned
92
+ * so the call proceeds.
93
+ */
94
+ export async function check_cost_cap_gate(connect, cap_config, logger) {
95
+ // Skip if cap is not configured or not enabled
96
+ if (!cap_config || cap_config.enabled !== true) {
97
+ return null;
98
+ }
99
+ // Skip if no connect available
100
+ if (!connect) {
101
+ return null;
102
+ }
103
+ // Get session_id from ALS context
104
+ const log_ctx = await safe_get_log_context();
105
+ const session_id = log_ctx?.sessionId;
106
+ if (!session_id) {
107
+ return null;
108
+ }
109
+ // Compute window start
110
+ const window_start = get_window_start(cap_config.window ?? 'session');
111
+ // Query accumulated cost
112
+ const current_usd = await query_session_cost(connect, session_id, window_start, logger);
113
+ // Get cap for this session
114
+ let cap_usd;
115
+ try {
116
+ cap_usd = await cap_config.get_user_cap({ session_id });
117
+ }
118
+ catch (err) {
119
+ logger.warn('check_cost_cap_gate: get_user_cap threw (non-fatal, skipping cap check)', {
120
+ session_id,
121
+ error: err instanceof Error ? err.message : String(err),
122
+ });
123
+ return null;
124
+ }
125
+ // Skip enforcement if cap is 0 or negative
126
+ if (cap_usd <= 0) {
127
+ return null;
128
+ }
129
+ // Under cap — proceed
130
+ if (current_usd < cap_usd) {
131
+ return null;
132
+ }
133
+ // Cap exceeded — handle according to mode
134
+ const mode = cap_config.on_exceeded ?? 'block';
135
+ if (mode === 'warn') {
136
+ // Fire the warn hook (errors swallowed), then proceed
137
+ if (cap_config.cost_cap_exceeded) {
138
+ try {
139
+ await cap_config.cost_cap_exceeded({ session_id, current_usd, cap_usd });
140
+ }
141
+ catch {
142
+ // Swallow hook errors
143
+ }
144
+ }
145
+ return null; // Proceed with the call
146
+ }
147
+ // Default: block mode — return error response
148
+ return build_error_response(LLM_ERROR_CODES.COST_LIMIT_EXCEEDED, `Cost cap exceeded: $${current_usd.toFixed(6)} spent of $${cap_usd.toFixed(6)} limit`, false, { session_id, current_usd, cap_usd });
149
+ }
150
+ //# sourceMappingURL=cost_cap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost_cap.js","sourceRoot":"","sources":["../../../src/lib/cost_cap/cost_cap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export type { CostCapConfig } from '../llm_api/types.js';
2
+ export { check_cost_cap_gate, query_session_cost, ensure_cost_cap_index, } from './cost_cap.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/cost_cap/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { check_cost_cap_gate, query_session_cost, ensure_cost_cap_index, } from './cost_cap.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/cost_cap/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { HazoConnect } from "../hazo_connect/types.js";
2
+ import type { Logger } from "../llm_api/types.js";
3
+ /**
4
+ * Idempotently create the hazo_llm_api_log table + its indexes on the active connection.
5
+ * Detects dialect from the connect adapter and runs the matching DDL.
6
+ *
7
+ * Safe to call on every initialize_llm_api() — if the table exists, this is a no-op.
8
+ */
9
+ export declare function ensure_api_log_table(connect: HazoConnect, logger: Logger): Promise<void>;
10
+ //# sourceMappingURL=init_api_log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init_api_log.d.ts","sourceRoot":"","sources":["../../../src/lib/database/init_api_log.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuF9F"}