@ultimat3/ai 5.0.1 → 7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/ai",
3
- "version": "5.0.1",
3
+ "version": "7.0.0",
4
4
  "description": "LLM gateway, versioned prompts, evals as tests, embeddings, hybrid vector search, RAG",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -32,14 +32,14 @@
32
32
  "test": "bun test"
33
33
  },
34
34
  "dependencies": {
35
- "@ultimat3/action": "5.0.1",
36
- "@ultimat3/cache": "5.0.1",
37
- "@ultimat3/core": "5.0.1",
38
- "@ultimat3/db": "5.0.1",
39
- "@ultimat3/jobs": "5.0.1",
40
- "@ultimat3/money": "5.0.1",
41
- "@ultimat3/policy": "5.0.1",
42
- "@ultimat3/schema": "5.0.1",
43
- "@ultimat3/time": "5.0.1"
35
+ "@ultimat3/action": "7.0.0",
36
+ "@ultimat3/cache": "7.0.0",
37
+ "@ultimat3/core": "7.0.0",
38
+ "@ultimat3/db": "7.0.0",
39
+ "@ultimat3/jobs": "7.0.0",
40
+ "@ultimat3/money": "7.0.0",
41
+ "@ultimat3/policy": "7.0.0",
42
+ "@ultimat3/schema": "7.0.0",
43
+ "@ultimat3/time": "7.0.0"
44
44
  }
45
45
  }
package/src/budget.ts CHANGED
@@ -4,12 +4,13 @@
4
4
  // wrong answer that looks like a real one, and the caller has no signal anything happened.
5
5
  // A thrown X_AI_BUDGET_EXCEEDED with the remaining count is strictly more useful.
6
6
  //
7
- // The carrier is an AsyncLocalStorage so nested calls (a RAG retrieval, a tool call that
8
- // generates, an eval judge) all debit the same ledger without threading it through every
9
- // signature. `node:async_hooks` is used directly because Bun implements it natively and the
10
- // framework's ALS context is established at the HTTP boundary, above this package.
7
+ // The carrier is an async context so nested calls (a RAG retrieval, a tool call that generates,
8
+ // an eval judge) all debit the same ledger without threading it through every signature. It opens
9
+ // through `@ultimat3/core`'s one lazy seam rather than constructing an `AsyncLocalStorage` here: a
10
+ // module-scope `new` threw at EVALUATION in a browser bundle, where the bundler stubs
11
+ // `node:async_hooks` to `{}`, and took every importer of `@ultimat3/ai` with it.
11
12
 
12
- import { AsyncLocalStorage } from 'node:async_hooks';
13
+ import { asyncContext } from '@ultimat3/core';
13
14
  import type { Money } from '@ultimat3/money';
14
15
  import { assertSameCurrency } from '@ultimat3/money';
15
16
  import { AiBudgetExceededError } from './errors';
@@ -307,7 +308,7 @@ function tighterMoney(a: Money | undefined, b: Money | undefined): Money | undef
307
308
  return a.minor <= b.minor ? a : b;
308
309
  }
309
310
 
310
- const storage = new AsyncLocalStorage<BudgetLedger>();
311
+ const storage = asyncContext<BudgetLedger>('an AI budget');
311
312
 
312
313
  /** Run `fn` with `ledger` as the ambient budget for everything it awaits. */
313
314
  export function withBudget<T>(ledger: BudgetLedger, fn: () => Promise<T>): Promise<T> {
@@ -316,5 +317,5 @@ export function withBudget<T>(ledger: BudgetLedger, fn: () => Promise<T>): Promi
316
317
 
317
318
  /** The ambient ledger, or `undefined` outside a budget scope (spend is then unmetered). */
318
319
  export function currentBudget(): BudgetLedger | undefined {
319
- return storage.getStore();
320
+ return storage.get();
320
321
  }
package/src/llm-stream.ts CHANGED
@@ -21,7 +21,7 @@
21
21
  * async chain — abandoning the iterator stops delivery, never the accounting.
22
22
  */
23
23
 
24
- import { AsyncLocalStorage } from 'node:async_hooks';
24
+ import { asyncContext } from '@ultimat3/core';
25
25
  import { AiTransportError } from './errors';
26
26
  import type { Gateway } from './gateway';
27
27
  import type { GenerateRequest, GenerateResult } from './provider';
@@ -102,7 +102,9 @@ export class LlmSink {
102
102
  }
103
103
  }
104
104
 
105
- const sinks = new AsyncLocalStorage<LlmSink>();
105
+ // Core's one lazy seam, never a construction here: a module-scope `new` threw at EVALUATION in a
106
+ // browser bundle, where the bundler stubs `node:async_hooks` to `{}`.
107
+ const sinks = asyncContext<LlmSink>('an LLM stream sink');
106
108
 
107
109
  /** Mark everything `fn` awaits as a streamed invocation. */
108
110
  export function withLlmSink<T>(sink: LlmSink, fn: () => Promise<T>): Promise<T> {
@@ -111,7 +113,7 @@ export function withLlmSink<T>(sink: LlmSink, fn: () => Promise<T>): Promise<T>
111
113
 
112
114
  /** The sink of the streamed invocation this call belongs to, or `undefined` for a plain one. */
113
115
  export function currentLlmSink(): LlmSink | undefined {
114
- return sinks.getStore();
116
+ return sinks.get();
115
117
  }
116
118
 
117
119
  /**