@hourslabs/domovoi 0.1.0 → 0.2.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/dist/index.d.ts CHANGED
@@ -7,11 +7,17 @@
7
7
  * - `@hourslabs/domovoi/testing` — mockProvider for unit tests.
8
8
  */
9
9
  import { memoryCache as memoryCacheFactory } from "./cache.js";
10
+ import { bind as bindFn, currentScope as currentScopeFn, scope as scopeFn } from "./scope.js";
10
11
  import { boolean as booleanVerb } from "./verbs/boolean.js";
11
12
  import { classifier as classifierFactory } from "./verbs/classifier.js";
12
13
  import { classify as classifyVerb } from "./verbs/classify.js";
14
+ export type { BudgetMode, BudgetSnapshot, ScopeBudget } from "./budget-tracker.js";
13
15
  export type { Cache, CacheStats, CacheWithStats } from "./cache.js";
14
- export { BudgetExhaustedError, ConfigError, DomovoiError, type ErrorCode, ProviderError, } from "./errors.js";
16
+ export type { ContextStorage } from "./context-storage.js";
17
+ export { configureContextStorage, resetContextStorage } from "./context-storage.js";
18
+ export { BudgetExceededError, BudgetExhaustedError, ConfigError, DomovoiError, type ErrorCode, ProviderError, } from "./errors.js";
19
+ export type { ResolvedScope, ScopeOptions } from "./scope.js";
20
+ export type { AttributeValue, Span, Tracer } from "./tracer.js";
15
21
  export type { Budget, Classified, Distribution, Filterable, Label, PromptTemplate, ProviderCapabilities, SerializableError, Thresholds, Uncertain, Unknown, UnknownVerdictCause, Verdict, VerdictMeta, } from "./types.js";
16
22
  export type { BooleanOptions } from "./verbs/boolean.js";
17
23
  export type { Classifier, ClassifierConfig } from "./verbs/classifier.js";
@@ -24,11 +30,20 @@ export { filter, isClassified, isUncertain, isUnknown, match } from "./verdict.j
24
30
  * import { domovoi, isClassified } from "@hourslabs/domovoi";
25
31
  * const v = await domovoi.classify(input, ["a","b","c"] as const);
26
32
  * if (isClassified(v)) console.log(v.value);
33
+ *
34
+ * @example v0.2 ambient context
35
+ * await domovoi.scope({ budget: { tokens: 10_000 } }, async () => {
36
+ * const v = await domovoi.classify(input, ["a","b","c"]);
37
+ * // v0.2: classify call inherits budget enforcement from scope
38
+ * });
27
39
  */
28
40
  export declare const domovoi: {
29
41
  readonly classify: typeof classifyVerb;
30
42
  readonly boolean: typeof booleanVerb;
31
43
  readonly classifier: typeof classifierFactory;
32
44
  readonly memoryCache: typeof memoryCacheFactory;
45
+ readonly scope: typeof scopeFn;
46
+ readonly bind: typeof bindFn;
47
+ readonly currentScope: typeof currentScopeFn;
33
48
  };
34
49
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,IAAI,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE/D,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,YAAY,EACZ,KAAK,SAAS,EACd,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,MAAM,EACN,UAAU,EACV,YAAY,EACZ,UAAU,EACV,KAAK,EACL,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,OAAO,EACP,mBAAmB,EACnB,OAAO,EACP,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC1E,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAEnF;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO;;;;;CAKV,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,IAAI,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,IAAI,IAAI,MAAM,EAAE,YAAY,IAAI,cAAc,EAAE,KAAK,IAAI,OAAO,EAAE,MAAM,YAAY,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE/D,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACnF,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACpE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,WAAW,EACX,YAAY,EACZ,KAAK,SAAS,EACd,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC9D,YAAY,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EACV,MAAM,EACN,UAAU,EACV,YAAY,EACZ,UAAU,EACV,KAAK,EACL,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,OAAO,EACP,mBAAmB,EACnB,OAAO,EACP,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC1E,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAEnF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,OAAO;;;;;;;;CAQV,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { createHash } from 'crypto';
2
+ import { AsyncLocalStorage } from 'async_hooks';
2
3
  import OpenAI from 'openai';
3
4
  import { get_encoding } from 'tiktoken';
4
5
 
@@ -158,6 +159,19 @@ var BudgetExhaustedError = class extends DomovoiError {
158
159
  this.elapsedMs = options.elapsedMs;
159
160
  }
160
161
  };
162
+ var BudgetExceededError = class extends DomovoiError {
163
+ spent;
164
+ limit;
165
+ constructor(options) {
166
+ super(`Scope budget exceeded: ${options.spent} / ${options.limit} tokens`, {
167
+ code: "tokens_exceeded",
168
+ cause: options.cause
169
+ });
170
+ this.name = "BudgetExceededError";
171
+ this.spent = options.spent;
172
+ this.limit = options.limit;
173
+ }
174
+ };
161
175
  function canonicalizeProviderThrow(thrown) {
162
176
  if (thrown instanceof DomovoiError) return thrown;
163
177
  if (thrown instanceof Error) {
@@ -186,6 +200,109 @@ function serializeError(err) {
186
200
  };
187
201
  }
188
202
 
203
+ // src/budget-tracker.ts
204
+ var BudgetTracker = class _BudgetTracker {
205
+ constructor(limit, mode) {
206
+ this.limit = limit;
207
+ this.mode = mode;
208
+ }
209
+ limit;
210
+ mode;
211
+ spent = 0;
212
+ /**
213
+ * Build a tracker from a public `ScopeBudget`, or return `undefined` if
214
+ * the budget is absent / has no `tokens` field. Used during scope merge.
215
+ *
216
+ * Throws `ConfigError` if `tokens` is non-finite or non-positive — these
217
+ * are construction-time validation failures, not runtime budget exhaustion.
218
+ */
219
+ static from(budget) {
220
+ if (budget?.tokens === void 0) return void 0;
221
+ if (!Number.isFinite(budget.tokens) || budget.tokens <= 0) {
222
+ throw new ConfigError(
223
+ `Scope budget tokens must be a finite positive number, got ${budget.tokens}`,
224
+ { code: "invalid_scope_budget" }
225
+ );
226
+ }
227
+ return new _BudgetTracker(budget.tokens, budget.onExceeded ?? "graceful");
228
+ }
229
+ /** Check whether the budget is already exhausted. Called pre-call. */
230
+ precheck() {
231
+ if (this.isExhausted()) {
232
+ return { ok: false, spent: this.spent, limit: this.limit };
233
+ }
234
+ return { ok: true };
235
+ }
236
+ /**
237
+ * Accumulate spend. Called post-call with the actual token cost.
238
+ * Negative or non-finite values are silently clamped to 0 — provider
239
+ * adapters occasionally return malformed token counts, and a budget
240
+ * tracker shouldn't panic on bad telemetry from upstream.
241
+ */
242
+ charge(tokens) {
243
+ if (!Number.isFinite(tokens) || tokens <= 0) return;
244
+ this.spent += tokens;
245
+ }
246
+ /**
247
+ * Throw `BudgetExceededError` if mode is `"throw"` and budget is exhausted.
248
+ * Caller invokes after `charge()` to enforce hard-fail semantics; under
249
+ * `"graceful"` mode this is a no-op and the next `precheck()` returns
250
+ * `{ ok: false, ... }` for graceful Unknown construction.
251
+ */
252
+ enforce() {
253
+ if (this.isExhausted() && this.mode === "throw") {
254
+ throw new BudgetExceededError({ spent: this.spent, limit: this.limit });
255
+ }
256
+ }
257
+ snapshot() {
258
+ return { spent: this.spent, limit: this.limit, mode: this.mode };
259
+ }
260
+ isExhausted() {
261
+ return this.spent >= this.limit;
262
+ }
263
+ };
264
+ var storage = new AsyncLocalStorage();
265
+ function getContextStorage() {
266
+ return storage;
267
+ }
268
+ function configureContextStorage(custom) {
269
+ storage = custom;
270
+ }
271
+ function resetContextStorage() {
272
+ storage = new AsyncLocalStorage();
273
+ }
274
+
275
+ // src/scope.ts
276
+ function scope(opts, fn) {
277
+ const parent = currentScope();
278
+ const merged = mergeScopes(parent, opts);
279
+ return getContextStorage().run(merged, fn);
280
+ }
281
+ function currentScope() {
282
+ return getContextStorage().getStore();
283
+ }
284
+ function bind(fn) {
285
+ const captured = currentScope();
286
+ if (!captured) return fn;
287
+ const storage2 = getContextStorage();
288
+ return ((...args) => storage2.run(captured, () => fn(...args)));
289
+ }
290
+ function mergeScopes(parent, child) {
291
+ const signal = mergeSignals(parent?.signal, child.signal);
292
+ const tracer = child.tracer ?? parent?.tracer;
293
+ const budgetTracker = child.budget ? BudgetTracker.from(child.budget) : parent?.budgetTracker;
294
+ return {
295
+ ...signal ? { signal } : {},
296
+ ...tracer ? { tracer } : {},
297
+ ...budgetTracker ? { budgetTracker } : {}
298
+ };
299
+ }
300
+ function mergeSignals(a, b) {
301
+ if (!a) return b;
302
+ if (!b) return a;
303
+ return AbortSignal.any([a, b]);
304
+ }
305
+
189
306
  // src/calibration/index.ts
190
307
  var identity = {
191
308
  kind: "identity",
@@ -380,6 +497,21 @@ function validateClassifierConfig(input) {
380
497
  }
381
498
  }
382
499
 
500
+ // src/tracer.ts
501
+ var noopSpan = {
502
+ setAttribute: () => {
503
+ },
504
+ recordException: () => {
505
+ },
506
+ setStatus: () => {
507
+ },
508
+ end: () => {
509
+ }
510
+ };
511
+ var noopTracer = {
512
+ startSpan: () => noopSpan
513
+ };
514
+
383
515
  // src/engine/meta.ts
384
516
  function makeMetaBuilder() {
385
517
  return {
@@ -433,11 +565,11 @@ function buildCancelledVerdict(meta, reason, provider) {
433
565
  meta: buildMetaForFailure(meta, provider)
434
566
  };
435
567
  }
436
- function buildBudgetExhaustedVerdict(meta, scope, policy, provider) {
568
+ function buildBudgetExhaustedVerdict(meta, scope2, policy, provider) {
437
569
  if (policy === "throw") return void 0;
438
570
  return {
439
571
  kind: "unknown",
440
- reason: { type: "budget_exhausted", scope },
572
+ reason: { type: "budget_exhausted", scope: scope2 },
441
573
  meta: buildMetaForFailure(meta, provider)
442
574
  };
443
575
  }
@@ -469,9 +601,10 @@ function computeProviderCacheKey(provider, formattedInput, config) {
469
601
  formattedInput
470
602
  });
471
603
  }
472
- function mergeSignals(userSignal, timeoutSignal) {
604
+ function mergeSignals2(userSignal, timeoutSignal, scopeSignal) {
473
605
  const signals = [timeoutSignal];
474
- if (userSignal !== void 0) signals.push(userSignal);
606
+ if (userSignal) signals.push(userSignal);
607
+ if (scopeSignal) signals.push(scopeSignal);
475
608
  return AbortSignal.any(signals);
476
609
  }
477
610
  async function loadDistribution(provider, formattedInput, config, meta, signal, cacheKey) {
@@ -583,6 +716,16 @@ function makeCancelledFromMeta(meta, reason) {
583
716
  meta: buildMetaForFailure(meta)
584
717
  };
585
718
  }
719
+ function makeBudgetExceededVerdict(meta, spent, limit, mode) {
720
+ if (mode === "throw") {
721
+ throw new BudgetExceededError({ spent, limit });
722
+ }
723
+ return {
724
+ kind: "unknown",
725
+ reason: { type: "budget_exceeded", spent, limit },
726
+ meta: buildMetaForFailure(meta)
727
+ };
728
+ }
586
729
  function finalizeChainExhausted(meta, lastCalibrated, attempts, config) {
587
730
  const allErrored = lastCalibrated === void 0 && meta.providerErrors.length > 0 && meta.providerErrors.length === meta.providersAttempted.length;
588
731
  if (allErrored) {
@@ -666,7 +809,8 @@ function applyMultiClassRule(top, second, t) {
666
809
  // src/engine/decide.ts
667
810
  async function decide(formattedInput, config, signal) {
668
811
  const meta = makeMetaBuilder();
669
- const preAbort = abortReason(signal);
812
+ const scope2 = currentScope();
813
+ const preAbort = firstAbortReason(signal, scope2?.signal);
670
814
  if (preAbort !== void 0) {
671
815
  return makeCancelledFromMeta(meta, preAbort);
672
816
  }
@@ -687,7 +831,20 @@ async function decide(formattedInput, config, signal) {
687
831
  fireAndForget(config.hooks?.onResult, chainBudgetVerdict);
688
832
  return chainBudgetVerdict;
689
833
  }
690
- const midAbort = abortReason(signal);
834
+ if (scope2?.budgetTracker) {
835
+ const pre = scope2.budgetTracker.precheck();
836
+ if (!pre.ok) {
837
+ const verdict = makeBudgetExceededVerdict(
838
+ meta,
839
+ pre.spent,
840
+ pre.limit,
841
+ scope2.budgetTracker.mode
842
+ );
843
+ fireAndForget(config.hooks?.onResult, verdict);
844
+ return verdict;
845
+ }
846
+ }
847
+ const midAbort = firstAbortReason(signal, scope2?.signal);
691
848
  if (midAbort !== void 0) {
692
849
  const verdict = buildCancelledVerdict(meta, midAbort, provider);
693
850
  fireAndForget(config.hooks?.onResult, verdict);
@@ -703,7 +860,8 @@ async function decide(formattedInput, config, signal) {
703
860
  i,
704
861
  chainStartMs,
705
862
  limits.perCallTimeoutMs,
706
- isLastProvider
863
+ isLastProvider,
864
+ scope2
707
865
  );
708
866
  if (outcome.kind === "verdict") {
709
867
  fireAndForget(config.hooks?.onResult, outcome.verdict);
@@ -725,40 +883,84 @@ function computeLimits(config) {
725
883
  maxCalls: config.budget?.maxCalls ?? config.providers.length
726
884
  };
727
885
  }
728
- async function attemptProvider(provider, formattedInput, config, meta, userSignal, index, chainStartMs, perCallTimeoutMs, isLastProvider) {
729
- const cacheKey = computeProviderCacheKey(provider, formattedInput, config);
730
- const timeoutSignal = AbortSignal.timeout(perCallTimeoutMs);
731
- const mergedSignal = mergeSignals(userSignal, timeoutSignal);
732
- let distribution;
733
- try {
734
- distribution = await loadDistribution(
735
- provider,
736
- formattedInput,
737
- config,
738
- meta,
739
- mergedSignal,
740
- cacheKey
741
- );
742
- } catch (err) {
743
- return handleDistributionError(
744
- err,
745
- provider,
746
- meta,
747
- config,
748
- userSignal,
749
- timeoutSignal,
750
- index,
751
- chainStartMs,
752
- cacheKey
753
- );
886
+ function firstAbortReason(...signals) {
887
+ for (const s of signals) {
888
+ const reason = abortReason(s);
889
+ if (reason !== void 0) return reason;
754
890
  }
891
+ return void 0;
892
+ }
893
+ function estimateInputTokens(formattedInput) {
894
+ return Math.ceil(formattedInput.length / 4);
895
+ }
896
+ function estimateOutputTokens() {
897
+ return 20;
898
+ }
899
+ async function attemptProvider(provider, formattedInput, config, meta, userSignal, index, chainStartMs, perCallTimeoutMs, isLastProvider, scope2) {
900
+ const tracer = scope2?.tracer ?? noopTracer;
901
+ const span = tracer.startSpan(`chat ${provider.id}`, {
902
+ "gen_ai.provider.name": provider.id,
903
+ "gen_ai.operation.name": "chat",
904
+ "gen_ai.request.model": provider.modelId,
905
+ "domovoi.label_space": [...config.space]
906
+ });
755
907
  try {
756
- validateDistribution(distribution, config.space);
908
+ const cacheKey = computeProviderCacheKey(provider, formattedInput, config);
909
+ const timeoutSignal = AbortSignal.timeout(perCallTimeoutMs);
910
+ const mergedSignal = mergeSignals2(userSignal, timeoutSignal, scope2?.signal);
911
+ let distribution;
912
+ try {
913
+ distribution = await loadDistribution(
914
+ provider,
915
+ formattedInput,
916
+ config,
917
+ meta,
918
+ mergedSignal,
919
+ cacheKey
920
+ );
921
+ } catch (err) {
922
+ span.recordException(err);
923
+ span.setStatus("error");
924
+ return handleDistributionError(
925
+ err,
926
+ provider,
927
+ meta,
928
+ config,
929
+ userSignal,
930
+ timeoutSignal,
931
+ index,
932
+ chainStartMs,
933
+ cacheKey
934
+ );
935
+ }
936
+ span.setAttribute("domovoi.cache.hit", meta.cacheHit);
937
+ if (!meta.cacheHit) {
938
+ const inputTokens = estimateInputTokens(formattedInput);
939
+ const outputTokens = estimateOutputTokens();
940
+ span.setAttribute("gen_ai.usage.input_tokens", inputTokens);
941
+ span.setAttribute("gen_ai.usage.output_tokens", outputTokens);
942
+ scope2?.budgetTracker?.charge(inputTokens + outputTokens);
943
+ scope2?.budgetTracker?.enforce();
944
+ }
945
+ try {
946
+ validateDistribution(distribution, config.space);
947
+ } catch (err) {
948
+ span.recordException(err);
949
+ span.setStatus("error");
950
+ return recordValidationError(err, provider, meta, config, index, cacheKey);
951
+ }
952
+ const calibrated = config.calibrator.apply(distribution);
953
+ const result = applyThresholds(calibrated, config.thresholds, config.space);
954
+ return finalizeOutcome(result, calibrated, provider, meta, isLastProvider, span);
757
955
  } catch (err) {
758
- return recordValidationError(err, provider, meta, config, index, cacheKey);
956
+ span.recordException(err);
957
+ span.setStatus("error");
958
+ throw err;
959
+ } finally {
960
+ span.end();
759
961
  }
760
- const calibrated = config.calibrator.apply(distribution);
761
- const result = applyThresholds(calibrated, config.thresholds, config.space);
962
+ }
963
+ function finalizeOutcome(result, calibrated, provider, meta, isLastProvider, span) {
762
964
  if (result.kind === "classified") {
763
965
  const verdict = {
764
966
  kind: "classified",
@@ -766,6 +968,10 @@ async function attemptProvider(provider, formattedInput, config, meta, userSigna
766
968
  probability: result.probability,
767
969
  meta: buildMeta(meta, provider)
768
970
  };
971
+ span.setAttribute("domovoi.verdict.kind", verdict.kind);
972
+ span.setAttribute("domovoi.verdict.value", verdict.value);
973
+ span.setAttribute("domovoi.verdict.probability", verdict.probability);
974
+ span.setStatus("ok");
769
975
  return { kind: "verdict", verdict };
770
976
  }
771
977
  if (result.kind === "out_of_distribution") {
@@ -779,6 +985,8 @@ async function attemptProvider(provider, formattedInput, config, meta, userSigna
779
985
  },
780
986
  meta: buildMeta(meta, provider)
781
987
  };
988
+ span.setAttribute("domovoi.verdict.kind", verdict.kind);
989
+ span.setStatus("ok");
782
990
  return { kind: "verdict", verdict };
783
991
  }
784
992
  if (isLastProvider) {
@@ -790,8 +998,13 @@ async function attemptProvider(provider, formattedInput, config, meta, userSigna
790
998
  distribution: calibrated,
791
999
  meta: buildMeta(meta, provider)
792
1000
  };
1001
+ span.setAttribute("domovoi.verdict.kind", verdict.kind);
1002
+ span.setAttribute("domovoi.verdict.probability", verdict.probability);
1003
+ span.setStatus("ok");
793
1004
  return { kind: "lastUncertain", verdict, calibrated };
794
1005
  }
1006
+ span.setAttribute("domovoi.verdict.kind", "continue");
1007
+ span.setStatus("ok");
795
1008
  return { kind: "continue", calibrated };
796
1009
  }
797
1010
  var cl100kSingleton;
@@ -1126,6 +1339,7 @@ function convertCause(cause) {
1126
1339
  case "predicate_rejected":
1127
1340
  case "provider_failure":
1128
1341
  case "budget_exhausted":
1342
+ case "budget_exceeded":
1129
1343
  case "cancelled":
1130
1344
  return cause;
1131
1345
  }
@@ -1255,9 +1469,12 @@ var domovoi = {
1255
1469
  classify,
1256
1470
  boolean,
1257
1471
  classifier,
1258
- memoryCache
1472
+ memoryCache,
1473
+ scope,
1474
+ bind,
1475
+ currentScope
1259
1476
  };
1260
1477
 
1261
- export { BudgetExhaustedError, ConfigError, DomovoiError, ProviderError, domovoi, filter, isClassified, isUncertain, isUnknown, match };
1478
+ export { BudgetExceededError, BudgetExhaustedError, ConfigError, DomovoiError, ProviderError, configureContextStorage, domovoi, filter, isClassified, isUncertain, isUnknown, match, resetContextStorage };
1262
1479
  //# sourceMappingURL=index.js.map
1263
1480
  //# sourceMappingURL=index.js.map